Skip to main content

mediadecode_ffmpeg/
lib.rs

1#![doc = include_str!("../README.md")]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3#![cfg_attr(docsrs, allow(unused_attributes))]
4#![deny(missing_docs)]
5// The core crate carries this same allow, for this same reason, and 0.9
6// is where this crate joined it: a signature here reads
7// `VideoPacket<VideoPacketExtra, FfmpegBytes>` because every one of those
8// three names is load-bearing — the household, the backend's extras,
9// and the owned carrier the D-seat amputation contract requires.
10// `clippy::type_complexity` counts nesting, and the fix it asks for is
11// an alias that hides exactly the word this release exists to make
12// visible. 0.8 had that alias; it was called `FfmpegBuffer`.
13#![allow(clippy::type_complexity)]
14
15mod adapter;
16mod audio;
17mod backend;
18pub mod boundary;
19mod buffer;
20mod carrier;
21pub mod channel_layout;
22mod codec_id;
23pub mod convert;
24mod decoder;
25mod demuxer;
26mod error;
27pub mod extras;
28#[cfg(test)]
29mod fault_subprocess;
30mod ffi;
31mod footprint;
32mod frame;
33mod image;
34pub mod limits;
35mod pixdesc;
36mod reader_guard;
37#[cfg(feature = "resample")]
38mod resampler;
39mod sample_format;
40mod subtitle;
41mod video;
42mod view;
43
44pub use adapter::Ffmpeg;
45pub use audio::{AudioDecodeError, CarrierAudioStreamDecoder};
46pub use backend::Backend;
47pub use boundary::{
48  MediaKind, PacketBuildError, SendPayloadTooLarge, SendSideDataTooLarge,
49  attachment_packet_from_ffmpeg, audio_packet_from_ffmpeg, audio_packet_from_ffmpeg_in,
50  data_packet_from_ffmpeg_in, empty_audio_frame, empty_owned_audio_frame,
51  empty_owned_subtitle_frame, empty_owned_video_frame, empty_subtitle_frame, empty_video_frame,
52  ffmpeg_packet_from_audio_packet, ffmpeg_packet_from_owned_audio_packet,
53  ffmpeg_packet_from_owned_subtitle_packet, ffmpeg_packet_from_owned_video_packet,
54  ffmpeg_packet_from_subtitle_packet, ffmpeg_packet_from_video_packet, from_av_pixel_format,
55  is_hardware_pix_fmt, owned_attachment_packet_from_ffmpeg, owned_audio_packet_from_ffmpeg_in,
56  owned_data_packet_from_ffmpeg_in, owned_subtitle_packet_from_ffmpeg_in,
57  owned_video_packet_from_ffmpeg_in, subtitle_packet_from_ffmpeg, subtitle_packet_from_ffmpeg_in,
58  video_packet_from_ffmpeg, video_packet_from_ffmpeg_in,
59};
60
61pub use buffer::{FfmpegBytes, PacketBufferError, TrustedPayload};
62pub(crate) use carrier::CarrierOps;
63pub use carrier::{FfmpegCarrier, Owned, View};
64pub use view::FfmpegBuffer;
65
66/// The demuxer, on the **view** lane — the ordinary road.
67///
68/// Packets carry [`FfmpegBuffer`] views onto libavformat's own
69/// allocations: nothing is copied, and a consumer that reads a packet
70/// and drops it never pays for bytes it did not keep. This is what a
71/// direct consumer wants, which is why it is what the bare name means.
72///
73/// Reach for [`FfmpegOwnedDemuxer`] when a packet has to **travel** —
74/// across a graph, between threads that both read it, into a cache
75/// that outlives the decoder. See [the carrier lanes][lanes] for the
76/// tradeoff table.
77///
78/// [lanes]: mediadecode::adapter#the-two-carrier-lanes
79pub type FfmpegDemuxer = demuxer::CarrierDemuxer<View>;
80
81/// The demuxer on the **owned** lane: every byte copied once at the
82/// boundary into memory Rust owns.
83///
84/// The same type as [`FfmpegDemuxer`] on the other carrier, with the
85/// same constructors — `FfmpegOwnedDemuxer::open(&path)`. Packets are
86/// `Send + Sync + 'static` and owe nothing to the session that produced
87/// them, which is what a graph needs and what a view cannot give.
88pub type FfmpegOwnedDemuxer = demuxer::CarrierDemuxer<Owned>;
89
90/// The audio decoder on the **view** lane.
91pub type FfmpegAudioStreamDecoder = audio::CarrierAudioStreamDecoder<View>;
92/// The audio decoder on the **owned** lane.
93pub type FfmpegOwnedAudioStreamDecoder = audio::CarrierAudioStreamDecoder<Owned>;
94
95/// The subtitle decoder on the **view** lane.
96pub type FfmpegSubtitleStreamDecoder = subtitle::CarrierSubtitleStreamDecoder<View>;
97/// The subtitle decoder on the **owned** lane.
98pub type FfmpegOwnedSubtitleStreamDecoder = subtitle::CarrierSubtitleStreamDecoder<Owned>;
99
100/// The still-image decoder on the **view** lane.
101pub type FfmpegImageDecoder = image::CarrierImageDecoder<View>;
102/// The still-image decoder on the **owned** lane.
103pub type FfmpegOwnedImageDecoder = image::CarrierImageDecoder<Owned>;
104
105/// The video stream decoder on the **view** lane.
106pub type FfmpegVideoStreamDecoder = video::CarrierVideoStreamDecoder<View>;
107/// The video stream decoder on the **owned** lane.
108pub type FfmpegOwnedVideoStreamDecoder = video::CarrierVideoStreamDecoder<Owned>;
109pub use channel_layout::{
110  channel_layout_description_from_ffmpeg, channel_layout_from_ffmpeg, channel_order_from_ffmpeg,
111};
112pub use codec_id::CodecId;
113pub use decoder::VideoDecoder;
114pub use demuxer::{CarrierDemuxer, DemuxError, ProbeBudgetExhausted};
115pub use error::{
116  Error, FrameBudgetExceeded, FrameMedium, HwSurfaceTooLarge, HwTransferTooLarge, Result,
117};
118pub use frame::Frame;
119pub use image::{CarrierImageDecoder, Corrupt, CorruptSource, ImageDecodeError, InputTooLarge};
120pub use limits::{
121  DEFAULT_MAX_ATTACHMENT_BYTES, DEFAULT_MAX_CODEC_PARAMETER_BYTES, DEFAULT_MAX_FRAME_BYTES,
122  DEFAULT_MAX_IMAGE_INPUT_BYTES, DEFAULT_MAX_IMAGE_SIDE_DATA_BYTES, DEFAULT_MAX_PACKET_BYTES,
123  DEFAULT_MAX_PIXELS, DEFAULT_MAX_PROBE_BYTES, DEFAULT_MAX_STREAMS,
124  DEFAULT_MAX_TOTAL_ATTACHMENT_BYTES, DEFAULT_MAX_TOTAL_CODEC_PARAMETER_BYTES, DecoderLimits,
125  DemuxLimits, FrameLimits, PacketLimits,
126};
127#[cfg(feature = "resample")]
128#[cfg_attr(docsrs, doc(cfg(feature = "resample")))]
129pub use resampler::{
130  CarrierResampler, OutputTooLarge, ResampleError, ResampleSpec, SpecEnd,
131  UnsupportedChannelCount as UnsupportedSpecChannelCount,
132};
133/// The resampler, on the **view** lane — planes shared out of its own
134/// output frame.
135///
136/// Its output frames are the resampler's, not a decoder's: it allocates
137/// one per conversion and never writes into a buffer it has handed out,
138/// so the pool-hostage warning that applies to decoder frames does not
139/// apply here. What does apply is `!Sync` and the amputation contract —
140/// use [`FfmpegOwnedResampler`] for a frame that has to travel.
141#[cfg(feature = "resample")]
142#[cfg_attr(docsrs, doc(cfg(feature = "resample")))]
143pub type FfmpegResampler = resampler::CarrierResampler<View>;
144
145/// The resampler, on the **owned** lane — every produced plane copied
146/// out of the output frame.
147#[cfg(feature = "resample")]
148#[cfg_attr(docsrs, doc(cfg(feature = "resample")))]
149pub type FfmpegOwnedResampler = resampler::CarrierResampler<Owned>;
150
151pub use sample_format::SampleFormat;
152pub use subtitle::{CarrierSubtitleStreamDecoder, SubtitleDecodeError};
153pub use video::{CarrierVideoStreamDecoder, VideoDecodeError};
154
155// Every bare alias below binds [`FfmpegBuffer`] in the `D` seat — the
156// view lane, the ordinary road: a decoder's output read where it lands
157// and dropped. The `Owned*` family binds [`FfmpegBytes`] and is what a
158// payload takes when it has to **travel** — outlive the decoder, cross
159// into a graph, be shared across threads.
160//
161// Each spells its carrier out rather than hiding it behind a neutral
162// name. That is deliberate, and it is the one lesson 0.8's version of
163// this block failed to teach: 0.8 also called this type `FfmpegBuffer`,
164// but the D seat was *only* ever that type, so a consumer reading
165// `VideoFrame` could not tell that holding one held libavcodec's memory
166// open. It did. Naming both carriers in both families is what makes the
167// question answerable at the use site — and [`FfmpegBytes`] answers it
168// by being nothing of ours: owned, `Send + Sync`, no FFmpeg lifetime
169// attached, the core's D-seat amputation contract satisfied by a type
170// out of `alloc`.
171
172/// Compressed video packet pre-parameterized with this crate's extras
173/// and view carrier — the type [`FfmpegVideoStreamDecoder`] consumes
174/// via [`mediadecode::decoder::VideoStreamDecoder::send_packet`].
175pub type VideoPacket = mediadecode::packet::VideoPacket<extras::VideoPacketExtra, FfmpegBuffer>;
176
177/// Compressed audio packet pre-parameterized with this crate's extras
178/// and view carrier.
179pub type AudioPacket = mediadecode::packet::AudioPacket<extras::AudioPacketExtra, FfmpegBuffer>;
180
181/// Compressed subtitle packet pre-parameterized with this crate's
182/// extras and view carrier.
183pub type SubtitlePacket =
184  mediadecode::packet::SubtitlePacket<extras::SubtitlePacketExtra, FfmpegBuffer>;
185
186/// Decoded video frame pre-parameterized with this crate's pixel
187/// format / extras / view carrier.
188///
189/// Its planes are windows into the decoder's own frame buffer wherever
190/// the geometry proves they may be — see the frame row of the lane
191/// table in [`mediadecode::adapter`]. **A frame held is a pool slot
192/// held**: on a hardware or fixed-pool decoder, retaining these past
193/// the next `receive_frame` starves the decoder. Use [`OwnedVideoFrame`]
194/// when a frame has to outlive the decode loop.
195pub type VideoFrame =
196  mediadecode::frame::VideoFrame<mediadecode::PixelFormat, extras::VideoFrameExtra, FfmpegBuffer>;
197
198/// Decoded audio frame pre-parameterized with this crate's sample
199/// format / channel layout / extras / view carrier.
200///
201/// Each plane is a window over exactly the samples the decoder wrote —
202/// never the allocator's alignment padding past them.
203pub type AudioFrame = mediadecode::frame::AudioFrame<
204  SampleFormat,
205  mediaframe::audio::ChannelLayoutDescription,
206  extras::AudioFrameExtra,
207  FfmpegBuffer,
208>;
209
210/// Decoded subtitle frame pre-parameterized with this crate's
211/// extras / view carrier.
212pub type SubtitleFrame =
213  mediadecode::frame::SubtitleFrame<extras::SubtitleFrameExtra, FfmpegBuffer>;
214
215/// Decoded still image pre-parameterized with this crate's pixel
216/// format / extras / view carrier — what [`FfmpegImageDecoder`]
217/// produces.
218pub type ImageFrame =
219  mediadecode::frame::ImageFrame<mediadecode::PixelFormat, extras::ImageFrameExtra, FfmpegBuffer>;
220
221/// Timed opaque-data packet pre-parameterized with this crate's extras
222/// and view carrier.
223pub type DataPacket = mediadecode::demuxer::DataPacket<extras::DataPacketExtra, FfmpegBuffer>;
224
225/// Attachment payload pre-parameterized with this crate's extras and
226/// view carrier — a font, or the cover art [`FfmpegImageDecoder`]
227/// decodes.
228pub type AttachmentPacket =
229  mediadecode::demuxer::AttachmentPacket<extras::AttachmentPacketExtra, FfmpegBuffer>;
230
231/// The five-arm demux envelope [`FfmpegDemuxer`] delivers.
232pub type DemuxedPacket = mediadecode::demuxer::DemuxedPacket<Ffmpeg, FfmpegBuffer>;
233
234// --- The owned lane's alias family -----------------------------------
235//
236// The same shapes on the copying carrier, named explicitly because the
237// bare names mean the view lane — the ordinary road for a direct
238// consumer. Reach for these when a packet has to travel.
239//
240// Note what is **not** doubled: the `*Extra` types and `SideDataEntry`
241// stay monomorphic on both lanes. Side data has no `AVBufferRef` to
242// share — `AVPacketSideData` and `AVFrameSideData` payloads are plain
243// allocations — so both lanes copy it, and a second family of extras
244// would have been two names for one representation. The carrier
245// parameter reaches the **payload**, not the annotations.
246
247/// [`VideoPacket`] on the owned lane.
248pub type OwnedVideoPacket = mediadecode::packet::VideoPacket<extras::VideoPacketExtra, FfmpegBytes>;
249
250/// [`AudioPacket`] on the owned lane.
251pub type OwnedAudioPacket = mediadecode::packet::AudioPacket<extras::AudioPacketExtra, FfmpegBytes>;
252
253/// [`SubtitlePacket`] on the owned lane.
254pub type OwnedSubtitlePacket =
255  mediadecode::packet::SubtitlePacket<extras::SubtitlePacketExtra, FfmpegBytes>;
256
257/// [`DataPacket`] on the owned lane.
258pub type OwnedDataPacket = mediadecode::demuxer::DataPacket<extras::DataPacketExtra, FfmpegBytes>;
259
260/// [`AttachmentPacket`] on the owned lane.
261pub type OwnedAttachmentPacket =
262  mediadecode::demuxer::AttachmentPacket<extras::AttachmentPacketExtra, FfmpegBytes>;
263
264/// [`DemuxedPacket`] on the owned lane.
265pub type OwnedDemuxedPacket = mediadecode::demuxer::DemuxedPacket<Ffmpeg, FfmpegBytes>;
266
267/// [`VideoFrame`] on the owned lane — planes copied out of the
268/// decoder's buffer, so the frame outlives it and the pool slot goes
269/// straight back.
270pub type OwnedVideoFrame =
271  mediadecode::frame::VideoFrame<mediadecode::PixelFormat, extras::VideoFrameExtra, FfmpegBytes>;
272
273/// [`AudioFrame`] on the owned lane.
274pub type OwnedAudioFrame = mediadecode::frame::AudioFrame<
275  SampleFormat,
276  mediaframe::audio::ChannelLayoutDescription,
277  extras::AudioFrameExtra,
278  FfmpegBytes,
279>;
280
281/// [`SubtitleFrame`] on the owned lane.
282pub type OwnedSubtitleFrame =
283  mediadecode::frame::SubtitleFrame<extras::SubtitleFrameExtra, FfmpegBytes>;
284
285/// [`ImageFrame`] on the owned lane — what [`FfmpegOwnedImageDecoder`]
286/// produces.
287pub type OwnedImageFrame =
288  mediadecode::frame::ImageFrame<mediadecode::PixelFormat, extras::ImageFrameExtra, FfmpegBytes>;
289
290/// One row of the track table [`FfmpegDemuxer::tracks`] returns.
291///
292/// [`FfmpegDemuxer::tracks`]: mediadecode::demuxer::Demuxer::tracks
293pub type TrackInfo = mediadecode::demuxer::TrackInfo<Ffmpeg>;
294
295/// A track's per-kind codec parameters, as [`TrackInfo`] carries them.
296pub type TrackParams = mediadecode::demuxer::TrackParams<Ffmpeg>;