XenevaOS
Loading...
Searching...
No Matches
minimp4.h
Go to the documentation of this file.
1#ifndef MINIMP4_H
2#define MINIMP4_H
3/*
4 https://github.com/aspt/mp4
5 https://github.com/lieff/minimp4
6 To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to the public domain worldwide.
7 This software is distributed without any warranty.
8 See <http://creativecommons.org/publicdomain/zero/1.0/>.
9*/
10
11#include <stdio.h>
12#include <stdint.h>
13#include <stdlib.h>
14#include <string.h>
15#include <limits.h>
16#include <assert.h>
17
18#ifdef __cplusplus
19extern "C" {
20#endif
21
22#define MINIMP4_MIN(x, y) ((x) < (y) ? (x) : (y))
23
24/************************************************************************/
25/* Build configuration */
26/************************************************************************/
27
28#define FIX_BAD_ANDROID_META_BOX 1
29
30#define MAX_CHUNKS_DEPTH 64 // Max chunks nesting level
31
32#define MINIMP4_MAX_SPS 32
33#define MINIMP4_MAX_PPS 256
34
35#define MINIMP4_TRANSCODE_SPS_ID 1
36
37// Support indexing of MP4 files over 4 GB.
38// If disabled, files with 64-bit offset fields is still supported,
39// but error signaled if such field contains too big offset
40// This switch affect return type of MP4D_frame_offset() function
41#define MINIMP4_ALLOW_64BIT 1
42
43#define MP4D_TRACE_SUPPORTED 0 // Debug trace
44#define MP4D_TRACE_TIMESTAMPS 1
45// Support parsing of supplementary information, not necessary for decoding:
46// duration, language, bitrate, metadata tags, etc
47#define MP4D_INFO_SUPPORTED 1
48
49// Enable code, which prints to stdout supplementary MP4 information:
50#define MP4D_PRINT_INFO_SUPPORTED 0
51
52#define MP4D_AVC_SUPPORTED 1
53#define MP4D_HEVC_SUPPORTED 1
54#define MP4D_TIMESTAMPS_SUPPORTED 1
55
56// Enable TrackFragmentBaseMediaDecodeTimeBox support
57#define MP4D_TFDT_SUPPORT 0
58
59/************************************************************************/
60/* Some values of MP4(E/D)_track_t->object_type_indication */
61/************************************************************************/
62// MPEG-4 AAC (all profiles)
63#define MP4_OBJECT_TYPE_AUDIO_ISO_IEC_14496_3 0x40
64// MPEG-2 AAC, Main profile
65#define MP4_OBJECT_TYPE_AUDIO_ISO_IEC_13818_7_MAIN_PROFILE 0x66
66// MPEG-2 AAC, LC profile
67#define MP4_OBJECT_TYPE_AUDIO_ISO_IEC_13818_7_LC_PROFILE 0x67
68// MPEG-2 AAC, SSR profile
69#define MP4_OBJECT_TYPE_AUDIO_ISO_IEC_13818_7_SSR_PROFILE 0x68
70// H.264 (AVC) video
71#define MP4_OBJECT_TYPE_AVC 0x21
72// H.265 (HEVC) video
73#define MP4_OBJECT_TYPE_HEVC 0x23
74// http://www.mp4ra.org/object.html 0xC0-E0 && 0xE2 - 0xFE are specified as "user private"
75#define MP4_OBJECT_TYPE_USER_PRIVATE 0xC0
76
77/************************************************************************/
78/* API error codes */
79/************************************************************************/
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
85
86/************************************************************************/
87/* Sample kind for MP4E_put_sample() */
88/************************************************************************/
89#define MP4E_SAMPLE_DEFAULT 0 // (beginning of) audio or video frame
90#define MP4E_SAMPLE_RANDOM_ACCESS 1 // mark sample as random access point (key frame)
91#define MP4E_SAMPLE_CONTINUATION 2 // Not a sample, but continuation of previous sample (new slice)
92
93/************************************************************************/
94/* Portable 64-bit type definition */
95/************************************************************************/
96
97#if MINIMP4_ALLOW_64BIT
99#else
100typedef unsigned int boxsize_t;
101#endif
103
104/************************************************************************/
105/* Some values of MP4D_track_t->handler_type */
106/************************************************************************/
107// Video track : 'vide'
108#define MP4D_HANDLER_TYPE_VIDE 0x76696465
109// Audio track : 'soun'
110#define MP4D_HANDLER_TYPE_SOUN 0x736F756E
111// General MPEG-4 systems streams (without specific handler).
112// Used for private stream, as suggested in http://www.mp4ra.org/handler.html
113#define MP4E_HANDLER_TYPE_GESM 0x6765736D
114
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
120
121/************************************************************************/
122/* Data structures */
123/************************************************************************/
124
125typedef struct MP4E_mux_tag MP4E_mux_t;
126
128
129typedef struct {
130 // MP4 object type code, which defined codec class for the track.
131 // See MP4E_OBJECT_TYPE_* values for some codecs
132 unsigned object_type_indication;
133
134 // Track language: 3-char ISO 639-2T code: "und", "eng", "rus", "jpn" etc...
135 unsigned char language[4];
136
137 track_media_kind_t track_media_kind;
138
139 // 90000 for video, sample rate for audio
140 unsigned time_scale;
141 unsigned default_duration;
142
143 union {
144 struct {
145 // number of channels in the audio track.
146 unsigned channelcount;
147 } a;
148
149 struct {
150 int width;
151 int height;
152 } v;
153 } u;
154
156
158
159typedef struct {
160 /************************************************************************/
161 /* mandatory public data */
162 /************************************************************************/
163 // How many 'samples' in the track
164 // The 'sample' is MP4 term, denoting audio or video frame
165 unsigned sample_count;
166
167 // Decoder-specific info (DSI) data
168 unsigned char* dsi;
169
170 // DSI data size
171 unsigned dsi_bytes;
172
173 // MP4 object type code
174 // case 0x00: return "Forbidden";
175 // case 0x01: return "Systems ISO/IEC 14496-1";
176 // case 0x02: return "Systems ISO/IEC 14496-1";
177 // case 0x20: return "Visual ISO/IEC 14496-2";
178 // case 0x40: return "Audio ISO/IEC 14496-3";
179 // case 0x60: return "Visual ISO/IEC 13818-2 Simple Profile";
180 // case 0x61: return "Visual ISO/IEC 13818-2 Main Profile";
181 // case 0x62: return "Visual ISO/IEC 13818-2 SNR Profile";
182 // case 0x63: return "Visual ISO/IEC 13818-2 Spatial Profile";
183 // case 0x64: return "Visual ISO/IEC 13818-2 High Profile";
184 // case 0x65: return "Visual ISO/IEC 13818-2 422 Profile";
185 // case 0x66: return "Audio ISO/IEC 13818-7 Main Profile";
186 // case 0x67: return "Audio ISO/IEC 13818-7 LC Profile";
187 // case 0x68: return "Audio ISO/IEC 13818-7 SSR Profile";
188 // case 0x69: return "Audio ISO/IEC 13818-3";
189 // case 0x6A: return "Visual ISO/IEC 11172-2";
190 // case 0x6B: return "Audio ISO/IEC 11172-3";
191 // case 0x6C: return "Visual ISO/IEC 10918-1";
192 unsigned object_type_indication;
193
194#if MP4D_INFO_SUPPORTED
195 /************************************************************************/
196 /* informational public data */
197 /************************************************************************/
198 // handler_type when present in a media box, is an integer containing one of
199 // the following values, or a value from a derived specification:
200 // 'vide' Video track
201 // 'soun' Audio track
202 // 'hint' Hint track
203 unsigned handler_type;
204
205 // Track duration: 64-bit value split into 2 variables
206 unsigned duration_hi;
207 unsigned duration_lo;
208
209 // duration scale: duration = timescale*seconds
210 unsigned timescale;
211
212 // Average bitrate, bits per second
213 unsigned avg_bitrate_bps;
214
215 // Track language: 3-char ISO 639-2T code: "und", "eng", "rus", "jpn" etc...
216 unsigned char language[4];
217
218 // MP4 stream type
219 // case 0x00: return "Forbidden";
220 // case 0x01: return "ObjectDescriptorStream";
221 // case 0x02: return "ClockReferenceStream";
222 // case 0x03: return "SceneDescriptionStream";
223 // case 0x04: return "VisualStream";
224 // case 0x05: return "AudioStream";
225 // case 0x06: return "MPEG7Stream";
226 // case 0x07: return "IPMPStream";
227 // case 0x08: return "ObjectContentInfoStream";
228 // case 0x09: return "MPEGJStream";
229 unsigned stream_type;
230
231 union {
232 // for handler_type == 'soun' tracks
233 struct {
234 unsigned channelcount;
235 unsigned samplerate_hz;
236 } audio;
237
238 // for handler_type == 'vide' tracks
239 struct {
240 unsigned width;
241 unsigned height;
242 } video;
243 } SampleDescription;
244#endif
245
246 /************************************************************************/
247 /* private data: MP4 indexes */
248 /************************************************************************/
249 unsigned* entry_size;
250
251 unsigned sample_to_chunk_count;
252 struct MP4D_sample_to_chunk_t_tag* sample_to_chunk;
253
254 unsigned chunk_count;
255 MP4D_file_offset_t* chunk_offset;
256
257#if MP4D_TIMESTAMPS_SUPPORTED
258 unsigned* timestamp;
259 unsigned* duration;
260#endif
261
263
264typedef struct MP4D_demux_tag {
265 /************************************************************************/
266 /* mandatory public data */
267 /************************************************************************/
271 int (*read_callback)(int64_t offset, void* buffer, size_t size, void* token);
272 void* token;
273
274 unsigned track_count; // number of tracks in the movie
275
276#if MP4D_INFO_SUPPORTED
277 /************************************************************************/
278 /* informational public data */
279 /************************************************************************/
280 // Movie duration: 64-bit value split into 2 variables
281 unsigned duration_hi;
282 unsigned duration_lo;
283
284 // duration scale: duration = timescale*seconds
285 unsigned timescale;
286
287 // Metadata tag (optional)
288 // Tags provided 'as-is', without any re-encoding
289 struct {
290 unsigned char* title;
291 unsigned char* artist;
292 unsigned char* album;
293 unsigned char* year;
294 unsigned char* comment;
295 unsigned char* genre;
297#endif
298
300
302 unsigned first_chunk;
303 unsigned samples_per_chunk;
304};
305
306typedef struct {
307 void* sps_cache[MINIMP4_MAX_SPS];
308 void* pps_cache[MINIMP4_MAX_PPS];
309 int sps_bytes[MINIMP4_MAX_SPS];
310 int pps_bytes[MINIMP4_MAX_PPS];
311
312 int map_sps[MINIMP4_MAX_SPS];
313 int map_pps[MINIMP4_MAX_PPS];
314
316
317typedef struct mp4_h26x_writer_tag {
318#if MINIMP4_TRANSCODE_SPS_ID
320#endif
324
325int mp4_h26x_write_init(mp4_h26x_writer_t* h, MP4E_mux_t* mux, int width, int height, int is_hevc);
328 const unsigned char* nal,
329 int length,
330 unsigned timeStamp90kHz_next);
331
332/************************************************************************/
333/* API */
334/************************************************************************/
335
345 int (*read_callback)(int64_t offset, void* buffer, size_t size, void* token),
346 void* token,
347 int64_t file_size);
348
360 unsigned int ntrack,
361 unsigned int nsample,
362 unsigned int* frame_bytes,
363 unsigned* timestamp,
364 unsigned* duration);
365
370
382const void* MP4D_read_sps(const MP4D_demux_t* mp4, unsigned int ntrack, int nsps, int* sps_bytes);
383const void* MP4D_read_pps(const MP4D_demux_t* mp4, unsigned int ntrack, int npps, int* pps_bytes);
384
385#if MP4D_PRINT_INFO_SUPPORTED
391void MP4D_printf_info(const MP4D_demux_t* mp4);
392#endif
393
404MP4E_open(int sequential_mode_flag,
405 int enable_fragmentation,
406 void* token,
407 int (*write_callback)(int64_t offset, const void* buffer, size_t size, void* token));
408
417int MP4E_add_track(MP4E_mux_t* mux, const MP4E_track_t* track_data);
418
430 MP4E_mux_t* mux, int track_num, const void* data, int data_bytes, int duration, int kind);
431
441
450int MP4E_set_dsi(MP4E_mux_t* mux, int track_id, const void* dsi, int bytes);
451
457int MP4E_set_vps(MP4E_mux_t* mux, int track_id, const void* vps, int bytes);
458
464int MP4E_set_sps(MP4E_mux_t* mux, int track_id, const void* sps, int bytes);
465
471int MP4E_set_pps(MP4E_mux_t* mux, int track_id, const void* pps, int bytes);
472
478int MP4E_set_text_comment(MP4E_mux_t* mux, const char* comment);
479
480#ifdef __cplusplus
481}
482#endif
483#endif //MINIMP4_H
484
485#if defined(MINIMP4_IMPLEMENTATION) && !defined(MINIMP4_IMPLEMENTATION_GUARD)
486#define MINIMP4_IMPLEMENTATION_GUARD
487
488#define FOUR_CHAR_INT(a, b, c, d) (((uint32_t)(a) << 24) | ((b) << 16) | ((c) << 8) | (d))
489enum {
490 BOX_co64 = FOUR_CHAR_INT('c', 'o', '6', '4'), //ChunkLargeOffsetAtomType
491 BOX_stco = FOUR_CHAR_INT('s', 't', 'c', 'o'), //ChunkOffsetAtomType
492 BOX_crhd = FOUR_CHAR_INT('c', 'r', 'h', 'd'), //ClockReferenceMediaHeaderAtomType
493 BOX_ctts = FOUR_CHAR_INT('c', 't', 't', 's'), //CompositionOffsetAtomType
494 BOX_cprt = FOUR_CHAR_INT('c', 'p', 'r', 't'), //CopyrightAtomType
495 BOX_url_ = FOUR_CHAR_INT('u', 'r', 'l', ' '), //DataEntryURLAtomType
496 BOX_urn_ = FOUR_CHAR_INT('u', 'r', 'n', ' '), //DataEntryURNAtomType
497 BOX_dinf = FOUR_CHAR_INT('d', 'i', 'n', 'f'), //DataInformationAtomType
498 BOX_dref = FOUR_CHAR_INT('d', 'r', 'e', 'f'), //DataReferenceAtomType
499 BOX_stdp = FOUR_CHAR_INT('s', 't', 'd', 'p'), //DegradationPriorityAtomType
500 BOX_edts = FOUR_CHAR_INT('e', 'd', 't', 's'), //EditAtomType
501 BOX_elst = FOUR_CHAR_INT('e', 'l', 's', 't'), //EditListAtomType
502 BOX_uuid = FOUR_CHAR_INT('u', 'u', 'i', 'd'), //ExtendedAtomType
503 BOX_free = FOUR_CHAR_INT('f', 'r', 'e', 'e'), //FreeSpaceAtomType
504 BOX_hdlr = FOUR_CHAR_INT('h', 'd', 'l', 'r'), //HandlerAtomType
505 BOX_hmhd = FOUR_CHAR_INT('h', 'm', 'h', 'd'), //HintMediaHeaderAtomType
506 BOX_hint = FOUR_CHAR_INT('h', 'i', 'n', 't'), //HintTrackReferenceAtomType
507 BOX_mdia = FOUR_CHAR_INT('m', 'd', 'i', 'a'), //MediaAtomType
508 BOX_mdat = FOUR_CHAR_INT('m', 'd', 'a', 't'), //MediaDataAtomType
509 BOX_mdhd = FOUR_CHAR_INT('m', 'd', 'h', 'd'), //MediaHeaderAtomType
510 BOX_minf = FOUR_CHAR_INT('m', 'i', 'n', 'f'), //MediaInformationAtomType
511 BOX_moov = FOUR_CHAR_INT('m', 'o', 'o', 'v'), //MovieAtomType
512 BOX_mvhd = FOUR_CHAR_INT('m', 'v', 'h', 'd'), //MovieHeaderAtomType
513 BOX_stsd = FOUR_CHAR_INT('s', 't', 's', 'd'), //SampleDescriptionAtomType
514 BOX_stsz = FOUR_CHAR_INT('s', 't', 's', 'z'), //SampleSizeAtomType
515 BOX_stz2 = FOUR_CHAR_INT('s', 't', 'z', '2'), //CompactSampleSizeAtomType
516 BOX_stbl = FOUR_CHAR_INT('s', 't', 'b', 'l'), //SampleTableAtomType
517 BOX_stsc = FOUR_CHAR_INT('s', 't', 's', 'c'), //SampleToChunkAtomType
518 BOX_stsh = FOUR_CHAR_INT('s', 't', 's', 'h'), //ShadowSyncAtomType
519 BOX_skip = FOUR_CHAR_INT('s', 'k', 'i', 'p'), //SkipAtomType
520 BOX_smhd = FOUR_CHAR_INT('s', 'm', 'h', 'd'), //SoundMediaHeaderAtomType
521 BOX_stss = FOUR_CHAR_INT('s', 't', 's', 's'), //SyncSampleAtomType
522 BOX_stts = FOUR_CHAR_INT('s', 't', 't', 's'), //TimeToSampleAtomType
523 BOX_trak = FOUR_CHAR_INT('t', 'r', 'a', 'k'), //TrackAtomType
524 BOX_tkhd = FOUR_CHAR_INT('t', 'k', 'h', 'd'), //TrackHeaderAtomType
525 BOX_tref = FOUR_CHAR_INT('t', 'r', 'e', 'f'), //TrackReferenceAtomType
526 BOX_udta = FOUR_CHAR_INT('u', 'd', 't', 'a'), //UserDataAtomType
527 BOX_vmhd = FOUR_CHAR_INT('v', 'm', 'h', 'd'), //VideoMediaHeaderAtomType
528 BOX_url = FOUR_CHAR_INT('u', 'r', 'l', ' '),
529 BOX_urn = FOUR_CHAR_INT('u', 'r', 'n', ' '),
530
531 BOX_gnrv = FOUR_CHAR_INT('g', 'n', 'r', 'v'), //GenericVisualSampleEntryAtomType
532 BOX_gnra = FOUR_CHAR_INT('g', 'n', 'r', 'a'), //GenericAudioSampleEntryAtomType
533
534 //V2 atoms
535 BOX_ftyp = FOUR_CHAR_INT('f', 't', 'y', 'p'), //FileTypeAtomType
536 BOX_padb = FOUR_CHAR_INT('p', 'a', 'd', 'b'), //PaddingBitsAtomType
537
538 //MP4 Atoms
539 BOX_sdhd = FOUR_CHAR_INT('s', 'd', 'h', 'd'), //SceneDescriptionMediaHeaderAtomType
540 BOX_dpnd = FOUR_CHAR_INT('d', 'p', 'n', 'd'), //StreamDependenceAtomType
541 BOX_iods = FOUR_CHAR_INT('i', 'o', 'd', 's'), //ObjectDescriptorAtomType
542 BOX_odhd = FOUR_CHAR_INT('o', 'd', 'h', 'd'), //ObjectDescriptorMediaHeaderAtomType
543 BOX_mpod = FOUR_CHAR_INT('m', 'p', 'o', 'd'), //ODTrackReferenceAtomType
544 BOX_nmhd = FOUR_CHAR_INT('n', 'm', 'h', 'd'), //MPEGMediaHeaderAtomType
545 BOX_esds = FOUR_CHAR_INT('e', 's', 'd', 's'), //ESDAtomType
546 BOX_sync = FOUR_CHAR_INT('s', 'y', 'n', 'c'), //OCRReferenceAtomType
547 BOX_ipir = FOUR_CHAR_INT('i', 'p', 'i', 'r'), //IPIReferenceAtomType
548 BOX_mp4s = FOUR_CHAR_INT('m', 'p', '4', 's'), //MPEGSampleEntryAtomType
549 BOX_mp4a = FOUR_CHAR_INT('m', 'p', '4', 'a'), //MPEGAudioSampleEntryAtomType
550 BOX_mp4v = FOUR_CHAR_INT('m', 'p', '4', 'v'), //MPEGVisualSampleEntryAtomType
551
552 // http://www.itscj.ipsj.or.jp/sc29/open/29view/29n7644t.doc
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'),
561
562 // H264/HEVC
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'),
566
567 //3GPP atoms
568 BOX_samr = FOUR_CHAR_INT('s', 'a', 'm', 'r'), //AMRSampleEntryAtomType
569 BOX_sawb = FOUR_CHAR_INT('s', 'a', 'w', 'b'), //WB_AMRSampleEntryAtomType
570 BOX_damr = FOUR_CHAR_INT('d', 'a', 'm', 'r'), //AMRConfigAtomType
571 BOX_s263 = FOUR_CHAR_INT('s', '2', '6', '3'), //H263SampleEntryAtomType
572 BOX_d263 = FOUR_CHAR_INT('d', '2', '6', '3'), //H263ConfigAtomType
573
574 //V2 atoms - Movie Fragments
575 BOX_mvex = FOUR_CHAR_INT('m', 'v', 'e', 'x'), //MovieExtendsAtomType
576 BOX_trex = FOUR_CHAR_INT('t', 'r', 'e', 'x'), //TrackExtendsAtomType
577 BOX_moof = FOUR_CHAR_INT('m', 'o', 'o', 'f'), //MovieFragmentAtomType
578 BOX_mfhd = FOUR_CHAR_INT('m', 'f', 'h', 'd'), //MovieFragmentHeaderAtomType
579 BOX_traf = FOUR_CHAR_INT('t', 'r', 'a', 'f'), //TrackFragmentAtomType
580 BOX_tfhd = FOUR_CHAR_INT('t', 'f', 'h', 'd'), //TrackFragmentHeaderAtomType
581 BOX_tfdt = FOUR_CHAR_INT('t', 'f', 'd', 't'), //TrackFragmentBaseMediaDecodeTimeBox
582 BOX_trun = FOUR_CHAR_INT('t', 'r', 'u', 'n'), //TrackFragmentRunAtomType
583 BOX_mehd = FOUR_CHAR_INT('m', 'e', 'h', 'd'), //MovieExtendsHeaderBox
584
585 // Object Descriptors (OD) data coding
586 // These takes only 1 byte; this implementation translate <od_tag> to
587 // <od_tag> + OD_BASE to keep API uniform and safe for string functions
588 OD_BASE = FOUR_CHAR_INT('$', '$', '$', '0'), //
589 OD_ESD = FOUR_CHAR_INT('$', '$', '$', '3'), //SDescriptor_Tag
590 OD_DCD = FOUR_CHAR_INT('$', '$', '$', '4'), //DecoderConfigDescriptor_Tag
591 OD_DSI = FOUR_CHAR_INT('$', '$', '$', '5'), //DecoderSpecificInfo_Tag
592 OD_SLC = FOUR_CHAR_INT('$', '$', '$', '6'), //SLConfigDescriptor_Tag
593
594 BOX_meta = FOUR_CHAR_INT('m', 'e', 't', 'a'),
595 BOX_ilst = FOUR_CHAR_INT('i', 'l', 's', 't'),
596
597 // Metagata tags, see http://atomicparsley.sourceforge.net/mpeg-4files.html
598 BOX_calb = FOUR_CHAR_INT('\xa9', 'a', 'l', 'b'), // album
599 BOX_cart = FOUR_CHAR_INT('\xa9', 'a', 'r', 't'), // artist
600 BOX_aART = FOUR_CHAR_INT('a', 'A', 'R', 'T'), // album artist
601 BOX_ccmt = FOUR_CHAR_INT('\xa9', 'c', 'm', 't'), // comment
602 BOX_cday = FOUR_CHAR_INT('\xa9', 'd', 'a', 'y'), // year (as string)
603 BOX_cnam = FOUR_CHAR_INT('\xa9', 'n', 'a', 'm'), // title
604 BOX_cgen = FOUR_CHAR_INT('\xa9', 'g', 'e', 'n'), // custom genre (as string or as byte!)
605 BOX_trkn = FOUR_CHAR_INT('t', 'r', 'k', 'n'), // track number (byte)
606 BOX_disk = FOUR_CHAR_INT('d', 'i', 's', 'k'), // disk number (byte)
607 BOX_cwrt = FOUR_CHAR_INT('\xa9', 'w', 'r', 't'), // composer
608 BOX_ctoo = FOUR_CHAR_INT('\xa9', 't', 'o', 'o'), // encoder
609 BOX_tmpo = FOUR_CHAR_INT('t', 'm', 'p', 'o'), // bpm (byte)
610 BOX_cpil = FOUR_CHAR_INT('c', 'p', 'i', 'l'), // compilation (byte)
611 BOX_covr = FOUR_CHAR_INT('c', 'o', 'v', 'r'), // cover art (JPEG/PNG)
612 BOX_rtng = FOUR_CHAR_INT('r', 't', 'n', 'g'), // rating/advisory (byte)
613 BOX_cgrp = FOUR_CHAR_INT('\xa9', 'g', 'r', 'p'), // grouping
614 BOX_stik = FOUR_CHAR_INT(
615 's',
616 't',
617 'i',
618 'k'), // stik (byte) 0 = Movie 1 = Normal 2 = Audiobook 5 = Whacked Bookmark 6 = Music Video 9 = Short Film 10 = TV Show 11 = Booklet 14 = Ringtone
619 BOX_pcst = FOUR_CHAR_INT('p', 'c', 's', 't'), // podcast (byte)
620 BOX_catg = FOUR_CHAR_INT('c', 'a', 't', 'g'), // category
621 BOX_keyw = FOUR_CHAR_INT('k', 'e', 'y', 'w'), // keyword
622 BOX_purl = FOUR_CHAR_INT('p', 'u', 'r', 'l'), // podcast URL (byte)
623 BOX_egid = FOUR_CHAR_INT('e', 'g', 'i', 'd'), // episode global unique ID (byte)
624 BOX_desc = FOUR_CHAR_INT('d', 'e', 's', 'c'), // description
625 BOX_clyr = FOUR_CHAR_INT('\xa9', 'l', 'y', 'r'), // lyrics (may be > 255 bytes)
626 BOX_tven = FOUR_CHAR_INT('t', 'v', 'e', 'n'), // tv episode number
627 BOX_tves = FOUR_CHAR_INT('t', 'v', 'e', 's'), // tv episode (byte)
628 BOX_tvnn = FOUR_CHAR_INT('t', 'v', 'n', 'n'), // tv network name
629 BOX_tvsh = FOUR_CHAR_INT('t', 'v', 's', 'h'), // tv show name
630 BOX_tvsn = FOUR_CHAR_INT('t', 'v', 's', 'n'), // tv season (byte)
631 BOX_purd = FOUR_CHAR_INT('p', 'u', 'r', 'd'), // purchase date
632 BOX_pgap = FOUR_CHAR_INT('p', 'g', 'a', 'p'), // Gapless Playback (byte)
633
634 //BOX_aart = FOUR_CHAR_INT( 'a', 'a', 'r', 't' ), // Album artist
635 BOX_cART = FOUR_CHAR_INT('\xa9', 'A', 'R', 'T'), // artist
636 BOX_gnre = FOUR_CHAR_INT('g', 'n', 'r', 'e'),
637
638 // 3GPP metatags (http://cpansearch.perl.org/src/JHAR/MP4-Info-1.12/Info.pm)
639 BOX_auth = FOUR_CHAR_INT('a', 'u', 't', 'h'), // author
640 BOX_titl = FOUR_CHAR_INT('t', 'i', 't', 'l'), // title
641 BOX_dscp = FOUR_CHAR_INT('d', 's', 'c', 'p'), // description
642 BOX_perf = FOUR_CHAR_INT('p', 'e', 'r', 'f'), // performer
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'), //
646
647 // these from http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/2008-September/053151.html
648 BOX_albm = FOUR_CHAR_INT('a', 'l', 'b', 'm'), // album
649 BOX_yrrc = FOUR_CHAR_INT('y', 'r', 'r', 'c') // album
650};
651
652// Video track : 'vide'
653#define MP4E_HANDLER_TYPE_VIDE 0x76696465
654// Audio track : 'soun'
655#define MP4E_HANDLER_TYPE_SOUN 0x736F756E
656// General MPEG-4 systems streams (without specific handler).
657// Used for private stream, as suggested in http://www.mp4ra.org/handler.html
658#define MP4E_HANDLER_TYPE_GESM 0x6765736D
659
660typedef struct {
661 boxsize_t size;
662 boxsize_t offset;
663 unsigned duration;
664 unsigned flag_random_access;
665} sample_t;
666
667typedef struct {
668 unsigned char* data;
669 int bytes;
670 int capacity;
671} minimp4_vector_t;
672
673typedef struct {
674 MP4E_track_t info;
675 minimp4_vector_t smpl; // sample descriptor
676 minimp4_vector_t pending_sample;
677
678 minimp4_vector_t vsps; // or dsi for audio
679 minimp4_vector_t vpps; // not used for audio
680 minimp4_vector_t vvps; // used for HEVC
681
682} track_t;
683
684typedef struct MP4E_mux_tag {
685 minimp4_vector_t tracks;
686
687 int64_t write_pos;
688 int (*write_callback)(int64_t offset, const void* buffer, size_t size, void* token);
689 void* token;
690 char* text_comment;
691
692 int sequential_mode_flag;
693 int enable_fragmentation; // flag, indicating streaming-friendly 'fragmentation' mode
694 int fragments_count; // # of fragments in 'fragmentation' mode
695
696} MP4E_mux_t;
697
698static const unsigned char box_ftyp[] = {
699#if 1
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',
702#else
703 // as in ffmpeg
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',
706#endif
707};
708
712#define WR(x, n) *p++ = (unsigned char)((x) >> 8 * n)
713#define WRITE_1(x) WR(x, 0);
714#define WRITE_2(x) \
715 WR(x, 1); \
716 WR(x, 0);
717#define WRITE_3(x) \
718 WR(x, 2); \
719 WR(x, 1); \
720 WR(x, 0);
721#define WRITE_4(x) \
722 WR(x, 3); \
723 WR(x, 2); \
724 WR(x, 1); \
725 WR(x, 0);
726#define WR4(p, x) \
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));
731
732// Finish atom: update atom size field
733#define END_ATOM \
734 --stack; \
735 WR4((unsigned char*)*stack, p - *stack);
736
737// Initiate atom: save position of size field on stack
738#define ATOM(x) \
739 *stack++ = p; \
740 p += 4; \
741 WRITE_4(x);
742
743// Atom with 'FullAtomVersionFlags' field
744#define ATOM_FULL(x, flag) \
745 ATOM(x); \
746 WRITE_4(flag);
747
748#define ERR(func) \
749 { \
750 int err = func; \
751 if (err) \
752 return err; \
753 }
754
758static int minimp4_vector_init(minimp4_vector_t* h, int capacity) {
759 h->bytes = 0;
760 h->capacity = capacity;
761 h->data = capacity ? (unsigned char*)malloc(capacity) : NULL;
762 return !capacity || !!h->data;
763}
764
768static void minimp4_vector_reset(minimp4_vector_t* h) {
769 if (h->data)
770 free(h->data);
771 memset(h, 0, sizeof(minimp4_vector_t));
772}
773
777static int minimp4_vector_grow(minimp4_vector_t* h, int bytes) {
778 void* p;
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);
783 if (!p)
784 return 0;
785 h->data = (unsigned char*)p;
786 h->capacity = new_size;
787 return 1;
788}
789
795static unsigned char* minimp4_vector_alloc_tail(minimp4_vector_t* h, int bytes) {
796 unsigned char* p;
797 if (!h->data && !minimp4_vector_init(h, 2 * bytes + 1024))
798 return NULL;
799 if ((h->capacity - h->bytes) < bytes && !minimp4_vector_grow(h, bytes))
800 return NULL;
801 assert(h->data);
802 assert((h->capacity - h->bytes) >= bytes);
803 p = h->data + h->bytes;
804 h->bytes += bytes;
805 return p;
806}
807
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);
813 if (tail)
814 memcpy(tail, (void*)buf, bytes);
815 return tail;
816}
817
823MP4E_open(int sequential_mode_flag,
824 int enable_fragmentation,
825 void* token,
826 int (*write_callback)(int64_t offset, const void* buffer, size_t size, void* token)) {
827 if (write_callback(0, box_ftyp, sizeof(box_ftyp), token)) // Write fixed header: 'ftyp' box
828 return 0;
829 MP4E_mux_t* mux = (MP4E_mux_t*)malloc(sizeof(MP4E_mux_t));
830 if (!mux)
831 return mux;
832 mux->sequential_mode_flag = sequential_mode_flag || enable_fragmentation;
833 mux->enable_fragmentation = enable_fragmentation;
834 mux->fragments_count = 0;
835 mux->write_callback = write_callback;
836 mux->token = token;
837 mux->text_comment = NULL;
838 mux->write_pos = sizeof(box_ftyp);
839
840 if (!mux->sequential_mode_flag) { // Write filler, which would be updated later
841 if (mux->write_callback(mux->write_pos, box_ftyp, 8, mux->token)) {
842 free(mux);
843 return 0;
844 }
845 mux->write_pos += 16; // box_ftyp + box_free for 32bit or 64bit size encoding
846 }
847 minimp4_vector_init(&mux->tracks, 2 * sizeof(track_t));
848 return mux;
849}
850
854int MP4E_add_track(MP4E_mux_t* mux, const MP4E_track_t* track_data) {
855 track_t* tr;
856 int ntr = mux->tracks.bytes / sizeof(track_t);
857
858 if (!mux || !track_data)
860
861 tr = (track_t*)minimp4_vector_alloc_tail(&mux->tracks, sizeof(track_t));
862 if (!tr)
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);
871 return ntr;
872}
873
874static const unsigned char* next_dsi(const unsigned char* p, const unsigned char* end, int* bytes) {
875 if (p < end + 2) {
876 *bytes = p[0] * 256 + p[1];
877 return p + 2;
878 } else
879 return NULL;
880}
881
882static int append_mem(minimp4_vector_t* v, const void* mem, int bytes) {
883 int i;
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))
889 return 1;
890 i += 2 + cb;
891 }
892 size[0] = bytes >> 8;
893 size[1] = bytes;
894 return minimp4_vector_put(v, size, 2) && minimp4_vector_put(v, mem, bytes);
895}
896
897static int items_count(minimp4_vector_t* v) {
898 int i, count = 0;
899 const unsigned char* p = v->data;
900 for (i = 0; i + 2 < v->bytes;) {
901 int cb = p[i] * 256 + p[i + 1];
902 count++;
903 i += 2 + cb;
904 }
905 return count;
906}
907
908int MP4E_set_dsi(MP4E_mux_t* mux, int track_id, const void* dsi, int bytes) {
909 track_t* tr = ((track_t*)mux->tracks.data) + track_id;
910 assert(tr->info.track_media_kind == e_audio || tr->info.track_media_kind == e_private);
911 if (tr->vsps.bytes)
912 return MP4E_STATUS_ONLY_ONE_DSI_ALLOWED; // only one DSI allowed
913 return append_mem(&tr->vsps, dsi, bytes) ? MP4E_STATUS_OK : MP4E_STATUS_NO_MEMORY;
914}
915
916int MP4E_set_vps(MP4E_mux_t* mux, int track_id, const void* vps, int bytes) {
917 track_t* tr = ((track_t*)mux->tracks.data) + track_id;
918 assert(tr->info.track_media_kind == e_video);
919 return append_mem(&tr->vvps, vps, bytes) ? MP4E_STATUS_OK : MP4E_STATUS_NO_MEMORY;
920}
921
922int MP4E_set_sps(MP4E_mux_t* mux, int track_id, const void* sps, int bytes) {
923 track_t* tr = ((track_t*)mux->tracks.data) + track_id;
924 assert(tr->info.track_media_kind == e_video);
925 return append_mem(&tr->vsps, sps, bytes) ? MP4E_STATUS_OK : MP4E_STATUS_NO_MEMORY;
926}
927
928int MP4E_set_pps(MP4E_mux_t* mux, int track_id, const void* pps, int bytes) {
929 track_t* tr = ((track_t*)mux->tracks.data) + track_id;
930 assert(tr->info.track_media_kind == e_video);
931 return append_mem(&tr->vpps, pps, bytes) ? MP4E_STATUS_OK : MP4E_STATUS_NO_MEMORY;
932}
933
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;
939 }
940 return sum_duration;
941}
942
943static int write_pending_data(MP4E_mux_t* mux, track_t* tr) {
944 // if have pending sample && have at least one sample in the index
945 if (tr->pending_sample.bytes > 0 && tr->smpl.bytes >= sizeof(sample_t)) {
946 // Complete pending sample
947 sample_t* smpl_desc;
948 unsigned char base[8], *p = base;
949
950 assert(mux->sequential_mode_flag);
951
952 // Write each sample to a separate atom
953 assert(mux->sequential_mode_flag); // Separate atom needed for sequential_mode only
954 WRITE_4(tr->pending_sample.bytes + 8);
955 WRITE_4(BOX_mdat);
956 ERR(mux->write_callback(mux->write_pos, base, p - base, mux->token));
957 mux->write_pos += p - base;
958
959 // Update sample descriptor with size and offset
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;
963
964 // Write data
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;
968
969 // reset buffer
970 tr->pending_sample.bytes = 0;
971 }
972 return MP4E_STATUS_OK;
973}
974
975static int
976add_sample_descriptor(MP4E_mux_t* mux, track_t* tr, int data_bytes, int duration, int kind) {
977 sample_t smp;
978 smp.size = data_bytes;
979 smp.offset = (boxsize_t)mux->write_pos;
980 smp.duration = (duration ? duration : tr->info.default_duration);
981 smp.flag_random_access = (kind == MP4E_SAMPLE_RANDOM_ACCESS);
982 return NULL != minimp4_vector_put(&tr->smpl, &smp, sizeof(sample_t));
983}
984
985static int mp4e_flush_index(MP4E_mux_t* mux);
986
990static int mp4e_write_fragment_header(MP4E_mux_t* mux,
991 int track_num,
992 int data_bytes,
993 int duration,
994 int kind
996 ,
997 uint64_t timestamp
998#endif
999) {
1000 unsigned char base[888], *p = base;
1001 unsigned char* stack_base[20]; // atoms nesting stack
1002 unsigned char** stack = stack_base;
1003 unsigned char* pdata_offset;
1004 unsigned flags;
1005 enum {
1006 default_sample_duration_present = 0x000008,
1007 default_sample_flags_present = 0x000020,
1008 } e;
1009
1010 track_t* tr = ((track_t*)mux->tracks.data) + track_num;
1011
1012 ATOM(BOX_moof)
1013 ATOM_FULL(BOX_mfhd, 0)
1014 WRITE_4(mux->fragments_count); // start from 1
1015 END_ATOM
1016 ATOM(BOX_traf)
1017 flags = 0;
1018 if (tr->info.track_media_kind == e_video)
1019 flags |= 0x20; // default-sample-flags-present
1020 else
1021 flags |= 0x08; // default-sample-duration-present
1022 flags = (tr->info.track_media_kind == e_video) ? 0x20020 : 0x20008;
1023
1024 ATOM_FULL(BOX_tfhd, flags)
1025 WRITE_4(track_num + 1); // track_ID
1026 if (tr->info.track_media_kind == e_video) {
1027 WRITE_4(0x1010000); // default_sample_flags
1028 } else {
1029 WRITE_4(duration);
1030 }
1031 END_ATOM
1032#if MP4D_TFDT_SUPPORT
1033 ATOM_FULL(BOX_tfdt, 0x01000000) // version 1
1034 WRITE_4(timestamp >> 32); // upper timestamp
1035 WRITE_4(timestamp & 0xffffffff); // lower timestamp
1036 END_ATOM
1037#endif
1038 if (tr->info.track_media_kind == e_audio) {
1039 flags = 0;
1040 flags |= 0x001; // data-offset-present
1041 flags |= 0x200; // sample-size-present
1042 ATOM_FULL(BOX_trun, flags)
1043 WRITE_4(1); // sample_count
1044 pdata_offset = p;
1045 p += 4; // save ptr to data_offset
1046 WRITE_4(data_bytes); // sample_size
1047 END_ATOM
1048 } else if (kind == MP4E_SAMPLE_RANDOM_ACCESS) {
1049 flags = 0;
1050 flags |= 0x001; // data-offset-present
1051 flags |= 0x004; // first-sample-flags-present
1052 flags |= 0x100; // sample-duration-present
1053 flags |= 0x200; // sample-size-present
1054 ATOM_FULL(BOX_trun, flags)
1055 WRITE_4(1); // sample_count
1056 pdata_offset = p;
1057 p += 4; // save ptr to data_offset
1058 WRITE_4(0x2000000); // first_sample_flags
1059 WRITE_4(duration); // sample_duration
1060 WRITE_4(data_bytes); // sample_size
1061 END_ATOM
1062 } else {
1063 flags = 0;
1064 flags |= 0x001; // data-offset-present
1065 flags |= 0x100; // sample-duration-present
1066 flags |= 0x200; // sample-size-present
1067 ATOM_FULL(BOX_trun, flags)
1068 WRITE_4(1); // sample_count
1069 pdata_offset = p;
1070 p += 4; // save ptr to data_offset
1071 WRITE_4(duration); // sample_duration
1072 WRITE_4(data_bytes); // sample_size
1073 END_ATOM
1074 }
1075 END_ATOM
1076 END_ATOM
1077 WR4(pdata_offset, (p - base) + 8);
1078
1079 ERR(mux->write_callback(mux->write_pos, base, p - base, mux->token));
1080 mux->write_pos += p - base;
1081 return MP4E_STATUS_OK;
1082}
1083
1084static int mp4e_write_mdat_box(MP4E_mux_t* mux, uint32_t size) {
1085 unsigned char base[8], *p = base;
1086 WRITE_4(size);
1087 WRITE_4(BOX_mdat);
1088 ERR(mux->write_callback(mux->write_pos, base, p - base, mux->token));
1089 mux->write_pos += p - base;
1090 return MP4E_STATUS_OK;
1091}
1092
1096int MP4E_put_sample(
1097 MP4E_mux_t* mux, int track_num, const void* data, int data_bytes, int duration, int kind) {
1098 track_t* tr;
1099 if (!mux || !data)
1101 tr = ((track_t*)mux->tracks.data) + track_num;
1102
1103 if (mux->enable_fragmentation) {
1104#if MP4D_TFDT_SUPPORT
1105 // NOTE: assume a constant `duration` to calculate current timestamp
1106 uint64_t timestamp = (uint64_t)mux->fragments_count * duration;
1107#endif
1108 if (!mux->fragments_count++)
1109 ERR(mp4e_flush_index(mux)); // write file headers before 1st sample
1110 // write MOOF + MDAT + sample data
1111#if MP4D_TFDT_SUPPORT
1112 ERR(mp4e_write_fragment_header(mux, track_num, data_bytes, duration, kind, timestamp));
1113#else
1114 ERR(mp4e_write_fragment_header(mux, track_num, data_bytes, duration, kind));
1115#endif
1116 // write MDAT box for each sample
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;
1120 return MP4E_STATUS_OK;
1121 }
1122
1123 if (kind != MP4E_SAMPLE_CONTINUATION) {
1124 if (mux->sequential_mode_flag)
1125 ERR(write_pending_data(mux, tr));
1126 if (!add_sample_descriptor(mux, tr, data_bytes, duration, kind))
1127 return MP4E_STATUS_NO_MEMORY;
1128 } else {
1129 if (!mux->sequential_mode_flag) {
1130 sample_t* smpl_desc;
1131 if (tr->smpl.bytes < sizeof(sample_t))
1132 return MP4E_STATUS_NO_MEMORY; // write continuation, but there are no samples in the index
1133 // Accumulate size of the continuation in the sample descriptor
1134 smpl_desc = (sample_t*)(tr->smpl.data + tr->smpl.bytes) - 1;
1135 smpl_desc->size += data_bytes;
1136 }
1137 }
1138
1139 if (mux->sequential_mode_flag) {
1140 if (!minimp4_vector_put(&tr->pending_sample, data, data_bytes))
1141 return MP4E_STATUS_NO_MEMORY;
1142 } else {
1143 ERR(mux->write_callback(mux->write_pos, data, data_bytes, mux->token));
1144 mux->write_pos += data_bytes;
1145 }
1146 return MP4E_STATUS_OK;
1147}
1148
1152static int od_size_of_size(int size) {
1153 int i, size_of_size = 1;
1154 for (i = size; i > 0x7F; i -= 0x7F)
1155 size_of_size++;
1156 return size_of_size;
1157}
1158
1165int MP4E_set_text_comment(MP4E_mux_t* mux, const char* comment) {
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)
1172 return MP4E_STATUS_NO_MEMORY;
1173 return MP4E_STATUS_OK;
1174}
1175
1179static int mp4e_flush_index(MP4E_mux_t* mux) {
1180 unsigned char* stack_base[20]; // atoms nesting stack
1181 unsigned char** stack = stack_base;
1182 unsigned char *base, *p;
1183 unsigned int ntr, index_bytes, ntracks = mux->tracks.bytes / sizeof(track_t);
1184 int i, err;
1185
1186 // How much memory needed for indexes
1187 // Experimental data:
1188 // file with 1 track = 560 bytes
1189 // file with 2 tracks = 972 bytes
1190 // track size = 412 bytes;
1191 // file header size = 148 bytes
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; // fixed amount (implementation-dependent)
1200 // may need extra 4 bytes for duration field + 4 bytes for worst-case random access box
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;
1204
1205 ERR(write_pending_data(mux, tr));
1206 }
1207
1208 base = (unsigned char*)malloc(index_bytes);
1209 if (!base)
1210 return MP4E_STATUS_NO_MEMORY;
1211 p = base;
1212
1213 if (!mux->sequential_mode_flag) {
1214 // update size of mdat box.
1215 // One of 2 points, which requires random file access.
1216 // Second is optional duration update at beginning of file in fragmentation mode.
1217 // This can be avoided using "till eof" size code, but in this case indexes must be
1218 // written before the mdat....
1219 int64_t size = mux->write_pos - sizeof(box_ftyp);
1220 const int64_t size_limit = (int64_t)(uint64_t)0xfffffffe;
1221 if (size > size_limit) {
1222 WRITE_4(1);
1223 WRITE_4(BOX_mdat);
1224 WRITE_4((size >> 32) & 0xffffffff);
1225 WRITE_4(size & 0xffffffff);
1226 } else {
1227 WRITE_4(8);
1228 WRITE_4(BOX_free);
1229 WRITE_4(size - 8);
1230 WRITE_4(BOX_mdat);
1231 }
1232 ERR(mux->write_callback(sizeof(box_ftyp), base, p - base, mux->token));
1233 p = base;
1234 }
1235
1236 // Write index atoms; order taken from Table 1 of [1]
1237#define MOOV_TIMESCALE 1000
1238 ATOM(BOX_moov);
1239 ATOM_FULL(BOX_mvhd, 0);
1240 WRITE_4(0); // creation_time
1241 WRITE_4(0); // modification_time
1242
1243 if (ntracks) {
1244 track_t* tr = ((track_t*)mux->tracks.data) + 0; // take 1st track
1245 unsigned duration = get_duration(tr);
1246 duration = (unsigned)(duration * 1LL * MOOV_TIMESCALE / tr->info.time_scale);
1247 WRITE_4(MOOV_TIMESCALE); // duration
1248 WRITE_4(duration); // duration
1249 }
1250
1251 WRITE_4(0x00010000); // rate
1252 WRITE_2(0x0100); // volume
1253 WRITE_2(0); // reserved
1254 WRITE_4(0); // reserved
1255 WRITE_4(0); // reserved
1256
1257 // matrix[9]
1258 WRITE_4(0x00010000);
1259 WRITE_4(0);
1260 WRITE_4(0);
1261 WRITE_4(0);
1262 WRITE_4(0x00010000);
1263 WRITE_4(0);
1264 WRITE_4(0);
1265 WRITE_4(0);
1266 WRITE_4(0x40000000);
1267
1268 // pre_defined[6]
1269 WRITE_4(0);
1270 WRITE_4(0);
1271 WRITE_4(0);
1272 WRITE_4(0);
1273 WRITE_4(0);
1274 WRITE_4(0);
1275
1276 //next_track_ID is a non-zero integer that indicates a value to use for the track ID of the next track to be
1277 //added to this presentation. Zero is not a valid track ID value. The value of next_track_ID shall be
1278 //larger than the largest track-ID in use.
1279 WRITE_4(ntracks + 1);
1280 END_ATOM;
1281
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;
1289
1290 if (mux->enable_fragmentation)
1291 samples_count = 0;
1292 else if (samples_count <= 0)
1293 continue; // skip empty track
1294
1295 switch (tr->info.track_media_kind) {
1296 case e_audio:
1297 handler_type = MP4E_HANDLER_TYPE_SOUN;
1298 handler_ascii = "SoundHandler";
1299 break;
1300 case e_video:
1301 handler_type = MP4E_HANDLER_TYPE_VIDE;
1302 handler_ascii = "VideoHandler";
1303 break;
1304 case e_private:
1305 handler_type = MP4E_HANDLER_TYPE_GESM;
1306 break;
1307 default:
1309 }
1310
1311 ATOM(BOX_trak);
1312 ATOM_FULL(BOX_tkhd, 7); // flag: 1=trak enabled; 2=track in movie; 4=track in preview
1313 WRITE_4(0); // creation_time
1314 WRITE_4(0); // modification_time
1315 WRITE_4(ntr + 1); // track_ID
1316 WRITE_4(0); // reserved
1317 WRITE_4((unsigned)(duration * 1LL * MOOV_TIMESCALE / tr->info.time_scale));
1318 WRITE_4(0);
1319 WRITE_4(0); // reserved[2]
1320 WRITE_2(0); // layer
1321 WRITE_2(0); // alternate_group
1322 WRITE_2(0x0100); // volume {if track_is_audio 0x0100 else 0};
1323 WRITE_2(0); // reserved
1324
1325 // matrix[9]
1326 WRITE_4(0x00010000);
1327 WRITE_4(0);
1328 WRITE_4(0);
1329 WRITE_4(0);
1330 WRITE_4(0x00010000);
1331 WRITE_4(0);
1332 WRITE_4(0);
1333 WRITE_4(0);
1334 WRITE_4(0x40000000);
1335
1336 if (tr->info.track_media_kind == e_audio || tr->info.track_media_kind == e_private) {
1337 WRITE_4(0); // width
1338 WRITE_4(0); // height
1339 } else {
1340 WRITE_4(tr->info.u.v.width * 0x10000); // width
1341 WRITE_4(tr->info.u.v.height * 0x10000); // height
1342 }
1343 END_ATOM;
1344
1345 ATOM(BOX_mdia);
1346 ATOM_FULL(BOX_mdhd, 0);
1347 WRITE_4(0); // creation_time
1348 WRITE_4(0); // modification_time
1349 WRITE_4(tr->info.time_scale);
1350 WRITE_4(duration); // duration
1351 {
1352 int lang_code = ((tr->info.language[0] & 31) << 10) |
1353 ((tr->info.language[1] & 31) << 5) | (tr->info.language[2] & 31);
1354 WRITE_2(lang_code); // language
1355 }
1356 WRITE_2(0); // pre_defined
1357 END_ATOM;
1358
1359 ATOM_FULL(BOX_hdlr, 0);
1360 WRITE_4(0); // pre_defined
1361 WRITE_4(handler_type); // handler_type
1362 WRITE_4(0);
1363 WRITE_4(0);
1364 WRITE_4(0); // reserved[3]
1365 // name is a null-terminated string in UTF-8 characters which gives a human-readable name for the track type (for debugging and inspection purposes).
1366 // set mdia hdlr name field to what quicktime uses.
1367 // Sony smartphone may fail to decode short files w/o handler name
1368 if (handler_ascii) {
1369 for (i = 0; i < (int)strlen(handler_ascii) + 1; i++) {
1370 WRITE_1(handler_ascii[i]);
1371 }
1372 } else {
1373 WRITE_4(0);
1374 }
1375 END_ATOM;
1376
1377 ATOM(BOX_minf);
1378
1379 if (tr->info.track_media_kind == e_audio) {
1380 // Sound Media Header Box
1381 ATOM_FULL(BOX_smhd, 0);
1382 WRITE_2(0); // balance
1383 WRITE_2(0); // reserved
1384 END_ATOM;
1385 }
1386 if (tr->info.track_media_kind == e_video) {
1387 // mandatory Video Media Header Box
1388 ATOM_FULL(BOX_vmhd, 1);
1389 WRITE_2(0); // graphicsmode
1390 WRITE_2(0);
1391 WRITE_2(0);
1392 WRITE_2(0); // opcolor[3]
1393 END_ATOM;
1394 }
1395
1396 ATOM(BOX_dinf);
1397 ATOM_FULL(BOX_dref, 0);
1398 WRITE_4(1); // entry_count
1399 // If the flag is set indicating that the data is in the same file as this box, then no string (not even an empty one)
1400 // shall be supplied in the entry field.
1401
1402 // ASP the correct way to avoid supply the string, is to use flag 1
1403 // otherwise ISO reference demux crashes
1404 ATOM_FULL(BOX_url, 1);
1405 END_ATOM;
1406 END_ATOM;
1407 END_ATOM;
1408
1409 ATOM(BOX_stbl);
1410 ATOM_FULL(BOX_stsd, 0);
1411 WRITE_4(1); // entry_count;
1412
1413 if (tr->info.track_media_kind == e_audio || tr->info.track_media_kind == e_private) {
1414 // AudioSampleEntry() assume MP4E_HANDLER_TYPE_SOUN
1415 if (tr->info.track_media_kind == e_audio) {
1416 ATOM(BOX_mp4a);
1417 } else {
1418 ATOM(BOX_mp4s);
1419 }
1420
1421 // SampleEntry
1422 WRITE_4(0);
1423 WRITE_2(0); // reserved[6]
1424 WRITE_2(1); // data_reference_index; - this is a tag for descriptor below
1425
1426 if (tr->info.track_media_kind == e_audio) {
1427 // AudioSampleEntry
1428 WRITE_4(0);
1429 WRITE_4(0); // reserved[2]
1430 WRITE_2(tr->info.u.a.channelcount); // channelcount
1431 WRITE_2(16); // samplesize
1432 WRITE_4(0); // pre_defined+reserved
1433 WRITE_4((tr->info.time_scale << 16)); // samplerate == = {timescale of media}<<16;
1434 }
1435
1436 ATOM_FULL(BOX_esds, 0);
1437 if (tr->vsps.bytes > 0) {
1438 int dsi_bytes = tr->vsps.bytes - 2; // - two bytes size field
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;
1443
1444#define WRITE_OD_LEN(size) \
1445 if (size > 0x7F) \
1446 do { \
1447 size -= 0x7F; \
1448 WRITE_1(0x00ff); \
1449 } while (size > 0x7F); \
1450 WRITE_1(size)
1451 WRITE_1(3); // OD_ESD
1452 WRITE_OD_LEN(esd_bytes);
1453 WRITE_2(0); // ES_ID(2) // TODO - what is this?
1454 WRITE_1(0); // flags(1)
1455
1456 WRITE_1(4); // OD_DCD
1457 WRITE_OD_LEN(dcd_bytes);
1458 if (tr->info.track_media_kind == e_audio) {
1459 WRITE_1(MP4_OBJECT_TYPE_AUDIO_ISO_IEC_14496_3); // OD_DCD
1460 WRITE_1(5 << 2); // stream_type == AudioStream
1461 } else {
1462 // http://xhelmboyx.tripod.com/formats/mp4-layout.txt
1463 WRITE_1(208); // 208 = private video
1464 WRITE_1(32 << 2); // stream_type == user private
1465 }
1466 WRITE_3(tr->info.u.a.channelcount * 6144 /
1467 8); // bufferSizeDB in bytes, constant as in reference decoder
1468 WRITE_4(0); // maxBitrate TODO
1469 WRITE_4(0); // avg_bitrate_bps TODO
1470
1471 WRITE_1(5); // OD_DSI
1472 WRITE_OD_LEN(dsi_bytes);
1473 for (i = 0; i < dsi_bytes; i++) {
1474 WRITE_1(tr->vsps.data[2 + i]);
1475 }
1476 }
1477 END_ATOM;
1478 END_ATOM;
1479 }
1480
1481 if (tr->info.track_media_kind == e_video &&
1482 (MP4_OBJECT_TYPE_AVC == tr->info.object_type_indication ||
1483 MP4_OBJECT_TYPE_HEVC == tr->info.object_type_indication)) {
1484 int numOfSequenceParameterSets = items_count(&tr->vsps);
1485 int numOfPictureParameterSets = items_count(&tr->vpps);
1486 if (MP4_OBJECT_TYPE_AVC == tr->info.object_type_indication) {
1487 ATOM(BOX_avc1);
1488 } else {
1489 ATOM(BOX_hvc1);
1490 }
1491 // VisualSampleEntry 8.16.2
1492 // extends SampleEntry
1493 WRITE_2(0); // reserved
1494 WRITE_2(0); // reserved
1495 WRITE_2(0); // reserved
1496 WRITE_2(1); // data_reference_index
1497
1498 WRITE_2(0); // pre_defined
1499 WRITE_2(0); // reserved
1500 WRITE_4(0); // pre_defined
1501 WRITE_4(0); // pre_defined
1502 WRITE_4(0); // pre_defined
1503 WRITE_2(tr->info.u.v.width);
1504 WRITE_2(tr->info.u.v.height);
1505 WRITE_4(0x00480000); // horizresolution = 72 dpi
1506 WRITE_4(0x00480000); // vertresolution = 72 dpi
1507 WRITE_4(0); // reserved
1508 WRITE_2(1); // frame_count
1509 for (i = 0; i < 32; i++) {
1510 WRITE_1(0); // compressorname
1511 }
1512 WRITE_2(24); // depth
1513 WRITE_2(-1); // pre_defined
1514
1515 if (MP4_OBJECT_TYPE_AVC == tr->info.object_type_indication) {
1516 ATOM(BOX_avcC);
1517 // AVCDecoderConfigurationRecord 5.2.4.1.1
1518 WRITE_1(1); // configurationVersion
1519 WRITE_1(tr->vsps.data[2 + 1]);
1520 WRITE_1(tr->vsps.data[2 + 2]);
1521 WRITE_1(tr->vsps.data[2 + 3]);
1522 WRITE_1(255); // 0xfc + NALU_len - 1
1523 WRITE_1(0xe0 | numOfSequenceParameterSets);
1524 for (i = 0; i < tr->vsps.bytes; i++) {
1525 WRITE_1(tr->vsps.data[i]);
1526 }
1527 WRITE_1(numOfPictureParameterSets);
1528 for (i = 0; i < tr->vpps.bytes; i++) {
1529 WRITE_1(tr->vpps.data[i]);
1530 }
1531 } else {
1532 int numOfVPS = items_count(&tr->vpps);
1533 ATOM(BOX_hvcC);
1534 // TODO: read actual params from stream
1535 WRITE_1(1); // configurationVersion
1536 WRITE_1(1); // Profile Space (2), Tier (1), Profile (5)
1537 WRITE_4(0x60000000); // Profile Compatibility
1538 WRITE_2(
1539 0); // progressive, interlaced, non packed constraint, frame only constraint flags
1540 WRITE_4(0); // constraint indicator flags
1541 WRITE_1(0); // level_idc
1542 WRITE_2(0xf000); // Min Spatial Segmentation
1543 WRITE_1(0xfc); // Parallelism Type
1544 WRITE_1(0xfc); // Chroma Format
1545 WRITE_1(0xf8); // Luma Depth
1546 WRITE_1(0xf8); // Chroma Depth
1547 WRITE_2(0); // Avg Frame Rate
1548 WRITE_1(
1549 3); // ConstantFrameRate (2), NumTemporalLayers (3), TemporalIdNested (1), LengthSizeMinusOne (2)
1550
1551 WRITE_1(3); // Num Of Arrays
1552 WRITE_1((1 << 7) | (HEVC_NAL_VPS & 0x3f)); // Array Completeness + NAL Unit Type
1553 WRITE_2(numOfVPS);
1554 for (i = 0; i < tr->vvps.bytes; i++) {
1555 WRITE_1(tr->vvps.data[i]);
1556 }
1557 WRITE_1((1 << 7) | (HEVC_NAL_SPS & 0x3f));
1558 WRITE_2(numOfSequenceParameterSets);
1559 for (i = 0; i < tr->vsps.bytes; i++) {
1560 WRITE_1(tr->vsps.data[i]);
1561 }
1562 WRITE_1((1 << 7) | (HEVC_NAL_PPS & 0x3f));
1563 WRITE_2(numOfPictureParameterSets);
1564 for (i = 0; i < tr->vpps.bytes; i++) {
1565 WRITE_1(tr->vpps.data[i]);
1566 }
1567 }
1568
1569 END_ATOM;
1570 END_ATOM;
1571 }
1572 END_ATOM;
1573
1574 /************************************************************************/
1575 /* indexes */
1576 /************************************************************************/
1577
1578 // Time to Sample Box
1579 ATOM_FULL(BOX_stts, 0);
1580 {
1581 unsigned char* pentry_count = p;
1582 int cnt = 1, entry_count = 0;
1583 WRITE_4(0);
1584 for (i = 0; i < samples_count; i++, cnt++) {
1585 if (i == (samples_count - 1) || sample[i].duration != sample[i + 1].duration) {
1586 WRITE_4(cnt);
1587 WRITE_4(sample[i].duration);
1588 cnt = 0;
1589 entry_count++;
1590 }
1591 }
1592 WR4(pentry_count, entry_count);
1593 }
1594 END_ATOM;
1595
1596 // Sample To Chunk Box
1597 ATOM_FULL(BOX_stsc, 0);
1598 if (mux->enable_fragmentation) {
1599 WRITE_4(0); // entry_count
1600 } else {
1601 WRITE_4(1); // entry_count
1602 WRITE_4(1); // first_chunk;
1603 WRITE_4(1); // samples_per_chunk;
1604 WRITE_4(1); // sample_description_index;
1605 }
1606 END_ATOM;
1607
1608 // Sample Size Box
1609 ATOM_FULL(BOX_stsz, 0);
1610 WRITE_4(
1611 0); // sample_size If this field is set to 0, then the samples have different sizes, and those sizes
1612 // are stored in the sample size table.
1613 WRITE_4(samples_count); // sample_count;
1614 for (i = 0; i < samples_count; i++) {
1615 WRITE_4(sample[i].size);
1616 }
1617 END_ATOM;
1618
1619 // Chunk Offset Box
1620 int is_64_bit = 0;
1621 if (samples_count && sample[samples_count - 1].offset > 0xffffffff)
1622 is_64_bit = 1;
1623 if (!is_64_bit) {
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);
1628 }
1629 } else {
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);
1635 }
1636 }
1637 END_ATOM;
1638
1639 // Sync Sample Box
1640 {
1641 int ra_count = 0;
1642 for (i = 0; i < samples_count; i++) {
1643 ra_count += !!sample[i].flag_random_access;
1644 }
1645 if (ra_count != samples_count) {
1646 // If the sync sample box is not present, every sample is a random access point.
1647 ATOM_FULL(BOX_stss, 0);
1648 WRITE_4(ra_count);
1649 for (i = 0; i < samples_count; i++) {
1650 if (sample[i].flag_random_access) {
1651 WRITE_4(i + 1);
1652 }
1653 }
1654 END_ATOM;
1655 }
1656 }
1657 END_ATOM;
1658 END_ATOM;
1659 END_ATOM;
1660 END_ATOM;
1661 } // tracks loop
1662
1663 if (mux->text_comment) {
1664 ATOM(BOX_udta);
1665 ATOM_FULL(BOX_meta, 0);
1666 ATOM_FULL(BOX_hdlr, 0);
1667 WRITE_4(0); // pre_defined
1668#define MP4E_HANDLER_TYPE_MDIR 0x6d646972
1669 WRITE_4(MP4E_HANDLER_TYPE_MDIR); // handler_type
1670 WRITE_4(0);
1671 WRITE_4(0);
1672 WRITE_4(0); // reserved[3]
1673 WRITE_4(
1674 0); // name is a null-terminated string in UTF-8 characters which gives a human-readable name for the track type (for debugging and inspection purposes).
1675 END_ATOM;
1676 ATOM(BOX_ilst);
1677 ATOM(BOX_ccmt);
1678 ATOM(BOX_data);
1679 WRITE_4(1); // type
1680 WRITE_4(0); // lang
1681 for (i = 0; i < (int)strlen(mux->text_comment) + 1; i++) {
1682 WRITE_1(mux->text_comment[i]);
1683 }
1684 END_ATOM;
1685 END_ATOM;
1686 END_ATOM;
1687 END_ATOM;
1688 END_ATOM;
1689 }
1690
1691 if (mux->enable_fragmentation) {
1692 track_t* tr = ((track_t*)mux->tracks.data) + 0;
1693 uint32_t movie_duration = get_duration(tr);
1694
1695 ATOM(BOX_mvex);
1696 ATOM_FULL(BOX_mehd, 0);
1697 WRITE_4(movie_duration); // duration
1698 END_ATOM;
1699 for (ntr = 0; ntr < ntracks; ntr++) {
1700 ATOM_FULL(BOX_trex, 0);
1701 WRITE_4(ntr + 1); // track_ID
1702 WRITE_4(1); // default_sample_description_index
1703 WRITE_4(0); // default_sample_duration
1704 WRITE_4(0); // default_sample_size
1705 WRITE_4(0); // default_sample_flags
1706 END_ATOM;
1707 }
1708 END_ATOM;
1709 }
1710 END_ATOM; // moov atom
1711
1712 assert((unsigned)(p - base) <= index_bytes);
1713
1714 err = mux->write_callback(mux->write_pos, base, p - base, mux->token);
1715 mux->write_pos += p - base;
1716 free(base);
1717 return err;
1718}
1719
1720int MP4E_close(MP4E_mux_t* mux) {
1721 int err = MP4E_STATUS_OK;
1722 unsigned ntr, ntracks;
1723 if (!mux)
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);
1736 }
1737 minimp4_vector_reset(&mux->tracks);
1738 free(mux);
1739 return err;
1740}
1741
1742typedef uint32_t bs_item_t;
1743#define BS_BITS 32
1744
1745typedef struct {
1746 // Look-ahead bit cache: MSB aligned, 17 bits guaranteed, zero stuffing
1747 unsigned int cache;
1748
1749 // Bit counter = 16 - (number of bits in wCache)
1750 // cache refilled when cache_free_bits >= 0
1751 int cache_free_bits;
1752
1753 // Current read position
1754 const uint16_t* buf;
1755
1756 // original data buffer
1757 const uint16_t* origin;
1758
1759 // original data buffer length, bytes
1760 unsigned origin_bytes;
1761} bit_reader_t;
1762
1763#define LOAD_SHORT(x) ((uint16_t)(x << 8) | (x >> 8))
1764
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));
1769 return retval;
1770}
1771
1772static void flush_bits(bit_reader_t* bs, int n) {
1773 assert(n >= 0 && n <= 16);
1774 bs->cache <<= n;
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;
1778 bs->buf++;
1779 bs->cache_free_bits -= 16;
1780 }
1781}
1782
1783static unsigned int get_bits(bit_reader_t* bs, int n) {
1784 unsigned int retval = show_bits(bs, n);
1785 flush_bits(bs, n);
1786 return retval;
1787}
1788
1789static void set_pos_bits(bit_reader_t* bs, unsigned pos_bits) {
1790 assert((int)pos_bits >= 0);
1791
1792 bs->buf = bs->origin + pos_bits / 16;
1793 bs->cache = 0;
1794 bs->cache_free_bits = 16;
1795 flush_bits(bs, 0);
1796 flush_bits(bs, pos_bits & 15);
1797}
1798
1799static unsigned get_pos_bits(const bit_reader_t* bs) {
1800 // Current bitbuffer position =
1801 // position of next wobits in the internal buffer
1802 // minus bs, available in bit cache wobits
1803 unsigned pos_bits = (unsigned)(bs->buf - bs->origin) * 16;
1804 pos_bits -= 16 - bs->cache_free_bits;
1805 assert((int)pos_bits >= 0);
1806 return pos_bits;
1807}
1808
1809static int remaining_bits(const bit_reader_t* bs) {
1810 return bs->origin_bytes * 8 - get_pos_bits(bs);
1811}
1812
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);
1817}
1818
1819#define GetBits(n) get_bits(bs, n)
1820
1824static int ue_bits(bit_reader_t* bs) {
1825 int clz;
1826 int val;
1827 for (clz = 0; !get_bits(bs, 1); clz++) {}
1828 //get_bits(bs, clz + 1);
1829 val = (1 << clz) - 1 + (clz ? get_bits(bs, clz) : 0);
1830 return val;
1831}
1832
1833#if MINIMP4_TRANSCODE_SPS_ID
1834
1838typedef struct {
1839 int shift; // bit position in the cache
1840 uint32_t cache; // bit cache
1841 bs_item_t* buf; // current position
1842 bs_item_t* origin; // initial position
1843} bs_t;
1844
1845#define SWAP32(x) \
1846 (uint32_t)((((x) >> 24) & 0xFF) | (((x) >> 8) & 0xFF00) | (((x) << 8) & 0xFF0000) | \
1847 ((x & 0xFF) << 24))
1848
1849static void h264e_bs_put_bits(bs_t* bs, unsigned n, unsigned val) {
1850 assert(!(val >> n));
1851 bs->shift -= n;
1852 assert((unsigned)n <= 32);
1853 if (bs->shift < 0) {
1854 assert(-bs->shift < 32);
1855 bs->cache |= val >> -bs->shift;
1856 *bs->buf++ = SWAP32(bs->cache);
1857 bs->shift = 32 + bs->shift;
1858 bs->cache = 0;
1859 }
1860 bs->cache |= val << bs->shift;
1861}
1862
1863static void h264e_bs_flush(bs_t* bs) {
1864 *bs->buf = SWAP32(bs->cache);
1865}
1866
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);
1871 return pos_bits;
1872}
1873
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);
1878}
1879
1894static void h264e_bs_put_golomb(bs_t* bs, unsigned val) {
1895 int size = 0;
1896 unsigned t = val + 1;
1897 do {
1898 size++;
1899 } while (t >>= 1);
1900
1901 h264e_bs_put_bits(bs, 2 * size - 1, val + 1);
1902}
1903
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;
1908 bs->cache = 0;
1909}
1910
1911static int find_mem_cache(void* cache[], int cache_bytes[], int cache_size, void* mem, int bytes) {
1912 int i;
1913 if (!bytes)
1914 return -1;
1915 for (i = 0; i < cache_size; i++) {
1916 if (cache_bytes[i] == bytes && !memcmp(mem, cache[i], bytes))
1917 return i; // found
1918 }
1919 for (i = 0; i < cache_size; i++) {
1920 if (!cache_bytes[i]) {
1921 cache[i] = malloc(bytes);
1922 if (cache[i]) {
1923 memcpy(cache[i], mem, bytes);
1924 cache_bytes[i] = bytes;
1925 }
1926 return i; // put in
1927 }
1928 }
1929 return -1; // no room
1930}
1931
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) {
1939 if (src[j] == 3) {
1940 if (j == h264_data_bytes - 1) {
1941 // cabac_zero_word: no action
1942 } else if (src[j + 1] <= 3) {
1943 j++;
1944 zero_cnt = 0;
1945 } else {
1946 // TODO: assume end-of-nal
1947 //return 0;
1948 }
1949 } else
1950 return 0;
1951 }
1952 dst[i++] = src[j];
1953 if (src[j])
1954 zero_cnt = 0;
1955 else
1956 zero_cnt++;
1957 }
1958 //while (--j > i) src[j] = 0;
1959 return i;
1960}
1961
1965static int nal_put_esc(uint8_t* d, const uint8_t* s, int n) {
1966 int i, j = 4, cntz = 0;
1967 d[0] = d[1] = d[2] = 0;
1968 d[3] = 1; // start code
1969 for (i = 0; i < n; i++) {
1970 uint8_t byte = *s++;
1971 if (cntz == 2 && byte <= 3) {
1972 d[j++] = 3;
1973 cntz = 0;
1974 }
1975 if (byte)
1976 cntz = 0;
1977 else
1978 cntz++;
1979 d[j++] = byte;
1980 }
1981 return j;
1982}
1983
1984static void copy_bits(bit_reader_t* bs, bs_t* bd) {
1985 unsigned cb, bits;
1986 int bit_count = remaining_bits(bs);
1987 while (bit_count > 7) {
1988 cb = MINIMP4_MIN(bit_count - 7, 8);
1989 bits = GetBits(cb);
1990 h264e_bs_put_bits(bd, cb, bits);
1991 bit_count -= cb;
1992 }
1993
1994 // cut extra zeros after stop-bit
1995 bits = GetBits(bit_count);
1996 for (; bit_count && ~bits & 1; bit_count--) {
1997 bits >>= 1;
1998 }
1999 if (bit_count) {
2000 h264e_bs_put_bits(bd, bit_count, bits);
2001 }
2002}
2003
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++) {
2007 bits = GetBits(8);
2008 h264e_bs_put_bits(bd, 8, bits);
2009 }
2010 sps_id = ue_bits(bs); // max = 31
2011
2012 *old_id = sps_id;
2013 sps_id = new_id;
2014 assert(sps_id <= 31);
2015
2016 h264e_bs_put_golomb(bd, sps_id);
2017 copy_bits(bs, bd);
2018
2019 bytes = h264e_bs_byte_align(bd) / 8;
2020 h264e_bs_flush(bd);
2021 return bytes;
2022}
2023
2024static int
2025patch_pps(h264_sps_id_patcher_t* h, bit_reader_t* bs, bs_t* bd, int new_pps_id, int* old_id) {
2026 int bytes;
2027 unsigned pps_id = ue_bits(bs); // max = 255
2028 unsigned sps_id = ue_bits(bs); // max = 31
2029
2030 *old_id = pps_id;
2031 sps_id = h->map_sps[sps_id];
2032 pps_id = new_pps_id;
2033
2034 assert(sps_id <= 31);
2035 assert(pps_id <= 255);
2036
2037 h264e_bs_put_golomb(bd, pps_id);
2038 h264e_bs_put_golomb(bd, sps_id);
2039 copy_bits(bs, bd);
2040
2041 bytes = h264e_bs_byte_align(bd) / 8;
2042 h264e_bs_flush(bd);
2043 return bytes;
2044}
2045
2046static void patch_slice_header(h264_sps_id_patcher_t* h, bit_reader_t* bs, bs_t* bd) {
2047 unsigned first_mb_in_slice = ue_bits(bs);
2048 unsigned slice_type = ue_bits(bs);
2049 unsigned pps_id = ue_bits(bs);
2050
2051 pps_id = h->map_pps[pps_id];
2052
2053 assert(pps_id <= 255);
2054
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);
2058 copy_bits(bs, bd);
2059}
2060
2061static int transcode_nalu(h264_sps_id_patcher_t* h,
2062 const unsigned char* src,
2063 int nalu_bytes,
2064 unsigned char* dst) {
2065 int old_id;
2066
2067 bit_reader_t bst[1];
2068 bs_t bdt[1];
2069
2070 bit_reader_t bs[1];
2071 bs_t bd[1];
2072 int payload_type = src[0] & 31;
2073
2074 *dst = *src;
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);
2079
2080 switch (payload_type) {
2081 case 7: {
2082 int cb = change_sps_id(bst, bdt, 0, &old_id);
2083 int id = find_mem_cache(h->sps_cache, h->sps_bytes, MINIMP4_MAX_SPS, dst + 1, cb);
2084 if (id == -1)
2085 return 0;
2086 h->map_sps[old_id] = id;
2087 change_sps_id(bs, bd, id, &old_id);
2088 } break;
2089 case 8: {
2090 int cb = patch_pps(h, bst, bdt, 0, &old_id);
2091 int id = find_mem_cache(h->pps_cache, h->pps_bytes, MINIMP4_MAX_PPS, dst + 1, cb);
2092 if (id == -1)
2093 return 0;
2094 h->map_pps[old_id] = id;
2095 patch_pps(h, bs, bd, id, &old_id);
2096 } break;
2097 case 1:
2098 case 2:
2099 case 5:
2100 patch_slice_header(h, bs, bd);
2101 break;
2102 default:
2103 memcpy(dst, (void*)src, nalu_bytes);
2104 return nalu_bytes;
2105 }
2106
2107 nalu_bytes = 1 + h264e_bs_byte_align(bd) / 8;
2108 h264e_bs_flush(bd);
2109
2110 return nalu_bytes;
2111}
2112
2113#endif
2114
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;
2125 const uint8_t* p = h264_data;
2126 do {
2127 int zero_cnt = 1;
2128 const uint8_t* found = (uint8_t*)memchr(p, 0, eof - p);
2129 p = found ? found : eof;
2130 while (p + zero_cnt < eof && !p[zero_cnt])
2131 zero_cnt++;
2132 if (zero_cnt >= 2 && p[zero_cnt] == 1) {
2133 *zcount = zero_cnt + 1;
2134 return p + zero_cnt + 1;
2135 }
2136 p += zero_cnt;
2137 } while (p < eof);
2138 *zcount = 0;
2139 return eof;
2140}
2141
2145static const uint8_t*
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;
2148 int zcount;
2149 const uint8_t* start = find_start_code(h264_data, h264_data_bytes, &zcount);
2150 const uint8_t* stop = start;
2151 if (start) {
2152 stop = find_start_code(start, (int)(eof - start), &zcount);
2153 while (stop > start && !stop[-1]) {
2154 stop--;
2155 }
2156 }
2157
2158 *pnal_unit_bytes = (int)(stop - start - zcount);
2159 return start;
2160}
2161
2162int mp4_h26x_write_init(mp4_h26x_writer_t* h, MP4E_mux_t* mux, int width, int height, int is_hevc) {
2163 MP4E_track_t tr;
2165 tr.language[0] = 'u';
2166 tr.language[1] = 'n';
2167 tr.language[2] = 'd';
2168 tr.language[3] = 0;
2170 tr.time_scale = 90000;
2171 tr.default_duration = 0;
2172 tr.u.v.width = width;
2173 tr.u.v.height = height;
2174 h->mux_track_id = MP4E_add_track(mux, &tr);
2175 h->mux = mux;
2176
2177 h->is_hevc = is_hevc;
2178 h->need_vps = is_hevc;
2179 h->need_sps = 1;
2180 h->need_pps = 1;
2181 h->need_idr = 1;
2182#if MINIMP4_TRANSCODE_SPS_ID
2183 memset(&h->sps_patcher, 0, sizeof(h264_sps_id_patcher_t));
2184#endif
2185 return MP4E_STATUS_OK;
2186}
2187
2189#if MINIMP4_TRANSCODE_SPS_ID
2191 int i;
2192 for (i = 0; i < MINIMP4_MAX_SPS; i++) {
2193 if (p->sps_cache[i])
2194 free(p->sps_cache[i]);
2195 }
2196 for (i = 0; i < MINIMP4_MAX_PPS; i++) {
2197 if (p->pps_cache[i])
2198 free(p->pps_cache[i]);
2199 }
2200#endif
2201 memset(h, 0, sizeof(*h));
2202}
2203
2204static int mp4_h265_write_nal(mp4_h26x_writer_t* h,
2205 const unsigned char* nal,
2206 int sizeof_nal,
2207 unsigned timeStamp90kHz_next) {
2208 int payload_type = (nal[0] >> 1) & 0x3f;
2209 int is_intra = payload_type >= HEVC_NAL_BLA_W_LP && payload_type <= HEVC_NAL_CRA_NUT;
2210 int err = MP4E_STATUS_OK;
2211 //printf("payload_type=%d, intra=%d\n", payload_type, is_intra);
2212
2213 if (is_intra && !h->need_sps && !h->need_pps && !h->need_vps)
2214 h->need_idr = 0;
2215 switch (payload_type) {
2216 case HEVC_NAL_VPS:
2217 MP4E_set_vps(h->mux, h->mux_track_id, nal, sizeof_nal);
2218 h->need_vps = 0;
2219 break;
2220 case HEVC_NAL_SPS:
2221 MP4E_set_sps(h->mux, h->mux_track_id, nal, sizeof_nal);
2222 h->need_sps = 0;
2223 break;
2224 case HEVC_NAL_PPS:
2225 MP4E_set_pps(h->mux, h->mux_track_id, nal, sizeof_nal);
2226 h->need_pps = 0;
2227 break;
2228 default:
2229 if (h->need_vps || h->need_sps || h->need_pps || h->need_idr)
2231 {
2232 unsigned char* tmp = (unsigned char*)malloc(4 + sizeof_nal);
2233 if (!tmp)
2234 return MP4E_STATUS_NO_MEMORY;
2235 int sample_kind = MP4E_SAMPLE_DEFAULT;
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);
2241 if (is_intra)
2242 sample_kind = MP4E_SAMPLE_RANDOM_ACCESS;
2243 err = MP4E_put_sample(
2244 h->mux, h->mux_track_id, tmp, 4 + sizeof_nal, timeStamp90kHz_next, sample_kind);
2245 free(tmp);
2246 }
2247 break;
2248 }
2249 return err;
2250}
2251
2253 const unsigned char* nal,
2254 int length,
2255 unsigned timeStamp90kHz_next) {
2256 const unsigned char* eof = nal + length;
2257 int payload_type, sizeof_nal, err = MP4E_STATUS_OK;
2258 for (;; nal++) {
2259#if MINIMP4_TRANSCODE_SPS_ID
2260 unsigned char *nal1, *nal2;
2261#endif
2262 nal = find_nal_unit(nal, (int)(eof - nal), &sizeof_nal);
2263 if (!sizeof_nal)
2264 break;
2265 if (h->is_hevc) {
2266 ERR(mp4_h265_write_nal(h, nal, sizeof_nal, timeStamp90kHz_next));
2267 continue;
2268 }
2269 payload_type = nal[0] & 31;
2270 if (9 == payload_type)
2271 continue; // access unit delimiter, nothing to be done
2272#if MINIMP4_TRANSCODE_SPS_ID
2273 // Transcode SPS, PPS and slice headers, reassigning ID's for SPS and PPS:
2274 // - assign unique ID's to different SPS and PPS
2275 // - assign same ID's to equal (except ID) SPS and PPS
2276 // - save all different SPS and PPS
2277 nal1 = (unsigned char*)malloc(sizeof_nal * 17 / 16 + 32);
2278 if (!nal1)
2279 return MP4E_STATUS_NO_MEMORY;
2280 nal2 = (unsigned char*)malloc(sizeof_nal * 17 / 16 + 32);
2281 if (!nal2) {
2282 free(nal1);
2283 return MP4E_STATUS_NO_MEMORY;
2284 }
2285 sizeof_nal = remove_nal_escapes(nal2, nal, sizeof_nal);
2286 if (!sizeof_nal) {
2287 exit_with_free:
2288 free(nal1);
2289 free(nal2);
2291 }
2292
2293 sizeof_nal = transcode_nalu(&h->sps_patcher, nal2, sizeof_nal, nal1);
2294 sizeof_nal = nal_put_esc(nal2, nal1, sizeof_nal);
2295
2296 switch (payload_type) {
2297 case 7:
2298 MP4E_set_sps(h->mux, h->mux_track_id, nal2 + 4, sizeof_nal - 4);
2299 h->need_sps = 0;
2300 break;
2301 case 8:
2302 if (h->need_sps)
2303 goto exit_with_free;
2304 MP4E_set_pps(h->mux, h->mux_track_id, nal2 + 4, sizeof_nal - 4);
2305 h->need_pps = 0;
2306 break;
2307 case 5:
2308 if (h->need_sps)
2309 goto exit_with_free;
2310 h->need_idr = 0;
2311 // flow through
2312 default:
2313 if (h->need_sps)
2314 goto exit_with_free;
2315 if (!h->need_pps && !h->need_idr) {
2316 bit_reader_t bs[1];
2317 init_bits(bs, nal + 1, sizeof_nal - 4 - 1);
2318 unsigned first_mb_in_slice = ue_bits(bs);
2319 //unsigned slice_type = ue_bits(bs);
2320 int sample_kind = MP4E_SAMPLE_DEFAULT;
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)
2326 sample_kind = MP4E_SAMPLE_CONTINUATION;
2327 else if (payload_type == 5)
2328 sample_kind = MP4E_SAMPLE_RANDOM_ACCESS;
2329 err = MP4E_put_sample(
2330 h->mux, h->mux_track_id, nal2, sizeof_nal, timeStamp90kHz_next, sample_kind);
2331 }
2332 break;
2333 }
2334 free(nal1);
2335 free(nal2);
2336#else
2337 // No SPS/PPS transcoding
2338 // This branch assumes that encoder use correct SPS/PPS ID's
2339 switch (payload_type) {
2340 case 7:
2341 MP4E_set_sps(h->mux, h->mux_track_id, nal, sizeof_nal);
2342 h->need_sps = 0;
2343 break;
2344 case 8:
2345 MP4E_set_pps(h->mux, h->mux_track_id, nal, sizeof_nal);
2346 h->need_pps = 0;
2347 break;
2348 case 5:
2349 if (h->need_sps)
2351 h->need_idr = 0;
2352 // flow through
2353 default:
2354 if (h->need_sps)
2356 if (!h->need_pps && !h->need_idr) {
2357 bit_reader_t bs[1];
2358 unsigned char* tmp = (unsigned char*)malloc(4 + sizeof_nal);
2359 if (!tmp)
2360 return MP4E_STATUS_NO_MEMORY;
2361 init_bits(bs, nal + 1, sizeof_nal - 1);
2362 unsigned first_mb_in_slice = ue_bits(bs);
2363 int sample_kind = MP4E_SAMPLE_DEFAULT;
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)
2370 sample_kind = MP4E_SAMPLE_CONTINUATION;
2371 else if (payload_type == 5)
2372 sample_kind = MP4E_SAMPLE_RANDOM_ACCESS;
2373 err = MP4E_put_sample(
2374 h->mux, h->mux_track_id, tmp, 4 + sizeof_nal, timeStamp90kHz_next, sample_kind);
2375 free(tmp);
2376 }
2377 break;
2378 }
2379#endif
2380 if (err)
2381 break;
2382 }
2383 return err;
2384}
2385
2386#if MP4D_TRACE_SUPPORTED
2387#define TRACE(x) printf x
2388#else
2389#define TRACE(x) printf x
2390#endif
2391
2392#define NELEM(x) (sizeof(x) / sizeof((x)[0]))
2393
2394static int minimp4_fgets(MP4D_demux_t* mp4) {
2395 uint8_t c;
2396 if (mp4->read_callback(mp4->read_pos, &c, 1, mp4->token))
2397 return -1;
2398 mp4->read_pos++;
2399 return c;
2400}
2401
2406static unsigned minimp4_read(MP4D_demux_t* mp4, int nb, int* eof_flag) {
2407 uint32_t v = 0;
2408 int last_byte;
2409 switch (nb) {
2410 case 4:
2411 v = (v << 8) | minimp4_fgets(mp4);
2412 case 3:
2413 v = (v << 8) | minimp4_fgets(mp4);
2414 case 2:
2415 v = (v << 8) | minimp4_fgets(mp4);
2416 default:
2417 case 1:
2418 v = (v << 8) | (last_byte = minimp4_fgets(mp4));
2419 }
2420 if (last_byte < 0) {
2421 *eof_flag = 1;
2422 }
2423 return v;
2424}
2425
2430static uint32_t
2431read_payload(MP4D_demux_t* mp4, unsigned nb, boxsize_t* payload_bytes, int* eof_flag) {
2432 if (*payload_bytes < nb) {
2433 *eof_flag = 1;
2434 nb = (int)*payload_bytes;
2435 }
2436 *payload_bytes -= nb;
2437
2438 return minimp4_read(mp4, nb, eof_flag);
2439}
2440
2445static void my_fseek(MP4D_demux_t* mp4, boxsize_t pos, int* eof_flag) {
2446 mp4->read_pos += pos;
2447 if (mp4->read_pos >= mp4->read_size)
2448 *eof_flag = 1;
2449}
2450
2451#define READ(n) read_payload(mp4, n, &payload_bytes, &eof_flag)
2452#define SKIP(n) \
2453 { \
2454 boxsize_t t = MINIMP4_MIN(payload_bytes, n); \
2455 my_fseek(mp4, t, &eof_flag); \
2456 payload_bytes -= t; \
2457 }
2458#define MALLOC(t, p, size) \
2459 p = (t)malloc(size); \
2460 if (!(p)) { \
2461 ERROR("out of memory"); \
2462 }
2463
2464/*
2465* On error: release resources.
2466*/
2467#define RETURN_ERROR(mess) \
2468 { \
2469 TRACE(("\nMP4 ERROR: " mess)); \
2470 MP4D_close(mp4); \
2471 return 0; \
2472 }
2473
2474/*
2475* Any errors, occurred on top-level hierarchy is passed to exit check: 'if (!mp4->track_count) ... '
2476*/
2477#define ERROR(mess) \
2478 if (!depth) \
2479 break; \
2480 else \
2481 RETURN_ERROR(mess);
2482
2483typedef enum { BOX_ATOM, BOX_OD } boxtype_t;
2484
2485int MP4D_open(MP4D_demux_t* mp4,
2486 int (*read_callback)(int64_t offset, void* buffer, size_t size, void* token),
2487 void* token,
2488 int64_t file_size) {
2489 // box stack size
2490 int depth = 0;
2491
2492 struct {
2493 // remaining bytes for box in the stack
2494 boxsize_t bytes;
2495
2496 // kind of box children's: OD chunks handled in the same manner as name chunks
2497 boxtype_t format;
2498
2499 } stack[MAX_CHUNKS_DEPTH];
2500
2501#if MP4D_TRACE_SUPPORTED
2502 // path of current element: List0/List1/... etc
2503 uint32_t box_path[MAX_CHUNKS_DEPTH];
2504#endif
2505
2506 int eof_flag = 0;
2507 unsigned i;
2508 MP4D_track_t* tr = NULL;
2509
2510 if (!mp4 || !read_callback) {
2511 TRACE(("\nERROR: invlaid arguments!"));
2512 return 0;
2513 }
2514
2515 memset(mp4, 0, sizeof(MP4D_demux_t));
2517 mp4->token = token;
2518 mp4->read_size = file_size;
2519
2520 stack[0].format = BOX_ATOM; // start with atom box
2521 stack[0].bytes = 0; // never accessed
2522
2523 do {
2524 // List of boxes, derived from 'FullBox'
2525 // ~~~~~~~~~~~~~~~~~~~~~
2526 // need read version field and check version for these boxes
2527 static const struct {
2528 uint32_t name;
2529 unsigned max_version;
2530 unsigned use_track_flag;
2531 } g_fullbox[] = {
2532#if MP4D_INFO_SUPPORTED
2533 {BOX_mdhd, 1, 1},
2534 {BOX_mvhd, 1, 0},
2535 {BOX_hdlr, 0, 0},
2536 {BOX_meta,
2537 0,
2538 0}, // Android can produce meta box without 'FullBox' field, comment this line to simulate the bug
2539#endif
2540#if MP4D_TRACE_TIMESTAMPS
2541 {BOX_stts, 0, 0},
2542 {BOX_ctts, 0, 0},
2543#endif
2544 {BOX_stz2, 0, 1},
2545 {BOX_stsz, 0, 1},
2546 {BOX_stsc, 0, 1},
2547 {BOX_stco, 0, 1},
2548 {BOX_co64, 0, 1},
2549 {BOX_stsd, 0, 0},
2550 {BOX_esds, 0, 1}
2551 // esds does not use track, but switches to OD mode. Check here, to avoid OD check
2552 };
2553
2554 // List of boxes, which contains other boxes ('envelopes')
2555 // Parser will descend down for boxes in this list, otherwise parsing will proceed to
2556 // the next sibling box
2557 // OD boxes handled in the same way as atom boxes...
2558 static const struct {
2559 uint32_t name;
2560 boxtype_t type;
2561 } g_envelope_box[] = {
2562 {BOX_esds,
2563 BOX_OD}, // TODO: BOX_esds can be used for both audio and video, but this code supports audio only!
2564 {OD_ESD, BOX_OD},
2565 {OD_DCD, BOX_OD},
2566 {OD_DSI, BOX_OD},
2567 {BOX_trak, BOX_ATOM},
2568 {BOX_moov, BOX_ATOM},
2569 //{BOX_moof, 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},
2581 //{BOX_avc2, BOX_ATOM},
2582 //{BOX_svc1, BOX_ATOM},
2583#endif
2584#if MP4D_HEVC_SUPPORTED
2585 {BOX_hvc1, BOX_ATOM},
2586#endif
2587 {BOX_udta, BOX_ATOM},
2588 {BOX_meta, BOX_ATOM},
2589 {BOX_ilst, BOX_ATOM}};
2590
2591 uint32_t FullAtomVersionAndFlags = 0;
2592 boxsize_t payload_bytes;
2593 boxsize_t box_bytes;
2594 uint32_t box_name;
2595#if MP4D_INFO_SUPPORTED
2596 unsigned char** ptag = NULL;
2597#endif
2598 int read_bytes = 0;
2599
2600 // Read header box type and it's length
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:
2605#endif
2606 if (eof_flag)
2607 break; // normal exit
2608
2609 if (box_bytes >= 2 && box_bytes < 8) {
2610 ERROR("invalid box size (broken file?)");
2611 }
2612
2613 box_name = minimp4_read(mp4, 4, &eof_flag);
2614 read_bytes = 8;
2615
2616 // Decode box size
2617 if (box_bytes == 0 || // standard indication of 'till eof' size
2618 box_bytes ==
2619 (boxsize_t)0xFFFFFFFFU // some files uses non-standard 'till eof' signaling
2620 ) {
2621 box_bytes = ~(boxsize_t)0;
2622 }
2623
2624 payload_bytes = box_bytes - 8;
2625
2626 if (box_bytes == 1) // 64-bit sizes
2627 {
2628 TRACE(("\n64-bit chunk encountered"));
2629
2630 box_bytes = minimp4_read(mp4, 4, &eof_flag);
2631#if MP4D_64BIT_SUPPORTED
2632 box_bytes <<= 32;
2633 box_bytes |= minimp4_read(mp4, 4, &eof_flag);
2634#else
2635 if (box_bytes) {
2636 ERROR("UNSUPPORTED FEATURE: MP4BoxHeader(): 64-bit boxes not supported!");
2637 }
2638 box_bytes = minimp4_read(mp4, 4, &eof_flag);
2639#endif
2640 if (box_bytes < 16) {
2641 ERROR("invalid box size (broken file?)");
2642 }
2643 payload_bytes = box_bytes - 16;
2644 }
2645
2646 // Read and check box version for some boxes
2647 for (i = 0; i < NELEM(g_fullbox); i++) {
2648 if (box_name == g_fullbox[i].name) {
2649 FullAtomVersionAndFlags = READ(4);
2650 read_bytes += 4;
2651
2652#if FIX_BAD_ANDROID_META_BOX
2653 // Fix invalid BOX_meta, found in some Android-produced MP4
2654 // This branch is optional: bad box would be skipped
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!");
2660 }
2661 stack[depth].bytes -= box_bytes;
2662 ;
2663 depth++;
2664 stack[depth].bytes = payload_bytes + 4; // +4 need for missing header
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;
2669 }
2670 }
2671#endif // FIX_BAD_ANDROID_META_BOX
2672
2673 if ((FullAtomVersionAndFlags >> 24) > g_fullbox[i].max_version) {
2674 ERROR("unsupported box version!");
2675 }
2676 if (g_fullbox[i].use_track_flag && !tr) {
2677 ERROR("broken file structure!");
2678 }
2679 }
2680 }
2681 } else // stack[depth].format == BOX_OD
2682 {
2683 int val;
2684 box_name = OD_BASE + minimp4_read(mp4, 1, &eof_flag); // 1-byte box type
2685 read_bytes += 1;
2686 if (eof_flag)
2687 break;
2688
2689 payload_bytes = 0;
2690 box_bytes = 1;
2691 do {
2692 val = minimp4_read(mp4, 1, &eof_flag);
2693 read_bytes += 1;
2694 if (eof_flag) {
2695 ERROR("premature EOF!");
2696 }
2697 payload_bytes = (payload_bytes << 7) | (val & 0x7F);
2698 box_bytes++;
2699 } while (val & 0x80);
2700 box_bytes += payload_bytes;
2701 }
2702
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",
2707 depth,
2708 (int)box_bytes,
2709 depth * 4,
2710 (char*)box_path,
2711 (int)stack[depth].bytes));
2712#endif
2713
2714 // Check that box size <= parent size
2715 if (depth) {
2716 // Skip box with bad size
2717 assert(box_bytes > 0);
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,
2723 box_name & 255));
2724 box_bytes = stack[depth].bytes;
2725 box_name = 0;
2726 payload_bytes = box_bytes - read_bytes;
2727 }
2728 stack[depth].bytes -= box_bytes;
2729 }
2730
2731 // Read box header
2732 switch (box_name) {
2733 case BOX_stz2: //ISO/IEC 14496-1 Page 38. Section 8.17.2 - Sample Size Box.
2734 case BOX_stsz: {
2735 int size = 0;
2736 uint32_t sample_size = READ(4);
2737 tr->sample_count = READ(4);
2738 MALLOC(unsigned int*, tr->entry_size, tr->sample_count * 4);
2739 for (i = 0; i < tr->sample_count; i++) {
2740 if (box_name == BOX_stsz) {
2741 tr->entry_size[i] = (sample_size ? sample_size : READ(4));
2742 } else {
2743 switch (sample_size & 0xFF) {
2744 case 16:
2745 tr->entry_size[i] = READ(2);
2746 break;
2747 case 8:
2748 tr->entry_size[i] = READ(1);
2749 break;
2750 case 4:
2751 if (i & 1) {
2752 tr->entry_size[i] = size & 15;
2753 } else {
2754 size = READ(1);
2755 tr->entry_size[i] = (size >> 4);
2756 }
2757 break;
2758 }
2759 }
2760 }
2761 } break;
2762
2763 case BOX_stsc: //ISO/IEC 14496-12 Page 38. Section 8.18 - Sample To Chunk Box.
2764 tr->sample_to_chunk_count = READ(4);
2765 MALLOC(MP4D_sample_to_chunk_t*,
2766 tr->sample_to_chunk,
2767 tr->sample_to_chunk_count * sizeof(tr->sample_to_chunk[0]));
2768 for (i = 0; i < tr->sample_to_chunk_count; i++) {
2769 tr->sample_to_chunk[i].first_chunk = READ(4);
2770 tr->sample_to_chunk[i].samples_per_chunk = READ(4);
2771 SKIP(4); // sample_description_index
2772 }
2773 break;
2774#if MP4D_TRACE_TIMESTAMPS || MP4D_TIMESTAMPS_SUPPORTED
2775 case BOX_stts: {
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);
2781#endif
2782
2783 for (i = 0; i < count; i++) {
2784 unsigned sc = READ(4);
2785 int d = 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) {
2789 ts_count = k + sc;
2790 tr->timestamp =
2791 (unsigned int*)realloc(tr->timestamp, ts_count * sizeof(unsigned));
2792 tr->duration =
2793 (unsigned int*)realloc(tr->duration, ts_count * sizeof(unsigned));
2794 }
2795 for (j = 0; j < sc; j++) {
2796 tr->duration[k] = d;
2797 tr->timestamp[k++] = ts;
2798 ts += d;
2799 }
2800#endif
2801 }
2802 } break;
2803 case BOX_ctts: {
2804 unsigned count = READ(4);
2805 for (i = 0; i < count; i++) {
2806 int sc = READ(4);
2807 int d = READ(4);
2808 (void)sc;
2809 (void)d;
2810 TRACE(("sample %8d count %8d decoding to composition offset %8d\n", i, sc, d));
2811 }
2812 } break;
2813#endif
2814 case BOX_stco: //ISO/IEC 14496-12 Page 39. Section 8.19 - Chunk Offset Box.
2815 case BOX_co64:
2816 tr->chunk_count = READ(4);
2817 MALLOC(MP4D_file_offset_t*,
2818 tr->chunk_offset,
2819 tr->chunk_count * sizeof(MP4D_file_offset_t));
2820 for (i = 0; i < tr->chunk_count; i++) {
2821 tr->chunk_offset[i] = READ(4);
2822 if (box_name == BOX_co64) {
2823#if !MP4D_64BIT_SUPPORTED
2824 if (tr->chunk_offset[i]) {
2825 ERROR("UNSUPPORTED FEATURE: 64-bit chunk_offset not supported!");
2826 }
2827#endif
2828 tr->chunk_offset[i] <<= 32;
2829 tr->chunk_offset[i] |= READ(4);
2830 }
2831 }
2832 break;
2833
2834#if MP4D_INFO_SUPPORTED
2835 case BOX_mvhd:
2836 SKIP(((FullAtomVersionAndFlags >> 24) == 1) ? 8 + 8 : 4 + 4);
2837 mp4->timescale = READ(4);
2838 mp4->duration_hi = ((FullAtomVersionAndFlags >> 24) == 1) ? READ(4) : 0;
2839 mp4->duration_lo = READ(4);
2840 SKIP(4 + 2 + 2 + 4 * 2 + 4 * 9 + 4 * 6 + 4);
2841 break;
2842
2843 case BOX_mdhd:
2844 SKIP(((FullAtomVersionAndFlags >> 24) == 1) ? 8 + 8 : 4 + 4);
2845 tr->timescale = READ(4);
2846 tr->duration_hi = ((FullAtomVersionAndFlags >> 24) == 1) ? READ(4) : 0;
2847 tr->duration_lo = READ(4);
2848
2849 {
2850 int ISO_639_2_T = READ(2);
2851 tr->language[2] = (ISO_639_2_T & 31) + 0x60;
2852 ISO_639_2_T >>= 5;
2853 tr->language[1] = (ISO_639_2_T & 31) + 0x60;
2854 ISO_639_2_T >>= 5;
2855 tr->language[0] = (ISO_639_2_T & 31) + 0x60;
2856 }
2857 // the rest of this box is skipped by default ...
2858 break;
2859
2860 case BOX_hdlr:
2861 if (tr) // When this box is within 'meta' box, the track may not be avaialable
2862 {
2863 SKIP(4); // pre_defined
2864 tr->handler_type = READ(4);
2865 }
2866 // typically hdlr box does not contain any useful info.
2867 // the rest of this box is skipped by default ...
2868 break;
2869
2870 case BOX_btrt:
2871 if (!tr) {
2872 ERROR("broken file structure!");
2873 }
2874
2875 SKIP(4 + 4);
2876 tr->avg_bitrate_bps = READ(4);
2877 break;
2878
2879 // Set pointer to tag to be read...
2880 case BOX_calb:
2881 ptag = &mp4->tag.album;
2882 break;
2883 case BOX_cART:
2884 ptag = &mp4->tag.artist;
2885 break;
2886 case BOX_cnam:
2887 ptag = &mp4->tag.title;
2888 break;
2889 case BOX_cday:
2890 ptag = &mp4->tag.year;
2891 break;
2892 case BOX_ccmt:
2893 ptag = &mp4->tag.comment;
2894 break;
2895 case BOX_cgen:
2896 ptag = &mp4->tag.genre;
2897 break;
2898
2899#endif
2900
2901 case BOX_stsd:
2902 SKIP(4); // entry_count, BOX_mp4a & BOX_mp4v boxes follows immediately
2903 break;
2904
2905 case BOX_mp4s: // private stream
2906 if (!tr) {
2907 ERROR("broken file structure!");
2908 }
2909 SKIP(6 * 1 + 2 /*Base SampleEntry*/);
2910 break;
2911
2912 case BOX_mp4a:
2913 if (!tr) {
2914 ERROR("broken file structure!");
2915 }
2916#if MP4D_INFO_SUPPORTED
2917 SKIP(6 * 1 + 2 /*Base SampleEntry*/ + 4 * 2);
2918 tr->SampleDescription.audio.channelcount = READ(2);
2919 SKIP(2 /*samplesize*/ + 2 + 2);
2920 tr->SampleDescription.audio.samplerate_hz = READ(4) >> 16;
2921#else
2922 SKIP(28);
2923#endif
2924 break;
2925
2926#if MP4D_AVC_SUPPORTED
2927 case BOX_avc1: // AVCSampleEntry extends VisualSampleEntry
2928 // case BOX_avc2: - no test
2929 // case BOX_svc1: - no test
2930 case BOX_mp4v:
2931 if (!tr) {
2932 ERROR("broken file structure!");
2933 }
2934#if MP4D_INFO_SUPPORTED
2935 SKIP(6 * 1 + 2 /*Base SampleEntry*/ + 2 + 2 + 4 * 3);
2936 tr->SampleDescription.video.width = READ(2);
2937 tr->SampleDescription.video.height = READ(2);
2938 // frame_count is always 1
2939 // compressorname is rarely set..
2940 SKIP(4 + 4 + 4 + 2 /*frame_count*/ + 32 /*compressorname*/ + 2 + 2);
2941#else
2942 SKIP(78);
2943#endif
2944 // ^^^ end of VisualSampleEntry
2945 // now follows for BOX_avc1:
2946 // BOX_avcC
2947 // BOX_btrt (optional)
2948 // BOX_m4ds (optional)
2949 // for BOX_mp4v:
2950 // BOX_esds
2951 break;
2952
2953 case BOX_avcC: // AVCDecoderConfigurationRecord()
2954 // hack: AAC-specific DSI field reused (for it have same purpoose as sps/pps)
2955 // TODO: check this hack if BOX_esds co-exist with BOX_avcC
2957 tr->dsi = (unsigned char*)malloc((size_t)box_bytes);
2958 tr->dsi_bytes = (unsigned)box_bytes;
2959 {
2960 int spspps;
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);
2966 //bit(6) reserved =
2967 unsigned int lengthSizeMinusOne = READ(1) & 3;
2968
2969 (void)configurationVersion;
2970 (void)AVCProfileIndication;
2971 (void)profile_compatibility;
2972 (void)AVCLevelIndication;
2973 (void)lengthSizeMinusOne;
2974
2975 for (spspps = 0; spspps < 2; spspps++) {
2976 unsigned int numOfSequenceParameterSets = READ(1);
2977 if (!spspps) {
2978 numOfSequenceParameterSets &= 31; // clears 3 msb for SPS
2979 }
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++) {
2986 *p++ = READ(1);
2987 }
2988 }
2989 }
2990 }
2991 break;
2992#endif // MP4D_AVC_SUPPORTED
2993
2994 case OD_ESD: {
2995 unsigned flags = READ(3); // ES_ID(2) + flags(1)
2996
2997 if (flags & 0x80) // steamdependflag
2998 {
2999 SKIP(2); // dependsOnESID
3000 }
3001 if (flags & 0x40) // urlflag
3002 {
3003 unsigned bytecount = READ(1);
3004 SKIP(bytecount); // skip URL
3005 }
3006 if (flags & 0x20) // ocrflag (was reserved in MPEG-4 v.1)
3007 {
3008 SKIP(2); // OCRESID
3009 }
3010 break;
3011 }
3012
3013 case OD_DCD: //ISO/IEC 14496-1 Page 28. Section 8.6.5 - DecoderConfigDescriptor.
3014 assert(tr); // ensured by g_fullbox[] check
3015 tr->object_type_indication = READ(1);
3016#if MP4D_INFO_SUPPORTED
3017 tr->stream_type = READ(1) >> 2;
3018 SKIP(3 /*bufferSizeDB*/ + 4 /*maxBitrate*/);
3019 tr->avg_bitrate_bps = READ(4);
3020#else
3021 SKIP(1 + 3 + 4 + 4);
3022#endif
3023 break;
3024
3025 case OD_DSI: //ISO/IEC 14496-1 Page 28. Section 8.6.5 - DecoderConfigDescriptor.
3026 assert(tr); // ensured by g_fullbox[] check
3027 if (!tr->dsi && payload_bytes) {
3028 MALLOC(unsigned char*, tr->dsi, (int)payload_bytes);
3029 for (i = 0; i < payload_bytes; i++) {
3030 tr->dsi[i] =
3031 minimp4_read(mp4, 1, &eof_flag); // These bytes available due to check above
3032 }
3033 tr->dsi_bytes = i;
3034 payload_bytes -= i;
3035 break;
3036 }
3037
3038 default:
3039 TRACE(("[%c%c%c%c] %d\n",
3040 box_name >> 24,
3041 box_name >> 16,
3042 box_name >> 8,
3043 box_name,
3044 (int)payload_bytes));
3045 }
3046
3047#if MP4D_INFO_SUPPORTED
3048 // Read tag is tag pointer is set
3049 if (ptag && !*ptag && payload_bytes > 16) {
3050#if 0
3051 uint32_t size = READ(4);
3052 uint32_t data = READ(4);
3053 uint32_t class = READ(4);
3054 uint32_t x1 = READ(4);
3055 TRACE(("%2d %2d %2d ", size, class, x1));
3056#else
3057 SKIP(4 + 4 + 4 + 4);
3058#endif
3059 MALLOC(unsigned char*, *ptag, (unsigned)payload_bytes + 1);
3060 for (i = 0; payload_bytes != 0; i++) {
3061 (*ptag)[i] = READ(1);
3062 }
3063 (*ptag)[i] = 0; // zero-terminated string
3064 }
3065#endif
3066
3067 if (box_name == BOX_trak) {
3068 // New track found: allocate memory using realloc()
3069 // Typically there are 1 audio track for AAC audio file,
3070 // 4 tracks for movie file,
3071 // 3-5 tracks for scalable audio (CELP+AAC)
3072 // and up to 50 tracks for BSAC scalable audio
3073 void* mem = realloc(mp4->track, (mp4->track_count + 1) * sizeof(MP4D_track_t));
3074 if (!mem) {
3075 // if realloc fails, it does not deallocate old pointer!
3076 ERROR("out of memory");
3077 }
3078 mp4->track = (MP4D_track_t*)mem;
3079 tr = mp4->track + mp4->track_count++;
3080 memset(tr, 0, sizeof(MP4D_track_t));
3081 } else if (box_name == BOX_meta) {
3082 tr = NULL; // Avoid update of 'hdlr' box, which may contains in the 'meta' box
3083 }
3084
3085 // If this box is envelope, save it's size in box stack
3086 for (i = 0; i < NELEM(g_envelope_box); i++) {
3087 if (box_name == g_envelope_box[i].name) {
3088 if (++depth >= MAX_CHUNKS_DEPTH) {
3089 ERROR("too deep atoms nesting!");
3090 }
3091 stack[depth].bytes = payload_bytes;
3092 stack[depth].format = g_envelope_box[i].type;
3093 break;
3094 }
3095 }
3096
3097 // if box is not envelope, just skip it
3098 if (i == NELEM(g_envelope_box)) {
3099 if (payload_bytes > file_size) {
3100 eof_flag = 1;
3101 } else {
3102 SKIP(payload_bytes);
3103 }
3104 }
3105
3106 // remove empty boxes from stack
3107 // don't touch box with index 0 (which indicates whole file)
3108 while (depth > 0 && !stack[depth].bytes) {
3109 depth--;
3110 }
3111
3112 } while (!eof_flag);
3113
3114 if (!mp4->track_count) {
3115 RETURN_ERROR("no tracks found");
3116 }
3117 return 1;
3118}
3119
3124static int sample_to_chunk(MP4D_track_t* tr, unsigned nsample, unsigned* nfirst_sample_in_chunk) {
3125 unsigned chunk_group = 0, nc;
3126 unsigned sum = 0;
3127 *nfirst_sample_in_chunk = 0;
3128 if (tr->chunk_count <= 1) {
3129 return 0;
3130 }
3131 for (nc = 0; nc < tr->chunk_count; nc++) {
3132 if (chunk_group + 1 < tr->sample_to_chunk_count // stuck at last entry till EOF
3133 && nc + 1 == // Chunks counted starting with '1'
3134 tr->sample_to_chunk[chunk_group + 1].first_chunk) // next group?
3135 {
3136 chunk_group++;
3137 }
3138
3139 sum += tr->sample_to_chunk[chunk_group].samples_per_chunk;
3140 if (nsample < sum)
3141 return nc;
3142
3143 // TODO: this can be calculated once per file
3144 *nfirst_sample_in_chunk = sum;
3145 }
3146 return -1;
3147}
3148
3149// Exported API function
3151 unsigned ntrack,
3152 unsigned nsample,
3153 unsigned* frame_bytes,
3154 unsigned* timestamp,
3155 unsigned* duration) {
3156 MP4D_track_t* tr = mp4->track + ntrack;
3157 unsigned ns;
3158 int nchunk = sample_to_chunk(tr, nsample, &ns);
3159 MP4D_file_offset_t offset;
3160
3161 if (nchunk < 0) {
3162 *frame_bytes = 0;
3163 return 0;
3164 }
3165
3166 offset = tr->chunk_offset[nchunk];
3167 for (; ns < nsample; ns++) {
3168 offset += tr->entry_size[ns];
3169 }
3170
3171 *frame_bytes = tr->entry_size[ns];
3172
3173 if (timestamp) {
3174#if MP4D_TIMESTAMPS_SUPPORTED
3175 *timestamp = tr->timestamp[ns];
3176#else
3177 *timestamp = 0;
3178#endif
3179 }
3180 if (duration) {
3181#if MP4D_TIMESTAMPS_SUPPORTED
3182 *duration = tr->duration[ns];
3183#else
3184 *duration = 0;
3185#endif
3186 }
3187
3188 return offset;
3189}
3190
3191#define FREE(x) \
3192 if (x) { \
3193 free(x); \
3194 x = NULL; \
3195 }
3196
3197// Exported API function
3198void MP4D_close(MP4D_demux_t* mp4) {
3199 while (mp4->track_count) {
3200 MP4D_track_t* tr = mp4->track + --mp4->track_count;
3201 FREE(tr->entry_size);
3202#if MP4D_TIMESTAMPS_SUPPORTED
3203 FREE(tr->timestamp);
3204 FREE(tr->duration);
3205#endif
3206 FREE(tr->sample_to_chunk);
3207 FREE(tr->chunk_offset);
3208 FREE(tr->dsi);
3209 }
3210 FREE(mp4->track);
3211#if MP4D_INFO_SUPPORTED
3212 FREE(mp4->tag.title);
3213 FREE(mp4->tag.artist);
3214 FREE(mp4->tag.album);
3215 FREE(mp4->tag.year);
3216 FREE(mp4->tag.comment);
3217 FREE(mp4->tag.genre);
3218#endif
3219}
3220
3221static int skip_spspps(const unsigned char* p, int nbytes, int nskip) {
3222 int i, k = 0;
3223 for (i = 0; i < nskip; i++) {
3224 unsigned segmbytes;
3225 if (k > nbytes - 2)
3226 return -1;
3227 segmbytes = p[k] * 256 + p[k + 1];
3228 k += 2 + segmbytes;
3229 }
3230 return k;
3231}
3232
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;
3236 int bytepos = 0;
3237 unsigned char* p = mp4->track[ntrack].dsi;
3238 if (ntrack >= mp4->track_count)
3239 return NULL;
3241 return NULL; // SPS/PPS are specific for AVC format only
3242
3243 if (pps_flag) {
3244 // Skip all SPS
3245 sps_count = p[bytepos++];
3246 skip_bytes = skip_spspps(p + bytepos, mp4->track[ntrack].dsi_bytes - bytepos, sps_count);
3247 if (skip_bytes < 0)
3248 return NULL;
3249 bytepos += skip_bytes;
3250 }
3251
3252 // Skip sps/pps before the given target
3253 sps_count = p[bytepos++];
3254 if (nsps >= sps_count)
3255 return NULL;
3256 skip_bytes = skip_spspps(p + bytepos, mp4->track[ntrack].dsi_bytes - bytepos, nsps);
3257 if (skip_bytes < 0)
3258 return NULL;
3259 bytepos += skip_bytes;
3260 *sps_bytes = p[bytepos] * 256 + p[bytepos + 1];
3261 return p + bytepos + 2;
3262}
3263
3264const void* MP4D_read_sps(const MP4D_demux_t* mp4, unsigned int ntrack, int nsps, int* sps_bytes) {
3265 return MP4D_read_spspps(mp4, ntrack, 0, nsps, sps_bytes);
3266}
3267
3268const void* MP4D_read_pps(const MP4D_demux_t* mp4, unsigned int ntrack, int npps, int* pps_bytes) {
3269 return MP4D_read_spspps(mp4, ntrack, 1, npps, pps_bytes);
3270}
3271
3272#if MP4D_PRINT_INFO_SUPPORTED
3273/************************************************************************/
3274/* Purely informational part, may be removed for embedded applications */
3275/************************************************************************/
3276
3277//
3278// Decodes ISO/IEC 14496 MP4 stream type to ASCII string
3279//
3280static const char* GetMP4StreamTypeName(int streamType) {
3281 switch (streamType) {
3282 case 0x00:
3283 return "Forbidden";
3284 case 0x01:
3285 return "ObjectDescriptorStream";
3286 case 0x02:
3287 return "ClockReferenceStream";
3288 case 0x03:
3289 return "SceneDescriptionStream";
3290 case 0x04:
3291 return "VisualStream";
3292 case 0x05:
3293 return "AudioStream";
3294 case 0x06:
3295 return "MPEG7Stream";
3296 case 0x07:
3297 return "IPMPStream";
3298 case 0x08:
3299 return "ObjectContentInfoStream";
3300 case 0x09:
3301 return "MPEGJStream";
3302 default:
3303 if (streamType >= 0x20 && streamType <= 0x3F) {
3304 return "User private";
3305 } else {
3306 return "Reserved for ISO use";
3307 }
3308 }
3309}
3310
3311//
3312// Decodes ISO/IEC 14496 MP4 object type to ASCII string
3313//
3314static const char* GetMP4ObjectTypeName(int objectTypeIndication) {
3315 switch (objectTypeIndication) {
3316 case 0x00:
3317 return "Forbidden";
3318 case 0x01:
3319 return "Systems ISO/IEC 14496-1";
3320 case 0x02:
3321 return "Systems ISO/IEC 14496-1";
3322 case 0x20:
3323 return "Visual ISO/IEC 14496-2";
3324 case 0x40:
3325 return "Audio ISO/IEC 14496-3";
3326 case 0x60:
3327 return "Visual ISO/IEC 13818-2 Simple Profile";
3328 case 0x61:
3329 return "Visual ISO/IEC 13818-2 Main Profile";
3330 case 0x62:
3331 return "Visual ISO/IEC 13818-2 SNR Profile";
3332 case 0x63:
3333 return "Visual ISO/IEC 13818-2 Spatial Profile";
3334 case 0x64:
3335 return "Visual ISO/IEC 13818-2 High Profile";
3336 case 0x65:
3337 return "Visual ISO/IEC 13818-2 422 Profile";
3338 case 0x66:
3339 return "Audio ISO/IEC 13818-7 Main Profile";
3340 case 0x67:
3341 return "Audio ISO/IEC 13818-7 LC Profile";
3342 case 0x68:
3343 return "Audio ISO/IEC 13818-7 SSR Profile";
3344 case 0x69:
3345 return "Audio ISO/IEC 13818-3";
3346 case 0x6A:
3347 return "Visual ISO/IEC 11172-2";
3348 case 0x6B:
3349 return "Audio ISO/IEC 11172-3";
3350 case 0x6C:
3351 return "Visual ISO/IEC 10918-1";
3352 case 0xFF:
3353 return "no object type specified";
3354 default:
3355 if (objectTypeIndication >= 0xC0 && objectTypeIndication <= 0xFE)
3356 return "User private";
3357 else
3358 return "Reserved for ISO use";
3359 }
3360}
3361
3391void MP4D_printf_info(const MP4D_demux_t* mp4) {
3392 unsigned i;
3393 printf("\nMP4 FILE: %d tracks found. Movie time %.2f sec\n",
3394 mp4->track_count,
3395 (4294967296.0 * mp4->duration_hi + mp4->duration_lo) / mp4->timescale);
3396#define STR_TAG(name) \
3397 if (mp4->tag.name) \
3398 printf("%10s = %s\n", #name, mp4->tag.name)
3399 STR_TAG(title);
3400 STR_TAG(artist);
3401 STR_TAG(album);
3402 STR_TAG(year);
3403 STR_TAG(comment);
3404 STR_TAG(genre);
3405 printf("\nNo|type|lng| duration | bitrate| %-23s| Object type", "Stream type");
3406 for (i = 0; i < mp4->track_count; i++) {
3407 MP4D_track_t* tr = mp4->track + i;
3408
3409 printf("\n%2d|%c%c%c%c|%c%c%c|%7.2f s %6d frm| %7d|",
3410 i,
3411 (tr->handler_type >> 24),
3412 (tr->handler_type >> 16),
3413 (tr->handler_type >> 8),
3414 (tr->handler_type >> 0),
3415 tr->language[0],
3416 tr->language[1],
3417 tr->language[2],
3418 (65536.0 * 65536.0 * tr->duration_hi + tr->duration_lo) / tr->timescale,
3419 tr->sample_count,
3420 tr->avg_bitrate_bps);
3421
3422 printf(" %-23s|", GetMP4StreamTypeName(tr->stream_type));
3423 printf(" %-23s", GetMP4ObjectTypeName(tr->object_type_indication));
3424
3426 printf(" - %d ch %d hz",
3429 } else if (tr->handler_type == MP4D_HANDLER_TYPE_VIDE) {
3430 printf(" - %dx%d",
3433 }
3434 }
3435 printf("\n");
3436}
3437
3438#endif // MP4D_PRINT_INFO_SUPPORTED
3439#endif
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
char end[]
XE_LIB void * realloc(void *address, unsigned int new_size)
Definition _heap.cpp:6421
Definition minimp4.h:264
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
Definition minimp4.h:301
unsigned first_chunk
Definition minimp4.h:302
unsigned samples_per_chunk
Definition minimp4.h:303
Definition minimp4.h:159
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
Definition minimp4.h:129
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
Definition minimp4.h:306
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
Definition minimp4.h:317
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