Skip to main content

CarrierDemuxer

Struct CarrierDemuxer 

Source
pub struct CarrierDemuxer<C: FfmpegCarrier> { /* private fields */ }
Expand description

mediadecode::demuxer::Demuxer impl wrapping ffmpeg::format::context::Input.

Construction is deliberately not on the trait — see Self::open and Self::open_reader.

Implementations§

Source§

impl CarrierDemuxer<View>

Source

pub fn open<P: AsRef<Path> + ?Sized>(path: &P) -> Result<Self, DemuxError>

Opens a container from a filesystem path.

Runs avformat_open_input followed by avformat_find_stream_info, then builds the track table and captures every attachment payload.

Call ffmpeg_next::init once before the first open if you want FFmpeg’s logging and network protocols configured; probing a local container does not require it.

Source

pub fn open_with<P: AsRef<Path> + ?Sized>( path: &P, limits: DemuxLimits, ) -> Result<Self, DemuxError>

Self::open, with the session’s resource budgets named.

The budgets are taken at open rather than through a with_* builder because the attachment half of them is spent here: every attachment payload is captured during this call.

Source

pub fn open_reader<R: Read + Seek + Send + 'static>( reader: R, url: Option<&str>, ) -> Result<Self, DemuxError>

Opens a container from any Read + Seek source.

Source

pub fn open_reader_with<R: Read + Seek + Send + 'static>( reader: R, url: Option<&str>, limits: DemuxLimits, ) -> Result<Self, DemuxError>

Self::open_reader, with the session’s budgets named.

Source

pub const fn input(&self) -> &Input

The wrapped AVFormatContext.

Source

pub const fn limits(&self) -> DemuxLimits

The budgets this session was opened with.

Source

pub const fn format(&self) -> Option<&ContainerFormat>

What the container IS, as libavformat identified it from the bytes — the demuxer it chose, with the short names that demuxer handles and its description.

Decided during the open and fixed for the life of the session, so this answers the same thing at any point and costs nothing to ask.

None only where libavformat left iformat null or its name is not readable text; neither happens on a session that opened successfully.

Nothing here looked at a path. A file’s extension is a claim about its bytes, and this is a reading of them — which is what makes the answer usable on a content-addressed row, where the same bytes under two names are one content. See ContainerFormat for what the demuxer’s name does and does not narrow to.

Source§

impl CarrierDemuxer<Owned>

Source

pub fn open<P: AsRef<Path> + ?Sized>(path: &P) -> Result<Self, DemuxError>

Opens a container from a filesystem path.

Runs avformat_open_input followed by avformat_find_stream_info, then builds the track table and captures every attachment payload.

Call ffmpeg_next::init once before the first open if you want FFmpeg’s logging and network protocols configured; probing a local container does not require it.

Source

pub fn open_with<P: AsRef<Path> + ?Sized>( path: &P, limits: DemuxLimits, ) -> Result<Self, DemuxError>

Self::open, with the session’s resource budgets named.

The budgets are taken at open rather than through a with_* builder because the attachment half of them is spent here: every attachment payload is captured during this call.

Source

pub fn open_reader<R: Read + Seek + Send + 'static>( reader: R, url: Option<&str>, ) -> Result<Self, DemuxError>

Opens a container from any Read + Seek source.

Source

pub fn open_reader_with<R: Read + Seek + Send + 'static>( reader: R, url: Option<&str>, limits: DemuxLimits, ) -> Result<Self, DemuxError>

Self::open_reader, with the session’s budgets named.

Source

pub const fn input(&self) -> &Input

The wrapped AVFormatContext.

Source

pub const fn limits(&self) -> DemuxLimits

The budgets this session was opened with.

Source

pub const fn format(&self) -> Option<&ContainerFormat>

What the container IS, as libavformat identified it from the bytes — the demuxer it chose, with the short names that demuxer handles and its description.

Decided during the open and fixed for the life of the session, so this answers the same thing at any point and costs nothing to ask.

