arduino-audio-tools
Loading...
Searching...
No Matches
VideoMuxerWithTasks.h
Go to the documentation of this file.
1#pragma once
2
6
7namespace audio_tools {
8
41 public:
44
46 void setMuxer(Muxer &muxer) { p_muxer = &muxer; }
47
52 void setAudioSource(Stream &pcm) { p_audio = &pcm; }
53
56 p_audio = &out;
58 audio_info = out.audioInfo();
59 }
60
65 void setAudioInfo(AudioInfo info) {
66 audio_info = info;
68 p_source_audio_info->setAudioInfo(info);
69 } else {
70 LOGI("VideoMuxerWithTasks: setAudioInfo() source not updated");
71 }
72 }
73
83 void setAudioEncoder(AudioEncoder &encoder) { p_audio_encoder = &encoder; }
84
88 void setVideoSource(VideoFrameSource &video) { p_video = &video; }
89
95 void setVideoEncoder(VideoEncoder &encoder) { p_video_encoder = &encoder; }
96
101 void setMutex(MutexBase &mutex) { p_mutex = &mutex; }
102
107 void setTaskParameters(uint32_t stackSizeWords, uint8_t priority,
108 int core = -1) {
109 task_stack_size = stackSizeWords;
110 task_priority = priority;
111 task_core = core;
112 }
113
118 bool begin() {
119 if (p_muxer == nullptr) {
120 LOGE("VideoMuxerWithTasks: setMuxer() was not called");
121 return false;
122 }
123
124 bool have_video = false;
125 if (p_video != nullptr) {
126 VideoInfo info = p_video->videoInfo();
127 if (info.fps <= 0 || info.width == 0 || info.height == 0) {
128 LOGE(
129 "VideoMuxerWithTasks: VideoFrameSource::videoInfo() incomplete "
130 "(width=%d height=%d fps=%f)",
131 (int)info.width, (int)info.height, info.fps);
132 return false;
133 }
135 cfg.width = info.width;
136 cfg.height = info.height;
137 cfg.fps = info.fps;
138 // with a video encoder, the source's own format describes the raw
139 // picture, not the container - query the encoder's own
140 // VideoEncoder::videoInfo() instead, the reliable way to determine
141 // what actually ends up in the container
142 cfg.format = p_video_encoder != nullptr
143 ? p_video_encoder->videoInfo().format
144 : info.format;
145 p_muxer->setVideoInfo(cfg);
146 video_interval_ms = (uint32_t)(1000.0f / info.fps);
147 video_sink.begin(*p_muxer);
148 have_video = true;
149 }
150
151 bool have_audio = p_audio != nullptr;
152 if (have_audio) {
153 AudioInfoFormat muxer_audio_info;
154 if (p_audio_encoder != nullptr) {
155 muxer_audio_info = AudioInfoFormat(audio_info);
156 AudioFormat mime_format = fromMime(p_audio_encoder->mime());
157 muxer_audio_info.format = mime_format != AudioFormat::UNKNOWN
158 ? mime_format
160 } else {
161 muxer_audio_info = AudioInfoFormat(audio_info);
162 muxer_audio_info.format = AudioFormat::PCM;
163 }
164 p_muxer->setAudioInfo(muxer_audio_info);
165 }
166
167 if (!p_muxer->begin()) {
168 LOGE("VideoMuxerWithTasks: Muxer::begin() failed");
169 return false;
170 }
171
172 bool ok = true;
173 if (have_video) {
174 if (p_video_encoder != nullptr) {
175 // routed through video_sink, not *p_muxer directly, so it can
176 // determine each frame's real isKeyFrame status (see
177 // MuxerVideoSink) instead of defaulting to true
178 p_video_encoder->setOutput(video_sink);
179 p_video_encoder->begin();
180 }
181 ok &= video_task.create("VideoMuxerVideoTask", task_stack_size,
183 ok &= video_task.begin([this]() { videoTaskLoop(); });
184 }
185 if (have_audio) {
186 if (p_audio_encoder != nullptr) {
187 p_audio_encoder->setAudioInfo(audio_info);
188 audio_sink.begin(*p_muxer);
189 p_audio_encoder->setOutput(audio_sink);
190 p_audio_encoder->begin();
191 }
192 ok &= audio_task.create("VideoMuxerAudioTask", task_stack_size,
194 ok &= audio_task.begin([this]() { audioTaskLoop(); });
195 }
196 return ok;
197 }
198
200 void end() {
201 audio_task.end();
202 video_task.end();
203 if (p_muxer != nullptr) p_muxer->end();
204 }
205
206 bool isRunning() { return audio_task.isRunning() || video_task.isRunning(); }
207
208 protected:
213 static constexpr size_t kAudioReadChunkSize = 512;
214
219#ifdef __linux__
220 using DefaultMutex = StdMutex;
221#else
223#endif
224
225 Muxer *p_muxer = nullptr;
226 Stream *p_audio = nullptr;
238 uint32_t task_stack_size = 4096;
239 uint8_t task_priority = 2;
240 int task_core = -1;
241 uint32_t video_interval_ms = 33;
242
251 if (p_audio != nullptr) {
252 uint8_t buf[kAudioReadChunkSize];
253 size_t n = p_audio->readBytes(buf, sizeof(buf));
254 if (n > 0) {
255 LockGuard guard(p_mutex);
256 p_muxer->setStreamType(StreamContentType::Audio);
257 if (p_audio_encoder != nullptr) {
258 p_audio_encoder->write(buf, n);
259 } else {
260 p_muxer->addAudioFrame(buf, n);
261 }
262 } else {
263 delay(1);
264 }
265 }
266 }
267
273 uint32_t start = millis();
274 if (p_video != nullptr && p_muxer != nullptr) {
275 size_t len = 0;
276 const uint8_t *data = p_video->nextFrame(len);
277 if (data != nullptr && len > 0) {
278 LockGuard guard(p_mutex);
279 p_muxer->setStreamType(StreamContentType::Video);
280 if (p_video_encoder != nullptr) {
281 p_video_encoder->write(data, len);
282 } else {
283 bool is_key = p_muxer->getVideoInfo().format == VideoFormat::H264
284 ? isH264KeyFrame(data, len)
285 : true;
286 p_muxer->addVideoFrame(data, len, is_key);
287 }
288 }
289 }
290 uint32_t elapsed = millis() - start;
291 // always yield, even when encoding took longer than the frame interval:
292 // otherwise lower priority tasks (e.g. the idle task watched by the
293 // task watchdog) never get to run on this core
294 delay(elapsed < video_interval_ms ? video_interval_ms - elapsed : 1);
295 }
296};
297
298} // namespace audio_tools
#define LOGI(...)
#define LOGE(...)
Encoding of PCM data.
Definition AudioCodecsBase.h:101
Supports changes to the sampling rate, bits and channels.
Definition AudioTypes.h:137
Base class for all Audio Streams. It support the boolean operator to test if the object is ready with...
Definition BaseStream.h:120
virtual AudioInfo audioInfo() override
provides the actual input AudioInfo
Definition BaseStream.h:151
RAII implementaion using a Mutex: Only a few microcontrollers provide lock guards,...
Definition LockGuard.h:17
Empty Mutex implementation which does nothing.
Definition Mutex.h:15
Print adapter that writes each write() call to a Muxer as one audio frame (Muxer::addAudioFrame()) - ...
Definition ContainerCommon.h:161
Common interface for muxers (MuxerAVI, MuxerMP4) that combine an already-encoded video track (and opt...
Definition ContainerCommon.h:42
Print sink that writes each frame it receives to a Muxer's video track via addVideoFrame(),...
Definition ContainerCommon.h:137
Mutex implemntation based on std::mutex.
Definition Mutex.h:16
Definition CodecOpusOgg.h:137
FreeRTOS task.
Definition Task.h:26
Common interface for video encoders (e.g. H264Encoder, H264EncoderESP32S3 - CodecH264....
Definition CodecVideo.h:89
Pull-based provider of one already-encoded video/image frame at a time - e.g. wraps a camera capture ...
Definition Video.h:92
void audioTaskLoop()
Definition VideoMuxerWithTasks.h:250
DefaultMutex default_mutex
Definition VideoMuxerWithTasks.h:234
VideoEncoder * p_video_encoder
Definition VideoMuxerWithTasks.h:231
MutexBase * p_mutex
Definition VideoMuxerWithTasks.h:235
void setMutex(MutexBase &mutex)
Definition VideoMuxerWithTasks.h:101
int task_core
Definition VideoMuxerWithTasks.h:240
Muxer * p_muxer
Definition VideoMuxerWithTasks.h:225
Task audio_task
Definition VideoMuxerWithTasks.h:236
MuxerAudioSink audio_sink
Definition VideoMuxerWithTasks.h:233
void setAudioEncoder(AudioEncoder &encoder)
Definition VideoMuxerWithTasks.h:83
bool isRunning()
Definition VideoMuxerWithTasks.h:206
void setMuxer(Muxer &muxer)
Defines the Muxer both tasks write to - call before begin().
Definition VideoMuxerWithTasks.h:46
MuxerVideoSink video_sink
Definition VideoMuxerWithTasks.h:232
void setAudioSource(Stream &pcm)
Definition VideoMuxerWithTasks.h:52
VideoMuxerWithTasks(Muxer &muxer)
Definition VideoMuxerWithTasks.h:43
void setAudioInfo(AudioInfo info)
Definition VideoMuxerWithTasks.h:65
bool begin()
Definition VideoMuxerWithTasks.h:118
AudioInfo audio_info
Definition VideoMuxerWithTasks.h:228
uint32_t video_interval_ms
Definition VideoMuxerWithTasks.h:241
uint8_t task_priority
Definition VideoMuxerWithTasks.h:239
void setVideoSource(VideoFrameSource &video)
Definition VideoMuxerWithTasks.h:88
AudioInfoSupport * p_source_audio_info
Definition VideoMuxerWithTasks.h:229
static constexpr size_t kAudioReadChunkSize
Definition VideoMuxerWithTasks.h:213
Task video_task
Definition VideoMuxerWithTasks.h:237
void end()
Stops both tasks and closes the Muxer.
Definition VideoMuxerWithTasks.h:200
AudioEncoder * p_audio_encoder
Definition VideoMuxerWithTasks.h:227
Mutex DefaultMutex
Definition VideoMuxerWithTasks.h:222
void setAudioSource(AudioStream &out)
Defines the AudioSource that we can configure with setAudioInfo().
Definition VideoMuxerWithTasks.h:55
void videoTaskLoop()
Definition VideoMuxerWithTasks.h:272
void setVideoEncoder(VideoEncoder &encoder)
Definition VideoMuxerWithTasks.h:95
VideoFrameSource * p_video
Definition VideoMuxerWithTasks.h:230
Stream * p_audio
Definition VideoMuxerWithTasks.h:226
uint32_t task_stack_size
Definition VideoMuxerWithTasks.h:238
void setTaskParameters(uint32_t stackSizeWords, uint8_t priority, int core=-1)
Definition VideoMuxerWithTasks.h:107
bool isH264KeyFrame(const uint8_t *data, size_t len)
True if the given Annex-B H.264 access unit contains an IDR slice NAL unit (nal_unit_type 5) - the re...
Definition Video.h:52
AudioFormat
Audio format codes used by Microsoft e.g. in avi or wav files.
Definition AudioFormat.h:21
AudioFormat fromMime(const char *mime)
Best-effort inverse of toMime(): maps a mime type (e.g. an AudioEncoder's mime()) back to the AudioFo...
Definition AudioFormat.h:363
@ H264
Definition VideoOutput.h:30
@ Audio
Definition Video.h:21
@ Video
Definition Video.h:21
@ PCM
Definition AudioFormat.h:23
@ UNKNOWN
Definition AudioFormat.h:22
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition LMSEchoCancellationStream.h:6
StdMutex Mutex
Default Mutex implementation using std::mutex.
Definition Mutex.h:42
void delay(uint32_t ms)
Definition Arduino.h:259
uint32_t millis()
Returns the milliseconds since the start.
Definition Arduino.h:260
AudioInfo extended with a WAVEFORMATEX-style codec tag (the "wavcode"): identifies the codec (PCM,...
Definition AudioFormat.h:392
AudioFormat format
Definition AudioFormat.h:401
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:56
Shared video track configuration for muxers (MuxerAVI, MuxerMP4) - call before begin().
Definition ContainerCommon.h:11
float fps
Definition ContainerCommon.h:14
uint16_t height
Definition ContainerCommon.h:13
uint16_t width
Definition ContainerCommon.h:12
VideoFormat format
Definition ContainerCommon.h:15
Basic video information (width/height/codec/frame size), analogous to AudioInfo - common to both Demu...
Definition VideoOutput.h:49
float fps
Definition VideoOutput.h:56
uint16_t height
Frame height in pixels.
Definition VideoOutput.h:53
uint16_t width
Frame width in pixels.
Definition VideoOutput.h:51
VideoFormat format
Video codec - VideoFormat::UNKNOWN if not (yet) determined.
Definition VideoOutput.h:58