22#define MINIMP4_MIN(x, y) ((x) < (y) ? (x) : (y))
28#define FIX_BAD_ANDROID_META_BOX 1
30#define MAX_CHUNKS_DEPTH 64
32#define MINIMP4_MAX_SPS 32
33#define MINIMP4_MAX_PPS 256
35#define MINIMP4_TRANSCODE_SPS_ID 1
41#define MINIMP4_ALLOW_64BIT 1
43#define MP4D_TRACE_SUPPORTED 0
44#define MP4D_TRACE_TIMESTAMPS 1
47#define MP4D_INFO_SUPPORTED 1
50#define MP4D_PRINT_INFO_SUPPORTED 0
52#define MP4D_AVC_SUPPORTED 1
53#define MP4D_HEVC_SUPPORTED 1
54#define MP4D_TIMESTAMPS_SUPPORTED 1
57#define MP4D_TFDT_SUPPORT 0
63#define MP4_OBJECT_TYPE_AUDIO_ISO_IEC_14496_3 0x40
65#define MP4_OBJECT_TYPE_AUDIO_ISO_IEC_13818_7_MAIN_PROFILE 0x66
67#define MP4_OBJECT_TYPE_AUDIO_ISO_IEC_13818_7_LC_PROFILE 0x67
69#define MP4_OBJECT_TYPE_AUDIO_ISO_IEC_13818_7_SSR_PROFILE 0x68
71#define MP4_OBJECT_TYPE_AVC 0x21
73#define MP4_OBJECT_TYPE_HEVC 0x23
75#define MP4_OBJECT_TYPE_USER_PRIVATE 0xC0
80#define MP4E_STATUS_OK 0
81#define MP4E_STATUS_BAD_ARGUMENTS -1
82#define MP4E_STATUS_NO_MEMORY -2
83#define MP4E_STATUS_FILE_WRITE_ERROR -3
84#define MP4E_STATUS_ONLY_ONE_DSI_ALLOWED -4
89#define MP4E_SAMPLE_DEFAULT 0
90#define MP4E_SAMPLE_RANDOM_ACCESS 1
91#define MP4E_SAMPLE_CONTINUATION 2
97#if MINIMP4_ALLOW_64BIT
108#define MP4D_HANDLER_TYPE_VIDE 0x76696465
110#define MP4D_HANDLER_TYPE_SOUN 0x736F756E
113#define MP4E_HANDLER_TYPE_GESM 0x6765736D
115#define HEVC_NAL_VPS 32
116#define HEVC_NAL_SPS 33
117#define HEVC_NAL_PPS 34
118#define HEVC_NAL_BLA_W_LP 16
119#define HEVC_NAL_CRA_NUT 21
132 unsigned object_type_indication;
135 unsigned char language[4];
141 unsigned default_duration;
146 unsigned channelcount;
165 unsigned sample_count;
192 unsigned object_type_indication;
194#if MP4D_INFO_SUPPORTED
203 unsigned handler_type;
206 unsigned duration_hi;
207 unsigned duration_lo;
213 unsigned avg_bitrate_bps;
216 unsigned char language[4];
229 unsigned stream_type;
234 unsigned channelcount;
235 unsigned samplerate_hz;
249 unsigned* entry_size;
251 unsigned sample_to_chunk_count;
254 unsigned chunk_count;
273#if MP4D_TIMESTAMPS_SUPPORTED
298#if MP4D_INFO_SUPPORTED
312 unsigned char*
title;
314 unsigned char*
album;
317 unsigned char*
genre;
340#if MINIMP4_TRANSCODE_SPS_ID
350 const unsigned char* nal,
352 unsigned timeStamp90kHz_next);
383 unsigned int nsample,
384 unsigned int* frame_bytes,
407#if MP4D_PRINT_INFO_SUPPORTED
427 int enable_fragmentation,
452 MP4E_mux_t* mux,
int track_num,
const void*
data,
int data_bytes,
int duration,
int kind);
507#if defined(MINIMP4_IMPLEMENTATION) && !defined(MINIMP4_IMPLEMENTATION_GUARD)
508#define MINIMP4_IMPLEMENTATION_GUARD
510#define FOUR_CHAR_INT(a, b, c, d) (((uint32_t)(a) << 24) | ((b) << 16) | ((c) << 8) | (d))
512 BOX_co64 = FOUR_CHAR_INT(
'c',
'o',
'6',
'4'),
513 BOX_stco = FOUR_CHAR_INT(
's',
't',
'c',
'o'),
514 BOX_crhd = FOUR_CHAR_INT(
'c',
'r',
'h',
'd'),
515 BOX_ctts = FOUR_CHAR_INT(
'c',
't',
't',
's'),
516 BOX_cprt = FOUR_CHAR_INT(
'c',
'p',
'r',
't'),
517 BOX_url_ = FOUR_CHAR_INT(
'u',
'r',
'l',
' '),
518 BOX_urn_ = FOUR_CHAR_INT(
'u',
'r',
'n',
' '),
519 BOX_dinf = FOUR_CHAR_INT(
'd',
'i',
'n',
'f'),
520 BOX_dref = FOUR_CHAR_INT(
'd',
'r',
'e',
'f'),
521 BOX_stdp = FOUR_CHAR_INT(
's',
't',
'd',
'p'),
522 BOX_edts = FOUR_CHAR_INT(
'e',
'd',
't',
's'),
523 BOX_elst = FOUR_CHAR_INT(
'e',
'l',
's',
't'),
524 BOX_uuid = FOUR_CHAR_INT(
'u',
'u',
'i',
'd'),
525 BOX_free = FOUR_CHAR_INT(
'f',
'r',
'e',
'e'),
526 BOX_hdlr = FOUR_CHAR_INT(
'h',
'd',
'l',
'r'),
527 BOX_hmhd = FOUR_CHAR_INT(
'h',
'm',
'h',
'd'),
528 BOX_hint = FOUR_CHAR_INT(
'h',
'i',
'n',
't'),
529 BOX_mdia = FOUR_CHAR_INT(
'm',
'd',
'i',
'a'),
530 BOX_mdat = FOUR_CHAR_INT(
'm',
'd',
'a',
't'),
531 BOX_mdhd = FOUR_CHAR_INT(
'm',
'd',
'h',
'd'),
532 BOX_minf = FOUR_CHAR_INT(
'm',
'i',
'n',
'f'),
533 BOX_moov = FOUR_CHAR_INT(
'm',
'o',
'o',
'v'),
534 BOX_mvhd = FOUR_CHAR_INT(
'm',
'v',
'h',
'd'),
535 BOX_stsd = FOUR_CHAR_INT(
's',
't',
's',
'd'),
536 BOX_stsz = FOUR_CHAR_INT(
's',
't',
's',
'z'),
537 BOX_stz2 = FOUR_CHAR_INT(
's',
't',
'z',
'2'),
538 BOX_stbl = FOUR_CHAR_INT(
's',
't',
'b',
'l'),
539 BOX_stsc = FOUR_CHAR_INT(
's',
't',
's',
'c'),
540 BOX_stsh = FOUR_CHAR_INT(
's',
't',
's',
'h'),
541 BOX_skip = FOUR_CHAR_INT(
's',
'k',
'i',
'p'),
542 BOX_smhd = FOUR_CHAR_INT(
's',
'm',
'h',
'd'),
543 BOX_stss = FOUR_CHAR_INT(
's',
't',
's',
's'),
544 BOX_stts = FOUR_CHAR_INT(
's',
't',
't',
's'),
545 BOX_trak = FOUR_CHAR_INT(
't',
'r',
'a',
'k'),
546 BOX_tkhd = FOUR_CHAR_INT(
't',
'k',
'h',
'd'),
547 BOX_tref = FOUR_CHAR_INT(
't',
'r',
'e',
'f'),
548 BOX_udta = FOUR_CHAR_INT(
'u',
'd',
't',
'a'),
549 BOX_vmhd = FOUR_CHAR_INT(
'v',
'm',
'h',
'd'),
550 BOX_url = FOUR_CHAR_INT(
'u',
'r',
'l',
' '),
551 BOX_urn = FOUR_CHAR_INT(
'u',
'r',
'n',
' '),
553 BOX_gnrv = FOUR_CHAR_INT(
'g',
'n',
'r',
'v'),
554 BOX_gnra = FOUR_CHAR_INT(
'g',
'n',
'r',
'a'),
557 BOX_ftyp = FOUR_CHAR_INT(
'f',
't',
'y',
'p'),
558 BOX_padb = FOUR_CHAR_INT(
'p',
'a',
'd',
'b'),
561 BOX_sdhd = FOUR_CHAR_INT(
's',
'd',
'h',
'd'),
562 BOX_dpnd = FOUR_CHAR_INT(
'd',
'p',
'n',
'd'),
563 BOX_iods = FOUR_CHAR_INT(
'i',
'o',
'd',
's'),
564 BOX_odhd = FOUR_CHAR_INT(
'o',
'd',
'h',
'd'),
565 BOX_mpod = FOUR_CHAR_INT(
'm',
'p',
'o',
'd'),
566 BOX_nmhd = FOUR_CHAR_INT(
'n',
'm',
'h',
'd'),
567 BOX_esds = FOUR_CHAR_INT(
'e',
's',
'd',
's'),
568 BOX_sync = FOUR_CHAR_INT(
's',
'y',
'n',
'c'),
569 BOX_ipir = FOUR_CHAR_INT(
'i',
'p',
'i',
'r'),
570 BOX_mp4s = FOUR_CHAR_INT(
'm',
'p',
'4',
's'),
571 BOX_mp4a = FOUR_CHAR_INT(
'm',
'p',
'4',
'a'),
572 BOX_mp4v = FOUR_CHAR_INT(
'm',
'p',
'4',
'v'),
575 BOX_avc1 = FOUR_CHAR_INT(
'a',
'v',
'c',
'1'),
576 BOX_avc2 = FOUR_CHAR_INT(
'a',
'v',
'c',
'2'),
577 BOX_svc1 = FOUR_CHAR_INT(
's',
'v',
'c',
'1'),
578 BOX_avcC = FOUR_CHAR_INT(
'a',
'v',
'c',
'C'),
579 BOX_svcC = FOUR_CHAR_INT(
's',
'v',
'c',
'C'),
580 BOX_btrt = FOUR_CHAR_INT(
'b',
't',
'r',
't'),
581 BOX_m4ds = FOUR_CHAR_INT(
'm',
'4',
'd',
's'),
582 BOX_seib = FOUR_CHAR_INT(
's',
'e',
'i',
'b'),
585 BOX_hev1 = FOUR_CHAR_INT(
'h',
'e',
'v',
'1'),
586 BOX_hvc1 = FOUR_CHAR_INT(
'h',
'v',
'c',
'1'),
587 BOX_hvcC = FOUR_CHAR_INT(
'h',
'v',
'c',
'C'),
590 BOX_samr = FOUR_CHAR_INT(
's',
'a',
'm',
'r'),
591 BOX_sawb = FOUR_CHAR_INT(
's',
'a',
'w',
'b'),
592 BOX_damr = FOUR_CHAR_INT(
'd',
'a',
'm',
'r'),
593 BOX_s263 = FOUR_CHAR_INT(
's',
'2',
'6',
'3'),
594 BOX_d263 = FOUR_CHAR_INT(
'd',
'2',
'6',
'3'),
597 BOX_mvex = FOUR_CHAR_INT(
'm',
'v',
'e',
'x'),
598 BOX_trex = FOUR_CHAR_INT(
't',
'r',
'e',
'x'),
599 BOX_moof = FOUR_CHAR_INT(
'm',
'o',
'o',
'f'),
600 BOX_mfhd = FOUR_CHAR_INT(
'm',
'f',
'h',
'd'),
601 BOX_traf = FOUR_CHAR_INT(
't',
'r',
'a',
'f'),
602 BOX_tfhd = FOUR_CHAR_INT(
't',
'f',
'h',
'd'),
603 BOX_tfdt = FOUR_CHAR_INT(
't',
'f',
'd',
't'),
604 BOX_trun = FOUR_CHAR_INT(
't',
'r',
'u',
'n'),
605 BOX_mehd = FOUR_CHAR_INT(
'm',
'e',
'h',
'd'),
610 OD_BASE = FOUR_CHAR_INT(
'$',
'$',
'$',
'0'),
611 OD_ESD = FOUR_CHAR_INT(
'$',
'$',
'$',
'3'),
612 OD_DCD = FOUR_CHAR_INT(
'$',
'$',
'$',
'4'),
613 OD_DSI = FOUR_CHAR_INT(
'$',
'$',
'$',
'5'),
614 OD_SLC = FOUR_CHAR_INT(
'$',
'$',
'$',
'6'),
616 BOX_meta = FOUR_CHAR_INT(
'm',
'e',
't',
'a'),
617 BOX_ilst = FOUR_CHAR_INT(
'i',
'l',
's',
't'),
620 BOX_calb = FOUR_CHAR_INT(
'\xa9',
'a',
'l',
'b'),
621 BOX_cart = FOUR_CHAR_INT(
'\xa9',
'a',
'r',
't'),
622 BOX_aART = FOUR_CHAR_INT(
'a',
'A',
'R',
'T'),
623 BOX_ccmt = FOUR_CHAR_INT(
'\xa9',
'c',
'm',
't'),
624 BOX_cday = FOUR_CHAR_INT(
'\xa9',
'd',
'a',
'y'),
625 BOX_cnam = FOUR_CHAR_INT(
'\xa9',
'n',
'a',
'm'),
626 BOX_cgen = FOUR_CHAR_INT(
'\xa9',
'g',
'e',
'n'),
627 BOX_trkn = FOUR_CHAR_INT(
't',
'r',
'k',
'n'),
628 BOX_disk = FOUR_CHAR_INT(
'd',
'i',
's',
'k'),
629 BOX_cwrt = FOUR_CHAR_INT(
'\xa9',
'w',
'r',
't'),
630 BOX_ctoo = FOUR_CHAR_INT(
'\xa9',
't',
'o',
'o'),
631 BOX_tmpo = FOUR_CHAR_INT(
't',
'm',
'p',
'o'),
632 BOX_cpil = FOUR_CHAR_INT(
'c',
'p',
'i',
'l'),
633 BOX_covr = FOUR_CHAR_INT(
'c',
'o',
'v',
'r'),
634 BOX_rtng = FOUR_CHAR_INT(
'r',
't',
'n',
'g'),
635 BOX_cgrp = FOUR_CHAR_INT(
'\xa9',
'g',
'r',
'p'),
636 BOX_stik = FOUR_CHAR_INT(
641 BOX_pcst = FOUR_CHAR_INT(
'p',
'c',
's',
't'),
642 BOX_catg = FOUR_CHAR_INT(
'c',
'a',
't',
'g'),
643 BOX_keyw = FOUR_CHAR_INT(
'k',
'e',
'y',
'w'),
644 BOX_purl = FOUR_CHAR_INT(
'p',
'u',
'r',
'l'),
645 BOX_egid = FOUR_CHAR_INT(
'e',
'g',
'i',
'd'),
646 BOX_desc = FOUR_CHAR_INT(
'd',
'e',
's',
'c'),
647 BOX_clyr = FOUR_CHAR_INT(
'\xa9',
'l',
'y',
'r'),
648 BOX_tven = FOUR_CHAR_INT(
't',
'v',
'e',
'n'),
649 BOX_tves = FOUR_CHAR_INT(
't',
'v',
'e',
's'),
650 BOX_tvnn = FOUR_CHAR_INT(
't',
'v',
'n',
'n'),
651 BOX_tvsh = FOUR_CHAR_INT(
't',
'v',
's',
'h'),
652 BOX_tvsn = FOUR_CHAR_INT(
't',
'v',
's',
'n'),
653 BOX_purd = FOUR_CHAR_INT(
'p',
'u',
'r',
'd'),
654 BOX_pgap = FOUR_CHAR_INT(
'p',
'g',
'a',
'p'),
657 BOX_cART = FOUR_CHAR_INT(
'\xa9',
'A',
'R',
'T'),
658 BOX_gnre = FOUR_CHAR_INT(
'g',
'n',
'r',
'e'),
661 BOX_auth = FOUR_CHAR_INT(
'a',
'u',
't',
'h'),
662 BOX_titl = FOUR_CHAR_INT(
't',
'i',
't',
'l'),
663 BOX_dscp = FOUR_CHAR_INT(
'd',
's',
'c',
'p'),
664 BOX_perf = FOUR_CHAR_INT(
'p',
'e',
'r',
'f'),
665 BOX_mean = FOUR_CHAR_INT(
'm',
'e',
'a',
'n'),
666 BOX_name = FOUR_CHAR_INT(
'n',
'a',
'm',
'e'),
667 BOX_data = FOUR_CHAR_INT(
'd',
'a',
't',
'a'),
670 BOX_albm = FOUR_CHAR_INT(
'a',
'l',
'b',
'm'),
671 BOX_yrrc = FOUR_CHAR_INT(
'y',
'r',
'r',
'c')
675#define MP4E_HANDLER_TYPE_VIDE 0x76696465
677#define MP4E_HANDLER_TYPE_SOUN 0x736F756E
680#define MP4E_HANDLER_TYPE_GESM 0x6765736D
686 unsigned flag_random_access;
697 minimp4_vector_t smpl;
698 minimp4_vector_t pending_sample;
700 minimp4_vector_t vsps;
701 minimp4_vector_t vpps;
702 minimp4_vector_t vvps;
706typedef struct MP4E_mux_tag {
707 minimp4_vector_t tracks;
714 int sequential_mode_flag;
715 int enable_fragmentation;
720static const unsigned char box_ftyp[] = {
722 0, 0, 0, 0x18,
'f',
't',
'y',
'p',
'm',
'p',
'4',
'2',
723 0, 0, 0, 0,
'm',
'p',
'4',
'2',
'i',
's',
'o',
'm',
726 0, 0, 0, 0x20,
'f',
't',
'y',
'p',
'i',
's',
'o',
'm', 0, 0, 2, 0,
727 'm',
'p',
'4',
'1',
'i',
's',
'o',
'm',
'i',
's',
'o',
'2',
'a',
'v',
'c',
'1',
734#define WR(x, n) *p++ = (unsigned char)((x) >> 8 * n)
735#define WRITE_1(x) WR(x, 0);
749 (p)[0] = (char)((x) >> 8 * 3); \
750 (p)[1] = (char)((x) >> 8 * 2); \
751 (p)[2] = (char)((x) >> 8 * 1); \
752 (p)[3] = (char)((x));
757 WR4((unsigned char*)*stack, p - *stack);
766#define ATOM_FULL(x, flag) \
780static int minimp4_vector_init(minimp4_vector_t*
h,
int capacity) {
782 h->capacity = capacity;
783 h->data = capacity ? (
unsigned char*)
malloc(capacity) :
NULL;
784 return !capacity || !!
h->data;
790static void minimp4_vector_reset(minimp4_vector_t*
h) {
793 memset(
h, 0,
sizeof(minimp4_vector_t));
799static int minimp4_vector_grow(minimp4_vector_t*
h,
int bytes) {
801 int new_size =
h->capacity * 2 + 1024;
802 if (new_size < h->capacity + bytes)
803 new_size =
h->capacity + bytes + 1024;
807 h->data = (
unsigned char*)p;
808 h->capacity = new_size;
817static unsigned char* minimp4_vector_alloc_tail(minimp4_vector_t*
h,
int bytes) {
819 if (!
h->data && !minimp4_vector_init(
h, 2 * bytes + 1024))
821 if ((
h->capacity -
h->bytes) < bytes && !minimp4_vector_grow(
h, bytes))
824 assert((
h->capacity -
h->bytes) >= bytes);
825 p =
h->data +
h->bytes;
833static unsigned char* minimp4_vector_put(minimp4_vector_t*
h,
const void* buf,
int bytes) {
834 unsigned char* tail = minimp4_vector_alloc_tail(
h, bytes);
836 memcpy(tail, (
void*)buf, bytes);
846 int enable_fragmentation,
854 mux->sequential_mode_flag = sequential_mode_flag || enable_fragmentation;
855 mux->enable_fragmentation = enable_fragmentation;
856 mux->fragments_count = 0;
859 mux->text_comment =
NULL;
860 mux->write_pos =
sizeof(box_ftyp);
862 if (!mux->sequential_mode_flag) {
863 if (mux->write_callback(mux->write_pos, box_ftyp, 8, mux->token)) {
867 mux->write_pos += 16;
869 minimp4_vector_init(&mux->tracks, 2 *
sizeof(track_t));
878 int ntr = mux->tracks.bytes /
sizeof(track_t);
880 if (!mux || !track_data)
883 tr = (track_t*)minimp4_vector_alloc_tail(&mux->tracks,
sizeof(track_t));
886 memset(tr, 0,
sizeof(track_t));
887 memcpy(&tr->info, (
void*)track_data,
sizeof(*track_data));
888 if (!minimp4_vector_init(&tr->smpl, 256))
890 minimp4_vector_init(&tr->vsps, 0);
891 minimp4_vector_init(&tr->vpps, 0);
892 minimp4_vector_init(&tr->pending_sample, 0);
896static const unsigned char* next_dsi(
const unsigned char* p,
const unsigned char*
end,
int* bytes) {
898 *bytes = p[0] * 256 + p[1];
904static int append_mem(minimp4_vector_t* v,
const void* mem,
int bytes) {
906 unsigned char size[2];
907 const unsigned char* p = v->data;
908 for (i = 0; i + 2 < v->bytes;) {
909 int cb = p[i] * 256 + p[i + 1];
910 if (cb == bytes && !
memcmp(p + i + 2, mem, cb))
914 size[0] = bytes >> 8;
916 return minimp4_vector_put(v,
size, 2) && minimp4_vector_put(v, mem, bytes);
919static int items_count(minimp4_vector_t* v) {
921 const unsigned char* p = v->data;
922 for (i = 0; i + 2 < v->bytes;) {
923 int cb = p[i] * 256 + p[i + 1];
931 track_t* tr = ((track_t*)mux->tracks.data) + track_id;
939 track_t* tr = ((track_t*)mux->tracks.data) + track_id;
945 track_t* tr = ((track_t*)mux->tracks.data) + track_id;
951 track_t* tr = ((track_t*)mux->tracks.data) + track_id;
956static unsigned get_duration(
const track_t* tr) {
957 unsigned i, sum_duration = 0;
958 const sample_t* s = (
const sample_t*)tr->smpl.data;
959 for (i = 0; i < tr->smpl.bytes /
sizeof(sample_t); i++) {
960 sum_duration += s[i].duration;
965static int write_pending_data(
MP4E_mux_t* mux, track_t* tr) {
967 if (tr->pending_sample.bytes > 0 && tr->smpl.bytes >=
sizeof(sample_t)) {
972 assert(mux->sequential_mode_flag);
975 assert(mux->sequential_mode_flag);
976 WRITE_4(tr->pending_sample.bytes + 8);
978 ERR(mux->write_callback(mux->write_pos,
base, p -
base, mux->token));
979 mux->write_pos += p -
base;
982 smpl_desc = ((sample_t*)minimp4_vector_alloc_tail(&tr->smpl, 0)) - 1;
983 smpl_desc->size = tr->pending_sample.bytes;
984 smpl_desc->offset = (
boxsize_t)mux->write_pos;
987 ERR(mux->write_callback(
988 mux->write_pos, tr->pending_sample.data, tr->pending_sample.bytes, mux->token));
989 mux->write_pos += tr->pending_sample.bytes;
992 tr->pending_sample.bytes = 0;
998add_sample_descriptor(
MP4E_mux_t* mux, track_t* tr,
int data_bytes,
int duration,
int kind) {
1000 smp.size = data_bytes;
1002 smp.duration = (duration ? duration : tr->info.default_duration);
1004 return NULL != minimp4_vector_put(&tr->smpl, &smp,
sizeof(sample_t));
1012static int mp4e_write_fragment_header(
MP4E_mux_t* mux,
1022 unsigned char base[888], *p =
base;
1023 unsigned char* stack_base[20];
1024 unsigned char** stack = stack_base;
1025 unsigned char* pdata_offset;
1028 default_sample_duration_present = 0x000008,
1029 default_sample_flags_present = 0x000020,
1032 track_t* tr = ((track_t*)mux->tracks.data) + track_num;
1035 ATOM_FULL(BOX_mfhd, 0)
1036 WRITE_4(mux->fragments_count);
1040 if (tr->info.track_media_kind ==
e_video)
1044 flags = (tr->info.track_media_kind ==
e_video) ? 0x20020 : 0x20008;
1046 ATOM_FULL(BOX_tfhd,
flags)
1047 WRITE_4(track_num + 1);
1048 if (tr->info.track_media_kind ==
e_video) {
1054#if MP4D_TFDT_SUPPORT
1055 ATOM_FULL(BOX_tfdt, 0x01000000)
1056 WRITE_4(timestamp >> 32);
1057 WRITE_4(timestamp & 0xffffffff);
1060 if (tr->info.track_media_kind ==
e_audio) {
1064 ATOM_FULL(BOX_trun,
flags)
1068 WRITE_4(data_bytes);
1076 ATOM_FULL(BOX_trun,
flags)
1082 WRITE_4(data_bytes);
1089 ATOM_FULL(BOX_trun,
flags)
1094 WRITE_4(data_bytes);
1099 WR4(pdata_offset, (p -
base) + 8);
1101 ERR(mux->write_callback(mux->write_pos,
base, p -
base, mux->token));
1102 mux->write_pos += p -
base;
1110 ERR(mux->write_callback(mux->write_pos,
base, p -
base, mux->token));
1111 mux->write_pos += p -
base;
1119 MP4E_mux_t* mux,
int track_num,
const void*
data,
int data_bytes,
int duration,
int kind) {
1123 tr = ((track_t*)mux->tracks.data) + track_num;
1125 if (mux->enable_fragmentation) {
1126#if MP4D_TFDT_SUPPORT
1130 if (!mux->fragments_count++)
1131 ERR(mp4e_flush_index(mux));
1133#if MP4D_TFDT_SUPPORT
1134 ERR(mp4e_write_fragment_header(mux, track_num, data_bytes, duration, kind, timestamp));
1136 ERR(mp4e_write_fragment_header(mux, track_num, data_bytes, duration, kind));
1139 ERR(mp4e_write_mdat_box(mux, data_bytes + 8));
1140 ERR(mux->write_callback(mux->write_pos,
data, data_bytes, mux->token));
1141 mux->write_pos += data_bytes;
1146 if (mux->sequential_mode_flag)
1147 ERR(write_pending_data(mux, tr));
1148 if (!add_sample_descriptor(mux, tr, data_bytes, duration, kind))
1151 if (!mux->sequential_mode_flag) {
1152 sample_t* smpl_desc;
1153 if (tr->smpl.bytes <
sizeof(sample_t))
1156 smpl_desc = (sample_t*)(tr->smpl.data + tr->smpl.bytes) - 1;
1157 smpl_desc->size += data_bytes;
1161 if (mux->sequential_mode_flag) {
1162 if (!minimp4_vector_put(&tr->pending_sample,
data, data_bytes))
1165 ERR(mux->write_callback(mux->write_pos,
data, data_bytes, mux->token));
1166 mux->write_pos += data_bytes;
1174static int od_size_of_size(
int size) {
1175 int i, size_of_size = 1;
1176 for (i =
size; i > 0x7F; i -= 0x7F)
1178 return size_of_size;
1188 if (!mux || !comment)
1190 if (mux->text_comment)
1191 free(mux->text_comment);
1192 mux->text_comment =
strdup(comment);
1193 if (!mux->text_comment)
1201static int mp4e_flush_index(
MP4E_mux_t* mux) {
1202 unsigned char* stack_base[20];
1203 unsigned char** stack = stack_base;
1204 unsigned char *
base, *p;
1205 unsigned int ntr, index_bytes, ntracks = mux->tracks.bytes /
sizeof(track_t);
1214#define FILE_HEADER_BYTES 256
1215#define TRACK_HEADER_BYTES 512
1216 index_bytes = FILE_HEADER_BYTES;
1217 if (mux->text_comment)
1218 index_bytes += 128 +
strlen(mux->text_comment);
1219 for (ntr = 0; ntr < ntracks; ntr++) {
1220 track_t* tr = ((track_t*)mux->tracks.data) + ntr;
1221 index_bytes += TRACK_HEADER_BYTES;
1223 index_bytes += tr->smpl.bytes * (
sizeof(sample_t) + 4 + 4) /
sizeof(sample_t);
1224 index_bytes += tr->vsps.bytes;
1225 index_bytes += tr->vpps.bytes;
1227 ERR(write_pending_data(mux, tr));
1235 if (!mux->sequential_mode_flag) {
1243 if (
size > size_limit) {
1246 WRITE_4((
size >> 32) & 0xffffffff);
1247 WRITE_4(
size & 0xffffffff);
1254 ERR(mux->write_callback(
sizeof(box_ftyp),
base, p -
base, mux->token));
1259#define MOOV_TIMESCALE 1000
1261 ATOM_FULL(BOX_mvhd, 0);
1266 track_t* tr = ((track_t*)mux->tracks.data) + 0;
1267 unsigned duration = get_duration(tr);
1268 duration = (unsigned)(duration * 1LL * MOOV_TIMESCALE / tr->info.time_scale);
1269 WRITE_4(MOOV_TIMESCALE);
1273 WRITE_4(0x00010000);
1280 WRITE_4(0x00010000);
1284 WRITE_4(0x00010000);
1288 WRITE_4(0x40000000);
1301 WRITE_4(ntracks + 1);
1304 for (ntr = 0; ntr < ntracks; ntr++) {
1305 track_t* tr = ((track_t*)mux->tracks.data) + ntr;
1306 unsigned duration = get_duration(tr);
1307 int samples_count = tr->smpl.bytes /
sizeof(sample_t);
1308 const sample_t*
sample = (
const sample_t*)tr->smpl.data;
1309 unsigned handler_type;
1310 const char* handler_ascii =
NULL;
1312 if (mux->enable_fragmentation)
1314 else if (samples_count <= 0)
1317 switch (tr->info.track_media_kind) {
1319 handler_type = MP4E_HANDLER_TYPE_SOUN;
1320 handler_ascii =
"SoundHandler";
1323 handler_type = MP4E_HANDLER_TYPE_VIDE;
1324 handler_ascii =
"VideoHandler";
1334 ATOM_FULL(BOX_tkhd, 7);
1339 WRITE_4((
unsigned)(duration * 1LL * MOOV_TIMESCALE / tr->info.time_scale));
1348 WRITE_4(0x00010000);
1352 WRITE_4(0x00010000);
1356 WRITE_4(0x40000000);
1358 if (tr->info.track_media_kind ==
e_audio || tr->info.track_media_kind ==
e_private) {
1362 WRITE_4(tr->info.u.v.width * 0x10000);
1363 WRITE_4(tr->info.u.v.height * 0x10000);
1368 ATOM_FULL(BOX_mdhd, 0);
1371 WRITE_4(tr->info.time_scale);
1374 int lang_code = ((tr->info.language[0] & 31) << 10) |
1375 ((tr->info.language[1] & 31) << 5) | (tr->info.language[2] & 31);
1381 ATOM_FULL(BOX_hdlr, 0);
1383 WRITE_4(handler_type);
1390 if (handler_ascii) {
1391 for (i = 0; i < (int)
strlen(handler_ascii) + 1; i++) {
1392 WRITE_1(handler_ascii[i]);
1401 if (tr->info.track_media_kind ==
e_audio) {
1403 ATOM_FULL(BOX_smhd, 0);
1408 if (tr->info.track_media_kind ==
e_video) {
1410 ATOM_FULL(BOX_vmhd, 1);
1419 ATOM_FULL(BOX_dref, 0);
1426 ATOM_FULL(BOX_url, 1);
1432 ATOM_FULL(BOX_stsd, 0);
1435 if (tr->info.track_media_kind ==
e_audio || tr->info.track_media_kind ==
e_private) {
1437 if (tr->info.track_media_kind ==
e_audio) {
1448 if (tr->info.track_media_kind ==
e_audio) {
1452 WRITE_2(tr->info.u.a.channelcount);
1455 WRITE_4((tr->info.time_scale << 16));
1458 ATOM_FULL(BOX_esds, 0);
1459 if (tr->vsps.bytes > 0) {
1460 int dsi_bytes = tr->vsps.bytes - 2;
1461 int dsi_size_size = od_size_of_size(dsi_bytes);
1462 int dcd_bytes = dsi_bytes + dsi_size_size + 1 + (1 + 1 + 3 + 4 + 4);
1463 int dcd_size_size = od_size_of_size(dcd_bytes);
1464 int esd_bytes = dcd_bytes + dcd_size_size + 1 + 3;
1466#define WRITE_OD_LEN(size) \
1471 } while (size > 0x7F); \
1474 WRITE_OD_LEN(esd_bytes);
1479 WRITE_OD_LEN(dcd_bytes);
1480 if (tr->info.track_media_kind ==
e_audio) {
1488 WRITE_3(tr->info.u.a.channelcount * 6144 /
1494 WRITE_OD_LEN(dsi_bytes);
1495 for (i = 0; i < dsi_bytes; i++) {
1496 WRITE_1(tr->vsps.data[2 + i]);
1503 if (tr->info.track_media_kind ==
e_video &&
1506 int numOfSequenceParameterSets = items_count(&tr->vsps);
1507 int numOfPictureParameterSets = items_count(&tr->vpps);
1525 WRITE_2(tr->info.u.v.width);
1526 WRITE_2(tr->info.u.v.height);
1527 WRITE_4(0x00480000);
1528 WRITE_4(0x00480000);
1531 for (i = 0; i < 32; i++) {
1541 WRITE_1(tr->vsps.data[2 + 1]);
1542 WRITE_1(tr->vsps.data[2 + 2]);
1543 WRITE_1(tr->vsps.data[2 + 3]);
1545 WRITE_1(0xe0 | numOfSequenceParameterSets);
1546 for (i = 0; i < tr->vsps.bytes; i++) {
1547 WRITE_1(tr->vsps.data[i]);
1549 WRITE_1(numOfPictureParameterSets);
1550 for (i = 0; i < tr->vpps.bytes; i++) {
1551 WRITE_1(tr->vpps.data[i]);
1554 int numOfVPS = items_count(&tr->vpps);
1559 WRITE_4(0x60000000);
1576 for (i = 0; i < tr->vvps.bytes; i++) {
1577 WRITE_1(tr->vvps.data[i]);
1580 WRITE_2(numOfSequenceParameterSets);
1581 for (i = 0; i < tr->vsps.bytes; i++) {
1582 WRITE_1(tr->vsps.data[i]);
1585 WRITE_2(numOfPictureParameterSets);
1586 for (i = 0; i < tr->vpps.bytes; i++) {
1587 WRITE_1(tr->vpps.data[i]);
1601 ATOM_FULL(BOX_stts, 0);
1603 unsigned char* pentry_count = p;
1604 int cnt = 1, entry_count = 0;
1606 for (i = 0; i < samples_count; i++, cnt++) {
1607 if (i == (samples_count - 1) ||
sample[i].duration !=
sample[i + 1].duration) {
1609 WRITE_4(
sample[i].duration);
1614 WR4(pentry_count, entry_count);
1619 ATOM_FULL(BOX_stsc, 0);
1620 if (mux->enable_fragmentation) {
1631 ATOM_FULL(BOX_stsz, 0);
1635 WRITE_4(samples_count);
1636 for (i = 0; i < samples_count; i++) {
1643 if (samples_count &&
sample[samples_count - 1].
offset > 0xffffffff)
1646 ATOM_FULL(BOX_stco, 0);
1647 WRITE_4(samples_count);
1648 for (i = 0; i < samples_count; i++) {
1652 ATOM_FULL(BOX_co64, 0);
1653 WRITE_4(samples_count);
1654 for (i = 0; i < samples_count; i++) {
1664 for (i = 0; i < samples_count; i++) {
1665 ra_count += !!
sample[i].flag_random_access;
1667 if (ra_count != samples_count) {
1669 ATOM_FULL(BOX_stss, 0);
1671 for (i = 0; i < samples_count; i++) {
1672 if (
sample[i].flag_random_access) {
1685 if (mux->text_comment) {
1687 ATOM_FULL(BOX_meta, 0);
1688 ATOM_FULL(BOX_hdlr, 0);
1690#define MP4E_HANDLER_TYPE_MDIR 0x6d646972
1691 WRITE_4(MP4E_HANDLER_TYPE_MDIR);
1703 for (i = 0; i < (int)
strlen(mux->text_comment) + 1; i++) {
1704 WRITE_1(mux->text_comment[i]);
1713 if (mux->enable_fragmentation) {
1714 track_t* tr = ((track_t*)mux->tracks.data) + 0;
1715 uint32_t movie_duration = get_duration(tr);
1718 ATOM_FULL(BOX_mehd, 0);
1719 WRITE_4(movie_duration);
1721 for (ntr = 0; ntr < ntracks; ntr++) {
1722 ATOM_FULL(BOX_trex, 0);
1736 err = mux->write_callback(mux->write_pos,
base, p -
base, mux->token);
1737 mux->write_pos += p -
base;
1744 unsigned ntr, ntracks;
1747 if (!mux->enable_fragmentation)
1748 err = mp4e_flush_index(mux);
1749 if (mux->text_comment)
1750 free(mux->text_comment);
1751 ntracks = mux->tracks.bytes /
sizeof(track_t);
1752 for (ntr = 0; ntr < ntracks; ntr++) {
1753 track_t* tr = ((track_t*)mux->tracks.data) + ntr;
1754 minimp4_vector_reset(&tr->vsps);
1755 minimp4_vector_reset(&tr->vpps);
1756 minimp4_vector_reset(&tr->smpl);
1757 minimp4_vector_reset(&tr->pending_sample);
1759 minimp4_vector_reset(&mux->tracks);
1773 int cache_free_bits;
1782 unsigned origin_bytes;
1785#define LOAD_SHORT(x) ((uint16_t)(x << 8) | (x >> 8))
1787static unsigned int show_bits(bit_reader_t* bs,
int n) {
1788 unsigned int retval;
1789 assert(n > 0 && n <= 16);
1790 retval = (
unsigned int)(bs->cache >> (32 - n));
1794static void flush_bits(bit_reader_t* bs,
int n) {
1795 assert(n >= 0 && n <= 16);
1797 bs->cache_free_bits += n;
1798 if (bs->cache_free_bits >= 0) {
1799 bs->cache |= ((
uint32_t)LOAD_SHORT(*bs->buf)) << bs->cache_free_bits;
1801 bs->cache_free_bits -= 16;
1805static unsigned int get_bits(bit_reader_t* bs,
int n) {
1806 unsigned int retval = show_bits(bs, n);
1811static void set_pos_bits(bit_reader_t* bs,
unsigned pos_bits) {
1812 assert((
int)pos_bits >= 0);
1814 bs->buf = bs->origin + pos_bits / 16;
1816 bs->cache_free_bits = 16;
1818 flush_bits(bs, pos_bits & 15);
1821static unsigned get_pos_bits(
const bit_reader_t* bs) {
1825 unsigned pos_bits = (unsigned)(bs->buf - bs->origin) * 16;
1826 pos_bits -= 16 - bs->cache_free_bits;
1827 assert((
int)pos_bits >= 0);
1831static int remaining_bits(
const bit_reader_t* bs) {
1832 return bs->origin_bytes * 8 - get_pos_bits(bs);
1835static void init_bits(bit_reader_t* bs,
const void*
data,
unsigned data_bytes) {
1837 bs->origin_bytes = data_bytes;
1838 set_pos_bits(bs, 0);
1841#define GetBits(n) get_bits(bs, n)
1846static int ue_bits(bit_reader_t* bs) {
1849 for (clz = 0; !get_bits(bs, 1); clz++) {}
1851 val = (1 << clz) - 1 + (clz ? get_bits(bs, clz) : 0);
1855#if MINIMP4_TRANSCODE_SPS_ID
1868 (uint32_t)((((x) >> 24) & 0xFF) | (((x) >> 8) & 0xFF00) | (((x) << 8) & 0xFF0000) | \
1871static void h264e_bs_put_bits(bs_t* bs,
unsigned n,
unsigned val) {
1874 assert((
unsigned)n <= 32);
1875 if (bs->shift < 0) {
1877 bs->cache |= val >> -bs->shift;
1878 *bs->buf++ = SWAP32(bs->cache);
1879 bs->shift = 32 + bs->shift;
1882 bs->cache |= val << bs->shift;
1885static void h264e_bs_flush(bs_t* bs) {
1886 *bs->buf = SWAP32(bs->cache);
1889static unsigned h264e_bs_get_pos_bits(
const bs_t* bs) {
1890 unsigned pos_bits = (unsigned)((bs->buf - bs->origin) * BS_BITS);
1891 pos_bits += BS_BITS - bs->shift;
1892 assert((
int)pos_bits >= 0);
1896static unsigned h264e_bs_byte_align(bs_t* bs) {
1897 int pos = h264e_bs_get_pos_bits(bs);
1898 h264e_bs_put_bits(bs, -pos & 7, 0);
1899 return pos + (-pos & 7);
1916static void h264e_bs_put_golomb(bs_t* bs,
unsigned val) {
1918 unsigned t = val + 1;
1923 h264e_bs_put_bits(bs, 2 *
size - 1, val + 1);
1926static void h264e_bs_init_bits(bs_t* bs,
void*
data) {
1927 bs->origin = (bs_item_t*)
data;
1928 bs->buf = bs->origin;
1929 bs->shift = BS_BITS;
1933static int find_mem_cache(
void* cache[],
int cache_bytes[],
int cache_size,
void* mem,
int bytes) {
1937 for (i = 0; i < cache_size; i++) {
1938 if (cache_bytes[i] == bytes && !
memcmp(mem, cache[i], bytes))
1941 for (i = 0; i < cache_size; i++) {
1942 if (!cache_bytes[i]) {
1943 cache[i] =
malloc(bytes);
1945 memcpy(cache[i], mem, bytes);
1946 cache_bytes[i] = bytes;
1957static int remove_nal_escapes(
unsigned char* dst,
const unsigned char* src,
int h264_data_bytes) {
1958 int i = 0, j = 0, zero_cnt = 0;
1959 for (j = 0; j < h264_data_bytes; j++) {
1960 if (zero_cnt == 2 && src[j] <= 3) {
1962 if (j == h264_data_bytes - 1) {
1964 }
else if (src[j + 1] <= 3) {
1988 int i, j = 4, cntz = 0;
1989 d[0] =
d[1] =
d[2] = 0;
1991 for (i = 0; i < n; i++) {
1993 if (cntz == 2 &&
byte <= 3) {
2006static void copy_bits(bit_reader_t* bs, bs_t* bd) {
2008 int bit_count = remaining_bits(bs);
2009 while (bit_count > 7) {
2012 h264e_bs_put_bits(bd, cb, bits);
2018 for (; bit_count && ~bits & 1; bit_count--) {
2022 h264e_bs_put_bits(bd, bit_count, bits);
2026static int change_sps_id(bit_reader_t* bs, bs_t* bd,
int new_id,
int* old_id) {
2027 unsigned bits, sps_id, i, bytes;
2028 for (i = 0; i < 3; i++) {
2030 h264e_bs_put_bits(bd, 8, bits);
2032 sps_id = ue_bits(bs);
2038 h264e_bs_put_golomb(bd, sps_id);
2041 bytes = h264e_bs_byte_align(bd) / 8;
2049 unsigned pps_id = ue_bits(bs);
2050 unsigned sps_id = ue_bits(bs);
2053 sps_id =
h->map_sps[sps_id];
2054 pps_id = new_pps_id;
2059 h264e_bs_put_golomb(bd, pps_id);
2060 h264e_bs_put_golomb(bd, sps_id);
2063 bytes = h264e_bs_byte_align(bd) / 8;
2069 unsigned first_mb_in_slice = ue_bits(bs);
2070 unsigned slice_type = ue_bits(bs);
2071 unsigned pps_id = ue_bits(bs);
2073 pps_id =
h->map_pps[pps_id];
2077 h264e_bs_put_golomb(bd, first_mb_in_slice);
2078 h264e_bs_put_golomb(bd, slice_type);
2079 h264e_bs_put_golomb(bd, pps_id);
2084 const unsigned char* src,
2086 unsigned char* dst) {
2089 bit_reader_t bst[1];
2094 int payload_type = src[0] & 31;
2097 h264e_bs_init_bits(bd, dst + 1);
2098 init_bits(bs, src + 1, nalu_bytes - 1);
2099 h264e_bs_init_bits(bdt, dst + 1);
2100 init_bits(bst, src + 1, nalu_bytes - 1);
2102 switch (payload_type) {
2104 int cb = change_sps_id(bst, bdt, 0, &old_id);
2105 int id = find_mem_cache(
h->sps_cache,
h->sps_bytes,
MINIMP4_MAX_SPS, dst + 1, cb);
2108 h->map_sps[old_id] = id;
2109 change_sps_id(bs, bd,
id, &old_id);
2112 int cb = patch_pps(
h, bst, bdt, 0, &old_id);
2113 int id = find_mem_cache(
h->pps_cache,
h->pps_bytes,
MINIMP4_MAX_PPS, dst + 1, cb);
2116 h->map_pps[old_id] = id;
2117 patch_pps(
h, bs, bd,
id, &old_id);
2122 patch_slice_header(
h, bs, bd);
2125 memcpy(dst, (
void*)src, nalu_bytes);
2129 nalu_bytes = 1 + h264e_bs_byte_align(bd) / 8;
2145static const uint8_t* find_start_code(
const uint8_t* h264_data,
int h264_data_bytes,
int* zcount) {
2146 const uint8_t* eof = h264_data + h264_data_bytes;
2151 p = found ? found : eof;
2152 while (p + zero_cnt < eof && !p[zero_cnt])
2154 if (zero_cnt >= 2 && p[zero_cnt] == 1) {
2155 *zcount = zero_cnt + 1;
2156 return p + zero_cnt + 1;
2168find_nal_unit(
const uint8_t* h264_data,
int h264_data_bytes,
int* pnal_unit_bytes) {
2169 const uint8_t* eof = h264_data + h264_data_bytes;
2171 const uint8_t* start = find_start_code(h264_data, h264_data_bytes, &zcount);
2174 stop = find_start_code(start, (
int)(eof - start), &zcount);
2175 while (stop > start && !stop[-1]) {
2180 *pnal_unit_bytes = (int)(stop - start - zcount);
2199 h->is_hevc = is_hevc;
2200 h->need_vps = is_hevc;
2204#if MINIMP4_TRANSCODE_SPS_ID
2211#if MINIMP4_TRANSCODE_SPS_ID
2227 const unsigned char* nal,
2229 unsigned timeStamp90kHz_next) {
2230 int payload_type = (nal[0] >> 1) & 0x3f;
2235 if (is_intra && !
h->need_sps && !
h->need_pps && !
h->need_vps)
2237 switch (payload_type) {
2251 if (
h->need_vps ||
h->need_sps ||
h->need_pps ||
h->need_idr)
2254 unsigned char* tmp = (
unsigned char*)
malloc(4 + sizeof_nal);
2258 tmp[0] = (
unsigned char)(sizeof_nal >> 24);
2259 tmp[1] = (
unsigned char)(sizeof_nal >> 16);
2260 tmp[2] = (
unsigned char)(sizeof_nal >> 8);
2261 tmp[3] = (
unsigned char)(sizeof_nal);
2262 memcpy(tmp + 4, (
void*)nal, sizeof_nal);
2266 h->mux,
h->mux_track_id, tmp, 4 + sizeof_nal, timeStamp90kHz_next, sample_kind);
2275 const unsigned char* nal,
2277 unsigned timeStamp90kHz_next) {
2278 const unsigned char* eof = nal + length;
2281#if MINIMP4_TRANSCODE_SPS_ID
2282 unsigned char *nal1, *nal2;
2284 nal = find_nal_unit(nal, (
int)(eof - nal), &sizeof_nal);
2288 ERR(mp4_h265_write_nal(
h, nal, sizeof_nal, timeStamp90kHz_next));
2291 payload_type = nal[0] & 31;
2292 if (9 == payload_type)
2294#if MINIMP4_TRANSCODE_SPS_ID
2299 nal1 = (
unsigned char*)
malloc(sizeof_nal * 17 / 16 + 32);
2302 nal2 = (
unsigned char*)
malloc(sizeof_nal * 17 / 16 + 32);
2307 sizeof_nal = remove_nal_escapes(nal2, nal, sizeof_nal);
2315 sizeof_nal = transcode_nalu(&
h->sps_patcher, nal2, sizeof_nal, nal1);
2316 sizeof_nal = nal_put_esc(nal2, nal1, sizeof_nal);
2318 switch (payload_type) {
2325 goto exit_with_free;
2331 goto exit_with_free;
2336 goto exit_with_free;
2337 if (!
h->need_pps && !
h->need_idr) {
2339 init_bits(bs, nal + 1, sizeof_nal - 4 - 1);
2340 unsigned first_mb_in_slice = ue_bits(bs);
2343 nal2[0] = (
unsigned char)((sizeof_nal - 4) >> 24);
2344 nal2[1] = (
unsigned char)((sizeof_nal - 4) >> 16);
2345 nal2[2] = (
unsigned char)((sizeof_nal - 4) >> 8);
2346 nal2[3] = (
unsigned char)((sizeof_nal - 4));
2347 if (first_mb_in_slice)
2349 else if (payload_type == 5)
2352 h->mux,
h->mux_track_id, nal2, sizeof_nal, timeStamp90kHz_next, sample_kind);
2361 switch (payload_type) {
2378 if (!
h->need_pps && !
h->need_idr) {
2380 unsigned char* tmp = (
unsigned char*)
malloc(4 + sizeof_nal);
2383 init_bits(bs, nal + 1, sizeof_nal - 1);
2384 unsigned first_mb_in_slice = ue_bits(bs);
2386 tmp[0] = (
unsigned char)(sizeof_nal >> 24);
2387 tmp[1] = (
unsigned char)(sizeof_nal >> 16);
2388 tmp[2] = (
unsigned char)(sizeof_nal >> 8);
2389 tmp[3] = (
unsigned char)(sizeof_nal);
2390 memcpy(tmp + 4, nal, sizeof_nal);
2391 if (first_mb_in_slice)
2393 else if (payload_type == 5)
2396 h->mux,
h->mux_track_id, tmp, 4 + sizeof_nal, timeStamp90kHz_next, sample_kind);
2408#if MP4D_TRACE_SUPPORTED
2409#define TRACE(x) printf x
2414#define NELEM(x) (sizeof(x) / sizeof((x)[0]))
2428static unsigned minimp4_read(
MP4D_demux_t* mp4,
int nb,
int* eof_flag) {
2433 v = (v << 8) | minimp4_fgets(mp4);
2435 v = (v << 8) | minimp4_fgets(mp4);
2437 v = (v << 8) | minimp4_fgets(mp4);
2440 v = (v << 8) | (last_byte = minimp4_fgets(mp4));
2442 if (last_byte < 0) {
2454 if (*payload_bytes < nb) {
2456 nb = (int)*payload_bytes;
2458 *payload_bytes -= nb;
2460 return minimp4_read(mp4, nb, eof_flag);
2473#define READ(n) read_payload(mp4, n, &payload_bytes, &eof_flag)
2476 boxsize_t t = MINIMP4_MIN(payload_bytes, n); \
2477 my_fseek(mp4, t, &eof_flag); \
2478 payload_bytes -= t; \
2492enum { MINIMP4_MAX_ALLOC_BYTES = 256u * 1024u * 1024u };
2494static void* minimp4_bounded_malloc(
size_t size) {
2495 if (
size > MINIMP4_MAX_ALLOC_BYTES)
2504#define MALLOC(t, p, size) \
2507 p = (t)minimp4_bounded_malloc(size); \
2509 ERROR("out of memory"); \
2516#define RETURN_ERROR(mess) \
2518 TRACE(("\nMP4 ERROR: " mess)); \
2526#define ERROR(mess) \
2532typedef enum { BOX_ATOM, BOX_OD } boxtype_t;
2550#if MP4D_TRACE_SUPPORTED
2560 TRACE((
"\nERROR: invlaid arguments!"));
2569 stack[0].format = BOX_ATOM;
2576 static const struct {
2578 unsigned max_version;
2579 unsigned use_track_flag;
2581#if MP4D_INFO_SUPPORTED
2589#if MP4D_TRACE_TIMESTAMPS
2607 static const struct {
2610 } g_envelope_box[] = {
2616 {BOX_trak, BOX_ATOM},
2617 {BOX_moov, BOX_ATOM},
2619 {BOX_mdia, BOX_ATOM},
2620 {BOX_tref, BOX_ATOM},
2621 {BOX_minf, BOX_ATOM},
2622 {BOX_dinf, BOX_ATOM},
2623 {BOX_stbl, BOX_ATOM},
2624 {BOX_stsd, BOX_ATOM},
2625 {BOX_mp4a, BOX_ATOM},
2626 {BOX_mp4s, BOX_ATOM},
2627#if MP4D_AVC_SUPPORTED
2628 {BOX_mp4v, BOX_ATOM},
2629 {BOX_avc1, BOX_ATOM},
2633#if MP4D_HEVC_SUPPORTED
2634 {BOX_hvc1, BOX_ATOM},
2636 {BOX_udta, BOX_ATOM},
2637 {BOX_meta, BOX_ATOM},
2638 {BOX_ilst, BOX_ATOM}};
2640 uint32_t FullAtomVersionAndFlags = 0;
2644#if MP4D_INFO_SUPPORTED
2645 unsigned char** ptag =
NULL;
2650 if (stack[depth].
format == BOX_ATOM) {
2651 box_bytes = minimp4_read(mp4, 4, &eof_flag);
2652#if FIX_BAD_ANDROID_META_BOX
2653 broken_android_meta_hack:
2658 if (box_bytes >= 2 && box_bytes < 8) {
2659 ERROR(
"invalid box size (broken file?)");
2662 box_name = minimp4_read(mp4, 4, &eof_flag);
2666 if (box_bytes == 0 ||
2673 payload_bytes = box_bytes - 8;
2677 TRACE((
"\n64-bit chunk encountered"));
2679 box_bytes = minimp4_read(mp4, 4, &eof_flag);
2680#if MP4D_64BIT_SUPPORTED
2682 box_bytes |= minimp4_read(mp4, 4, &eof_flag);
2685 ERROR(
"UNSUPPORTED FEATURE: MP4BoxHeader(): 64-bit boxes not supported!");
2687 box_bytes = minimp4_read(mp4, 4, &eof_flag);
2689 if (box_bytes < 16) {
2690 ERROR(
"invalid box size (broken file?)");
2692 payload_bytes = box_bytes - 16;
2696 for (i = 0; i < NELEM(g_fullbox); i++) {
2697 if (box_name == g_fullbox[i].
name) {
2698 FullAtomVersionAndFlags = READ(4);
2701#if FIX_BAD_ANDROID_META_BOX
2704 if (box_name == BOX_meta) {
2705 if (FullAtomVersionAndFlags >= 8 &&
2706 FullAtomVersionAndFlags < payload_bytes) {
2707 if (box_bytes > stack[depth].bytes) {
2708 ERROR(
"broken file structure!");
2710 stack[depth].bytes -= box_bytes;
2713 stack[depth].bytes = payload_bytes + 4;
2714 stack[depth].format = BOX_ATOM;
2715 box_bytes = FullAtomVersionAndFlags;
2716 TRACE((
"Bad metadata box detected (Android bug?)!\n"));
2717 goto broken_android_meta_hack;
2722 if ((FullAtomVersionAndFlags >> 24) > g_fullbox[i].max_version) {
2723 ERROR(
"unsupported box version!");
2725 if (g_fullbox[i].use_track_flag && !tr) {
2726 ERROR(
"broken file structure!");
2733 box_name = OD_BASE + minimp4_read(mp4, 1, &eof_flag);
2741 val = minimp4_read(mp4, 1, &eof_flag);
2744 ERROR(
"premature EOF!");
2746 payload_bytes = (payload_bytes << 7) | (val & 0x7F);
2748 }
while (val & 0x80);
2749 box_bytes += payload_bytes;
2752#if MP4D_TRACE_SUPPORTED
2753 box_path[depth] = (box_name >> 24) | (box_name << 24) | ((box_name >> 8) & 0x0000FF00) |
2754 ((box_name << 8) & 0x00FF0000);
2755 TRACE((
"%2d %8d %.*s (%d bytes remains for sibilings) \n",
2760 (
int)stack[depth].bytes));
2767 if (box_bytes > stack[depth].bytes) {
2768 TRACE((
"Wrong %c%c%c%c box size: broken file?\n",
2769 (box_name >> 24) & 255,
2770 (box_name >> 16) & 255,
2771 (box_name >> 8) & 255,
2773 box_bytes = stack[depth].bytes;
2775 payload_bytes = box_bytes - read_bytes;
2777 stack[depth].bytes -= box_bytes;
2795 sample_size = READ(4);
2804 if (box_name == BOX_stsz) {
2805 tr->
entry_size[i] = (sample_size ? sample_size : READ(4));
2807 switch (sample_size & 0xFF) {
2841#if MP4D_TRACE_TIMESTAMPS || MP4D_TIMESTAMPS_SUPPORTED
2843 unsigned count, j, k = 0, ts = 0, ts_capacity;
2854 ts_capacity = count;
2855#if MP4D_TIMESTAMPS_SUPPORTED
2864 for (i = 0; i < count; i++) {
2865 unsigned sc = READ(4);
2868 TRACE((
"sample %8d count %8d duration %8d\n", i, sc,
d));
2869#if MP4D_TIMESTAMPS_SUPPORTED
2870 if (new_k > ts_capacity) {
2899 if (new_capacity < new_k)
2900 new_capacity = new_k;
2901 if (new_capacity *
sizeof(
unsigned) > MINIMP4_MAX_ALLOC_BYTES)
2902 new_capacity = MINIMP4_MAX_ALLOC_BYTES /
sizeof(
unsigned);
2903 if (new_capacity < new_k) {
2904 ERROR(
"out of memory");
2906 ts_capacity = (unsigned)new_capacity;
2912 ERROR(
"out of memory");
2915 for (j = 0; j < sc; j++) {
2925 unsigned count = READ(4);
2926 for (i = 0; i < count; i++) {
2936 if (payload_bytes == 0)
2942 TRACE((
"sample %8d count %8d decoding to composition offset %8d\n", i, sc,
d));
2957 if (box_name == BOX_co64) {
2958#if !MP4D_64BIT_SUPPORTED
2960 ERROR(
"UNSUPPORTED FEATURE: 64-bit chunk_offset not supported!");
2969#if MP4D_INFO_SUPPORTED
2971 SKIP(((FullAtomVersionAndFlags >> 24) == 1) ? 8 + 8 : 4 + 4);
2973 mp4->
duration_hi = ((FullAtomVersionAndFlags >> 24) == 1) ? READ(4) : 0;
2975 SKIP(4 + 2 + 2 + 4 * 2 + 4 * 9 + 4 * 6 + 4);
2982 SKIP(((FullAtomVersionAndFlags >> 24) == 1) ? 8 + 8 : 4 + 4);
2984 tr->
duration_hi = ((FullAtomVersionAndFlags >> 24) == 1) ? READ(4) : 0;
2988 int ISO_639_2_T = READ(2);
2989 tr->
language[2] = (ISO_639_2_T & 31) + 0x60;
2991 tr->
language[1] = (ISO_639_2_T & 31) + 0x60;
2993 tr->
language[0] = (ISO_639_2_T & 31) + 0x60;
3010 ERROR(
"broken file structure!");
3045 ERROR(
"broken file structure!");
3052 ERROR(
"broken file structure!");
3054#if MP4D_INFO_SUPPORTED
3055 SKIP(6 * 1 + 2 + 4 * 2);
3064#if MP4D_AVC_SUPPORTED
3070 ERROR(
"broken file structure!");
3072#if MP4D_INFO_SUPPORTED
3073 SKIP(6 * 1 + 2 + 2 + 2 + 4 * 3);
3078 SKIP(4 + 4 + 4 + 2 + 32 + 2 + 2);
3100 tr->
dsi = (
unsigned char*)minimp4_bounded_malloc((
size_t)box_bytes);
3102 ERROR(
"out of memory");
3107 unsigned char* p = tr->
dsi;
3108 unsigned int configurationVersion = READ(1);
3109 unsigned int AVCProfileIndication = READ(1);
3110 unsigned int profile_compatibility = READ(1);
3111 unsigned int AVCLevelIndication = READ(1);
3113 unsigned int lengthSizeMinusOne = READ(1) & 3;
3115 (void)configurationVersion;
3116 (void)AVCProfileIndication;
3117 (void)profile_compatibility;
3118 (void)AVCLevelIndication;
3119 (void)lengthSizeMinusOne;
3121 for (spspps = 0; spspps < 2; spspps++) {
3122 unsigned int numOfSequenceParameterSets = READ(1);
3124 numOfSequenceParameterSets &= 31;
3126 *p++ = numOfSequenceParameterSets;
3127 for (i = 0; i < numOfSequenceParameterSets; i++) {
3128 unsigned k, sequenceParameterSetLength = READ(2);
3129 *p++ = sequenceParameterSetLength >> 8;
3130 *p++ = sequenceParameterSetLength;
3131 for (k = 0; k < sequenceParameterSetLength; k++) {
3141 unsigned flags = READ(3);
3149 unsigned bytecount = READ(1);
3168#if MP4D_INFO_SUPPORTED
3173 SKIP(1 + 3 + 4 + 4);
3180 if (!tr->
dsi && payload_bytes) {
3188 MALLOC(
unsigned char*, tr->
dsi, (
uint64_t)payload_bytes);
3189 for (i = 0; i < payload_bytes; i++) {
3191 minimp4_read(mp4, 1, &eof_flag);
3199 TRACE((
"[%c%c%c%c] %d\n",
3204 (
int)payload_bytes));
3207#if MP4D_INFO_SUPPORTED
3209 if (ptag && !*ptag && payload_bytes > 16) {
3215 TRACE((
"%2d %2d %2d ",
size,
class, x1));
3217 SKIP(4 + 4 + 4 + 4);
3221 MALLOC(
unsigned char*, *ptag, (
uint64_t)payload_bytes + 1);
3222 for (i = 0; payload_bytes != 0; i++) {
3223 (*ptag)[i] = READ(1);
3229 if (box_name == BOX_trak) {
3238 ERROR(
"out of memory");
3243 }
else if (box_name == BOX_meta) {
3248 for (i = 0; i < NELEM(g_envelope_box); i++) {
3249 if (box_name == g_envelope_box[i].
name) {
3251 ERROR(
"too deep atoms nesting!");
3253 stack[depth].bytes = payload_bytes;
3254 stack[depth].format = g_envelope_box[i].type;
3260 if (i == NELEM(g_envelope_box)) {
3261 if (payload_bytes > file_size) {
3264 SKIP(payload_bytes);
3270 while (depth > 0 && !stack[depth].bytes) {
3274 }
while (!eof_flag);
3286static int sample_to_chunk(
MP4D_track_t* tr,
unsigned nsample,
unsigned* nfirst_sample_in_chunk) {
3287 unsigned chunk_group, nc, sum;
3288 *nfirst_sample_in_chunk = 0;
3322 *nfirst_sample_in_chunk = sum;
3338 if (nsample < sum) {
3345 *nfirst_sample_in_chunk = sum;
3358 unsigned* frame_bytes,
3359 unsigned* timestamp,
3360 unsigned* duration) {
3363 int nchunk = sample_to_chunk(tr, nsample, &ns);
3366 if (nchunk < 0 || !tr->chunk_offset || !tr->
entry_size) {
3395 for (; ns < nsample; ns++) {
3406#if MP4D_TIMESTAMPS_SUPPORTED
3419#if MP4D_TIMESTAMPS_SUPPORTED
3440#if MP4D_TIMESTAMPS_SUPPORTED
3449#if MP4D_INFO_SUPPORTED
3459static int skip_spspps(
const unsigned char* p,
int nbytes,
int nskip) {
3461 for (i = 0; i < nskip; i++) {
3465 segmbytes = p[k] * 256 + p[k + 1];
3471static const void* MP4D_read_spspps(
3472 const MP4D_demux_t* mp4,
unsigned int ntrack,
int pps_flag,
int nsps,
int* sps_bytes) {
3473 int sps_count, skip_bytes;
3475 unsigned char* p = mp4->
track[ntrack].
dsi;
3483 sps_count = p[bytepos++];
3484 skip_bytes = skip_spspps(p + bytepos, mp4->
track[ntrack].
dsi_bytes - bytepos, sps_count);
3487 bytepos += skip_bytes;
3491 sps_count = p[bytepos++];
3492 if (nsps >= sps_count)
3494 skip_bytes = skip_spspps(p + bytepos, mp4->
track[ntrack].
dsi_bytes - bytepos, nsps);
3497 bytepos += skip_bytes;
3498 *sps_bytes = p[bytepos] * 256 + p[bytepos + 1];
3499 return p + bytepos + 2;
3503 return MP4D_read_spspps(mp4, ntrack, 0, nsps, sps_bytes);
3507 return MP4D_read_spspps(mp4, ntrack, 1, npps, pps_bytes);
3510#if MP4D_PRINT_INFO_SUPPORTED
3518static const char* GetMP4StreamTypeName(
int streamType) {
3519 switch (streamType) {
3523 return "ObjectDescriptorStream";
3525 return "ClockReferenceStream";
3527 return "SceneDescriptionStream";
3529 return "VisualStream";
3531 return "AudioStream";
3533 return "MPEG7Stream";
3535 return "IPMPStream";
3537 return "ObjectContentInfoStream";
3539 return "MPEGJStream";
3541 if (streamType >= 0x20 && streamType <= 0x3F) {
3542 return "User private";
3544 return "Reserved for ISO use";
3552static const char* GetMP4ObjectTypeName(
int objectTypeIndication) {
3553 switch (objectTypeIndication) {
3557 return "Systems ISO/IEC 14496-1";
3559 return "Systems ISO/IEC 14496-1";
3561 return "Visual ISO/IEC 14496-2";
3563 return "Audio ISO/IEC 14496-3";
3565 return "Visual ISO/IEC 13818-2 Simple Profile";
3567 return "Visual ISO/IEC 13818-2 Main Profile";
3569 return "Visual ISO/IEC 13818-2 SNR Profile";
3571 return "Visual ISO/IEC 13818-2 Spatial Profile";
3573 return "Visual ISO/IEC 13818-2 High Profile";
3575 return "Visual ISO/IEC 13818-2 422 Profile";
3577 return "Audio ISO/IEC 13818-7 Main Profile";
3579 return "Audio ISO/IEC 13818-7 LC Profile";
3581 return "Audio ISO/IEC 13818-7 SSR Profile";
3583 return "Audio ISO/IEC 13818-3";
3585 return "Visual ISO/IEC 11172-2";
3587 return "Audio ISO/IEC 11172-3";
3589 return "Visual ISO/IEC 10918-1";
3591 return "no object type specified";
3593 if (objectTypeIndication >= 0xC0 && objectTypeIndication <= 0xFE)
3594 return "User private";
3596 return "Reserved for ISO use";
3631 printf(
"\nMP4 FILE: %d tracks found. Movie time %.2f sec\n",
3634#define STR_TAG(name) \
3635 if (mp4->tag.name) \
3636 printf("%10s = %s\n", #name, mp4->tag.name)
3643 printf(
"\nNo|type|lng| duration | bitrate| %-23s| Object type",
"Stream type");
3647 printf(
"\n%2d|%c%c%c%c|%c%c%c|%7.2f s %6d frm| %7d|",
const void * MP4D_read_sps(const MP4D_demux_t *mp4, unsigned int ntrack, int nsps, int *sps_bytes)
boxsize_t MP4D_file_offset_t
Definition minimp4.h:102
struct MP4E_mux_tag MP4E_mux_t
Definition minimp4.h:125
#define MP4E_SAMPLE_DEFAULT
Definition minimp4.h:89
#define MP4_OBJECT_TYPE_AVC
Definition minimp4.h:71
#define MP4E_STATUS_NO_MEMORY
Definition minimp4.h:82
int mp4_h26x_write_init(mp4_h26x_writer_t *h, MP4E_mux_t *mux, int width, int height, int is_hevc)
#define MINIMP4_MAX_SPS
Definition minimp4.h:32
void MP4D_close(MP4D_demux_t *mp4)
int MP4E_set_text_comment(MP4E_mux_t *mux, const char *comment)
MP4E_mux_t * MP4E_open(int sequential_mode_flag, int enable_fragmentation, void *token, int(*write_callback)(int64_t offset, const void *buffer, size_t size, void *token))
int MP4D_open(MP4D_demux_t *mp4, int(*read_callback)(int64_t offset, void *buffer, size_t size, void *token), void *token, int64_t file_size)
void mp4_h26x_write_close(mp4_h26x_writer_t *h)
struct MP4D_demux_tag MP4D_demux_t
#define MP4D_TFDT_SUPPORT
Definition minimp4.h:57
#define HEVC_NAL_CRA_NUT
Definition minimp4.h:119
int mp4_h26x_write_nal(mp4_h26x_writer_t *h, const unsigned char *nal, int length, unsigned timeStamp90kHz_next)
#define MP4E_HANDLER_TYPE_GESM
Definition minimp4.h:113
int MP4E_put_sample(MP4E_mux_t *mux, int track_num, const void *data, int data_bytes, int duration, int kind)
uint64_t boxsize_t
Definition minimp4.h:98
#define MP4E_STATUS_BAD_ARGUMENTS
Definition minimp4.h:81
#define MP4D_HANDLER_TYPE_SOUN
Definition minimp4.h:110
int MP4E_close(MP4E_mux_t *mux)
int MP4E_set_dsi(MP4E_mux_t *mux, int track_id, const void *dsi, int bytes)
int MP4E_set_sps(MP4E_mux_t *mux, int track_id, const void *sps, int bytes)
#define HEVC_NAL_VPS
Definition minimp4.h:115
#define MP4E_SAMPLE_RANDOM_ACCESS
Definition minimp4.h:90
#define MINIMP4_MAX_PPS
Definition minimp4.h:33
#define MP4E_STATUS_OK
Definition minimp4.h:80
#define MINIMP4_MIN(x, y)
Definition minimp4.h:22
int MP4E_add_track(MP4E_mux_t *mux, const MP4E_track_t *track_data)
MP4D_file_offset_t MP4D_frame_offset(const MP4D_demux_t *mp4, unsigned int ntrack, unsigned int nsample, unsigned int *frame_bytes, unsigned *timestamp, unsigned *duration)
track_media_kind_t
Definition minimp4.h:127
@ e_private
Definition minimp4.h:127
@ e_video
Definition minimp4.h:127
@ e_audio
Definition minimp4.h:127
struct mp4_h26x_writer_tag mp4_h26x_writer_t
int MP4E_set_vps(MP4E_mux_t *mux, int track_id, const void *vps, int bytes)
#define MAX_CHUNKS_DEPTH
Definition minimp4.h:30
const void * MP4D_read_pps(const MP4D_demux_t *mp4, unsigned int ntrack, int npps, int *pps_bytes)
#define HEVC_NAL_SPS
Definition minimp4.h:116
#define MP4E_STATUS_ONLY_ONE_DSI_ALLOWED
Definition minimp4.h:84
#define MP4_OBJECT_TYPE_AUDIO_ISO_IEC_14496_3
Definition minimp4.h:63
#define MP4_OBJECT_TYPE_HEVC
Definition minimp4.h:73
int MP4E_set_pps(MP4E_mux_t *mux, int track_id, const void *pps, int bytes)
#define HEVC_NAL_BLA_W_LP
Definition minimp4.h:118
#define MP4D_HANDLER_TYPE_VIDE
Definition minimp4.h:108
#define MP4E_SAMPLE_CONTINUATION
Definition minimp4.h:91
#define HEVC_NAL_PPS
Definition minimp4.h:117
AU_EXTERN AU_EXPORT void printf(const char *format,...)
Definition stdio.cpp:121
AU_EXPORT char * strdup(const char *c)
Definition string.cpp:237
#define RETURN_ERROR(StatusCode)
Definition Base.h:1000
#define assert(expr)
Definition assert.h:32
uint8_t flags
Definition virtio.h:0
XE_LIB void * memchr(const void *src, int c, size_t n)
Definition string.cpp:883
XETime t
Definition main.cpp:53
size_t a
Definition main.cpp:156
boxsize_t MP4D_file_offset_t
Definition minimp4.h:102
unsigned int uint32_t
Definition acefiex.h:163
COMPILER_DEPENDENT_INT64 int64_t
Definition acefiex.h:164
unsigned char uint8_t
Definition acefiex.h:161
COMPILER_DEPENDENT_UINT64 uint64_t
Definition acefiex.h:165
unsigned short int uint16_t
Definition acefiex.h:162
#define NULL
Definition actypes.h:561
#define GetBits
Definition bitstream.h:53
char title[128]
Definition d_main.c:877
uint8_t byte
Definition doomtype.h:83
size_t size
Definition drm_bridge.h:1299
size_t size_t offset
Definition drm_bridge.h:1299
struct drm_crtc struct drm_plane struct drm_plane const struct drm_crtc_funcs const char * name
Definition drm_crtc.h:1242
const char const char * format
Definition drm_print.h:516
int sample
Definition h264bsd_deblocking.c:642
#define FREE(ptr)
Definition h264bsd_util.h:150
struct i915_user_extension base
Definition i915_drm.h:0
void * data
Definition kthread.h:30
int h
Definition layout.c:118
#define d
Definition libunicode.c:1833
#define realloc(p, s)
Definition quickjs.c:2292
#define malloc(s)
Definition quickjs.c:2290
#define free(p)
Definition quickjs.c:2291
unsigned duration_hi
Definition minimp4.h:281
unsigned char * album
Definition minimp4.h:292
unsigned timescale
Definition minimp4.h:285
int64_t read_size
Definition minimp4.h:269
void * token
Definition minimp4.h:272
struct MP4D_demux_tag::@753 tag
unsigned char * title
Definition minimp4.h:290
MP4D_track_t * track
Definition minimp4.h:270
int64_t read_pos
Definition minimp4.h:268
unsigned char * year
Definition minimp4.h:293
unsigned duration_lo
Definition minimp4.h:282
unsigned char * artist
Definition minimp4.h:291
unsigned char * comment
Definition minimp4.h:294
unsigned char * genre
Definition minimp4.h:295
unsigned track_count
Definition minimp4.h:274
int(* read_callback)(int64_t offset, void *buffer, size_t size, void *token)
Definition minimp4.h:271
unsigned first_chunk
Definition minimp4.h:302
unsigned samples_per_chunk
Definition minimp4.h:303
unsigned sample_count
Definition minimp4.h:165
MP4D_file_offset_t * chunk_offset
Definition minimp4.h:255
unsigned channelcount
Definition minimp4.h:234
unsigned stc_cache_group
Definition minimp4.h:260
unsigned timestamp_count
Definition minimp4.h:281
unsigned fo_cache_nsample
Definition minimp4.h:270
unsigned sample_to_chunk_count
Definition minimp4.h:251
unsigned chunk_count
Definition minimp4.h:254
unsigned width
Definition minimp4.h:240
struct MP4D_track_t::@750::@751 audio
unsigned height
Definition minimp4.h:241
unsigned * timestamp
Definition minimp4.h:258
unsigned samplerate_hz
Definition minimp4.h:235
struct MP4D_track_t::@750::@752 video
unsigned object_type_indication
Definition minimp4.h:192
unsigned timescale
Definition minimp4.h:210
unsigned stc_cache_sum
Definition minimp4.h:262
struct MP4D_sample_to_chunk_t_tag * sample_to_chunk
Definition minimp4.h:252
unsigned * entry_size
Definition minimp4.h:249
unsigned char * dsi
Definition minimp4.h:168
unsigned duration_lo
Definition minimp4.h:207
union MP4D_track_t::@750 SampleDescription
unsigned fo_cache_valid
Definition minimp4.h:269
unsigned stc_cache_nc
Definition minimp4.h:261
unsigned handler_type
Definition minimp4.h:203
MP4D_file_offset_t fo_cache_offset
Definition minimp4.h:271
unsigned * duration
Definition minimp4.h:259
unsigned dsi_bytes
Definition minimp4.h:171
unsigned char language[4]
Definition minimp4.h:216
unsigned duration_hi
Definition minimp4.h:206
unsigned stream_type
Definition minimp4.h:229
unsigned avg_bitrate_bps
Definition minimp4.h:213
int width
Definition minimp4.h:150
track_media_kind_t track_media_kind
Definition minimp4.h:137
unsigned time_scale
Definition minimp4.h:140
unsigned char language[4]
Definition minimp4.h:135
int height
Definition minimp4.h:151
unsigned object_type_indication
Definition minimp4.h:132
union MP4E_track_t::@747 u
unsigned default_duration
Definition minimp4.h:141
struct MP4E_track_t::@747::@749 v
void * sps_cache[MINIMP4_MAX_SPS]
Definition minimp4.h:307
void * pps_cache[MINIMP4_MAX_PPS]
Definition minimp4.h:308
int need_sps
Definition minimp4.h:322
MP4E_mux_t * mux
Definition minimp4.h:321
int need_pps
Definition minimp4.h:322
int need_vps
Definition minimp4.h:322
int is_hevc
Definition minimp4.h:322
int need_idr
Definition minimp4.h:322
h264_sps_id_patcher_t sps_patcher
Definition minimp4.h:319
int mux_track_id
Definition minimp4.h:322
size_t(* write_callback)(struct __VFS_NODE__ *node, struct __VFS_NODE__ *file, uint64_t *buffer, uint32_t length)
Definition vfs.h:103
size_t(* read_callback)(struct __VFS_NODE__ *node, struct __VFS_NODE__ *file, uint64_t *buffer, uint32_t length)
Definition vfs.h:96