MPEG-1 System (Program) Stream Demuxer, as defined by ISO/IEC 11172-1: splits the pack_header/system_header/PES_packet framing apart and forwards the raw MPEG-1 video (ISO/IEC 11172-2) and MPEG-1 audio (ISO/IEC 11172-3, Layer I/II/III) elementary streams to setOutputVideo()/ setOutputAudio(). Both elementary streams are self-delimiting (the video ES has its own picture_start_code sequence, the audio ES its own frame sync word) so, like DemuxerAVI/DemuxerMP4, no separate decoding is done here - point the outputs at whatever decoder understands the codec (e.g. an MPEG1 video decoder, or an EncodedAudioStream wrapping an MP3/MP2 AudioDecoder).
More...
#include <ContainerMPG.h>
|
| int | id |
| | custom id to be used by application
|
| |
MPEG-1 System (Program) Stream Demuxer, as defined by ISO/IEC 11172-1: splits the pack_header/system_header/PES_packet framing apart and forwards the raw MPEG-1 video (ISO/IEC 11172-2) and MPEG-1 audio (ISO/IEC 11172-3, Layer I/II/III) elementary streams to setOutputVideo()/ setOutputAudio(). Both elementary streams are self-delimiting (the video ES has its own picture_start_code sequence, the audio ES its own frame sync word) so, like DemuxerAVI/DemuxerMP4, no separate decoding is done here - point the outputs at whatever decoder understands the codec (e.g. an MPEG1 video decoder, or an EncodedAudioStream wrapping an MP3/MP2 AudioDecoder).
Scope (v1): a single MPEG-1 video track (stream_id 0xE0) and a single MPEG-1 audio track (stream_id 0xC0) - the common case for files produced by encoders targeting this container (see MuxerMPG). Only the plain ISO/IEC 11172-1 pack_header (fixed 12 bytes, no stuffing) and PES header (PTS/DTS-or-none, no stuffing bytes, no STD_buffer field) are recognized; MPEG-2-style Program Streams (marker pattern '01' at the start of the pack header) are not supported.
The audio track is forwarded as a plain, continuous elementary-stream byte stream (PES packet boundaries are not required to line up with MP3/ MP2 frame boundaries - the decoder resyncs on its own frame sync word), so setOutputAudio() can point straight at an EncodedAudioStream wrapping any MPEG audio AudioDecoder (e.g. MP3DecoderHelix):
demuxer.
write(mpgData, len);
- Author
- Phil Schatzmann
- Copyright
- GPLv3
◆ DemuxerMPG()
- Parameters
-
| bufferSize | internal parse buffer size - must be able to hold at least one full pack_header/system_header/PES header (a few dozen bytes) |
◆ addNotifyAudioChange()
Adds target to be notified about audio changes.
Reimplemented in CodecNOP, EncodedAudioOutput, EncodedAudioStream, AACDecoderFDK, DecoderBasic, CodecChain, MP3DecoderHelix, MP3DecoderMAD, OggContainerDecoder, RTSPClient< TcpClient, UdpSocket >, Pipeline, and Pipeline::ModifyingStreamAdapter.
◆ appendToAudio()
| void appendToAudio |
( |
const uint8_t * |
data, |
|
|
size_t |
len |
|
) |
| |
|
inlineprotected |
◆ appendToVideo()
| void appendToVideo |
( |
const uint8_t * |
data, |
|
|
size_t |
len |
|
) |
| |
|
inlineprotected |
Appends to video_unit_buffer with amortized (doubling) growth - see its comment for why an exact-size resize() per call would be O(N^2).
◆ audioInfo()
|
|
inlineoverridevirtualinherited |
provides the actual input AudioInfo
Implements AudioInfoSupport.
Reimplemented in CodecNOP, DecoderBasic, DSFDecoder, MP3DecoderHelix, MP3DecoderMAD, OpusAudioDecoder, OpusMultiStreamAudioDecoder, VorbisDecoder, WAVDecoder, WavIMADecoder, OggContainerDecoder, and VorbisDecoder.
◆ audioInfoOut()
provides the actual output AudioInfo: this is usually the same as audioInfo() unless we use a transforming stream
Reimplemented in MP3EncoderShine, PureDataStream, PWMAudioOutput< PWMDriverT >, ChannelFormatConverterStreamT< T >, ChannelFormatConverterStream, NumberFormatConverterStreamT< TFrom, TTo >, NumberFormatConverterStream, FormatConverterStream, Pipeline, ResampleStream, ResampleStreamT< TInterpolator >, and SupportedRatesStream.
◆ begin() [1/2]
◆ begin() [2/2]
|
|
inlineoverridevirtualinherited |
◆ clearNotifyAudioChange()
| virtual void clearNotifyAudioChange |
( |
| ) |
|
|
inlinevirtualinherited |
◆ continuePayload()
◆ deliver()
| void deliver |
( |
size_t |
len | ) |
|
|
inlineprotected |
Appends one delivered fragment to the appropriate access-unit accumulator instead of writing it straight through - see video_unit_buffer's comment. The unit is only actually written once it's complete, from flushVideoUnit()/flushAudioUnit().
◆ deliverVideo()
| void deliverVideo |
( |
const uint8_t * |
data, |
|
|
size_t |
len |
|
) |
| |
|
inlineprotected |
Appends video bytes to video_unit_buffer, splitting off a new access unit whenever an internal picture_start_code (00 00 01 00) marks the start of a NEW picture - needed because flushVideoUnit()'s other caller (see parsePes()) only flushes when a new video PES arrives with a PTS, which some encoders don't set on every single picture's PES packet (e.g. only once per GOP) - relying on that alone can silently bundle many pictures (an entire GOP, in the worst case) into one access unit, which then reaches the decoder as one huge, multi-picture write() call instead of one call per picture (breaking every caller downstream that assumes that 1:1 correspondence, e.g. PacedVideoOutput's per-frame scheduling/counting).
The first picture_start_code seen in a fresh unit is never a split point (it stays attached to any preceding sequence_header/ GOP_header, matching what flushVideoUnit()'s own doc comment already assumes) - only the second and later ones are. video_unit_seen_picture tracks whether the current (not yet flushed) unit has seen its first one yet; reset to false by flushVideoUnit() itself once a unit is actually emptied, and re-set to true here immediately after an internal split (the retained remainder already starts with one).
◆ end()
◆ flushAudioUnit()
Writes out audio_unit_buffer as one single, complete write() call if it currently holds anything, then resets it for the next unit.
◆ flushVideoUnit()
Writes out video_unit_buffer as one single, complete write() call if it currently holds anything, then resets it for the next unit. Call once a picture is known to be complete (a new video PES with a PTS starts, an internal picture_start_code marks a new one - see deliverVideo() - or the stream/end() is closing) - never mid-picture.
◆ getAudioInfo()
Common audio info, parsed from the audio ES's own MPEG audio frame header once seen - falls back to 44100/stereo if not yet available.
Implements Demuxer.
◆ getOutput()
◆ getVideoInfo()
Common video info (width/height/fps/format), parsed from the video ES's own sequence_header (ISO/IEC 11172-2) once seen - all zero/ VideoFormat::MPEG1 until then.
Implements Demuxer.
◆ indexOfContainerStartCode()
| long indexOfContainerStartCode |
( |
size_t |
from = 0 | ) |
|
|
inlineprotected |
Like parse_buffer.indexOfStartCode(), but skips past any start code that isn't a genuine container-level boundary (see isContainerLevelStartCode()) - needed for unbounded video PES payloads (PES_packet_length==0, ISO/IEC 11172-1's convention for a video access unit whose length isn't known up front): the payload is only terminated by the next container-level unit, per spec, but it's also full of the video ES's own internal start codes (picture/slice/sequence/GOP) that plain indexOfStartCode() can't tell apart from that - mistaking one for the payload's end would drop it into the "reserved/unrecognized id" fallback in parse(), silently corrupting the video ES one byte at a time from there.
◆ isContainerLevelStartCode()
| static bool isContainerLevelStartCode |
( |
uint8_t |
id | ) |
|
|
inlinestaticprotected |
True if 'id' (the byte after a 00 00 01 start-code prefix) marks a genuine container-level unit boundary (a new pack_header/ system_header/program_end/program_stream_map/private or padding stream/audio or video PES) rather than something internal to the video ES itself (a picture_start_code, a slice, or a sequence_header/ GOP/extension/user_data code - ISO/IEC 11172-2's own 0x00-0xB8 range). See indexOfContainerStartCode().
◆ isNotifyActive()
Checks if the automatic AudioInfo update is active.
◆ isValid()
| bool isValid |
( |
const uint8_t * |
data, |
|
|
size_t |
len |
|
) |
| |
|
inlineoverridevirtual |
◆ mime()
Provides the audio mime - "audio/mpeg" covers MPEG-1 Layer I/II/III alike (there's no separately registered "audio/mp2"), but once the audio ES's own frame header has been probed (see probeAudioHeader()) a Layer II stream - the common case for this container, and what MuxerMPG itself produces - gets an explicit RFC 6381 codecs parameter naming the layer. Layer I/III/not-yet-probed still report the plain generic mime.
Implements Demuxer.
◆ mimeVideo()
| const char * mimeVideo |
( |
| ) |
|
|
inlineoverridevirtual |
Provides the container mime.
Implements Demuxer.
◆ notifyAudioChange()
◆ operator bool()
◆ parse()
Parses/consumes as much as is currently buffered; returns true if progress was made (call again - more units may already be buffered), false if it needs more data (wait for the next write()).
◆ parsePack()
◆ parsePes()
| bool parsePes |
( |
uint8_t |
id, |
|
|
bool |
isVideo |
|
) |
| |
|
inlineprotected |
◆ parseSkip()
program_stream_map / private_stream_1 / padding_stream / private_stream_2: same PES_packet_length-prefixed framing, payload discarded.
◆ parseSystemHeader()
| bool parseSystemHeader |
( |
| ) |
|
|
inlineprotected |
◆ probeAudioHeader()
| void probeAudioHeader |
( |
const uint8_t * |
data, |
|
|
size_t |
len |
|
) |
| |
|
inlineprotected |
Inspects the first 4 bytes of the audio ES for an MPEG audio frame header (ISO/IEC 11172-3) to determine sample_rate/channels.
◆ probeVideoHeader()
| void probeVideoHeader |
( |
const uint8_t * |
data, |
|
|
size_t |
len |
|
) |
| |
|
inlineprotected |
Accumulates the first bytes of the video ES looking for its sequence_header (00 00 01 B3) to determine width/height/fps - harmless to keep calling once found, since video_header_parsed then short-circuits it.
◆ removeNotifyAudioChange()
◆ setAudioInfo()
|
|
inlineoverridevirtualinherited |
◆ setCodecConfig()
| virtual bool setCodecConfig |
( |
const uint8_t * |
data, |
|
|
size_t |
len |
|
) |
| |
|
inlinevirtualinherited |
Some decoders need e.g. a magic cookie to provide the relevant info for decoding.
Reimplemented in DecoderALAC, and MultiDecoder.
◆ setNotifyActive()
| void setNotifyActive |
( |
bool |
flag | ) |
|
|
inlineinherited |
Deactivate/Reactivate automatic AudioInfo updates: (default is active)
◆ setOutput() [1/3]
◆ setOutput() [2/3]
◆ setOutput() [3/3]
| void setOutput |
( |
Print & |
out | ) |
|
|
inlineoverridevirtual |
Satisfies the AudioWriter/AudioDecoder interface - needed so EncodedAudioOutput/EncodedAudioStream's polymorphic AudioDecoder* wiring reaches the audio output correctly; delegates to setOutputAudio().
Reimplemented from AudioDecoder.
◆ setOutputAudio()
| void setOutputAudio |
( |
Print & |
out | ) |
|
|
inlineoverridevirtual |
◆ setOutputVideo() [1/2]
| void setOutputVideo |
( |
Print & |
out | ) |
|
|
inlineoverridevirtual |
Defines the video output - e.g. a VideoOutput implementation, or any other Print if you want the raw MPEG-1 video ES as-is.
Implements Demuxer.
◆ setOutputVideo() [2/2]
Defines the video output - the VideoOutput-specific counterpart of setOutputVideo(Print&), for a target like PacedVideoOutput/ OutputTinyGPU/OutputOpenCV that implements VideoOutput but not Print (the two are unrelated types - see VideoFrameMeter's own comment). Part of the base interface (unlike other concrete-class-specific extras) so code holding only a Demuxer& (e.g. VideoPlayer) can wire it to an arbitrary VideoOutput& without knowing the concrete container format - every current demuxer already implemented this identically before it was pulled up into the interface.
Implements Demuxer.
◆ setSendWavHeader()
| void setSendWavHeader |
( |
bool |
flag | ) |
|
|
inlineoverridevirtual |
Not applicable: MPEG-1 audio (Layer I/II/III) is compressed and self-framed (its own sync word), unlike PCM - it never needs a synthetic WAV header. Provided only to satisfy the Demuxer interface.
Implements Demuxer.
◆ videoInfo()
|
|
inlineoverridevirtualinherited |
Fulfills VideoInfoSource::videoInfo(), so any Demuxer can be passed directly to e.g. OutputOpenCV::setVideoInfoSource() - note the reported 'format' is the container's codec (e.g. H264), not necessarily what ends up written to a raw-picture VideoOutput/Print (that depends on whatever decoder sits between the demuxer and the output); consumers that care about the decoded format should still set it explicitly and rely on this only for width/height.
Implements VideoInfoSource.
◆ write()
| size_t write |
( |
const uint8_t * |
data, |
|
|
size_t |
len |
|
) |
| |
|
inlineoverridevirtual |
◆ writeBlocking()
| void writeBlocking |
( |
Print * |
out, |
|
|
uint8_t * |
data, |
|
|
size_t |
len |
|
) |
| |
|
inlineprotectedinherited |
◆ audio_channels
| uint8_t audio_channels = 0 |
|
protected |
◆ audio_frame_open
| bool audio_frame_open = false |
|
protected |
◆ audio_header_parsed
| bool audio_header_parsed = false |
|
protected |
◆ audio_layer
0=not yet probed/reserved, else 1/2/3
◆ audio_probe
◆ audio_sample_rate
| uint32_t audio_sample_rate = 0 |
|
protected |
◆ audio_unit_buffer
| Vector<uint8_t> audio_unit_buffer |
|
protected |
◆ audio_unit_len
| size_t audio_unit_len = 0 |
|
protected |
◆ id
custom id to be used by application
◆ info
◆ is_notify_active
| bool is_notify_active = true |
|
protectedinherited |
◆ is_parsing_active
| bool is_parsing_active = true |
|
protected |
◆ is_skip_unit
| bool is_skip_unit = false |
|
protected |
◆ is_video_unit
| bool is_video_unit = false |
|
protected |
◆ notify_vector
◆ p_output_audio
| Print* p_output_audio = nullptr |
|
protected |
◆ p_output_video
| Print* p_output_video = nullptr |
|
protected |
◆ p_output_video_video
◆ p_print
◆ parse_buffer
◆ remaining
◆ total_bytes
◆ unbounded
◆ unit_open
◆ video_fps
◆ video_frame_open
| bool video_frame_open = false |
|
protected |
◆ video_header_parsed
| bool video_header_parsed = false |
|
protected |
◆ video_height
| uint16_t video_height = 0 |
|
protected |
◆ video_probe
◆ VIDEO_PROBE_MAX
| const size_t VIDEO_PROBE_MAX = 64 |
|
staticprotected |
◆ video_unit_buffer
| Vector<uint8_t> video_unit_buffer |
|
protected |
◆ video_unit_len
| size_t video_unit_len = 0 |
|
protected |
◆ video_unit_seen_picture
| bool video_unit_seen_picture = false |
|
protected |
◆ video_width
The documentation for this class was generated from the following file: