1 /*
2   Licensed to the Apache Software Foundation (ASF) under one
3   or more contributor license agreements.  See the NOTICE file
4   distributed with this work for additional information
5   regarding copyright ownership.  The ASF licenses this file
6   to you under the Apache License, Version 2.0 (the
7   "License"); you may not use this file except in compliance
8   with the License.  You may obtain a copy of the License at
9 
10   http://www.apache.org/licenses/LICENSE-2.0
11 
12   Unless required by applicable law or agreed to in writing, software
13   distributed under the License is distributed on an "AS IS" BASIS,
14   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   See the License for the specific language governing permissions and
16   limitations under the License.
17 */
18 
19 #pragma once
20 
21 #include <cstring>
22 #include <cstdlib>
23 #include <cstdio>
24 #include <cstddef>
25 #include <unistd.h>
26 #include <getopt.h>
27 #include <cinttypes>
28 
29 #include <ts/ts.h>
30 
31 #define MP4_MAX_TRAK_NUM 6
32 #define MP4_MAX_BUFFER_SIZE (10 * 1024 * 1024)
33 #define MP4_MIN_BUFFER_SIZE 1024
34 
35 #define DEBUG_TAG "ts_mp4"
36 
37 #define mp4_set_atom_name(p, n1, n2, n3, n4) \
38   ((u_char *)(p))[4] = n1;                   \
39   ((u_char *)(p))[5] = n2;                   \
40   ((u_char *)(p))[6] = n3;                   \
41   ((u_char *)(p))[7] = n4
42 
43 #define mp4_get_32value(p) \
44   (((uint32_t)((u_char *)(p))[0] << 24) + (((u_char *)(p))[1] << 16) + (((u_char *)(p))[2] << 8) + (((u_char *)(p))[3]))
45 
46 #define mp4_set_32value(p, n)               \
47   ((u_char *)(p))[0] = (u_char)((n) >> 24); \
48   ((u_char *)(p))[1] = (u_char)((n) >> 16); \
49   ((u_char *)(p))[2] = (u_char)((n) >> 8);  \
50   ((u_char *)(p))[3] = (u_char)(n)
51 
52 #define mp4_get_64value(p)                                                                                              \
53   (((uint64_t)((u_char *)(p))[0] << 56) + ((uint64_t)((u_char *)(p))[1] << 48) + ((uint64_t)((u_char *)(p))[2] << 40) + \
54    ((uint64_t)((u_char *)(p))[3] << 32) + ((uint64_t)((u_char *)(p))[4] << 24) + (((u_char *)(p))[5] << 16) +           \
55    (((u_char *)(p))[6] << 8) + (((u_char *)(p))[7]))
56 
57 #define mp4_set_64value(p, n)                         \
58   ((u_char *)(p))[0] = (u_char)((uint64_t)(n) >> 56); \
59   ((u_char *)(p))[1] = (u_char)((uint64_t)(n) >> 48); \
60   ((u_char *)(p))[2] = (u_char)((uint64_t)(n) >> 40); \
61   ((u_char *)(p))[3] = (u_char)((uint64_t)(n) >> 32); \
62   ((u_char *)(p))[4] = (u_char)((n) >> 24);           \
63   ((u_char *)(p))[5] = (u_char)((n) >> 16);           \
64   ((u_char *)(p))[6] = (u_char)((n) >> 8);            \
65   ((u_char *)(p))[7] = (u_char)(n)
66 
67 typedef enum {
68   MP4_TRAK_ATOM = 0,
69   MP4_TKHD_ATOM,
70   MP4_MDIA_ATOM,
71   MP4_MDHD_ATOM,
72   MP4_HDLR_ATOM,
73   MP4_MINF_ATOM,
74   MP4_VMHD_ATOM,
75   MP4_SMHD_ATOM,
76   MP4_DINF_ATOM,
77   MP4_STBL_ATOM,
78   MP4_STSD_ATOM,
79   MP4_STTS_ATOM,
80   MP4_STTS_DATA,
81   MP4_STSS_ATOM,
82   MP4_STSS_DATA,
83   MP4_CTTS_ATOM,
84   MP4_CTTS_DATA,
85   MP4_STSC_ATOM,
86   MP4_STSC_CHUNK,
87   MP4_STSC_DATA,
88   MP4_STSZ_ATOM,
89   MP4_STSZ_DATA,
90   MP4_STCO_ATOM,
91   MP4_STCO_DATA,
92   MP4_CO64_ATOM,
93   MP4_CO64_DATA,
94   MP4_LAST_ATOM = MP4_CO64_DATA
95 } TSMp4AtomID;
96 
97 typedef struct {
98   u_char size[4];
99   u_char name[4];
100 } mp4_atom_header;
101 
102 typedef struct {
103   u_char size[4];
104   u_char name[4];
105   u_char size64[8];
106 } mp4_atom_header64;
107 
108 typedef struct {
109   u_char size[4];
110   u_char name[4];
111   u_char version[1];
112   u_char flags[3];
113   u_char creation_time[4];
114   u_char modification_time[4];
115   u_char timescale[4];
116   u_char duration[4];
117   u_char rate[4];
118   u_char volume[2];
119   u_char reserved[10];
120   u_char matrix[36];
121   u_char preview_time[4];
122   u_char preview_duration[4];
123   u_char poster_time[4];
124   u_char selection_time[4];
125   u_char selection_duration[4];
126   u_char current_time[4];
127   u_char next_track_id[4];
128 } mp4_mvhd_atom;
129 
130 typedef struct {
131   u_char size[4];
132   u_char name[4];
133   u_char version[1];
134   u_char flags[3];
135   u_char creation_time[8];
136   u_char modification_time[8];
137   u_char timescale[4];
138   u_char duration[8];
139   u_char rate[4];
140   u_char volume[2];
141   u_char reserved[10];
142   u_char matrix[36];
143   u_char preview_time[4];
144   u_char preview_duration[4];
145   u_char poster_time[4];
146   u_char selection_time[4];
147   u_char selection_duration[4];
148   u_char current_time[4];
149   u_char next_track_id[4];
150 } mp4_mvhd64_atom;
151 
152 typedef struct {
153   u_char size[4];
154   u_char name[4];
155   u_char version[1];
156   u_char flags[3];
157   u_char creation_time[4];
158   u_char modification_time[4];
159   u_char track_id[4];
160   u_char reserved1[4];
161   u_char duration[4];
162   u_char reserved2[8];
163   u_char layer[2];
164   u_char group[2];
165   u_char volume[2];
166   u_char reverved3[2];
167   u_char matrix[36];
168   u_char width[4];
169   u_char height[4];
170 } mp4_tkhd_atom;
171 
172 typedef struct {
173   u_char size[4];
174   u_char name[4];
175   u_char version[1];
176   u_char flags[3];
177   u_char creation_time[8];
178   u_char modification_time[8];
179   u_char track_id[4];
180   u_char reserved1[4];
181   u_char duration[8];
182   u_char reserved2[8];
183   u_char layer[2];
184   u_char group[2];
185   u_char volume[2];
186   u_char reverved3[2];
187   u_char matrix[36];
188   u_char width[4];
189   u_char height[4];
190 } mp4_tkhd64_atom;
191 
192 typedef struct {
193   u_char size[4];
194   u_char name[4];
195   u_char version[1];
196   u_char flags[3];
197   u_char creation_time[4];
198   u_char modification_time[4];
199   u_char timescale[4];
200   u_char duration[4];
201   u_char language[2];
202   u_char quality[2];
203 } mp4_mdhd_atom;
204 
205 typedef struct {
206   u_char size[4];
207   u_char name[4];
208   u_char version[1];
209   u_char flags[3];
210   u_char creation_time[8];
211   u_char modification_time[8];
212   u_char timescale[4];
213   u_char duration[8];
214   u_char language[2];
215   u_char quality[2];
216 } mp4_mdhd64_atom;
217 
218 typedef struct {
219   u_char size[4];
220   u_char name[4];
221   u_char version[1];
222   u_char flags[3];
223   u_char entries[4];
224 
225   u_char media_size[4];
226   u_char media_name[4];
227 } mp4_stsd_atom;
228 
229 typedef struct {
230   u_char size[4];
231   u_char name[4];
232   u_char version[1];
233   u_char flags[3];
234   u_char entries[4];
235 } mp4_stts_atom;
236 
237 typedef struct {
238   u_char count[4];
239   u_char duration[4];
240 } mp4_stts_entry;
241 
242 typedef struct {
243   u_char size[4];
244   u_char name[4];
245   u_char version[1];
246   u_char flags[3];
247   u_char entries[4];
248 } mp4_stss_atom;
249 
250 typedef struct {
251   u_char size[4];
252   u_char name[4];
253   u_char version[1];
254   u_char flags[3];
255   u_char entries[4];
256 } mp4_ctts_atom;
257 
258 typedef struct {
259   u_char count[4];
260   u_char offset[4];
261 } mp4_ctts_entry;
262 
263 typedef struct {
264   u_char size[4];
265   u_char name[4];
266   u_char version[1];
267   u_char flags[3];
268   u_char entries[4];
269 } mp4_stsc_atom;
270 
271 typedef struct {
272   u_char chunk[4];
273   u_char samples[4];
274   u_char id[4];
275 } mp4_stsc_entry;
276 
277 typedef struct {
278   u_char size[4];
279   u_char name[4];
280   u_char version[1];
281   u_char flags[3];
282   u_char uniform_size[4];
283   u_char entries[4];
284 } mp4_stsz_atom;
285 
286 typedef struct {
287   u_char size[4];
288   u_char name[4];
289   u_char version[1];
290   u_char flags[3];
291   u_char entries[4];
292 } mp4_stco_atom;
293 
294 typedef struct {
295   u_char size[4];
296   u_char name[4];
297   u_char version[1];
298   u_char flags[3];
299   u_char entries[4];
300 } mp4_co64_atom;
301 
302 class Mp4Meta;
303 typedef int (Mp4Meta::*Mp4AtomHandler)(int64_t atom_header_size, int64_t atom_data_size);
304 
305 typedef struct {
306   const char *name;
307   Mp4AtomHandler handler;
308 } mp4_atom_handler;
309 
310 class BufferHandle
311 {
312 public:
BufferHandle()313   BufferHandle(){};
314 
~BufferHandle()315   ~BufferHandle()
316   {
317     if (reader) {
318       TSIOBufferReaderFree(reader);
319       reader = nullptr;
320     }
321 
322     if (buffer) {
323       TSIOBufferDestroy(buffer);
324       buffer = nullptr;
325     }
326   }
327 
328 public:
329   TSIOBuffer buffer       = nullptr;
330   TSIOBufferReader reader = nullptr;
331 };
332 
333 class Mp4Trak
334 {
335 public:
Mp4Trak()336   Mp4Trak() { memset(&stsc_chunk_entry, 0, sizeof(mp4_stsc_entry)); }
337 
~Mp4Trak()338   ~Mp4Trak() {}
339 
340 public:
341   uint32_t timescale = 0;
342   int64_t duration   = 0;
343 
344   uint32_t time_to_sample_entries     = 0; // stsc
345   uint32_t sample_to_chunk_entries    = 0; // stsc
346   uint32_t sync_samples_entries       = 0; // stss
347   uint32_t composition_offset_entries = 0; // ctts
348   uint32_t sample_sizes_entries       = 0; // stsz
349   uint32_t chunks                     = 0; // stco, co64
350 
351   uint32_t start_sample       = 0;
352   uint32_t start_chunk        = 0;
353   uint32_t chunk_samples      = 0;
354   uint64_t chunk_samples_size = 0;
355   off_t start_offset          = 0;
356 
357   size_t tkhd_size = 0;
358   size_t mdhd_size = 0;
359   size_t hdlr_size = 0;
360   size_t vmhd_size = 0;
361   size_t smhd_size = 0;
362   size_t dinf_size = 0;
363   size_t size      = 0;
364 
365   BufferHandle atoms[MP4_LAST_ATOM + 1];
366 
367   mp4_stsc_entry stsc_chunk_entry;
368 };
369 
370 class Mp4Meta
371 {
372 public:
Mp4Meta()373   Mp4Meta()
374 
375   {
376     memset(trak_vec, 0, sizeof(trak_vec));
377     meta_buffer = TSIOBufferCreate();
378     meta_reader = TSIOBufferReaderAlloc(meta_buffer);
379   }
380 
~Mp4Meta()381   ~Mp4Meta()
382   {
383     uint32_t i;
384 
385     for (i = 0; i < trak_num; i++)
386       delete trak_vec[i];
387 
388     if (meta_reader) {
389       TSIOBufferReaderFree(meta_reader);
390       meta_reader = nullptr;
391     }
392 
393     if (meta_buffer) {
394       TSIOBufferDestroy(meta_buffer);
395       meta_buffer = nullptr;
396     }
397   }
398 
399   int parse_meta(bool body_complete);
400 
401   int post_process_meta();
402   void mp4_meta_consume(int64_t size);
403   int mp4_atom_next(int64_t atom_size, bool wait = false);
404 
405   int mp4_read_atom(mp4_atom_handler *atom, int64_t size);
406   int parse_root_atoms();
407 
408   int mp4_read_ftyp_atom(int64_t header_size, int64_t data_size);
409   int mp4_read_moov_atom(int64_t header_size, int64_t data_size);
410   int mp4_read_mdat_atom(int64_t header_size, int64_t data_size);
411 
412   int mp4_read_mvhd_atom(int64_t header_size, int64_t data_size);
413   int mp4_read_trak_atom(int64_t header_size, int64_t data_size);
414   int mp4_read_cmov_atom(int64_t header_size, int64_t data_size);
415 
416   int mp4_read_tkhd_atom(int64_t header_size, int64_t data_size);
417   int mp4_read_mdia_atom(int64_t header_size, int64_t data_size);
418 
419   int mp4_read_mdhd_atom(int64_t header_size, int64_t data_size);
420   int mp4_read_hdlr_atom(int64_t header_size, int64_t data_size);
421   int mp4_read_minf_atom(int64_t header_size, int64_t data_size);
422 
423   int mp4_read_vmhd_atom(int64_t header_size, int64_t data_size);
424   int mp4_read_smhd_atom(int64_t header_size, int64_t data_size);
425   int mp4_read_dinf_atom(int64_t header_size, int64_t data_size);
426   int mp4_read_stbl_atom(int64_t header_size, int64_t data_size);
427 
428   int mp4_read_stsd_atom(int64_t header_size, int64_t data_size);
429   int mp4_read_stts_atom(int64_t header_size, int64_t data_size);
430   int mp4_read_stss_atom(int64_t header_size, int64_t data_size);
431   int mp4_read_ctts_atom(int64_t header_size, int64_t data_size);
432   int mp4_read_stsc_atom(int64_t header_size, int64_t data_size);
433   int mp4_read_stsz_atom(int64_t header_size, int64_t data_size);
434   int mp4_read_stco_atom(int64_t header_size, int64_t data_size);
435   int mp4_read_co64_atom(int64_t header_size, int64_t data_size);
436 
437   int mp4_update_stts_atom(Mp4Trak *trak);
438   int mp4_update_stss_atom(Mp4Trak *trak);
439   int mp4_update_ctts_atom(Mp4Trak *trak);
440   int mp4_update_stsc_atom(Mp4Trak *trak);
441   int mp4_update_stsz_atom(Mp4Trak *trak);
442   int mp4_update_co64_atom(Mp4Trak *trak);
443   int mp4_update_stco_atom(Mp4Trak *trak);
444   int mp4_update_stbl_atom(Mp4Trak *trak);
445   int mp4_update_minf_atom(Mp4Trak *trak);
446   int mp4_update_mdia_atom(Mp4Trak *trak);
447   int mp4_update_trak_atom(Mp4Trak *trak);
448 
449   int64_t mp4_update_mdat_atom(int64_t start_offset);
450   int mp4_adjust_co64_atom(Mp4Trak *trak, off_t adjustment);
451   int mp4_adjust_stco_atom(Mp4Trak *trak, int32_t adjustment);
452 
453   uint32_t mp4_find_key_sample(uint32_t start_sample, Mp4Trak *trak);
454   void mp4_update_mvhd_duration();
455   void mp4_update_tkhd_duration(Mp4Trak *trak);
456   void mp4_update_mdhd_duration(Mp4Trak *trak);
457 
458 public:
459   int64_t start          = 0; // requested start time, measured in milliseconds.
460   int64_t cl             = 0; // the total size of the mp4 file
461   int64_t content_length = 0; // the size of the new mp4 file
462   int64_t meta_atom_size = 0;
463 
464   TSIOBuffer meta_buffer; // meta data to be parsed
465   TSIOBufferReader meta_reader;
466 
467   int64_t meta_avail = 0;
468   int64_t wait_next  = 0;
469   int64_t need_size  = 0;
470 
471   BufferHandle meta_atom;
472   BufferHandle ftyp_atom;
473   BufferHandle moov_atom;
474   BufferHandle mvhd_atom;
475   BufferHandle mdat_atom;
476   BufferHandle mdat_data;
477   BufferHandle out_handle;
478 
479   Mp4Trak *trak_vec[MP4_MAX_TRAK_NUM];
480 
481   double rs   = 0;
482   double rate = 0;
483 
484   int64_t ftyp_size  = 0;
485   int64_t moov_size  = 0;
486   int64_t start_pos  = 0; // start position of the new mp4 file
487   uint32_t timescale = 0;
488   uint32_t trak_num  = 0;
489   int64_t passed     = 0;
490 
491   u_char mdat_atom_header[16];
492   bool meta_complete = false;
493 };
494