None only where libavformat left iformat null or its name is not readable text; neither happens on a session that opened successfully.

Nothing here looked at a path. A file’s extension is a claim about its bytes, and this is a reading of them — which is what makes the answer usable on a content-addressed row, where the same bytes under two names are one content. See ContainerFormat for what the demuxer’s name does and does not narrow to.

Trait Implementations§

Source§

impl Demuxer for CarrierDemuxer<View>

Source§

fn tracks(&self) -> &[TrackArc<TrackInfo<Ffmpeg>>]

The track table, held for the life of the session.

A row’s duration is libavformat’s figure for the stream as it stood after avformat_open_input and before avformat_find_stream_info. It is no claim about the file — a format’s reader may compute it itself — and a value that appears only after probing is libavformat’s fill, which hands a stream that supplied no timing the container’s length, so it is not carried; neither is one for a stream libavformat creates during probing. The last packet end this backend observed on the track’s timeline is measured_end; a length needs the track’s start and its presentation edits applied, which is the composer’s job.

Reading the table takes nothing away — clone the handles worth keeping. Arc is the carrier because CodecTicket mirrors an AVCodecParameters into owned Rust, which is what makes a row Send + Sync and a table shareable across tasks.

Source§

fn chapters(&self) -> &[Chapter<Ffmpeg>]

The container’s chapter table, in the order AVFormatContext.chapters holds it, mirrored at open and held for the life of the session.

Empty where the file declares no chapters — which is the provided answer too, so the override changes nothing for a container that has none.

Nothing is repaired. A chapter whose end precedes its start, and one whose end libavformat left at its no-timestamp sentinel because the file declared none, are mirrored exactly as written; see Chapter for why this layer reports rather than clamps.

Source§

fn duration(&self) -> Option<ContainerDuration>

The container-level duration with libavformat’s account of it, from AVFormatContext.duration and AVFormatContext.duration_estimation_method, read once at open and held for the life of the session.

The container’s figure, never a track’s: Matroska reports a length here and none on any track, and the tracks’ rows keep saying so. None where libavformat holds no positive figure.

The figure is counted in AV_TIME_BASE ticks — microseconds — and carried in that timebase, not rescaled. The account is libavformat’s own, word for word: FROM_PTS is FromPts, FROM_STREAM is FromStream, FROM_BITRATE is FromBitrate, and a method this build does not name is Unknown.

Source§

fn measured_end(&self, track: TrackIndex) -> Option<MeasuredEnd>

Where track’s packets ended, as this session’s walk measured it: the greatest pts + duration over the timed packets read on it, in the track’s own timebase.

The figure is an endpoint on the track’s own timeline, not a length. The container’s duration is a length, and the two are different quantities: a track that starts at ten seconds and runs for two ends at twelve. Turning an end into a length means subtracting the track’s start — the backend’s TrackExtra::start_time is AVStream.start_time as it stands after probing, which libavformat may itself have filled in — and honouring presentation edits, which is the composer’s job and not this crate’s. The figure’s own promise is only that it is exact when MeasuredEnd::exact says so, and covers what MeasuredEnd::walk_complete says.

A packet that carries no duration contributes its pts alone; libavformat derives a duration from the stream’s frame rate or frame size for most packets whose demuxer wrote none, so that is the rare case. A packet with no pts moves no end. A timed packet with no payload still counts: it is timed before the payload conversion runs, because it is a real endpoint and a later one is the end. Nothing is read for this and nothing is sought: the figure rides the pulls the caller makes.

Exactness. MeasuredEnd::exact turns false, for good, the first time a timed packet on the track is read with a duration that is not positive (libavformat writes zero for one it does not know) or a packet on it is read with no usable pts. The mark is made when the packet is read, before the payload conversion, so it does not depend on whether the packet is then delivered, refused or parked, nor on whether it carries a payload. A packet with no usable duration advances the end to its pts only; either way the figure is a lower bound. A duration libavformat derived from the stream’s frame rate or frame size counts as a duration, and is only as exact as that derivation.

