arduino-audio-tools
Loading...
Searching...
No Matches
Public Member Functions | Protected Member Functions | Static Protected Member Functions | Protected Attributes | List of all members

MPEG-1 (part 2) video decoder wrapper around TinyMPGDecoder. More...

#include <CodecMPG.h>

Inheritance diagram for MPGDecoder:
VideoDecoder VideoInfoSource VideoOutput

Public Member Functions

 MPGDecoder ()
 
 MPGDecoder (Print &out)
 
 MPGDecoder (VideoOutput &out)
 
bool begin () override
 Initializes the decoder (allocates its picture buffers, etc).
 
bool byteSwap () const
 
VideoFormat codecFormat () override
 
tinympg::TinyMPGDecoder< tinympg::PSRAMAllocatorESP32< uint8_t > > & driver ()
 
void end () override
 
void flush () override
 
virtual uint32_t getWriteTimeMs () const
 Optional: returns the time (ms) spent in the last write() call.
 
bool hadOutput () const override
 
bool hasError ()
 
bool ignorePFrames () const
 
bool isKeyFrame (const uint8_t *data, size_t len) override
 
bool isValid (const uint8_t *data, size_t len) override
 
void setByteSwap (bool active)
 
void setIgnorePFrames (bool active)
 
void setOutput (Print &out) override
 Defines the target each decoded picture is written to.
 
void setOutput (VideoOutput &out) override
 
virtual void setSkipRender (bool skip)
 
void setVideoFormat (VideoFormat format) override
 
virtual void setVideoInfoSource (VideoInfoSource &source)
 
virtual uint64_t totalDecodeMs () const
 
VideoInfo videoInfo () override
 
size_t write (const uint8_t *data, size_t len) override
 

Protected Member Functions

void writeFrame (tinympg::TinyMPGDecoder< tinympg::PSRAMAllocatorESP32< uint8_t > > &decoder)
 
size_t writeToOutput (uint8_t *data, size_t len)
 

Static Protected Member Functions

static void onFrame (tinympg::TinyMPGDecoder< tinympg::PSRAMAllocatorESP32< uint8_t > > &decoder, void *userData)
 

Protected Attributes

bool byte_swap = true
 
tinympg::TinyMPGDecoder< tinympg::PSRAMAllocatorESP32< uint8_t > > decoder_
 
Vector< uint8_t > frame_buffer
 
bool frame_emitted = false
 
Printp_out = nullptr
 
VideoOutputp_out_video = nullptr
 
VideoFormat pixel_format = VideoFormat::RGB565
 

Detailed Description

MPEG-1 (part 2) video decoder wrapper around TinyMPGDecoder.

The class mirrors the usage style of CodecH264.h: feed MPEG-1 bitstream data via write(), and receive decoded frames on the configured output.

Note: Requires TinyMPG (TinyMPGDecoder.h) to be installed and reachable by the compiler include path: https://github.com/pschatzmann/TinyMPG

Constructor & Destructor Documentation

◆ MPGDecoder() [1/3]

MPGDecoder ( )
inline

◆ MPGDecoder() [2/3]

MPGDecoder ( Print out)
inline

◆ MPGDecoder() [3/3]

MPGDecoder ( VideoOutput out)
inline

Member Function Documentation

◆ begin()

bool begin ( )
inlineoverridevirtual

Initializes the decoder (allocates its picture buffers, etc).

Implements VideoDecoder.

◆ byteSwap()

bool byteSwap ( ) const
inline

◆ codecFormat()

VideoFormat codecFormat ( )
inlineoverridevirtual

The compressed bitstream codec this decoder consumes (e.g. VideoFormat::H264, VideoFormat::MJPEG) - NOT the same axis as setVideoFormat()/videoInfo().format below, which is the decoded pixel format this decoder produces. Used by MultiVideoDecoder::addDecoder() to register a decoder under its own codec instead of the caller having to pass it separately (and possibly get it wrong).

Implements VideoDecoder.

◆ driver()

tinympg::TinyMPGDecoder< tinympg::PSRAMAllocatorESP32< uint8_t > > & driver ( )
inline

◆ end()

void end ( )
inlineoverridevirtual

