na_mpeg2_decoder/
pipeline.rs

1use std::sync::Arc;
2
3use crate::demux::{Demuxer, StreamType};
4use crate::video::{Decoder, Frame};
5
6use crate::video::Result;
7
8/// High-level convenience wrapper: demux container bytes and decode MPEG-1/2 video frames.
9///
10/// This type is designed for low-overhead integration:
11/// - You can reuse a single pipeline instance across the whole stream.
12/// - Use `push_with()`/`flush_with()` to avoid collecting frames into intermediate vectors.
13#[derive(Debug, Default)]
14pub struct MpegVideoPipeline {
15    demux: Demuxer,
16    dec: Decoder,
17    pkts: Vec<crate::demux::Packet>,
18}
19
20impl MpegVideoPipeline {
21    #[inline]
22    pub fn new() -> Self {
23        Self { demux: Demuxer::new_auto(), dec: Decoder::new(), pkts: Vec::new() }
24    }
25
26    #[inline]
27    pub fn decoder_mut(&mut self) -> &mut Decoder {
28        &mut self.dec
29    }
30
31    #[inline]
32    pub fn demuxer_mut(&mut self) -> &mut Demuxer {
33        &mut self.demux
34    }
35
36    /// Feed container bytes and invoke `on_frame` for each decoded frame.
37    ///
38    /// `pts_90k` is optional chunk-level PTS in 90 kHz timebase. When demuxing TS/PS,
39    /// packet-level PTS from PES headers takes precedence.
40    pub fn push_with<F>(&mut self, data: &[u8], pts_90k: Option<i64>, mut on_frame: F) -> Result<()>
41    where
42        F: FnMut(Arc<Frame>),
43    {
44        self.pkts.clear();
45        self.demux.push_into(data, pts_90k, &mut self.pkts);
46        for pkt in self.pkts.drain(..) {
47            if pkt.stream_type != StreamType::MpegVideo {
48                continue;
49            }
50            for f in self.dec.decode_shared(&pkt.data, pkt.pts_90k)? {
51                on_frame(f);
52            }
53        }
54        Ok(())
55    }
56
57    /// Flush delayed frames and invoke `on_frame` for each of them.
58    pub fn flush_with<F>(&mut self, mut on_frame: F) -> Result<()>
59    where
60        F: FnMut(Arc<Frame>),
61    {
62        for f in self.dec.flush_shared()? {
63            on_frame(f);
64        }
65        Ok(())
66    }
67}