|
arduino-audio-tools
|
Feeds a Muxer (MuxerAVI, MuxerMP4, ...) from two background Tasks instead of a single loop()/copy() call - one per track, each write wrapped in a LockGuard over a shared mutex (real by default; override via setMutex()), since a Muxer is not safe to call from two threads concurrently. More...
#include <VideoMuxerWithTasks.h>
Public Member Functions | |
| VideoMuxerWithTasks ()=default | |
| VideoMuxerWithTasks (Muxer &muxer) | |
| bool | begin () |
| void | end () |
| Stops both tasks and closes the Muxer. | |
| bool | isRunning () |
| void | setAudioEncoder (AudioEncoder &encoder) |
| void | setAudioInfo (AudioInfo info) |
| void | setAudioSource (AudioStream &out) |
| Defines the AudioSource that we can configure with setAudioInfo() | |
| void | setAudioSource (Stream &pcm) |
| void | setMutex (MutexBase &mutex) |
| void | setMuxer (Muxer &muxer) |
| Defines the Muxer both tasks write to - call before begin(). | |
| void | setTaskParameters (uint32_t stackSizeWords, uint8_t priority, int core=-1) |
| void | setVideoEncoder (VideoEncoder &encoder) |
| void | setVideoSource (VideoFrameSource &video) |
Protected Types | |
| using | DefaultMutex = Mutex |
Protected Member Functions | |
| void | audioTaskLoop () |
| void | videoTaskLoop () |
Protected Attributes | |
| AudioInfo | audio_info |
| Task | audio_task |
| DefaultMutex | default_mutex |
| Stream * | p_audio = nullptr |
| AudioEncoder * | p_audio_encoder = nullptr |
| MutexBase * | p_mutex = &default_mutex |
| Muxer * | p_muxer = nullptr |
| AudioInfoSupport * | p_source_audio_info = nullptr |
| VideoFrameSource * | p_video = nullptr |
| VideoEncoder * | p_video_encoder = nullptr |
| int | task_core = -1 |
| uint8_t | task_priority = 2 |
| uint32_t | task_stack_size = 4096 |
| uint32_t | video_interval_ms = 33 |
| MuxerVideoSink | video_sink |
| Task | video_task |
Static Protected Attributes | |
| static constexpr size_t | kAudioReadChunkSize = 512 |
Feeds a Muxer (MuxerAVI, MuxerMP4, ...) from two background Tasks instead of a single loop()/copy() call - one per track, each write wrapped in a LockGuard over a shared mutex (real by default; override via setMutex()), since a Muxer is not safe to call from two threads concurrently.
Audio (setAudioSource() + optional setAudioEncoder()): reads PCM from a Stream expected to deliver data synchronously, at the real capture rate (e.g. a blocking I2S read) - that's this task's only pacing, no timer/delay() of its own. With an encoder, each chunk is handed to it (framed and written to the Muxer by the encoder itself); without one, each chunk is written to the Muxer as raw PCM directly (call setAudioInfo() in that case).
Video (setVideoSource() + optional setVideoEncoder()): pulls one frame per iteration, timed by VideoFrameSource::videoInfo().fps. With an encoder, each raw picture is passed to VideoEncoder::write(); without one, the frame is written to the Muxer as-is (already-encoded).
begin() derives both Muxer tracks from the source/encoder objects above (VideoEncoder::videoInfo().format decides the real container format, not VideoFrameSource's, since that describes the raw picture when an encoder is used) and calls Muxer::begin() itself - the only Muxer setup still needed from the caller is Muxer::setOutput(). end() stops both tasks and closes the Muxer.
|
protected |
Real mutex type used for the default_mutex member (see setMutex()) - audio_tools::Mutex (MutexRTOS) on RTOS platforms, StdMutex on desktop - both real, so two tasks are protected out of the box without requiring setMutex().
|
default |
|
inline |
|
inlineprotected |
Reads one PCM chunk and either hands it to the audio encoder (which frames and writes it to the Muxer itself) or, without one, writes it to the Muxer directly as one raw PCM frame - no delay() on success: pacing is the PCM Stream's own responsibility (see class comment); a short fallback delay only kicks in if it returned nothing, so a Stream that violates that contract (e.g. non-blocking) can't spin this task at full CPU.
|
inline |
Configures the Muxer's video/audio tracks from the source/encoder objects above, calls Muxer::begin(), then starts the audio and/or video task - see the class comment for exactly what's still the caller's own responsibility beforehand.
|
inline |
Stops both tasks and closes the Muxer.
|
inline |
|
inline |
Defines the (optional) encoder the audio task hands each PCM chunk to - responsible for framing and writing the encoded result to the Muxer itself; its setOutput() is pointed at the Muxer by begin(), overriding any output previously set on it. Its audioInfo() (set it on the encoder, as usual, before calling this) and mime() (see AudioFormat.h's fromMime() - best-effort; falls back to AudioFormat::PCM if it doesn't map) configure the Muxer's audio track. Leave unset to write setAudioSource()'s PCM straight through instead (see setAudioInfo()).
|
inline |
Defines the sample_rate/channels/bits_per_sample of setAudioSource()'s PCM data - only used (instead of AudioEncoder::audioInfo()) when no setAudioEncoder() was called, i.e. the PCM is written to the Muxer as-is. Call before begin().
|
inline |
Defines the AudioSource that we can configure with setAudioInfo()
|
inline |
Defines the raw PCM source the audio task reads from - expected to deliver data synchronously, at the real capture rate (see class comment). On its own (no setAudioEncoder()) each chunk is written to the Muxer as raw PCM - call setAudioInfo() too in that case.
|
inline |
|
inline |
Stack size (words, not bytes)/priority/core applied to both tasks - see audio_tools::Task's own constructor comment for what each parameter means and its platform-specific caveats. Call before begin().
|
inline |
Defines the (optional) encoder the video task hands each raw picture from setVideoSource() to - e.g. an H264Encoder (AudioTools/Video/ CodecH264.h), configured as usual (setSize()/setVideoFormat()/...) before passing it here. Leave unset to write setVideoSource()'s bytes straight through as already-encoded frames instead.
|
inline |
Defines the video frame provider the video task pulls one frame from per iteration - already-encoded unless setVideoEncoder() is also called (see class comment). Leave unset to run the audio task only.
|
inlineprotected |
Pulls one frame, encodes/writes it, then sleeps only the remainder of video_interval_ms - compensating for time spent above (a slow encoder otherwise makes the real capture cadence slower than the fps written into the Muxer's video track).
|
protected |
|
protected |
|
protected |
|
staticconstexprprotected |
Size (bytes) of the PCM chunk read from setAudioSource() and handed to setAudioEncoder()'s write() per audio task iteration - purely a throughput/latency knob (the encoder does its own framing on top of however much data it's given), not a correctness-critical value.
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |