Skip to main content

mediadecode_ffmpeg/
adapter.rs

1//! `Ffmpeg` adapter — implements [`mediadecode::VideoAdapter`],
2//! [`mediadecode::AudioAdapter`], [`mediadecode::SubtitleAdapter`] and
3//! [`mediadecode::demuxer::DemuxAdapter`] for this crate.
4//!
5//! The adapter is a zero-sized type whose sole purpose is to bind the
6//! associated types together so the rest of the API (Packet / Frame /
7//! Decoder) reads cleanly: `VideoPacket<Ffmpeg, FfmpegBuffer>` etc.
8//!
9//! `DemuxAdapter` bundles the other three, and `Ffmpeg` fills all four
10//! seats with itself — the demux tier's `CodecId` bound (one
11//! codec-identifier namespace across a container's whole track table) is
12//! trivially satisfied when every family already binds
13//! [`crate::CodecId`].
14
15use mediadecode::{
16  PixelFormat,
17  adapter::{AudioAdapter, SubtitleAdapter, VideoAdapter},
18  demuxer::DemuxAdapter,
19};
20use mediaframe::audio::ChannelLayoutDescription;
21use smol_str::SmolStr;
22
23use crate::{
24  codec_id::CodecId,
25  extras::{
26    AttachmentPacketExtra, AudioFrameExtra, AudioPacketExtra, DataPacketExtra, SubtitleFrameExtra,
27    SubtitlePacketExtra, TrackExtra, VideoFrameExtra, VideoPacketExtra,
28  },
29  sample_format::SampleFormat,
30};
31
32/// Zero-sized type carrying the FFmpeg adapter's vocabulary.
33///
34/// Used as the `A` parameter on `mediadecode::VideoPacket<A, B>` /
35/// `Frame<A, B>` (and audio / subtitle counterparts) when this crate's
36/// decoders are in play. Construction is `Ffmpeg` (unit struct);
37/// nothing about the adapter is stateful.
38#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Hash)]
39pub struct Ffmpeg;
40
41impl VideoAdapter for Ffmpeg {
42  type CodecId = CodecId;
43  type PixelFormat = PixelFormat;
44  type PacketExtra = VideoPacketExtra;
45  type FrameExtra = VideoFrameExtra;
46}
47
48impl AudioAdapter for Ffmpeg {
49  type CodecId = CodecId;
50  type SampleFormat = SampleFormat;
51  type ChannelLayout = ChannelLayoutDescription;
52  type PacketExtra = AudioPacketExtra;
53  type FrameExtra = AudioFrameExtra;
54}
55
56impl SubtitleAdapter for Ffmpeg {
57  type CodecId = CodecId;
58  type PacketExtra = SubtitlePacketExtra;
59  type FrameExtra = SubtitleFrameExtra;
60}
61
62impl DemuxAdapter for Ffmpeg {
63  type CodecId = CodecId;
64  type Video = Ffmpeg;
65  type Audio = Ffmpeg;
66  type Subtitle = Ffmpeg;
67  type DataExtra = DataPacketExtra;
68  type AttachmentExtra = AttachmentPacketExtra;
69  type TrackExtra = TrackExtra;
70  // `AVStream.metadata` hands out borrowed `&str` that dies with the
71  // format context, so a track row has to own its identity strings.
72  // `SmolStr` stores a filename or a MIME type inline — both are short
73  // — which is why the rest of this crate's FFI text handling already
74  // uses it.
75  type Text = SmolStr;
76}
77
78#[cfg(test)]
79mod tests {
80  use super::*;
81
82  /// Compile-time proof that the three trait impls' associated types
83  /// resolve correctly when the `Ffmpeg` adapter parameterizes
84  /// mediadecode's generic types.
85  #[test]
86  fn adapter_parameterizes_mediadecode_types() {
87    use crate::buffer::FfmpegBuffer;
88    use mediadecode::{
89      adapter::{AudioAdapter, SubtitleAdapter, VideoAdapter},
90      packet::{AudioPacket, SubtitlePacket, VideoPacket},
91    };
92
93    fn _video_packet_resolves(
94      _: &VideoPacket<Ffmpeg, FfmpegBuffer>,
95      _: <Ffmpeg as VideoAdapter>::CodecId,
96      _: <Ffmpeg as VideoAdapter>::PixelFormat,
97      _: &<Ffmpeg as VideoAdapter>::PacketExtra,
98      _: &<Ffmpeg as VideoAdapter>::FrameExtra,
99    ) {
100    }
101
102    fn _audio_packet_resolves(
103      _: &AudioPacket<Ffmpeg, FfmpegBuffer>,
104      _: <Ffmpeg as AudioAdapter>::CodecId,
105      _: <Ffmpeg as AudioAdapter>::SampleFormat,
106      _: &<Ffmpeg as AudioAdapter>::ChannelLayout,
107      _: &<Ffmpeg as AudioAdapter>::PacketExtra,
108      _: &<Ffmpeg as AudioAdapter>::FrameExtra,
109    ) {
110    }
111
112    fn _subtitle_packet_resolves(
113      _: &SubtitlePacket<Ffmpeg, FfmpegBuffer>,
114      _: <Ffmpeg as SubtitleAdapter>::CodecId,
115      _: &<Ffmpeg as SubtitleAdapter>::PacketExtra,
116      _: &<Ffmpeg as SubtitleAdapter>::FrameExtra,
117    ) {
118    }
119  }
120
121  #[test]
122  fn ffmpeg_is_zero_sized() {
123    use core::mem::size_of;
124    assert_eq!(size_of::<Ffmpeg>(), 0);
125  }
126}