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) {
160 }
161
164 return true;
165 }
166
168 void end() {
169 if (p_muxer != nullptr) p_muxer->end();
170 }
171
180 size_t copy() {
181 if (have_audio) return copyAudio();
182 if (have_video) return copyVideoPaced() ? 1 : 0;
183 return 0;
184 }
185
186 protected:
187 static constexpr size_t kAudioReadChunkSize = 512;
188
189 Muxer* p_muxer = nullptr;
190 Stream* p_audio = nullptr;
197 bool have_audio = false;
198 bool have_video = false;
199 float video_fps = 0;
200 uint32_t video_interval_ms = 33;
201 uint32_t sample_rate = 0;
202 uint32_t bytes_per_sample = 0;
204 uint32_t video_frame_count = 0;
205
206 size_t copyAudio() {
207 uint8_t buf[kAudioReadChunkSize];
208 size_t n = p_audio->readBytes(buf, sizeof(buf));
209 if (n == 0) return 0;
210
212 if (p_audio_encoder != nullptr) {
213 p_audio_encoder->write(buf, n);
214 } else {
215 p_muxer->addAudioFrame(buf, n);
216 }
217
219
220 // catch up: mux/encode every video frame now due, given the audio
221 // time just reached - this, not a timer, is what paces video. Strict
222 // '<' (not '<=') so a duration landing exactly on a frame boundary
223 // doesn't pull one extra frame for the instant at that boundary.
224 if (have_video && sample_rate > 0) {
225 double audio_time_s = (double)audio_samples_written / sample_rate;
226 while ((double)video_frame_count / video_fps < audio_time_s) {
227 if (!copyVideo()) break; // source exhausted
228 }
229 }
230 return n;
231 }
232
233 bool copyVideo() {
234 size_t len = 0;
235 const uint8_t* data = p_video->nextFrame(len);
236 if (data == nullptr || len == 0) return false;
237
239 if (p_video_encoder != nullptr) {
240 p_video_encoder->write(data, len);
241 } else {
242 bool is_key = p_muxer->getVideoInfo().format == VideoFormat::H264
243 ? isH264KeyFrame(data, len)
244 : true;
245 p_muxer->addVideoFrame(data, len, is_key);
246 }
248 return true;
249 }
250
257 uint32_t start = millis();
258 if (!copyVideo()) return false;
259 uint32_t elapsed = millis() - start;
260 if (elapsed < video_interval_ms) delay(video_interval_ms - elapsed);
261 return true;
262 }
263};
264
265} // 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:98
void setAudioInfo(AudioInfo from) override
Defines the sample rate, number of channels and bits per sample.
Definition AudioCodecsBase.h:107
virtual void setOutput(Print &out_stream) override
Default output assignment (encoders may override to store Print reference)
Definition AudioCodecsBase.h:110
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:131
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
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:59
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:150
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:202
VideoEncoder * p_video_encoder
Definition VideoMuxer.h:195
bool have_video
Definition VideoMuxer.h:198
Muxer * p_muxer
Definition VideoMuxer.h:189
uint32_t sample_rate
Definition VideoMuxer.h:201
float video_fps
Definition VideoMuxer.h:199
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:196
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:192
bool have_audio
Definition VideoMuxer.h:197
uint32_t video_interval_ms
Definition VideoMuxer.h:200
bool copyVideoPaced()
Definition VideoMuxer.h:256
void setVideoSource(VideoFrameSource &video)
Definition VideoMuxer.h:82
AudioInfoSupport * p_source_audio_info
Definition VideoMuxer.h:193
static constexpr size_t kAudioReadChunkSize
Definition VideoMuxer.h:187
void end()
Closes the Muxer.
Definition VideoMuxer.h:168
size_t copyAudio()
Definition VideoMuxer.h:206
AudioEncoder * p_audio_encoder
Definition VideoMuxer.h:191
uint64_t audio_samples_written
Definition VideoMuxer.h:203
uint32_t video_frame_count
Definition VideoMuxer.h:204
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:180
VideoFrameSource * p_video
Definition VideoMuxer.h:194
Stream * p_audio
Definition VideoMuxer.h:190
bool copyVideo()
Definition VideoMuxer.h:233
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:86
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:361
@ Audio
Definition Video.h:19
@ Video
Definition Video.h:19
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:389
AudioFormat format
Definition AudioFormat.h:398
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:51
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:53
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:55
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:57
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 Video.h:102
float fps
Definition Video.h:109
uint16_t height
Frame height in pixels.
Definition Video.h:106
uint16_t width
Frame width in pixels.
Definition Video.h:104
VideoFormat format
Video codec - VideoFormat::UNKNOWN if not (yet) determined.
Definition Video.h:111