Completeness. MeasuredEnd::walk_complete holds once a walk that skipped nothing has answered Ok(None), and a complete walk is frozen: a later read or seek neither moves its figures nor takes the flag back. The walk stops being complete for good, before it completes, at a seek and at every packet av_read_frame produced that this session did not observe: refused and dropped, skipped as corrupt (AVERROR_INVALIDDATA), or on a stream the table never described — which is what a container that adds streams after open (MPEG-TS, RTP) produces, so a session that read a packet on a grown stream never answers complete. Accounting for such streams as they appear is not done here. A cover picture’s duplicate packet, whose one delivery happened at open, and an untimed empty packet lose nothing and do not break the walk (the untimed one still costs the track its exactness). After a break the figure keeps rising as a “so far” maximum and stays a lower bound.

What it does not cover. libavformat probes while the container opens, before this session’s first read. It buffers the packets it reads and replays them, but a read error it swallows during probing is not exposed anywhere, so data skipped there is invisible and a complete walk does not vouch for it.

An attachment track answers None, and so does a track whose end does not fit in an i64, which breaks the walk as well.

Source§

fn next_packet( &mut self, ) -> Result<Option<DemuxedPacket<Ffmpeg, Self::Buffer>>, DemuxError>

Pulls the next packet.

A refusal that another attempt could survive costs no packet. av_read_frame advances the container, so a conversion that then fails on an allocation would otherwise drop bytes nothing can ask for again. Such a packet is parked instead, and this method re-attempts it before reading another — so a caller who pulls again loses nothing. A refusal about the packet itself is not parked: retrying a malformed packet forever would be worse than passing it by.

Source§

type Adapter = Ffmpeg

Backend-specific vocabulary.
Source§

type Buffer = <View as FfmpegCarrier>::Buffer

Buffer type held by the packets this session produces.
Source§

type TrackHandle = Arc<TrackInfo<Ffmpeg>>

A shareable handle on one row of the track table. Read more
Source§

type Error = DemuxError

Demuxer-specific error type.
Source§

fn seek(&mut self, target: Timestamp) -> Result<(), DemuxError>

Seeks to target, landing on the nearest keyframe at or before it. Read more
Source§

impl Demuxer for CarrierDemuxer<Owned>

Source§

fn tracks(&self) -> &[TrackArc<TrackInfo<Ffmpeg>>]

The track table, held for the life of the session.

A row’s duration is libavformat’s figure for the stream as it stood after avformat_open_input and before avformat_find_stream_info. It is no claim about the file — a format’s reader may compute it itself — and a value that appears only after probing is libavformat’s fill, which hands a stream that supplied no timing the container’s length, so it is not carried; neither is one for a stream libavformat creates during probing. The last packet end this backend observed on the track’s timeline is measured_end; a length needs the track’s start and its presentation edits applied, which is the composer’s job.

Reading the table takes nothing away — clone the handles worth keeping. Arc is the carrier because CodecTicket mirrors an AVCodecParameters into owned Rust, which is what makes a row Send + Sync and a table shareable across tasks.

Source§

fn chapters(&self) -> &[Chapter<Ffmpeg>]

The container’s chapter table, in the order AVFormatContext.chapters holds it, mirrored at open and held for the life of the session.

Empty where the file declares no chapters — which is the provided answer too, so the override changes nothing for a container that has none.

Nothing is repaired. A chapter whose end precedes its start, and one whose end libavformat left at its no-timestamp sentinel because the file declared none, are mirrored exactly as written; see Chapter for why this layer reports rather than clamps.

Source§

fn duration(&self) -> Option<ContainerDuration>

The container-level duration with libavformat’s account of it, from AVFormatContext.duration and AVFormatContext.duration_estimation_method, read once at open and held for the life of the session.

The container’s figure, never a track’s: Matroska reports a length here and none on any track, and the tracks’ rows keep saying so. None where libavformat holds no positive figure.

