arduino-audio-tools
Loading...
Searching...
No Matches
Video.h
Go to the documentation of this file.
1#pragma once
5#include "stdint.h"
6
13namespace audio_tools {
14
20
43enum class VideoFormat {
44 H264,
45 MJPEG,
46 MPEG4,
47 RAW,
48 YUV422,
49 RGB565,
50 RGB666,
51 RGB888,
52 I420,
53 MPEG1,
55};
56
61inline size_t videoFrameSizeBytes(VideoFormat format, uint16_t width,
62 uint16_t height) {
63 size_t px = (size_t)width * (size_t)height;
64 switch (format) {
68 return px * 3;
71 return px * 2;
73 return px + px / 2;
74 default:
75 return 0;
76 }
77}
78
86inline bool isH264KeyFrame(const uint8_t* data, size_t len) {
87 for (size_t i = 0; i + 3 < len; i++) {
88 if (data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1) {
89 if ((data[i + 3] & 0x1F) == 5) return true; // IDR slice
90 i += 2;
91 }
92 }
93 return false;
94}
95
105inline bool isMpeg1KeyFrame(const uint8_t* data, size_t len) {
106 for (size_t i = 0; i + 5 < len; i++) {
107 if (data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1 &&
108 data[i + 3] == 0x00) {
109 return ((data[i + 5] >> 3) & 0x07) == 1; // I-picture
110 }
111 }
112 return false;
113}
114
121struct VideoInfo {
123 uint16_t width = 0;
125 uint16_t height = 0;
128 float fps = 0;
134 uint32_t frame_size = 0;
140 uint32_t total_file_size = 0;
141
142 bool operator==(const VideoInfo& alt) const {
143 return width == alt.width && height == alt.height && fps == alt.fps &&
144 format == alt.format && frame_size == alt.frame_size &&
146 }
147 bool operator!=(const VideoInfo& alt) const { return !(*this == alt); }
149 operator bool() const { return width > 0 && height > 0; }
150 void logInfo(const char* source = "") {
151 LOGI(
152 "%s width: %d / height: %d / fps: %f / format: %d / frame_size: %d / "
153 "total_file_size: %d",
154 source, (int)width, (int)height, fps, (int)format, (int)frame_size,
155 (int)total_file_size);
156 }
157};
158
171 public:
172 virtual ~VideoFrameSource() = default;
177 virtual const uint8_t* nextFrame(size_t& len) = 0;
183 virtual VideoInfo videoInfo() = 0;
184
186 bool writeTo(Print& out) {
187 size_t len;
188 const uint8_t* frame = nextFrame(len);
189 if (frame == nullptr || len == 0) return false;
190 size_t written = out.write(frame, len);
191 return written = len;
192 }
193};
194
196 public:
197 virtual VideoInfo videoInfo() = 0;
198};
199
211 public:
212 virtual size_t write(const uint8_t* data, size_t len) = 0;
216 virtual void flush() {}
224 virtual void setSkipRender(bool skip) {}
225
238 virtual bool isKeyFrame(const uint8_t* data, size_t len) { return false; }
239
241 virtual uint32_t getWriteTimeMs() const { return 0; }
242
255 virtual bool hadOutput() const { return true; }
256};
257
258
287 public:
289 VideoFrameMeter(Print& target) : p_target(&target) {}
290
299
300 size_t write(const uint8_t* data, size_t len) override {
301 uint32_t now = millis();
302 if (has_last_call) {
304 }
305 last_call_ms = now;
306 has_last_call = true;
307
308 // VideoOutput and Print are unrelated types (no common base), so the
309 // constructor that received a VideoOutput& only has somewhere to
310 // store it as p_target_video, not p_target - check that one first.
311 uint32_t forwardStart = millis();
312 size_t result = 0;
313 if (p_target_video != nullptr) {
314 result = p_target_video->write(data, len);
315 } else if (p_target != nullptr) {
316 result = p_target->write(data, len);
317 }
318 total_forward_ms += millis() - forwardStart;
319
320 count_++;
321 return result;
322 }
323
324 void flush() override {
325 if (p_target_video != nullptr) p_target_video->flush();
326 }
327 void setSkipRender(bool skip) override {
328 if (p_target_video != nullptr) p_target_video->setSkipRender(skip);
329 }
330
332 uint32_t count() const { return count_; }
333
334 float fpsMax() const {
335 return count_ > 0 && total_forward_ms > 0
336 ? (1000.0f * count_) / total_forward_ms
337 : 0.0f;
338 }
339
340 float fpsAvg() const {
341 return count_ > 1 && total_turnaround_ms > 0
342 ? (1000.0f * (count_ - 1)) / total_turnaround_ms
343 : 0.0f;
344 }
345
350 float timeWriteMs() const {
351 return count_ > 0 ? (float)total_forward_ms / count_ : 0.0f;
352 }
353
358 float timeTurnaroundMs() const {
359 return count_ > 1 ? (float)total_turnaround_ms / (count_ - 1) : 0.0f;
360 }
361
371 Print& asPrint() { return print_view_; }
372
373 protected:
374 class PrintView : public Print {
375 public:
376 explicit PrintView(VideoFrameMeter& meter) : meter_(meter) {}
377 size_t write(const uint8_t* data, size_t len) override {
378 return meter_.write(data, len);
379 }
380 size_t write(uint8_t b) override { return meter_.write(&b, 1); }
381
382 private:
383 VideoFrameMeter& meter_;
384 };
385
386 Print* p_target = nullptr;
388 uint32_t count_ = 0;
389 uint32_t last_call_ms = 0;
390 bool has_last_call = false;
391 uint32_t total_forward_ms = 0;
394};
395
396} // namespace audio_tools
397
398// PacedVideoOutput derives from VideoOutput (defined above), so this must
399// come after the closing brace - see PacedVideoOutput.h's
400// own #include "AudioTools/Video/Video.h" for the other half of this
401// mutually-including-but-order-safe-via-pragma-once pair.
#define LOGI(...)
Definition AudioLoggerIDF.h:28
Definition Arduino.h:56
virtual size_t write(const uint8_t *data, size_t len)
Definition Arduino.h:120
size_t write(uint8_t b) override
Definition Video.h:380
PrintView(VideoFrameMeter &meter)
Definition Video.h:376
size_t write(const uint8_t *data, size_t len) override
Definition Video.h:377
Transparent write() wrapper that measures throughput/turnaround while forwarding every call unchanged...
Definition Video.h:286
void flush() override
Definition Video.h:324
uint32_t count() const
Total number of write() calls forwarded so far.
Definition Video.h:332
float timeWriteMs() const
Definition Video.h:350
uint32_t last_call_ms
Definition Video.h:389
bool has_last_call
Definition Video.h:390
uint32_t count_
Definition Video.h:388
float fpsAvg() const
Definition Video.h:340
size_t write(const uint8_t *data, size_t len) override
Definition Video.h:300
PrintView print_view_
Definition Video.h:393
VideoFrameMeter(VideoOutput &target)
Definition Video.h:298
uint32_t total_turnaround_ms
Definition Video.h:392
VideoFrameMeter(Print &target)
Definition Video.h:289
void setSkipRender(bool skip) override
Definition Video.h:327
VideoOutput * p_target_video
Definition Video.h:387
float timeTurnaroundMs() const
Definition Video.h:358
Print & asPrint()
Definition Video.h:371
Print * p_target
Definition Video.h:386
float fpsMax() const
Definition Video.h:334
uint32_t total_forward_ms
Definition Video.h:391
Pull-based provider of one already-encoded video/image frame at a time - e.g. wraps a camera capture ...
Definition Video.h:170
virtual const uint8_t * nextFrame(size_t &len)=0
bool writeTo(Print &out)
Write the frame to the indicated destination.
Definition Video.h:186
virtual ~VideoFrameSource()=default
virtual VideoInfo videoInfo()=0
Definition Video.h:195
virtual VideoInfo videoInfo()=0
Abstract class for video playback. This class is used to assemble a complete video frame in memory....
Definition Video.h:210
virtual size_t write(const uint8_t *data, size_t len)=0
virtual bool hadOutput() const
Definition Video.h:255
virtual uint32_t getWriteTimeMs() const
Optional: returns the time (ms) spent in the last write() call.
Definition Video.h:241
virtual void setSkipRender(bool skip)
Definition Video.h:224
virtual void flush()
Definition Video.h:216
virtual bool isKeyFrame(const uint8_t *data, size_t len)
Definition Video.h:238
VideoFormat
Video codec/pixel-format identifier, shared by two unrelated uses: the (single) video stream of a con...
Definition Video.h:43
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
bool isMpeg1KeyFrame(const uint8_t *data, size_t len)
True if the given MPEG-1/2 video access unit's picture header declares picture_coding_type == 1 (I-pi...
Definition Video.h:105
StreamContentType
Which track write() feeds, for muxers (MuxerAVI, MuxerMP4) that double as a plain,...
Definition Video.h:19
size_t videoFrameSizeBytes(VideoFormat format, uint16_t width, uint16_t height)
Fixed per-frame size (bytes) for a raw/uncompressed VideoFormat at the given resolution - 0 for compr...
Definition Video.h:61
@ 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
uint32_t millis()
Returns the milliseconds since the start.
Definition Arduino.h:260
Basic video information (width/height/codec/frame size), analogous to AudioInfo - common to both Demu...
Definition Video.h:121
uint32_t frame_size
Definition Video.h:134
bool operator==(const VideoInfo &alt) const
Definition Video.h:142
uint32_t total_file_size
Definition Video.h:140
float fps
Definition Video.h:128
uint16_t height
Frame height in pixels.
Definition Video.h:125
bool operator!=(const VideoInfo &alt) const
Definition Video.h:147
uint16_t width
Frame width in pixels.
Definition Video.h:123
VideoFormat format
Video codec - VideoFormat::UNKNOWN if not (yet) determined.
Definition Video.h:130
void logInfo(const char *source="")
Definition Video.h:150