Skip to main content

media_pp\core/
buffer.rs

1use std::sync::Arc;
2
3use ffmpeg_next as ffmpeg;
4
5use crate::pool::UnboundObjectPoolRef;
6
7/// The unit of data that flows between elements.
8///
9/// Compressed and uncompressed data are kept as distinct variants (rather
10/// than a single opaque `Buffer` type like GStreamer) because ffmpeg-next
11/// already gives us strongly-typed `Packet`/`Frame` types — collapsing them
12/// into one type would just mean unwrapping again downstream.
13///
14/// Payloads are `Arc`-wrapped so `MediaBuffer` is cheaply `Clone` —
15/// duplicating a buffer (e.g. [`crate::elements::Tee`] fanning packets out
16/// to a decode branch and a remux branch) is a refcount bump, never a copy
17/// of the encoded/decoded data.
18///
19/// `Video` specifically wraps an [`UnboundObjectPoolRef`], not a plain
20/// `ffmpeg::frame::Video` — that's what lets whichever element produced it
21/// (see [`crate::pool::UnboundObjectPool`], owned as that element's own
22/// struct field) get the underlying buffer back automatically once every
23/// `Arc` clone downstream has been dropped, instead of it just being freed.
24#[derive(Clone)]
25pub enum MediaBuffer {
26    Packet(Arc<ffmpeg::Packet>),
27    Video(Arc<UnboundObjectPoolRef<ffmpeg::frame::Video>>),
28    Audio(Arc<ffmpeg::frame::Audio>),
29    /// End of stream marker. Elements that hold resources (encoders with
30    /// delayed frames, muxers, ...) should flush when they see this.
31    Eos,
32}
33
34impl MediaBuffer {
35    pub fn is_eos(&self) -> bool {
36        matches!(self, MediaBuffer::Eos)
37    }
38
39    /// Stable, human-readable variant name for diagnostics emitted when
40    /// elements are wired to an incompatible media type.
41    pub fn kind(&self) -> &'static str {
42        match self {
43            MediaBuffer::Packet(_) => "Packet",
44            MediaBuffer::Video(_) => "Video",
45            MediaBuffer::Audio(_) => "Audio",
46            MediaBuffer::Eos => "Eos",
47        }
48    }
49}
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54
55    #[test]
56    fn kind_reports_each_variant() {
57        assert_eq!(
58            MediaBuffer::Packet(Arc::new(ffmpeg::Packet::empty())).kind(),
59            "Packet"
60        );
61        assert_eq!(
62            MediaBuffer::Audio(Arc::new(ffmpeg::frame::Audio::empty())).kind(),
63            "Audio"
64        );
65        assert_eq!(MediaBuffer::Eos.kind(), "Eos");
66    }
67}