1pub mod av1;
15pub mod h264;
16pub mod h265;
17pub mod vp8;
18pub mod vp9;
19
20use std::os::fd::AsFd;
21use std::os::fd::BorrowedFd;
22
23use nix::errno::Errno;
24use nix::sys::epoll::Epoll;
25use nix::sys::epoll::EpollCreateFlags;
26use nix::sys::epoll::EpollEvent;
27use nix::sys::epoll::EpollFlags;
28use nix::sys::eventfd::EventFd;
29use thiserror::Error;
30
31use crate::codec::vp8::parser::ParseFrameError;
32use crate::decoder::BlockingMode;
33use crate::decoder::DecodedHandle;
34use crate::decoder::DecoderEvent;
35use crate::decoder::DecoderFormatNegotiator;
36use crate::decoder::DynDecodedHandle;
37use crate::decoder::FramePool;
38use crate::decoder::ReadyFramesQueue;
39use crate::decoder::StreamInfo;
40use crate::DecodedFormat;
41use crate::Resolution;
42
43#[derive(Error, Debug)]
46pub enum NewPictureError {
47 #[error("need one output buffer to be returned before operation can proceed")]
50 OutOfOutputBuffers,
51 #[error("no frame pool can satisfy the requested frame resolution {0:?}")]
54 NoFramePool(Resolution),
55 #[error(transparent)]
57 BackendError(#[from] anyhow::Error),
58}
59
60pub type NewPictureResult<T> = Result<T, NewPictureError>;
61
62#[derive(Error, Debug)]
64pub enum StatelessBackendError {
65 #[error(transparent)]
66 Other(#[from] anyhow::Error),
67}
68
69pub type StatelessBackendResult<T> = Result<T, StatelessBackendError>;
71
72#[derive(Default)]
77enum DecodingState<F> {
78 #[default]
80 AwaitingStreamInfo,
81 AwaitingFormat(F),
83 Decoding,
85 Reset,
88}
89
90#[derive(Debug, Error)]
92pub enum DecodeError {
93 #[error("not enough output buffers available to continue, need {0} more")]
94 NotEnoughOutputBuffers(usize),
95 #[error("cannot accept more input until pending events are processed")]
96 CheckEvents,
97 #[error("error while parsing frame: {0}")]
98 ParseFrameError(#[from] ParseFrameError),
99 #[error(transparent)]
100 DecoderError(#[from] anyhow::Error),
101 #[error(transparent)]
102 BackendError(#[from] StatelessBackendError),
103}
104
105impl From<NewPictureError> for DecodeError {
107 fn from(err: NewPictureError) -> Self {
108 match err {
109 NewPictureError::OutOfOutputBuffers => DecodeError::NotEnoughOutputBuffers(1),
110 e @ NewPictureError::NoFramePool(_) => {
111 DecodeError::BackendError(StatelessBackendError::Other(anyhow::anyhow!(e)))
112 }
113 NewPictureError::BackendError(e) => {
114 DecodeError::BackendError(StatelessBackendError::Other(e))
115 }
116 }
117 }
118}
119
120mod private {
121 use super::*;
122
123 pub(super) trait StatelessVideoDecoder {
126 fn try_format(&mut self, format: DecodedFormat) -> anyhow::Result<()>;
129 }
130}
131
132pub trait StatelessDecoderBackendPicture<Codec: StatelessCodec> {
137 type Picture;
142}
143
144pub trait TryFormat<Codec: StatelessCodec> {
145 fn try_format(
147 &mut self,
148 format_info: &Codec::FormatInfo,
149 format: DecodedFormat,
150 ) -> anyhow::Result<()>;
151}
152
153pub trait StatelessDecoderBackend {
156 type Handle: DecodedHandle;
161
162 type FramePool: FramePool<Descriptor = <Self::Handle as DecodedHandle>::Descriptor>;
163
164 fn stream_info(&self) -> Option<&StreamInfo>;
166
167 fn frame_pool(&mut self, layer: PoolLayer) -> Vec<&mut Self::FramePool>;
169}
170
171pub struct StatelessDecoderFormatNegotiator<'a, H, FP, D, FH, F>
173where
174 H: DecodedHandle,
175 FP: FramePool<Descriptor = H::Descriptor>,
176 D: StatelessVideoDecoder<Handle = H, FramePool = FP>,
177 F: Fn(&mut D, &FH),
178{
179 decoder: &'a mut D,
180 format_hint: FH,
181 apply_format: F,
182}
183
184impl<'a, H, FP, D, FH, F> StatelessDecoderFormatNegotiator<'a, H, FP, D, FH, F>
185where
186 H: DecodedHandle,
187 FP: FramePool<Descriptor = H::Descriptor>,
188 D: StatelessVideoDecoder<Handle = H, FramePool = FP>,
189 F: Fn(&mut D, &FH),
190{
191 fn new(decoder: &'a mut D, format_hint: FH, apply_format: F) -> Self {
201 Self {
202 decoder,
203 format_hint,
204 apply_format,
205 }
206 }
207}
208
209impl<'a, H, FP, D, FH, F> DecoderFormatNegotiator
210 for StatelessDecoderFormatNegotiator<'a, H, FP, D, FH, F>
211where
212 H: DecodedHandle,
213 FP: FramePool<Descriptor = H::Descriptor>,
214 D: StatelessVideoDecoder<Handle = H, FramePool = FP> + private::StatelessVideoDecoder,
215 F: Fn(&mut D, &FH),
216{
217 type Descriptor = H::Descriptor;
218
219 fn try_format(&mut self, format: DecodedFormat) -> anyhow::Result<()> {
220 self.decoder.try_format(format)
221 }
222
223 fn frame_pool(
224 &mut self,
225 layer: PoolLayer,
226 ) -> Vec<&mut dyn FramePool<Descriptor = Self::Descriptor>> {
227 self.decoder
228 .frame_pool(layer)
229 .into_iter()
230 .map(|p| p as &mut dyn FramePool<Descriptor = _>)
231 .collect()
232 }
233
234 fn stream_info(&self) -> &StreamInfo {
235 self.decoder.stream_info().unwrap()
236 }
237}
238
239impl<'a, H, FP, D, FH, F> Drop for StatelessDecoderFormatNegotiator<'a, H, FP, D, FH, F>
240where
241 H: DecodedHandle,
242 FP: FramePool<Descriptor = H::Descriptor>,
243 D: StatelessVideoDecoder<Handle = H, FramePool = FP>,
244 F: Fn(&mut D, &FH),
245{
246 fn drop(&mut self) {
247 (self.apply_format)(self.decoder, &self.format_hint)
248 }
249}
250
251#[derive(Debug, Clone, Copy)]
253pub enum PoolLayer {
254 Highest,
256 Layer(Resolution),
258 All,
260}
261
262pub trait StatelessVideoDecoder {
277 type Handle: DecodedHandle;
279
280 type FramePool: FramePool<Descriptor = <Self::Handle as DecodedHandle>::Descriptor> + ?Sized;
283
284 fn decode(&mut self, timestamp: u64, bitstream: &[u8]) -> Result<usize, DecodeError>;
298
299 fn flush(&mut self) -> Result<(), DecodeError>;
306
307 fn frame_pool(&mut self, layer: PoolLayer) -> Vec<&mut Self::FramePool>;
315
316 fn stream_info(&self) -> Option<&StreamInfo>;
317
318 fn next_event(&mut self) -> Option<DecoderEvent<Self::Handle>>;
320
321 fn poll_fd(&self) -> BorrowedFd;
324
325 fn into_trait_object(
331 self,
332 ) -> DynStatelessVideoDecoder<<Self::Handle as DecodedHandle>::Descriptor>
333 where
334 Self: Sized + 'static,
335 Self::FramePool: Sized + 'static,
336 Self::Handle: 'static,
337 {
338 Box::new(DynStatelessVideoDecoderWrapper(self))
339 }
340}
341
342struct DynStatelessVideoDecoderWrapper<D: StatelessVideoDecoder>(D);
345
346impl<D> StatelessVideoDecoder for DynStatelessVideoDecoderWrapper<D>
347where
348 D: StatelessVideoDecoder,
349 <D as StatelessVideoDecoder>::FramePool: Sized + 'static,
350 <D as StatelessVideoDecoder>::Handle: 'static,
351{
352 type Handle = DynDecodedHandle<<D::Handle as DecodedHandle>::Descriptor>;
353 type FramePool = dyn FramePool<Descriptor = <D::FramePool as FramePool>::Descriptor>;
354
355 fn decode(&mut self, timestamp: u64, bitstream: &[u8]) -> Result<usize, DecodeError> {
356 self.0.decode(timestamp, bitstream)
357 }
358
359 fn flush(&mut self) -> Result<(), DecodeError> {
360 self.0.flush()
361 }
362
363 fn frame_pool(&mut self, layer: PoolLayer) -> Vec<&mut Self::FramePool> {
364 self.0
365 .frame_pool(layer)
366 .into_iter()
367 .map(|p| p as &mut Self::FramePool)
368 .collect()
369 }
370
371 fn stream_info(&self) -> Option<&StreamInfo> {
372 self.0.stream_info()
373 }
374
375 fn next_event(&mut self) -> Option<DecoderEvent<Self::Handle>> {
376 self.0.next_event().map(|e| match e {
377 DecoderEvent::FrameReady(h) => {
378 DecoderEvent::FrameReady(Box::new(h) as DynDecodedHandle<_>)
379 }
380 DecoderEvent::FormatChanged(n) => DecoderEvent::FormatChanged(n),
381 })
382 }
383
384 fn poll_fd(&self) -> BorrowedFd {
385 self.0.poll_fd()
386 }
387}
388
389pub type DynStatelessVideoDecoder<D> = Box<
390 dyn StatelessVideoDecoder<
391 Handle = DynDecodedHandle<D>,
392 FramePool = dyn FramePool<Descriptor = D>,
393 >,
394>;
395
396pub trait StatelessCodec {
397 type FormatInfo;
401 type DecoderState<H: DecodedHandle, P>;
403}
404
405pub struct StatelessDecoder<C, B>
425where
426 C: StatelessCodec,
427 B: StatelessDecoderBackend + StatelessDecoderBackendPicture<C>,
428{
429 coded_resolution: Resolution,
431
432 blocking_mode: BlockingMode,
434
435 ready_queue: ReadyFramesQueue<B::Handle>,
436
437 decoding_state: DecodingState<C::FormatInfo>,
438
439 backend: B,
441
442 codec: C::DecoderState<B::Handle, B::Picture>,
444
445 awaiting_format_event: EventFd,
447
448 epoll_fd: Epoll,
451}
452
453#[derive(Debug, Error)]
454pub enum NewStatelessDecoderError {
455 #[error("failed to create EventFd for ready frames queue: {0}")]
456 ReadyFramesQueue(Errno),
457 #[error("failed to create EventFd for awaiting format event: {0}")]
458 AwaitingFormatEventFd(Errno),
459 #[error("failed to create Epoll for decoder: {0}")]
460 Epoll(Errno),
461 #[error("failed to add poll FDs to decoder Epoll: {0}")]
462 EpollAdd(Errno),
463}
464
465impl<C, B> StatelessDecoder<C, B>
466where
467 C: StatelessCodec,
468 B: StatelessDecoderBackend + StatelessDecoderBackendPicture<C> + TryFormat<C>,
469 C::DecoderState<B::Handle, B::Picture>: Default,
470{
471 pub fn new(backend: B, blocking_mode: BlockingMode) -> Result<Self, NewStatelessDecoderError> {
472 let ready_queue =
473 ReadyFramesQueue::new().map_err(NewStatelessDecoderError::ReadyFramesQueue)?;
474 let awaiting_format_event =
475 EventFd::new().map_err(NewStatelessDecoderError::AwaitingFormatEventFd)?;
476 let epoll_fd =
477 Epoll::new(EpollCreateFlags::empty()).map_err(NewStatelessDecoderError::Epoll)?;
478 epoll_fd
479 .add(
480 ready_queue.poll_fd(),
481 EpollEvent::new(EpollFlags::EPOLLIN, 1),
482 )
483 .map_err(NewStatelessDecoderError::EpollAdd)?;
484 epoll_fd
485 .add(
486 awaiting_format_event.as_fd(),
487 EpollEvent::new(EpollFlags::EPOLLIN, 2),
488 )
489 .map_err(NewStatelessDecoderError::EpollAdd)?;
490
491 Ok(Self {
492 backend,
493 blocking_mode,
494 coded_resolution: Default::default(),
495 decoding_state: Default::default(),
496 ready_queue,
497 codec: Default::default(),
498 awaiting_format_event,
499 epoll_fd,
500 })
501 }
502
503 fn await_format_change(&mut self, format_info: C::FormatInfo) {
506 self.decoding_state = DecodingState::AwaitingFormat(format_info);
507 self.awaiting_format_event.write(1).unwrap();
508 }
509
510 fn query_next_event<F>(&mut self, on_format_changed: F) -> Option<DecoderEvent<B::Handle>>
514 where
515 Self: StatelessVideoDecoder<Handle = B::Handle, FramePool = B::FramePool>,
516 C::FormatInfo: Clone,
517 F: Fn(&mut Self, &C::FormatInfo) + 'static,
518 {
519 self.ready_queue
522 .next()
523 .map(DecoderEvent::FrameReady)
524 .or_else(|| {
525 if let DecodingState::AwaitingFormat(format_info) = &self.decoding_state {
526 Some(DecoderEvent::FormatChanged(Box::new(
527 StatelessDecoderFormatNegotiator::new(
528 self,
529 format_info.clone(),
530 move |decoder, sps| {
531 on_format_changed(decoder, sps);
532 decoder.decoding_state = DecodingState::Decoding;
533 decoder.awaiting_format_event.read().unwrap();
535 },
536 ),
537 )))
538 } else {
539 None
540 }
541 })
542 }
543}
544
545impl<C, B> private::StatelessVideoDecoder for StatelessDecoder<C, B>
546where
547 C: StatelessCodec,
548 B: StatelessDecoderBackend + StatelessDecoderBackendPicture<C> + TryFormat<C>,
549{
550 fn try_format(&mut self, format: crate::DecodedFormat) -> anyhow::Result<()> {
551 match &self.decoding_state {
552 DecodingState::AwaitingFormat(sps) => self.backend.try_format(sps, format),
553 _ => Err(anyhow::anyhow!(
554 "current decoder state does not allow format change"
555 )),
556 }
557 }
558}
559
560#[cfg(test)]
561pub(crate) mod tests {
562 use crate::decoder::stateless::StatelessVideoDecoder;
563 use crate::decoder::DecodedHandle;
564 use crate::decoder::FramePool;
565
566 pub struct TestStream {
568 pub stream: &'static [u8],
570 pub crcs: &'static str,
572 }
573
574 pub fn test_decode_stream<D, H, FP, L>(
584 decoding_loop: L,
585 mut decoder: D,
586 test: &TestStream,
587 check_crcs: bool,
588 dump_yuv: bool,
589 ) where
590 H: DecodedHandle,
591 FP: FramePool,
592 D: StatelessVideoDecoder<Handle = H, FramePool = FP>,
593 L: Fn(&mut D, &[u8], &mut dyn FnMut(H)) -> anyhow::Result<()>,
594 {
595 let mut crcs = test.crcs.lines().enumerate();
596
597 decoding_loop(&mut decoder, test.stream, &mut |handle| {
598 let (frame_num, expected_crc) = crcs.next().expect("decoded more frames than expected");
599
600 if check_crcs || dump_yuv {
601 handle.sync().unwrap();
602 let picture = handle.dyn_picture();
603 let mut backend_handle = picture.dyn_mappable_handle().unwrap();
604
605 let buffer_size = backend_handle.image_size();
606 let mut nv12 = vec![0; buffer_size];
607
608 backend_handle.read(&mut nv12).unwrap();
609
610 if dump_yuv {
611 std::fs::write(format!("/tmp/frame{:03}.yuv", frame_num), &nv12).unwrap();
612 }
613
614 if check_crcs {
615 let frame_crc = format!("{:08x}", crc32fast::hash(&nv12));
616 assert_eq!(frame_crc, expected_crc, "at frame {}", frame_num);
617 }
618 }
619 })
620 .unwrap();
621
622 assert_eq!(crcs.next(), None, "decoded less frames than expected");
623 }
624}