The figure is counted in AV_TIME_BASE ticks — microseconds — and carried in that timebase, not rescaled. The account is libavformat’s own, word for word: FROM_PTS is FromPts, FROM_STREAM is FromStream, FROM_BITRATE is FromBitrate, and a method this build does not name is Unknown.

Source§

fn measured_end(&self, track: TrackIndex) -> Option<MeasuredEnd>

Where track’s packets ended, as this session’s walk measured it: the greatest pts + duration over the timed packets read on it, in the track’s own timebase.

The figure is an endpoint on the track’s own timeline, not a length. The container’s duration is a length, and the two are different quantities: a track that starts at ten seconds and runs for two ends at twelve. Turning an end into a length means subtracting the track’s start — the backend’s TrackExtra::start_time is AVStream.start_time as it stands after probing, which libavformat may itself have filled in — and honouring presentation edits, which is the composer’s job and not this crate’s. The figure’s own promise is only that it is exact when MeasuredEnd::exact says so, and covers what MeasuredEnd::walk_complete says.

A packet that carries no duration contributes its pts alone; libavformat derives a duration from the stream’s frame rate or frame size for most packets whose demuxer wrote none, so that is the rare case. A packet with no pts moves no end. A timed packet with no payload still counts: it is timed before the payload conversion runs, because it is a real endpoint and a later one is the end. Nothing is read for this and nothing is sought: the figure rides the pulls the caller makes.

Exactness. MeasuredEnd::exact turns false, for good, the first time a timed packet on the track is read with a duration that is not positive (libavformat writes zero for one it does not know) or a packet on it is read with no usable pts. The mark is made when the packet is read, before the payload conversion, so it does not depend on whether the packet is then delivered, refused or parked, nor on whether it carries a payload. A packet with no usable duration advances the end to its pts only; either way the figure is a lower bound. A duration libavformat derived from the stream’s frame rate or frame size counts as a duration, and is only as exact as that derivation.

Completeness. MeasuredEnd::walk_complete holds once a walk that skipped nothing has answered Ok(None), and a complete walk is frozen: a later read or seek neither moves its figures nor takes the flag back. The walk stops being complete for good, before it completes, at a seek and at every packet av_read_frame produced that this session did not observe: refused and dropped, skipped as corrupt (AVERROR_INVALIDDATA), or on a stream the table never described — which is what a container that adds streams after open (MPEG-TS, RTP) produces, so a session that read a packet on a grown stream never answers complete. Accounting for such streams as they appear is not done here. A cover picture’s duplicate packet, whose one delivery happened at open, and an untimed empty packet lose nothing and do not break the walk (the untimed one still costs the track its exactness). After a break the figure keeps rising as a “so far” maximum and stays a lower bound.

What it does not cover. libavformat probes while the container opens, before this session’s first read. It buffers the packets it reads and replays them, but a read error it swallows during probing is not exposed anywhere, so data skipped there is invisible and a complete walk does not vouch for it.

An attachment track answers None, and so does a track whose end does not fit in an i64, which breaks the walk as well.

Source§

fn next_packet( &mut self, ) -> Result<Option<DemuxedPacket<Ffmpeg, Self::Buffer>>, DemuxError>

Pulls the next packet.

A refusal that another attempt could survive costs no packet. av_read_frame advances the container, so a conversion that then fails on an allocation would otherwise drop bytes nothing can ask for again. Such a packet is parked instead, and this method re-attempts it before reading another — so a caller who pulls again loses nothing. A refusal about the packet itself is not parked: retrying a malformed packet forever would be worse than passing it by.

Source§

type Adapter = Ffmpeg

Backend-specific vocabulary.
Source§

type Buffer = <Owned as FfmpegCarrier>::Buffer

Buffer type held by the packets this session produces.
Source§

type TrackHandle = Arc<TrackInfo<Ffmpeg>>

A shareable handle on one row of the track table. Read more
Source§

type Error = DemuxError

Demuxer-specific error type.
Source§

fn seek(&mut self, target: Timestamp) -> Result<(), DemuxError>

Seeks to target, landing on the nearest keyframe at or before it. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more