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;
117 const char *
mime()
override {
return "video/mpeg"; }
196 size_t write(
const uint8_t *data,
size_t len)
override {
244 if (!(buf[0] == 0 && buf[1] == 0 && buf[2] == 1)) {
266 LOGI(
"MPEG_program_end_code");
272 if (
id >= 0xC0 &&
id <= 0xDF)
return parsePes(
id,
false);
273 if (
id >= 0xE0 &&
id <= 0xEF)
return parsePes(
id,
true);
290 uint16_t header_length = ((uint16_t)buf[4] << 8) | buf[5];
291 size_t total = 6 + header_length;
303 uint16_t len = ((uint16_t)buf[4] << 8) | buf[5];
305 if (len == 0)
return true;
319 uint16_t pes_len = ((uint16_t)buf[4] << 8) | buf[5];
320 uint8_t peek = buf[6];
323 bool has_pts =
false;
326 }
else if ((peek >> 4) == 0x02) {
329 }
else if ((peek >> 4) == 0x03) {
333 LOGW(
"DemuxerMPG: unsupported PES optional header 0x%02X - treating as no-timestamp",
345 bool is_unbounded =
false;
346 size_t payload_len = 0;
349 is_unbounded = isVideo;
350 }
else if (pes_len < optional_len) {
353 payload_len = (size_t)pes_len - optional_len;
356 if (isVideo && has_pts) {
420 ts |= ((uint64_t)(p[0] >> 1) & 0x07) << 30;
421 ts |= ((uint64_t)((((uint16_t)p[1] << 8) | p[2]) >> 1) & 0x7FFF) << 15;
422 ts |= (uint64_t)((((uint16_t)p[3] << 8) | p[4]) >> 1) & 0x7FFF;
433 if (take > len) take = len;
434 for (
size_t i = 0; i < take; i++) {
440 for (
size_t i = 0; i + 7 < n; i++) {
445 video_width = (uint16_t)(((uint16_t)b0 << 4) | (b1 >> 4));
446 video_height = (uint16_t)(((uint16_t)(b1 & 0x0F) << 8) | b2);
447 static const float rates[16] = {0, 23.976f, 24.0f, 25.0f,
448 29.97f, 30.0f, 50.0f, 59.94f,
466 size_t take = old_size < 4 ? 4 - old_size : 0;
467 if (take > len) take = len;
468 for (
size_t i = 0; i < take; i++) {
476 if (b0 == 0xFF && (b1 & 0xE0) == 0xE0) {
477 uint8_t version = (b1 >> 3) & 0x03;
478 uint8_t sr_index = (b2 >> 2) & 0x03;
479 uint8_t mode = (b3 >> 6) & 0x03;
480 static const uint32_t rates_v1[4] = {44100, 48000, 32000, 0};
481 static const uint32_t rates_v2[4] = {22050, 24000, 16000, 0};
482 static const uint32_t rates_v25[4] = {11025, 12000, 8000, 0};
485 rate = rates_v1[sr_index];
486 else if (version == 0x02)
487 rate = rates_v2[sr_index];
488 else if (version == 0x00)
489 rate = rates_v25[sr_index];
575 const char *
mime()
override {
return "video/mpeg"; }
601 if (
p_out ==
nullptr) {
602 LOGE(
"output not defined");
628 static const uint8_t end_code[4] = {0x00, 0x00, 0x01,
639 size_t write(
const uint8_t *data,
size_t len)
override {
652 bool isKeyFrame =
true)
override {
654 if (!
is_open || data ==
nullptr || len == 0)
return 0;
664 LOGW(
"MuxerMPG: MJPEG is not supported by MPEG-1 Program Stream");
668 LOGW(
"MuxerMPG: raw YUV422 is not supported by MPEG-1 Program Stream");
672 LOGW(
"MuxerMPG: raw RGB565 is not supported by MPEG-1 Program Stream");
676 LOGW(
"MuxerMPG: raw I420 is not supported by MPEG-1 Program Stream");
737 b[0] = (uint8_t)(0x20 | (((scr >> 30) & 0x07) << 1) | 0x01);
738 b[1] = (uint8_t)((scr >> 22) & 0xFF);
739 b[2] = (uint8_t)((((scr >> 15) & 0x7F) << 1) | 0x01);
740 b[3] = (uint8_t)((scr >> 7) & 0xFF);
741 b[4] = (uint8_t)(((scr & 0x7F) << 1) | 0x01);
742 b[5] = (uint8_t)(0x80 | ((
MUX_RATE >> 15) & 0x7F));
743 b[6] = (uint8_t)((
MUX_RATE >> 7) & 0xFF);
744 b[7] = (uint8_t)(((
MUX_RATE & 0x7F) << 1) | 0x01);
751 uint16_t bound = isVideo ? 46 : 4;
754 b[1] = (uint8_t)(0xC0 | (isVideo ? 0x20 : 0x00) | ((bound >> 8) & 0x1F));
755 b[2] = (uint8_t)(bound & 0xFF);
760 int num_streams = 1 + (
has_audio ? 1 : 0);
761 uint16_t header_length = (uint16_t)(6 + 3 * num_streams);
762 static const uint8_t start[4] = {0x00, 0x00, 0x01,
765 uint8_t len_b[2] = {(uint8_t)(header_length >> 8),
766 (uint8_t)header_length};
769 uint16_t audio_bound =
has_audio ? 1 : 0;
770 uint16_t video_bound = 1;
773 b[0] = (uint8_t)(0x80 | ((
MUX_RATE >> 15) & 0x7F));
774 b[1] = (uint8_t)((
MUX_RATE >> 7) & 0xFF);
775 b[2] = (uint8_t)(((
MUX_RATE & 0x7F) << 1) | 0x01);
777 b[3] = (uint8_t)((audio_bound & 0x3F) << 2);
779 b[4] = (uint8_t)(0x20 | (video_bound & 0x1F));
789 b[0] = (uint8_t)((id4 << 4) | (((ts >> 30) & 0x07) << 1) | 0x01);
790 uint16_t mid = (uint16_t)((((ts >> 15) & 0x7FFF) << 1) | 0x01);
791 uint16_t low = (uint16_t)(((ts & 0x7FFF) << 1) | 0x01);
792 b[1] = (uint8_t)(mid >> 8);
794 b[3] = (uint8_t)(low >> 8);
801 size_t len,
bool withPts, uint64_t pts) {
803 uint16_t optional_len = withPts ? 5 : 1;
804 uint16_t pes_len = (uint16_t)(len + optional_len);
809 (uint8_t)(pes_len >> 8),
820 static const uint8_t no_ts = 0x0F;
835 size_t chunk = len - offset;
841 }
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:19
@ Audio
Definition Video.h:19
@ Video
Definition Video.h:19