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;
257#if MP4D_TIMESTAMPS_SUPPORTED
276#if MP4D_INFO_SUPPORTED
290 unsigned char*
title;
292 unsigned char*
album;
295 unsigned char*
genre;
318#if MINIMP4_TRANSCODE_SPS_ID
328 const unsigned char* nal,
330 unsigned timeStamp90kHz_next);
361 unsigned int nsample,
362 unsigned int* frame_bytes,
385#if MP4D_PRINT_INFO_SUPPORTED
405 int enable_fragmentation,
430 MP4E_mux_t* mux,
int track_num,
const void* data,
int data_bytes,
int duration,
int kind);
485#if defined(MINIMP4_IMPLEMENTATION) && !defined(MINIMP4_IMPLEMENTATION_GUARD)
486#define MINIMP4_IMPLEMENTATION_GUARD
488#define FOUR_CHAR_INT(a, b, c, d) (((uint32_t)(a) << 24) | ((b) << 16) | ((c) << 8) | (d))
490 BOX_co64 = FOUR_CHAR_INT(
'c',
'o',
'6',
'4'),
491 BOX_stco = FOUR_CHAR_INT(
's',
't',
'c',
'o'),
492 BOX_crhd = FOUR_CHAR_INT(
'c',
'r',
'h',
'd'),
493 BOX_ctts = FOUR_CHAR_INT(
'c',
't',
't',
's'),
494 BOX_cprt = FOUR_CHAR_INT(
'c',
'p',
'r',
't'),
495 BOX_url_ = FOUR_CHAR_INT(
'u',
'r',
'l',
' '),
496 BOX_urn_ = FOUR_CHAR_INT(
'u',
'r',
'n',
' '),
497 BOX_dinf = FOUR_CHAR_INT(
'd',
'i',
'n',
'f'),
498 BOX_dref = FOUR_CHAR_INT(
'd',
'r',
'e',
'f'),
499 BOX_stdp = FOUR_CHAR_INT(
's',
't',
'd',
'p'),
500 BOX_edts = FOUR_CHAR_INT(
'e',
'd',
't',
's'),
501 BOX_elst = FOUR_CHAR_INT(
'e',
'l',
's',
't'),
502 BOX_uuid = FOUR_CHAR_INT(
'u',
'u',
'i',
'd'),
503 BOX_free = FOUR_CHAR_INT(
'f',
'r',
'e',
'e'),
504 BOX_hdlr = FOUR_CHAR_INT(
'h',
'd',
'l',
'r'),
505 BOX_hmhd = FOUR_CHAR_INT(
'h',
'm',
'h',
'd'),
506 BOX_hint = FOUR_CHAR_INT(
'h',
'i',
'n',
't'),
507 BOX_mdia = FOUR_CHAR_INT(
'm',
'd',
'i',
'a'),
508 BOX_mdat = FOUR_CHAR_INT(
'm',
'd',
'a',
't'),
509 BOX_mdhd = FOUR_CHAR_INT(
'm',
'd',
'h',
'd'),
510 BOX_minf = FOUR_CHAR_INT(
'm',
'i',
'n',
'f'),
511 BOX_moov = FOUR_CHAR_INT(
'm',
'o',
'o',
'v'),
512 BOX_mvhd = FOUR_CHAR_INT(
'm',
'v',
'h',
'd'),
513 BOX_stsd = FOUR_CHAR_INT(
's',
't',
's',
'd'),
514 BOX_stsz = FOUR_CHAR_INT(
's',
't',
's',
'z'),
515 BOX_stz2 = FOUR_CHAR_INT(
's',
't',
'z',
'2'),
516 BOX_stbl = FOUR_CHAR_INT(
's',
't',
'b',
'l'),
517 BOX_stsc = FOUR_CHAR_INT(
's',
't',
's',
'c'),
518 BOX_stsh = FOUR_CHAR_INT(
's',
't',
's',
'h'),
519 BOX_skip = FOUR_CHAR_INT(
's',
'k',
'i',
'p'),
520 BOX_smhd = FOUR_CHAR_INT(
's',
'm',
'h',
'd'),
521 BOX_stss = FOUR_CHAR_INT(
's',
't',
's',
's'),
522 BOX_stts = FOUR_CHAR_INT(
's',
't',
't',
's'),
523 BOX_trak = FOUR_CHAR_INT(
't',
'r',
'a',
'k'),
524 BOX_tkhd = FOUR_CHAR_INT(
't',
'k',
'h',
'd'),
525 BOX_tref = FOUR_CHAR_INT(
't',
'r',
'e',
'f'),
526 BOX_udta = FOUR_CHAR_INT(
'u',
'd',
't',
'a'),
527 BOX_vmhd = FOUR_CHAR_INT(
'v',
'm',
'h',
'd'),
528 BOX_url = FOUR_CHAR_INT(
'u',
'r',
'l',
' '),
529 BOX_urn = FOUR_CHAR_INT(
'u',
'r',
'n',
' '),
531 BOX_gnrv = FOUR_CHAR_INT(
'g',
'n',
'r',
'v'),
532 BOX_gnra = FOUR_CHAR_INT(
'g',
'n',
'r',
'a'),
535 BOX_ftyp = FOUR_CHAR_INT(
'f',
't',
'y',
'p'),
536 BOX_padb = FOUR_CHAR_INT(
'p',
'a',
'd',
'b'),
539 BOX_sdhd = FOUR_CHAR_INT(
's',
'd',
'h',
'd'),
540 BOX_dpnd = FOUR_CHAR_INT(
'd',
'p',
'n',
'd'),
541 BOX_iods = FOUR_CHAR_INT(
'i',
'o',
'd',
's'),
542 BOX_odhd = FOUR_CHAR_INT(
'o',
'd',
'h',
'd'),
543 BOX_mpod = FOUR_CHAR_INT(
'm',
'p',
'o',
'd'),
544 BOX_nmhd = FOUR_CHAR_INT(
'n',
'm',
'h',
'd'),
545 BOX_esds = FOUR_CHAR_INT(
'e',
's',
'd',
's'),
546 BOX_sync = FOUR_CHAR_INT(
's',
'y',
'n',
'c'),
547 BOX_ipir = FOUR_CHAR_INT(
'i',
'p',
'i',
'r'),
548 BOX_mp4s = FOUR_CHAR_INT(
'm',
'p',
'4',
's'),
549 BOX_mp4a = FOUR_CHAR_INT(
'm',
'p',
'4',
'a'),
550 BOX_mp4v = FOUR_CHAR_INT(
'm',
'p',
'4',
'v'),
553 BOX_avc1 = FOUR_CHAR_INT(
'a',
'v',
'c',
'1'),
554 BOX_avc2 = FOUR_CHAR_INT(
'a',
'v',
'c',
'2'),
555 BOX_svc1 = FOUR_CHAR_INT(
's',
'v',
'c',
'1'),
556 BOX_avcC = FOUR_CHAR_INT(
'a',
'v',
'c',
'C'),
557 BOX_svcC = FOUR_CHAR_INT(
's',
'v',
'c',
'C'),
558 BOX_btrt = FOUR_CHAR_INT(
'b',
't',
'r',
't'),
559 BOX_m4ds = FOUR_CHAR_INT(
'm',
'4',
'd',
's'),
560 BOX_seib = FOUR_CHAR_INT(
's',
'e',
'i',
'b'),
563 BOX_hev1 = FOUR_CHAR_INT(
'h',
'e',
'v',
'1'),
564 BOX_hvc1 = FOUR_CHAR_INT(
'h',
'v',
'c',
'1'),
565 BOX_hvcC = FOUR_CHAR_INT(
'h',
'v',
'c',
'C'),
568 BOX_samr = FOUR_CHAR_INT(
's',
'a',
'm',
'r'),
569 BOX_sawb = FOUR_CHAR_INT(
's',
'a',
'w',
'b'),
570 BOX_damr = FOUR_CHAR_INT(
'd',
'a',
'm',
'r'),
571 BOX_s263 = FOUR_CHAR_INT(
's',
'2',
'6',
'3'),
572 BOX_d263 = FOUR_CHAR_INT(
'd',
'2',
'6',
'3'),
575 BOX_mvex = FOUR_CHAR_INT(
'm',
'v',
'e',
'x'),
576 BOX_trex = FOUR_CHAR_INT(
't',
'r',
'e',
'x'),
577 BOX_moof = FOUR_CHAR_INT(
'm',
'o',
'o',
'f'),
578 BOX_mfhd = FOUR_CHAR_INT(
'm',
'f',
'h',
'd'),
579 BOX_traf = FOUR_CHAR_INT(
't',
'r',
'a',
'f'),
580 BOX_tfhd = FOUR_CHAR_INT(
't',
'f',
'h',
'd'),
581 BOX_tfdt = FOUR_CHAR_INT(
't',
'f',
'd',
't'),
582 BOX_trun = FOUR_CHAR_INT(
't',
'r',
'u',
'n'),
583 BOX_mehd = FOUR_CHAR_INT(
'm',
'e',
'h',
'd'),
588 OD_BASE = FOUR_CHAR_INT(
'$',
'$',
'$',
'0'),
589 OD_ESD = FOUR_CHAR_INT(
'$',
'$',
'$',
'3'),
590 OD_DCD = FOUR_CHAR_INT(
'$',
'$',
'$',
'4'),
591 OD_DSI = FOUR_CHAR_INT(
'$',
'$',
'$',
'5'),
592 OD_SLC = FOUR_CHAR_INT(
'$',
'$',
'$',
'6'),
594 BOX_meta = FOUR_CHAR_INT(
'm',
'e',
't',
'a'),
595 BOX_ilst = FOUR_CHAR_INT(
'i',
'l',
's',
't'),
598 BOX_calb = FOUR_CHAR_INT(
'\xa9',
'a',
'l',
'b'),
599 BOX_cart = FOUR_CHAR_INT(
'\xa9',
'a',
'r',
't'),
600 BOX_aART = FOUR_CHAR_INT(
'a',
'A',
'R',
'T'),
601 BOX_ccmt = FOUR_CHAR_INT(
'\xa9',
'c',
'm',
't'),
602 BOX_cday = FOUR_CHAR_INT(
'\xa9',
'd',
'a',
'y'),
603 BOX_cnam = FOUR_CHAR_INT(
'\xa9',
'n',
'a',
'm'),
604 BOX_cgen = FOUR_CHAR_INT(
'\xa9',
'g',
'e',
'n'),
605 BOX_trkn = FOUR_CHAR_INT(
't',
'r',
'k',
'n'),
606 BOX_disk = FOUR_CHAR_INT(
'd',
'i',
's',
'k'),
607 BOX_cwrt = FOUR_CHAR_INT(
'\xa9',
'w',
'r',
't'),
608 BOX_ctoo = FOUR_CHAR_INT(
'\xa9',
't',
'o',
'o'),
609 BOX_tmpo = FOUR_CHAR_INT(
't',
'm',
'p',
'o'),
610 BOX_cpil = FOUR_CHAR_INT(
'c',
'p',
'i',
'l'),
611 BOX_covr = FOUR_CHAR_INT(
'c',
'o',
'v',
'r'),
612 BOX_rtng = FOUR_CHAR_INT(
'r',
't',
'n',
'g'),
613 BOX_cgrp = FOUR_CHAR_INT(
'\xa9',
'g',
'r',
'p'),
614 BOX_stik = FOUR_CHAR_INT(
619 BOX_pcst = FOUR_CHAR_INT(
'p',
'c',
's',
't'),
620 BOX_catg = FOUR_CHAR_INT(
'c',
'a',
't',
'g'),
621 BOX_keyw = FOUR_CHAR_INT(
'k',
'e',
'y',
'w'),
622 BOX_purl = FOUR_CHAR_INT(
'p',
'u',
'r',
'l'),
623 BOX_egid = FOUR_CHAR_INT(
'e',
'g',
'i',
'd'),
624 BOX_desc = FOUR_CHAR_INT(
'd',
'e',
's',
'c'),
625 BOX_clyr = FOUR_CHAR_INT(
'\xa9',
'l',
'y',
'r'),
626 BOX_tven = FOUR_CHAR_INT(
't',
'v',
'e',
'n'),
627 BOX_tves = FOUR_CHAR_INT(
't',
'v',
'e',
's'),
628 BOX_tvnn = FOUR_CHAR_INT(
't',
'v',
'n',
'n'),
629 BOX_tvsh = FOUR_CHAR_INT(
't',
'v',
's',
'h'),
630 BOX_tvsn = FOUR_CHAR_INT(
't',
'v',
's',
'n'),
631 BOX_purd = FOUR_CHAR_INT(
'p',
'u',
'r',
'd'),
632 BOX_pgap = FOUR_CHAR_INT(
'p',
'g',
'a',
'p'),
635 BOX_cART = FOUR_CHAR_INT(
'\xa9',
'A',
'R',
'T'),
636 BOX_gnre = FOUR_CHAR_INT(
'g',
'n',
'r',
'e'),
639 BOX_auth = FOUR_CHAR_INT(
'a',
'u',
't',
'h'),
640 BOX_titl = FOUR_CHAR_INT(
't',
'i',
't',
'l'),
641 BOX_dscp = FOUR_CHAR_INT(
'd',
's',
'c',
'p'),
642 BOX_perf = FOUR_CHAR_INT(
'p',
'e',
'r',
'f'),
643 BOX_mean = FOUR_CHAR_INT(
'm',
'e',
'a',
'n'),
644 BOX_name = FOUR_CHAR_INT(
'n',
'a',
'm',
'e'),
645 BOX_data = FOUR_CHAR_INT(
'd',
'a',
't',
'a'),
648 BOX_albm = FOUR_CHAR_INT(
'a',
'l',
'b',
'm'),
649 BOX_yrrc = FOUR_CHAR_INT(
'y',
'r',
'r',
'c')
653#define MP4E_HANDLER_TYPE_VIDE 0x76696465
655#define MP4E_HANDLER_TYPE_SOUN 0x736F756E
658#define MP4E_HANDLER_TYPE_GESM 0x6765736D
664 unsigned flag_random_access;
675 minimp4_vector_t smpl;
676 minimp4_vector_t pending_sample;
678 minimp4_vector_t vsps;
679 minimp4_vector_t vpps;
680 minimp4_vector_t vvps;
684typedef struct MP4E_mux_tag {
685 minimp4_vector_t tracks;
692 int sequential_mode_flag;
693 int enable_fragmentation;
698static const unsigned char box_ftyp[] = {
700 0, 0, 0, 0x18,
'f',
't',
'y',
'p',
'm',
'p',
'4',
'2',
701 0, 0, 0, 0,
'm',
'p',
'4',
'2',
'i',
's',
'o',
'm',
704 0, 0, 0, 0x20,
'f',
't',
'y',
'p',
'i',
's',
'o',
'm', 0, 0, 2, 0,
705 'm',
'p',
'4',
'1',
'i',
's',
'o',
'm',
'i',
's',
'o',
'2',
'a',
'v',
'c',
'1',
712#define WR(x, n) *p++ = (unsigned char)((x) >> 8 * n)
713#define WRITE_1(x) WR(x, 0);
727 (p)[0] = (char)((x) >> 8 * 3); \
728 (p)[1] = (char)((x) >> 8 * 2); \
729 (p)[2] = (char)((x) >> 8 * 1); \
730 (p)[3] = (char)((x));
735 WR4((unsigned char*)*stack, p - *stack);
744#define ATOM_FULL(x, flag) \
758static int minimp4_vector_init(minimp4_vector_t* h,
int capacity) {
760 h->capacity = capacity;
761 h->data = capacity ? (
unsigned char*)
malloc(capacity) :
NULL;
762 return !capacity || !!h->data;
768static void minimp4_vector_reset(minimp4_vector_t* h) {
771 memset(h, 0,
sizeof(minimp4_vector_t));
777static int minimp4_vector_grow(minimp4_vector_t* h,
int bytes) {
779 int new_size = h->capacity * 2 + 1024;
780 if (new_size < h->capacity + bytes)
781 new_size = h->capacity + bytes + 1024;
782 p =
realloc(h->data, new_size);
785 h->data = (
unsigned char*)p;
786 h->capacity = new_size;
795static unsigned char* minimp4_vector_alloc_tail(minimp4_vector_t* h,
int bytes) {
797 if (!h->data && !minimp4_vector_init(h, 2 * bytes + 1024))
799 if ((h->capacity - h->bytes) < bytes && !minimp4_vector_grow(h, bytes))
802 assert((h->capacity - h->bytes) >= bytes);
803 p = h->data + h->bytes;
811static unsigned char* minimp4_vector_put(minimp4_vector_t* h,
const void* buf,
int bytes) {
812 unsigned char* tail = minimp4_vector_alloc_tail(h, bytes);
814 memcpy(tail, (
void*)buf, bytes);
824 int enable_fragmentation,
832 mux->sequential_mode_flag = sequential_mode_flag || enable_fragmentation;
833 mux->enable_fragmentation = enable_fragmentation;
834 mux->fragments_count = 0;
837 mux->text_comment =
NULL;
838 mux->write_pos =
sizeof(box_ftyp);
840 if (!mux->sequential_mode_flag) {
841 if (mux->write_callback(mux->write_pos, box_ftyp, 8, mux->token)) {
845 mux->write_pos += 16;
847 minimp4_vector_init(&mux->tracks, 2 *
sizeof(track_t));
856 int ntr = mux->tracks.bytes /
sizeof(track_t);
858 if (!mux || !track_data)
861 tr = (track_t*)minimp4_vector_alloc_tail(&mux->tracks,
sizeof(track_t));
864 memset(tr, 0,
sizeof(track_t));
865 memcpy(&tr->info, (
void*)track_data,
sizeof(*track_data));
866 if (!minimp4_vector_init(&tr->smpl, 256))
868 minimp4_vector_init(&tr->vsps, 0);
869 minimp4_vector_init(&tr->vpps, 0);
870 minimp4_vector_init(&tr->pending_sample, 0);
874static const unsigned char* next_dsi(
const unsigned char* p,
const unsigned char*
end,
int* bytes) {
876 *bytes = p[0] * 256 + p[1];
882static int append_mem(minimp4_vector_t* v,
const void* mem,
int bytes) {
884 unsigned char size[2];
885 const unsigned char* p = v->data;
886 for (i = 0; i + 2 < v->bytes;) {
887 int cb = p[i] * 256 + p[i + 1];
888 if (cb == bytes && !
memcmp(p + i + 2, mem, cb))
892 size[0] = bytes >> 8;
894 return minimp4_vector_put(v, size, 2) && minimp4_vector_put(v, mem, bytes);
897static int items_count(minimp4_vector_t* v) {
899 const unsigned char* p = v->data;
900 for (i = 0; i + 2 < v->bytes;) {
901 int cb = p[i] * 256 + p[i + 1];
909 track_t* tr = ((track_t*)mux->tracks.data) + track_id;
917 track_t* tr = ((track_t*)mux->tracks.data) + track_id;
923 track_t* tr = ((track_t*)mux->tracks.data) + track_id;
929 track_t* tr = ((track_t*)mux->tracks.data) + track_id;
934static unsigned get_duration(
const track_t* tr) {
935 unsigned i, sum_duration = 0;
936 const sample_t* s = (
const sample_t*)tr->smpl.data;
937 for (i = 0; i < tr->smpl.bytes /
sizeof(sample_t); i++) {
938 sum_duration += s[i].duration;
943static int write_pending_data(
MP4E_mux_t* mux, track_t* tr) {
945 if (tr->pending_sample.bytes > 0 && tr->smpl.bytes >=
sizeof(sample_t)) {
948 unsigned char base[8], *p = base;
950 assert(mux->sequential_mode_flag);
953 assert(mux->sequential_mode_flag);
954 WRITE_4(tr->pending_sample.bytes + 8);
956 ERR(mux->write_callback(mux->write_pos, base, p - base, mux->token));
957 mux->write_pos += p - base;
960 smpl_desc = ((sample_t*)minimp4_vector_alloc_tail(&tr->smpl, 0)) - 1;
961 smpl_desc->size = tr->pending_sample.bytes;
962 smpl_desc->offset = (
boxsize_t)mux->write_pos;
965 ERR(mux->write_callback(
966 mux->write_pos, tr->pending_sample.data, tr->pending_sample.bytes, mux->token));
967 mux->write_pos += tr->pending_sample.bytes;
970 tr->pending_sample.bytes = 0;
976add_sample_descriptor(
MP4E_mux_t* mux, track_t* tr,
int data_bytes,
int duration,
int kind) {
978 smp.size = data_bytes;
980 smp.duration = (duration ? duration : tr->info.default_duration);
982 return NULL != minimp4_vector_put(&tr->smpl, &smp,
sizeof(sample_t));
990static int mp4e_write_fragment_header(
MP4E_mux_t* mux,
1000 unsigned char base[888], *p = base;
1001 unsigned char* stack_base[20];
1002 unsigned char** stack = stack_base;
1003 unsigned char* pdata_offset;
1006 default_sample_duration_present = 0x000008,
1007 default_sample_flags_present = 0x000020,
1010 track_t* tr = ((track_t*)mux->tracks.data) + track_num;
1013 ATOM_FULL(BOX_mfhd, 0)
1014 WRITE_4(mux->fragments_count);
1018 if (tr->info.track_media_kind ==
e_video)
1022 flags = (tr->info.track_media_kind ==
e_video) ? 0x20020 : 0x20008;
1024 ATOM_FULL(BOX_tfhd, flags)
1025 WRITE_4(track_num + 1);
1026 if (tr->info.track_media_kind ==
e_video) {
1032#if MP4D_TFDT_SUPPORT
1033 ATOM_FULL(BOX_tfdt, 0x01000000)
1034 WRITE_4(timestamp >> 32);
1035 WRITE_4(timestamp & 0xffffffff);
1038 if (tr->info.track_media_kind ==
e_audio) {
1042 ATOM_FULL(BOX_trun, flags)
1046 WRITE_4(data_bytes);
1054 ATOM_FULL(BOX_trun, flags)
1060 WRITE_4(data_bytes);
1067 ATOM_FULL(BOX_trun, flags)
1072 WRITE_4(data_bytes);
1077 WR4(pdata_offset, (p - base) + 8);
1079 ERR(mux->write_callback(mux->write_pos, base, p - base, mux->token));
1080 mux->write_pos += p - base;
1085 unsigned char base[8], *p = base;
1088 ERR(mux->write_callback(mux->write_pos, base, p - base, mux->token));
1089 mux->write_pos += p - base;
1097 MP4E_mux_t* mux,
int track_num,
const void* data,
int data_bytes,
int duration,
int kind) {
1101 tr = ((track_t*)mux->tracks.data) + track_num;
1103 if (mux->enable_fragmentation) {
1104#if MP4D_TFDT_SUPPORT
1108 if (!mux->fragments_count++)
1109 ERR(mp4e_flush_index(mux));
1111#if MP4D_TFDT_SUPPORT
1112 ERR(mp4e_write_fragment_header(mux, track_num, data_bytes, duration, kind, timestamp));
1114 ERR(mp4e_write_fragment_header(mux, track_num, data_bytes, duration, kind));
1117 ERR(mp4e_write_mdat_box(mux, data_bytes + 8));
1118 ERR(mux->write_callback(mux->write_pos, data, data_bytes, mux->token));
1119 mux->write_pos += data_bytes;
1124 if (mux->sequential_mode_flag)
1125 ERR(write_pending_data(mux, tr));
1126 if (!add_sample_descriptor(mux, tr, data_bytes, duration, kind))
1129 if (!mux->sequential_mode_flag) {
1130 sample_t* smpl_desc;
1131 if (tr->smpl.bytes <
sizeof(sample_t))
1134 smpl_desc = (sample_t*)(tr->smpl.data + tr->smpl.bytes) - 1;
1135 smpl_desc->size += data_bytes;
1139 if (mux->sequential_mode_flag) {
1140 if (!minimp4_vector_put(&tr->pending_sample, data, data_bytes))
1143 ERR(mux->write_callback(mux->write_pos, data, data_bytes, mux->token));
1144 mux->write_pos += data_bytes;
1152static int od_size_of_size(
int size) {
1153 int i, size_of_size = 1;
1154 for (i = size; i > 0x7F; i -= 0x7F)
1156 return size_of_size;
1166 if (!mux || !comment)
1168 if (mux->text_comment)
1169 free(mux->text_comment);
1170 mux->text_comment =
strdup(comment);
1171 if (!mux->text_comment)
1179static int mp4e_flush_index(
MP4E_mux_t* mux) {
1180 unsigned char* stack_base[20];
1181 unsigned char** stack = stack_base;
1182 unsigned char *base, *p;
1183 unsigned int ntr, index_bytes, ntracks = mux->tracks.bytes /
sizeof(track_t);
1192#define FILE_HEADER_BYTES 256
1193#define TRACK_HEADER_BYTES 512
1194 index_bytes = FILE_HEADER_BYTES;
1195 if (mux->text_comment)
1196 index_bytes += 128 +
strlen(mux->text_comment);
1197 for (ntr = 0; ntr < ntracks; ntr++) {
1198 track_t* tr = ((track_t*)mux->tracks.data) + ntr;
1199 index_bytes += TRACK_HEADER_BYTES;
1201 index_bytes += tr->smpl.bytes * (
sizeof(sample_t) + 4 + 4) /
sizeof(sample_t);
1202 index_bytes += tr->vsps.bytes;
1203 index_bytes += tr->vpps.bytes;
1205 ERR(write_pending_data(mux, tr));
1208 base = (
unsigned char*)
malloc(index_bytes);
1213 if (!mux->sequential_mode_flag) {
1219 int64_t size = mux->write_pos -
sizeof(box_ftyp);
1221 if (size > size_limit) {
1224 WRITE_4((size >> 32) & 0xffffffff);
1225 WRITE_4(size & 0xffffffff);
1232 ERR(mux->write_callback(
sizeof(box_ftyp), base, p - base, mux->token));
1237#define MOOV_TIMESCALE 1000
1239 ATOM_FULL(BOX_mvhd, 0);
1244 track_t* tr = ((track_t*)mux->tracks.data) + 0;
1245 unsigned duration = get_duration(tr);
1246 duration = (unsigned)(duration * 1LL * MOOV_TIMESCALE / tr->info.time_scale);
1247 WRITE_4(MOOV_TIMESCALE);
1251 WRITE_4(0x00010000);
1258 WRITE_4(0x00010000);
1262 WRITE_4(0x00010000);
1266 WRITE_4(0x40000000);
1279 WRITE_4(ntracks + 1);
1282 for (ntr = 0; ntr < ntracks; ntr++) {
1283 track_t* tr = ((track_t*)mux->tracks.data) + ntr;
1284 unsigned duration = get_duration(tr);
1285 int samples_count = tr->smpl.bytes /
sizeof(sample_t);
1286 const sample_t* sample = (
const sample_t*)tr->smpl.data;
1287 unsigned handler_type;
1288 const char* handler_ascii =
NULL;
1290 if (mux->enable_fragmentation)
1292 else if (samples_count <= 0)
1295 switch (tr->info.track_media_kind) {
1297 handler_type = MP4E_HANDLER_TYPE_SOUN;
1298 handler_ascii =
"SoundHandler";
1301 handler_type = MP4E_HANDLER_TYPE_VIDE;
1302 handler_ascii =
"VideoHandler";
1312 ATOM_FULL(BOX_tkhd, 7);
1317 WRITE_4((
unsigned)(duration * 1LL * MOOV_TIMESCALE / tr->info.time_scale));
1326 WRITE_4(0x00010000);
1330 WRITE_4(0x00010000);
1334 WRITE_4(0x40000000);
1336 if (tr->info.track_media_kind ==
e_audio || tr->info.track_media_kind ==
e_private) {
1340 WRITE_4(tr->info.u.v.width * 0x10000);
1341 WRITE_4(tr->info.u.v.height * 0x10000);
1346 ATOM_FULL(BOX_mdhd, 0);
1349 WRITE_4(tr->info.time_scale);
1352 int lang_code = ((tr->info.language[0] & 31) << 10) |
1353 ((tr->info.language[1] & 31) << 5) | (tr->info.language[2] & 31);
1359 ATOM_FULL(BOX_hdlr, 0);
1361 WRITE_4(handler_type);
1368 if (handler_ascii) {
1369 for (i = 0; i < (int)
strlen(handler_ascii) + 1; i++) {
1370 WRITE_1(handler_ascii[i]);
1379 if (tr->info.track_media_kind ==
e_audio) {
1381 ATOM_FULL(BOX_smhd, 0);
1386 if (tr->info.track_media_kind ==
e_video) {
1388 ATOM_FULL(BOX_vmhd, 1);
1397 ATOM_FULL(BOX_dref, 0);
1404 ATOM_FULL(BOX_url, 1);
1410 ATOM_FULL(BOX_stsd, 0);
1413 if (tr->info.track_media_kind ==
e_audio || tr->info.track_media_kind ==
e_private) {
1415 if (tr->info.track_media_kind ==
e_audio) {
1426 if (tr->info.track_media_kind ==
e_audio) {
1430 WRITE_2(tr->info.u.a.channelcount);
1433 WRITE_4((tr->info.time_scale << 16));
1436 ATOM_FULL(BOX_esds, 0);
1437 if (tr->vsps.bytes > 0) {
1438 int dsi_bytes = tr->vsps.bytes - 2;
1439 int dsi_size_size = od_size_of_size(dsi_bytes);
1440 int dcd_bytes = dsi_bytes + dsi_size_size + 1 + (1 + 1 + 3 + 4 + 4);
1441 int dcd_size_size = od_size_of_size(dcd_bytes);
1442 int esd_bytes = dcd_bytes + dcd_size_size + 1 + 3;
1444#define WRITE_OD_LEN(size) \
1449 } while (size > 0x7F); \
1452 WRITE_OD_LEN(esd_bytes);
1457 WRITE_OD_LEN(dcd_bytes);
1458 if (tr->info.track_media_kind ==
e_audio) {
1466 WRITE_3(tr->info.u.a.channelcount * 6144 /
1472 WRITE_OD_LEN(dsi_bytes);
1473 for (i = 0; i < dsi_bytes; i++) {
1474 WRITE_1(tr->vsps.data[2 + i]);
1481 if (tr->info.track_media_kind ==
e_video &&
1484 int numOfSequenceParameterSets = items_count(&tr->vsps);
1485 int numOfPictureParameterSets = items_count(&tr->vpps);
1503 WRITE_2(tr->info.u.v.width);
1504 WRITE_2(tr->info.u.v.height);
1505 WRITE_4(0x00480000);
1506 WRITE_4(0x00480000);
1509 for (i = 0; i < 32; i++) {
1519 WRITE_1(tr->vsps.data[2 + 1]);
1520 WRITE_1(tr->vsps.data[2 + 2]);
1521 WRITE_1(tr->vsps.data[2 + 3]);
1523 WRITE_1(0xe0 | numOfSequenceParameterSets);
1524 for (i = 0; i < tr->vsps.bytes; i++) {
1525 WRITE_1(tr->vsps.data[i]);
1527 WRITE_1(numOfPictureParameterSets);
1528 for (i = 0; i < tr->vpps.bytes; i++) {
1529 WRITE_1(tr->vpps.data[i]);
1532 int numOfVPS = items_count(&tr->vpps);
1537 WRITE_4(0x60000000);
1554 for (i = 0; i < tr->vvps.bytes; i++) {
1555 WRITE_1(tr->vvps.data[i]);
1558 WRITE_2(numOfSequenceParameterSets);
1559 for (i = 0; i < tr->vsps.bytes; i++) {
1560 WRITE_1(tr->vsps.data[i]);
1563 WRITE_2(numOfPictureParameterSets);
1564 for (i = 0; i < tr->vpps.bytes; i++) {
1565 WRITE_1(tr->vpps.data[i]);
1579 ATOM_FULL(BOX_stts, 0);
1581 unsigned char* pentry_count = p;
1582 int cnt = 1, entry_count = 0;
1584 for (i = 0; i < samples_count; i++, cnt++) {
1585 if (i == (samples_count - 1) || sample[i].duration != sample[i + 1].duration) {
1587 WRITE_4(sample[i].duration);
1592 WR4(pentry_count, entry_count);
1597 ATOM_FULL(BOX_stsc, 0);
1598 if (mux->enable_fragmentation) {
1609 ATOM_FULL(BOX_stsz, 0);
1613 WRITE_4(samples_count);
1614 for (i = 0; i < samples_count; i++) {
1615 WRITE_4(sample[i].size);
1621 if (samples_count && sample[samples_count - 1].offset > 0xffffffff)
1624 ATOM_FULL(BOX_stco, 0);
1625 WRITE_4(samples_count);
1626 for (i = 0; i < samples_count; i++) {
1627 WRITE_4(sample[i].offset);
1630 ATOM_FULL(BOX_co64, 0);
1631 WRITE_4(samples_count);
1632 for (i = 0; i < samples_count; i++) {
1633 WRITE_4((sample[i].offset >> 32) & 0xffffffff);
1634 WRITE_4(sample[i].offset & 0xffffffff);
1642 for (i = 0; i < samples_count; i++) {
1643 ra_count += !!sample[i].flag_random_access;
1645 if (ra_count != samples_count) {
1647 ATOM_FULL(BOX_stss, 0);
1649 for (i = 0; i < samples_count; i++) {
1650 if (sample[i].flag_random_access) {
1663 if (mux->text_comment) {
1665 ATOM_FULL(BOX_meta, 0);
1666 ATOM_FULL(BOX_hdlr, 0);
1668#define MP4E_HANDLER_TYPE_MDIR 0x6d646972
1669 WRITE_4(MP4E_HANDLER_TYPE_MDIR);
1681 for (i = 0; i < (int)
strlen(mux->text_comment) + 1; i++) {
1682 WRITE_1(mux->text_comment[i]);
1691 if (mux->enable_fragmentation) {
1692 track_t* tr = ((track_t*)mux->tracks.data) + 0;
1693 uint32_t movie_duration = get_duration(tr);
1696 ATOM_FULL(BOX_mehd, 0);
1697 WRITE_4(movie_duration);
1699 for (ntr = 0; ntr < ntracks; ntr++) {
1700 ATOM_FULL(BOX_trex, 0);
1712 assert((
unsigned)(p - base) <= index_bytes);
1714 err = mux->write_callback(mux->write_pos, base, p - base, mux->token);
1715 mux->write_pos += p - base;
1722 unsigned ntr, ntracks;
1725 if (!mux->enable_fragmentation)
1726 err = mp4e_flush_index(mux);
1727 if (mux->text_comment)
1728 free(mux->text_comment);
1729 ntracks = mux->tracks.bytes /
sizeof(track_t);
1730 for (ntr = 0; ntr < ntracks; ntr++) {
1731 track_t* tr = ((track_t*)mux->tracks.data) + ntr;
1732 minimp4_vector_reset(&tr->vsps);
1733 minimp4_vector_reset(&tr->vpps);
1734 minimp4_vector_reset(&tr->smpl);
1735 minimp4_vector_reset(&tr->pending_sample);
1737 minimp4_vector_reset(&mux->tracks);
1751 int cache_free_bits;
1760 unsigned origin_bytes;
1763#define LOAD_SHORT(x) ((uint16_t)(x << 8) | (x >> 8))
1765static unsigned int show_bits(bit_reader_t* bs,
int n) {
1766 unsigned int retval;
1767 assert(n > 0 && n <= 16);
1768 retval = (
unsigned int)(bs->cache >> (32 - n));
1772static void flush_bits(bit_reader_t* bs,
int n) {
1773 assert(n >= 0 && n <= 16);
1775 bs->cache_free_bits += n;
1776 if (bs->cache_free_bits >= 0) {
1777 bs->cache |= ((
uint32_t)LOAD_SHORT(*bs->buf)) << bs->cache_free_bits;
1779 bs->cache_free_bits -= 16;
1783static unsigned int get_bits(bit_reader_t* bs,
int n) {
1784 unsigned int retval = show_bits(bs, n);
1789static void set_pos_bits(bit_reader_t* bs,
unsigned pos_bits) {
1790 assert((
int)pos_bits >= 0);
1792 bs->buf = bs->origin + pos_bits / 16;
1794 bs->cache_free_bits = 16;
1796 flush_bits(bs, pos_bits & 15);
1799static unsigned get_pos_bits(
const bit_reader_t* bs) {
1803 unsigned pos_bits = (unsigned)(bs->buf - bs->origin) * 16;
1804 pos_bits -= 16 - bs->cache_free_bits;
1805 assert((
int)pos_bits >= 0);
1809static int remaining_bits(
const bit_reader_t* bs) {
1810 return bs->origin_bytes * 8 - get_pos_bits(bs);
1813static void init_bits(bit_reader_t* bs,
const void* data,
unsigned data_bytes) {
1814 bs->origin = (
const uint16_t*)data;
1815 bs->origin_bytes = data_bytes;
1816 set_pos_bits(bs, 0);
1819#define GetBits(n) get_bits(bs, n)
1824static int ue_bits(bit_reader_t* bs) {
1827 for (clz = 0; !get_bits(bs, 1); clz++) {}
1829 val = (1 << clz) - 1 + (clz ? get_bits(bs, clz) : 0);
1833#if MINIMP4_TRANSCODE_SPS_ID
1846 (uint32_t)((((x) >> 24) & 0xFF) | (((x) >> 8) & 0xFF00) | (((x) << 8) & 0xFF0000) | \
1849static void h264e_bs_put_bits(bs_t* bs,
unsigned n,
unsigned val) {
1852 assert((
unsigned)n <= 32);
1853 if (bs->shift < 0) {
1855 bs->cache |= val >> -bs->shift;
1856 *bs->buf++ = SWAP32(bs->cache);
1857 bs->shift = 32 + bs->shift;
1860 bs->cache |= val << bs->shift;
1863static void h264e_bs_flush(bs_t* bs) {
1864 *bs->buf = SWAP32(bs->cache);
1867static unsigned h264e_bs_get_pos_bits(
const bs_t* bs) {
1868 unsigned pos_bits = (unsigned)((bs->buf - bs->origin) * BS_BITS);
1869 pos_bits += BS_BITS - bs->shift;
1870 assert((
int)pos_bits >= 0);
1874static unsigned h264e_bs_byte_align(bs_t* bs) {
1875 int pos = h264e_bs_get_pos_bits(bs);
1876 h264e_bs_put_bits(bs, -pos & 7, 0);
1877 return pos + (-pos & 7);
1894static void h264e_bs_put_golomb(bs_t* bs,
unsigned val) {
1896 unsigned t = val + 1;
1901 h264e_bs_put_bits(bs, 2 * size - 1, val + 1);
1904static void h264e_bs_init_bits(bs_t* bs,
void* data) {
1905 bs->origin = (bs_item_t*)data;
1906 bs->buf = bs->origin;
1907 bs->shift = BS_BITS;
1911static int find_mem_cache(
void* cache[],
int cache_bytes[],
int cache_size,
void* mem,
int bytes) {
1915 for (i = 0; i < cache_size; i++) {
1916 if (cache_bytes[i] == bytes && !
memcmp(mem, cache[i], bytes))
1919 for (i = 0; i < cache_size; i++) {
1920 if (!cache_bytes[i]) {
1921 cache[i] =
malloc(bytes);
1923 memcpy(cache[i], mem, bytes);
1924 cache_bytes[i] = bytes;
1935static int remove_nal_escapes(
unsigned char* dst,
const unsigned char* src,
int h264_data_bytes) {
1936 int i = 0, j = 0, zero_cnt = 0;
1937 for (j = 0; j < h264_data_bytes; j++) {
1938 if (zero_cnt == 2 && src[j] <= 3) {
1940 if (j == h264_data_bytes - 1) {
1942 }
else if (src[j + 1] <= 3) {
1966 int i, j = 4, cntz = 0;
1967 d[0] = d[1] = d[2] = 0;
1969 for (i = 0; i < n; i++) {
1971 if (cntz == 2 &&
byte <= 3) {
1984static void copy_bits(bit_reader_t* bs, bs_t* bd) {
1986 int bit_count = remaining_bits(bs);
1987 while (bit_count > 7) {
1990 h264e_bs_put_bits(bd, cb, bits);
1995 bits = GetBits(bit_count);
1996 for (; bit_count && ~bits & 1; bit_count--) {
2000 h264e_bs_put_bits(bd, bit_count, bits);
2004static int change_sps_id(bit_reader_t* bs, bs_t* bd,
int new_id,
int* old_id) {
2005 unsigned bits, sps_id, i, bytes;
2006 for (i = 0; i < 3; i++) {
2008 h264e_bs_put_bits(bd, 8, bits);
2010 sps_id = ue_bits(bs);
2016 h264e_bs_put_golomb(bd, sps_id);
2019 bytes = h264e_bs_byte_align(bd) / 8;
2027 unsigned pps_id = ue_bits(bs);
2028 unsigned sps_id = ue_bits(bs);
2032 pps_id = new_pps_id;
2037 h264e_bs_put_golomb(bd, pps_id);
2038 h264e_bs_put_golomb(bd, sps_id);
2041 bytes = h264e_bs_byte_align(bd) / 8;
2047 unsigned first_mb_in_slice = ue_bits(bs);
2048 unsigned slice_type = ue_bits(bs);
2049 unsigned pps_id = ue_bits(bs);
2055 h264e_bs_put_golomb(bd, first_mb_in_slice);
2056 h264e_bs_put_golomb(bd, slice_type);
2057 h264e_bs_put_golomb(bd, pps_id);
2062 const unsigned char* src,
2064 unsigned char* dst) {
2067 bit_reader_t bst[1];
2072 int payload_type = src[0] & 31;
2075 h264e_bs_init_bits(bd, dst + 1);
2076 init_bits(bs, src + 1, nalu_bytes - 1);
2077 h264e_bs_init_bits(bdt, dst + 1);
2078 init_bits(bst, src + 1, nalu_bytes - 1);
2080 switch (payload_type) {
2082 int cb = change_sps_id(bst, bdt, 0, &old_id);
2087 change_sps_id(bs, bd,
id, &old_id);
2090 int cb = patch_pps(h, bst, bdt, 0, &old_id);
2095 patch_pps(h, bs, bd,
id, &old_id);
2100 patch_slice_header(h, bs, bd);
2103 memcpy(dst, (
void*)src, nalu_bytes);
2107 nalu_bytes = 1 + h264e_bs_byte_align(bd) / 8;
2123static const uint8_t* find_start_code(
const uint8_t* h264_data,
int h264_data_bytes,
int* zcount) {
2124 const uint8_t* eof = h264_data + h264_data_bytes;
2129 p = found ? found : eof;
2130 while (p + zero_cnt < eof && !p[zero_cnt])
2132 if (zero_cnt >= 2 && p[zero_cnt] == 1) {
2133 *zcount = zero_cnt + 1;
2134 return p + zero_cnt + 1;
2146find_nal_unit(
const uint8_t* h264_data,
int h264_data_bytes,
int* pnal_unit_bytes) {
2147 const uint8_t* eof = h264_data + h264_data_bytes;
2149 const uint8_t* start = find_start_code(h264_data, h264_data_bytes, &zcount);
2152 stop = find_start_code(start, (
int)(eof - start), &zcount);
2153 while (stop > start && !stop[-1]) {
2158 *pnal_unit_bytes = (int)(stop - start - zcount);
2182#if MINIMP4_TRANSCODE_SPS_ID
2189#if MINIMP4_TRANSCODE_SPS_ID
2201 memset(h, 0,
sizeof(*h));
2205 const unsigned char* nal,
2207 unsigned timeStamp90kHz_next) {
2208 int payload_type = (nal[0] >> 1) & 0x3f;
2215 switch (payload_type) {
2232 unsigned char* tmp = (
unsigned char*)
malloc(4 + sizeof_nal);
2236 tmp[0] = (
unsigned char)(sizeof_nal >> 24);
2237 tmp[1] = (
unsigned char)(sizeof_nal >> 16);
2238 tmp[2] = (
unsigned char)(sizeof_nal >> 8);
2239 tmp[3] = (
unsigned char)(sizeof_nal);
2240 memcpy(tmp + 4, (
void*)nal, sizeof_nal);
2244 h->
mux, h->
mux_track_id, tmp, 4 + sizeof_nal, timeStamp90kHz_next, sample_kind);
2253 const unsigned char* nal,
2255 unsigned timeStamp90kHz_next) {
2256 const unsigned char* eof = nal + length;
2259#if MINIMP4_TRANSCODE_SPS_ID
2260 unsigned char *nal1, *nal2;
2262 nal = find_nal_unit(nal, (
int)(eof - nal), &sizeof_nal);
2266 ERR(mp4_h265_write_nal(h, nal, sizeof_nal, timeStamp90kHz_next));
2269 payload_type = nal[0] & 31;
2270 if (9 == payload_type)
2272#if MINIMP4_TRANSCODE_SPS_ID
2277 nal1 = (
unsigned char*)
malloc(sizeof_nal * 17 / 16 + 32);
2280 nal2 = (
unsigned char*)
malloc(sizeof_nal * 17 / 16 + 32);
2285 sizeof_nal = remove_nal_escapes(nal2, nal, sizeof_nal);
2293 sizeof_nal = transcode_nalu(&h->
sps_patcher, nal2, sizeof_nal, nal1);
2294 sizeof_nal = nal_put_esc(nal2, nal1, sizeof_nal);
2296 switch (payload_type) {
2303 goto exit_with_free;
2309 goto exit_with_free;
2314 goto exit_with_free;
2317 init_bits(bs, nal + 1, sizeof_nal - 4 - 1);
2318 unsigned first_mb_in_slice = ue_bits(bs);
2321 nal2[0] = (
unsigned char)((sizeof_nal - 4) >> 24);
2322 nal2[1] = (
unsigned char)((sizeof_nal - 4) >> 16);
2323 nal2[2] = (
unsigned char)((sizeof_nal - 4) >> 8);
2324 nal2[3] = (
unsigned char)((sizeof_nal - 4));
2325 if (first_mb_in_slice)
2327 else if (payload_type == 5)
2330 h->
mux, h->
mux_track_id, nal2, sizeof_nal, timeStamp90kHz_next, sample_kind);
2339 switch (payload_type) {
2358 unsigned char* tmp = (
unsigned char*)
malloc(4 + sizeof_nal);
2361 init_bits(bs, nal + 1, sizeof_nal - 1);
2362 unsigned first_mb_in_slice = ue_bits(bs);
2364 tmp[0] = (
unsigned char)(sizeof_nal >> 24);
2365 tmp[1] = (
unsigned char)(sizeof_nal >> 16);
2366 tmp[2] = (
unsigned char)(sizeof_nal >> 8);
2367 tmp[3] = (
unsigned char)(sizeof_nal);
2368 memcpy(tmp + 4, nal, sizeof_nal);
2369 if (first_mb_in_slice)
2371 else if (payload_type == 5)
2374 h->
mux, h->
mux_track_id, tmp, 4 + sizeof_nal, timeStamp90kHz_next, sample_kind);
2386#if MP4D_TRACE_SUPPORTED
2387#define TRACE(x) printf x
2389#define TRACE(x) printf x
2392#define NELEM(x) (sizeof(x) / sizeof((x)[0]))
2406static unsigned minimp4_read(
MP4D_demux_t* mp4,
int nb,
int* eof_flag) {
2411 v = (v << 8) | minimp4_fgets(mp4);
2413 v = (v << 8) | minimp4_fgets(mp4);
2415 v = (v << 8) | minimp4_fgets(mp4);
2418 v = (v << 8) | (last_byte = minimp4_fgets(mp4));
2420 if (last_byte < 0) {
2432 if (*payload_bytes < nb) {
2434 nb = (int)*payload_bytes;
2436 *payload_bytes -= nb;
2438 return minimp4_read(mp4, nb, eof_flag);
2451#define READ(n) read_payload(mp4, n, &payload_bytes, &eof_flag)
2454 boxsize_t t = MINIMP4_MIN(payload_bytes, n); \
2455 my_fseek(mp4, t, &eof_flag); \
2456 payload_bytes -= t; \
2458#define MALLOC(t, p, size) \
2459 p = (t)malloc(size); \
2461 ERROR("out of memory"); \
2467#define RETURN_ERROR(mess) \
2469 TRACE(("\nMP4 ERROR: " mess)); \
2477#define ERROR(mess) \
2483typedef enum { BOX_ATOM, BOX_OD } boxtype_t;
2501#if MP4D_TRACE_SUPPORTED
2511 TRACE((
"\nERROR: invlaid arguments!"));
2520 stack[0].format = BOX_ATOM;
2527 static const struct {
2529 unsigned max_version;
2530 unsigned use_track_flag;
2532#if MP4D_INFO_SUPPORTED
2540#if MP4D_TRACE_TIMESTAMPS
2558 static const struct {
2561 } g_envelope_box[] = {
2567 {BOX_trak, BOX_ATOM},
2568 {BOX_moov, BOX_ATOM},
2570 {BOX_mdia, BOX_ATOM},
2571 {BOX_tref, BOX_ATOM},
2572 {BOX_minf, BOX_ATOM},
2573 {BOX_dinf, BOX_ATOM},
2574 {BOX_stbl, BOX_ATOM},
2575 {BOX_stsd, BOX_ATOM},
2576 {BOX_mp4a, BOX_ATOM},
2577 {BOX_mp4s, BOX_ATOM},
2578#if MP4D_AVC_SUPPORTED
2579 {BOX_mp4v, BOX_ATOM},
2580 {BOX_avc1, BOX_ATOM},
2584#if MP4D_HEVC_SUPPORTED
2585 {BOX_hvc1, BOX_ATOM},
2587 {BOX_udta, BOX_ATOM},
2588 {BOX_meta, BOX_ATOM},
2589 {BOX_ilst, BOX_ATOM}};
2591 uint32_t FullAtomVersionAndFlags = 0;
2595#if MP4D_INFO_SUPPORTED
2596 unsigned char** ptag =
NULL;
2601 if (stack[depth].format == BOX_ATOM) {
2602 box_bytes = minimp4_read(mp4, 4, &eof_flag);
2603#if FIX_BAD_ANDROID_META_BOX
2604 broken_android_meta_hack:
2609 if (box_bytes >= 2 && box_bytes < 8) {
2610 ERROR(
"invalid box size (broken file?)");
2613 box_name = minimp4_read(mp4, 4, &eof_flag);
2617 if (box_bytes == 0 ||
2624 payload_bytes = box_bytes - 8;
2628 TRACE((
"\n64-bit chunk encountered"));
2630 box_bytes = minimp4_read(mp4, 4, &eof_flag);
2631#if MP4D_64BIT_SUPPORTED
2633 box_bytes |= minimp4_read(mp4, 4, &eof_flag);
2636 ERROR(
"UNSUPPORTED FEATURE: MP4BoxHeader(): 64-bit boxes not supported!");
2638 box_bytes = minimp4_read(mp4, 4, &eof_flag);
2640 if (box_bytes < 16) {
2641 ERROR(
"invalid box size (broken file?)");
2643 payload_bytes = box_bytes - 16;
2647 for (i = 0; i < NELEM(g_fullbox); i++) {
2648 if (box_name == g_fullbox[i].name) {
2649 FullAtomVersionAndFlags = READ(4);
2652#if FIX_BAD_ANDROID_META_BOX
2655 if (box_name == BOX_meta) {
2656 if (FullAtomVersionAndFlags >= 8 &&
2657 FullAtomVersionAndFlags < payload_bytes) {
2658 if (box_bytes > stack[depth].bytes) {
2659 ERROR(
"broken file structure!");
2661 stack[depth].bytes -= box_bytes;
2664 stack[depth].bytes = payload_bytes + 4;
2665 stack[depth].format = BOX_ATOM;
2666 box_bytes = FullAtomVersionAndFlags;
2667 TRACE((
"Bad metadata box detected (Android bug?)!\n"));
2668 goto broken_android_meta_hack;
2673 if ((FullAtomVersionAndFlags >> 24) > g_fullbox[i].max_version) {
2674 ERROR(
"unsupported box version!");
2676 if (g_fullbox[i].use_track_flag && !tr) {
2677 ERROR(
"broken file structure!");
2684 box_name = OD_BASE + minimp4_read(mp4, 1, &eof_flag);
2692 val = minimp4_read(mp4, 1, &eof_flag);
2695 ERROR(
"premature EOF!");
2697 payload_bytes = (payload_bytes << 7) | (val & 0x7F);
2699 }
while (val & 0x80);
2700 box_bytes += payload_bytes;
2703#if MP4D_TRACE_SUPPORTED
2704 box_path[depth] = (box_name >> 24) | (box_name << 24) | ((box_name >> 8) & 0x0000FF00) |
2705 ((box_name << 8) & 0x00FF0000);
2706 TRACE((
"%2d %8d %.*s (%d bytes remains for sibilings) \n",
2711 (
int)stack[depth].bytes));
2718 if (box_bytes > stack[depth].bytes) {
2719 TRACE((
"Wrong %c%c%c%c box size: broken file?\n",
2720 (box_name >> 24) & 255,
2721 (box_name >> 16) & 255,
2722 (box_name >> 8) & 255,
2724 box_bytes = stack[depth].bytes;
2726 payload_bytes = box_bytes - read_bytes;
2728 stack[depth].bytes -= box_bytes;
2740 if (box_name == BOX_stsz) {
2741 tr->
entry_size[i] = (sample_size ? sample_size : READ(4));
2743 switch (sample_size & 0xFF) {
2774#if MP4D_TRACE_TIMESTAMPS || MP4D_TIMESTAMPS_SUPPORTED
2776 unsigned count = READ(4);
2777 unsigned j, k = 0, ts = 0, ts_count = count;
2778#if MP4D_TIMESTAMPS_SUPPORTED
2779 MALLOC(
unsigned int*, tr->
timestamp, ts_count * 4);
2780 MALLOC(
unsigned int*, tr->
duration, ts_count * 4);
2783 for (i = 0; i < count; i++) {
2784 unsigned sc = READ(4);
2786 TRACE((
"sample %8d count %8d duration %8d\n", i, sc, d));
2787#if MP4D_TIMESTAMPS_SUPPORTED
2788 if (k + sc > ts_count) {
2795 for (j = 0; j < sc; j++) {
2804 unsigned count = READ(4);
2805 for (i = 0; i < count; i++) {
2810 TRACE((
"sample %8d count %8d decoding to composition offset %8d\n", i, sc, d));
2822 if (box_name == BOX_co64) {
2823#if !MP4D_64BIT_SUPPORTED
2825 ERROR(
"UNSUPPORTED FEATURE: 64-bit chunk_offset not supported!");
2834#if MP4D_INFO_SUPPORTED
2836 SKIP(((FullAtomVersionAndFlags >> 24) == 1) ? 8 + 8 : 4 + 4);
2838 mp4->
duration_hi = ((FullAtomVersionAndFlags >> 24) == 1) ? READ(4) : 0;
2840 SKIP(4 + 2 + 2 + 4 * 2 + 4 * 9 + 4 * 6 + 4);
2844 SKIP(((FullAtomVersionAndFlags >> 24) == 1) ? 8 + 8 : 4 + 4);
2846 tr->
duration_hi = ((FullAtomVersionAndFlags >> 24) == 1) ? READ(4) : 0;
2850 int ISO_639_2_T = READ(2);
2851 tr->
language[2] = (ISO_639_2_T & 31) + 0x60;
2853 tr->
language[1] = (ISO_639_2_T & 31) + 0x60;
2855 tr->
language[0] = (ISO_639_2_T & 31) + 0x60;
2872 ERROR(
"broken file structure!");
2907 ERROR(
"broken file structure!");
2914 ERROR(
"broken file structure!");
2916#if MP4D_INFO_SUPPORTED
2917 SKIP(6 * 1 + 2 + 4 * 2);
2926#if MP4D_AVC_SUPPORTED
2932 ERROR(
"broken file structure!");
2934#if MP4D_INFO_SUPPORTED
2935 SKIP(6 * 1 + 2 + 2 + 2 + 4 * 3);
2940 SKIP(4 + 4 + 4 + 2 + 32 + 2 + 2);
2957 tr->
dsi = (
unsigned char*)
malloc((
size_t)box_bytes);
2961 unsigned char* p = tr->
dsi;
2962 unsigned int configurationVersion = READ(1);
2963 unsigned int AVCProfileIndication = READ(1);
2964 unsigned int profile_compatibility = READ(1);
2965 unsigned int AVCLevelIndication = READ(1);
2967 unsigned int lengthSizeMinusOne = READ(1) & 3;
2969 (void)configurationVersion;
2970 (void)AVCProfileIndication;
2971 (void)profile_compatibility;
2972 (void)AVCLevelIndication;
2973 (void)lengthSizeMinusOne;
2975 for (spspps = 0; spspps < 2; spspps++) {
2976 unsigned int numOfSequenceParameterSets = READ(1);
2978 numOfSequenceParameterSets &= 31;
2980 *p++ = numOfSequenceParameterSets;
2981 for (i = 0; i < numOfSequenceParameterSets; i++) {
2982 unsigned k, sequenceParameterSetLength = READ(2);
2983 *p++ = sequenceParameterSetLength >> 8;
2984 *p++ = sequenceParameterSetLength;
2985 for (k = 0; k < sequenceParameterSetLength; k++) {
2995 unsigned flags = READ(3);
3003 unsigned bytecount = READ(1);
3016#if MP4D_INFO_SUPPORTED
3021 SKIP(1 + 3 + 4 + 4);
3027 if (!tr->
dsi && payload_bytes) {
3028 MALLOC(
unsigned char*, tr->
dsi, (
int)payload_bytes);
3029 for (i = 0; i < payload_bytes; i++) {
3031 minimp4_read(mp4, 1, &eof_flag);
3039 TRACE((
"[%c%c%c%c] %d\n",
3044 (
int)payload_bytes));
3047#if MP4D_INFO_SUPPORTED
3049 if (ptag && !*ptag && payload_bytes > 16) {
3055 TRACE((
"%2d %2d %2d ", size,
class, x1));
3057 SKIP(4 + 4 + 4 + 4);
3059 MALLOC(
unsigned char*, *ptag, (
unsigned)payload_bytes + 1);
3060 for (i = 0; payload_bytes != 0; i++) {
3061 (*ptag)[i] = READ(1);
3067 if (box_name == BOX_trak) {
3076 ERROR(
"out of memory");
3081 }
else if (box_name == BOX_meta) {
3086 for (i = 0; i < NELEM(g_envelope_box); i++) {
3087 if (box_name == g_envelope_box[i].name) {
3089 ERROR(
"too deep atoms nesting!");
3091 stack[depth].bytes = payload_bytes;
3092 stack[depth].format = g_envelope_box[i].type;
3098 if (i == NELEM(g_envelope_box)) {
3099 if (payload_bytes > file_size) {
3102 SKIP(payload_bytes);
3108 while (depth > 0 && !stack[depth].bytes) {
3112 }
while (!eof_flag);
3124static int sample_to_chunk(
MP4D_track_t* tr,
unsigned nsample,
unsigned* nfirst_sample_in_chunk) {
3125 unsigned chunk_group = 0, nc;
3127 *nfirst_sample_in_chunk = 0;
3144 *nfirst_sample_in_chunk = sum;
3153 unsigned* frame_bytes,
3154 unsigned* timestamp,
3155 unsigned* duration) {
3158 int nchunk = sample_to_chunk(tr, nsample, &ns);
3167 for (; ns < nsample; ns++) {
3174#if MP4D_TIMESTAMPS_SUPPORTED
3181#if MP4D_TIMESTAMPS_SUPPORTED
3202#if MP4D_TIMESTAMPS_SUPPORTED
3211#if MP4D_INFO_SUPPORTED
3221static int skip_spspps(
const unsigned char* p,
int nbytes,
int nskip) {
3223 for (i = 0; i < nskip; i++) {
3227 segmbytes = p[k] * 256 + p[k + 1];
3233static const void* MP4D_read_spspps(
3234 const MP4D_demux_t* mp4,
unsigned int ntrack,
int pps_flag,
int nsps,
int* sps_bytes) {
3235 int sps_count, skip_bytes;
3237 unsigned char* p = mp4->
track[ntrack].
dsi;
3245 sps_count = p[bytepos++];
3246 skip_bytes = skip_spspps(p + bytepos, mp4->
track[ntrack].
dsi_bytes - bytepos, sps_count);
3249 bytepos += skip_bytes;
3253 sps_count = p[bytepos++];
3254 if (nsps >= sps_count)
3256 skip_bytes = skip_spspps(p + bytepos, mp4->
track[ntrack].
dsi_bytes - bytepos, nsps);
3259 bytepos += skip_bytes;
3260 *sps_bytes = p[bytepos] * 256 + p[bytepos + 1];
3261 return p + bytepos + 2;
3265 return MP4D_read_spspps(mp4, ntrack, 0, nsps, sps_bytes);
3269 return MP4D_read_spspps(mp4, ntrack, 1, npps, pps_bytes);
3272#if MP4D_PRINT_INFO_SUPPORTED
3280static const char* GetMP4StreamTypeName(
int streamType) {
3281 switch (streamType) {
3285 return "ObjectDescriptorStream";
3287 return "ClockReferenceStream";
3289 return "SceneDescriptionStream";
3291 return "VisualStream";
3293 return "AudioStream";
3295 return "MPEG7Stream";
3297 return "IPMPStream";
3299 return "ObjectContentInfoStream";
3301 return "MPEGJStream";
3303 if (streamType >= 0x20 && streamType <= 0x3F) {
3304 return "User private";
3306 return "Reserved for ISO use";
3314static const char* GetMP4ObjectTypeName(
int objectTypeIndication) {
3315 switch (objectTypeIndication) {
3319 return "Systems ISO/IEC 14496-1";
3321 return "Systems ISO/IEC 14496-1";
3323 return "Visual ISO/IEC 14496-2";
3325 return "Audio ISO/IEC 14496-3";
3327 return "Visual ISO/IEC 13818-2 Simple Profile";
3329 return "Visual ISO/IEC 13818-2 Main Profile";
3331 return "Visual ISO/IEC 13818-2 SNR Profile";
3333 return "Visual ISO/IEC 13818-2 Spatial Profile";
3335 return "Visual ISO/IEC 13818-2 High Profile";
3337 return "Visual ISO/IEC 13818-2 422 Profile";
3339 return "Audio ISO/IEC 13818-7 Main Profile";
3341 return "Audio ISO/IEC 13818-7 LC Profile";
3343 return "Audio ISO/IEC 13818-7 SSR Profile";
3345 return "Audio ISO/IEC 13818-3";
3347 return "Visual ISO/IEC 11172-2";
3349 return "Audio ISO/IEC 11172-3";
3351 return "Visual ISO/IEC 10918-1";
3353 return "no object type specified";
3355 if (objectTypeIndication >= 0xC0 && objectTypeIndication <= 0xFE)
3356 return "User private";
3358 return "Reserved for ISO use";
3393 printf(
"\nMP4 FILE: %d tracks found. Movie time %.2f sec\n",
3396#define STR_TAG(name) \
3397 if (mp4->tag.name) \
3398 printf("%10s = %s\n", #name, mp4->tag.name)
3405 printf(
"\nNo|type|lng| duration | bitrate| %-23s| Object type",
"Stream type");
3409 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
XE_LIB void * memchr(const void *src, int c, size_t n)
Definition string.cpp:883
XETime t
Definition main.cpp:53
void * memcpy(void *Dest, const void *Src, ACPI_SIZE Count)
Definition utclib.c:310
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition utclib.c:222
ACPI_SIZE strlen(const char *String)
Definition utclib.c:379
void * memset(void *Dest, int Value, ACPI_SIZE Count)
Definition utclib.c:346
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
XE_LIB void * realloc(void *address, unsigned int new_size)
Definition _heap.cpp:6421
unsigned duration_hi
Definition minimp4.h:281
unsigned char * album
Definition minimp4.h:292
unsigned timescale
Definition minimp4.h:285
struct MP4D_demux_tag::@502 tag
int64_t read_size
Definition minimp4.h:269
void * token
Definition minimp4.h:272
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
struct MP4D_track_t::@499::@501 video
union MP4D_track_t::@499 SampleDescription
unsigned sample_to_chunk_count
Definition minimp4.h:251
unsigned chunk_count
Definition minimp4.h:254
unsigned width
Definition minimp4.h:240
unsigned height
Definition minimp4.h:241
unsigned * timestamp
Definition minimp4.h:258
unsigned samplerate_hz
Definition minimp4.h:235
unsigned object_type_indication
Definition minimp4.h:192
unsigned timescale
Definition minimp4.h:210
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
unsigned handler_type
Definition minimp4.h:203
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
struct MP4D_track_t::@499::@500 audio
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
unsigned default_duration
Definition minimp4.h:141
struct MP4E_track_t::@496::@498 v
union MP4E_track_t::@496 u
int map_pps[MINIMP4_MAX_PPS]
Definition minimp4.h:313
void * sps_cache[MINIMP4_MAX_SPS]
Definition minimp4.h:307
int sps_bytes[MINIMP4_MAX_SPS]
Definition minimp4.h:309
void * pps_cache[MINIMP4_MAX_PPS]
Definition minimp4.h:308
int map_sps[MINIMP4_MAX_SPS]
Definition minimp4.h:312
int pps_bytes[MINIMP4_MAX_PPS]
Definition minimp4.h:310
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
void * malloc(unsigned nSize)
Definition uspios.c:31
void free(void *pBlock)
Definition uspios.c:35
size_t(* write_callback)(struct __VFS_NODE__ *node, struct __VFS_NODE__ *file, uint64_t *buffer, uint32_t length)
Definition vfs.h:85
size_t(* read_callback)(struct __VFS_NODE__ *node, struct __VFS_NODE__ *file, uint64_t *buffer, uint32_t length)
Definition vfs.h:83