57 if (count < 3 || from + 3 >
count)
return -1;
58 for (
size_t i = from; i + 2 <
count; i++) {
59 if (
vec[i] == 0 &&
vec[i + 1] == 0 &&
vec[i + 2] == 1)
return (
long)i;
118 const char *
mimeVideo()
override {
return "video/mpeg"; }
127 if (
audio_layer == 2)
return "audio/mpeg; codecs=\"mpeg1-layer2\"";
133 bool isValid(
const uint8_t *data,
size_t len)
override {
134 return len >= 4 && data[0] == 0x00 && data[1] == 0x00 &&
219 size_t write(
const uint8_t *data,
size_t len)
override {
316 if (!(buf[0] == 0 && buf[1] == 0 && buf[2] == 1)) {
337 LOGI(
"MPEG_program_end_code");
343 if (
id >= 0xC0 &&
id <= 0xDF)
return parsePes(
id,
false);
344 if (
id >= 0xE0 &&
id <= 0xEF)
return parsePes(
id,
true);
361 uint16_t header_length = ((uint16_t)buf[4] << 8) | buf[5];
362 size_t total = 6 + header_length;
374 uint16_t len = ((uint16_t)buf[4] << 8) | buf[5];
376 if (len == 0)
return true;
390 uint16_t pes_len = ((uint16_t)buf[4] << 8) | buf[5];
391 uint8_t peek = buf[6];
394 bool has_pts =
false;
397 }
else if ((peek >> 4) == 0x02) {
400 }
else if ((peek >> 4) == 0x03) {
404 LOGW(
"DemuxerMPG: unsupported PES optional header 0x%02X - treating as no-timestamp",
413 bool is_unbounded =
false;
414 size_t payload_len = 0;
417 is_unbounded = isVideo;
418 }
else if (pes_len < optional_len) {
421 payload_len = (size_t)pes_len - optional_len;
424 if (!isVideo && has_pts) {
431 if (isVideo && has_pts) {
480 size_t idPos = (size_t)idx + 3;
538 if (newCap < needed) newCap = needed;
550 if (newCap < needed) newCap = needed;
584 size_t search_from = old_len > 3 ? old_len - 3 : 0;
589 if (buf[i] == 0 && buf[i + 1] == 0 && buf[i + 2] == 1 && buf[i + 3] == 0) {
597 search_from = (size_t)idx + 4;
644 if (take > len) take = len;
645 for (
size_t i = 0; i < take; i++) {
651 for (
size_t i = 0; i + 7 < n; i++) {
656 video_width = (uint16_t)(((uint16_t)b0 << 4) | (b1 >> 4));
657 video_height = (uint16_t)(((uint16_t)(b1 & 0x0F) << 8) | b2);
658 static const float rates[16] = {0, 23.976f, 24.0f, 25.0f,
659 29.97f, 30.0f, 50.0f, 59.94f,
677 size_t take = old_size < 4 ? 4 - old_size : 0;
678 if (take > len) take = len;
679 for (
size_t i = 0; i < take; i++) {
687 if (b0 == 0xFF && (b1 & 0xE0) == 0xE0) {
688 uint8_t version = (b1 >> 3) & 0x03;
689 uint8_t layer_bits = (b1 >> 1) & 0x03;
690 uint8_t sr_index = (b2 >> 2) & 0x03;
691 uint8_t mode = (b3 >> 6) & 0x03;
692 static const uint32_t rates_v1[4] = {44100, 48000, 32000, 0};
693 static const uint32_t rates_v2[4] = {22050, 24000, 16000, 0};
694 static const uint32_t rates_v25[4] = {11025, 12000, 8000, 0};
697 rate = rates_v1[sr_index];
698 else if (version == 0x02)
699 rate = rates_v2[sr_index];
700 else if (version == 0x00)
701 rate = rates_v25[sr_index];
706 static const uint8_t layers[4] = {0, 3, 2, 1};
790 const char *
mimeVideo()
override {
return "video/mpeg"; }
816 if (
p_out ==
nullptr) {
817 LOGE(
"output not defined");
843 static const uint8_t end_code[4] = {0x00, 0x00, 0x01,
854 size_t write(
const uint8_t *data,
size_t len)
override {
869 if (!
is_open || data ==
nullptr || len == 0)
return 0;
879 LOGW(
"MuxerMPG: MJPEG is not supported by MPEG-1 Program Stream");
883 LOGW(
"MuxerMPG: raw YUV422 is not supported by MPEG-1 Program Stream");
887 LOGW(
"MuxerMPG: raw RGB565 is not supported by MPEG-1 Program Stream");
891 LOGW(
"MuxerMPG: raw I420 is not supported by MPEG-1 Program Stream");
952 b[0] = (uint8_t)(0x20 | (((scr >> 30) & 0x07) << 1) | 0x01);
953 b[1] = (uint8_t)((scr >> 22) & 0xFF);
954 b[2] = (uint8_t)((((scr >> 15) & 0x7F) << 1) | 0x01);
955 b[3] = (uint8_t)((scr >> 7) & 0xFF);
956 b[4] = (uint8_t)(((scr & 0x7F) << 1) | 0x01);
957 b[5] = (uint8_t)(0x80 | ((
MUX_RATE >> 15) & 0x7F));
958 b[6] = (uint8_t)((
MUX_RATE >> 7) & 0xFF);
959 b[7] = (uint8_t)(((
MUX_RATE & 0x7F) << 1) | 0x01);
966 uint16_t bound = isVideo ? 46 : 4;
969 b[1] = (uint8_t)(0xC0 | (isVideo ? 0x20 : 0x00) | ((bound >> 8) & 0x1F));
970 b[2] = (uint8_t)(bound & 0xFF);
975 int num_streams = 1 + (
has_audio ? 1 : 0);
976 uint16_t header_length = (uint16_t)(6 + 3 * num_streams);
977 static const uint8_t start[4] = {0x00, 0x00, 0x01,
980 uint8_t len_b[2] = {(uint8_t)(header_length >> 8),
981 (uint8_t)header_length};
984 uint16_t audio_bound =
has_audio ? 1 : 0;
985 uint16_t video_bound = 1;
988 b[0] = (uint8_t)(0x80 | ((
MUX_RATE >> 15) & 0x7F));
989 b[1] = (uint8_t)((
MUX_RATE >> 7) & 0xFF);
990 b[2] = (uint8_t)(((
MUX_RATE & 0x7F) << 1) | 0x01);
992 b[3] = (uint8_t)((audio_bound & 0x3F) << 2);
994 b[4] = (uint8_t)(0x20 | (video_bound & 0x1F));
1004 b[0] = (uint8_t)((id4 << 4) | (((ts >> 30) & 0x07) << 1) | 0x01);
1005 uint16_t mid = (uint16_t)((((ts >> 15) & 0x7FFF) << 1) | 0x01);
1006 uint16_t low = (uint16_t)(((ts & 0x7FFF) << 1) | 0x01);
1007 b[1] = (uint8_t)(mid >> 8);
1008 b[2] = (uint8_t)mid;
1009 b[3] = (uint8_t)(low >> 8);
1010 b[4] = (uint8_t)low;
1016 size_t len,
bool withPts, uint64_t pts) {
1018 uint16_t optional_len = withPts ? 5 : 1;
1019 uint16_t pes_len = (uint16_t)(len + optional_len);
1020 uint8_t hdr[6] = {0,
1024 (uint8_t)(pes_len >> 8),
1035 static const uint8_t no_ts = 0x0F;
1050 size_t chunk = len - offset;
1056 }
while (offset < len);
#define LOGW(...)
Definition AudioLoggerIDF.h:29
#define LOGI(...)
Definition AudioLoggerIDF.h:28
#define LOGE(...)
Definition AudioLoggerIDF.h:30
virtual size_t write(const uint8_t *data, size_t len)
Definition Arduino.h:120
virtual void flush()
Definition Arduino.h:130
StreamContentType
Which track write() feeds, for muxers (MuxerAVI, MuxerMP4) that double as a plain,...
Definition Video.h:21
const char * toMime(AudioFormat format)
Provides the mime type for a AudioFormat wav code, or nullptr if not known/mapped.
Definition AudioFormat.h:300
@ Audio
Definition Video.h:21
@ Video
Definition Video.h:21