Releases any picture still held back for display-order reordering (see TinyMPGDecoder's docs/decoding.md, "Frame delivery order and latency") before resetting the decoder - without this, the last anchor picture (or two, if the stream has B-pictures) of a session that ends here would never reach the frame callback at all, since write() below deliberately never triggers that release on its own (see its own comment).

Implements VideoDecoder.

◆ flush()

void flush ( )
inlineoverridevirtual

Deliberately a no-op, not wired to TinyMPGDecoder in any way: this is called once per picture boundary by DemuxerMPG (ContainerMPG.h), not just at genuine end-of-stream, so treating it as "no more data is coming" (the way end() above does) would release every anchor picture the moment its own data finishes decoding instead of holding it back for correct B-picture reordering - that release only happens once end() runs, or once a genuine following picture's data arrives via write().

Reimplemented from VideoOutput.

◆ getWriteTimeMs()

virtual uint32_t getWriteTimeMs ( ) const
inlinevirtualinherited

Optional: returns the time (ms) spent in the last write() call.

Reimplemented in OutputTFT_eSPI, OutputTinyGPU, and OutputOpenCV.

◆ hadOutput()

bool hadOutput ( ) const
inlineoverridevirtual

See VideoOutput::hadOutput() - TinyMPGDecoder's B-picture display- order reordering means a given write() can decode a new picture without emitting it yet (held back), or emit an earlier held picture instead - either way "write()+flush() was called" doesn't reliably mean "a picture was just pushed to the output" the way it does for a synchronous decoder. Reflects whether writeFrame() (only ever invoked from TinyMPGDecoder's frame callback, i.e. only when a picture was actually ready) ran during the most recent write() call.

Reimplemented from VideoOutput.

◆ hasError()

bool hasError ( )
inline

◆ ignorePFrames()

bool ignorePFrames ( ) const
inline

◆ isKeyFrame()

bool isKeyFrame ( const uint8_t *  data,
size_t  len 
)
inlineoverridevirtual

See VideoOutput::isKeyFrame() - true only for an I-picture (picture_coding_type == 1); P- and B-pictures both depend on other frames, so neither counts as self-contained here.

Reimplemented from VideoOutput.

◆ isValid()

bool isValid ( const uint8_t *  data,
size_t  len 
)
inlineoverridevirtual

True if data contains an MPEG-1 sequence_header (00 00 01 B3) - required by spec to precede the first picture of any real MPEG-1 elementary stream, so it's reliably present in the very first access unit a demuxer ever hands to write() (bundled with the first GOP/ picture - see ContainerMPG.h's own unit-buffering comment). 0xB3 can never appear as a valid H.264 NAL header byte (forbidden_zero_bit would have to be 1), so this never false-positives on H.264 content. See VideoDecoder::isValid().

Reimplemented from VideoDecoder.

◆ onFrame()

static void onFrame ( tinympg::TinyMPGDecoder< tinympg::PSRAMAllocatorESP32< uint8_t > > &  decoder,
void *  userData 
)
inlinestaticprotected

◆ setByteSwap()

void setByteSwap ( bool  active)
inline

Swaps the two bytes of every RGB565 pixel before it reaches setOutput()'s target - on by default. TinyMPGDecoder::toRGB565() (via convertYuv420ToRgb565(), TinyMPG/decoder/mpg_rgb.h) packs each pixel into a native uint16_t, which lands little-endian in memory on ESP32/most Arduino targets, but SPI TFT panels (ILI9341 etc.) expect RGB565 transmitted big-endian - without the swap, colors come out visibly wrong. Only affects VideoFormat::RGB565 - RGB666/RGB888/I420 are unaffected (already byte-oriented, not packed into a uint16_t). Turn off only if your VideoOutput target already performs its own byte-swap.

◆ setIgnorePFrames()

void setIgnorePFrames ( bool  active)
inline

See tinympg::TinyMPGDecoder::setIgnorePFrames() - when set, P-pictures are silently discarded (no slices decoded, no callback fired, no error status) instead of being decoded; I- and B-pictures are unaffected. Off by default.

◆ setOutput() [1/2]

void setOutput ( Print out)
inlineoverridevirtual

Defines the target each decoded picture is written to.

Implements VideoDecoder.

◆ setOutput() [2/2]

void setOutput ( VideoOutput out)
inlineoverridevirtual

Defines the target each decoded picture is written to - the VideoOutput-specific counterpart of setOutput(Print&), for a target like 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 decoder-specific extras) so code holding only a VideoDecoder& (e.g. VideoPlayer) can wire it to an arbitrary VideoOutput& without knowing the concrete decoder type - every current decoder already implemented this identically before it was pulled up into the interface.

Implements VideoDecoder.

◆ setSkipRender()

virtual void setSkipRender ( bool  skip)
inlinevirtualinherited

