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}