arduino-audio-tools
Loading...
Searching...
No Matches
Classes | Public Member Functions | Protected Attributes | List of all members
VideoFrameMeter Class Reference

Transparent write() wrapper that measures throughput/turnaround while forwarding every call unchanged to the target given in the constructor - drop it into a pipeline slot (e.g. h264Decoder.setOutput( meter) instead of h264Decoder.setOutput(tftOutput), with meter wrapping tftOutput) to find out how that one stage is actually performing, without instrumenting the stage itself. More...

#include <Video.h>

Inheritance diagram for VideoFrameMeter:
VideoOutput

Classes

class  PrintView
 

Public Member Functions

 VideoFrameMeter (Print &target)
 
 VideoFrameMeter (VideoOutput &target)
 
PrintasPrint ()
 
uint32_t count () const
 Total number of write() calls forwarded so far.
 
void flush () override
 
float fpsAvg () const
 
float fpsMax () const
 
virtual uint32_t getWriteTimeMs () const
 Optional: returns the time (ms) spent in the last write() call.
 
virtual bool hadOutput () const
 
virtual bool isKeyFrame (const uint8_t *data, size_t len)
 
void setSkipRender (bool skip) override
 
float timeTurnaroundMs () const
 
float timeWriteMs () const
 
size_t write (const uint8_t *data, size_t len) override
 

Protected Attributes

uint32_t count_ = 0
 
bool has_last_call = false
 
uint32_t last_call_ms = 0
 
Printp_target = nullptr
 
VideoOutputp_target_video = nullptr
 
PrintView print_view_ {*this}
 
uint32_t total_forward_ms = 0
 
uint32_t total_turnaround_ms = 0
 

Detailed Description

Transparent write() wrapper that measures throughput/turnaround while forwarding every call unchanged to the target given in the constructor - drop it into a pipeline slot (e.g. h264Decoder.setOutput( meter) instead of h264Decoder.setOutput(tftOutput), with meter wrapping tftOutput) to find out how that one stage is actually performing, without instrumenting the stage itself.

Derives from VideoOutput only (not also Print - see asPrint() for why), so it can be passed directly wherever a VideoOutput& is expected; for a plain Print& target/slot, use asPrint() instead of the object itself.

Tracks, as running averages since construction:

Author
Phil Schatzmann

Constructor & Destructor Documentation

◆ VideoFrameMeter() [1/2]

VideoFrameMeter ( Print target)
inline
Parameters
targetevery write() call is forwarded here, unmodified.

◆ VideoFrameMeter() [2/2]

VideoFrameMeter ( VideoOutput target)
inline
Parameters
targetevery write() call is forwarded here, unmodified - AND flush()/setSkipRender() are also forwarded, so a meter dropped in front of a VideoOutput (e.g. wrapping tftOutput in h264Decoder. setOutput(meter) instead of h264Decoder.setOutput(tftOutput)) stays transparent to a pipeline's render-skip hint instead of silently breaking it - the Print-only constructor above can't do that, since Print has no equivalent call to forward.

Member Function Documentation

◆ asPrint()

Print & asPrint ( )
inline

A Print-compatible view onto this meter - use this (e.g. someSink.setOutput(meter.asPrint())) at any call site that specifically needs a Print& rather than a VideoOutput&. Never pass the meter itself there: VideoFrameMeter derives only from VideoOutput precisely so it stays unambiguous wherever an API (this codebase has several - DemuxerAVI::setOutputVideo(), H264Decoder::setOutput(), ...) is overloaded on both Print& and VideoOutput& - a type implicitly convertible to both would make every such call ambiguous.

◆ count()

uint32_t count ( ) const
inline

Total number of write() calls forwarded so far.

◆ flush()

void flush ( )
inlineoverridevirtual

Finalizes the frame most recently written via one or more write() calls - see class comment. Default no-op for implementations that display/decode synchronously in write() instead.

Reimplemented from VideoOutput.

◆ fpsAvg()

float fpsAvg ( ) const
inline

◆ fpsMax()

float fpsMax ( ) const
inline

◆ 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()

virtual bool hadOutput ( ) const
inlinevirtualinherited

True if the most recent write()+flush() call actually produced a displayable picture - default true, matching every synchronous decoder (H264Decoder, MJPEGDecoder, ...), which always decodes and pushes pixels fully within that one call. Override this only if your decoder can legitimately accept/decode a frame's bytes without emitting a picture during that same call - e.g. MPGDecoder, whose B-picture display-order reordering can hold a just-decoded picture back and instead emit an earlier one (or nothing at all) from a given write(), see its own override. Used by PacedVideoOutput to avoid counting/timing a call that did no real rendering work as a rendered frame - without this, its outputFPS()/frameCountI()/ frameCountP()/avgFrameMs() would overcount for such a decoder.

Reimplemented in MPGDecoder.

◆ isKeyFrame()

virtual bool isKeyFrame ( const uint8_t *  data,
size_t  len 
)
inlinevirtualinherited

True if data (one complete encoded frame, as handed to write()) is a keyframe/sync-sample - self-contained, decodable without any earlier frame. Used e.g. by PacedVideoOutput to decide which frames are safe to drop, and whether it's safe to resume decoding after abandoning a backlog (see its own class comment). Default false: a plain VideoOutput doesn't know or care about codec structure - override this in a decoder for the bitstream format it actually parses (see H264Decoder/H264DecoderESP32S3's isH264KeyFrame()-based override, MPGDecoder's isMpeg1KeyFrame()- based one). Getting this right matters beyond bookkeeping: a target whose frames are never recognized as keyframes can leave a caller like PacedVideoOutput unable to ever resume after a resync.

Reimplemented in PacedVideoOutput, H264Decoder, H264DecoderESP32S3< Alloc >, MJPEGDecoder, MPGDecoder, and MultiVideoDecoder.

◆ setSkipRender()

void setSkipRender ( bool  skip)
inlineoverridevirtual

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 from VideoOutput.

◆ timeTurnaroundMs()

float timeTurnaroundMs ( ) const
inline

Average wall-clock gap between the start of consecutive write() calls, in ms - the same figure fpsAvg() is derived from (fpsAvg() == 1000/timeTurnaroundMs()), for callers that want the raw duration instead of a rate.

◆ timeWriteMs()

float timeWriteMs ( ) const
inline

Average time spent inside the forwarded write() call, in ms - the same figure fpsMax() is derived from (fpsMax() == 1000/timeWriteMs()), for callers that want the raw duration instead of a rate.

◆ write()

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

Implements VideoOutput.

Member Data Documentation

◆ count_

uint32_t count_ = 0
protected

◆ has_last_call

bool has_last_call = false
protected

◆ last_call_ms

uint32_t last_call_ms = 0
protected

◆ p_target

Print* p_target = nullptr
protected

◆ p_target_video

VideoOutput* p_target_video = nullptr
protected

◆ print_view_

PrintView print_view_ {*this}
protected

◆ total_forward_ms

uint32_t total_forward_ms = 0
protected

◆ total_turnaround_ms

uint32_t total_turnaround_ms = 0
protected

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