Hint to skip the expensive part of displaying the next frame(s) (e.g. the panel refresh) while still accepting and fully processing write() calls - used to recover from falling behind the playback schedule without breaking a codec's decode state (e.g. H.264 inter-prediction reference chain, which requires every frame to still be decoded even if it's never shown). Default no-op: implementations that can't skip rendering cheaply just ignore it and always render.

Reimplemented in MultiVideoDecoder, OutputFPSMeter, OutputTinyGPU, PacedVideoOutput, and VideoFrameMeter.

◆ setVideoFormat()

void setVideoFormat ( VideoFormat  format)
inlineoverridevirtual

Selects the pixel format written to setOutput()'s target - e.g. VideoFormat::RGB565 (the common TFT wire format), RGB666/RGB888 for higher color depth displays, or I420 to pass the decoded planes through unconverted. Not every decoder backend supports every value (e.g. RGB666/RGB888 are TinyH264-only, not available on the esp_h264 backend) - unsupported values are logged and ignored (the previously selected format stays in effect); see the concrete class for exactly which ones it supports. Call before begin().

Implements VideoDecoder.

◆ setVideoInfoSource()

virtual void setVideoInfoSource ( VideoInfoSource source)
inlinevirtualinherited

Optional: registers where width/height/fps/format (VideoInfo) come from - e.g. the demuxer feeding this output, so it can size its own buffers/panel setup without the caller having to duplicate that call per sketch (VideoPlayer::begin() does this automatically for whichever VideoOutput it was given). Default no-op: only implementations that actually need VideoInfo (OutputTinyGPU/ OutputOpenCV/OutputTFT_eSPI) override this.

Reimplemented in MultiVideoDecoder, OutputOpenCV, OutputTFT_eSPI, and OutputTinyGPU.

◆ totalDecodeMs()

virtual uint64_t totalDecodeMs ( ) const
inlinevirtualinherited

Optional: sum of time (ms) spent purely decoding (excluding any surrounding convert/render/SPI work a subclass's write() also does) since begin() - see H264Decoder's own override for the only current implementation. Default 0: only meaningful for a decoder that separates decode time from render time internally: PacedVideoOutput:: logTo() prints a decode-vs-render split under "avg decode ms:" only when this returns nonzero.

Reimplemented in H264Decoder, and MultiVideoDecoder.

◆ videoInfo()

VideoInfo videoInfo ( )
inlineoverridevirtual

Reports the format/dimensions of the picture written to setOutput()'s target - VideoInfo::format is always the format most recently selected via setVideoFormat() (RGB565 if never called), the reliable way to determine it (rather than assuming); width/ height reflect the most recently decoded picture, 0 before any picture has been decoded.

Implements VideoDecoder.

◆ write()

size_t write ( const uint8_t *  data,
size_t  len 
)
inlineoverridevirtual

Forwards to TinyMPGDecoder::write() with the default isLastChunk=true ("this buffer is one whole, self-contained unit"). Correct because DemuxerMPG (ContainerMPG.h) now accumulates every fragment of a picture (across PES boundaries and its own small parse buffer) into one complete access unit before ever calling write() here - each call really does receive exactly one whole picture, never a boundary-split partial one. (Previously, before that buffering existed, DemuxerMPG forwarded video data in whatever increments happened to be buffered, and this needed isLastChunk=false to avoid TinyMPGDecoder treating a split unit as complete and silently reconstructing it from stale/wrong macroblocks - see ContainerMPG.h's own video_unit_buffer comment.)

Implements VideoOutput.

◆ writeFrame()

void writeFrame ( tinympg::TinyMPGDecoder< tinympg::PSRAMAllocatorESP32< uint8_t > > &  decoder)
inlineprotected

◆ writeToOutput()

size_t writeToOutput ( uint8_t *  data,
size_t  len 
)
inlineprotected

Member Data Documentation

◆ byte_swap

bool byte_swap = true
protected

◆ decoder_

tinympg::TinyMPGDecoder< tinympg::PSRAMAllocatorESP32<uint8_t> > decoder_
protected

◆ frame_buffer

Vector<uint8_t> frame_buffer
protected

◆ frame_emitted

bool frame_emitted = false
protected

◆ p_out

Print* p_out = nullptr
protected

◆ p_out_video

VideoOutput* p_out_video = nullptr
protected

◆ pixel_format

VideoFormat pixel_format = VideoFormat::RGB565
protected

The documentation for this class was generated from the following file: