arduino-audio-tools
Loading...
Searching...
No Matches
VideoMuxer.h
Go to the documentation of this file.
1#pragma once
2
5
6namespace audio_tools {
7
40 public:
41 VideoMuxer() = default;
42 VideoMuxer(Muxer& muxer) { setMuxer(muxer); }
43
45 void setMuxer(Muxer& muxer) { p_muxer = &muxer; }
46
51 void setAudioSource(Stream& pcm) { p_audio = &pcm; }
52
55 p_audio = &out;
57 audio_info = out.audioInfo();
58 }
59
64 audio_info = info;
67 } else {
68 LOGI("VideoMuxer: setAudioInfo() source not updated");
69 }
70 }
71
77 void setAudioEncoder(AudioEncoder& encoder) { p_audio_encoder = &encoder; }
78
82 void setVideoSource(VideoFrameSource& video) { p_video = &video; }
83
89 void setVideoEncoder(VideoEncoder& encoder) { p_video_encoder = &encoder; }
90
95 bool begin() {
96 if (p_muxer == nullptr) {
97 LOGE("VideoMuxer: setMuxer() was not called");
98 return false;
99 }
100
101 have_video = false;
102 if (p_video != nullptr) {
103 VideoInfo info = p_video->videoInfo();
104 if (info.fps <= 0 || info.width == 0 || info.height == 0) {
105 LOGE(
106 "VideoMuxer: VideoFrameSource::videoInfo() incomplete "
107 "(width=%d height=%d fps=%f)",
108 (int)info.width, (int)info.height, info.fps);
109 return false;
110 }
112 cfg.width = info.width;
113 cfg.height = info.height;
114 cfg.fps = info.fps;
115 cfg.format = p_video_encoder != nullptr
117 : info.format;
118 p_muxer->setVideoInfo(cfg);
119 video_fps = info.fps;
120 video_interval_ms = (uint32_t)(1000.0f / info.fps);
122 have_video = true;
123 }
124
125 have_audio = p_audio != nullptr;
126 if (have_audio) {
127 AudioInfoFormat muxer_audio_info;
128 if (p_audio_encoder != nullptr) {
129 muxer_audio_info = AudioInfoFormat(audio_info);
130 AudioFormat mime_format = fromMime(p_audio_encoder->mime());
131 muxer_audio_info.format = mime_format != AudioFormat::UNKNOWN
132 ? mime_format
134 } else {
135 muxer_audio_info = AudioInfoFormat(audio_info);
136 muxer_audio_info.format = AudioFormat::PCM;
137 }
138 p_muxer->setAudioInfo(muxer_audio_info);
139 sample_rate = muxer_audio_info.sample_rate;
141 (muxer_audio_info.bits_per_sample / 8) * muxer_audio_info.channels;
142 }
143
144 if (!p_muxer->begin()) {
145 LOGE("VideoMuxer: Muxer::begin() failed");
146 return false;
147 }
148
149 if (have_video && p_video_encoder != nullptr) {
150 // routed through video_sink, not *p_muxer directly, so it can
151 // determine each frame's real isKeyFrame status (see
152 // MuxerVideoSink, ContainerCommon.h) instead of defaulting to true
155 }
156 if (have_audio && p_audio_encoder != nullptr) {
161 }
162
165 return true;
166 }
167
169 void end() {
170 if (p_muxer != nullptr) p_muxer->end();
171 }
172
181 size_t copy() {
182 if (have_audio) return copyAudio();
183 if (have_video) return copyVideoPaced() ? 1 : 0;
184 return 0;
185 }
186
187 protected:
188 static constexpr size_t kAudioReadChunkSize = 512;
189
190 Muxer* p_muxer = nullptr;
191 Stream* p_audio = nullptr;
199 bool have_audio = false;
200 bool have_video = false;
201 float video_fps = 0;
207
208 size_t copyAudio() {
210 size_t n = p_audio->readBytes(buf, sizeof(buf));
211 if (n == 0) return 0;
212
214 if (p_audio_encoder != nullptr) {
215 p_audio_encoder->write(buf, n);
216 } else {
217 p_muxer->addAudioFrame(buf, n);
218 }
219
221
222 // catch up: mux/encode every video frame now due, given the audio
223 // time just reached - this, not a timer, is what paces video. Strict
224 // '<' (not '<=') so a duration landing exactly on a frame boundary
225 // doesn't pull one extra frame for the instant at that boundary.
226 if (have_video && sample_rate > 0) {
227 double audio_time_s = (double)audio_samples_written / sample_rate;
228 while ((double)video_frame_count / video_fps < audio_time_s) {
229 if (!copyVideo()) break; // source exhausted
230 }
231 }
232 return n;
233 }
234
235 bool copyVideo() {
236 size_t len = 0;
237 const uint8_t* data = p_video->nextFrame(len);
238 if (data == nullptr || len == 0) return false;
239
241 if (p_video_encoder != nullptr) {
242 p_video_encoder->write(data, len);
243 } else {
244 bool is_key = p_muxer->getVideoInfo().format == VideoFormat::H264
245 ? isH264KeyFrame(data, len)
246 : true;
247 p_muxer->addVideoFrame(data, len, is_key);
248 }
250 return true;
251 }
252
259 uint32_t start = millis();
260 if (!copyVideo()) return false;
261 uint32_t elapsed = millis() - start;
262 if (elapsed < video_interval_ms) delay(video_interval_ms - elapsed);
263 return true;
264 }
265};
266
267} // namespace audio_tools
#define LOGI(...)
Definition AudioLoggerIDF.h:28
#define LOGE(...)
Definition AudioLoggerIDF.h:30
Definition Arduino.h:136
virtual size_t readBytes(uint8_t *data, size_t len)
Definition Arduino.h:140
Encoding of PCM data.
Definition AudioCodecsBase.h:101
void setAudioInfo(AudioInfo from) override
Defines the sample rate, number of channels and bits per sample.
Definition AudioCodecsBase.h:110
virtual void setOutput(Print &out_stream) override
Default output assignment (encoders may override to store Print reference)
Definition AudioCodecsBase.h:113
virtual const char * mime()=0
Provides the mime type of the encoded result.
Supports changes to the sampling rate, bits and channels.
Definition AudioTypes.h:137
virtual void setAudioInfo(AudioInfo info)=0
Defines the input AudioInfo.
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
virtual size_t write(const uint8_t *data, size_t len)=0
virtual bool begin()=0
Print adapter that writes each write() call to a Muxer as one audio frame (Muxer::addAudioFrame()) - ...
Definition ContainerCommon.h:161
void begin(Muxer &muxer)
Definition ContainerCommon.h:163
Common interface for muxers (MuxerAVI, MuxerMP4) that combine an already-encoded video track (and opt...
Definition ContainerCommon.h:42
virtual void setVideoInfo(MuxerVideoConfig config)=0
Defines the video track configuration - call before begin()
virtual MuxerVideoConfig getVideoInfo()=0
Provides the video track configuration.
virtual void setAudioInfo(AudioInfoFormat info)=0
virtual size_t addAudioFrame(const uint8_t *data, size_t len)=0
virtual size_t addVideoFrame(const uint8_t *data, size_t len, bool isKeyFrame=true)=0
virtual void end()=0
Closes the muxer.
virtual void setStreamType(StreamContentType type)=0
Selects whether write() feeds the video or the audio track.
virtual bool begin()=0
Print sink that writes each frame it receives to a Muxer's video track via addVideoFrame(),...
Definition ContainerCommon.h:137
void begin(Muxer &muxer)
Definition ContainerCommon.h:139
Common interface for video encoders (e.g. H264Encoder, H264EncoderESP32S3 - CodecH264....
Definition CodecVideo.h:89
virtual size_t write(const uint8_t *data, size_t len)=0
virtual void setOutput(Print &out)=0
Defines the target the encoded bitstream is written to.
virtual bool begin()=0
Initializes the encoder (allocates its picture buffers, etc).
virtual VideoInfo videoInfo()=0
Pull-based provider of one already-encoded video/image frame at a time - e.g. wraps a camera capture ...
Definition Video.h:92
virtual const uint8_t * nextFrame(size_t &len)=0
virtual VideoInfo videoInfo()=0
Feeds a Muxer (MuxerAVI, MuxerMP4, ...) from a single copy() call.
Definition VideoMuxer.h:39
uint32_t bytes_per_sample
Definition VideoMuxer.h:204
VideoEncoder * p_video_encoder
Definition VideoMuxer.h:196
bool have_video
Definition VideoMuxer.h:200
Muxer * p_muxer
Definition VideoMuxer.h:190
uint32_t sample_rate
Definition VideoMuxer.h:203
float video_fps
Definition VideoMuxer.h:201
MuxerAudioSink audio_sink
Definition VideoMuxer.h:198
void setAudioEncoder(AudioEncoder &encoder)
Definition VideoMuxer.h:77
VideoMuxer(Muxer &muxer)
Definition VideoMuxer.h:42
void setMuxer(Muxer &muxer)
Defines the Muxer copy() writes to - call before begin().
Definition VideoMuxer.h:45
MuxerVideoSink video_sink
Definition VideoMuxer.h:197
void setAudioSource(Stream &pcm)
Definition VideoMuxer.h:51
void setAudioInfo(AudioInfo info)
Definition VideoMuxer.h:63
bool begin()
Definition VideoMuxer.h:95
AudioInfo audio_info
Definition VideoMuxer.h:193
bool have_audio
Definition VideoMuxer.h:199
uint32_t video_interval_ms
Definition VideoMuxer.h:202
bool copyVideoPaced()
Definition VideoMuxer.h:258
void setVideoSource(VideoFrameSource &video)
Definition VideoMuxer.h:82
AudioInfoSupport * p_source_audio_info
Definition VideoMuxer.h:194
static constexpr size_t kAudioReadChunkSize
Definition VideoMuxer.h:188
void end()
Closes the Muxer.
Definition VideoMuxer.h:169
size_t copyAudio()
Definition VideoMuxer.h:208
AudioEncoder * p_audio_encoder
Definition VideoMuxer.h:192
uint64_t audio_samples_written
Definition VideoMuxer.h:205
uint32_t video_frame_count
Definition VideoMuxer.h:206
void setAudioSource(AudioStream &out)
Defines the AudioSource that we can configure with setAudioInfo()
Definition VideoMuxer.h:54
void setVideoEncoder(VideoEncoder &encoder)
Definition VideoMuxer.h:89
size_t copy()
Definition VideoMuxer.h:181
VideoFrameSource * p_video
Definition VideoMuxer.h:195
Stream * p_audio
Definition VideoMuxer.h:191
bool copyVideo()
Definition VideoMuxer.h:235
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:371
@ Audio
Definition Video.h:21
@ Video
Definition Video.h:21
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition LMSEchoCancellationStream.h:6
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 "wav code"): identifies the codec (PCM,...
Definition AudioFormat.h:400
AudioFormat format
Definition AudioFormat.h:409
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:56
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:58
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:60
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:62
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