1use alloc::boxed::Box;
30use alloc::sync::Arc;
31use core::fmt;
32
33use enough::StopReason;
34pub use zencodec::decode::ErasedError;
35
36use crate::frame::{Frame, FrameInterpretation};
37use crate::limits::MediaLimitExceeded;
38use crate::packet::Packet;
39use crate::track::{CodecId, TrackInfo, VideoTrackInfo};
40use zencodec::time::TimeBase;
41
42#[derive(Clone, Copy, Debug, PartialEq, Eq)]
43#[non_exhaustive]
44pub enum SendStatus {
46 Accepted,
48 ReceivePending,
51}
52
53#[derive(Debug)]
54#[non_exhaustive]
55pub enum Receive<T> {
57 Ready(T),
59 NeedInput,
61 EndOfStream,
63}
64
65#[derive(Clone, Copy, Debug, PartialEq, Eq)]
66#[non_exhaustive]
67pub enum ProtocolViolation {
69 SendAfterEnd,
71 EmptyPacket,
73 NotConfigured,
75 EpochMismatch,
77 MissingTimestamp,
79 ClockMismatch,
81 BeginTwice,
83 NoBegin,
85 NoProgress,
88 ReceivePendingWithoutOutput,
90 FinishTwice,
92 IndexRequired,
94 EndOfStreamBeforeEndInput,
96}
97
98#[derive(Clone, Copy, Debug, PartialEq, Eq)]
99#[non_exhaustive]
100pub enum UnsupportedMedia {
102 Seek,
104 ConfigChange,
106 ForwardOnlyLayout,
108 Codec,
110 Container,
112 PixelFormat,
114 ExactTiming,
116}
117
118#[derive(Debug)]
121#[non_exhaustive]
122pub enum SessionError<E> {
123 Codec(E),
126 Cancelled(StopReason),
128 Finished,
130 Protocol(ProtocolViolation),
132 Unsupported(UnsupportedMedia),
134 Limit(MediaLimitExceeded),
136}
137
138impl<E> SessionError<E> {
139 pub fn map_codec<F>(self, f: impl FnOnce(E) -> F) -> SessionError<F> {
141 match self {
142 Self::Codec(e) => SessionError::Codec(f(e)),
143 Self::Cancelled(r) => SessionError::Cancelled(r),
144 Self::Finished => SessionError::Finished,
145 Self::Protocol(p) => SessionError::Protocol(p),
146 Self::Unsupported(u) => SessionError::Unsupported(u),
147 Self::Limit(l) => SessionError::Limit(l),
148 }
149 }
150}
151
152impl<E> From<StopReason> for SessionError<E> {
153 fn from(r: StopReason) -> Self {
154 Self::Cancelled(r)
155 }
156}
157
158impl<E: fmt::Display> fmt::Display for SessionError<E> {
159 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
160 match self {
161 Self::Codec(e) => write!(f, "{e}"),
162 Self::Cancelled(r) => write!(f, "cancelled: {r:?}"),
163 Self::Finished => f.write_str("session used after a terminal error"),
164 Self::Protocol(p) => write!(f, "protocol violation: {p:?}"),
165 Self::Unsupported(u) => write!(f, "unsupported: {u:?}"),
166 Self::Limit(l) => write!(f, "{l}"),
167 }
168 }
169}
170
171impl<E: core::error::Error + 'static> core::error::Error for SessionError<E> {
172 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
173 match self {
174 Self::Codec(e) => Some(e),
175 Self::Limit(l) => Some(l),
176 _ => None,
177 }
178 }
179}
180
181#[derive(Clone, Debug)]
184#[non_exhaustive]
185pub struct CodecConfig {
186 pub codec: CodecId,
188 pub private: Option<Arc<[u8]>>,
190 pub epoch: u32,
192 pub time_base: TimeBase,
194 pub video: Option<VideoTrackInfo>,
196}
197
198impl CodecConfig {
199 pub fn new(codec: CodecId, time_base: TimeBase) -> Self {
201 Self {
202 codec,
203 private: None,
204 epoch: 0,
205 time_base,
206 video: None,
207 }
208 }
209 pub fn with_video(mut self, video: VideoTrackInfo) -> Self {
211 self.video = Some(video);
212 self
213 }
214
215 pub fn with_private(mut self, private: Arc<[u8]>) -> Self {
217 self.private = Some(private);
218 self
219 }
220
221 pub fn with_epoch(mut self, epoch: u32) -> Self {
223 self.epoch = epoch;
224 self
225 }
226}
227
228impl From<&TrackInfo> for CodecConfig {
229 fn from(t: &TrackInfo) -> Self {
230 Self {
231 codec: t.codec().clone(),
232 private: t.codec_private().cloned(),
233 epoch: t.config_epoch(),
234 time_base: t.time_base(),
235 video: t.video_info().copied(),
236 }
237 }
238}
239
240#[derive(Clone, Debug)]
242#[non_exhaustive]
243pub struct VideoStreamInfo {
244 pub interpretation: Arc<FrameInterpretation>,
246 pub reorder_depth: Option<u32>,
249}
250
251impl VideoStreamInfo {
252 pub fn new(interpretation: Arc<FrameInterpretation>) -> Self {
254 Self {
255 interpretation,
256 reorder_depth: None,
257 }
258 }
259}
260
261pub trait VideoDecoder {
264 type Error: core::error::Error + Send + Sync + 'static;
266
267 fn configure(
270 &mut self,
271 config: &CodecConfig,
272 pulse: Option<&dyn zencodec::Pulse>,
273 ) -> Result<(), SessionError<Self::Error>>;
274
275 fn send(
278 &mut self,
279 packet: &mut Packet,
280 pulse: Option<&dyn zencodec::Pulse>,
281 ) -> Result<SendStatus, SessionError<Self::Error>>;
282
283 fn receive(
285 &mut self,
286 pulse: Option<&dyn zencodec::Pulse>,
287 ) -> Result<Receive<Frame>, SessionError<Self::Error>>;
288
289 fn end_input(&mut self) -> Result<(), SessionError<Self::Error>>;
291
292 fn reset(&mut self) -> Result<(), SessionError<Self::Error>>;
295
296 fn stream_info(&self) -> Option<&VideoStreamInfo>;
298}
299
300pub trait VideoEncoder {
303 type Error: core::error::Error + Send + Sync + 'static;
305
306 fn send(
309 &mut self,
310 frame: &Frame,
311 pulse: Option<&dyn zencodec::Pulse>,
312 ) -> Result<SendStatus, SessionError<Self::Error>>;
313
314 fn receive(
317 &mut self,
318 pulse: Option<&dyn zencodec::Pulse>,
319 ) -> Result<Receive<Packet>, SessionError<Self::Error>>;
320
321 fn end_input(&mut self) -> Result<(), SessionError<Self::Error>>;
323
324 fn output_config(&self) -> Option<&CodecConfig>;
326
327 fn output_fidelity(&self) -> Option<zencodec::encode::Fidelity> {
334 None
335 }
336}
337
338pub type DynVideoDecoder = dyn VideoDecoder<Error = ErasedError> + Send;
340pub type DynVideoEncoder = dyn VideoEncoder<Error = ErasedError> + Send;
342
343fn erase<E: core::error::Error + Send + Sync + 'static>(
344 e: SessionError<E>,
345) -> SessionError<ErasedError> {
346 e.map_codec(|c| ErasedError::new(Box::new(c)))
347}
348
349pub struct VideoDecoderShim<D>(pub D);
351
352impl<D: VideoDecoder> VideoDecoder for VideoDecoderShim<D> {
353 type Error = ErasedError;
354 fn configure(
355 &mut self,
356 config: &CodecConfig,
357 pulse: Option<&dyn zencodec::Pulse>,
358 ) -> Result<(), SessionError<ErasedError>> {
359 self.0.configure(config, pulse).map_err(erase)
360 }
361 fn send(
362 &mut self,
363 packet: &mut Packet,
364 pulse: Option<&dyn zencodec::Pulse>,
365 ) -> Result<SendStatus, SessionError<ErasedError>> {
366 self.0.send(packet, pulse).map_err(erase)
367 }
368 fn receive(
369 &mut self,
370 pulse: Option<&dyn zencodec::Pulse>,
371 ) -> Result<Receive<Frame>, SessionError<ErasedError>> {
372 self.0.receive(pulse).map_err(erase)
373 }
374 fn end_input(&mut self) -> Result<(), SessionError<ErasedError>> {
375 self.0.end_input().map_err(erase)
376 }
377 fn reset(&mut self) -> Result<(), SessionError<ErasedError>> {
378 self.0.reset().map_err(erase)
379 }
380 fn stream_info(&self) -> Option<&VideoStreamInfo> {
381 self.0.stream_info()
382 }
383}
384
385pub struct VideoEncoderShim<E>(pub E);
387
388impl<E: VideoEncoder> VideoEncoder for VideoEncoderShim<E> {
389 type Error = ErasedError;
390 fn send(
391 &mut self,
392 frame: &Frame,
393 pulse: Option<&dyn zencodec::Pulse>,
394 ) -> Result<SendStatus, SessionError<ErasedError>> {
395 self.0.send(frame, pulse).map_err(erase)
396 }
397 fn receive(
398 &mut self,
399 pulse: Option<&dyn zencodec::Pulse>,
400 ) -> Result<Receive<Packet>, SessionError<ErasedError>> {
401 self.0.receive(pulse).map_err(erase)
402 }
403 fn end_input(&mut self) -> Result<(), SessionError<ErasedError>> {
404 self.0.end_input().map_err(erase)
405 }
406 fn output_config(&self) -> Option<&CodecConfig> {
407 self.0.output_config()
408 }
409 fn output_fidelity(&self) -> Option<zencodec::encode::Fidelity> {
410 self.0.output_fidelity()
411 }
412}
413
414pub struct FusedDecoder<D> {
417 inner: D,
418 failed: bool,
419}
420
421impl<D> FusedDecoder<D> {
422 pub const fn new(inner: D) -> Self {
424 Self {
425 inner,
426 failed: false,
427 }
428 }
429 pub fn into_inner(self) -> D {
431 self.inner
432 }
433}
434
435impl<D: VideoDecoder> FusedDecoder<D> {
436 fn guard<T>(
437 &mut self,
438 pulse: &dyn zencodec::Pulse,
439 f: impl FnOnce(&mut D) -> Result<T, SessionError<D::Error>>,
440 ) -> Result<T, SessionError<D::Error>> {
441 if self.failed {
442 return Err(SessionError::Finished);
443 }
444 self.failed = true;
445 if let Err(r) = pulse.check() {
446 return Err(SessionError::Cancelled(r));
447 }
448 let r = f(&mut self.inner);
449 self.failed = r.is_err();
450 r
451 }
452}
453
454impl<D: VideoDecoder> VideoDecoder for FusedDecoder<D> {
455 type Error = D::Error;
456 fn configure(
457 &mut self,
458 config: &CodecConfig,
459 pulse: Option<&dyn zencodec::Pulse>,
460 ) -> Result<(), SessionError<D::Error>> {
461 let local_pulse = pulse.unwrap_or(&zencodec::NoPulse);
462 self.guard(local_pulse, |d| d.configure(config, pulse))
463 }
464 fn send(
465 &mut self,
466 packet: &mut Packet,
467 pulse: Option<&dyn zencodec::Pulse>,
468 ) -> Result<SendStatus, SessionError<D::Error>> {
469 let local_pulse = pulse.unwrap_or(&zencodec::NoPulse);
470 self.guard(local_pulse, |d| d.send(packet, pulse))
471 }
472 fn receive(
473 &mut self,
474 pulse: Option<&dyn zencodec::Pulse>,
475 ) -> Result<Receive<Frame>, SessionError<D::Error>> {
476 let local_pulse = pulse.unwrap_or(&zencodec::NoPulse);
477 self.guard(local_pulse, |d| d.receive(pulse))
478 }
479 fn end_input(&mut self) -> Result<(), SessionError<D::Error>> {
480 if self.failed {
481 return Err(SessionError::Finished);
482 }
483 self.failed = true;
484 let r = self.inner.end_input();
485 self.failed = r.is_err();
486 r
487 }
488 fn reset(&mut self) -> Result<(), SessionError<D::Error>> {
489 self.failed = true;
490 let r = self.inner.reset();
491 self.failed = r.is_err();
492 r
493 }
494 fn stream_info(&self) -> Option<&VideoStreamInfo> {
495 self.inner.stream_info()
496 }
497}
498
499pub struct FusedEncoder<E> {
506 inner: E,
507 failed: bool,
508}
509
510impl<E> FusedEncoder<E> {
511 pub const fn new(inner: E) -> Self {
513 Self {
514 inner,
515 failed: false,
516 }
517 }
518
519 pub fn into_inner(self) -> E {
521 self.inner
522 }
523}
524
525impl<E: VideoEncoder> FusedEncoder<E> {
526 fn guard<T>(
527 &mut self,
528 pulse: &dyn zencodec::Pulse,
529 f: impl FnOnce(&mut E) -> Result<T, SessionError<E::Error>>,
530 ) -> Result<T, SessionError<E::Error>> {
531 if self.failed {
532 return Err(SessionError::Finished);
533 }
534 self.failed = true;
537 pulse.check().map_err(SessionError::Cancelled)?;
538 let result = f(&mut self.inner);
539 self.failed = result.is_err();
540 result
541 }
542}
543
544impl<E: VideoEncoder> VideoEncoder for FusedEncoder<E> {
545 type Error = E::Error;
546 fn send(
547 &mut self,
548 frame: &Frame,
549 pulse: Option<&dyn zencodec::Pulse>,
550 ) -> Result<SendStatus, SessionError<E::Error>> {
551 let local_pulse = pulse.unwrap_or(&zencodec::NoPulse);
552 self.guard(local_pulse, |encoder| encoder.send(frame, pulse))
553 }
554 fn receive(
555 &mut self,
556 pulse: Option<&dyn zencodec::Pulse>,
557 ) -> Result<Receive<Packet>, SessionError<E::Error>> {
558 let local_pulse = pulse.unwrap_or(&zencodec::NoPulse);
559 self.guard(local_pulse, |encoder| encoder.receive(pulse))
560 }
561 fn end_input(&mut self) -> Result<(), SessionError<E::Error>> {
562 self.guard(&zencodec::how_far::NoPulse, VideoEncoder::end_input)
563 }
564 fn output_config(&self) -> Option<&CodecConfig> {
565 self.inner.output_config()
566 }
567 fn output_fidelity(&self) -> Option<zencodec::encode::Fidelity> {
568 self.inner.output_fidelity()
569 }
570}
571
572pub fn erase_video_decoder<D: VideoDecoder + Send + 'static>(d: D) -> Box<DynVideoDecoder> {
575 Box::new(VideoDecoderShim(FusedDecoder::new(d)))
576}
577
578pub fn erase_video_encoder<E: VideoEncoder + Send + 'static>(e: E) -> Box<DynVideoEncoder> {
582 Box::new(VideoEncoderShim(FusedEncoder::new(e)))
583}
584
585impl<D: VideoDecoder + ?Sized> VideoDecoder for Box<D> {
586 type Error = D::Error;
587 fn configure(
588 &mut self,
589 config: &CodecConfig,
590 pulse: Option<&dyn zencodec::Pulse>,
591 ) -> Result<(), SessionError<D::Error>> {
592 (**self).configure(config, pulse)
593 }
594 fn send(
595 &mut self,
596 packet: &mut Packet,
597 pulse: Option<&dyn zencodec::Pulse>,
598 ) -> Result<SendStatus, SessionError<D::Error>> {
599 (**self).send(packet, pulse)
600 }
601 fn receive(
602 &mut self,
603 pulse: Option<&dyn zencodec::Pulse>,
604 ) -> Result<Receive<Frame>, SessionError<D::Error>> {
605 (**self).receive(pulse)
606 }
607 fn end_input(&mut self) -> Result<(), SessionError<D::Error>> {
608 (**self).end_input()
609 }
610 fn reset(&mut self) -> Result<(), SessionError<D::Error>> {
611 (**self).reset()
612 }
613 fn stream_info(&self) -> Option<&VideoStreamInfo> {
614 (**self).stream_info()
615 }
616}
617
618impl<E: VideoEncoder + ?Sized> VideoEncoder for Box<E> {
619 type Error = E::Error;
620 fn send(
621 &mut self,
622 frame: &Frame,
623 pulse: Option<&dyn zencodec::Pulse>,
624 ) -> Result<SendStatus, SessionError<E::Error>> {
625 (**self).send(frame, pulse)
626 }
627 fn receive(
628 &mut self,
629 pulse: Option<&dyn zencodec::Pulse>,
630 ) -> Result<Receive<Packet>, SessionError<E::Error>> {
631 (**self).receive(pulse)
632 }
633 fn end_input(&mut self) -> Result<(), SessionError<E::Error>> {
634 (**self).end_input()
635 }
636 fn output_config(&self) -> Option<&CodecConfig> {
637 (**self).output_config()
638 }
639 fn output_fidelity(&self) -> Option<zencodec::encode::Fidelity> {
640 (**self).output_fidelity()
641 }
642}
643
644pub fn send_packet_until_accepted<D, F, E2>(
652 dec: &mut D,
653 packet: &mut Packet,
654 pulse: Option<&dyn zencodec::Pulse>,
655 mut on_output: F,
656) -> Result<(), PumpError<SessionError<D::Error>, E2>>
657where
658 D: VideoDecoder + ?Sized,
659 F: FnMut(Frame) -> Result<(), E2>,
660{
661 loop {
662 match dec.send(packet, pulse).map_err(PumpError::Upstream)? {
663 SendStatus::Accepted => break,
664 SendStatus::ReceivePending => match dec.receive(pulse).map_err(PumpError::Upstream)? {
665 Receive::Ready(f) => on_output(f).map_err(PumpError::Downstream)?,
666 _ => {
667 return Err(PumpError::Upstream(SessionError::Protocol(
668 ProtocolViolation::ReceivePendingWithoutOutput,
669 )));
670 }
671 },
672 }
673 }
674 loop {
677 match dec.receive(pulse).map_err(PumpError::Upstream)? {
678 Receive::Ready(f) => on_output(f).map_err(PumpError::Downstream)?,
679 Receive::NeedInput => return Ok(()),
680 Receive::EndOfStream => {
681 return Err(PumpError::Upstream(SessionError::Protocol(
682 ProtocolViolation::EndOfStreamBeforeEndInput,
683 )));
684 }
685 }
686 }
687}
688
689pub fn send_frame_until_accepted<E, F, E2>(
695 enc: &mut E,
696 frame: &Frame,
697 pulse: Option<&dyn zencodec::Pulse>,
698 mut on_output: F,
699) -> Result<(), PumpError<SessionError<E::Error>, E2>>
700where
701 E: VideoEncoder + ?Sized,
702 F: FnMut(Packet) -> Result<(), E2>,
703{
704 loop {
705 match enc.send(frame, pulse).map_err(PumpError::Upstream)? {
706 SendStatus::Accepted => break,
707 SendStatus::ReceivePending => match enc.receive(pulse).map_err(PumpError::Upstream)? {
708 Receive::Ready(p) => on_output(p).map_err(PumpError::Downstream)?,
709 _ => {
710 return Err(PumpError::Upstream(SessionError::Protocol(
711 ProtocolViolation::ReceivePendingWithoutOutput,
712 )));
713 }
714 },
715 }
716 }
717 loop {
718 match enc.receive(pulse).map_err(PumpError::Upstream)? {
719 Receive::Ready(p) => on_output(p).map_err(PumpError::Downstream)?,
720 Receive::NeedInput => return Ok(()),
721 Receive::EndOfStream => {
722 return Err(PumpError::Upstream(SessionError::Protocol(
723 ProtocolViolation::EndOfStreamBeforeEndInput,
724 )));
725 }
726 }
727 }
728}
729
730pub fn drain_decoder<D, F, E2>(
737 dec: &mut D,
738 pulse: Option<&dyn zencodec::Pulse>,
739 mut on_output: F,
740) -> Result<(), PumpError<SessionError<D::Error>, E2>>
741where
742 D: VideoDecoder + ?Sized,
743 F: FnMut(Frame) -> Result<(), E2>,
744{
745 dec.end_input().map_err(PumpError::Upstream)?;
746 loop {
747 match dec.receive(pulse).map_err(PumpError::Upstream)? {
748 Receive::Ready(f) => on_output(f).map_err(PumpError::Downstream)?,
749 Receive::EndOfStream => return Ok(()),
750 Receive::NeedInput => {
751 return Err(PumpError::Upstream(SessionError::Protocol(
752 ProtocolViolation::NoProgress,
753 )));
754 }
755 }
756 }
757}
758
759pub fn drain_encoder<E, F, E2>(
765 enc: &mut E,
766 pulse: Option<&dyn zencodec::Pulse>,
767 mut on_output: F,
768) -> Result<(), PumpError<SessionError<E::Error>, E2>>
769where
770 E: VideoEncoder + ?Sized,
771 F: FnMut(Packet) -> Result<(), E2>,
772{
773 enc.end_input().map_err(PumpError::Upstream)?;
774 loop {
775 match enc.receive(pulse).map_err(PumpError::Upstream)? {
776 Receive::Ready(p) => on_output(p).map_err(PumpError::Downstream)?,
777 Receive::EndOfStream => return Ok(()),
778 Receive::NeedInput => {
779 return Err(PumpError::Upstream(SessionError::Protocol(
780 ProtocolViolation::NoProgress,
781 )));
782 }
783 }
784 }
785}
786
787#[derive(Debug)]
789pub enum PumpError<U, D> {
790 Upstream(U),
792 Downstream(D),
794}
795
796impl<U: fmt::Display, D: fmt::Display> fmt::Display for PumpError<U, D> {
797 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
798 match self {
799 Self::Upstream(e) => write!(f, "upstream: {e}"),
800 Self::Downstream(e) => write!(f, "downstream: {e}"),
801 }
802 }
803}
804impl<U: core::error::Error + 'static, D: core::error::Error + 'static> core::error::Error
805 for PumpError<U, D>
806{
807 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
808 match self {
809 Self::Upstream(error) => Some(error),
810 Self::Downstream(error) => Some(error),
811 }
812 }
813}