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
116#define HEVC_NAL_VPS 32
117#define HEVC_NAL_SPS 33
118#define HEVC_NAL_PPS 34
119#define HEVC_NAL_BLA_W_LP 16
120#define HEVC_NAL_CRA_NUT 21
139 unsigned object_type_indication;
142 unsigned char language[4];
148 unsigned default_duration;
155 unsigned channelcount;
176 unsigned sample_count;
203 unsigned object_type_indication;
205#if MP4D_INFO_SUPPORTED
214 unsigned handler_type;
217 unsigned duration_hi;
218 unsigned duration_lo;
224 unsigned avg_bitrate_bps;
227 unsigned char language[4];
240 unsigned stream_type;
247 unsigned channelcount;
248 unsigned samplerate_hz;
263 unsigned* entry_size;
265 unsigned sample_to_chunk_count;
268 unsigned chunk_count;
271#if MP4D_TIMESTAMPS_SUPPORTED
291#if MP4D_INFO_SUPPORTED
306 unsigned char*
title;
308 unsigned char*
album;
311 unsigned char*
genre;
337#if MINIMP4_TRANSCODE_SPS_ID
393#if MP4D_PRINT_INFO_SUPPORTED
489#if defined(MINIMP4_IMPLEMENTATION) && !defined(MINIMP4_IMPLEMENTATION_GUARD)
490#define MINIMP4_IMPLEMENTATION_GUARD
492#define FOUR_CHAR_INT(a, b, c, d) (((uint32_t)(a) << 24) | ((b) << 16) | ((c) << 8) | (d))
495 BOX_co64 = FOUR_CHAR_INT(
'c',
'o',
'6',
'4'),
496 BOX_stco = FOUR_CHAR_INT(
's',
't',
'c',
'o'),
497 BOX_crhd = FOUR_CHAR_INT(
'c',
'r',
'h',
'd'),
498 BOX_ctts = FOUR_CHAR_INT(
'c',
't',
't',
's'),
499 BOX_cprt = FOUR_CHAR_INT(
'c',
'p',
'r',
't'),
500 BOX_url_ = FOUR_CHAR_INT(
'u',
'r',
'l',
' '),
501 BOX_urn_ = FOUR_CHAR_INT(
'u',
'r',
'n',
' '),
502 BOX_dinf = FOUR_CHAR_INT(
'd',
'i',
'n',
'f'),
503 BOX_dref = FOUR_CHAR_INT(
'd',
'r',
'e',
'f'),
504 BOX_stdp = FOUR_CHAR_INT(
's',
't',
'd',
'p'),
505 BOX_edts = FOUR_CHAR_INT(
'e',
'd',
't',
's'),
506 BOX_elst = FOUR_CHAR_INT(
'e',
'l',
's',
't'),
507 BOX_uuid = FOUR_CHAR_INT(
'u',
'u',
'i',
'd'),
508 BOX_free = FOUR_CHAR_INT(
'f',
'r',
'e',
'e'),
509 BOX_hdlr = FOUR_CHAR_INT(
'h',
'd',
'l',
'r'),
510 BOX_hmhd = FOUR_CHAR_INT(
'h',
'm',
'h',
'd'),
511 BOX_hint = FOUR_CHAR_INT(
'h',
'i',
'n',
't'),
512 BOX_mdia = FOUR_CHAR_INT(
'm',
'd',
'i',
'a'),
513 BOX_mdat = FOUR_CHAR_INT(
'm',
'd',
'a',
't'),
514 BOX_mdhd = FOUR_CHAR_INT(
'm',
'd',
'h',
'd'),
515 BOX_minf = FOUR_CHAR_INT(
'm',
'i',
'n',
'f'),
516 BOX_moov = FOUR_CHAR_INT(
'm',
'o',
'o',
'v'),
517 BOX_mvhd = FOUR_CHAR_INT(
'm',
'v',
'h',
'd'),
518 BOX_stsd = FOUR_CHAR_INT(
's',
't',
's',
'd'),
519 BOX_stsz = FOUR_CHAR_INT(
's',
't',
's',
'z'),
520 BOX_stz2 = FOUR_CHAR_INT(
's',
't',
'z',
'2'),
521 BOX_stbl = FOUR_CHAR_INT(
's',
't',
'b',
'l'),
522 BOX_stsc = FOUR_CHAR_INT(
's',
't',
's',
'c'),
523 BOX_stsh = FOUR_CHAR_INT(
's',
't',
's',
'h'),
524 BOX_skip = FOUR_CHAR_INT(
's',
'k',
'i',
'p'),
525 BOX_smhd = FOUR_CHAR_INT(
's',
'm',
'h',
'd'),
526 BOX_stss = FOUR_CHAR_INT(
's',
't',
's',
's'),
527 BOX_stts = FOUR_CHAR_INT(
's',
't',
't',
's'),
528 BOX_trak = FOUR_CHAR_INT(
't',
'r',
'a',
'k'),
529 BOX_tkhd = FOUR_CHAR_INT(
't',
'k',
'h',
'd'),
530 BOX_tref = FOUR_CHAR_INT(
't',
'r',
'e',
'f'),
531 BOX_udta = FOUR_CHAR_INT(
'u',
'd',
't',
'a'),
532 BOX_vmhd = FOUR_CHAR_INT(
'v',
'm',
'h',
'd'),
533 BOX_url = FOUR_CHAR_INT(
'u',
'r',
'l',
' '),
534 BOX_urn = FOUR_CHAR_INT(
'u',
'r',
'n',
' '),
536 BOX_gnrv = FOUR_CHAR_INT(
'g',
'n',
'r',
'v'),
537 BOX_gnra = FOUR_CHAR_INT(
'g',
'n',
'r',
'a'),
540 BOX_ftyp = FOUR_CHAR_INT(
'f',
't',
'y',
'p'),
541 BOX_padb = FOUR_CHAR_INT(
'p',
'a',
'd',
'b'),
544 BOX_sdhd = FOUR_CHAR_INT(
's',
'd',
'h',
'd'),
545 BOX_dpnd = FOUR_CHAR_INT(
'd',
'p',
'n',
'd'),
546 BOX_iods = FOUR_CHAR_INT(
'i',
'o',
'd',
's'),
547 BOX_odhd = FOUR_CHAR_INT(
'o',
'd',
'h',
'd'),
548 BOX_mpod = FOUR_CHAR_INT(
'm',
'p',
'o',
'd'),
549 BOX_nmhd = FOUR_CHAR_INT(
'n',
'm',
'h',
'd'),
550 BOX_esds = FOUR_CHAR_INT(
'e',
's',
'd',
's'),
551 BOX_sync = FOUR_CHAR_INT(
's',
'y',
'n',
'c'),
552 BOX_ipir = FOUR_CHAR_INT(
'i',
'p',
'i',
'r'),
553 BOX_mp4s = FOUR_CHAR_INT(
'm',
'p',
'4',
's'),
554 BOX_mp4a = FOUR_CHAR_INT(
'm',
'p',
'4',
'a'),
555 BOX_mp4v = FOUR_CHAR_INT(
'm',
'p',
'4',
'v'),
558 BOX_avc1 = FOUR_CHAR_INT(
'a',
'v',
'c',
'1'),
559 BOX_avc2 = FOUR_CHAR_INT(
'a',
'v',
'c',
'2'),
560 BOX_svc1 = FOUR_CHAR_INT(
's',
'v',
'c',
'1'),
561 BOX_avcC = FOUR_CHAR_INT(
'a',
'v',
'c',
'C'),
562 BOX_svcC = FOUR_CHAR_INT(
's',
'v',
'c',
'C'),
563 BOX_btrt = FOUR_CHAR_INT(
'b',
't',
'r',
't'),
564 BOX_m4ds = FOUR_CHAR_INT(
'm',
'4',
'd',
's'),
565 BOX_seib = FOUR_CHAR_INT(
's',
'e',
'i',
'b'),
568 BOX_hev1 = FOUR_CHAR_INT(
'h',
'e',
'v',
'1'),
569 BOX_hvc1 = FOUR_CHAR_INT(
'h',
'v',
'c',
'1'),
570 BOX_hvcC = FOUR_CHAR_INT(
'h',
'v',
'c',
'C'),
573 BOX_samr = FOUR_CHAR_INT(
's',
'a',
'm',
'r'),
574 BOX_sawb = FOUR_CHAR_INT(
's',
'a',
'w',
'b'),
575 BOX_damr = FOUR_CHAR_INT(
'd',
'a',
'm',
'r'),
576 BOX_s263 = FOUR_CHAR_INT(
's',
'2',
'6',
'3'),
577 BOX_d263 = FOUR_CHAR_INT(
'd',
'2',
'6',
'3'),
580 BOX_mvex = FOUR_CHAR_INT(
'm',
'v',
'e',
'x'),
581 BOX_trex = FOUR_CHAR_INT(
't',
'r',
'e',
'x'),
582 BOX_moof = FOUR_CHAR_INT(
'm',
'o',
'o',
'f'),
583 BOX_mfhd = FOUR_CHAR_INT(
'm',
'f',
'h',
'd'),
584 BOX_traf = FOUR_CHAR_INT(
't',
'r',
'a',
'f'),
585 BOX_tfhd = FOUR_CHAR_INT(
't',
'f',
'h',
'd'),
586 BOX_tfdt = FOUR_CHAR_INT(
't',
'f',
'd',
't'),
587 BOX_trun = FOUR_CHAR_INT(
't',
'r',
'u',
'n'),
588 BOX_mehd = FOUR_CHAR_INT(
'm',
'e',
'h',
'd'),
593 OD_BASE = FOUR_CHAR_INT(
'$',
'$',
'$',
'0'),
594 OD_ESD = FOUR_CHAR_INT(
'$',
'$',
'$',
'3'),
595 OD_DCD = FOUR_CHAR_INT(
'$',
'$',
'$',
'4'),
596 OD_DSI = FOUR_CHAR_INT(
'$',
'$',
'$',
'5'),
597 OD_SLC = FOUR_CHAR_INT(
'$',
'$',
'$',
'6'),
599 BOX_meta = FOUR_CHAR_INT(
'm',
'e',
't',
'a'),
600 BOX_ilst = FOUR_CHAR_INT(
'i',
'l',
's',
't'),
603 BOX_calb = FOUR_CHAR_INT(
'\xa9',
'a',
'l',
'b'),
604 BOX_cart = FOUR_CHAR_INT(
'\xa9',
'a',
'r',
't'),
605 BOX_aART = FOUR_CHAR_INT(
'a',
'A',
'R',
'T'),
606 BOX_ccmt = FOUR_CHAR_INT(
'\xa9',
'c',
'm',
't'),
607 BOX_cday = FOUR_CHAR_INT(
'\xa9',
'd',
'a',
'y'),
608 BOX_cnam = FOUR_CHAR_INT(
'\xa9',
'n',
'a',
'm'),
609 BOX_cgen = FOUR_CHAR_INT(
'\xa9',
'g',
'e',
'n'),
610 BOX_trkn = FOUR_CHAR_INT(
't',
'r',
'k',
'n'),
611 BOX_disk = FOUR_CHAR_INT(
'd',
'i',
's',
'k'),
612 BOX_cwrt = FOUR_CHAR_INT(
'\xa9',
'w',
'r',
't'),
613 BOX_ctoo = FOUR_CHAR_INT(
'\xa9',
't',
'o',
'o'),
614 BOX_tmpo = FOUR_CHAR_INT(
't',
'm',
'p',
'o'),
615 BOX_cpil = FOUR_CHAR_INT(
'c',
'p',
'i',
'l'),
616 BOX_covr = FOUR_CHAR_INT(
'c',
'o',
'v',
'r'),
617 BOX_rtng = FOUR_CHAR_INT(
'r',
't',
'n',
'g'),
618 BOX_cgrp = FOUR_CHAR_INT(
'\xa9',
'g',
'r',
'p'),
619 BOX_stik = FOUR_CHAR_INT(
's',
't',
'i',
'k'),
620 BOX_pcst = FOUR_CHAR_INT(
'p',
'c',
's',
't'),
621 BOX_catg = FOUR_CHAR_INT(
'c',
'a',
't',
'g'),
622 BOX_keyw = FOUR_CHAR_INT(
'k',
'e',
'y',
'w'),
623 BOX_purl = FOUR_CHAR_INT(
'p',
'u',
'r',
'l'),
624 BOX_egid = FOUR_CHAR_INT(
'e',
'g',
'i',
'd'),
625 BOX_desc = FOUR_CHAR_INT(
'd',
'e',
's',
'c'),
626 BOX_clyr = FOUR_CHAR_INT(
'\xa9',
'l',
'y',
'r'),
627 BOX_tven = FOUR_CHAR_INT(
't',
'v',
'e',
'n'),
628 BOX_tves = FOUR_CHAR_INT(
't',
'v',
'e',
's'),
629 BOX_tvnn = FOUR_CHAR_INT(
't',
'v',
'n',
'n'),
630 BOX_tvsh = FOUR_CHAR_INT(
't',
'v',
's',
'h'),
631 BOX_tvsn = FOUR_CHAR_INT(
't',
'v',
's',
'n'),
632 BOX_purd = FOUR_CHAR_INT(
'p',
'u',
'r',
'd'),
633 BOX_pgap = FOUR_CHAR_INT(
'p',
'g',
'a',
'p'),
636 BOX_cART = FOUR_CHAR_INT(
'\xa9',
'A',
'R',
'T'),
637 BOX_gnre = FOUR_CHAR_INT(
'g',
'n',
'r',
'e'),
640 BOX_auth = FOUR_CHAR_INT(
'a',
'u',
't',
'h'),
641 BOX_titl = FOUR_CHAR_INT(
't',
'i',
't',
'l'),
642 BOX_dscp = FOUR_CHAR_INT(
'd',
's',
'c',
'p'),
643 BOX_perf = FOUR_CHAR_INT(
'p',
'e',
'r',
'f'),
644 BOX_mean = FOUR_CHAR_INT(
'm',
'e',
'a',
'n'),
645 BOX_name = FOUR_CHAR_INT(
'n',
'a',
'm',
'e'),
646 BOX_data = FOUR_CHAR_INT(
'd',
'a',
't',
'a'),
649 BOX_albm = FOUR_CHAR_INT(
'a',
'l',
'b',
'm'),
650 BOX_yrrc = FOUR_CHAR_INT(
'y',
'r',
'r',
'c')
654#define MP4E_HANDLER_TYPE_VIDE 0x76696465
656#define MP4E_HANDLER_TYPE_SOUN 0x736F756E
659#define MP4E_HANDLER_TYPE_GESM 0x6765736D
666 unsigned flag_random_access;
678 minimp4_vector_t smpl;
679 minimp4_vector_t pending_sample;
681 minimp4_vector_t vsps;
682 minimp4_vector_t vpps;
683 minimp4_vector_t vvps;
687typedef struct MP4E_mux_tag
689 minimp4_vector_t tracks;
696 int sequential_mode_flag;
697 int enable_fragmentation;
702static const unsigned char box_ftyp[] = {
704 0,0,0,0x18,
'f',
't',
'y',
'p',
705 'm',
'p',
'4',
'2',0,0,0,0,
706 'm',
'p',
'4',
'2',
'i',
's',
'o',
'm',
709 0,0,0,0x20,
'f',
't',
'y',
'p',
710 'i',
's',
'o',
'm',0,0,2,0,
711 'm',
'p',
'4',
'1',
'i',
's',
'o',
'm',
712 'i',
's',
'o',
'2',
'a',
'v',
'c',
'1',
719#define WR(x, n) *p++ = (unsigned char)((x) >> 8*n)
720#define WRITE_1(x) WR(x, 0);
721#define WRITE_2(x) WR(x, 1); WR(x, 0);
722#define WRITE_3(x) WR(x, 2); WR(x, 1); WR(x, 0);
723#define WRITE_4(x) WR(x, 3); WR(x, 2); WR(x, 1); WR(x, 0);
724#define WR4(p, x) (p)[0] = (char)((x) >> 8*3); (p)[1] = (char)((x) >> 8*2); (p)[2] = (char)((x) >> 8*1); (p)[3] = (char)((x));
727#define END_ATOM --stack; WR4((unsigned char*)*stack, p - *stack);
730#define ATOM(x) *stack++ = p; p += 4; WRITE_4(x);
733#define ATOM_FULL(x, flag) ATOM(x); WRITE_4(flag);
735#define ERR(func) { int err = func; if (err) return err; }
740static int minimp4_vector_init(minimp4_vector_t* h,
int capacity)
743 h->capacity = capacity;
744 h->data = capacity ? (
unsigned char*)
malloc(capacity) :
NULL;
745 return !capacity || !!h->data;
751static void minimp4_vector_reset(minimp4_vector_t* h)
755 memset(h, 0,
sizeof(minimp4_vector_t));
761static int minimp4_vector_grow(minimp4_vector_t* h,
int bytes)
764 int new_size = h->capacity * 2 + 1024;
765 if (new_size < h->capacity + bytes)
766 new_size = h->capacity + bytes + 1024;
767 p =
realloc(h->data, new_size);
770 h->data = (
unsigned char*)p;
771 h->capacity = new_size;
780static unsigned char* minimp4_vector_alloc_tail(minimp4_vector_t* h,
int bytes)
783 if (!h->data && !minimp4_vector_init(h, 2 * bytes + 1024))
785 if ((h->capacity - h->bytes) < bytes && !minimp4_vector_grow(h, bytes))
788 assert((h->capacity - h->bytes) >= bytes);
789 p = h->data + h->bytes;
797static unsigned char* minimp4_vector_put(minimp4_vector_t* h,
const void* buf,
int bytes)
799 unsigned char* tail = minimp4_vector_alloc_tail(h, bytes);
801 memcpy(tail, (
void*)buf, bytes);
817 mux->sequential_mode_flag = sequential_mode_flag || enable_fragmentation;
818 mux->enable_fragmentation = enable_fragmentation;
819 mux->fragments_count = 0;
822 mux->text_comment =
NULL;
823 mux->write_pos =
sizeof(box_ftyp);
825 if (!mux->sequential_mode_flag)
827 if (mux->write_callback(mux->write_pos, box_ftyp, 8, mux->token))
832 mux->write_pos += 16;
834 minimp4_vector_init(&mux->tracks, 2 *
sizeof(track_t));
844 int ntr = mux->tracks.bytes /
sizeof(track_t);
846 if (!mux || !track_data)
849 tr = (track_t*)minimp4_vector_alloc_tail(&mux->tracks,
sizeof(track_t));
852 memset(tr, 0,
sizeof(track_t));
853 memcpy(&tr->info, (
void*)track_data,
sizeof(*track_data));
854 if (!minimp4_vector_init(&tr->smpl, 256))
856 minimp4_vector_init(&tr->vsps, 0);
857 minimp4_vector_init(&tr->vpps, 0);
858 minimp4_vector_init(&tr->pending_sample, 0);
862static const unsigned char* next_dsi(
const unsigned char* p,
const unsigned char*
end,
int* bytes)
866 *bytes = p[0] * 256 + p[1];
873static int append_mem(minimp4_vector_t* v,
const void* mem,
int bytes)
876 unsigned char size[2];
877 const unsigned char* p = v->data;
878 for (i = 0; i + 2 < v->bytes;)
880 int cb = p[i] * 256 + p[i + 1];
881 if (cb == bytes && !
memcmp(p + i + 2, mem, cb))
885 size[0] = bytes >> 8;
887 return minimp4_vector_put(v, size, 2) && minimp4_vector_put(v, mem, bytes);
890static int items_count(minimp4_vector_t* v)
893 const unsigned char* p = v->data;
894 for (i = 0; i + 2 < v->bytes;)
896 int cb = p[i] * 256 + p[i + 1];
905 track_t* tr = ((track_t*)mux->tracks.data) + track_id;
915 track_t* tr = ((track_t*)mux->tracks.data) + track_id;
922 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)
936 unsigned i, sum_duration = 0;
937 const sample_t* s = (
const sample_t*)tr->smpl.data;
938 for (i = 0; i < tr->smpl.bytes /
sizeof(sample_t); i++)
940 sum_duration += s[i].duration;
945static int write_pending_data(
MP4E_mux_t* mux, track_t* tr)
948 if (tr->pending_sample.bytes > 0 && tr->smpl.bytes >=
sizeof(sample_t))
952 unsigned char base[8], * p = base;
954 assert(mux->sequential_mode_flag);
957 assert(mux->sequential_mode_flag);
958 WRITE_4(tr->pending_sample.bytes + 8);
960 ERR(mux->write_callback(mux->write_pos, base, p - base, mux->token));
961 mux->write_pos += p - base;
964 smpl_desc = ((sample_t*)minimp4_vector_alloc_tail(&tr->smpl, 0)) - 1;
965 smpl_desc->size = tr->pending_sample.bytes;
966 smpl_desc->offset = (
boxsize_t)mux->write_pos;
969 ERR(mux->write_callback(mux->write_pos, tr->pending_sample.data, tr->pending_sample.bytes, mux->token));
970 mux->write_pos += tr->pending_sample.bytes;
973 tr->pending_sample.bytes = 0;
978static int add_sample_descriptor(
MP4E_mux_t* mux, track_t* tr,
int data_bytes,
int duration,
int kind)
981 smp.size = data_bytes;
983 smp.duration = (duration ? duration : tr->info.default_duration);
985 return NULL != minimp4_vector_put(&tr->smpl, &smp,
sizeof(sample_t));
993static int mp4e_write_fragment_header(
MP4E_mux_t* mux,
int track_num,
int data_bytes,
int duration,
int kind
999 unsigned char base[888], * p = base;
1000 unsigned char* stack_base[20];
1001 unsigned char** stack = stack_base;
1002 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)
1035#if MP4D_TFDT_SUPPORT
1036 ATOM_FULL(BOX_tfdt, 0x01000000)
1037 WRITE_4(timestamp >> 32);
1038 WRITE_4(timestamp & 0xffffffff);
1041 if (tr->info.track_media_kind ==
e_audio)
1046 ATOM_FULL(BOX_trun, flags)
1048 pdata_offset = p; p += 4;
1049 WRITE_4(data_bytes);
1059 ATOM_FULL(BOX_trun, flags)
1061 pdata_offset = p; p += 4;
1064 WRITE_4(data_bytes);
1073 ATOM_FULL(BOX_trun, flags)
1075 pdata_offset = p; p += 4;
1077 WRITE_4(data_bytes);
1082 WR4(pdata_offset, (p - base) + 8);
1084 ERR(mux->write_callback(mux->write_pos, base, p - base, mux->token));
1085 mux->write_pos += p - base;
1091 unsigned char base[8], * p = base;
1094 ERR(mux->write_callback(mux->write_pos, base, p - base, mux->token));
1095 mux->write_pos += p - base;
1107 tr = ((track_t*)mux->tracks.data) + track_num;
1109 if (mux->enable_fragmentation)
1111#if MP4D_TFDT_SUPPORT
1115 if (!mux->fragments_count++)
1116 ERR(mp4e_flush_index(mux));
1118#if MP4D_TFDT_SUPPORT
1119 ERR(mp4e_write_fragment_header(mux, track_num, data_bytes, duration, kind, timestamp));
1121 ERR(mp4e_write_fragment_header(mux, track_num, data_bytes, duration, kind));
1124 ERR(mp4e_write_mdat_box(mux, data_bytes + 8));
1125 ERR(mux->write_callback(mux->write_pos, data, data_bytes, mux->token));
1126 mux->write_pos += data_bytes;
1132 if (mux->sequential_mode_flag)
1133 ERR(write_pending_data(mux, tr));
1134 if (!add_sample_descriptor(mux, tr, data_bytes, duration, kind))
1139 if (!mux->sequential_mode_flag)
1141 sample_t* smpl_desc;
1142 if (tr->smpl.bytes <
sizeof(sample_t))
1145 smpl_desc = (sample_t*)(tr->smpl.data + tr->smpl.bytes) - 1;
1146 smpl_desc->size += data_bytes;
1150 if (mux->sequential_mode_flag)
1152 if (!minimp4_vector_put(&tr->pending_sample, data, data_bytes))
1157 ERR(mux->write_callback(mux->write_pos, data, data_bytes, mux->token));
1158 mux->write_pos += data_bytes;
1166static int od_size_of_size(
int size)
1168 int i, size_of_size = 1;
1169 for (i = size; i > 0x7F; i -= 0x7F)
1171 return size_of_size;
1182 if (!mux || !comment)
1184 if (mux->text_comment)
1185 free(mux->text_comment);
1186 mux->text_comment =
strdup(comment);
1187 if (!mux->text_comment)
1197 unsigned char* stack_base[20];
1198 unsigned char** stack = stack_base;
1199 unsigned char* base, * p;
1200 unsigned int ntr, index_bytes, ntracks = mux->tracks.bytes /
sizeof(track_t);
1209#define FILE_HEADER_BYTES 256
1210#define TRACK_HEADER_BYTES 512
1211 index_bytes = FILE_HEADER_BYTES;
1212 if (mux->text_comment)
1213 index_bytes += 128 +
strlen(mux->text_comment);
1214 for (ntr = 0; ntr < ntracks; ntr++)
1216 track_t* tr = ((track_t*)mux->tracks.data) + ntr;
1217 index_bytes += TRACK_HEADER_BYTES;
1219 index_bytes += tr->smpl.bytes * (
sizeof(sample_t) + 4 + 4) /
sizeof(sample_t);
1220 index_bytes += tr->vsps.bytes;
1221 index_bytes += tr->vpps.bytes;
1223 ERR(write_pending_data(mux, tr));
1226 base = (
unsigned char*)
malloc(index_bytes);
1231 if (!mux->sequential_mode_flag)
1238 int64_t size = mux->write_pos -
sizeof(box_ftyp);
1240 if (size > size_limit)
1244 WRITE_4((size >> 32) & 0xffffffff);
1245 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);
1267 track_t* tr = ((track_t*)mux->tracks.data) + 0;
1268 unsigned duration = get_duration(tr);
1269 duration = (unsigned)(duration * 1LL * MOOV_TIMESCALE / tr->info.time_scale);
1270 WRITE_4(MOOV_TIMESCALE);
1274 WRITE_4(0x00010000);
1281 WRITE_4(0x00010000); WRITE_4(0); WRITE_4(0);
1282 WRITE_4(0); WRITE_4(0x00010000); WRITE_4(0);
1283 WRITE_4(0); WRITE_4(0); WRITE_4(0x40000000);
1286 WRITE_4(0); WRITE_4(0); WRITE_4(0);
1287 WRITE_4(0); WRITE_4(0); WRITE_4(0);
1292 WRITE_4(ntracks + 1);
1295 for (ntr = 0; ntr < ntracks; ntr++)
1297 track_t* tr = ((track_t*)mux->tracks.data) + ntr;
1298 unsigned duration = get_duration(tr);
1299 int samples_count = tr->smpl.bytes /
sizeof(sample_t);
1300 const sample_t* sample = (
const sample_t*)tr->smpl.data;
1301 unsigned handler_type;
1302 const char* handler_ascii =
NULL;
1304 if (mux->enable_fragmentation)
1306 else if (samples_count <= 0)
1309 switch (tr->info.track_media_kind)
1312 handler_type = MP4E_HANDLER_TYPE_SOUN;
1313 handler_ascii =
"SoundHandler";
1316 handler_type = MP4E_HANDLER_TYPE_VIDE;
1317 handler_ascii =
"VideoHandler";
1327 ATOM_FULL(BOX_tkhd, 7);
1332 WRITE_4((
unsigned)(duration * 1LL * MOOV_TIMESCALE / tr->info.time_scale));
1333 WRITE_4(0); WRITE_4(0);
1340 WRITE_4(0x00010000); WRITE_4(0); WRITE_4(0);
1341 WRITE_4(0); WRITE_4(0x00010000); WRITE_4(0);
1342 WRITE_4(0); WRITE_4(0); WRITE_4(0x40000000);
1344 if (tr->info.track_media_kind ==
e_audio || tr->info.track_media_kind ==
e_private)
1351 WRITE_4(tr->info.u.v.width * 0x10000);
1352 WRITE_4(tr->info.u.v.height * 0x10000);
1357 ATOM_FULL(BOX_mdhd, 0);
1360 WRITE_4(tr->info.time_scale);
1363 int lang_code = ((tr->info.language[0] & 31) << 10) | ((tr->info.language[1] & 31) << 5) | (tr->info.language[2] & 31);
1369 ATOM_FULL(BOX_hdlr, 0);
1371 WRITE_4(handler_type);
1372 WRITE_4(0); WRITE_4(0); WRITE_4(0);
1378 for (i = 0; i < (int)
strlen(handler_ascii) + 1; i++)
1380 WRITE_1(handler_ascii[i]);
1391 if (tr->info.track_media_kind ==
e_audio)
1394 ATOM_FULL(BOX_smhd, 0);
1399 if (tr->info.track_media_kind ==
e_video)
1402 ATOM_FULL(BOX_vmhd, 1);
1404 WRITE_2(0); WRITE_2(0); WRITE_2(0);
1409 ATOM_FULL(BOX_dref, 0);
1416 ATOM_FULL(BOX_url, 1);
1422 ATOM_FULL(BOX_stsd, 0);
1425 if (tr->info.track_media_kind ==
e_audio || tr->info.track_media_kind ==
e_private)
1428 if (tr->info.track_media_kind ==
e_audio)
1438 WRITE_4(0); WRITE_2(0);
1441 if (tr->info.track_media_kind ==
e_audio)
1444 WRITE_4(0); WRITE_4(0);
1445 WRITE_2(tr->info.u.a.channelcount);
1448 WRITE_4((tr->info.time_scale << 16));
1451 ATOM_FULL(BOX_esds, 0);
1452 if (tr->vsps.bytes > 0)
1454 int dsi_bytes = tr->vsps.bytes - 2;
1455 int dsi_size_size = od_size_of_size(dsi_bytes);
1456 int dcd_bytes = dsi_bytes + dsi_size_size + 1 + (1 + 1 + 3 + 4 + 4);
1457 int dcd_size_size = od_size_of_size(dcd_bytes);
1458 int esd_bytes = dcd_bytes + dcd_size_size + 1 + 3;
1460#define WRITE_OD_LEN(size) if (size > 0x7F) do { size -= 0x7F; WRITE_1(0x00ff); } while (size > 0x7F); WRITE_1(size)
1462 WRITE_OD_LEN(esd_bytes);
1467 WRITE_OD_LEN(dcd_bytes);
1468 if (tr->info.track_media_kind ==
e_audio)
1479 WRITE_3(tr->info.u.a.channelcount * 6144 / 8);
1484 WRITE_OD_LEN(dsi_bytes);
1485 for (i = 0; i < dsi_bytes; i++)
1487 WRITE_1(tr->vsps.data[2 + i]);
1496 int numOfSequenceParameterSets = items_count(&tr->vsps);
1497 int numOfPictureParameterSets = items_count(&tr->vpps);
1518 WRITE_2(tr->info.u.v.width);
1519 WRITE_2(tr->info.u.v.height);
1520 WRITE_4(0x00480000);
1521 WRITE_4(0x00480000);
1524 for (i = 0; i < 32; i++)
1536 WRITE_1(tr->vsps.data[2 + 1]);
1537 WRITE_1(tr->vsps.data[2 + 2]);
1538 WRITE_1(tr->vsps.data[2 + 3]);
1540 WRITE_1(0xe0 | numOfSequenceParameterSets);
1541 for (i = 0; i < tr->vsps.bytes; i++)
1543 WRITE_1(tr->vsps.data[i]);
1545 WRITE_1(numOfPictureParameterSets);
1546 for (i = 0; i < tr->vpps.bytes; i++)
1548 WRITE_1(tr->vpps.data[i]);
1553 int numOfVPS = items_count(&tr->vpps);
1558 WRITE_4(0x60000000);
1573 for (i = 0; i < tr->vvps.bytes; i++)
1575 WRITE_1(tr->vvps.data[i]);
1578 WRITE_2(numOfSequenceParameterSets);
1579 for (i = 0; i < tr->vsps.bytes; i++)
1581 WRITE_1(tr->vsps.data[i]);
1584 WRITE_2(numOfPictureParameterSets);
1585 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++)
1608 if (i == (samples_count - 1) || sample[i].duration != sample[i + 1].duration)
1611 WRITE_4(sample[i].duration);
1616 WR4(pentry_count, entry_count);
1621 ATOM_FULL(BOX_stsc, 0);
1622 if (mux->enable_fragmentation)
1636 ATOM_FULL(BOX_stsz, 0);
1639 WRITE_4(samples_count);
1640 for (i = 0; i < samples_count; i++)
1642 WRITE_4(sample[i].size);
1648 if (samples_count && sample[samples_count - 1].offset > 0xffffffff)
1652 ATOM_FULL(BOX_stco, 0);
1653 WRITE_4(samples_count);
1654 for (i = 0; i < samples_count; i++)
1656 WRITE_4(sample[i].offset);
1661 ATOM_FULL(BOX_co64, 0);
1662 WRITE_4(samples_count);
1663 for (i = 0; i < samples_count; i++)
1665 WRITE_4((sample[i].offset >> 32) & 0xffffffff);
1666 WRITE_4(sample[i].offset & 0xffffffff);
1674 for (i = 0; i < samples_count; i++)
1676 ra_count += !!sample[i].flag_random_access;
1678 if (ra_count != samples_count)
1681 ATOM_FULL(BOX_stss, 0);
1683 for (i = 0; i < samples_count; i++)
1685 if (sample[i].flag_random_access)
1699 if (mux->text_comment)
1702 ATOM_FULL(BOX_meta, 0);
1703 ATOM_FULL(BOX_hdlr, 0);
1705#define MP4E_HANDLER_TYPE_MDIR 0x6d646972
1706 WRITE_4(MP4E_HANDLER_TYPE_MDIR);
1707 WRITE_4(0); WRITE_4(0); WRITE_4(0);
1715 for (i = 0; i < (int)
strlen(mux->text_comment) + 1; i++)
1717 WRITE_1(mux->text_comment[i]);
1726 if (mux->enable_fragmentation)
1728 track_t* tr = ((track_t*)mux->tracks.data) + 0;
1729 uint32_t movie_duration = get_duration(tr);
1732 ATOM_FULL(BOX_mehd, 0);
1733 WRITE_4(movie_duration);
1735 for (ntr = 0; ntr < ntracks; ntr++)
1737 ATOM_FULL(BOX_trex, 0);
1749 assert((
unsigned)(p - base) <= index_bytes);
1751 err = mux->write_callback(mux->write_pos, base, p - base, mux->token);
1752 mux->write_pos += p - base;
1760 unsigned ntr, ntracks;
1763 if (!mux->enable_fragmentation)
1764 err = mp4e_flush_index(mux);
1765 if (mux->text_comment)
1766 free(mux->text_comment);
1767 ntracks = mux->tracks.bytes /
sizeof(track_t);
1768 for (ntr = 0; ntr < ntracks; ntr++)
1770 track_t* tr = ((track_t*)mux->tracks.data) + ntr;
1771 minimp4_vector_reset(&tr->vsps);
1772 minimp4_vector_reset(&tr->vpps);
1773 minimp4_vector_reset(&tr->smpl);
1774 minimp4_vector_reset(&tr->pending_sample);
1776 minimp4_vector_reset(&mux->tracks);
1791 int cache_free_bits;
1800 unsigned origin_bytes;
1804#define LOAD_SHORT(x) ((uint16_t)(x << 8) | (x >> 8))
1806static unsigned int show_bits(bit_reader_t* bs,
int n)
1808 unsigned int retval;
1809 assert(n > 0 && n <= 16);
1810 retval = (
unsigned int)(bs->cache >> (32 - n));
1814static void flush_bits(bit_reader_t* bs,
int n)
1816 assert(n >= 0 && n <= 16);
1818 bs->cache_free_bits += n;
1819 if (bs->cache_free_bits >= 0)
1821 bs->cache |= ((
uint32_t)LOAD_SHORT(*bs->buf)) << bs->cache_free_bits;
1823 bs->cache_free_bits -= 16;
1827static unsigned int get_bits(bit_reader_t* bs,
int n)
1829 unsigned int retval = show_bits(bs, n);
1834static void set_pos_bits(bit_reader_t* bs,
unsigned pos_bits)
1836 assert((
int)pos_bits >= 0);
1838 bs->buf = bs->origin + pos_bits / 16;
1840 bs->cache_free_bits = 16;
1842 flush_bits(bs, pos_bits & 15);
1845static unsigned get_pos_bits(
const bit_reader_t* bs)
1850 unsigned pos_bits = (unsigned)(bs->buf - bs->origin) * 16;
1851 pos_bits -= 16 - bs->cache_free_bits;
1852 assert((
int)pos_bits >= 0);
1856static int remaining_bits(
const bit_reader_t* bs)
1858 return bs->origin_bytes * 8 - get_pos_bits(bs);
1861static void init_bits(bit_reader_t* bs,
const void* data,
unsigned data_bytes)
1863 bs->origin = (
const uint16_t*)data;
1864 bs->origin_bytes = data_bytes;
1865 set_pos_bits(bs, 0);
1868#define GetBits(n) get_bits(bs, n)
1873static int ue_bits(bit_reader_t* bs)
1877 for (clz = 0; !get_bits(bs, 1); clz++) {}
1879 val = (1 << clz) - 1 + (clz ? get_bits(bs, clz) : 0);
1883#if MINIMP4_TRANSCODE_SPS_ID
1896#define SWAP32(x) (uint32_t)((((x) >> 24) & 0xFF) | (((x) >> 8) & 0xFF00) | (((x) << 8) & 0xFF0000) | ((x & 0xFF) << 24))
1898static void h264e_bs_put_bits(bs_t* bs,
unsigned n,
unsigned val)
1902 assert((
unsigned)n <= 32);
1906 bs->cache |= val >> -bs->shift;
1907 *bs->buf++ = SWAP32(bs->cache);
1908 bs->shift = 32 + bs->shift;
1911 bs->cache |= val << bs->shift;
1914static void h264e_bs_flush(bs_t* bs)
1916 *bs->buf = SWAP32(bs->cache);
1919static unsigned h264e_bs_get_pos_bits(
const bs_t* bs)
1921 unsigned pos_bits = (unsigned)((bs->buf - bs->origin) * BS_BITS);
1922 pos_bits += BS_BITS - bs->shift;
1923 assert((
int)pos_bits >= 0);
1927static unsigned h264e_bs_byte_align(bs_t* bs)
1929 int pos = h264e_bs_get_pos_bits(bs);
1930 h264e_bs_put_bits(bs, -pos & 7, 0);
1931 return pos + (-pos & 7);
1948static void h264e_bs_put_golomb(bs_t* bs,
unsigned val)
1951 unsigned t = val + 1;
1957 h264e_bs_put_bits(bs, 2 * size - 1, val + 1);
1960static void h264e_bs_init_bits(bs_t* bs,
void* data)
1962 bs->origin = (bs_item_t*)data;
1963 bs->buf = bs->origin;
1964 bs->shift = BS_BITS;
1968static int find_mem_cache(
void* cache[],
int cache_bytes[],
int cache_size,
void* mem,
int bytes)
1973 for (i = 0; i < cache_size; i++)
1975 if (cache_bytes[i] == bytes && !
memcmp(mem, cache[i], bytes))
1978 for (i = 0; i < cache_size; i++)
1980 if (!cache_bytes[i])
1982 cache[i] =
malloc(bytes);
1985 memcpy(cache[i], mem, bytes);
1986 cache_bytes[i] = bytes;
1997static int remove_nal_escapes(
unsigned char* dst,
const unsigned char* src,
int h264_data_bytes)
1999 int i = 0, j = 0, zero_cnt = 0;
2000 for (j = 0; j < h264_data_bytes; j++)
2002 if (zero_cnt == 2 && src[j] <= 3)
2006 if (j == h264_data_bytes - 1)
2010 else if (src[j + 1] <= 3)
2039 int i, j = 4, cntz = 0;
2040 d[0] = d[1] = d[2] = 0; d[3] = 1;
2041 for (i = 0; i < n; i++)
2044 if (cntz == 2 &&
byte <= 3)
2058static void copy_bits(bit_reader_t* bs, bs_t* bd)
2061 int bit_count = remaining_bits(bs);
2062 while (bit_count > 7)
2066 h264e_bs_put_bits(bd, cb, bits);
2071 bits = GetBits(bit_count);
2072 for (; bit_count && ~bits & 1; bit_count--)
2078 h264e_bs_put_bits(bd, bit_count, bits);
2082static int change_sps_id(bit_reader_t* bs, bs_t* bd,
int new_id,
int* old_id)
2084 unsigned bits, sps_id, i, bytes;
2085 for (i = 0; i < 3; i++)
2088 h264e_bs_put_bits(bd, 8, bits);
2090 sps_id = ue_bits(bs);
2096 h264e_bs_put_golomb(bd, sps_id);
2099 bytes = h264e_bs_byte_align(bd) / 8;
2104static int patch_pps(
h264_sps_id_patcher_t* h, bit_reader_t* bs, bs_t* bd,
int new_pps_id,
int* old_id)
2107 unsigned pps_id = ue_bits(bs);
2108 unsigned sps_id = ue_bits(bs);
2112 pps_id = new_pps_id;
2117 h264e_bs_put_golomb(bd, pps_id);
2118 h264e_bs_put_golomb(bd, sps_id);
2121 bytes = h264e_bs_byte_align(bd) / 8;
2128 unsigned first_mb_in_slice = ue_bits(bs);
2129 unsigned slice_type = ue_bits(bs);
2130 unsigned pps_id = ue_bits(bs);
2136 h264e_bs_put_golomb(bd, first_mb_in_slice);
2137 h264e_bs_put_golomb(bd, slice_type);
2138 h264e_bs_put_golomb(bd, pps_id);
2142static int transcode_nalu(
h264_sps_id_patcher_t* h,
const unsigned char* src,
int nalu_bytes,
unsigned char* dst)
2146 bit_reader_t bst[1];
2151 int payload_type = src[0] & 31;
2154 h264e_bs_init_bits(bd, dst + 1);
2155 init_bits(bs, src + 1, nalu_bytes - 1);
2156 h264e_bs_init_bits(bdt, dst + 1);
2157 init_bits(bst, src + 1, nalu_bytes - 1);
2159 switch (payload_type)
2163 int cb = change_sps_id(bst, bdt, 0, &old_id);
2168 change_sps_id(bs, bd,
id, &old_id);
2173 int cb = patch_pps(h, bst, bdt, 0, &old_id);
2178 patch_pps(h, bs, bd,
id, &old_id);
2184 patch_slice_header(h, bs, bd);
2187 memcpy(dst, (
void*)src, nalu_bytes);
2191 nalu_bytes = 1 + h264e_bs_byte_align(bd) / 8;
2207static const uint8_t* find_start_code(
const uint8_t* h264_data,
int h264_data_bytes,
int* zcount)
2209 const uint8_t* eof = h264_data + h264_data_bytes;
2215 p = found ? found : eof;
2216 while (p + zero_cnt < eof && !p[zero_cnt]) zero_cnt++;
2217 if (zero_cnt >= 2 && p[zero_cnt] == 1)
2219 *zcount = zero_cnt + 1;
2220 return p + zero_cnt + 1;
2231static const uint8_t* find_nal_unit(
const uint8_t* h264_data,
int h264_data_bytes,
int* pnal_unit_bytes)
2233 const uint8_t* eof = h264_data + h264_data_bytes;
2235 const uint8_t* start = find_start_code(h264_data, h264_data_bytes, &zcount);
2239 stop = find_start_code(start, (
int)(eof - start), &zcount);
2240 while (stop > start && !stop[-1])
2246 *pnal_unit_bytes = (int)(stop - start - zcount);
2271#if MINIMP4_TRANSCODE_SPS_ID
2279#if MINIMP4_TRANSCODE_SPS_ID
2293 memset(h, 0,
sizeof(*h));
2296static int mp4_h265_write_nal(
mp4_h26x_writer_t* h,
const unsigned char* nal,
int sizeof_nal,
unsigned timeStamp90kHz_next)
2298 int payload_type = (nal[0] >> 1) & 0x3f;
2305 switch (payload_type)
2323 unsigned char* tmp = (
unsigned char*)
malloc(4 + sizeof_nal);
2327 tmp[0] = (
unsigned char)(sizeof_nal >> 24);
2328 tmp[1] = (
unsigned char)(sizeof_nal >> 16);
2329 tmp[2] = (
unsigned char)(sizeof_nal >> 8);
2330 tmp[3] = (
unsigned char)(sizeof_nal);
2331 memcpy(tmp + 4, (
void*)nal, sizeof_nal);
2344 const unsigned char* eof = nal + length;
2348#if MINIMP4_TRANSCODE_SPS_ID
2349 unsigned char* nal1, * nal2;
2351 nal = find_nal_unit(nal, (
int)(eof - nal), &sizeof_nal);
2356 ERR(mp4_h265_write_nal(h, nal, sizeof_nal, timeStamp90kHz_next));
2359 payload_type = nal[0] & 31;
2360 if (9 == payload_type)
2362#if MINIMP4_TRANSCODE_SPS_ID
2367 nal1 = (
unsigned char*)
malloc(sizeof_nal * 17 / 16 + 32);
2370 nal2 = (
unsigned char*)
malloc(sizeof_nal * 17 / 16 + 32);
2376 sizeof_nal = remove_nal_escapes(nal2, nal, sizeof_nal);
2385 sizeof_nal = transcode_nalu(&h->
sps_patcher, nal2, sizeof_nal, nal1);
2386 sizeof_nal = nal_put_esc(nal2, nal1, sizeof_nal);
2388 switch (payload_type) {
2395 goto exit_with_free;
2401 goto exit_with_free;
2406 goto exit_with_free;
2410 init_bits(bs, nal + 1, sizeof_nal - 4 - 1);
2411 unsigned first_mb_in_slice = ue_bits(bs);
2414 nal2[0] = (
unsigned char)((sizeof_nal - 4) >> 24);
2415 nal2[1] = (
unsigned char)((sizeof_nal - 4) >> 16);
2416 nal2[2] = (
unsigned char)((sizeof_nal - 4) >> 8);
2417 nal2[3] = (
unsigned char)((sizeof_nal - 4));
2418 if (first_mb_in_slice)
2420 else if (payload_type == 5)
2431 switch (payload_type) {
2451 unsigned char* tmp = (
unsigned char*)
malloc(4 + sizeof_nal);
2454 init_bits(bs, nal + 1, sizeof_nal - 1);
2455 unsigned first_mb_in_slice = ue_bits(bs);
2457 tmp[0] = (
unsigned char)(sizeof_nal >> 24);
2458 tmp[1] = (
unsigned char)(sizeof_nal >> 16);
2459 tmp[2] = (
unsigned char)(sizeof_nal >> 8);
2460 tmp[3] = (
unsigned char)(sizeof_nal);
2461 memcpy(tmp + 4, nal, sizeof_nal);
2462 if (first_mb_in_slice)
2464 else if (payload_type == 5)
2478#if MP4D_TRACE_SUPPORTED
2479# define TRACE(x) printf x
2481# define TRACE(x) printf x
2484#define NELEM(x) (sizeof(x) / sizeof((x)[0]))
2499static unsigned minimp4_read(
MP4D_demux_t* mp4,
int nb,
int* eof_flag)
2504 case 4: v = (v << 8) | minimp4_fgets(mp4);
2505 case 3: v = (v << 8) | minimp4_fgets(mp4);
2506 case 2: v = (v << 8) | minimp4_fgets(mp4);
2508 case 1: v = (v << 8) | (last_byte = minimp4_fgets(mp4));
2523 if (*payload_bytes < nb)
2526 nb = (int)*payload_bytes;
2528 *payload_bytes -= nb;
2530 return minimp4_read(mp4, nb, eof_flag);
2544#define READ(n) read_payload(mp4, n, &payload_bytes, &eof_flag)
2545#define SKIP(n) { boxsize_t t = MINIMP4_MIN(payload_bytes, n); my_fseek(mp4, t, &eof_flag); payload_bytes -= t; }
2546#define MALLOC(t, p, size) p = (t)malloc(size); if (!(p)) { ERROR("out of memory"); }
2551#define RETURN_ERROR(mess) { \
2552 TRACE(("\nMP4 ERROR: " mess)); \
2560#define ERROR(mess) \
2566typedef enum { BOX_ATOM, BOX_OD } boxtype_t;
2583#if MP4D_TRACE_SUPPORTED
2594 TRACE((
"\nERROR: invlaid arguments!"));
2603 stack[0].format = BOX_ATOM;
2614 unsigned max_version;
2615 unsigned use_track_flag;
2618#if MP4D_INFO_SUPPORTED
2624#if MP4D_TRACE_TIMESTAMPS
2645 } g_envelope_box[] =
2651 {BOX_trak, BOX_ATOM},
2652 {BOX_moov, BOX_ATOM},
2654 {BOX_mdia, BOX_ATOM},
2655 {BOX_tref, BOX_ATOM},
2656 {BOX_minf, BOX_ATOM},
2657 {BOX_dinf, BOX_ATOM},
2658 {BOX_stbl, BOX_ATOM},
2659 {BOX_stsd, BOX_ATOM},
2660 {BOX_mp4a, BOX_ATOM},
2661 {BOX_mp4s, BOX_ATOM},
2662#if MP4D_AVC_SUPPORTED
2663 {BOX_mp4v, BOX_ATOM},
2664 {BOX_avc1, BOX_ATOM},
2668#if MP4D_HEVC_SUPPORTED
2669 {BOX_hvc1, BOX_ATOM},
2671 {BOX_udta, BOX_ATOM},
2672 {BOX_meta, BOX_ATOM},
2673 {BOX_ilst, BOX_ATOM}
2676 uint32_t FullAtomVersionAndFlags = 0;
2680#if MP4D_INFO_SUPPORTED
2681 unsigned char** ptag =
NULL;
2686 if (stack[depth].format == BOX_ATOM)
2688 box_bytes = minimp4_read(mp4, 4, &eof_flag);
2689#if FIX_BAD_ANDROID_META_BOX
2690 broken_android_meta_hack :
2695 if (box_bytes >= 2 && box_bytes < 8)
2697 ERROR(
"invalid box size (broken file?)");
2700 box_name = minimp4_read(mp4, 4, &eof_flag);
2704 if (box_bytes == 0 ||
2711 payload_bytes = box_bytes - 8;
2715 TRACE((
"\n64-bit chunk encountered"));
2717 box_bytes = minimp4_read(mp4, 4, &eof_flag);
2718#if MP4D_64BIT_SUPPORTED
2720 box_bytes |= minimp4_read(mp4, 4, &eof_flag);
2724 ERROR(
"UNSUPPORTED FEATURE: MP4BoxHeader(): 64-bit boxes not supported!");
2726 box_bytes = minimp4_read(mp4, 4, &eof_flag);
2730 ERROR(
"invalid box size (broken file?)");
2732 payload_bytes = box_bytes - 16;
2736 for (i = 0; i < NELEM(g_fullbox); i++)
2738 if (box_name == g_fullbox[i].name)
2740 FullAtomVersionAndFlags = READ(4);
2743#if FIX_BAD_ANDROID_META_BOX
2746 if (box_name == BOX_meta)
2748 if (FullAtomVersionAndFlags >= 8 && FullAtomVersionAndFlags < payload_bytes)
2750 if (box_bytes > stack[depth].bytes)
2752 ERROR(
"broken file structure!");
2754 stack[depth].bytes -= box_bytes;;
2756 stack[depth].bytes = payload_bytes + 4;
2757 stack[depth].format = BOX_ATOM;
2758 box_bytes = FullAtomVersionAndFlags;
2759 TRACE((
"Bad metadata box detected (Android bug?)!\n"));
2760 goto broken_android_meta_hack;
2765 if ((FullAtomVersionAndFlags >> 24) > g_fullbox[i].max_version)
2767 ERROR(
"unsupported box version!");
2769 if (g_fullbox[i].use_track_flag && !tr)
2771 ERROR(
"broken file structure!");
2779 box_name = OD_BASE + minimp4_read(mp4, 1, &eof_flag);
2788 val = minimp4_read(mp4, 1, &eof_flag);
2792 ERROR(
"premature EOF!");
2794 payload_bytes = (payload_bytes << 7) | (val & 0x7F);
2796 }
while (val & 0x80);
2797 box_bytes += payload_bytes;
2800#if MP4D_TRACE_SUPPORTED
2801 box_path[depth] = (box_name >> 24) | (box_name << 24) | ((box_name >> 8) & 0x0000FF00) | ((box_name << 8) & 0x00FF0000);
2802 TRACE((
"%2d %8d %.*s (%d bytes remains for sibilings) \n", depth, (
int)box_bytes, depth * 4, (
char*)box_path, (
int)stack[depth].bytes));
2810 if (box_bytes > stack[depth].bytes)
2812 TRACE((
"Wrong %c%c%c%c box size: broken file?\n", (box_name >> 24) & 255, (box_name >> 16) & 255, (box_name >> 8) & 255, box_name & 255));
2813 box_bytes = stack[depth].bytes;
2815 payload_bytes = box_bytes - read_bytes;
2817 stack[depth].bytes -= box_bytes;
2832 if (box_name == BOX_stsz)
2834 tr->
entry_size[i] = (sample_size ? sample_size : READ(4));
2838 switch (sample_size & 0xFF)
2873#if MP4D_TRACE_TIMESTAMPS || MP4D_TIMESTAMPS_SUPPORTED
2876 unsigned count = READ(4);
2877 unsigned j, k = 0, ts = 0, ts_count = count;
2878#if MP4D_TIMESTAMPS_SUPPORTED
2879 MALLOC(
unsigned int*, tr->
timestamp, ts_count * 4);
2880 MALLOC(
unsigned int*, tr->
duration, ts_count * 4);
2883 for (i = 0; i < count; i++)
2885 unsigned sc = READ(4);
2887 TRACE((
"sample %8d count %8d duration %8d\n", i, sc, d));
2888#if MP4D_TIMESTAMPS_SUPPORTED
2889 if (k + sc > ts_count)
2895 for (j = 0; j < sc; j++)
2907 unsigned count = READ(4);
2908 for (i = 0; i < count; i++)
2914 TRACE((
"sample %8d count %8d decoding to composition offset %8d\n", i, sc, d));
2926 if (box_name == BOX_co64)
2928#if !MP4D_64BIT_SUPPORTED
2931 ERROR(
"UNSUPPORTED FEATURE: 64-bit chunk_offset not supported!");
2940#if MP4D_INFO_SUPPORTED
2942 SKIP(((FullAtomVersionAndFlags >> 24) == 1) ? 8 + 8 : 4 + 4);
2944 mp4->
duration_hi = ((FullAtomVersionAndFlags >> 24) == 1) ? READ(4) : 0;
2946 SKIP(4 + 2 + 2 + 4 * 2 + 4 * 9 + 4 * 6 + 4);
2950 SKIP(((FullAtomVersionAndFlags >> 24) == 1) ? 8 + 8 : 4 + 4);
2952 tr->
duration_hi = ((FullAtomVersionAndFlags >> 24) == 1) ? READ(4) : 0;
2956 int ISO_639_2_T = READ(2);
2957 tr->
language[2] = (ISO_639_2_T & 31) + 0x60; ISO_639_2_T >>= 5;
2958 tr->
language[1] = (ISO_639_2_T & 31) + 0x60; ISO_639_2_T >>= 5;
2959 tr->
language[0] = (ISO_639_2_T & 31) + 0x60;
2977 ERROR(
"broken file structure!");
2985 case BOX_calb: ptag = &mp4->
tag.
album;
break;
2986 case BOX_cART: ptag = &mp4->
tag.
artist;
break;
2987 case BOX_cnam: ptag = &mp4->
tag.
title;
break;
2988 case BOX_cday: ptag = &mp4->
tag.
year;
break;
2989 case BOX_ccmt: ptag = &mp4->
tag.
comment;
break;
2990 case BOX_cgen: ptag = &mp4->
tag.
genre;
break;
3001 ERROR(
"broken file structure!");
3009 ERROR(
"broken file structure!");
3011#if MP4D_INFO_SUPPORTED
3012 SKIP(6 * 1 + 2 + 4 * 2);
3021#if MP4D_AVC_SUPPORTED
3028 ERROR(
"broken file structure!");
3030#if MP4D_INFO_SUPPORTED
3031 SKIP(6 * 1 + 2 + 2 + 2 + 4 * 3);
3036 SKIP(4 + 4 + 4 + 2 + 32 + 2 + 2);
3053 tr->
dsi = (
unsigned char*)
malloc((
size_t)box_bytes);
3057 unsigned char* p = tr->
dsi;
3058 unsigned int configurationVersion = READ(1);
3059 unsigned int AVCProfileIndication = READ(1);
3060 unsigned int profile_compatibility = READ(1);
3061 unsigned int AVCLevelIndication = READ(1);
3063 unsigned int lengthSizeMinusOne = READ(1) & 3;
3065 (void)configurationVersion;
3066 (void)AVCProfileIndication;
3067 (void)profile_compatibility;
3068 (void)AVCLevelIndication;
3069 (void)lengthSizeMinusOne;
3071 for (spspps = 0; spspps < 2; spspps++)
3073 unsigned int numOfSequenceParameterSets = READ(1);
3076 numOfSequenceParameterSets &= 31;
3078 *p++ = numOfSequenceParameterSets;
3079 for (i = 0; i < numOfSequenceParameterSets; i++)
3081 unsigned k, sequenceParameterSetLength = READ(2);
3082 *p++ = sequenceParameterSetLength >> 8;
3083 *p++ = sequenceParameterSetLength;
3084 for (k = 0; k < sequenceParameterSetLength; k++)
3096 unsigned flags = READ(3);
3104 unsigned bytecount = READ(1);
3117#if MP4D_INFO_SUPPORTED
3122 SKIP(1 + 3 + 4 + 4);
3128 if (!tr->
dsi && payload_bytes)
3130 MALLOC(
unsigned char*, tr->
dsi, (
int)payload_bytes);
3131 for (i = 0; i < payload_bytes; i++)
3133 tr->
dsi[i] = minimp4_read(mp4, 1, &eof_flag);
3141 TRACE((
"[%c%c%c%c] %d\n", box_name >> 24, box_name >> 16, box_name >> 8, box_name, (
int)payload_bytes));
3144#if MP4D_INFO_SUPPORTED
3146 if (ptag && !*ptag && payload_bytes > 16)
3153 TRACE((
"%2d %2d %2d ", size,
class, x1));
3155 SKIP(4 + 4 + 4 + 4);
3157 MALLOC(
unsigned char*, *ptag, (
unsigned)payload_bytes + 1);
3158 for (i = 0; payload_bytes != 0; i++)
3160 (*ptag)[i] = READ(1);
3166 if (box_name == BOX_trak)
3177 ERROR(
"out of memory");
3183 else if (box_name == BOX_meta)
3189 for (i = 0; i < NELEM(g_envelope_box); i++)
3191 if (box_name == g_envelope_box[i].name)
3195 ERROR(
"too deep atoms nesting!");
3197 stack[depth].bytes = payload_bytes;
3198 stack[depth].format = g_envelope_box[i].type;
3204 if (i == NELEM(g_envelope_box))
3206 if (payload_bytes > file_size)
3212 SKIP(payload_bytes);
3218 while (depth > 0 && !stack[depth].bytes)
3223 }
while (!eof_flag);
3236static int sample_to_chunk(
MP4D_track_t* tr,
unsigned nsample,
unsigned* nfirst_sample_in_chunk)
3238 unsigned chunk_group = 0, nc;
3240 *nfirst_sample_in_chunk = 0;
3259 *nfirst_sample_in_chunk = sum;
3269 int nchunk = sample_to_chunk(tr, nsample, &ns);
3279 for (; ns < nsample; ns++)
3288#if MP4D_TIMESTAMPS_SUPPORTED
3296#if MP4D_TIMESTAMPS_SUPPORTED
3306#define FREE(x) if (x) {free(x); x = NULL;}
3315#if MP4D_TIMESTAMPS_SUPPORTED
3324#if MP4D_INFO_SUPPORTED
3334static int skip_spspps(
const unsigned char* p,
int nbytes,
int nskip)
3337 for (i = 0; i < nskip; i++)
3342 segmbytes = p[k] * 256 + p[k + 1];
3348static const void* MP4D_read_spspps(
const MP4D_demux_t* mp4,
unsigned int ntrack,
int pps_flag,
int nsps,
int* sps_bytes)
3350 int sps_count, skip_bytes;
3352 unsigned char* p = mp4->
track[ntrack].
dsi;
3361 sps_count = p[bytepos++];
3362 skip_bytes = skip_spspps(p + bytepos, mp4->
track[ntrack].
dsi_bytes - bytepos, sps_count);
3365 bytepos += skip_bytes;
3369 sps_count = p[bytepos++];
3370 if (nsps >= sps_count)
3372 skip_bytes = skip_spspps(p + bytepos, mp4->
track[ntrack].
dsi_bytes - bytepos, nsps);
3375 bytepos += skip_bytes;
3376 *sps_bytes = p[bytepos] * 256 + p[bytepos + 1];
3377 return p + bytepos + 2;
3383 return MP4D_read_spspps(mp4, ntrack, 0, nsps, sps_bytes);
3388 return MP4D_read_spspps(mp4, ntrack, 1, npps, pps_bytes);
3391#if MP4D_PRINT_INFO_SUPPORTED
3399static const char* GetMP4StreamTypeName(
int streamType)
3403 case 0x00:
return "Forbidden";
3404 case 0x01:
return "ObjectDescriptorStream";
3405 case 0x02:
return "ClockReferenceStream";
3406 case 0x03:
return "SceneDescriptionStream";
3407 case 0x04:
return "VisualStream";
3408 case 0x05:
return "AudioStream";
3409 case 0x06:
return "MPEG7Stream";
3410 case 0x07:
return "IPMPStream";
3411 case 0x08:
return "ObjectContentInfoStream";
3412 case 0x09:
return "MPEGJStream";
3414 if (streamType >= 0x20 && streamType <= 0x3F)
3416 return "User private";
3420 return "Reserved for ISO use";
3428static const char* GetMP4ObjectTypeName(
int objectTypeIndication)
3430 switch (objectTypeIndication)
3432 case 0x00:
return "Forbidden";
3433 case 0x01:
return "Systems ISO/IEC 14496-1";
3434 case 0x02:
return "Systems ISO/IEC 14496-1";
3435 case 0x20:
return "Visual ISO/IEC 14496-2";
3436 case 0x40:
return "Audio ISO/IEC 14496-3";
3437 case 0x60:
return "Visual ISO/IEC 13818-2 Simple Profile";
3438 case 0x61:
return "Visual ISO/IEC 13818-2 Main Profile";
3439 case 0x62:
return "Visual ISO/IEC 13818-2 SNR Profile";
3440 case 0x63:
return "Visual ISO/IEC 13818-2 Spatial Profile";
3441 case 0x64:
return "Visual ISO/IEC 13818-2 High Profile";
3442 case 0x65:
return "Visual ISO/IEC 13818-2 422 Profile";
3443 case 0x66:
return "Audio ISO/IEC 13818-7 Main Profile";
3444 case 0x67:
return "Audio ISO/IEC 13818-7 LC Profile";
3445 case 0x68:
return "Audio ISO/IEC 13818-7 SSR Profile";
3446 case 0x69:
return "Audio ISO/IEC 13818-3";
3447 case 0x6A:
return "Visual ISO/IEC 11172-2";
3448 case 0x6B:
return "Audio ISO/IEC 11172-3";
3449 case 0x6C:
return "Visual ISO/IEC 10918-1";
3450 case 0xFF:
return "no object type specified";
3452 if (objectTypeIndication >= 0xC0 && objectTypeIndication <= 0xFE)
3453 return "User private";
3455 return "Reserved for ISO use";
3492#define STR_TAG(name) if (mp4->tag.name) printf("%10s = %s\n", #name, mp4->tag.name)
3499 printf(
"\nNo|type|lng| duration | bitrate| %-23s| Object type",
"Stream type");
3504 printf(
"\n%2d|%c%c%c%c|%c%c%c|%7.2f s %6d frm| %7d|", i,
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:126
#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:120
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:116
#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:129
@ e_private
Definition minimp4.h:132
@ e_video
Definition minimp4.h:131
@ e_audio
Definition minimp4.h:130
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:117
#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:119
#define MP4D_HANDLER_TYPE_VIDE
Definition minimp4.h:108
#define MP4E_SAMPLE_CONTINUATION
Definition minimp4.h:91
#define HEVC_NAL_PPS
Definition minimp4.h:118
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
XE_LIB void * memchr(const void *src, int c, size_t n)
Definition string.cpp:652
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
#define assert(expression)
Definition assert.h:40
XE_LIB void * realloc(void *address, unsigned int new_size)
Definition _heap.cpp:502
XE_LIB void * malloc(unsigned int)
Definition _heap.cpp:281
XE_LIB void free(void *ptr)
Definition _heap.cpp:392
unsigned duration_hi
Definition minimp4.h:296
unsigned char * album
Definition minimp4.h:308
unsigned timescale
Definition minimp4.h:300
int64_t read_size
Definition minimp4.h:284
void * token
Definition minimp4.h:287
unsigned char * title
Definition minimp4.h:306
MP4D_track_t * track
Definition minimp4.h:285
int64_t read_pos
Definition minimp4.h:283
unsigned char * year
Definition minimp4.h:309
unsigned duration_lo
Definition minimp4.h:297
unsigned char * artist
Definition minimp4.h:307
unsigned char * comment
Definition minimp4.h:310
unsigned char * genre
Definition minimp4.h:311
unsigned track_count
Definition minimp4.h:289
struct MP4D_demux_tag::@481 tag
int(* read_callback)(int64_t offset, void *buffer, size_t size, void *token)
Definition minimp4.h:286
unsigned first_chunk
Definition minimp4.h:319
unsigned samples_per_chunk
Definition minimp4.h:320
unsigned sample_count
Definition minimp4.h:176
MP4D_file_offset_t * chunk_offset
Definition minimp4.h:269
unsigned channelcount
Definition minimp4.h:247
unsigned sample_to_chunk_count
Definition minimp4.h:265
unsigned chunk_count
Definition minimp4.h:268
unsigned width
Definition minimp4.h:254
unsigned height
Definition minimp4.h:255
unsigned * timestamp
Definition minimp4.h:272
union MP4D_track_t::@478 SampleDescription
unsigned samplerate_hz
Definition minimp4.h:248
struct MP4D_track_t::@478::@480 video
unsigned object_type_indication
Definition minimp4.h:203
unsigned timescale
Definition minimp4.h:221
struct MP4D_sample_to_chunk_t_tag * sample_to_chunk
Definition minimp4.h:266
unsigned * entry_size
Definition minimp4.h:263
unsigned char * dsi
Definition minimp4.h:179
unsigned duration_lo
Definition minimp4.h:218
unsigned handler_type
Definition minimp4.h:214
unsigned * duration
Definition minimp4.h:273
unsigned dsi_bytes
Definition minimp4.h:182
unsigned char language[4]
Definition minimp4.h:227
unsigned duration_hi
Definition minimp4.h:217
unsigned stream_type
Definition minimp4.h:240
struct MP4D_track_t::@478::@479 audio
unsigned avg_bitrate_bps
Definition minimp4.h:224
int width
Definition minimp4.h:160
track_media_kind_t track_media_kind
Definition minimp4.h:144
unsigned time_scale
Definition minimp4.h:147
unsigned char language[4]
Definition minimp4.h:142
struct MP4E_track_t::@475::@477 v
int height
Definition minimp4.h:161
unsigned object_type_indication
Definition minimp4.h:139
unsigned default_duration
Definition minimp4.h:148
union MP4E_track_t::@475 u
int map_pps[MINIMP4_MAX_PPS]
Definition minimp4.h:331
void * sps_cache[MINIMP4_MAX_SPS]
Definition minimp4.h:325
int sps_bytes[MINIMP4_MAX_SPS]
Definition minimp4.h:327
void * pps_cache[MINIMP4_MAX_PPS]
Definition minimp4.h:326
int map_sps[MINIMP4_MAX_SPS]
Definition minimp4.h:330
int pps_bytes[MINIMP4_MAX_PPS]
Definition minimp4.h:328
int need_sps
Definition minimp4.h:341
MP4E_mux_t * mux
Definition minimp4.h:340
int need_pps
Definition minimp4.h:341
int need_vps
Definition minimp4.h:341
int is_hevc
Definition minimp4.h:341
int need_idr
Definition minimp4.h:341
h264_sps_id_patcher_t sps_patcher
Definition minimp4.h:338
int mux_track_id
Definition minimp4.h:341
size_t(* write_callback)(struct __VFS_NODE__ *node, struct __VFS_NODE__ *file, uint64_t *buffer, uint32_t length)
Definition vfs.h:77
size_t(* read_callback)(struct __VFS_NODE__ *node, struct __VFS_NODE__ *file, uint64_t *buffer, uint32_t length)
Definition vfs.h:75