|
arduino-audio-tools
|
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>


Public Member Functions | |
| DemuxerMPG (int bufferSize=1024) | |
| virtual void | addNotifyAudioChange (AudioInfoSupport &bi) |
| Adds target to be notified about audio changes. | |
| AudioInfo | audioInfo () override |
| provides the actual input AudioInfo | |
| virtual AudioInfo | audioInfoOut () |
| bool | begin () override |
| virtual bool | begin (AudioInfo info) override |
| virtual void | clearNotifyAudioChange () |
| Deletes all change notify subscriptions. | |
| void | end () override |
| AudioInfoFormat | getAudioInfo () override |
| Print * | getOutput () |
| VideoInfo | getVideoInfo () override |
| bool | isNotifyActive () |
| Checks if the automatic AudioInfo update is active. | |
| bool | isValid (const uint8_t *data, size_t len) override |
| const char * | mime () override |
| const char * | mimeVideo () override |
| Provides the container mime. | |
| operator bool () override | |
| virtual bool | removeNotifyAudioChange (AudioInfoSupport &bi) |
| Removes a target in order not to be notified about audio changes. | |
| void | setAudioInfo (AudioInfo from) override |
| for most decoders this is not needed | |
| virtual bool | setCodecConfig (const uint8_t *data, size_t len) |
| Some decoders need e.g. a magic cookie to provide the relevant info for decoding. | |
| void | setNotifyActive (bool flag) |
| Deactivate/Reactivate automatic AudioInfo updates: (default is active) | |
| virtual void | setOutput (AudioOutput &out_stream) |
| Defines where the decoded result is written to. | |
| virtual void | setOutput (AudioStream &out_stream) |
| Defines where the decoded result is written to. | |
| void | setOutput (Print &out) override |
| void | setOutputAudio (Print &out) override |
| void | setOutputVideo (Print &out) override |
| void | setOutputVideo (VideoOutput &out) override |
| void | setSendWavHeader (bool flag) override |
| VideoInfo | videoInfo () override |
| size_t | write (const uint8_t *data, size_t len) override |
Public Attributes | |
| int | id |
| custom id to be used by application | |
Protected Member Functions | |
| void | appendToAudio (const uint8_t *data, size_t len) |
| Same as appendToVideo(), for audio_unit_buffer. | |
| void | appendToVideo (const uint8_t *data, size_t len) |
| bool | continuePayload () |
| void | deliver (size_t len) |
| void | deliverVideo (const uint8_t *data, size_t len) |
| void | flushAudioUnit () |
| void | flushVideoUnit () |
| long | indexOfContainerStartCode (size_t from=0) |
| void | notifyAudioChange (AudioInfo info) |
| bool | parse () |
| bool | parsePack () |
| bool | parsePes (uint8_t id, bool isVideo) |
| bool | parseSkip () |
| bool | parseSystemHeader () |
| void | probeAudioHeader (const uint8_t *data, size_t len) |
| void | probeVideoHeader (const uint8_t *data, size_t len) |
| void | writeBlocking (Print *out, uint8_t *data, size_t len) |
Static Protected Member Functions | |
| static bool | isContainerLevelStartCode (uint8_t id) |
Protected Attributes | |
| uint8_t | audio_channels = 0 |
| bool | audio_frame_open = false |
| bool | audio_header_parsed = false |
| uint8_t | audio_layer = 0 |
| 0=not yet probed/reserved, else 1/2/3 | |
| Vector< uint8_t > | audio_probe |
| uint32_t | audio_sample_rate = 0 |
| Vector< uint8_t > | audio_unit_buffer |
| size_t | audio_unit_len = 0 |
| AudioInfo | info |
| bool | is_notify_active = true |
| bool | is_parsing_active = true |
| bool | is_skip_unit = false |
| bool | is_video_unit = false |
| Vector< AudioInfoSupport * > | notify_vector |
| Print * | p_output_audio = nullptr |
| Print * | p_output_video = nullptr |
| VideoOutput * | p_output_video_video = nullptr |
| Print * | p_print = nullptr |
| MPGParseBuffer | parse_buffer |
| size_t | remaining = 0 |
| uint32_t | total_bytes = 0 |
| bool | unbounded = false |
| bool | unit_open = false |
| float | video_fps = 0 |
| bool | video_frame_open = false |
| bool | video_header_parsed = false |
| uint16_t | video_height = 0 |
| Vector< uint8_t > | video_probe |
| Vector< uint8_t > | video_unit_buffer |
| size_t | video_unit_len = 0 |
| bool | video_unit_seen_picture = false |
| uint16_t | video_width = 0 |
Static Protected Attributes | |
| static const size_t | VIDEO_PROBE_MAX = 64 |
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):
|
inline |
| bufferSize | internal parse buffer size - must be able to hold at least one full pack_header/system_header/PES header (a few dozen bytes) |
|
inlinevirtualinherited |
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.
Same as appendToVideo(), for audio_unit_buffer.
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).
|
inlineoverridevirtualinherited |
provides the actual input AudioInfo
Implements AudioInfoSupport.
Reimplemented in CodecNOP, DecoderBasic, DSFDecoder, MP3DecoderHelix, MP3DecoderMAD, OpusAudioDecoder, OpusMultiStreamAudioDecoder, VorbisDecoder, WAVDecoder, WavIMADecoder, OggContainerDecoder, and VorbisDecoder.
|
inlinevirtualinherited |
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.
|
inlineoverridevirtual |
Reimplemented from AudioDecoder.
Reimplemented from AudioWriter.
Reimplemented in DecoderBasic, and OggContainerDecoder.
|
inlinevirtualinherited |
Deletes all change notify subscriptions.
Reimplemented in RTSPClient< TcpClient, UdpSocket >.
|
inlineprotected |
|
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().
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).
|
inlineoverridevirtual |
Reimplemented from AudioDecoder.
|
inlineprotected |
Writes out audio_unit_buffer as one single, complete write() call if it currently holds anything, then resets it for the next unit.
|
inlineprotected |
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.
|
inlineoverridevirtual |
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.
|
inlineinherited |
|
inlineoverridevirtual |
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.
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.
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().
True if data starts with an MPEG Program Stream pack_start_code (00 00 01 BA) - see Demuxer::isValid().
Reimplemented from Demuxer.
|
inlineoverridevirtual |
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.
|
inlineoverridevirtual |
Provides the container mime.
Implements Demuxer.
|
inlineprotectedinherited |
|
inlineoverridevirtual |
Implements AudioWriter.
|
inlineprotected |
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()).
|
inlineprotected |
|
inlineprotected |
program_stream_map / private_stream_1 / padding_stream / private_stream_2: same PES_packet_length-prefixed framing, payload discarded.
|
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.
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.
|
inlinevirtualinherited |
Removes a target in order not to be notified about audio changes.
Reimplemented in RTSPClient< TcpClient, UdpSocket >.
|
inlineoverridevirtualinherited |
for most decoders this is not needed
Implements AudioWriter.
Reimplemented in DecoderALAC, CodecChain, DSFDecoder, DecoderL8, OpusAudioDecoder, OpusMultiStreamAudioDecoder, CodecNOP, G729Decoder, and G7xxDecoder.
Some decoders need e.g. a magic cookie to provide the relevant info for decoding.
Reimplemented in DecoderALAC, DecoderATRAC, and MultiDecoder.
|
inlineinherited |
Deactivate/Reactivate automatic AudioInfo updates: (default is active)
|
inlinevirtualinherited |
Defines where the decoded result is written to.
Reimplemented in ContainerATRAC, ADTSDecoder, CodecChain, MTSDecoder, MTSDecoderTSDemux, and MetaDataFilterDecoder.
|
inlinevirtualinherited |
Defines where the decoded result is written to.
Reimplemented in ContainerATRAC, ADTSDecoder, CodecChain, MTSDecoder, MTSDecoderTSDemux, and MetaDataFilterDecoder.
|
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.
|
inlineoverridevirtual |
Defines the audio output stream - e.g. an EncodedAudioStream wrapping an MP3/MP2 AudioDecoder, or any other Print if you want the raw payload as-is.
Implements Demuxer.
|
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.
|
inlineoverridevirtual |
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.
|
inlineoverridevirtual |
|
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.
Implements AudioWriter.
|
protected |
|
protected |
|
protected |
|
protected |
0=not yet probed/reserved, else 1/2/3
|
protected |
|
protected |
|
inherited |
custom id to be used by application
|
protectedinherited |
|
protectedinherited |
|
protected |
|
protected |
|
protected |
|
protectedinherited |
|
protected |
|
protected |
|
protected |
|
protectedinherited |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
staticprotected |
|
protected |
|
protected |
|
protected |