1 /*
2 Copyright (c) 2012, Broadcom Europe Ltd
3 All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7     * Redistributions of source code must retain the above copyright
8       notice, this list of conditions and the following disclaimer.
9     * Redistributions in binary form must reproduce the above copyright
10       notice, this list of conditions and the following disclaimer in the
11       documentation and/or other materials provided with the distribution.
12     * Neither the name of the copyright holder nor the
13       names of its contributors may be used to endorse or promote products
14       derived from this software without specific prior written permission.
15 
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 #include <stdlib.h>
28 #include <string.h>
29 
30 /* Work-around for MSVC debugger issue */
31 #define VC_CONTAINER_MODULE_T VC_CONTAINER_MODULE_MP4_READER_T
32 #define VC_CONTAINER_TRACK_MODULE_T VC_CONTAINER_TRACK_MODULE_MP4_READER_T
33 
34 #define CONTAINER_IS_BIG_ENDIAN
35 #include "containers/core/containers_private.h"
36 #include "containers/core/containers_io_helpers.h"
37 #include "containers/core/containers_utils.h"
38 #include "containers/core/containers_logging.h"
39 #include "containers/mp4/mp4_common.h"
40 #undef CONTAINER_HELPER_LOG_INDENT
41 #define CONTAINER_HELPER_LOG_INDENT(a) (a)->priv->module->box_level
42 
43 VC_CONTAINER_STATUS_T mp4_reader_open( VC_CONTAINER_T *p_ctx );
44 
45 /******************************************************************************
46 TODO:
47 - aspect ratio
48 - itunes gapless
49 - edit list
50 - subpicture track
51 ******************************************************************************/
52 
53 /******************************************************************************
54 Defines.
55 ******************************************************************************/
56 #define MP4_TRACKS_MAX 16
57 
58 #define MP4_BOX_MIN_HEADER_SIZE 8
59 #define MP4_MAX_BOX_SIZE  (1<<29) /* Does not apply to the mdat box */
60 #define MP4_MAX_BOX_LEVEL 10
61 
62 #define MP4_MAX_SAMPLES_BATCH_SIZE (16*1024)
63 
64 #define MP4_SKIP_U8(ctx,n)   (size -= 1, SKIP_U8(ctx,n))
65 #define MP4_SKIP_U16(ctx,n)  (size -= 2, SKIP_U16(ctx,n))
66 #define MP4_SKIP_U24(ctx,n)  (size -= 3, SKIP_U24(ctx,n))
67 #define MP4_SKIP_U32(ctx,n)  (size -= 4, SKIP_U32(ctx,n))
68 #define MP4_SKIP_U64(ctx,n)  (size -= 8, SKIP_U64(ctx,n))
69 #define MP4_READ_U8(ctx,n)   (size -= 1, READ_U8(ctx,n))
70 #define MP4_READ_U16(ctx,n)  (size -= 2, READ_U16(ctx,n))
71 #define MP4_READ_U24(ctx,n)  (size -= 3, READ_U24(ctx,n))
72 #define MP4_READ_U32(ctx,n)  (size -= 4, READ_U32(ctx,n))
73 #define MP4_READ_U64(ctx,n)  (size -= 8, READ_U64(ctx,n))
74 #define MP4_READ_FOURCC(ctx,n)  (size -= 4, READ_FOURCC(ctx,n))
75 #define MP4_SKIP_FOURCC(ctx,n)  (size -= 4, SKIP_FOURCC(ctx,n))
76 #define MP4_READ_BYTES(ctx,buffer,sz) (size -= sz, READ_BYTES(ctx,buffer,sz))
77 #define MP4_SKIP_BYTES(ctx,sz) (size -= sz, SKIP_BYTES(ctx,sz))
78 #define MP4_SKIP_STRING(ctx,sz,n) (size -= sz, SKIP_STRING(ctx,sz,n))
79 
80 /******************************************************************************
81 Type definitions.
82 ******************************************************************************/
83 typedef struct
84 {
85    VC_CONTAINER_STATUS_T status;
86 
87    int64_t  duration;
88    int64_t  pts;
89    int64_t  dts;
90 
91    uint32_t sample;
92    int64_t offset;
93    unsigned int sample_offset;
94    unsigned int sample_size;
95 
96    uint32_t sample_duration;
97    uint32_t sample_duration_count;
98    int32_t sample_composition_offset;
99    uint32_t sample_composition_count;
100 
101    uint32_t next_sync_sample;
102    bool keyframe;
103 
104    uint32_t samples_per_chunk;
105    uint32_t chunks;
106    uint32_t samples_in_chunk;
107 
108    struct {
109       uint32_t entry;
110    } sample_table[MP4_SAMPLE_TABLE_NUM];
111 
112 } MP4_READER_STATE_T;
113 
114 typedef struct VC_CONTAINER_TRACK_MODULE_T
115 {
116    MP4_READER_STATE_T state;
117 
118    int64_t timescale;
119    uint8_t object_type_indication;
120 
121    uint32_t sample_size;
122    struct {
123       int64_t offset;
124       uint32_t entries;
125       uint32_t entry_size;
126    } sample_table[MP4_SAMPLE_TABLE_NUM];
127 
128    uint32_t samples_batch_size;
129 
130 } VC_CONTAINER_TRACK_MODULE_T;
131 
132 typedef struct VC_CONTAINER_MODULE_T
133 {
134    int64_t box_offset;
135    int box_level;
136 
137    MP4_BRAND_T brand;
138 
139    int64_t timescale;
140 
141    VC_CONTAINER_TRACK_T *tracks[MP4_TRACKS_MAX];
142    unsigned int current_track;
143 
144    bool found_moov;
145    int64_t data_offset;
146    int64_t data_size;
147 
148 } VC_CONTAINER_MODULE_T;
149 
150 /******************************************************************************
151 Static functions within this file.
152 ******************************************************************************/
153 static VC_CONTAINER_STATUS_T mp4_read_box( VC_CONTAINER_T *p_ctx, int64_t size, MP4_BOX_TYPE_T parent_type );
154 static VC_CONTAINER_STATUS_T mp4_read_boxes( VC_CONTAINER_T *p_ctx, int64_t size, MP4_BOX_TYPE_T type );
155 static VC_CONTAINER_STATUS_T mp4_read_box_ftyp( VC_CONTAINER_T *p_ctx, int64_t size );
156 static VC_CONTAINER_STATUS_T mp4_read_box_moov( VC_CONTAINER_T *p_ctx, int64_t size );
157 static VC_CONTAINER_STATUS_T mp4_read_box_mvhd( VC_CONTAINER_T *p_ctx, int64_t size );
158 static VC_CONTAINER_STATUS_T mp4_read_box_trak( VC_CONTAINER_T *p_ctx, int64_t size );
159 static VC_CONTAINER_STATUS_T mp4_read_box_tkhd( VC_CONTAINER_T *p_ctx, int64_t size );
160 static VC_CONTAINER_STATUS_T mp4_read_box_mdia( VC_CONTAINER_T *p_ctx, int64_t size );
161 static VC_CONTAINER_STATUS_T mp4_read_box_mdhd( VC_CONTAINER_T *p_ctx, int64_t size );
162 static VC_CONTAINER_STATUS_T mp4_read_box_hdlr( VC_CONTAINER_T *p_ctx, int64_t size );
163 static VC_CONTAINER_STATUS_T mp4_read_box_minf( VC_CONTAINER_T *p_ctx, int64_t size );
164 static VC_CONTAINER_STATUS_T mp4_read_box_vmhd( VC_CONTAINER_T *p_ctx, int64_t size );
165 static VC_CONTAINER_STATUS_T mp4_read_box_smhd( VC_CONTAINER_T *p_ctx, int64_t size );
166 static VC_CONTAINER_STATUS_T mp4_read_box_dinf( VC_CONTAINER_T *p_ctx, int64_t size );
167 static VC_CONTAINER_STATUS_T mp4_read_box_dref( VC_CONTAINER_T *p_ctx, int64_t size );
168 static VC_CONTAINER_STATUS_T mp4_read_box_stbl( VC_CONTAINER_T *p_ctx, int64_t size );
169 static VC_CONTAINER_STATUS_T mp4_read_box_stsd( VC_CONTAINER_T *p_ctx, int64_t size );
170 static VC_CONTAINER_STATUS_T mp4_read_box_stts( VC_CONTAINER_T *p_ctx, int64_t size );
171 static VC_CONTAINER_STATUS_T mp4_read_box_ctts( VC_CONTAINER_T *p_ctx, int64_t size );
172 static VC_CONTAINER_STATUS_T mp4_read_box_stsc( VC_CONTAINER_T *p_ctx, int64_t size );
173 static VC_CONTAINER_STATUS_T mp4_read_box_stsz( VC_CONTAINER_T *p_ctx, int64_t size );
174 static VC_CONTAINER_STATUS_T mp4_read_box_stco( VC_CONTAINER_T *p_ctx, int64_t size );
175 static VC_CONTAINER_STATUS_T mp4_read_box_co64( VC_CONTAINER_T *p_ctx, int64_t size );
176 static VC_CONTAINER_STATUS_T mp4_read_box_stss( VC_CONTAINER_T *p_ctx, int64_t size );
177 static VC_CONTAINER_STATUS_T mp4_read_box_vide( VC_CONTAINER_T *p_ctx, int64_t size );
178 static VC_CONTAINER_STATUS_T mp4_read_box_soun( VC_CONTAINER_T *p_ctx, int64_t size );
179 static VC_CONTAINER_STATUS_T mp4_read_box_text( VC_CONTAINER_T *p_ctx, int64_t size );
180 
181 static VC_CONTAINER_STATUS_T mp4_read_box_esds( VC_CONTAINER_T *p_ctx, int64_t size );
182 static VC_CONTAINER_STATUS_T mp4_read_box_vide_avcC( VC_CONTAINER_T *p_ctx, int64_t size );
183 static VC_CONTAINER_STATUS_T mp4_read_box_vide_d263( VC_CONTAINER_T *p_ctx, int64_t size );
184 static VC_CONTAINER_STATUS_T mp4_read_box_soun_damr( VC_CONTAINER_T *p_ctx, int64_t size );
185 static VC_CONTAINER_STATUS_T mp4_read_box_soun_dawp( VC_CONTAINER_T *p_ctx, int64_t size );
186 static VC_CONTAINER_STATUS_T mp4_read_box_soun_devc( VC_CONTAINER_T *p_ctx, int64_t size );
187 static VC_CONTAINER_STATUS_T mp4_read_box_soun_wave( VC_CONTAINER_T *p_ctx, int64_t size );
188 
189 static struct {
190   const MP4_BOX_TYPE_T type;
191   VC_CONTAINER_STATUS_T (*pf_func)( VC_CONTAINER_T *, int64_t );
192   const MP4_BOX_TYPE_T parent_type;
193 } mp4_box_list[] =
194 {
195    {MP4_BOX_TYPE_FTYP, mp4_read_box_ftyp, MP4_BOX_TYPE_ROOT},
196    {MP4_BOX_TYPE_MDAT, 0,                 MP4_BOX_TYPE_ROOT},
197    {MP4_BOX_TYPE_MOOV, mp4_read_box_moov, MP4_BOX_TYPE_ROOT},
198    {MP4_BOX_TYPE_MVHD, mp4_read_box_mvhd, MP4_BOX_TYPE_MOOV},
199    {MP4_BOX_TYPE_TRAK, mp4_read_box_trak, MP4_BOX_TYPE_MOOV},
200    {MP4_BOX_TYPE_TKHD, mp4_read_box_tkhd, MP4_BOX_TYPE_TRAK},
201    {MP4_BOX_TYPE_MDIA, mp4_read_box_mdia, MP4_BOX_TYPE_TRAK},
202    {MP4_BOX_TYPE_MDHD, mp4_read_box_mdhd, MP4_BOX_TYPE_MDIA},
203    {MP4_BOX_TYPE_HDLR, mp4_read_box_hdlr, MP4_BOX_TYPE_MDIA},
204    {MP4_BOX_TYPE_MINF, mp4_read_box_minf, MP4_BOX_TYPE_MDIA},
205    {MP4_BOX_TYPE_VMHD, mp4_read_box_vmhd, MP4_BOX_TYPE_MINF},
206    {MP4_BOX_TYPE_SMHD, mp4_read_box_smhd, MP4_BOX_TYPE_MINF},
207    {MP4_BOX_TYPE_DINF, mp4_read_box_dinf, MP4_BOX_TYPE_MINF},
208    {MP4_BOX_TYPE_DREF, mp4_read_box_dref, MP4_BOX_TYPE_DINF},
209    {MP4_BOX_TYPE_STBL, mp4_read_box_stbl, MP4_BOX_TYPE_MINF},
210    {MP4_BOX_TYPE_STSD, mp4_read_box_stsd, MP4_BOX_TYPE_STBL},
211    {MP4_BOX_TYPE_STTS, mp4_read_box_stts, MP4_BOX_TYPE_STBL},
212    {MP4_BOX_TYPE_CTTS, mp4_read_box_ctts, MP4_BOX_TYPE_STBL},
213    {MP4_BOX_TYPE_STSC, mp4_read_box_stsc, MP4_BOX_TYPE_STBL},
214    {MP4_BOX_TYPE_STSZ, mp4_read_box_stsz, MP4_BOX_TYPE_STBL},
215    {MP4_BOX_TYPE_STCO, mp4_read_box_stco, MP4_BOX_TYPE_STBL},
216    {MP4_BOX_TYPE_CO64, mp4_read_box_co64, MP4_BOX_TYPE_STBL},
217    {MP4_BOX_TYPE_STSS, mp4_read_box_stss, MP4_BOX_TYPE_STBL},
218    {MP4_BOX_TYPE_VIDE, mp4_read_box_vide, MP4_BOX_TYPE_STSD},
219    {MP4_BOX_TYPE_SOUN, mp4_read_box_soun, MP4_BOX_TYPE_STSD},
220    {MP4_BOX_TYPE_TEXT, mp4_read_box_text, MP4_BOX_TYPE_STSD},
221 
222    /* Codec specific boxes */
223    {MP4_BOX_TYPE_AVCC, mp4_read_box_vide_avcC, MP4_BOX_TYPE_VIDE},
224    {MP4_BOX_TYPE_D263, mp4_read_box_vide_d263, MP4_BOX_TYPE_VIDE},
225    {MP4_BOX_TYPE_ESDS, mp4_read_box_esds, MP4_BOX_TYPE_VIDE},
226    {MP4_BOX_TYPE_DAMR, mp4_read_box_soun_damr, MP4_BOX_TYPE_SOUN},
227    {MP4_BOX_TYPE_DAWP, mp4_read_box_soun_dawp, MP4_BOX_TYPE_SOUN},
228    {MP4_BOX_TYPE_DEVC, mp4_read_box_soun_devc, MP4_BOX_TYPE_SOUN},
229    {MP4_BOX_TYPE_WAVE, mp4_read_box_soun_wave, MP4_BOX_TYPE_SOUN},
230    {MP4_BOX_TYPE_ESDS, mp4_read_box_esds, MP4_BOX_TYPE_SOUN},
231 
232    {MP4_BOX_TYPE_UNKNOWN, 0,              MP4_BOX_TYPE_UNKNOWN}
233 };
234 
235 static struct {
236   const VC_CONTAINER_FOURCC_T type;
237   const VC_CONTAINER_FOURCC_T codec;
238   bool batch;
239 } mp4_codec_mapping[] =
240 {
241   {VC_FOURCC('a','v','c','1'), VC_CONTAINER_CODEC_H264, 0},
242   {VC_FOURCC('m','p','4','v'), VC_CONTAINER_CODEC_MP4V, 0},
243   {VC_FOURCC('s','2','6','3'), VC_CONTAINER_CODEC_H263, 0},
244   {VC_FOURCC('m','p','e','g'), VC_CONTAINER_CODEC_MP2V, 0},
245   {VC_FOURCC('m','j','p','a'), VC_CONTAINER_CODEC_MJPEGA, 0},
246   {VC_FOURCC('m','j','p','b'), VC_CONTAINER_CODEC_MJPEGB, 0},
247 
248   {VC_FOURCC('j','p','e','g'), VC_CONTAINER_CODEC_JPEG, 0},
249 
250   {VC_FOURCC('m','p','4','a'), VC_CONTAINER_CODEC_MP4A, 0},
251   {VC_FOURCC('s','a','m','r'), VC_CONTAINER_CODEC_AMRNB, 0},
252   {VC_FOURCC('s','a','w','b'), VC_CONTAINER_CODEC_AMRWB, 0},
253   {VC_FOURCC('s','a','w','p'), VC_CONTAINER_CODEC_AMRWBP, 0},
254   {VC_FOURCC('a','c','-','3'), VC_CONTAINER_CODEC_AC3, 0},
255   {VC_FOURCC('e','c','-','3'), VC_CONTAINER_CODEC_EAC3, 0},
256   {VC_FOURCC('s','e','v','c'), VC_CONTAINER_CODEC_EVRC, 0},
257   {VC_FOURCC('e','v','r','c'), VC_CONTAINER_CODEC_EVRC, 0},
258   {VC_FOURCC('s','q','c','p'), VC_CONTAINER_CODEC_QCELP, 0},
259   {VC_FOURCC('a','l','a','w'), VC_CONTAINER_CODEC_ALAW, 1},
260   {VC_FOURCC('u','l','a','w'), VC_CONTAINER_CODEC_MULAW, 1},
261   {VC_FOURCC('t','w','o','s'), VC_CONTAINER_CODEC_PCM_SIGNED_BE, 1},
262   {VC_FOURCC('s','o','w','t'), VC_CONTAINER_CODEC_PCM_SIGNED_LE, 1},
263 
264   {0, 0},
265 };
mp4_box_type_to_codec(VC_CONTAINER_FOURCC_T type)266 static VC_CONTAINER_FOURCC_T mp4_box_type_to_codec(VC_CONTAINER_FOURCC_T type)
267 {
268    int i;
269    for(i = 0; mp4_codec_mapping[i].type; i++ )
270       if(mp4_codec_mapping[i].type == type) break;
271    return mp4_codec_mapping[i].codec;
272 }
273 
codec_needs_batch_mode(VC_CONTAINER_FOURCC_T codec)274 static bool codec_needs_batch_mode(VC_CONTAINER_FOURCC_T codec)
275 {
276    int i;
277    for(i = 0; mp4_codec_mapping[i].codec; i++ )
278       if(mp4_codec_mapping[i].codec == codec) break;
279    return mp4_codec_mapping[i].batch;
280 }
281 
282 /*****************************************************************************/
mp4_read_box_header(VC_CONTAINER_T * p_ctx,int64_t size,MP4_BOX_TYPE_T * box_type,int64_t * box_size)283 static VC_CONTAINER_STATUS_T mp4_read_box_header( VC_CONTAINER_T *p_ctx, int64_t size,
284    MP4_BOX_TYPE_T *box_type, int64_t *box_size )
285 {
286    VC_CONTAINER_MODULE_T *module = p_ctx->priv->module;
287    int64_t offset = STREAM_POSITION(p_ctx);
288 
289    module->box_offset = offset;
290 
291    *box_size = _READ_U32(p_ctx);
292    *box_type = _READ_FOURCC(p_ctx);
293    if(!*box_type) return VC_CONTAINER_ERROR_CORRUPTED;
294 
295    if(*box_size == 1) *box_size = _READ_U64(p_ctx);
296    LOG_FORMAT(p_ctx, "- Box %4.4s, Size: %"PRIi64", Offset: %"PRIi64,
297               (const char *)box_type, *box_size, offset);
298 
299    /* Sanity check the box size */
300    if(*box_size < 0 /* Shouldn't ever get that big */ ||
301       /* Only the mdat box can really be massive */
302       (*box_type != MP4_BOX_TYPE_MDAT && *box_size > MP4_MAX_BOX_SIZE))
303    {
304       LOG_DEBUG(p_ctx, "box %4.4s has an invalid size (%"PRIi64")",
305                 (const char *)box_type, *box_size);
306       return VC_CONTAINER_ERROR_CORRUPTED;
307    }
308 
309 #if 0
310    /* It is valid for a box to have a zero size (i.e unknown) if it is the last one */
311    if(*box_size == 0 && size >= 0) *box_size = size;
312    else if(*box_size == 0) *box_size = INT64_C(-1);
313 #else
314    if(*box_size <= 0)
315    {
316       LOG_DEBUG(p_ctx, "box %4.4s has an invalid size (%"PRIi64")",
317                 (const char *)box_type, *box_size);
318       return VC_CONTAINER_ERROR_CORRUPTED;
319    }
320 #endif
321 
322    /* Sanity check box size against parent */
323    if(size >= 0 && *box_size > size)
324    {
325       LOG_DEBUG(p_ctx, "box %4.4s is bigger than it should (%"PRIi64" > %"PRIi64")",
326             (const char *)box_type, *box_size, size);
327       return VC_CONTAINER_ERROR_CORRUPTED;
328    }
329 
330    *box_size -= (STREAM_POSITION(p_ctx) - offset);
331    return STREAM_STATUS(p_ctx);
332 }
333 
334 /*****************************************************************************/
mp4_read_box_data(VC_CONTAINER_T * p_ctx,MP4_BOX_TYPE_T box_type,int64_t box_size,MP4_BOX_TYPE_T parent_type)335 static VC_CONTAINER_STATUS_T mp4_read_box_data( VC_CONTAINER_T *p_ctx,
336    MP4_BOX_TYPE_T box_type, int64_t box_size, MP4_BOX_TYPE_T parent_type )
337 {
338    VC_CONTAINER_MODULE_T *module = p_ctx->priv->module;
339    int64_t offset = STREAM_POSITION(p_ctx);
340    VC_CONTAINER_STATUS_T status = VC_CONTAINER_SUCCESS;
341    unsigned int i;
342 
343    /* Check if the box is a recognised one */
344    for(i = 0; mp4_box_list[i].type; i++)
345       if(mp4_box_list[i].type == box_type &&
346          mp4_box_list[i].parent_type == parent_type) break;
347    if(mp4_box_list[i].type == MP4_BOX_TYPE_UNKNOWN)
348       for(i = 0; mp4_box_list[i].type; i++)
349          if(mp4_box_list[i].type == box_type) break;
350 
351    /* Sanity check that the box has the right parent */
352    if(mp4_box_list[i].type != MP4_BOX_TYPE_UNKNOWN &&
353       mp4_box_list[i].parent_type != MP4_BOX_TYPE_UNKNOWN &&
354       parent_type != MP4_BOX_TYPE_UNKNOWN && parent_type != mp4_box_list[i].parent_type)
355    {
356       LOG_FORMAT(p_ctx, "Ignoring mis-placed box %4.4s", (const char *)&box_type);
357       goto skip;
358    }
359 
360    /* Sanity check that the element isn't too deeply nested */
361    if(module->box_level >= 2 * MP4_MAX_BOX_LEVEL)
362    {
363       LOG_DEBUG(p_ctx, "box %4.4s is too deep. skipping", (const char *)&box_type);
364       goto skip;
365    }
366 
367    module->box_level++;
368 
369    /* Call the box specific parsing function */
370    if(mp4_box_list[i].pf_func)
371       status = mp4_box_list[i].pf_func(p_ctx, box_size);
372 
373    module->box_level--;
374 
375    if(status != VC_CONTAINER_SUCCESS)
376       LOG_DEBUG(p_ctx, "box %4.4s appears to be corrupted (%i)", (const char *)&box_type, status);
377 
378  skip:
379    /* Skip the rest of the box */
380    box_size -= (STREAM_POSITION(p_ctx) - offset);
381    if(box_size < 0) /* Check for overruns */
382    {
383       /* Things have gone really bad here and we ended up reading past the end of the
384        * box. We could maybe try to be clever and recover by seeking back to the end
385        * of the box. However if we get there, the file is clearly corrupted so there's
386        * no guarantee it would work anyway. */
387       LOG_DEBUG(p_ctx, "%"PRIi64" bytes overrun past the end of box %4.4s",
388                 -box_size, (const char *)&box_type);
389       return VC_CONTAINER_ERROR_CORRUPTED;
390    }
391 
392    if(box_size)
393       LOG_FORMAT(p_ctx, "%"PRIi64" bytes left unread in box %4.4s",
394                  box_size, (const char *)&box_type );
395 
396    if(box_size < MP4_MAX_BOX_SIZE) box_size = SKIP_BYTES(p_ctx, box_size);
397    else SEEK(p_ctx, STREAM_POSITION(p_ctx) + box_size);
398 
399    return STREAM_STATUS(p_ctx);
400 }
401 
402 /*****************************************************************************/
mp4_read_box(VC_CONTAINER_T * p_ctx,int64_t size,MP4_BOX_TYPE_T parent_type)403 static VC_CONTAINER_STATUS_T mp4_read_box( VC_CONTAINER_T *p_ctx, int64_t size,
404    MP4_BOX_TYPE_T parent_type )
405 {
406    VC_CONTAINER_STATUS_T status;
407    MP4_BOX_TYPE_T box_type;
408    int64_t box_size;
409 
410    status = mp4_read_box_header( p_ctx, size, &box_type, &box_size );
411    if(status != VC_CONTAINER_SUCCESS) return status;
412    return mp4_read_box_data( p_ctx, box_type, box_size, parent_type );
413 }
414 
415 /*****************************************************************************/
mp4_read_boxes(VC_CONTAINER_T * p_ctx,int64_t size,MP4_BOX_TYPE_T type)416 static VC_CONTAINER_STATUS_T mp4_read_boxes( VC_CONTAINER_T *p_ctx, int64_t size,
417    MP4_BOX_TYPE_T type)
418 {
419    VC_CONTAINER_MODULE_T *module = p_ctx->priv->module;
420    VC_CONTAINER_STATUS_T status = VC_CONTAINER_SUCCESS;
421    int64_t offset = STREAM_POSITION(p_ctx);
422    bool unknown_size = size < 0;
423 
424    /* Read contained boxes */
425    module->box_level++;
426    while(status == VC_CONTAINER_SUCCESS &&
427          (unknown_size || size >= MP4_BOX_MIN_HEADER_SIZE))
428    {
429       offset = STREAM_POSITION(p_ctx);
430       status = mp4_read_box(p_ctx, size, type);
431       if(!unknown_size) size -= (STREAM_POSITION(p_ctx) - offset);
432    }
433    module->box_level--;
434    return status;
435 }
436 
437 /*****************************************************************************/
mp4_read_box_ftyp(VC_CONTAINER_T * p_ctx,int64_t size)438 static VC_CONTAINER_STATUS_T mp4_read_box_ftyp( VC_CONTAINER_T *p_ctx, int64_t size )
439 {
440    VC_CONTAINER_MODULE_T *module = p_ctx->priv->module;
441 
442    module->brand = MP4_READ_FOURCC(p_ctx, "major_brand");
443    MP4_SKIP_U32(p_ctx, "minor_version");
444    while(size >= 4) MP4_SKIP_FOURCC(p_ctx, "compatible_brands");
445 
446    return STREAM_STATUS(p_ctx);
447 }
448 
449 /*****************************************************************************/
mp4_read_box_moov(VC_CONTAINER_T * p_ctx,int64_t size)450 static VC_CONTAINER_STATUS_T mp4_read_box_moov( VC_CONTAINER_T *p_ctx, int64_t size )
451 {
452    return mp4_read_boxes( p_ctx, size, MP4_BOX_TYPE_MOOV);
453 }
454 
455 /*****************************************************************************/
mp4_read_box_mvhd(VC_CONTAINER_T * p_ctx,int64_t size)456 static VC_CONTAINER_STATUS_T mp4_read_box_mvhd( VC_CONTAINER_T *p_ctx, int64_t size )
457 {
458    VC_CONTAINER_MODULE_T *module = p_ctx->priv->module;
459    uint32_t version, i;
460    int64_t duration;
461 
462    version = MP4_READ_U8(p_ctx, "version");
463    MP4_SKIP_U24(p_ctx, "flags");
464 
465    if(version)
466    {
467       MP4_SKIP_U64(p_ctx, "creation_time");
468       MP4_SKIP_U64(p_ctx, "modification_time");
469       module->timescale = MP4_READ_U32(p_ctx, "timescale");
470       duration = MP4_READ_U64(p_ctx, "duration");
471    }
472    else
473    {
474       MP4_SKIP_U32(p_ctx, "creation_time");
475       MP4_SKIP_U32(p_ctx, "modification_time");
476       module->timescale = MP4_READ_U32(p_ctx, "timescale");
477       duration = MP4_READ_U32(p_ctx, "duration");
478    }
479 
480    if(module->timescale)
481       p_ctx->duration = duration * 1000000 / module->timescale;
482 
483    MP4_SKIP_U32(p_ctx, "rate");
484    MP4_SKIP_U16(p_ctx, "volume");
485    MP4_SKIP_U16(p_ctx, "reserved");
486    for(i = 0; i < 2; i++) MP4_SKIP_U32(p_ctx, "reserved");
487    for(i = 0; i < 9; i++) MP4_SKIP_U32(p_ctx, "matrix");
488    for(i = 0; i < 6; i++) MP4_SKIP_U32(p_ctx, "pre_defined");
489    MP4_SKIP_U32(p_ctx, "next_track_ID");
490 
491    return STREAM_STATUS(p_ctx);
492 }
493 
494 /*****************************************************************************/
mp4_read_box_trak(VC_CONTAINER_T * p_ctx,int64_t size)495 static VC_CONTAINER_STATUS_T mp4_read_box_trak( VC_CONTAINER_T *p_ctx, int64_t size )
496 {
497    VC_CONTAINER_STATUS_T status = VC_CONTAINER_SUCCESS;
498    VC_CONTAINER_MODULE_T *module = p_ctx->priv->module;
499    VC_CONTAINER_TRACK_T *track;
500 
501    /* We have a new track. Allocate and initialise our track context */
502    if(p_ctx->tracks_num >= MP4_TRACKS_MAX) return VC_CONTAINER_ERROR_OUT_OF_RESOURCES;
503    p_ctx->tracks[p_ctx->tracks_num] = track =
504       vc_container_allocate_track(p_ctx, sizeof(*p_ctx->tracks[0]->priv->module));
505    if(!track) return VC_CONTAINER_ERROR_OUT_OF_MEMORY;
506 
507    track->priv->module->sample_table[MP4_SAMPLE_TABLE_STTS].entry_size = 8;
508    track->priv->module->sample_table[MP4_SAMPLE_TABLE_STSZ].entry_size = 4;
509    track->priv->module->sample_table[MP4_SAMPLE_TABLE_STSC].entry_size = 12;
510    track->priv->module->sample_table[MP4_SAMPLE_TABLE_STCO].entry_size = 4;
511    track->priv->module->sample_table[MP4_SAMPLE_TABLE_STSS].entry_size = 4;
512    track->priv->module->sample_table[MP4_SAMPLE_TABLE_CO64].entry_size = 8;
513    track->priv->module->sample_table[MP4_SAMPLE_TABLE_CTTS].entry_size = 8;
514 
515    status = mp4_read_boxes( p_ctx, size, MP4_BOX_TYPE_TRAK);
516 
517    /* TODO: Sanity check track */
518 
519    track->is_enabled = true;
520    track->format->flags |= VC_CONTAINER_ES_FORMAT_FLAG_FRAMED;
521    module->current_track++;
522    p_ctx->tracks_num++;
523 
524    return status;
525 }
526 
527 /*****************************************************************************/
mp4_read_box_tkhd(VC_CONTAINER_T * p_ctx,int64_t size)528 static VC_CONTAINER_STATUS_T mp4_read_box_tkhd( VC_CONTAINER_T *p_ctx, int64_t size )
529 {
530    VC_CONTAINER_MODULE_T *module = p_ctx->priv->module;
531    uint32_t i, version;
532    int64_t duration;
533 
534    version = MP4_READ_U8(p_ctx, "version");
535    MP4_SKIP_U24(p_ctx, "flags");
536 
537    if(version)
538    {
539       MP4_SKIP_U64(p_ctx, "creation_time");
540       MP4_SKIP_U64(p_ctx, "modification_time");
541       MP4_SKIP_U32(p_ctx, "track_ID");
542       MP4_SKIP_U32(p_ctx, "reserved");
543       duration = MP4_READ_U64(p_ctx, "duration");
544    }
545    else
546    {
547       MP4_SKIP_U32(p_ctx, "creation_time");
548       MP4_SKIP_U32(p_ctx, "modification_time");
549       MP4_SKIP_U32(p_ctx, "track_ID");
550       MP4_SKIP_U32(p_ctx, "reserved");
551       duration = MP4_READ_U32(p_ctx, "duration");
552    }
553 
554    if(module->timescale)
555       duration = duration * 1000000 / module->timescale;
556 
557    for(i = 0; i < 2; i++) MP4_SKIP_U32(p_ctx, "reserved");
558    MP4_SKIP_U16(p_ctx, "layer");
559    MP4_SKIP_U16(p_ctx, "alternate_group");
560    MP4_SKIP_U16(p_ctx, "volume");
561    MP4_SKIP_U16(p_ctx, "reserved");
562    for(i = 0; i < 9; i++) MP4_SKIP_U32(p_ctx, "matrix");
563 
564    MP4_SKIP_U32(p_ctx, "width");
565    MP4_SKIP_U32(p_ctx, "height");
566 
567    return STREAM_STATUS(p_ctx);
568 }
569 
570 /*****************************************************************************/
mp4_read_box_mdia(VC_CONTAINER_T * p_ctx,int64_t size)571 static VC_CONTAINER_STATUS_T mp4_read_box_mdia( VC_CONTAINER_T *p_ctx, int64_t size )
572 {
573    return mp4_read_boxes( p_ctx, size, MP4_BOX_TYPE_MDIA);
574 }
575 
576 /*****************************************************************************/
mp4_read_box_mdhd(VC_CONTAINER_T * p_ctx,int64_t size)577 static VC_CONTAINER_STATUS_T mp4_read_box_mdhd( VC_CONTAINER_T *p_ctx, int64_t size )
578 {
579    VC_CONTAINER_MODULE_T *module = p_ctx->priv->module;
580    VC_CONTAINER_TRACK_MODULE_T *track_module = p_ctx->tracks[module->current_track]->priv->module;
581    uint32_t version, timescale;
582    int64_t duration;
583 
584    version = MP4_READ_U8(p_ctx, "version");
585    MP4_SKIP_U24(p_ctx, "flags");
586 
587    if(version)
588    {
589       MP4_SKIP_U64(p_ctx, "creation_time");
590       MP4_SKIP_U64(p_ctx, "modification_time");
591       timescale = MP4_READ_U32(p_ctx, "timescale");
592       duration = MP4_READ_U64(p_ctx, "duration");
593    }
594    else
595    {
596       MP4_SKIP_U32(p_ctx, "creation_time");
597       MP4_SKIP_U32(p_ctx, "modification_time");
598       timescale = MP4_READ_U32(p_ctx, "timescale");
599       duration = MP4_READ_U32(p_ctx, "duration");
600    }
601 
602    if(timescale) duration = duration * 1000000 / timescale;
603    track_module->timescale = timescale;
604 
605    MP4_SKIP_U16(p_ctx, "language"); /* ISO-639-2/T language code */
606    MP4_SKIP_U16(p_ctx, "pre_defined");
607 
608    return STREAM_STATUS(p_ctx);
609 }
610 
611 /*****************************************************************************/
mp4_read_box_hdlr(VC_CONTAINER_T * p_ctx,int64_t size)612 static VC_CONTAINER_STATUS_T mp4_read_box_hdlr( VC_CONTAINER_T *p_ctx, int64_t size )
613 {
614    VC_CONTAINER_MODULE_T *module = p_ctx->priv->module;
615    VC_CONTAINER_TRACK_T *track = p_ctx->tracks[module->current_track];
616    uint32_t i, fourcc, string_size;
617    VC_CONTAINER_ES_TYPE_T es_type = VC_CONTAINER_ES_TYPE_UNKNOWN;
618 
619    if(size <= 24) return VC_CONTAINER_ERROR_CORRUPTED;
620 
621    MP4_SKIP_U8(p_ctx, "version");
622    MP4_SKIP_U24(p_ctx, "flags");
623 
624    MP4_SKIP_U32(p_ctx, "pre-defined");
625 
626    fourcc = MP4_READ_FOURCC(p_ctx, "handler_type");
627    if(fourcc == MP4_BOX_TYPE_VIDE) es_type = VC_CONTAINER_ES_TYPE_VIDEO;
628    if(fourcc == MP4_BOX_TYPE_SOUN) es_type = VC_CONTAINER_ES_TYPE_AUDIO;
629    if(fourcc == MP4_BOX_TYPE_TEXT) es_type = VC_CONTAINER_ES_TYPE_SUBPICTURE;
630    track->format->es_type = es_type;
631 
632    for(i = 0; i < 3; i++) MP4_SKIP_U32(p_ctx, "reserved");
633 
634    string_size = size;
635    if(module->brand == MP4_BRAND_QT)
636       string_size = MP4_READ_U8(p_ctx, "string_size");
637 
638    if(size < 0) return VC_CONTAINER_ERROR_CORRUPTED;
639    if(string_size > size) string_size = size;
640 
641    MP4_SKIP_STRING(p_ctx, string_size, "name");
642 
643    return STREAM_STATUS(p_ctx);
644 }
645 
646 /*****************************************************************************/
mp4_read_box_minf(VC_CONTAINER_T * p_ctx,int64_t size)647 static VC_CONTAINER_STATUS_T mp4_read_box_minf( VC_CONTAINER_T *p_ctx, int64_t size )
648 {
649    return mp4_read_boxes( p_ctx, size, MP4_BOX_TYPE_MINF);
650 }
651 
652 /*****************************************************************************/
mp4_read_box_vmhd(VC_CONTAINER_T * p_ctx,int64_t size)653 static VC_CONTAINER_STATUS_T mp4_read_box_vmhd( VC_CONTAINER_T *p_ctx, int64_t size )
654 {
655    MP4_SKIP_U8(p_ctx, "version");
656    MP4_SKIP_U24(p_ctx, "flags");
657 
658    MP4_SKIP_U16(p_ctx, "graphicsmode");
659    MP4_SKIP_U16(p_ctx, "opcolor");
660    MP4_SKIP_U16(p_ctx, "opcolor");
661    MP4_SKIP_U16(p_ctx, "opcolor");
662 
663    return STREAM_STATUS(p_ctx);
664 }
665 
666 /*****************************************************************************/
mp4_read_box_smhd(VC_CONTAINER_T * p_ctx,int64_t size)667 static VC_CONTAINER_STATUS_T mp4_read_box_smhd( VC_CONTAINER_T *p_ctx, int64_t size )
668 {
669    MP4_SKIP_U8(p_ctx, "version");
670    MP4_SKIP_U24(p_ctx, "flags");
671 
672    MP4_SKIP_U16(p_ctx, "balance");
673    MP4_SKIP_U16(p_ctx, "reserved");
674 
675    return STREAM_STATUS(p_ctx);
676 }
677 
678 /*****************************************************************************/
mp4_read_box_dinf(VC_CONTAINER_T * p_ctx,int64_t size)679 static VC_CONTAINER_STATUS_T mp4_read_box_dinf( VC_CONTAINER_T *p_ctx, int64_t size )
680 {
681    return mp4_read_boxes( p_ctx, size, MP4_BOX_TYPE_DINF);
682 }
683 
684 /*****************************************************************************/
mp4_read_box_dref(VC_CONTAINER_T * p_ctx,int64_t size)685 static VC_CONTAINER_STATUS_T mp4_read_box_dref( VC_CONTAINER_T *p_ctx, int64_t size )
686 {
687    MP4_SKIP_U8(p_ctx, "version");
688    MP4_SKIP_U24(p_ctx, "flags");
689 
690    MP4_SKIP_U32(p_ctx, "entry_count");
691 
692    return STREAM_STATUS(p_ctx);
693 }
694 
695 /*****************************************************************************/
mp4_read_box_stbl(VC_CONTAINER_T * p_ctx,int64_t size)696 static VC_CONTAINER_STATUS_T mp4_read_box_stbl( VC_CONTAINER_T *p_ctx, int64_t size )
697 {
698    return mp4_read_boxes( p_ctx, size, MP4_BOX_TYPE_STBL);
699 }
700 
701 /*****************************************************************************/
mp4_read_box_stsd(VC_CONTAINER_T * p_ctx,int64_t size)702 static VC_CONTAINER_STATUS_T mp4_read_box_stsd( VC_CONTAINER_T *p_ctx, int64_t size )
703 {
704    VC_CONTAINER_MODULE_T *module = p_ctx->priv->module;
705    VC_CONTAINER_TRACK_T *track = p_ctx->tracks[module->current_track];
706    VC_CONTAINER_STATUS_T status;
707    MP4_BOX_TYPE_T box_type;
708    int64_t box_size;
709    uint32_t count;
710 
711    MP4_SKIP_U8(p_ctx, "version");
712    MP4_SKIP_U24(p_ctx, "flags");
713 
714    count = MP4_READ_U32(p_ctx, "entry_count");
715    if(!count) return VC_CONTAINER_ERROR_CORRUPTED;
716 
717    status = mp4_read_box_header( p_ctx, size, &box_type, &box_size );
718    if(status != VC_CONTAINER_SUCCESS) return status;
719 
720    track->format->codec = mp4_box_type_to_codec(box_type);
721    if(!track->format->codec) track->format->codec = box_type;
722 
723    if(track->format->es_type == VC_CONTAINER_ES_TYPE_VIDEO) box_type = MP4_BOX_TYPE_VIDE;
724    if(track->format->es_type == VC_CONTAINER_ES_TYPE_AUDIO) box_type = MP4_BOX_TYPE_SOUN;
725    if(track->format->es_type == VC_CONTAINER_ES_TYPE_SUBPICTURE) box_type = MP4_BOX_TYPE_TEXT;
726    status = mp4_read_box_data( p_ctx, box_type, box_size, MP4_BOX_TYPE_STSD );
727    if(status != VC_CONTAINER_SUCCESS) return status;
728 
729    /* Special treatment for MPEG4 */
730    if(track->format->codec == VC_CONTAINER_CODEC_MP4A)
731    {
732       switch (track->priv->module->object_type_indication)
733       {
734       case MP4_MPEG4_AAC_LC_OBJECT_TYPE:
735       case MP4_MPEG2_AAC_LC_OBJECT_TYPE:
736          track->format->codec = VC_CONTAINER_CODEC_MP4A; break;
737       case MP4_MP3_OBJECT_TYPE:
738       case MP4_MPEG1_AUDIO_OBJECT_TYPE:
739       case MP4_KTF_MP3_OBJECT_TYPE:
740          track->format->codec = VC_CONTAINER_CODEC_MPGA; break;
741       case MP4_SKT_EVRC_2V1_OBJECT_TYPE:
742       case MP4_SKT_EVRC_OBJECT_TYPE:
743          track->format->codec = VC_CONTAINER_CODEC_EVRC; break;
744       case MP4_3GPP2_QCELP_OBJECT_TYPE:
745          track->format->codec = VC_CONTAINER_CODEC_QCELP; break;
746       default:
747          track->format->codec = VC_CONTAINER_CODEC_UNKNOWN; break;
748       }
749    }
750    else if(track->format->codec == VC_CONTAINER_CODEC_MP4V)
751    {
752       switch (track->priv->module->object_type_indication)
753       {
754       case MP4_MPEG4_VISUAL_OBJECT_TYPE:
755          track->format->codec = VC_CONTAINER_CODEC_MP4V; break;
756       case MP4_JPEG_OBJECT_TYPE:
757          track->format->codec = VC_CONTAINER_CODEC_JPEG; break;
758       case MP4_MPEG2_SP_OBJECT_TYPE:
759       case MP4_MPEG2_SNR_OBJECT_TYPE:
760       case MP4_MPEG2_AAC_LC_OBJECT_TYPE:
761       case MP4_MPEG2_MP_OBJECT_TYPE:
762          track->format->codec = VC_CONTAINER_CODEC_MP2V; break;
763       case MP4_MPEG1_VISUAL_OBJECT_TYPE:
764          track->format->codec = VC_CONTAINER_CODEC_MP1V; break;
765       default:
766          track->format->codec = VC_CONTAINER_CODEC_UNKNOWN; break;
767       }
768    }
769 
770    /* For some codecs we process the samples in batches to be more efficient */
771    if(codec_needs_batch_mode(track->format->codec))
772       track->priv->module->samples_batch_size = MP4_MAX_SAMPLES_BATCH_SIZE;
773 
774    /* Fix-up some of the data */
775    switch(track->format->codec)
776    {
777    case VC_CONTAINER_CODEC_ALAW:
778    case VC_CONTAINER_CODEC_MULAW:
779       track->format->type->audio.bits_per_sample = 8;
780       track->priv->module->sample_size = track->format->type->audio.channels;
781       break;
782    case VC_CONTAINER_CODEC_PCM_SIGNED_LE:
783    case VC_CONTAINER_CODEC_PCM_SIGNED_BE:
784       track->priv->module->sample_size = (track->format->type->audio.bits_per_sample + 7) /
785          8 * track->format->type->audio.channels;
786       break;
787    case VC_CONTAINER_CODEC_MP4A:
788       /* samplerate / channels is sometimes invalid so sanity check it using the codec config data */
789       if(track->format->extradata_size >= 2)
790       {
791          static unsigned int rate[] =
792          { 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
793            16000, 12000, 11025, 8000, 7350 };
794          unsigned int samplerate = 0, channels = 0;
795          uint8_t *p = track->format->extradata;
796          uint32_t index = (p[0] & 7) << 1 | (p[1] >> 7);
797          if(index == 15 && track->format->extradata_size >= 5)
798          {
799             samplerate = (p[1] & 0x7f) << 17 | (p[2] << 9) | (p[3] << 1) | (p[4] >> 7);
800             channels = (p[4] >> 3) & 15;
801          }
802          else if(index < 13)
803          {
804             samplerate = rate[index];
805             channels = (p[1] >> 3) & 15;;
806          }
807 
808          if(samplerate && samplerate != track->format->type->audio.sample_rate &&
809                2 * samplerate != track->format->type->audio.sample_rate)
810             track->format->type->audio.sample_rate = samplerate;
811          if(channels && channels != track->format->type->audio.channels &&
812                2 * channels != track->format->type->audio.channels)
813             track->format->type->audio.channels = channels;
814       }
815       break;
816    default: break;
817    }
818 
819    return VC_CONTAINER_SUCCESS;
820 }
821 
822 /*****************************************************************************/
mp4_cache_table(VC_CONTAINER_T * p_ctx,MP4_SAMPLE_TABLE_T table,uint32_t entries,int64_t size)823 static VC_CONTAINER_STATUS_T mp4_cache_table( VC_CONTAINER_T *p_ctx, MP4_SAMPLE_TABLE_T table,
824    uint32_t entries, int64_t size )
825 {
826    VC_CONTAINER_MODULE_T *module = p_ctx->priv->module;
827    VC_CONTAINER_TRACK_MODULE_T *track_module = p_ctx->tracks[module->current_track]->priv->module;
828    uint32_t available_entries, entries_size;
829 
830    if(size < 0) return VC_CONTAINER_ERROR_CORRUPTED;
831 
832    track_module->sample_table[table].offset = STREAM_POSITION(p_ctx);
833    track_module->sample_table[table].entries = entries;
834 
835    available_entries = size / track_module->sample_table[table].entry_size;
836    if(available_entries < entries)
837    {
838       LOG_DEBUG(p_ctx, "table has less entries than advertised (%i/%i)", available_entries, entries);
839       entries = available_entries;
840    }
841 
842    entries_size = entries * track_module->sample_table[table].entry_size;
843    size = vc_container_io_cache(p_ctx->priv->io, entries_size );
844    if(size != entries_size)
845    {
846       available_entries = size / track_module->sample_table[table].entry_size;
847       LOG_DEBUG(p_ctx, "cached less table entries than advertised (%i/%i)", available_entries, entries);
848       track_module->sample_table[table].entries = available_entries;
849    }
850 
851    return STREAM_STATUS(p_ctx);
852 }
853 
854 /*****************************************************************************/
mp4_read_box_stts(VC_CONTAINER_T * p_ctx,int64_t size)855 static VC_CONTAINER_STATUS_T mp4_read_box_stts( VC_CONTAINER_T *p_ctx, int64_t size )
856 {
857    uint32_t entries;
858 
859    MP4_SKIP_U8(p_ctx, "version");
860    MP4_SKIP_U24(p_ctx, "flags");
861 
862    entries = MP4_READ_U32(p_ctx, "entry_count");
863    return mp4_cache_table( p_ctx, MP4_SAMPLE_TABLE_STTS, entries, size );
864 }
865 
866 /*****************************************************************************/
mp4_read_box_ctts(VC_CONTAINER_T * p_ctx,int64_t size)867 static VC_CONTAINER_STATUS_T mp4_read_box_ctts( VC_CONTAINER_T *p_ctx, int64_t size )
868 {
869    uint32_t entries;
870 
871    MP4_SKIP_U8(p_ctx, "version");
872    MP4_SKIP_U24(p_ctx, "flags");
873 
874    entries = MP4_READ_U32(p_ctx, "entry_count");
875    return mp4_cache_table( p_ctx, MP4_SAMPLE_TABLE_CTTS, entries, size );
876 }
877 
878 /*****************************************************************************/
mp4_read_box_stsc(VC_CONTAINER_T * p_ctx,int64_t size)879 static VC_CONTAINER_STATUS_T mp4_read_box_stsc( VC_CONTAINER_T *p_ctx, int64_t size )
880 {
881    uint32_t entries;
882 
883    MP4_SKIP_U8(p_ctx, "version");
884    MP4_SKIP_U24(p_ctx, "flags");
885 
886    entries = MP4_READ_U32(p_ctx, "entry_count");
887    return mp4_cache_table( p_ctx, MP4_SAMPLE_TABLE_STSC, entries, size );
888 }
889 
890 /*****************************************************************************/
mp4_read_box_stsz(VC_CONTAINER_T * p_ctx,int64_t size)891 static VC_CONTAINER_STATUS_T mp4_read_box_stsz( VC_CONTAINER_T *p_ctx, int64_t size )
892 {
893    VC_CONTAINER_MODULE_T *module = p_ctx->priv->module;
894    VC_CONTAINER_TRACK_MODULE_T *track_module = p_ctx->tracks[module->current_track]->priv->module;
895    uint32_t entries;
896 
897    MP4_SKIP_U8(p_ctx, "version");
898    MP4_SKIP_U24(p_ctx, "flags");
899 
900    track_module->sample_size = READ_U32(p_ctx, "sample_size");
901    if(track_module->sample_size) return STREAM_STATUS(p_ctx);
902 
903    entries = MP4_READ_U32(p_ctx, "sample_count");
904    return mp4_cache_table( p_ctx, MP4_SAMPLE_TABLE_STSZ, entries, size );
905 }
906 
907 /*****************************************************************************/
mp4_read_box_stco(VC_CONTAINER_T * p_ctx,int64_t size)908 static VC_CONTAINER_STATUS_T mp4_read_box_stco( VC_CONTAINER_T *p_ctx, int64_t size )
909 {
910    uint32_t entries;
911 
912    MP4_SKIP_U8(p_ctx, "version");
913    MP4_SKIP_U24(p_ctx, "flags");
914 
915    entries = MP4_READ_U32(p_ctx, "entry_count");
916    return mp4_cache_table( p_ctx, MP4_SAMPLE_TABLE_STCO, entries, size );
917 }
918 
919 /*****************************************************************************/
mp4_read_box_co64(VC_CONTAINER_T * p_ctx,int64_t size)920 static VC_CONTAINER_STATUS_T mp4_read_box_co64( VC_CONTAINER_T *p_ctx, int64_t size )
921 {
922    uint32_t entries;
923 
924    MP4_SKIP_U8(p_ctx, "version");
925    MP4_SKIP_U24(p_ctx, "flags");
926 
927    entries = MP4_READ_U32(p_ctx, "entry_count");
928    return mp4_cache_table( p_ctx, MP4_SAMPLE_TABLE_CO64, entries, size );
929 }
930 
931 /*****************************************************************************/
mp4_read_box_stss(VC_CONTAINER_T * p_ctx,int64_t size)932 static VC_CONTAINER_STATUS_T mp4_read_box_stss( VC_CONTAINER_T *p_ctx, int64_t size )
933 {
934    uint32_t entries;
935 
936    MP4_SKIP_U8(p_ctx, "version");
937    MP4_SKIP_U24(p_ctx, "flags");
938 
939    entries = MP4_READ_U32(p_ctx, "entry_count");
940    return mp4_cache_table( p_ctx, MP4_SAMPLE_TABLE_STSS, entries, size );
941 }
942 
943 /*****************************************************************************/
mp4_read_esds_descriptor_header(VC_CONTAINER_T * p_ctx,int64_t * size,uint32_t * descriptor_length,uint8_t * descriptor_type)944 static VC_CONTAINER_STATUS_T mp4_read_esds_descriptor_header(VC_CONTAINER_T *p_ctx, int64_t *size,
945    uint32_t *descriptor_length, uint8_t *descriptor_type)
946 {
947    uint32_t byte, length = 0;
948 
949    if(*size <= 0) return VC_CONTAINER_ERROR_CORRUPTED;
950 
951    *descriptor_type = _READ_U8(p_ctx);
952    (*size)--;
953 
954    /* Read descriptor size */
955    while(*size)
956    {
957       byte = _READ_U8(p_ctx);
958       (*size)--;
959       length = (length << 7) | (byte&0x7F);
960       if(!(byte & 0x80)) break;
961    }
962 
963    if(*size <= 0 || length > *size)
964    {
965       LOG_FORMAT(p_ctx, "esds descriptor is corrupted");
966       return VC_CONTAINER_ERROR_CORRUPTED;
967    }
968 
969    *descriptor_length = length;
970    LOG_FORMAT(p_ctx, "esds descriptor %x, size %i", *descriptor_type, *descriptor_length);
971    return VC_CONTAINER_SUCCESS;
972 }
973 
974 /*****************************************************************************/
mp4_read_box_esds(VC_CONTAINER_T * p_ctx,int64_t size)975 static VC_CONTAINER_STATUS_T mp4_read_box_esds( VC_CONTAINER_T *p_ctx, int64_t size )
976 {
977    VC_CONTAINER_MODULE_T *module = p_ctx->priv->module;
978    VC_CONTAINER_TRACK_T *track = p_ctx->tracks[module->current_track];
979    VC_CONTAINER_STATUS_T status;
980    uint32_t descriptor_length;
981    uint8_t descriptor_type;
982 
983    MP4_SKIP_U8(p_ctx, "version");
984    MP4_SKIP_U24(p_ctx, "flags");
985 
986    status = mp4_read_esds_descriptor_header(p_ctx, &size, &descriptor_length, &descriptor_type);
987    if(status != VC_CONTAINER_SUCCESS) return status;
988 
989    if(descriptor_type == 0x3) /* ES descriptor */
990    {
991       uint8_t flags;
992 
993       MP4_SKIP_U16(p_ctx, "es_id");
994       flags = MP4_READ_U8(p_ctx, "flags");
995 
996       if(flags & 0x80) /* Stream dependence */
997          MP4_SKIP_U16(p_ctx, "depend_on_es_id");
998 
999       if(flags & 0x40) /* URL */
1000       {
1001          uint32_t url_size = MP4_READ_U8(p_ctx, "url_size");
1002          MP4_SKIP_STRING(p_ctx, url_size, "url");
1003       }
1004 
1005       if(flags & 0x20) /* OCR_stream*/
1006          MP4_SKIP_U16(p_ctx, "OCR_es_id");
1007 
1008       status = mp4_read_esds_descriptor_header(p_ctx, &size, &descriptor_length, &descriptor_type);
1009       if(status != VC_CONTAINER_SUCCESS) return status;
1010    }
1011 
1012    if(descriptor_type == 0x4) /* Decoder Config descriptor */
1013    {
1014       track->priv->module->object_type_indication = MP4_READ_U8(p_ctx, "object_type_indication");
1015       MP4_SKIP_U8(p_ctx, "stream_type");
1016       MP4_SKIP_U24(p_ctx, "buffer_size_db");
1017       MP4_SKIP_U32(p_ctx, "max_bitrate");
1018       track->format->bitrate = MP4_READ_U32(p_ctx, "avg_bitrate");
1019 
1020       if(size <= 0 || descriptor_length <= 13) return STREAM_STATUS(p_ctx);
1021 
1022       status = mp4_read_esds_descriptor_header(p_ctx, &size, &descriptor_length, &descriptor_type);
1023       if(status != VC_CONTAINER_SUCCESS) return status;
1024       if(descriptor_type == 0x05 && descriptor_length)
1025       {
1026          status = vc_container_track_allocate_extradata(p_ctx, track, descriptor_length);
1027          if(status != VC_CONTAINER_SUCCESS) return status;
1028          track->format->extradata_size = MP4_READ_BYTES(p_ctx, track->format->extradata, descriptor_length);
1029       }
1030    }
1031 
1032    return STREAM_STATUS(p_ctx);
1033 }
1034 
1035 /*****************************************************************************/
mp4_read_box_vide(VC_CONTAINER_T * p_ctx,int64_t size)1036 static VC_CONTAINER_STATUS_T mp4_read_box_vide( VC_CONTAINER_T *p_ctx, int64_t size )
1037 {
1038    VC_CONTAINER_MODULE_T *module = p_ctx->priv->module;
1039    VC_CONTAINER_TRACK_T *track = p_ctx->tracks[module->current_track];
1040    unsigned int i;
1041 
1042    for(i = 0; i < 6; i++) MP4_SKIP_U8(p_ctx, "reserved");
1043    MP4_SKIP_U16(p_ctx, "data_reference_index");
1044 
1045    MP4_SKIP_U16(p_ctx, "pre_defined");
1046    MP4_SKIP_U16(p_ctx, "reserved");
1047    for(i = 0; i < 3; i++) MP4_SKIP_U32(p_ctx, "pre_defined");
1048    track->format->type->video.width = MP4_READ_U16(p_ctx, "width");
1049    track->format->type->video.height = MP4_READ_U16(p_ctx, "height");
1050    MP4_SKIP_U32(p_ctx, "horizresolution"); /* dpi */
1051    MP4_SKIP_U32(p_ctx, "vertresolution"); /* dpi */
1052    MP4_SKIP_U32(p_ctx, "reserved");
1053    MP4_SKIP_U16(p_ctx, "frame_count");
1054    MP4_SKIP_BYTES(p_ctx, 32);
1055    MP4_SKIP_U16(p_ctx, "depth");
1056    MP4_SKIP_U16(p_ctx, "pre_defined");
1057 
1058    if(size > 0)
1059       return mp4_read_boxes( p_ctx, size, MP4_BOX_TYPE_VIDE );
1060 
1061    return STREAM_STATUS(p_ctx);
1062 }
1063 
1064 /*****************************************************************************/
mp4_read_box_vide_avcC(VC_CONTAINER_T * p_ctx,int64_t size)1065 static VC_CONTAINER_STATUS_T mp4_read_box_vide_avcC( VC_CONTAINER_T *p_ctx, int64_t size )
1066 {
1067    VC_CONTAINER_MODULE_T *module = p_ctx->priv->module;
1068    VC_CONTAINER_TRACK_T *track = p_ctx->tracks[module->current_track];
1069    VC_CONTAINER_STATUS_T status;
1070 
1071    if(track->format->codec != VC_CONTAINER_CODEC_H264 || size <= 0)
1072       return VC_CONTAINER_ERROR_CORRUPTED;
1073 
1074    track->format->codec_variant = VC_FOURCC('a','v','c','C');
1075 
1076    status = vc_container_track_allocate_extradata(p_ctx, track, (unsigned int)size);
1077    if(status != VC_CONTAINER_SUCCESS) return status;
1078    track->format->extradata_size = READ_BYTES(p_ctx, track->format->extradata, size);
1079 
1080    return STREAM_STATUS(p_ctx);
1081 }
1082 
1083 /*****************************************************************************/
mp4_read_box_vide_d263(VC_CONTAINER_T * p_ctx,int64_t size)1084 static VC_CONTAINER_STATUS_T mp4_read_box_vide_d263( VC_CONTAINER_T *p_ctx, int64_t size )
1085 {
1086    MP4_SKIP_FOURCC(p_ctx, "vendor");
1087    MP4_SKIP_U8(p_ctx, "version");
1088    MP4_SKIP_U8(p_ctx, "level");
1089    MP4_SKIP_U8(p_ctx, "profile");
1090    return STREAM_STATUS(p_ctx);
1091 }
1092 
1093 /*****************************************************************************/
mp4_read_box_soun(VC_CONTAINER_T * p_ctx,int64_t size)1094 static VC_CONTAINER_STATUS_T mp4_read_box_soun( VC_CONTAINER_T *p_ctx, int64_t size )
1095 {
1096    VC_CONTAINER_MODULE_T *module = p_ctx->priv->module;
1097    VC_CONTAINER_TRACK_T *track = p_ctx->tracks[module->current_track];
1098    unsigned int i, version = 0;
1099 
1100    for(i = 0; i < 6; i++) MP4_SKIP_U8(p_ctx, "reserved");
1101    MP4_SKIP_U16(p_ctx, "data_reference_index");
1102 
1103    version = MP4_READ_U16(p_ctx, "version");
1104    MP4_SKIP_U16(p_ctx, "revision_level");
1105    MP4_SKIP_U32(p_ctx, "vendor");
1106 
1107    track->format->type->audio.channels = MP4_READ_U16(p_ctx, "channelcount");
1108    track->format->type->audio.bits_per_sample = MP4_READ_U16(p_ctx, "samplesize");
1109    MP4_SKIP_U16(p_ctx, "pre_defined");
1110    MP4_SKIP_U16(p_ctx, "reserved");
1111    track->format->type->audio.sample_rate = MP4_READ_U16(p_ctx, "samplerate");
1112    MP4_SKIP_U16(p_ctx, "samplerate_fp_low");
1113 
1114    if(version == 1)
1115    {
1116       MP4_SKIP_U32(p_ctx, "samples_per_packet");
1117       MP4_SKIP_U32(p_ctx, "bytes_per_packet");
1118       MP4_SKIP_U32(p_ctx, "bytes_per_frame");
1119       MP4_SKIP_U32(p_ctx, "bytes_per_sample");
1120    }
1121 
1122    if(size > 0)
1123       return mp4_read_box( p_ctx, size, MP4_BOX_TYPE_SOUN );
1124 
1125    return STREAM_STATUS(p_ctx);
1126 }
1127 
1128 /*****************************************************************************/
mp4_read_box_soun_damr(VC_CONTAINER_T * p_ctx,int64_t size)1129 static VC_CONTAINER_STATUS_T mp4_read_box_soun_damr( VC_CONTAINER_T *p_ctx, int64_t size )
1130 {
1131    VC_CONTAINER_MODULE_T *module = p_ctx->priv->module;
1132    VC_CONTAINER_TRACK_T *track = p_ctx->tracks[module->current_track];
1133 
1134    MP4_SKIP_FOURCC(p_ctx, "vendor");
1135    MP4_SKIP_U8(p_ctx, "version");
1136    MP4_SKIP_U8(p_ctx, "mode_set");
1137    MP4_SKIP_U8(p_ctx, "mode_change_period");
1138    MP4_SKIP_U8(p_ctx, "frame_per_second");
1139 
1140    track->format->type->audio.channels = 1;
1141    if(track->format->codec == VC_CONTAINER_CODEC_AMRNB)
1142       track->format->type->audio.sample_rate = 8000;
1143    else if(track->format->codec == VC_CONTAINER_CODEC_AMRWB)
1144       track->format->type->audio.sample_rate = 16000;
1145 
1146    return STREAM_STATUS(p_ctx);
1147 }
1148 
1149 /*****************************************************************************/
mp4_read_box_soun_dawp(VC_CONTAINER_T * p_ctx,int64_t size)1150 static VC_CONTAINER_STATUS_T mp4_read_box_soun_dawp( VC_CONTAINER_T *p_ctx, int64_t size )
1151 {
1152    VC_CONTAINER_MODULE_T *module = p_ctx->priv->module;
1153    VC_CONTAINER_TRACK_T *track = p_ctx->tracks[module->current_track];
1154 
1155    MP4_SKIP_FOURCC(p_ctx, "vendor");
1156    MP4_SKIP_U8(p_ctx, "version");
1157 
1158    track->format->type->audio.channels = 2;
1159    track->format->type->audio.sample_rate = 16000;
1160 
1161    return STREAM_STATUS(p_ctx);
1162 }
1163 
1164 /*****************************************************************************/
mp4_read_box_soun_devc(VC_CONTAINER_T * p_ctx,int64_t size)1165 static VC_CONTAINER_STATUS_T mp4_read_box_soun_devc( VC_CONTAINER_T *p_ctx, int64_t size )
1166 {
1167    VC_CONTAINER_MODULE_T *module = p_ctx->priv->module;
1168    VC_CONTAINER_TRACK_T *track = p_ctx->tracks[module->current_track];
1169 
1170    MP4_SKIP_FOURCC(p_ctx, "vendor");
1171    MP4_SKIP_U8(p_ctx, "version");
1172    MP4_SKIP_U8(p_ctx, "samples_per_frame");
1173 
1174    track->format->type->audio.channels = 1;
1175    track->format->type->audio.sample_rate = 8000;
1176 
1177    return STREAM_STATUS(p_ctx);
1178 }
1179 
1180 /*****************************************************************************/
mp4_read_box_soun_wave(VC_CONTAINER_T * p_ctx,int64_t size)1181 static VC_CONTAINER_STATUS_T mp4_read_box_soun_wave( VC_CONTAINER_T *p_ctx, int64_t size )
1182 {
1183    return mp4_read_boxes( p_ctx, size, MP4_BOX_TYPE_SOUN);
1184 }
1185 
1186 /*****************************************************************************/
mp4_read_box_text(VC_CONTAINER_T * p_ctx,int64_t size)1187 static VC_CONTAINER_STATUS_T mp4_read_box_text( VC_CONTAINER_T *p_ctx, int64_t size )
1188 {
1189    VC_CONTAINER_MODULE_T *module = p_ctx->priv->module;
1190    VC_CONTAINER_PARAM_UNUSED(module);
1191 
1192    /* TODO */if(1) return VC_CONTAINER_ERROR_FAILED;
1193 
1194    if(size > 0)
1195       return mp4_read_box( p_ctx, size, MP4_BOX_TYPE_TEXT );
1196 
1197    return STREAM_STATUS(p_ctx);
1198 }
1199 
1200 /*****************************************************************************/
mp4_reader_close(VC_CONTAINER_T * p_ctx)1201 static VC_CONTAINER_STATUS_T mp4_reader_close( VC_CONTAINER_T *p_ctx )
1202 {
1203    VC_CONTAINER_MODULE_T *module = p_ctx->priv->module;
1204    unsigned int i;
1205 
1206    for(i = 0; i < p_ctx->tracks_num; i++)
1207       vc_container_free_track(p_ctx, p_ctx->tracks[i]);
1208    free(module);
1209    return VC_CONTAINER_SUCCESS;
1210 }
1211 
1212 /*****************************************************************************/
1213 #ifdef ENABLE_MP4_READER_LOG_STATE
mp4_log_state(VC_CONTAINER_T * p_ctx,MP4_READER_STATE_T * state)1214 static void mp4_log_state( VC_CONTAINER_T *p_ctx, MP4_READER_STATE_T *state )
1215 {
1216    VC_CONTAINER_PARAM_UNUSED(p_ctx);
1217 
1218    LOG_DEBUG(p_ctx, "state:");
1219    LOG_DEBUG(p_ctx, "duration: %i, pts %i, dts %i", (int)state->duration,
1220              (int)state->pts, (int)state->dts);
1221    LOG_DEBUG(p_ctx, "sample: %i, offset %i, sample_offset %i, sample_size %i",
1222              state->sample, (int)state->offset, state->sample_offset,
1223              state->sample_size);
1224    LOG_DEBUG(p_ctx, "sample_duration: %i, count %i",
1225              state->sample_duration, state->sample_duration_count);
1226    LOG_DEBUG(p_ctx, "sample_composition_offset: %i, count %i",
1227              state->sample_composition_offset, state->sample_composition_count);
1228    LOG_DEBUG(p_ctx, "next_sync_sample: %i, keyframe %i",
1229              state->next_sync_sample, state->keyframe);
1230    LOG_DEBUG(p_ctx, "samples_per_chunk: %i, chunks %i, samples_in_chunk %i",
1231              state->samples_per_chunk, state->chunks, state->samples_in_chunk);
1232    LOG_DEBUG(p_ctx, "MP4_SAMPLE_TABLE_STTS %i", state->sample_table[MP4_SAMPLE_TABLE_STTS].entry);
1233    LOG_DEBUG(p_ctx, "MP4_SAMPLE_TABLE_STSZ %i", state->sample_table[MP4_SAMPLE_TABLE_STSZ].entry);
1234    LOG_DEBUG(p_ctx, "MP4_SAMPLE_TABLE_STSC %i", state->sample_table[MP4_SAMPLE_TABLE_STSC].entry);
1235    LOG_DEBUG(p_ctx, "MP4_SAMPLE_TABLE_STCO %i", state->sample_table[MP4_SAMPLE_TABLE_STCO].entry);
1236    LOG_DEBUG(p_ctx, "MP4_SAMPLE_TABLE_CO64 %i", state->sample_table[MP4_SAMPLE_TABLE_CO64].entry);
1237    LOG_DEBUG(p_ctx, "MP4_SAMPLE_TABLE_CTTS %i", state->sample_table[MP4_SAMPLE_TABLE_CTTS].entry);
1238 }
1239 #endif /* ENABLE_MP4_READER_LOG_STATE */
1240 
1241 /*****************************************************************************/
mp4_seek_sample_table(VC_CONTAINER_T * p_ctx,VC_CONTAINER_TRACK_MODULE_T * track_module,MP4_READER_STATE_T * state,MP4_SAMPLE_TABLE_T table)1242 static VC_CONTAINER_STATUS_T mp4_seek_sample_table( VC_CONTAINER_T *p_ctx,
1243    VC_CONTAINER_TRACK_MODULE_T *track_module, MP4_READER_STATE_T *state,
1244    MP4_SAMPLE_TABLE_T table)
1245 {
1246    int64_t seek_offset;
1247 
1248    /* Seek to the next entry in the table */
1249    if(state->sample_table[table].entry >= track_module->sample_table[table].entries)
1250       return VC_CONTAINER_ERROR_EOS;
1251 
1252    seek_offset = track_module->sample_table[table].offset +
1253       track_module->sample_table[table].entry_size * state->sample_table[table].entry;
1254 
1255    return SEEK(p_ctx, seek_offset);
1256 }
1257 
1258 /*****************************************************************************/
mp4_read_sample_table(VC_CONTAINER_T * p_ctx,VC_CONTAINER_TRACK_MODULE_T * track_module,MP4_READER_STATE_T * state,MP4_SAMPLE_TABLE_T table,unsigned int seek)1259 static VC_CONTAINER_STATUS_T mp4_read_sample_table( VC_CONTAINER_T *p_ctx,
1260    VC_CONTAINER_TRACK_MODULE_T *track_module, MP4_READER_STATE_T *state,
1261    MP4_SAMPLE_TABLE_T table, unsigned int seek)
1262 {
1263    uint32_t value;
1264 
1265    if(table == MP4_SAMPLE_TABLE_STSZ && track_module->sample_size)
1266    {
1267       state->sample_size = track_module->sample_size;
1268       return state->status;
1269    }
1270 
1271    /* CO64 support */
1272    if(table == MP4_SAMPLE_TABLE_STCO &&
1273       track_module->sample_table[MP4_SAMPLE_TABLE_CO64].entries)
1274       table = MP4_SAMPLE_TABLE_CO64;
1275 
1276    /* Seek to the next entry in the table */
1277    if(seek)
1278    {
1279       state->status = mp4_seek_sample_table( p_ctx, track_module, state, table );
1280       if(state->status != VC_CONTAINER_SUCCESS) return state->status;
1281    }
1282 
1283    switch(table)
1284    {
1285    case MP4_SAMPLE_TABLE_STSZ:
1286       state->sample_size = _READ_U32(p_ctx);
1287       state->status = STREAM_STATUS(p_ctx);
1288       break;
1289 
1290    case MP4_SAMPLE_TABLE_STTS:
1291       state->sample_duration_count = _READ_U32(p_ctx);
1292       state->sample_duration = _READ_U32(p_ctx);
1293       state->status = STREAM_STATUS(p_ctx);
1294       if(state->status != VC_CONTAINER_SUCCESS) break;
1295       if(!state->sample_duration_count) state->status = VC_CONTAINER_ERROR_CORRUPTED;
1296       break;
1297 
1298    case MP4_SAMPLE_TABLE_CTTS:
1299       state->sample_composition_count = _READ_U32(p_ctx);
1300       state->sample_composition_offset = _READ_U32(p_ctx); /* Converted to signed */
1301       state->status = STREAM_STATUS(p_ctx);
1302       if(state->status != VC_CONTAINER_SUCCESS) break;
1303       if(!state->sample_composition_count) state->status = VC_CONTAINER_ERROR_CORRUPTED;
1304       break;
1305 
1306    case MP4_SAMPLE_TABLE_STSC:
1307       state->chunks = _READ_U32(p_ctx);
1308       state->samples_per_chunk = _READ_U32(p_ctx);
1309       _SKIP_U32(p_ctx);
1310       state->status = STREAM_STATUS(p_ctx);
1311       if(state->status != VC_CONTAINER_SUCCESS) break;
1312 
1313       if(state->sample_table[table].entry + 1 <
1314          track_module->sample_table[MP4_SAMPLE_TABLE_STSC].entries) value = _READ_U32(p_ctx);
1315       else value = -1;
1316 
1317       if(!state->chunks || !state->samples_per_chunk || state->chunks >= value )
1318       {state->status = VC_CONTAINER_ERROR_CORRUPTED; break;}
1319       state->chunks = value - state->chunks;
1320       state->samples_in_chunk = state->samples_per_chunk;
1321       break;
1322 
1323    case MP4_SAMPLE_TABLE_STCO:
1324    case MP4_SAMPLE_TABLE_CO64:
1325       state->offset = table == MP4_SAMPLE_TABLE_STCO ? _READ_U32(p_ctx) : _READ_U64(p_ctx);
1326       state->status = STREAM_STATUS(p_ctx);
1327       if(state->status != VC_CONTAINER_SUCCESS) break;
1328       if(!state->offset) state->status = VC_CONTAINER_ERROR_CORRUPTED;
1329       state->samples_in_chunk = state->samples_per_chunk;
1330       break;
1331 
1332    case MP4_SAMPLE_TABLE_STSS:
1333       state->next_sync_sample = _READ_U32(p_ctx);
1334       state->status = STREAM_STATUS(p_ctx);
1335       break;
1336 
1337    default: break;
1338    }
1339 
1340    state->sample_table[table].entry++;
1341    return state->status;
1342 }
1343 
1344 /*****************************************************************************/
mp4_read_sample_header(VC_CONTAINER_T * p_ctx,uint32_t track,MP4_READER_STATE_T * state)1345 static VC_CONTAINER_STATUS_T mp4_read_sample_header( VC_CONTAINER_T *p_ctx, uint32_t track,
1346    MP4_READER_STATE_T *state )
1347 {
1348    VC_CONTAINER_TRACK_MODULE_T *track_module = p_ctx->tracks[track]->priv->module;
1349 
1350    if(state->status != VC_CONTAINER_SUCCESS) return state->status;
1351 
1352    if(state->sample_offset < state->sample_size)
1353       return state->status; /* We still have data left from the current sample */
1354 
1355    /* Switch to the next sample */
1356    state->offset += state->sample_size;
1357    state->sample_offset = 0;
1358    state->sample_size = 0;
1359    state->sample++;
1360 
1361    if(!state->samples_in_chunk)
1362    {
1363       /* We're switching to the next chunk */
1364       if(!state->chunks)
1365       {
1366          /* Seek to the next entry in the STSC */
1367          state->status = mp4_read_sample_table( p_ctx, track_module, state, MP4_SAMPLE_TABLE_STSC, 1 );
1368          if(state->status != VC_CONTAINER_SUCCESS) goto error;
1369       }
1370 
1371       /* Get the offset of the new chunk */
1372       state->status = mp4_read_sample_table( p_ctx, track_module, state, MP4_SAMPLE_TABLE_STCO, 1 );
1373       if(state->status != VC_CONTAINER_SUCCESS) goto error;
1374 
1375       state->chunks--;
1376    }
1377    state->samples_in_chunk--;
1378 
1379    /* Get the new sample size */
1380    state->status = mp4_read_sample_table( p_ctx, track_module, state, MP4_SAMPLE_TABLE_STSZ, 1 );
1381    if(state->status != VC_CONTAINER_SUCCESS) goto error;
1382 
1383    /* Get the timestamp */
1384    if(track_module->timescale)
1385       state->pts = state->dts = state->duration * 1000000 / track_module->timescale;
1386    if(!state->sample_duration_count)
1387    {
1388       state->status = mp4_read_sample_table( p_ctx, track_module, state, MP4_SAMPLE_TABLE_STTS, 1 );
1389       if(state->status != VC_CONTAINER_SUCCESS) goto error;
1390    }
1391    state->sample_duration_count--;
1392 
1393    /* Get the composition time */
1394    if(track_module->sample_table[MP4_SAMPLE_TABLE_CTTS].entries)
1395    {
1396       if(!state->sample_composition_count)
1397       {
1398          state->status = mp4_read_sample_table( p_ctx, track_module, state, MP4_SAMPLE_TABLE_CTTS, 1 );
1399          if(state->status != VC_CONTAINER_SUCCESS) goto error;
1400       }
1401       if(track_module->timescale)
1402          state->pts = (state->duration + state->sample_composition_offset) * 1000000 / track_module->timescale;
1403       state->sample_composition_count--;
1404    }
1405    state->duration += state->sample_duration;
1406 
1407    /* Get the keyframe flag */
1408    if(state->sample_table[MP4_SAMPLE_TABLE_STSS].entry <
1409          track_module->sample_table[MP4_SAMPLE_TABLE_STSS].entries &&
1410       !state->next_sync_sample)
1411    {
1412       mp4_read_sample_table( p_ctx, track_module, state, MP4_SAMPLE_TABLE_STSS, 1 );
1413       state->status = VC_CONTAINER_SUCCESS; /* This isn't a critical error */
1414    }
1415 
1416    state->keyframe =
1417       track_module->sample_table[MP4_SAMPLE_TABLE_STSS].entries &&
1418       state->sample == state->next_sync_sample;
1419    if(state->keyframe)
1420       state->next_sync_sample = 0;
1421 
1422    /* Try to batch several samples together if requested. We'll always stop at the chunk boundary */
1423    if(track_module->samples_batch_size)
1424    {
1425       uint32_t size = state->sample_size;
1426       while(state->samples_in_chunk && size < track_module->samples_batch_size)
1427       {
1428          if(mp4_read_sample_table( p_ctx, track_module, state, MP4_SAMPLE_TABLE_STSZ, 1 )) break;
1429 
1430          if(!state->sample_duration_count)
1431             if(mp4_read_sample_table( p_ctx, track_module, state, MP4_SAMPLE_TABLE_STTS, 1 )) break;
1432 
1433          state->sample_duration_count--;
1434          state->duration += state->sample_duration;
1435 
1436          size += state->sample_size;
1437          state->samples_in_chunk--;
1438          state->sample++;
1439       }
1440       state->sample_size = size;
1441    }
1442 
1443 #ifdef ENABLE_MP4_READER_LOG_STATE
1444    mp4_log_state(p_ctx, state);
1445 #endif
1446 
1447  error:
1448    return state->status;
1449 }
1450 
1451 /*****************************************************************************/
mp4_read_sample_data(VC_CONTAINER_T * p_ctx,uint32_t track,MP4_READER_STATE_T * state,uint8_t * data,unsigned int * data_size)1452 static VC_CONTAINER_STATUS_T mp4_read_sample_data( VC_CONTAINER_T *p_ctx, uint32_t track,
1453    MP4_READER_STATE_T *state, uint8_t *data, unsigned int *data_size )
1454 {
1455    VC_CONTAINER_STATUS_T status;
1456    unsigned int size = state->sample_size - state->sample_offset;
1457 
1458    if(state->status != VC_CONTAINER_SUCCESS) return state->status;
1459 
1460    if(data_size && *data_size < size) size = *data_size;
1461 
1462    if(data)
1463    {
1464       state->status = SEEK(p_ctx, state->offset + state->sample_offset);
1465       if(state->status != VC_CONTAINER_SUCCESS) return state->status;
1466 
1467       size = READ_BYTES(p_ctx, data, size);
1468    }
1469    state->sample_offset += size;
1470 
1471    if(data_size) *data_size = size;
1472    state->status = STREAM_STATUS(p_ctx);
1473    if(state->status != VC_CONTAINER_SUCCESS) return state->status;
1474 
1475    status = state->status;
1476 
1477    /* Switch to the start of the next sample */
1478    if(state->sample_offset >= state->sample_size)
1479       mp4_read_sample_header(p_ctx, track, state);
1480 
1481    return status;
1482 }
1483 
1484 /*****************************************************************************/
mp4_reader_read(VC_CONTAINER_T * p_ctx,VC_CONTAINER_PACKET_T * packet,uint32_t flags)1485 static VC_CONTAINER_STATUS_T mp4_reader_read( VC_CONTAINER_T *p_ctx,
1486                                               VC_CONTAINER_PACKET_T *packet, uint32_t flags )
1487 {
1488    VC_CONTAINER_TRACK_MODULE_T *track_module;
1489    VC_CONTAINER_STATUS_T status;
1490    MP4_READER_STATE_T *state;
1491    uint32_t i, track;
1492    unsigned int data_size;
1493    uint8_t *data = 0;
1494    int64_t offset;
1495 
1496    /* Select the track to read from. If no specific track is requested by the caller, this
1497     * will be the track to which the next bit of data in the mdat belongs to */
1498    if(!(flags & VC_CONTAINER_READ_FLAG_FORCE_TRACK))
1499    {
1500       for(i = 0, track = 0, offset = -1; i < p_ctx->tracks_num; i++)
1501       {
1502          track_module = p_ctx->tracks[i]->priv->module;
1503 
1504          /* Ignore tracks which have no more readable data */
1505          if(track_module->state.status != VC_CONTAINER_SUCCESS) continue;
1506 
1507          if(offset >= 0 && track_module->state.offset >= offset) continue;
1508          offset = track_module->state.offset;
1509          track = i;
1510       }
1511    }
1512    else track = packet->track;
1513 
1514    if(track >= p_ctx->tracks_num) return VC_CONTAINER_ERROR_INVALID_ARGUMENT;
1515 
1516    track_module = p_ctx->tracks[track]->priv->module;
1517    state = &track_module->state;
1518 
1519    status = mp4_read_sample_header(p_ctx, track, state);
1520    if(status != VC_CONTAINER_SUCCESS) return status;
1521 
1522    if(!packet) /* Skip packet */
1523       return mp4_read_sample_data(p_ctx, track, state, 0, 0);
1524 
1525    packet->dts = state->dts;
1526    packet->pts = state->pts;
1527    packet->flags = VC_CONTAINER_PACKET_FLAG_FRAME_END;
1528    if(state->keyframe) packet->flags |= VC_CONTAINER_PACKET_FLAG_KEYFRAME;
1529    if(!state->sample_offset) packet->flags |= VC_CONTAINER_PACKET_FLAG_FRAME_START;
1530    packet->track = track;
1531    packet->frame_size = state->sample_size;
1532    packet->size = state->sample_size - state->sample_offset;
1533 
1534    if(flags & VC_CONTAINER_READ_FLAG_SKIP)
1535       return mp4_read_sample_data(p_ctx, track, state, 0, 0);
1536    else if((flags & VC_CONTAINER_READ_FLAG_INFO) || !packet->data)
1537       return VC_CONTAINER_SUCCESS;
1538 
1539    data = packet->data;
1540    data_size = packet->buffer_size;
1541 
1542    status = mp4_read_sample_data(p_ctx, track, state, data, &data_size);
1543    if(status != VC_CONTAINER_SUCCESS)
1544    {
1545       /* FIXME */
1546       return status;
1547    }
1548 
1549    packet->size = data_size;
1550    if(state->sample_offset) //?
1551       packet->flags &= ~VC_CONTAINER_PACKET_FLAG_FRAME_END;
1552 
1553    return status;
1554 }
1555 
1556 /*****************************************************************************/
mp4_find_sample(VC_CONTAINER_T * p_ctx,uint32_t track,MP4_READER_STATE_T * state,int64_t seek_time,VC_CONTAINER_STATUS_T * p_status)1557 static uint32_t mp4_find_sample( VC_CONTAINER_T *p_ctx, uint32_t track,
1558    MP4_READER_STATE_T *state, int64_t seek_time, VC_CONTAINER_STATUS_T *p_status )
1559 {
1560    VC_CONTAINER_TRACK_MODULE_T *track_module = p_ctx->tracks[track]->priv->module;
1561    VC_CONTAINER_STATUS_T status = VC_CONTAINER_SUCCESS;
1562    uint32_t sample = 0, sample_duration_count;
1563    int64_t sample_duration, seek_time_up = seek_time + 1;
1564    unsigned int i;
1565    VC_CONTAINER_PARAM_UNUSED(state);
1566 
1567    seek_time = seek_time * track_module->timescale / 1000000;
1568    /* We also need to check against the time rounded up to account for
1569     * rounding errors in the timestamp (because of the timescale conversion) */
1570    seek_time_up = seek_time_up * track_module->timescale / 1000000;
1571 
1572    status = SEEK(p_ctx, track_module->sample_table[MP4_SAMPLE_TABLE_STTS].offset);
1573    if(status != VC_CONTAINER_SUCCESS) goto end;
1574 
1575    /* Find the sample which corresponds to the requested time */
1576    for(i = 0; i < track_module->sample_table[MP4_SAMPLE_TABLE_STTS].entries; i++)
1577    {
1578       sample_duration_count = _READ_U32(p_ctx);
1579       sample_duration = _READ_U32(p_ctx);
1580       status = STREAM_STATUS(p_ctx);
1581       if(status != VC_CONTAINER_SUCCESS) break;
1582 
1583       if(sample_duration_count * sample_duration <= seek_time)
1584       {
1585          seek_time -= sample_duration_count * sample_duration;
1586          seek_time_up -= sample_duration_count * sample_duration;
1587          sample += sample_duration_count;
1588          continue;
1589       }
1590       if(!sample_duration) break;
1591 
1592       seek_time /= sample_duration;
1593       seek_time_up /= sample_duration;
1594       sample += MAX(seek_time, seek_time_up);
1595       break;
1596    }
1597 
1598  end:
1599    if(p_status) *p_status = status;
1600    return sample;
1601 }
1602 
1603 /*****************************************************************************/
mp4_seek_track(VC_CONTAINER_T * p_ctx,uint32_t track,MP4_READER_STATE_T * state,uint32_t sample)1604 static VC_CONTAINER_STATUS_T mp4_seek_track( VC_CONTAINER_T *p_ctx, uint32_t track,
1605    MP4_READER_STATE_T *state, uint32_t sample )
1606 {
1607    VC_CONTAINER_TRACK_MODULE_T *track_module = p_ctx->tracks[track]->priv->module;
1608    uint32_t chunk = 0, samples;
1609    unsigned int i;
1610 
1611    memset(state, 0, sizeof(*state));
1612 
1613    /* Find the right chunk */
1614    for(i = 0, samples = sample; i < track_module->sample_table[MP4_SAMPLE_TABLE_STSC].entries; i++)
1615    {
1616       state->status = mp4_read_sample_table( p_ctx, track_module, state, MP4_SAMPLE_TABLE_STSC, 1 );
1617       if(state->status != VC_CONTAINER_SUCCESS) goto error;
1618 
1619       if(state->chunks * state->samples_per_chunk <= samples)
1620       {
1621          samples -= state->chunks * state->samples_per_chunk;
1622          chunk += state->chunks;
1623          continue;
1624       }
1625 
1626       while(samples >= state->samples_per_chunk)
1627       {
1628          samples -= state->samples_per_chunk;
1629          state->chunks--;
1630          chunk++;
1631       }
1632 
1633       state->chunks--;
1634       break;
1635    }
1636 
1637    /* Get the offset of the selected chunk */
1638    state->sample_table[MP4_SAMPLE_TABLE_STCO].entry = chunk;
1639    state->sample_table[MP4_SAMPLE_TABLE_CO64].entry = chunk;
1640    state->status = mp4_read_sample_table( p_ctx, track_module, state, MP4_SAMPLE_TABLE_STCO, 1 );
1641    if(state->status != VC_CONTAINER_SUCCESS) goto error;
1642 
1643    /* Find the sample offset within the chunk */
1644    state->sample_table[MP4_SAMPLE_TABLE_STSZ].entry = sample - samples;
1645    for(i = 0; i < samples; i++)
1646    {
1647       state->status = mp4_read_sample_table( p_ctx, track_module, state, MP4_SAMPLE_TABLE_STSZ, !i );
1648       if(state->status != VC_CONTAINER_SUCCESS) goto error;
1649       state->offset += state->sample_size;
1650       state->samples_in_chunk--;
1651    }
1652 
1653    /* Get the timestamp */
1654    for(i = 0, samples = sample; i < track_module->sample_table[MP4_SAMPLE_TABLE_STTS].entries; i++)
1655    {
1656       state->status = mp4_read_sample_table( p_ctx, track_module, state, MP4_SAMPLE_TABLE_STTS, !i );
1657       if(state->status != VC_CONTAINER_SUCCESS) goto error;
1658 
1659       if(state->sample_duration_count <= samples)
1660       {
1661          samples -= state->sample_duration_count;
1662          state->duration += state->sample_duration * state->sample_duration_count;
1663          continue;
1664       }
1665 
1666       state->sample_duration_count -= samples;
1667       state->duration += samples * state->sample_duration;
1668       break;
1669    }
1670 
1671    /* Find the right place in the sample composition table */
1672    for(i = 0, samples = sample; i < track_module->sample_table[MP4_SAMPLE_TABLE_CTTS].entries; i++)
1673    {
1674       state->status = mp4_read_sample_table( p_ctx, track_module, state, MP4_SAMPLE_TABLE_CTTS, !i );
1675       if(state->status != VC_CONTAINER_SUCCESS) goto error;
1676 
1677       if(state->sample_composition_count <= samples)
1678       {
1679          samples -= state->sample_composition_count;
1680          continue;
1681       }
1682 
1683       state->sample_composition_count -= samples;
1684       break;
1685    }
1686 
1687    /* Find the right place in the synchronisation table */
1688    for(i = 0; i < track_module->sample_table[MP4_SAMPLE_TABLE_STSS].entries; i++)
1689    {
1690       state->status = mp4_read_sample_table( p_ctx, track_module, state, MP4_SAMPLE_TABLE_STSS, !i );
1691       if(state->status != VC_CONTAINER_SUCCESS) goto error;
1692 
1693       if(state->next_sync_sample >= sample + 1) break;
1694    }
1695 
1696    state->sample = sample;
1697    state->sample_size = 0;
1698    mp4_read_sample_header(p_ctx, track, state);
1699 
1700  error:
1701    return state->status;
1702 }
1703 
1704 /*****************************************************************************/
mp4_reader_seek(VC_CONTAINER_T * p_ctx,int64_t * offset,VC_CONTAINER_SEEK_MODE_T mode,VC_CONTAINER_SEEK_FLAGS_T flags)1705 static VC_CONTAINER_STATUS_T mp4_reader_seek(VC_CONTAINER_T *p_ctx,
1706    int64_t *offset, VC_CONTAINER_SEEK_MODE_T mode, VC_CONTAINER_SEEK_FLAGS_T flags)
1707 {
1708    VC_CONTAINER_MODULE_T *module = p_ctx->priv->module;
1709    VC_CONTAINER_TRACK_MODULE_T *track_module;
1710    VC_CONTAINER_STATUS_T status;
1711    uint32_t i, track, sample, prev_sample, next_sample;
1712    int64_t seek_time = *offset;
1713    VC_CONTAINER_PARAM_UNUSED(module);
1714    VC_CONTAINER_PARAM_UNUSED(mode);
1715 
1716    /* Reset the states */
1717    for(i = 0; i < p_ctx->tracks_num; i++)
1718       memset(&p_ctx->tracks[i]->priv->module->state, 0, sizeof(p_ctx->tracks[i]->priv->module->state));
1719 
1720    /* Deal with the easy case first */
1721    if(!*offset)
1722    {
1723       /* Initialise tracks */
1724       for(i = 0; i < p_ctx->tracks_num; i++)
1725       {
1726          /* FIXME: we should check we've got at least one success */
1727         mp4_read_sample_header(p_ctx, i, &p_ctx->tracks[i]->priv->module->state);
1728       }
1729       return VC_CONTAINER_SUCCESS;
1730    }
1731 
1732    /* Find the first enabled video track */
1733    for(track = 0; track < p_ctx->tracks_num; track++)
1734       if(p_ctx->tracks[track]->is_enabled &&
1735          p_ctx->tracks[track]->format->es_type == VC_CONTAINER_ES_TYPE_VIDEO) break;
1736    if(track == p_ctx->tracks_num) goto seek_time_found; /* No video track found */
1737    track_module = p_ctx->tracks[track]->priv->module;
1738 
1739    /* Find the sample number for the requested time */
1740    sample = mp4_find_sample( p_ctx, track, &track_module->state, seek_time, &status );
1741    if(status != VC_CONTAINER_SUCCESS) goto seek_time_found;
1742 
1743    /* Find the closest sync sample */
1744    status = mp4_seek_sample_table( p_ctx, track_module, &track_module->state, MP4_SAMPLE_TABLE_STSS );
1745    if(status != VC_CONTAINER_SUCCESS) goto seek_time_found;
1746    for(i = 0, prev_sample = 0, next_sample = 0;
1747        i < track_module->sample_table[MP4_SAMPLE_TABLE_STSS].entries; i++)
1748    {
1749       next_sample = _READ_U32(p_ctx) - 1;
1750       if(next_sample > sample)
1751       {
1752          sample = (flags & VC_CONTAINER_SEEK_FLAG_FORWARD) ? next_sample : prev_sample;
1753          break;
1754       }
1755       prev_sample = next_sample;
1756    }
1757 
1758    /* Do the seek on this track and use its timestamp as the new seek point */
1759    status = mp4_seek_track(p_ctx, track, &track_module->state, sample);
1760    if(status != VC_CONTAINER_SUCCESS) goto seek_time_found;
1761    seek_time = track_module->state.pts;
1762 
1763  seek_time_found:
1764 
1765    for(i = 0; i < p_ctx->tracks_num; i++)
1766    {
1767       uint32_t sample;
1768       track_module = p_ctx->tracks[i]->priv->module;
1769       if(track_module->state.offset) continue;
1770       sample = mp4_find_sample( p_ctx, i, &track_module->state, seek_time, &status );
1771       if(status != VC_CONTAINER_SUCCESS) return status; //FIXME
1772 
1773       status = mp4_seek_track(p_ctx, i, &track_module->state, sample);
1774    }
1775 
1776    *offset = seek_time;
1777    return VC_CONTAINER_SUCCESS;
1778 }
1779 
1780 /******************************************************************************
1781 Global function definitions.
1782 ******************************************************************************/
1783 
mp4_reader_open(VC_CONTAINER_T * p_ctx)1784 VC_CONTAINER_STATUS_T mp4_reader_open( VC_CONTAINER_T *p_ctx )
1785 {
1786    VC_CONTAINER_STATUS_T status = VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED;
1787    VC_CONTAINER_MODULE_T *module = 0;
1788    unsigned int i;
1789    uint8_t h[8];
1790 
1791    /* Check for a known box type to see if we're dealing with mp4 */
1792    if( PEEK_BYTES(p_ctx, h, 8) != 8 )
1793       return VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED;
1794    switch(VC_FOURCC(h[4],h[5],h[6],h[7]))
1795    {
1796    case MP4_BOX_TYPE_FTYP:
1797    case MP4_BOX_TYPE_MDAT:
1798    case MP4_BOX_TYPE_MOOV:
1799    case MP4_BOX_TYPE_FREE:
1800    case MP4_BOX_TYPE_SKIP:
1801    case MP4_BOX_TYPE_WIDE:
1802    case MP4_BOX_TYPE_PNOT:
1803    case MP4_BOX_TYPE_PICT:
1804    case MP4_BOX_TYPE_UDTA:
1805    case MP4_BOX_TYPE_UUID:
1806       break;
1807    default:
1808       /* Couldn't recognize the box type. This doesn't look like an mp4. */
1809       return VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED;
1810    }
1811 
1812    /*
1813     *  We are dealing with an MP4 file
1814     */
1815 
1816    LOG_DEBUG(p_ctx, "using mp4 reader");
1817 
1818    /* Allocate our context */
1819    module = malloc(sizeof(*module));
1820    if(!module) { status = VC_CONTAINER_ERROR_OUT_OF_MEMORY; goto error; }
1821    memset(module, 0, sizeof(*module));
1822    p_ctx->priv->module = module;
1823    p_ctx->tracks = module->tracks;
1824 
1825    while(STREAM_STATUS(p_ctx) == VC_CONTAINER_SUCCESS)
1826    {
1827       MP4_BOX_TYPE_T box_type;
1828       int64_t box_size;
1829 
1830       status = mp4_read_box_header( p_ctx, INT64_C(-1), &box_type, &box_size );
1831       if(status != VC_CONTAINER_SUCCESS) goto error;
1832 
1833       if(box_type == MP4_BOX_TYPE_MDAT)
1834       {
1835          module->data_offset = STREAM_POSITION(p_ctx);
1836          module->data_size = box_size;
1837          if(module->found_moov) break; /* We've got everything we want */
1838       }
1839       else if(box_type == MP4_BOX_TYPE_MOOV)
1840          module->found_moov = true;
1841 
1842       status = mp4_read_box_data( p_ctx, box_type, box_size, MP4_BOX_TYPE_ROOT );
1843       if(status != VC_CONTAINER_SUCCESS) goto error;
1844 
1845       if(module->found_moov && module->data_offset) break; /* We've got everything we want */
1846    }
1847 
1848    /* Initialise tracks */
1849    for(i = 0; i < p_ctx->tracks_num; i++)
1850    {
1851       /* FIXME: we should check we've got at least one success */
1852       status = mp4_read_sample_header(p_ctx, i, &p_ctx->tracks[i]->priv->module->state);
1853    }
1854 
1855    status = SEEK(p_ctx, module->data_offset);
1856    if(status != VC_CONTAINER_SUCCESS) goto error;
1857 
1858    p_ctx->priv->pf_close = mp4_reader_close;
1859    p_ctx->priv->pf_read = mp4_reader_read;
1860    p_ctx->priv->pf_seek = mp4_reader_seek;
1861 
1862    if(STREAM_SEEKABLE(p_ctx))
1863       p_ctx->capabilities |= VC_CONTAINER_CAPS_CAN_SEEK;
1864 
1865    return VC_CONTAINER_SUCCESS;
1866 
1867  error:
1868    LOG_DEBUG(p_ctx, "mp4: error opening stream");
1869    if(module) mp4_reader_close(p_ctx);
1870    return status;
1871 }
1872 
1873 /********************************************************************************
1874  Entrypoint function
1875  ********************************************************************************/
1876 
1877 #if !defined(ENABLE_CONTAINERS_STANDALONE) && defined(__HIGHC__)
1878 # pragma weak reader_open mp4_reader_open
1879 #endif
1880