1 /*****************************************************************************
2 * libmp4.c : LibMP4 library for mp4 module for vlc
3 *****************************************************************************
4 * Copyright (C) 2001-2004, 2010 the VideoLAN team
6 * Author: Laurent Aimar <fenrir@via.ecp.fr>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
27 #include <vlc_common.h>
28 #include <vlc_demux.h>
31 # include <zlib.h> /* for compressed moov */
37 /*****************************************************************************
38 * Here are defined some macro to make life simpler but before using it
41 *****************************************************************************/
43 static inline size_t mp4_box_headersize( MP4_Box_t
*p_box
)
46 + ( p_box
->i_shortsize
== 1 ? 8 : 0 )
47 + ( p_box
->i_type
== ATOM_uuid
? 16 : 0 );
50 #define MP4_GETX_PRIVATE(dst, code, size) do { \
51 if( (i_read) >= (size) ) { dst = (code); p_peek += (size); } \
56 #define MP4_GET1BYTE( dst ) MP4_GETX_PRIVATE( dst, *p_peek, 1 )
57 #define MP4_GET2BYTES( dst ) MP4_GETX_PRIVATE( dst, GetWBE(p_peek), 2 )
58 #define MP4_GET3BYTES( dst ) MP4_GETX_PRIVATE( dst, Get24bBE(p_peek), 3 )
59 #define MP4_GET4BYTES( dst ) MP4_GETX_PRIVATE( dst, GetDWBE(p_peek), 4 )
60 #define MP4_GET8BYTES( dst ) MP4_GETX_PRIVATE( dst, GetQWBE(p_peek), 8 )
61 #define MP4_GETFOURCC( dst ) MP4_GETX_PRIVATE( dst, \
62 VLC_FOURCC(p_peek[0],p_peek[1],p_peek[2],p_peek[3]), 4)
64 #define MP4_GETVERSIONFLAGS( p_void ) \
65 MP4_GET1BYTE( p_void->i_version ); \
66 MP4_GET3BYTES( p_void->i_flags )
68 #define MP4_GETSTRINGZ( p_str ) \
69 if( (i_read > 0) && (p_peek[0]) ) \
71 const int __i_copy__ = strnlen( (char*)p_peek, i_read-1 ); \
72 p_str = malloc( __i_copy__+1 ); \
75 memcpy( p_str, p_peek, __i_copy__ ); \
76 p_str[__i_copy__] = 0; \
78 p_peek += __i_copy__ + 1; \
79 i_read -= __i_copy__ + 1; \
86 #define MP4_READBOX_ENTER( MP4_Box_data_TYPE_t ) \
87 int64_t i_read = p_box->i_size; \
88 uint8_t *p_peek, *p_buff; \
89 int i_actually_read; \
90 if( !( p_peek = p_buff = malloc( i_read ) ) ) \
94 i_actually_read = stream_Read( p_stream, p_peek, i_read ); \
95 if( i_actually_read < 0 || (int64_t)i_actually_read < i_read )\
100 p_peek += mp4_box_headersize( p_box ); \
101 i_read -= mp4_box_headersize( p_box ); \
102 if( !( p_box->data.p_data = calloc( 1, sizeof( MP4_Box_data_TYPE_t ) ) ) ) \
108 #define MP4_READBOX_EXIT( i_code ) \
113 msg_Warn( p_stream, "Not enough data" ); \
119 * The input method HAS to be seekable
123 /* This macro is used when we want to printf the box type
124 * APPLE annotation box is :
125 * either 0xA9 + 24-bit ASCII text string (and 0xA9 isn't printable)
126 * either 32-bit ASCII text string
128 #define MP4_BOX_TYPE_ASCII() ( ((char*)&p_box->i_type)[0] != (char)0xA9 )
130 static uint32_t Get24bBE( const uint8_t *p
)
132 return( ( p
[0] <<16 ) + ( p
[1] <<8 ) + p
[2] );
135 static void GetUUID( UUID_t
*p_uuid
, const uint8_t *p_buff
)
137 memcpy( p_uuid
, p_buff
, 16 );
140 static void CreateUUID( UUID_t
*p_uuid
, uint32_t i_fourcc
)
142 /* made by 0xXXXXXXXX-0011-0010-8000-00aa00389b71
143 where XXXXXXXX is the fourcc */
144 /* FIXME implement this */
149 /* some functions for mp4 encoding of variables */
151 static void MP4_ConvertDate2Str( char *psz
, uint64_t i_date
)
158 /* date begin at 1 jan 1904 */
159 i_date
+= ((INT64_C(1904) * 365) + 17) * 24 * 60 * 60;
161 i_day
= i_date
/ ( 60*60*24);
162 i_hour
= ( i_date
/( 60*60 ) ) % 60;
163 i_min
= ( i_date
/ 60 ) % 60;
165 sprintf( psz
, "%dd-%2.2dh:%2.2dm:%2.2ds", i_day
, i_hour
, i_min
, i_sec
);
169 /*****************************************************************************
171 *****************************************************************************/
172 static MP4_Box_t
*MP4_ReadBox( stream_t
*p_stream
, MP4_Box_t
*p_father
);
175 /*****************************************************************************
176 * MP4_ReadBoxCommon : Load only common parameters for all boxes
177 *****************************************************************************
178 * p_box need to be an already allocated MP4_Box_t, and all data
179 * will only be peek not read
181 * RETURN : 0 if it fail, 1 otherwise
182 *****************************************************************************/
183 int MP4_ReadBoxCommon( stream_t
*p_stream
, MP4_Box_t
*p_box
)
186 const uint8_t *p_peek
;
188 if( ( ( i_read
= stream_Peek( p_stream
, &p_peek
, 32 ) ) < 8 ) )
192 p_box
->i_pos
= stream_Tell( p_stream
);
194 p_box
->data
.p_data
= NULL
;
195 p_box
->p_father
= NULL
;
196 p_box
->p_first
= NULL
;
197 p_box
->p_last
= NULL
;
198 p_box
->p_next
= NULL
;
200 MP4_GET4BYTES( p_box
->i_shortsize
);
201 MP4_GETFOURCC( p_box
->i_type
);
203 /* Now special case */
205 if( p_box
->i_shortsize
== 1 )
207 /* get the true size on 64 bits */
208 MP4_GET8BYTES( p_box
->i_size
);
212 p_box
->i_size
= p_box
->i_shortsize
;
213 /* XXX size of 0 means that the box extends to end of file */
216 if( p_box
->i_type
== ATOM_uuid
)
218 /* get extented type on 16 bytes */
219 GetUUID( &p_box
->i_uuid
, p_peek
);
220 p_peek
+= 16; i_read
-= 16;
224 CreateUUID( &p_box
->i_uuid
, p_box
->i_type
);
229 if MP4_BOX_TYPE_ASCII()
230 msg_Dbg( p_stream
, "found Box: %4.4s size %"PRId64
,
231 (char*)&p_box
->i_type
, p_box
->i_size
);
233 msg_Dbg( p_stream
, "found Box: c%3.3s size %"PRId64
,
234 (char*)&p_box
->i_type
+1, p_box
->i_size
);
241 /*****************************************************************************
242 * MP4_NextBox : Go to the next box
243 *****************************************************************************
244 * if p_box == NULL, go to the next box in which we are( at the begining ).
245 *****************************************************************************/
246 static int MP4_NextBox( stream_t
*p_stream
, MP4_Box_t
*p_box
)
252 MP4_ReadBoxCommon( p_stream
, &box
);
258 return 2; /* Box with infinite size */
261 if( p_box
->p_father
)
263 const off_t i_box_end
= p_box
->i_size
+ p_box
->i_pos
;
264 const off_t i_father_end
= p_box
->p_father
->i_size
+ p_box
->p_father
->i_pos
;
266 /* check if it's within p-father */
267 if( i_box_end
>= i_father_end
)
269 if( i_box_end
> i_father_end
)
270 msg_Dbg( p_stream
, "out of bound child" );
271 return 0; /* out of bound */
274 if( stream_Seek( p_stream
, p_box
->i_size
+ p_box
->i_pos
) )
282 /*****************************************************************************
283 * For all known box a loader is given,
284 * XXX: all common struct have to be already read by MP4_ReadBoxCommon
285 * after called one of theses functions, file position is unknown
286 * you need to call MP4_GotoBox to go where you want
287 *****************************************************************************/
288 static int MP4_ReadBoxContainerRaw( stream_t
*p_stream
, MP4_Box_t
*p_container
)
292 if( stream_Tell( p_stream
) + 8 >
293 (off_t
)(p_container
->i_pos
+ p_container
->i_size
) )
295 /* there is no box to load */
301 if( ( p_box
= MP4_ReadBox( p_stream
, p_container
) ) == NULL
) break;
303 /* chain this box with the father and the other at same level */
304 if( !p_container
->p_first
) p_container
->p_first
= p_box
;
305 else p_container
->p_last
->p_next
= p_box
;
306 p_container
->p_last
= p_box
;
308 } while( MP4_NextBox( p_stream
, p_box
) == 1 );
313 static int MP4_ReadBoxContainer( stream_t
*p_stream
, MP4_Box_t
*p_container
)
315 if( p_container
->i_size
<= (size_t)mp4_box_headersize(p_container
) + 8 )
317 /* container is empty, 8 stand for the first header in this box */
322 stream_Seek( p_stream
, p_container
->i_pos
+
323 mp4_box_headersize( p_container
) );
325 return MP4_ReadBoxContainerRaw( p_stream
, p_container
);
328 static void MP4_FreeBox_Common( MP4_Box_t
*p_box
)
330 /* Up to now do nothing */
334 static int MP4_ReadBoxSkip( stream_t
*p_stream
, MP4_Box_t
*p_box
)
336 /* XXX sometime moov is hiden in a free box */
337 if( p_box
->p_father
&&
338 p_box
->p_father
->i_type
== ATOM_root
&&
339 p_box
->i_type
== ATOM_free
)
341 const uint8_t *p_peek
;
345 i_read
= stream_Peek( p_stream
, &p_peek
, 44 );
347 p_peek
+= mp4_box_headersize( p_box
) + 4;
348 i_read
-= mp4_box_headersize( p_box
) + 4;
352 i_fcc
= VLC_FOURCC( p_peek
[0], p_peek
[1], p_peek
[2], p_peek
[3] );
354 if( i_fcc
== ATOM_cmov
|| i_fcc
== ATOM_mvhd
)
356 msg_Warn( p_stream
, "detected moov hidden in a free box ..." );
358 p_box
->i_type
= ATOM_foov
;
359 return MP4_ReadBoxContainer( p_stream
, p_box
);
366 if MP4_BOX_TYPE_ASCII()
367 msg_Dbg( p_stream
, "skip box: \"%4.4s\"", (char*)&p_box
->i_type
);
369 msg_Dbg( p_stream
, "skip box: \"c%3.3s\"", (char*)&p_box
->i_type
+1 );
374 static int MP4_ReadBox_ftyp( stream_t
*p_stream
, MP4_Box_t
*p_box
)
376 MP4_READBOX_ENTER( MP4_Box_data_ftyp_t
);
378 MP4_GETFOURCC( p_box
->data
.p_ftyp
->i_major_brand
);
379 MP4_GET4BYTES( p_box
->data
.p_ftyp
->i_minor_version
);
381 if( ( p_box
->data
.p_ftyp
->i_compatible_brands_count
= i_read
/ 4 ) )
384 uint32_t *tab
= p_box
->data
.p_ftyp
->i_compatible_brands
=
385 calloc( p_box
->data
.p_ftyp
->i_compatible_brands_count
,
389 MP4_READBOX_EXIT( 0 );
391 for( i
=0; i
< p_box
->data
.p_ftyp
->i_compatible_brands_count
; i
++ )
393 MP4_GETFOURCC( tab
[i
] );
398 p_box
->data
.p_ftyp
->i_compatible_brands
= NULL
;
401 MP4_READBOX_EXIT( 1 );
404 static void MP4_FreeBox_ftyp( MP4_Box_t
*p_box
)
406 FREENULL( p_box
->data
.p_ftyp
->i_compatible_brands
);
410 static int MP4_ReadBox_mvhd( stream_t
*p_stream
, MP4_Box_t
*p_box
)
414 char s_creation_time
[128];
415 char s_modification_time
[128];
416 char s_duration
[128];
418 MP4_READBOX_ENTER( MP4_Box_data_mvhd_t
);
420 MP4_GETVERSIONFLAGS( p_box
->data
.p_mvhd
);
422 if( p_box
->data
.p_mvhd
->i_version
)
424 MP4_GET8BYTES( p_box
->data
.p_mvhd
->i_creation_time
);
425 MP4_GET8BYTES( p_box
->data
.p_mvhd
->i_modification_time
);
426 MP4_GET4BYTES( p_box
->data
.p_mvhd
->i_timescale
);
427 MP4_GET8BYTES( p_box
->data
.p_mvhd
->i_duration
);
431 MP4_GET4BYTES( p_box
->data
.p_mvhd
->i_creation_time
);
432 MP4_GET4BYTES( p_box
->data
.p_mvhd
->i_modification_time
);
433 MP4_GET4BYTES( p_box
->data
.p_mvhd
->i_timescale
);
434 MP4_GET4BYTES( p_box
->data
.p_mvhd
->i_duration
);
436 MP4_GET4BYTES( p_box
->data
.p_mvhd
->i_rate
);
437 MP4_GET2BYTES( p_box
->data
.p_mvhd
->i_volume
);
438 MP4_GET2BYTES( p_box
->data
.p_mvhd
->i_reserved1
);
441 for( i
= 0; i
< 2; i
++ )
443 MP4_GET4BYTES( p_box
->data
.p_mvhd
->i_reserved2
[i
] );
445 for( i
= 0; i
< 9; i
++ )
447 MP4_GET4BYTES( p_box
->data
.p_mvhd
->i_matrix
[i
] );
449 for( i
= 0; i
< 6; i
++ )
451 MP4_GET4BYTES( p_box
->data
.p_mvhd
->i_predefined
[i
] );
454 MP4_GET4BYTES( p_box
->data
.p_mvhd
->i_next_track_id
);
458 MP4_ConvertDate2Str( s_creation_time
, p_box
->data
.p_mvhd
->i_creation_time
);
459 MP4_ConvertDate2Str( s_modification_time
,
460 p_box
->data
.p_mvhd
->i_modification_time
);
461 if( p_box
->data
.p_mvhd
->i_rate
)
463 MP4_ConvertDate2Str( s_duration
,
464 p_box
->data
.p_mvhd
->i_duration
/ p_box
->data
.p_mvhd
->i_rate
);
470 msg_Dbg( p_stream
, "read box: \"mvhd\" creation %s modification %s time scale %d duration %s rate %f volume %f next track id %d",
473 (uint32_t)p_box
->data
.p_mvhd
->i_timescale
,
475 (float)p_box
->data
.p_mvhd
->i_rate
/ (1<<16 ),
476 (float)p_box
->data
.p_mvhd
->i_volume
/ 256 ,
477 (uint32_t)p_box
->data
.p_mvhd
->i_next_track_id
);
479 MP4_READBOX_EXIT( 1 );
482 static int MP4_ReadBox_mfhd( stream_t
*p_stream
, MP4_Box_t
*p_box
)
484 MP4_READBOX_ENTER( MP4_Box_data_mfhd_t
);
486 MP4_GET4BYTES( p_box
->data
.p_mfhd
->i_sequence_number
);
489 msg_Dbg( p_stream
, "read box: \"mfhd\" sequence number %d",
490 p_box
->data
.p_mfhd
->i_sequence_number
);
492 MP4_READBOX_EXIT( 1 );
495 static int MP4_ReadBox_tfhd( stream_t
*p_stream
, MP4_Box_t
*p_box
)
497 MP4_READBOX_ENTER( MP4_Box_data_tfhd_t
);
499 MP4_GETVERSIONFLAGS( p_box
->data
.p_tfhd
);
501 MP4_GET4BYTES( p_box
->data
.p_tfhd
->i_track_ID
);
503 if( p_box
->data
.p_tfhd
->i_version
== 0 )
505 if( p_box
->data
.p_tfhd
->i_flags
& MP4_TFHD_BASE_DATA_OFFSET
)
506 MP4_GET8BYTES( p_box
->data
.p_tfhd
->i_base_data_offset
);
507 if( p_box
->data
.p_tfhd
->i_flags
& MP4_TFHD_SAMPLE_DESC_INDEX
)
508 MP4_GET4BYTES( p_box
->data
.p_tfhd
->i_sample_description_index
);
509 if( p_box
->data
.p_tfhd
->i_flags
& MP4_TFHD_DFLT_SAMPLE_DURATION
)
510 MP4_GET4BYTES( p_box
->data
.p_tfhd
->i_default_sample_duration
);
511 if( p_box
->data
.p_tfhd
->i_flags
& MP4_TFHD_DFLT_SAMPLE_SIZE
)
512 MP4_GET4BYTES( p_box
->data
.p_tfhd
->i_default_sample_size
);
513 if( p_box
->data
.p_tfhd
->i_flags
& MP4_TFHD_DFLT_SAMPLE_FLAGS
)
514 MP4_GET4BYTES( p_box
->data
.p_tfhd
->i_default_sample_flags
);
517 char psz_base
[128] = "\0";
518 char psz_desc
[128] = "\0";
519 char psz_dura
[128] = "\0";
520 char psz_size
[128] = "\0";
521 char psz_flag
[128] = "\0";
522 if( p_box
->data
.p_tfhd
->i_flags
& MP4_TFHD_BASE_DATA_OFFSET
)
523 snprintf(psz_base
, sizeof(psz_base
), "base offset %"PRId64
, p_box
->data
.p_tfhd
->i_base_data_offset
);
524 if( p_box
->data
.p_tfhd
->i_flags
& MP4_TFHD_SAMPLE_DESC_INDEX
)
525 snprintf(psz_desc
, sizeof(psz_desc
), "sample description index %d", p_box
->data
.p_tfhd
->i_sample_description_index
);
526 if( p_box
->data
.p_tfhd
->i_flags
& MP4_TFHD_DFLT_SAMPLE_DURATION
)
527 snprintf(psz_dura
, sizeof(psz_dura
), "sample duration %d", p_box
->data
.p_tfhd
->i_default_sample_duration
);
528 if( p_box
->data
.p_tfhd
->i_flags
& MP4_TFHD_DFLT_SAMPLE_SIZE
)
529 snprintf(psz_size
, sizeof(psz_size
), "sample size %d", p_box
->data
.p_tfhd
->i_default_sample_size
);
530 if( p_box
->data
.p_tfhd
->i_flags
& MP4_TFHD_DFLT_SAMPLE_FLAGS
)
531 snprintf(psz_flag
, sizeof(psz_flag
), "sample flags 0x%x", p_box
->data
.p_tfhd
->i_default_sample_flags
);
533 msg_Dbg( p_stream
, "read box: \"tfhd\" version %d flags 0x%x track ID %d %s %s %s %s %s",
534 p_box
->data
.p_tfhd
->i_version
,
535 p_box
->data
.p_tfhd
->i_flags
,
536 p_box
->data
.p_tfhd
->i_track_ID
,
537 psz_base
, psz_desc
, psz_dura
, psz_size
, psz_flag
);
541 MP4_READBOX_EXIT( 1 );
544 static int MP4_ReadBox_trun( stream_t
*p_stream
, MP4_Box_t
*p_box
)
546 MP4_READBOX_ENTER( MP4_Box_data_trun_t
);
548 MP4_GETVERSIONFLAGS( p_box
->data
.p_trun
);
550 MP4_GET4BYTES( p_box
->data
.p_trun
->i_sample_count
);
552 if( p_box
->data
.p_trun
->i_flags
& MP4_TRUN_DATA_OFFSET
)
553 MP4_GET8BYTES( p_box
->data
.p_trun
->i_data_offset
);
554 if( p_box
->data
.p_trun
->i_flags
& MP4_TRUN_FIRST_FLAGS
)
555 MP4_GET4BYTES( p_box
->data
.p_trun
->i_first_sample_flags
);
557 p_box
->data
.p_trun
->p_samples
=
558 calloc( p_box
->data
.p_trun
->i_sample_count
, sizeof(MP4_descriptor_trun_sample_t
) );
559 if ( p_box
->data
.p_trun
->p_samples
== NULL
)
560 MP4_READBOX_EXIT( 0 );
562 for( unsigned int i
= 0; i
<p_box
->data
.p_trun
->i_sample_count
; i
++ )
564 MP4_descriptor_trun_sample_t
*p_sample
= &p_box
->data
.p_trun
->p_samples
[i
];
565 if( p_box
->data
.p_trun
->i_flags
& MP4_TRUN_SAMPLE_DURATION
)
566 MP4_GET4BYTES( p_sample
->i_duration
);
567 if( p_box
->data
.p_trun
->i_flags
& MP4_TRUN_SAMPLE_SIZE
)
568 MP4_GET4BYTES( p_sample
->i_size
);
569 if( p_box
->data
.p_trun
->i_flags
& MP4_TRUN_SAMPLE_FLAGS
)
570 MP4_GET4BYTES( p_sample
->i_flags
);
571 if( p_box
->data
.p_trun
->i_flags
& MP4_TRUN_SAMPLE_TIME_OFFSET
)
572 MP4_GET4BYTES( p_sample
->i_composition_time_offset
);
576 msg_Dbg( p_stream
, "read box: \"trun\" version %d flags 0x%x sample count %d",
577 p_box
->data
.p_trun
->i_version
,
578 p_box
->data
.p_trun
->i_flags
,
579 p_box
->data
.p_trun
->i_sample_count
);
581 for( unsigned int i
= 0; i
<p_box
->data
.p_trun
->i_sample_count
; i
++ )
583 MP4_descriptor_trun_sample_t
*p_sample
= &p_box
->data
.p_trun
->p_samples
[i
];
584 msg_Dbg( p_stream
, "read box: \"trun\" sample %4.4d flags 0x%x duration %d size %d composition time offset %d",
585 i
, p_sample
->i_flags
, p_sample
->i_duration
,
586 p_sample
->i_size
, p_sample
->i_composition_time_offset
);
590 MP4_READBOX_EXIT( 1 );
593 static void MP4_FreeBox_trun( MP4_Box_t
*p_box
)
595 FREENULL( p_box
->data
.p_trun
->p_samples
);
600 static int MP4_ReadBox_tkhd( stream_t
*p_stream
, MP4_Box_t
*p_box
)
604 char s_creation_time
[128];
605 char s_modification_time
[128];
606 char s_duration
[128];
608 MP4_READBOX_ENTER( MP4_Box_data_tkhd_t
);
610 MP4_GETVERSIONFLAGS( p_box
->data
.p_tkhd
);
612 if( p_box
->data
.p_tkhd
->i_version
)
614 MP4_GET8BYTES( p_box
->data
.p_tkhd
->i_creation_time
);
615 MP4_GET8BYTES( p_box
->data
.p_tkhd
->i_modification_time
);
616 MP4_GET4BYTES( p_box
->data
.p_tkhd
->i_track_ID
);
617 MP4_GET4BYTES( p_box
->data
.p_tkhd
->i_reserved
);
618 MP4_GET8BYTES( p_box
->data
.p_tkhd
->i_duration
);
622 MP4_GET4BYTES( p_box
->data
.p_tkhd
->i_creation_time
);
623 MP4_GET4BYTES( p_box
->data
.p_tkhd
->i_modification_time
);
624 MP4_GET4BYTES( p_box
->data
.p_tkhd
->i_track_ID
);
625 MP4_GET4BYTES( p_box
->data
.p_tkhd
->i_reserved
);
626 MP4_GET4BYTES( p_box
->data
.p_tkhd
->i_duration
);
629 for( i
= 0; i
< 2; i
++ )
631 MP4_GET4BYTES( p_box
->data
.p_tkhd
->i_reserved2
[i
] );
633 MP4_GET2BYTES( p_box
->data
.p_tkhd
->i_layer
);
634 MP4_GET2BYTES( p_box
->data
.p_tkhd
->i_predefined
);
635 MP4_GET2BYTES( p_box
->data
.p_tkhd
->i_volume
);
636 MP4_GET2BYTES( p_box
->data
.p_tkhd
->i_reserved3
);
638 for( i
= 0; i
< 9; i
++ )
640 MP4_GET4BYTES( p_box
->data
.p_tkhd
->i_matrix
[i
] );
642 MP4_GET4BYTES( p_box
->data
.p_tkhd
->i_width
);
643 MP4_GET4BYTES( p_box
->data
.p_tkhd
->i_height
);
646 MP4_ConvertDate2Str( s_creation_time
, p_box
->data
.p_mvhd
->i_creation_time
);
647 MP4_ConvertDate2Str( s_modification_time
, p_box
->data
.p_mvhd
->i_modification_time
);
648 MP4_ConvertDate2Str( s_duration
, p_box
->data
.p_mvhd
->i_duration
);
650 msg_Dbg( p_stream
, "read box: \"tkhd\" creation %s modification %s duration %s track ID %d layer %d volume %f width %f height %f",
654 p_box
->data
.p_tkhd
->i_track_ID
,
655 p_box
->data
.p_tkhd
->i_layer
,
656 (float)p_box
->data
.p_tkhd
->i_volume
/ 256 ,
657 (float)p_box
->data
.p_tkhd
->i_width
/ 65536,
658 (float)p_box
->data
.p_tkhd
->i_height
/ 65536 );
660 MP4_READBOX_EXIT( 1 );
664 static int MP4_ReadBox_mdhd( stream_t
*p_stream
, MP4_Box_t
*p_box
)
669 char s_creation_time
[128];
670 char s_modification_time
[128];
671 char s_duration
[128];
673 MP4_READBOX_ENTER( MP4_Box_data_mdhd_t
);
675 MP4_GETVERSIONFLAGS( p_box
->data
.p_mdhd
);
677 if( p_box
->data
.p_mdhd
->i_version
)
679 MP4_GET8BYTES( p_box
->data
.p_mdhd
->i_creation_time
);
680 MP4_GET8BYTES( p_box
->data
.p_mdhd
->i_modification_time
);
681 MP4_GET4BYTES( p_box
->data
.p_mdhd
->i_timescale
);
682 MP4_GET8BYTES( p_box
->data
.p_mdhd
->i_duration
);
686 MP4_GET4BYTES( p_box
->data
.p_mdhd
->i_creation_time
);
687 MP4_GET4BYTES( p_box
->data
.p_mdhd
->i_modification_time
);
688 MP4_GET4BYTES( p_box
->data
.p_mdhd
->i_timescale
);
689 MP4_GET4BYTES( p_box
->data
.p_mdhd
->i_duration
);
691 p_box
->data
.p_mdhd
->i_language_code
= i_language
= GetWBE( p_peek
);
692 for( i
= 0; i
< 3; i
++ )
694 p_box
->data
.p_mdhd
->i_language
[i
] =
695 ( ( i_language
>> ( (2-i
)*5 ) )&0x1f ) + 0x60;
698 MP4_GET2BYTES( p_box
->data
.p_mdhd
->i_predefined
);
701 MP4_ConvertDate2Str( s_creation_time
, p_box
->data
.p_mdhd
->i_creation_time
);
702 MP4_ConvertDate2Str( s_modification_time
, p_box
->data
.p_mdhd
->i_modification_time
);
703 MP4_ConvertDate2Str( s_duration
, p_box
->data
.p_mdhd
->i_duration
);
704 msg_Dbg( p_stream
, "read box: \"mdhd\" creation %s modification %s time scale %d duration %s language %c%c%c",
707 (uint32_t)p_box
->data
.p_mdhd
->i_timescale
,
709 p_box
->data
.p_mdhd
->i_language
[0],
710 p_box
->data
.p_mdhd
->i_language
[1],
711 p_box
->data
.p_mdhd
->i_language
[2] );
713 MP4_READBOX_EXIT( 1 );
717 static int MP4_ReadBox_hdlr( stream_t
*p_stream
, MP4_Box_t
*p_box
)
721 MP4_READBOX_ENTER( MP4_Box_data_hdlr_t
);
723 MP4_GETVERSIONFLAGS( p_box
->data
.p_hdlr
);
725 MP4_GETFOURCC( p_box
->data
.p_hdlr
->i_predefined
);
726 MP4_GETFOURCC( p_box
->data
.p_hdlr
->i_handler_type
);
728 MP4_GET4BYTES( i_reserved
);
729 MP4_GET4BYTES( i_reserved
);
730 MP4_GET4BYTES( i_reserved
);
731 p_box
->data
.p_hdlr
->psz_name
= NULL
;
735 uint8_t *psz
= p_box
->data
.p_hdlr
->psz_name
= malloc( i_read
+ 1 );
737 MP4_READBOX_EXIT( 0 );
739 /* Yes, I love .mp4 :( */
740 if( p_box
->data
.p_hdlr
->i_predefined
== VLC_FOURCC( 'm', 'h', 'l', 'r' ) )
745 MP4_GET1BYTE( i_len
);
746 i_copy
= __MIN( i_read
, i_len
);
748 memcpy( psz
, p_peek
, i_copy
);
749 p_box
->data
.p_hdlr
->psz_name
[i_copy
] = '\0';
753 memcpy( psz
, p_peek
, i_read
);
754 p_box
->data
.p_hdlr
->psz_name
[i_read
] = '\0';
759 msg_Dbg( p_stream
, "read box: \"hdlr\" handler type: \"%4.4s\" name: \"%s\"",
760 (char*)&p_box
->data
.p_hdlr
->i_handler_type
,
761 p_box
->data
.p_hdlr
->psz_name
);
764 MP4_READBOX_EXIT( 1 );
767 static void MP4_FreeBox_hdlr( MP4_Box_t
*p_box
)
769 FREENULL( p_box
->data
.p_hdlr
->psz_name
);
772 static int MP4_ReadBox_vmhd( stream_t
*p_stream
, MP4_Box_t
*p_box
)
776 MP4_READBOX_ENTER( MP4_Box_data_vmhd_t
);
778 MP4_GETVERSIONFLAGS( p_box
->data
.p_vmhd
);
780 MP4_GET2BYTES( p_box
->data
.p_vmhd
->i_graphics_mode
);
781 for( i
= 0; i
< 3; i
++ )
783 MP4_GET2BYTES( p_box
->data
.p_vmhd
->i_opcolor
[i
] );
787 msg_Dbg( p_stream
, "read box: \"vmhd\" graphics-mode %d opcolor (%d, %d, %d)",
788 p_box
->data
.p_vmhd
->i_graphics_mode
,
789 p_box
->data
.p_vmhd
->i_opcolor
[0],
790 p_box
->data
.p_vmhd
->i_opcolor
[1],
791 p_box
->data
.p_vmhd
->i_opcolor
[2] );
793 MP4_READBOX_EXIT( 1 );
796 static int MP4_ReadBox_smhd( stream_t
*p_stream
, MP4_Box_t
*p_box
)
798 MP4_READBOX_ENTER( MP4_Box_data_smhd_t
);
800 MP4_GETVERSIONFLAGS( p_box
->data
.p_smhd
);
804 MP4_GET2BYTES( p_box
->data
.p_smhd
->i_balance
);
806 MP4_GET2BYTES( p_box
->data
.p_smhd
->i_reserved
);
809 msg_Dbg( p_stream
, "read box: \"smhd\" balance %f",
810 (float)p_box
->data
.p_smhd
->i_balance
/ 256 );
812 MP4_READBOX_EXIT( 1 );
816 static int MP4_ReadBox_hmhd( stream_t
*p_stream
, MP4_Box_t
*p_box
)
818 MP4_READBOX_ENTER( MP4_Box_data_hmhd_t
);
820 MP4_GETVERSIONFLAGS( p_box
->data
.p_hmhd
);
822 MP4_GET2BYTES( p_box
->data
.p_hmhd
->i_max_PDU_size
);
823 MP4_GET2BYTES( p_box
->data
.p_hmhd
->i_avg_PDU_size
);
825 MP4_GET4BYTES( p_box
->data
.p_hmhd
->i_max_bitrate
);
826 MP4_GET4BYTES( p_box
->data
.p_hmhd
->i_avg_bitrate
);
828 MP4_GET4BYTES( p_box
->data
.p_hmhd
->i_reserved
);
831 msg_Dbg( p_stream
, "read box: \"hmhd\" maxPDU-size %d avgPDU-size %d max-bitrate %d avg-bitrate %d",
832 p_box
->data
.p_hmhd
->i_max_PDU_size
,
833 p_box
->data
.p_hmhd
->i_avg_PDU_size
,
834 p_box
->data
.p_hmhd
->i_max_bitrate
,
835 p_box
->data
.p_hmhd
->i_avg_bitrate
);
837 MP4_READBOX_EXIT( 1 );
840 static int MP4_ReadBox_url( stream_t
*p_stream
, MP4_Box_t
*p_box
)
842 MP4_READBOX_ENTER( MP4_Box_data_url_t
);
844 MP4_GETVERSIONFLAGS( p_box
->data
.p_url
);
845 MP4_GETSTRINGZ( p_box
->data
.p_url
->psz_location
);
848 msg_Dbg( p_stream
, "read box: \"url\" url: %s",
849 p_box
->data
.p_url
->psz_location
);
852 MP4_READBOX_EXIT( 1 );
856 static void MP4_FreeBox_url( MP4_Box_t
*p_box
)
858 FREENULL( p_box
->data
.p_url
->psz_location
);
861 static int MP4_ReadBox_urn( stream_t
*p_stream
, MP4_Box_t
*p_box
)
863 MP4_READBOX_ENTER( MP4_Box_data_urn_t
);
865 MP4_GETVERSIONFLAGS( p_box
->data
.p_urn
);
867 MP4_GETSTRINGZ( p_box
->data
.p_urn
->psz_name
);
868 MP4_GETSTRINGZ( p_box
->data
.p_urn
->psz_location
);
871 msg_Dbg( p_stream
, "read box: \"urn\" name %s location %s",
872 p_box
->data
.p_urn
->psz_name
,
873 p_box
->data
.p_urn
->psz_location
);
875 MP4_READBOX_EXIT( 1 );
877 static void MP4_FreeBox_urn( MP4_Box_t
*p_box
)
879 FREENULL( p_box
->data
.p_urn
->psz_name
);
880 FREENULL( p_box
->data
.p_urn
->psz_location
);
884 static int MP4_ReadBox_dref( stream_t
*p_stream
, MP4_Box_t
*p_box
)
886 MP4_READBOX_ENTER( MP4_Box_data_dref_t
);
888 MP4_GETVERSIONFLAGS( p_box
->data
.p_dref
);
890 MP4_GET4BYTES( p_box
->data
.p_dref
->i_entry_count
);
892 stream_Seek( p_stream
, p_box
->i_pos
+ mp4_box_headersize( p_box
) + 8 );
893 MP4_ReadBoxContainerRaw( p_stream
, p_box
);
896 msg_Dbg( p_stream
, "read box: \"dref\" entry-count %d",
897 p_box
->data
.p_dref
->i_entry_count
);
900 MP4_READBOX_EXIT( 1 );
903 static void MP4_FreeBox_stts( MP4_Box_t
*p_box
)
905 FREENULL( p_box
->data
.p_stts
->i_sample_count
);
906 FREENULL( p_box
->data
.p_stts
->i_sample_delta
);
909 static int MP4_ReadBox_stts( stream_t
*p_stream
, MP4_Box_t
*p_box
)
912 MP4_READBOX_ENTER( MP4_Box_data_stts_t
);
914 MP4_GETVERSIONFLAGS( p_box
->data
.p_stts
);
915 MP4_GET4BYTES( p_box
->data
.p_stts
->i_entry_count
);
917 p_box
->data
.p_stts
->i_sample_count
=
918 calloc( p_box
->data
.p_stts
->i_entry_count
, sizeof(uint32_t) );
919 p_box
->data
.p_stts
->i_sample_delta
=
920 calloc( p_box
->data
.p_stts
->i_entry_count
, sizeof(uint32_t) );
921 if( p_box
->data
.p_stts
->i_sample_count
== NULL
922 || p_box
->data
.p_stts
->i_sample_delta
== NULL
)
924 MP4_READBOX_EXIT( 0 );
927 for( i
= 0; (i
< p_box
->data
.p_stts
->i_entry_count
)&&( i_read
>=8 ); i
++ )
929 MP4_GET4BYTES( p_box
->data
.p_stts
->i_sample_count
[i
] );
930 MP4_GET4BYTES( p_box
->data
.p_stts
->i_sample_delta
[i
] );
934 msg_Dbg( p_stream
, "read box: \"stts\" entry-count %d",
935 p_box
->data
.p_stts
->i_entry_count
);
938 MP4_READBOX_EXIT( 1 );
942 static void MP4_FreeBox_ctts( MP4_Box_t
*p_box
)
944 FREENULL( p_box
->data
.p_ctts
->i_sample_count
);
945 FREENULL( p_box
->data
.p_ctts
->i_sample_offset
);
948 static int MP4_ReadBox_ctts( stream_t
*p_stream
, MP4_Box_t
*p_box
)
951 MP4_READBOX_ENTER( MP4_Box_data_ctts_t
);
953 MP4_GETVERSIONFLAGS( p_box
->data
.p_ctts
);
955 MP4_GET4BYTES( p_box
->data
.p_ctts
->i_entry_count
);
957 p_box
->data
.p_ctts
->i_sample_count
=
958 calloc( p_box
->data
.p_ctts
->i_entry_count
, sizeof(uint32_t) );
959 p_box
->data
.p_ctts
->i_sample_offset
=
960 calloc( p_box
->data
.p_ctts
->i_entry_count
, sizeof(uint32_t) );
961 if( ( p_box
->data
.p_ctts
->i_sample_count
== NULL
)
962 || ( p_box
->data
.p_ctts
->i_sample_offset
== NULL
) )
964 MP4_READBOX_EXIT( 0 );
967 for( i
= 0; (i
< p_box
->data
.p_ctts
->i_entry_count
)&&( i_read
>=8 ); i
++ )
969 MP4_GET4BYTES( p_box
->data
.p_ctts
->i_sample_count
[i
] );
970 MP4_GET4BYTES( p_box
->data
.p_ctts
->i_sample_offset
[i
] );
974 msg_Dbg( p_stream
, "read box: \"ctts\" entry-count %d",
975 p_box
->data
.p_ctts
->i_entry_count
);
978 MP4_READBOX_EXIT( 1 );
982 static int MP4_ReadLengthDescriptor( uint8_t **pp_peek
, int64_t *i_read
)
985 unsigned int i_len
= 0;
992 i_len
= ( i_len
<< 7 ) + ( i_b
&0x7f );
998 static void MP4_FreeBox_esds( MP4_Box_t
*p_box
)
1000 FREENULL( p_box
->data
.p_esds
->es_descriptor
.psz_URL
);
1001 if( p_box
->data
.p_esds
->es_descriptor
.p_decConfigDescr
)
1003 FREENULL( p_box
->data
.p_esds
->es_descriptor
.p_decConfigDescr
->p_decoder_specific_info
);
1004 FREENULL( p_box
->data
.p_esds
->es_descriptor
.p_decConfigDescr
);
1008 static int MP4_ReadBox_esds( stream_t
*p_stream
, MP4_Box_t
*p_box
)
1010 #define es_descriptor p_box->data.p_esds->es_descriptor
1012 unsigned int i_flags
;
1013 unsigned int i_type
;
1015 MP4_READBOX_ENTER( MP4_Box_data_esds_t
);
1017 MP4_GETVERSIONFLAGS( p_box
->data
.p_esds
);
1020 MP4_GET1BYTE( i_type
);
1021 if( i_type
== 0x03 ) /* MP4ESDescrTag */
1023 i_len
= MP4_ReadLengthDescriptor( &p_peek
, &i_read
);
1026 msg_Dbg( p_stream
, "found esds MPEG4ESDescr (%dBytes)",
1030 MP4_GET2BYTES( es_descriptor
.i_ES_ID
);
1031 MP4_GET1BYTE( i_flags
);
1032 es_descriptor
.b_stream_dependence
= ( (i_flags
&0x80) != 0);
1033 es_descriptor
.b_url
= ( (i_flags
&0x40) != 0);
1034 es_descriptor
.b_OCRstream
= ( (i_flags
&0x20) != 0);
1036 es_descriptor
.i_stream_priority
= i_flags
&0x1f;
1037 if( es_descriptor
.b_stream_dependence
)
1039 MP4_GET2BYTES( es_descriptor
.i_depend_on_ES_ID
);
1041 if( es_descriptor
.b_url
)
1045 MP4_GET1BYTE( i_len
);
1046 es_descriptor
.psz_URL
= malloc( i_len
+ 1 );
1047 if( es_descriptor
.psz_URL
)
1049 memcpy( es_descriptor
.psz_URL
, p_peek
, i_len
);
1050 es_descriptor
.psz_URL
[i_len
] = 0;
1057 es_descriptor
.psz_URL
= NULL
;
1059 if( es_descriptor
.b_OCRstream
)
1061 MP4_GET2BYTES( es_descriptor
.i_OCR_ES_ID
);
1063 MP4_GET1BYTE( i_type
); /* get next type */
1066 if( i_type
!= 0x04)/* MP4DecConfigDescrTag */
1068 es_descriptor
.p_decConfigDescr
= NULL
;
1069 MP4_READBOX_EXIT( 1 ); /* rest isn't interesting up to now */
1072 i_len
= MP4_ReadLengthDescriptor( &p_peek
, &i_read
);
1075 msg_Dbg( p_stream
, "found esds MP4DecConfigDescr (%dBytes)",
1079 es_descriptor
.p_decConfigDescr
=
1080 calloc( 1, sizeof( MP4_descriptor_decoder_config_t
));
1081 if( es_descriptor
.p_decConfigDescr
== NULL
)
1082 MP4_READBOX_EXIT( 0 );
1084 MP4_GET1BYTE( es_descriptor
.p_decConfigDescr
->i_objectTypeIndication
);
1085 MP4_GET1BYTE( i_flags
);
1086 es_descriptor
.p_decConfigDescr
->i_streamType
= i_flags
>> 2;
1087 es_descriptor
.p_decConfigDescr
->b_upStream
= ( i_flags
>> 1 )&0x01;
1088 MP4_GET3BYTES( es_descriptor
.p_decConfigDescr
->i_buffer_sizeDB
);
1089 MP4_GET4BYTES( es_descriptor
.p_decConfigDescr
->i_max_bitrate
);
1090 MP4_GET4BYTES( es_descriptor
.p_decConfigDescr
->i_avg_bitrate
);
1091 MP4_GET1BYTE( i_type
);
1092 if( i_type
!= 0x05 )/* MP4DecSpecificDescrTag */
1094 es_descriptor
.p_decConfigDescr
->i_decoder_specific_info_len
= 0;
1095 es_descriptor
.p_decConfigDescr
->p_decoder_specific_info
= NULL
;
1096 MP4_READBOX_EXIT( 1 );
1099 i_len
= MP4_ReadLengthDescriptor( &p_peek
, &i_read
);
1102 msg_Dbg( p_stream
, "found esds MP4DecSpecificDescr (%dBytes)",
1105 if( i_len
> i_read
)
1106 MP4_READBOX_EXIT( 0 );
1108 es_descriptor
.p_decConfigDescr
->i_decoder_specific_info_len
= i_len
;
1109 es_descriptor
.p_decConfigDescr
->p_decoder_specific_info
= malloc( i_len
);
1110 if( es_descriptor
.p_decConfigDescr
->p_decoder_specific_info
== NULL
)
1111 MP4_READBOX_EXIT( 0 );
1113 memcpy( es_descriptor
.p_decConfigDescr
->p_decoder_specific_info
,
1116 MP4_READBOX_EXIT( 1 );
1117 #undef es_descriptor
1120 static void MP4_FreeBox_avcC( MP4_Box_t
*p_box
)
1122 MP4_Box_data_avcC_t
*p_avcC
= p_box
->data
.p_avcC
;
1125 if( p_avcC
->i_avcC
> 0 ) FREENULL( p_avcC
->p_avcC
);
1129 for( i
= 0; i
< p_avcC
->i_sps
; i
++ )
1130 FREENULL( p_avcC
->sps
[i
] );
1134 for( i
= 0; i
< p_avcC
->i_pps
; i
++ )
1135 FREENULL( p_avcC
->pps
[i
] );
1137 if( p_avcC
->i_sps
> 0 ) FREENULL( p_avcC
->sps
);
1138 if( p_avcC
->i_sps
> 0 ) FREENULL( p_avcC
->i_sps_length
);
1139 if( p_avcC
->i_pps
> 0 ) FREENULL( p_avcC
->pps
);
1140 if( p_avcC
->i_pps
> 0 ) FREENULL( p_avcC
->i_pps_length
);
1143 static int MP4_ReadBox_avcC( stream_t
*p_stream
, MP4_Box_t
*p_box
)
1145 MP4_Box_data_avcC_t
*p_avcC
;
1148 MP4_READBOX_ENTER( MP4_Box_data_avcC_t
);
1149 p_avcC
= p_box
->data
.p_avcC
;
1151 p_avcC
->i_avcC
= i_read
;
1152 if( p_avcC
->i_avcC
> 0 )
1154 uint8_t * p
= p_avcC
->p_avcC
= malloc( p_avcC
->i_avcC
);
1156 memcpy( p
, p_peek
, i_read
);
1159 MP4_GET1BYTE( p_avcC
->i_version
);
1160 MP4_GET1BYTE( p_avcC
->i_profile
);
1161 MP4_GET1BYTE( p_avcC
->i_profile_compatibility
);
1162 MP4_GET1BYTE( p_avcC
->i_level
);
1163 MP4_GET1BYTE( p_avcC
->i_reserved1
);
1164 p_avcC
->i_length_size
= (p_avcC
->i_reserved1
&0x03) + 1;
1165 p_avcC
->i_reserved1
>>= 2;
1167 MP4_GET1BYTE( p_avcC
->i_reserved2
);
1168 p_avcC
->i_sps
= p_avcC
->i_reserved2
&0x1f;
1169 p_avcC
->i_reserved2
>>= 5;
1171 if( p_avcC
->i_sps
> 0 )
1173 p_avcC
->i_sps_length
= calloc( p_avcC
->i_sps
, sizeof( uint16_t ) );
1174 p_avcC
->sps
= calloc( p_avcC
->i_sps
, sizeof( uint8_t* ) );
1176 if( !p_avcC
->i_sps_length
|| !p_avcC
->sps
)
1179 for( i
= 0; i
< p_avcC
->i_sps
; i
++ )
1181 MP4_GET2BYTES( p_avcC
->i_sps_length
[i
] );
1182 p_avcC
->sps
[i
] = malloc( p_avcC
->i_sps_length
[i
] );
1183 if( p_avcC
->sps
[i
] )
1184 memcpy( p_avcC
->sps
[i
], p_peek
, p_avcC
->i_sps_length
[i
] );
1186 p_peek
+= p_avcC
->i_sps_length
[i
];
1187 i_read
-= p_avcC
->i_sps_length
[i
];
1191 MP4_GET1BYTE( p_avcC
->i_pps
);
1192 if( p_avcC
->i_pps
> 0 )
1194 p_avcC
->i_pps_length
= calloc( p_avcC
->i_pps
, sizeof( uint16_t ) );
1195 p_avcC
->pps
= calloc( p_avcC
->i_pps
, sizeof( uint8_t* ) );
1197 if( !p_avcC
->i_pps_length
|| !p_avcC
->pps
)
1200 for( i
= 0; i
< p_avcC
->i_pps
; i
++ )
1202 MP4_GET2BYTES( p_avcC
->i_pps_length
[i
] );
1203 p_avcC
->pps
[i
] = malloc( p_avcC
->i_pps_length
[i
] );
1204 if( p_avcC
->pps
[i
] )
1205 memcpy( p_avcC
->pps
[i
], p_peek
, p_avcC
->i_pps_length
[i
] );
1207 p_peek
+= p_avcC
->i_pps_length
[i
];
1208 i_read
-= p_avcC
->i_pps_length
[i
];
1213 "read box: \"avcC\" version=%d profile=0x%x level=0x%x length size=%d sps=%d pps=%d",
1214 p_avcC
->i_version
, p_avcC
->i_profile
, p_avcC
->i_level
,
1215 p_avcC
->i_length_size
,
1216 p_avcC
->i_sps
, p_avcC
->i_pps
);
1217 for( i
= 0; i
< p_avcC
->i_sps
; i
++ )
1219 msg_Dbg( p_stream
, " - sps[%d] length=%d",
1220 i
, p_avcC
->i_sps_length
[i
] );
1222 for( i
= 0; i
< p_avcC
->i_pps
; i
++ )
1224 msg_Dbg( p_stream
, " - pps[%d] length=%d",
1225 i
, p_avcC
->i_pps_length
[i
] );
1229 MP4_READBOX_EXIT( 1 );
1232 MP4_READBOX_EXIT( 0 );
1235 static int MP4_ReadBox_dac3( stream_t
*p_stream
, MP4_Box_t
*p_box
)
1237 MP4_Box_data_dac3_t
*p_dac3
;
1238 MP4_READBOX_ENTER( MP4_Box_data_dac3_t
);
1240 p_dac3
= p_box
->data
.p_dac3
;
1243 MP4_GET3BYTES( i_header
);
1245 p_dac3
->i_fscod
= ( i_header
>> 22 ) & 0x03;
1246 p_dac3
->i_bsid
= ( i_header
>> 17 ) & 0x01f;
1247 p_dac3
->i_bsmod
= ( i_header
>> 14 ) & 0x07;
1248 p_dac3
->i_acmod
= ( i_header
>> 11 ) & 0x07;
1249 p_dac3
->i_lfeon
= ( i_header
>> 10 ) & 0x01;
1250 p_dac3
->i_bitrate_code
= ( i_header
>> 5) & 0x1f;
1254 "read box: \"dac3\" fscod=0x%x bsid=0x%x bsmod=0x%x acmod=0x%x lfeon=0x%x bitrate_code=0x%x",
1255 p_dac3
->i_fscod
, p_dac3
->i_bsid
, p_dac3
->i_bsmod
, p_dac3
->i_acmod
, p_dac3
->i_lfeon
, p_dac3
->i_bitrate_code
);
1257 MP4_READBOX_EXIT( 1 );
1260 static int MP4_ReadBox_enda( stream_t
*p_stream
, MP4_Box_t
*p_box
)
1262 MP4_Box_data_enda_t
*p_enda
;
1263 MP4_READBOX_ENTER( MP4_Box_data_enda_t
);
1265 p_enda
= p_box
->data
.p_enda
;
1267 MP4_GET2BYTES( p_enda
->i_little_endian
);
1271 "read box: \"enda\" little_endian=%d", p_enda
->i_little_endian
);
1273 MP4_READBOX_EXIT( 1 );
1276 static int MP4_ReadBox_gnre( stream_t
*p_stream
, MP4_Box_t
*p_box
)
1278 MP4_Box_data_gnre_t
*p_gnre
;
1279 MP4_READBOX_ENTER( MP4_Box_data_gnre_t
);
1281 p_gnre
= p_box
->data
.p_gnre
;
1283 uint32_t i_data_len
;
1284 uint32_t i_data_tag
;
1286 MP4_GET4BYTES( i_data_len
);
1287 MP4_GETFOURCC( i_data_tag
);
1288 if( i_data_len
< 10 || i_data_tag
!= ATOM_data
)
1289 MP4_READBOX_EXIT( 0 );
1292 uint32_t i_reserved
;
1293 MP4_GET4BYTES( i_version
);
1294 MP4_GET4BYTES( i_reserved
);
1295 MP4_GET2BYTES( p_gnre
->i_genre
);
1296 if( p_gnre
->i_genre
== 0 )
1297 MP4_READBOX_EXIT( 0 );
1299 msg_Dbg( p_stream
, "read box: \"gnre\" genre=%i", p_gnre
->i_genre
);
1302 MP4_READBOX_EXIT( 1 );
1305 static int MP4_ReadBox_trkn( stream_t
*p_stream
, MP4_Box_t
*p_box
)
1307 MP4_Box_data_trkn_t
*p_trkn
;
1308 MP4_READBOX_ENTER( MP4_Box_data_trkn_t
);
1310 p_trkn
= p_box
->data
.p_trkn
;
1312 uint32_t i_data_len
;
1313 uint32_t i_data_tag
;
1315 MP4_GET4BYTES( i_data_len
);
1316 MP4_GETFOURCC( i_data_tag
);
1317 if( i_data_len
< 12 || i_data_tag
!= ATOM_data
)
1318 MP4_READBOX_EXIT( 0 );
1321 uint32_t i_reserved
;
1322 MP4_GET4BYTES( i_version
);
1323 MP4_GET4BYTES( i_reserved
);
1324 MP4_GET4BYTES( p_trkn
->i_track_number
);
1326 msg_Dbg( p_stream
, "read box: \"trkn\" number=%i", p_trkn
->i_track_number
);
1328 if( i_data_len
> 15 )
1330 MP4_GET4BYTES( p_trkn
->i_track_total
);
1332 msg_Dbg( p_stream
, "read box: \"trkn\" total=%i", p_trkn
->i_track_total
);
1336 MP4_READBOX_EXIT( 1 );
1340 static int MP4_ReadBox_sample_soun( stream_t
*p_stream
, MP4_Box_t
*p_box
)
1344 MP4_READBOX_ENTER( MP4_Box_data_sample_soun_t
);
1345 p_box
->data
.p_sample_soun
->p_qt_description
= NULL
;
1347 /* Sanity check needed because the "wave" box does also contain an
1348 * "mp4a" box that we don't understand. */
1352 MP4_READBOX_EXIT( 1 );
1355 for( i
= 0; i
< 6 ; i
++ )
1357 MP4_GET1BYTE( p_box
->data
.p_sample_soun
->i_reserved1
[i
] );
1360 MP4_GET2BYTES( p_box
->data
.p_sample_soun
->i_data_reference_index
);
1363 * XXX hack -> produce a copy of the nearly complete chunk
1365 p_box
->data
.p_sample_soun
->i_qt_description
= 0;
1366 p_box
->data
.p_sample_soun
->p_qt_description
= NULL
;
1369 p_box
->data
.p_sample_soun
->p_qt_description
= malloc( i_read
);
1370 if( p_box
->data
.p_sample_soun
->p_qt_description
)
1372 p_box
->data
.p_sample_soun
->i_qt_description
= i_read
;
1373 memcpy( p_box
->data
.p_sample_soun
->p_qt_description
, p_peek
, i_read
);
1377 MP4_GET2BYTES( p_box
->data
.p_sample_soun
->i_qt_version
);
1378 MP4_GET2BYTES( p_box
->data
.p_sample_soun
->i_qt_revision_level
);
1379 MP4_GET4BYTES( p_box
->data
.p_sample_soun
->i_qt_vendor
);
1381 MP4_GET2BYTES( p_box
->data
.p_sample_soun
->i_channelcount
);
1382 MP4_GET2BYTES( p_box
->data
.p_sample_soun
->i_samplesize
);
1383 MP4_GET2BYTES( p_box
->data
.p_sample_soun
->i_predefined
);
1384 MP4_GET2BYTES( p_box
->data
.p_sample_soun
->i_reserved3
);
1385 MP4_GET2BYTES( p_box
->data
.p_sample_soun
->i_sampleratehi
);
1386 MP4_GET2BYTES( p_box
->data
.p_sample_soun
->i_sampleratelo
);
1388 if( p_box
->data
.p_sample_soun
->i_qt_version
== 1 && i_read
>= 16 )
1390 /* SoundDescriptionV1 */
1391 MP4_GET4BYTES( p_box
->data
.p_sample_soun
->i_sample_per_packet
);
1392 MP4_GET4BYTES( p_box
->data
.p_sample_soun
->i_bytes_per_packet
);
1393 MP4_GET4BYTES( p_box
->data
.p_sample_soun
->i_bytes_per_frame
);
1394 MP4_GET4BYTES( p_box
->data
.p_sample_soun
->i_bytes_per_sample
);
1398 "read box: \"soun\" qt3+ sample/packet=%d bytes/packet=%d "
1399 "bytes/frame=%d bytes/sample=%d",
1400 p_box
->data
.p_sample_soun
->i_sample_per_packet
,
1401 p_box
->data
.p_sample_soun
->i_bytes_per_packet
,
1402 p_box
->data
.p_sample_soun
->i_bytes_per_frame
,
1403 p_box
->data
.p_sample_soun
->i_bytes_per_sample
);
1405 stream_Seek( p_stream
, p_box
->i_pos
+
1406 mp4_box_headersize( p_box
) + 44 );
1408 else if( p_box
->data
.p_sample_soun
->i_qt_version
== 2 && i_read
>= 36 )
1410 /* SoundDescriptionV2 */
1411 double f_sample_rate
;
1415 MP4_GET4BYTES( p_box
->data
.p_sample_soun
->i_sample_per_packet
);
1416 MP4_GET8BYTES( dummy
);
1417 memcpy( &f_sample_rate
, &dummy
, 8 );
1419 msg_Dbg( p_stream
, "read box: %f Hz", f_sample_rate
);
1420 p_box
->data
.p_sample_soun
->i_sampleratehi
= (int)f_sample_rate
% 65536;
1421 p_box
->data
.p_sample_soun
->i_sampleratelo
= f_sample_rate
/ 65536;
1423 MP4_GET4BYTES( i_channel
);
1424 p_box
->data
.p_sample_soun
->i_channelcount
= i_channel
;
1427 msg_Dbg( p_stream
, "read box: \"soun\" V2" );
1429 stream_Seek( p_stream
, p_box
->i_pos
+
1430 mp4_box_headersize( p_box
) + 28 + 36 );
1434 p_box
->data
.p_sample_soun
->i_sample_per_packet
= 0;
1435 p_box
->data
.p_sample_soun
->i_bytes_per_packet
= 0;
1436 p_box
->data
.p_sample_soun
->i_bytes_per_frame
= 0;
1437 p_box
->data
.p_sample_soun
->i_bytes_per_sample
= 0;
1440 msg_Dbg( p_stream
, "read box: \"soun\" mp4 or qt1/2 (rest=%"PRId64
")",
1443 stream_Seek( p_stream
, p_box
->i_pos
+
1444 mp4_box_headersize( p_box
) + 28 );
1447 if( p_box
->i_type
== ATOM_drms
)
1449 char *home
= config_GetUserDir( VLC_HOME_DIR
);
1452 p_box
->data
.p_sample_soun
->p_drms
= drms_alloc( home
);
1453 if( p_box
->data
.p_sample_soun
->p_drms
== NULL
)
1454 msg_Err( p_stream
, "drms_alloc() failed" );
1458 if( p_box
->i_type
== ATOM_samr
|| p_box
->i_type
== ATOM_sawb
)
1460 /* Ignore channelcount for AMR (3gpp AMRSpecificBox) */
1461 p_box
->data
.p_sample_soun
->i_channelcount
= 1;
1464 MP4_ReadBoxContainerRaw( p_stream
, p_box
); /* esds/wave/... */
1467 msg_Dbg( p_stream
, "read box: \"soun\" in stsd channel %d "
1468 "sample size %d sample rate %f",
1469 p_box
->data
.p_sample_soun
->i_channelcount
,
1470 p_box
->data
.p_sample_soun
->i_samplesize
,
1471 (float)p_box
->data
.p_sample_soun
->i_sampleratehi
+
1472 (float)p_box
->data
.p_sample_soun
->i_sampleratelo
/ 65536 );
1475 MP4_READBOX_EXIT( 1 );
1479 static void MP4_FreeBox_sample_soun( MP4_Box_t
*p_box
)
1481 FREENULL( p_box
->data
.p_sample_soun
->p_qt_description
);
1483 if( p_box
->i_type
== ATOM_drms
)
1485 if( p_box
->data
.p_sample_soun
->p_drms
)
1487 drms_free( p_box
->data
.p_sample_soun
->p_drms
);
1493 int MP4_ReadBox_sample_vide( stream_t
*p_stream
, MP4_Box_t
*p_box
)
1497 MP4_READBOX_ENTER( MP4_Box_data_sample_vide_t
);
1499 for( i
= 0; i
< 6 ; i
++ )
1501 MP4_GET1BYTE( p_box
->data
.p_sample_vide
->i_reserved1
[i
] );
1504 MP4_GET2BYTES( p_box
->data
.p_sample_vide
->i_data_reference_index
);
1507 * XXX hack -> produce a copy of the nearly complete chunk
1511 p_box
->data
.p_sample_vide
->p_qt_image_description
= malloc( i_read
);
1512 if( p_box
->data
.p_sample_vide
->p_qt_image_description
== NULL
)
1513 MP4_READBOX_EXIT( 0 );
1514 p_box
->data
.p_sample_vide
->i_qt_image_description
= i_read
;
1515 memcpy( p_box
->data
.p_sample_vide
->p_qt_image_description
,
1520 p_box
->data
.p_sample_vide
->i_qt_image_description
= 0;
1521 p_box
->data
.p_sample_vide
->p_qt_image_description
= NULL
;
1524 MP4_GET2BYTES( p_box
->data
.p_sample_vide
->i_qt_version
);
1525 MP4_GET2BYTES( p_box
->data
.p_sample_vide
->i_qt_revision_level
);
1526 MP4_GET4BYTES( p_box
->data
.p_sample_vide
->i_qt_vendor
);
1528 MP4_GET4BYTES( p_box
->data
.p_sample_vide
->i_qt_temporal_quality
);
1529 MP4_GET4BYTES( p_box
->data
.p_sample_vide
->i_qt_spatial_quality
);
1531 MP4_GET2BYTES( p_box
->data
.p_sample_vide
->i_width
);
1532 MP4_GET2BYTES( p_box
->data
.p_sample_vide
->i_height
);
1534 MP4_GET4BYTES( p_box
->data
.p_sample_vide
->i_horizresolution
);
1535 MP4_GET4BYTES( p_box
->data
.p_sample_vide
->i_vertresolution
);
1537 MP4_GET4BYTES( p_box
->data
.p_sample_vide
->i_qt_data_size
);
1538 MP4_GET2BYTES( p_box
->data
.p_sample_vide
->i_qt_frame_count
);
1540 memcpy( &p_box
->data
.p_sample_vide
->i_compressorname
, p_peek
, 32 );
1541 p_peek
+= 32; i_read
-= 32;
1543 MP4_GET2BYTES( p_box
->data
.p_sample_vide
->i_depth
);
1544 MP4_GET2BYTES( p_box
->data
.p_sample_vide
->i_qt_color_table
);
1546 stream_Seek( p_stream
, p_box
->i_pos
+ mp4_box_headersize( p_box
) + 78);
1548 if( p_box
->i_type
== ATOM_drmi
)
1550 char *home
= config_GetUserDir( VLC_HOME_DIR
);
1553 p_box
->data
.p_sample_vide
->p_drms
= drms_alloc( home
);
1554 if( p_box
->data
.p_sample_vide
->p_drms
== NULL
)
1555 msg_Err( p_stream
, "drms_alloc() failed" );
1559 MP4_ReadBoxContainerRaw( p_stream
, p_box
);
1562 msg_Dbg( p_stream
, "read box: \"vide\" in stsd %dx%d depth %d",
1563 p_box
->data
.p_sample_vide
->i_width
,
1564 p_box
->data
.p_sample_vide
->i_height
,
1565 p_box
->data
.p_sample_vide
->i_depth
);
1568 MP4_READBOX_EXIT( 1 );
1572 void MP4_FreeBox_sample_vide( MP4_Box_t
*p_box
)
1574 FREENULL( p_box
->data
.p_sample_vide
->p_qt_image_description
);
1576 if( p_box
->i_type
== ATOM_drmi
)
1578 if( p_box
->data
.p_sample_vide
->p_drms
)
1580 drms_free( p_box
->data
.p_sample_vide
->p_drms
);
1585 static int MP4_ReadBox_sample_mp4s( stream_t
*p_stream
, MP4_Box_t
*p_box
)
1587 stream_Seek( p_stream
, p_box
->i_pos
+ mp4_box_headersize( p_box
) + 8 );
1588 MP4_ReadBoxContainerRaw( p_stream
, p_box
);
1592 static int MP4_ReadBox_sample_text( stream_t
*p_stream
, MP4_Box_t
*p_box
)
1596 MP4_READBOX_ENTER( MP4_Box_data_sample_text_t
);
1598 MP4_GET4BYTES( p_box
->data
.p_sample_text
->i_reserved1
);
1599 MP4_GET2BYTES( p_box
->data
.p_sample_text
->i_reserved2
);
1601 MP4_GET2BYTES( p_box
->data
.p_sample_text
->i_data_reference_index
);
1603 MP4_GET4BYTES( p_box
->data
.p_sample_text
->i_display_flags
);
1608 /* FIXME search right signification */
1610 p_box
->data
.p_sample_text
->i_justification_horizontal
= 1;
1611 p_box
->data
.p_sample_text
->i_justification_vertical
= 1;
1613 case -1: // Flush Right
1614 p_box
->data
.p_sample_text
->i_justification_horizontal
= -1;
1615 p_box
->data
.p_sample_text
->i_justification_vertical
= -1;
1617 case -2: // Flush Left
1618 p_box
->data
.p_sample_text
->i_justification_horizontal
= 0;
1619 p_box
->data
.p_sample_text
->i_justification_vertical
= 0;
1621 case 0: // Flush Default
1623 p_box
->data
.p_sample_text
->i_justification_horizontal
= 1;
1624 p_box
->data
.p_sample_text
->i_justification_vertical
= -1;
1628 MP4_GET2BYTES( p_box
->data
.p_sample_text
->i_background_color
[0] );
1629 MP4_GET2BYTES( p_box
->data
.p_sample_text
->i_background_color
[1] );
1630 MP4_GET2BYTES( p_box
->data
.p_sample_text
->i_background_color
[2] );
1631 p_box
->data
.p_sample_text
->i_background_color
[3] = 0;
1633 MP4_GET2BYTES( p_box
->data
.p_sample_text
->i_text_box_top
);
1634 MP4_GET2BYTES( p_box
->data
.p_sample_text
->i_text_box_left
);
1635 MP4_GET2BYTES( p_box
->data
.p_sample_text
->i_text_box_bottom
);
1636 MP4_GET2BYTES( p_box
->data
.p_sample_text
->i_text_box_right
);
1639 msg_Dbg( p_stream
, "read box: \"text\" in stsd text" );
1641 MP4_READBOX_EXIT( 1 );
1644 static int MP4_ReadBox_sample_tx3g( stream_t
*p_stream
, MP4_Box_t
*p_box
)
1646 MP4_READBOX_ENTER( MP4_Box_data_sample_text_t
);
1648 MP4_GET4BYTES( p_box
->data
.p_sample_text
->i_reserved1
);
1649 MP4_GET2BYTES( p_box
->data
.p_sample_text
->i_reserved2
);
1651 MP4_GET2BYTES( p_box
->data
.p_sample_text
->i_data_reference_index
);
1653 MP4_GET4BYTES( p_box
->data
.p_sample_text
->i_display_flags
);
1655 MP4_GET1BYTE ( p_box
->data
.p_sample_text
->i_justification_horizontal
);
1656 MP4_GET1BYTE ( p_box
->data
.p_sample_text
->i_justification_vertical
);
1658 MP4_GET1BYTE ( p_box
->data
.p_sample_text
->i_background_color
[0] );
1659 MP4_GET1BYTE ( p_box
->data
.p_sample_text
->i_background_color
[1] );
1660 MP4_GET1BYTE ( p_box
->data
.p_sample_text
->i_background_color
[2] );
1661 MP4_GET1BYTE ( p_box
->data
.p_sample_text
->i_background_color
[3] );
1663 MP4_GET2BYTES( p_box
->data
.p_sample_text
->i_text_box_top
);
1664 MP4_GET2BYTES( p_box
->data
.p_sample_text
->i_text_box_left
);
1665 MP4_GET2BYTES( p_box
->data
.p_sample_text
->i_text_box_bottom
);
1666 MP4_GET2BYTES( p_box
->data
.p_sample_text
->i_text_box_right
);
1669 msg_Dbg( p_stream
, "read box: \"tx3g\" in stsd text" );
1671 MP4_READBOX_EXIT( 1 );
1676 /* We can't easily call it, and anyway ~ 20 bytes lost isn't a real problem */
1677 static void MP4_FreeBox_sample_text( MP4_Box_t
*p_box
)
1679 FREENULL( p_box
->data
.p_sample_text
->psz_text_name
);
1684 static int MP4_ReadBox_stsd( stream_t
*p_stream
, MP4_Box_t
*p_box
)
1687 MP4_READBOX_ENTER( MP4_Box_data_stsd_t
);
1689 MP4_GETVERSIONFLAGS( p_box
->data
.p_stsd
);
1691 MP4_GET4BYTES( p_box
->data
.p_stsd
->i_entry_count
);
1693 stream_Seek( p_stream
, p_box
->i_pos
+ mp4_box_headersize( p_box
) + 8 );
1695 MP4_ReadBoxContainerRaw( p_stream
, p_box
);
1698 msg_Dbg( p_stream
, "read box: \"stsd\" entry-count %d",
1699 p_box
->data
.p_stsd
->i_entry_count
);
1702 MP4_READBOX_EXIT( 1 );
1706 static int MP4_ReadBox_stsz( stream_t
*p_stream
, MP4_Box_t
*p_box
)
1710 MP4_READBOX_ENTER( MP4_Box_data_stsz_t
);
1712 MP4_GETVERSIONFLAGS( p_box
->data
.p_stsz
);
1714 MP4_GET4BYTES( p_box
->data
.p_stsz
->i_sample_size
);
1716 MP4_GET4BYTES( p_box
->data
.p_stsz
->i_sample_count
);
1718 p_box
->data
.p_stsz
->i_entry_size
=
1719 calloc( p_box
->data
.p_stsz
->i_sample_count
, sizeof(uint32_t) );
1720 if( p_box
->data
.p_stsz
->i_entry_size
== NULL
)
1721 MP4_READBOX_EXIT( 0 );
1723 if( !p_box
->data
.p_stsz
->i_sample_size
)
1725 for( i
=0; (i
<p_box
->data
.p_stsz
->i_sample_count
)&&(i_read
>= 4 ); i
++ )
1727 MP4_GET4BYTES( p_box
->data
.p_stsz
->i_entry_size
[i
] );
1732 msg_Dbg( p_stream
, "read box: \"stsz\" sample-size %d sample-count %d",
1733 p_box
->data
.p_stsz
->i_sample_size
,
1734 p_box
->data
.p_stsz
->i_sample_count
);
1737 MP4_READBOX_EXIT( 1 );
1740 static void MP4_FreeBox_stsz( MP4_Box_t
*p_box
)
1742 FREENULL( p_box
->data
.p_stsz
->i_entry_size
);
1745 static void MP4_FreeBox_stsc( MP4_Box_t
*p_box
)
1747 FREENULL( p_box
->data
.p_stsc
->i_first_chunk
);
1748 FREENULL( p_box
->data
.p_stsc
->i_samples_per_chunk
);
1749 FREENULL( p_box
->data
.p_stsc
->i_sample_description_index
);
1752 static int MP4_ReadBox_stsc( stream_t
*p_stream
, MP4_Box_t
*p_box
)
1756 MP4_READBOX_ENTER( MP4_Box_data_stsc_t
);
1758 MP4_GETVERSIONFLAGS( p_box
->data
.p_stsc
);
1760 MP4_GET4BYTES( p_box
->data
.p_stsc
->i_entry_count
);
1762 p_box
->data
.p_stsc
->i_first_chunk
=
1763 calloc( p_box
->data
.p_stsc
->i_entry_count
, sizeof(uint32_t) );
1764 p_box
->data
.p_stsc
->i_samples_per_chunk
=
1765 calloc( p_box
->data
.p_stsc
->i_entry_count
, sizeof(uint32_t) );
1766 p_box
->data
.p_stsc
->i_sample_description_index
=
1767 calloc( p_box
->data
.p_stsc
->i_entry_count
, sizeof(uint32_t) );
1768 if( p_box
->data
.p_stsc
->i_first_chunk
== NULL
1769 || p_box
->data
.p_stsc
->i_samples_per_chunk
== NULL
1770 || p_box
->data
.p_stsc
->i_sample_description_index
== NULL
)
1772 MP4_READBOX_EXIT( 0 );
1775 for( i
= 0; (i
< p_box
->data
.p_stsc
->i_entry_count
)&&( i_read
>= 12 );i
++ )
1777 MP4_GET4BYTES( p_box
->data
.p_stsc
->i_first_chunk
[i
] );
1778 MP4_GET4BYTES( p_box
->data
.p_stsc
->i_samples_per_chunk
[i
] );
1779 MP4_GET4BYTES( p_box
->data
.p_stsc
->i_sample_description_index
[i
] );
1783 msg_Dbg( p_stream
, "read box: \"stsc\" entry-count %d",
1784 p_box
->data
.p_stsc
->i_entry_count
);
1787 MP4_READBOX_EXIT( 1 );
1790 static int MP4_ReadBox_stco_co64( stream_t
*p_stream
, MP4_Box_t
*p_box
)
1794 MP4_READBOX_ENTER( MP4_Box_data_co64_t
);
1796 MP4_GETVERSIONFLAGS( p_box
->data
.p_co64
);
1798 MP4_GET4BYTES( p_box
->data
.p_co64
->i_entry_count
);
1800 p_box
->data
.p_co64
->i_chunk_offset
=
1801 calloc( p_box
->data
.p_co64
->i_entry_count
, sizeof(uint64_t) );
1802 if( p_box
->data
.p_co64
->i_chunk_offset
== NULL
)
1803 MP4_READBOX_EXIT( 0 );
1805 for( i
= 0; i
< p_box
->data
.p_co64
->i_entry_count
; i
++ )
1807 if( p_box
->i_type
== ATOM_stco
)
1813 MP4_GET4BYTES( p_box
->data
.p_co64
->i_chunk_offset
[i
] );
1821 MP4_GET8BYTES( p_box
->data
.p_co64
->i_chunk_offset
[i
] );
1826 msg_Dbg( p_stream
, "read box: \"co64\" entry-count %d",
1827 p_box
->data
.p_co64
->i_entry_count
);
1830 MP4_READBOX_EXIT( 1 );
1833 static void MP4_FreeBox_stco_co64( MP4_Box_t
*p_box
)
1835 FREENULL( p_box
->data
.p_co64
->i_chunk_offset
);
1838 static int MP4_ReadBox_stss( stream_t
*p_stream
, MP4_Box_t
*p_box
)
1842 MP4_READBOX_ENTER( MP4_Box_data_stss_t
);
1844 MP4_GETVERSIONFLAGS( p_box
->data
.p_stss
);
1846 MP4_GET4BYTES( p_box
->data
.p_stss
->i_entry_count
);
1848 p_box
->data
.p_stss
->i_sample_number
=
1849 calloc( p_box
->data
.p_stss
->i_entry_count
, sizeof(uint32_t) );
1850 if( p_box
->data
.p_stss
->i_sample_number
== NULL
)
1851 MP4_READBOX_EXIT( 0 );
1853 for( i
= 0; (i
< p_box
->data
.p_stss
->i_entry_count
)&&( i_read
>= 4 ); i
++ )
1856 MP4_GET4BYTES( p_box
->data
.p_stss
->i_sample_number
[i
] );
1857 /* XXX in libmp4 sample begin at 0 */
1858 p_box
->data
.p_stss
->i_sample_number
[i
]--;
1862 msg_Dbg( p_stream
, "read box: \"stss\" entry-count %d",
1863 p_box
->data
.p_stss
->i_entry_count
);
1866 MP4_READBOX_EXIT( 1 );
1869 static void MP4_FreeBox_stss( MP4_Box_t
*p_box
)
1871 FREENULL( p_box
->data
.p_stss
->i_sample_number
);
1874 static void MP4_FreeBox_stsh( MP4_Box_t
*p_box
)
1876 FREENULL( p_box
->data
.p_stsh
->i_shadowed_sample_number
);
1877 FREENULL( p_box
->data
.p_stsh
->i_sync_sample_number
);
1880 static int MP4_ReadBox_stsh( stream_t
*p_stream
, MP4_Box_t
*p_box
)
1884 MP4_READBOX_ENTER( MP4_Box_data_stsh_t
);
1886 MP4_GETVERSIONFLAGS( p_box
->data
.p_stsh
);
1889 MP4_GET4BYTES( p_box
->data
.p_stsh
->i_entry_count
);
1891 p_box
->data
.p_stsh
->i_shadowed_sample_number
=
1892 calloc( p_box
->data
.p_stsh
->i_entry_count
, sizeof(uint32_t) );
1893 p_box
->data
.p_stsh
->i_sync_sample_number
=
1894 calloc( p_box
->data
.p_stsh
->i_entry_count
, sizeof(uint32_t) );
1896 if( p_box
->data
.p_stsh
->i_shadowed_sample_number
== NULL
1897 || p_box
->data
.p_stsh
->i_sync_sample_number
== NULL
)
1899 MP4_READBOX_EXIT( 0 );
1902 for( i
= 0; (i
< p_box
->data
.p_stss
->i_entry_count
)&&( i_read
>= 8 ); i
++ )
1905 MP4_GET4BYTES( p_box
->data
.p_stsh
->i_shadowed_sample_number
[i
] );
1906 MP4_GET4BYTES( p_box
->data
.p_stsh
->i_sync_sample_number
[i
] );
1910 msg_Dbg( p_stream
, "read box: \"stsh\" entry-count %d",
1911 p_box
->data
.p_stsh
->i_entry_count
);
1913 MP4_READBOX_EXIT( 1 );
1917 static int MP4_ReadBox_stdp( stream_t
*p_stream
, MP4_Box_t
*p_box
)
1921 MP4_READBOX_ENTER( MP4_Box_data_stdp_t
);
1923 MP4_GETVERSIONFLAGS( p_box
->data
.p_stdp
);
1925 p_box
->data
.p_stdp
->i_priority
=
1926 calloc( i_read
/ 2, sizeof(uint16_t) );
1928 for( i
= 0; i
< i_read
/ 2 ; i
++ )
1931 MP4_GET2BYTES( p_box
->data
.p_stdp
->i_priority
[i
] );
1935 msg_Dbg( p_stream
, "read box: \"stdp\" entry-count %"PRId64
,
1939 MP4_READBOX_EXIT( 1 );
1942 static void MP4_FreeBox_stdp( MP4_Box_t
*p_box
)
1944 FREENULL( p_box
->data
.p_stdp
->i_priority
);
1947 static void MP4_FreeBox_padb( MP4_Box_t
*p_box
)
1949 FREENULL( p_box
->data
.p_padb
->i_reserved1
);
1950 FREENULL( p_box
->data
.p_padb
->i_pad2
);
1951 FREENULL( p_box
->data
.p_padb
->i_reserved2
);
1952 FREENULL( p_box
->data
.p_padb
->i_pad1
);
1955 static int MP4_ReadBox_padb( stream_t
*p_stream
, MP4_Box_t
*p_box
)
1960 MP4_READBOX_ENTER( MP4_Box_data_padb_t
);
1962 MP4_GETVERSIONFLAGS( p_box
->data
.p_padb
);
1964 MP4_GET4BYTES( p_box
->data
.p_padb
->i_sample_count
);
1965 count
= (p_box
->data
.p_padb
->i_sample_count
+ 1) / 2;
1967 p_box
->data
.p_padb
->i_reserved1
= calloc( count
, sizeof(uint16_t) );
1968 p_box
->data
.p_padb
->i_pad2
= calloc( count
, sizeof(uint16_t) );
1969 p_box
->data
.p_padb
->i_reserved2
= calloc( count
, sizeof(uint16_t) );
1970 p_box
->data
.p_padb
->i_pad1
= calloc( count
, sizeof(uint16_t) );
1971 if( p_box
->data
.p_padb
->i_reserved1
== NULL
1972 || p_box
->data
.p_padb
->i_pad2
== NULL
1973 || p_box
->data
.p_padb
->i_reserved2
== NULL
1974 || p_box
->data
.p_padb
->i_pad1
== NULL
)
1976 MP4_READBOX_EXIT( 0 );
1979 for( i
= 0; i
< i_read
/ 2 ; i
++ )
1983 MP4_READBOX_EXIT( 0 );
1985 p_box
->data
.p_padb
->i_reserved1
[i
] = ( (*p_peek
) >> 7 )&0x01;
1986 p_box
->data
.p_padb
->i_pad2
[i
] = ( (*p_peek
) >> 4 )&0x07;
1987 p_box
->data
.p_padb
->i_reserved1
[i
] = ( (*p_peek
) >> 3 )&0x01;
1988 p_box
->data
.p_padb
->i_pad1
[i
] = ( (*p_peek
) )&0x07;
1990 p_peek
+= 1; i_read
-= 1;
1994 msg_Dbg( p_stream
, "read box: \"stdp\" entry-count %"PRId64
,
1998 MP4_READBOX_EXIT( 1 );
2001 static void MP4_FreeBox_elst( MP4_Box_t
*p_box
)
2003 FREENULL( p_box
->data
.p_elst
->i_segment_duration
);
2004 FREENULL( p_box
->data
.p_elst
->i_media_time
);
2005 FREENULL( p_box
->data
.p_elst
->i_media_rate_integer
);
2006 FREENULL( p_box
->data
.p_elst
->i_media_rate_fraction
);
2009 static int MP4_ReadBox_elst( stream_t
*p_stream
, MP4_Box_t
*p_box
)
2013 MP4_READBOX_ENTER( MP4_Box_data_elst_t
);
2015 MP4_GETVERSIONFLAGS( p_box
->data
.p_elst
);
2018 MP4_GET4BYTES( p_box
->data
.p_elst
->i_entry_count
);
2020 p_box
->data
.p_elst
->i_segment_duration
=
2021 calloc( p_box
->data
.p_elst
->i_entry_count
, sizeof(uint64_t) );
2022 p_box
->data
.p_elst
->i_media_time
=
2023 calloc( p_box
->data
.p_elst
->i_entry_count
, sizeof(uint64_t) );
2024 p_box
->data
.p_elst
->i_media_rate_integer
=
2025 calloc( p_box
->data
.p_elst
->i_entry_count
, sizeof(uint16_t) );
2026 p_box
->data
.p_elst
->i_media_rate_fraction
=
2027 calloc( p_box
->data
.p_elst
->i_entry_count
, sizeof(uint16_t) );
2028 if( p_box
->data
.p_elst
->i_segment_duration
== NULL
2029 || p_box
->data
.p_elst
->i_media_time
== NULL
2030 || p_box
->data
.p_elst
->i_media_rate_integer
== NULL
2031 || p_box
->data
.p_elst
->i_media_rate_fraction
== NULL
)
2033 MP4_READBOX_EXIT( 0 );
2037 for( i
= 0; i
< p_box
->data
.p_elst
->i_entry_count
; i
++ )
2039 if( p_box
->data
.p_elst
->i_version
== 1 )
2042 MP4_GET8BYTES( p_box
->data
.p_elst
->i_segment_duration
[i
] );
2044 MP4_GET8BYTES( p_box
->data
.p_elst
->i_media_time
[i
] );
2049 MP4_GET4BYTES( p_box
->data
.p_elst
->i_segment_duration
[i
] );
2051 MP4_GET4BYTES( p_box
->data
.p_elst
->i_media_time
[i
] );
2052 p_box
->data
.p_elst
->i_media_time
[i
] = (int32_t)p_box
->data
.p_elst
->i_media_time
[i
];
2055 MP4_GET2BYTES( p_box
->data
.p_elst
->i_media_rate_integer
[i
] );
2056 MP4_GET2BYTES( p_box
->data
.p_elst
->i_media_rate_fraction
[i
] );
2060 msg_Dbg( p_stream
, "read box: \"elst\" entry-count %lu",
2061 (unsigned long)p_box
->data
.p_elst
->i_entry_count
);
2063 MP4_READBOX_EXIT( 1 );
2066 static int MP4_ReadBox_cprt( stream_t
*p_stream
, MP4_Box_t
*p_box
)
2068 unsigned int i_language
;
2071 MP4_READBOX_ENTER( MP4_Box_data_cprt_t
);
2073 MP4_GETVERSIONFLAGS( p_box
->data
.p_cprt
);
2075 i_language
= GetWBE( p_peek
);
2076 for( i
= 0; i
< 3; i
++ )
2078 p_box
->data
.p_cprt
->i_language
[i
] =
2079 ( ( i_language
>> ( (2-i
)*5 ) )&0x1f ) + 0x60;
2081 p_peek
+= 2; i_read
-= 2;
2082 MP4_GETSTRINGZ( p_box
->data
.p_cprt
->psz_notice
);
2085 msg_Dbg( p_stream
, "read box: \"cprt\" language %c%c%c notice %s",
2086 p_box
->data
.p_cprt
->i_language
[0],
2087 p_box
->data
.p_cprt
->i_language
[1],
2088 p_box
->data
.p_cprt
->i_language
[2],
2089 p_box
->data
.p_cprt
->psz_notice
);
2092 MP4_READBOX_EXIT( 1 );
2095 static void MP4_FreeBox_cprt( MP4_Box_t
*p_box
)
2097 FREENULL( p_box
->data
.p_cprt
->psz_notice
);
2101 static int MP4_ReadBox_dcom( stream_t
*p_stream
, MP4_Box_t
*p_box
)
2103 MP4_READBOX_ENTER( MP4_Box_data_dcom_t
);
2105 MP4_GETFOURCC( p_box
->data
.p_dcom
->i_algorithm
);
2108 "read box: \"dcom\" compression algorithm : %4.4s",
2109 (char*)&p_box
->data
.p_dcom
->i_algorithm
);
2111 MP4_READBOX_EXIT( 1 );
2114 static int MP4_ReadBox_cmvd( stream_t
*p_stream
, MP4_Box_t
*p_box
)
2116 MP4_READBOX_ENTER( MP4_Box_data_cmvd_t
);
2118 MP4_GET4BYTES( p_box
->data
.p_cmvd
->i_uncompressed_size
);
2120 p_box
->data
.p_cmvd
->i_compressed_size
= i_read
;
2122 if( !( p_box
->data
.p_cmvd
->p_data
= malloc( i_read
) ) )
2125 /* now copy compressed data */
2126 memcpy( p_box
->data
.p_cmvd
->p_data
,
2130 p_box
->data
.p_cmvd
->b_compressed
= 1;
2133 msg_Dbg( p_stream
, "read box: \"cmvd\" compressed data size %d",
2134 p_box
->data
.p_cmvd
->i_compressed_size
);
2137 MP4_READBOX_EXIT( 1 );
2139 static void MP4_FreeBox_cmvd( MP4_Box_t
*p_box
)
2141 FREENULL( p_box
->data
.p_cmvd
->p_data
);
2145 static int MP4_ReadBox_cmov( stream_t
*p_stream
, MP4_Box_t
*p_box
)
2151 stream_t
*p_stream_memory
;
2157 if( !( p_box
->data
.p_cmov
= malloc( sizeof( MP4_Box_data_cmov_t
) ) ) )
2159 memset( p_box
->data
.p_cmov
, 0, sizeof( MP4_Box_data_cmov_t
) );
2161 if( !p_box
->p_father
||
2162 ( p_box
->p_father
->i_type
!= ATOM_moov
&&
2163 p_box
->p_father
->i_type
!= ATOM_foov
) )
2165 msg_Warn( p_stream
, "Read box: \"cmov\" box alone" );
2169 if( !MP4_ReadBoxContainer( p_stream
, p_box
) )
2174 if( ( p_dcom
= MP4_BoxGet( p_box
, "dcom" ) ) == NULL
||
2175 ( p_cmvd
= MP4_BoxGet( p_box
, "cmvd" ) ) == NULL
||
2176 p_cmvd
->data
.p_cmvd
->p_data
== NULL
)
2178 msg_Warn( p_stream
, "read box: \"cmov\" incomplete" );
2182 if( p_dcom
->data
.p_dcom
->i_algorithm
!= ATOM_zlib
)
2184 msg_Dbg( p_stream
, "read box: \"cmov\" compression algorithm : %4.4s "
2185 "not supported", (char*)&p_dcom
->data
.p_dcom
->i_algorithm
);
2190 msg_Dbg( p_stream
, "read box: \"cmov\" zlib unsupported" );
2194 /* decompress data */
2195 /* allocate a new buffer */
2196 if( !( p_data
= malloc( p_cmvd
->data
.p_cmvd
->i_uncompressed_size
) ) )
2198 /* init default structures */
2199 z_data
.next_in
= p_cmvd
->data
.p_cmvd
->p_data
;
2200 z_data
.avail_in
= p_cmvd
->data
.p_cmvd
->i_compressed_size
;
2201 z_data
.next_out
= p_data
;
2202 z_data
.avail_out
= p_cmvd
->data
.p_cmvd
->i_uncompressed_size
;
2203 z_data
.zalloc
= (alloc_func
)Z_NULL
;
2204 z_data
.zfree
= (free_func
)Z_NULL
;
2205 z_data
.opaque
= (voidpf
)Z_NULL
;
2208 if( inflateInit( &z_data
) != Z_OK
)
2210 msg_Err( p_stream
, "read box: \"cmov\" error while uncompressing" );
2216 i_result
= inflate( &z_data
, Z_NO_FLUSH
);
2217 if( i_result
!= Z_OK
&& i_result
!= Z_STREAM_END
)
2219 msg_Err( p_stream
, "read box: \"cmov\" error while uncompressing" );
2224 if( p_cmvd
->data
.p_cmvd
->i_uncompressed_size
!= z_data
.total_out
)
2226 msg_Warn( p_stream
, "read box: \"cmov\" uncompressing data size "
2229 p_cmvd
->data
.p_cmvd
->i_uncompressed_size
= z_data
.total_out
;
2232 if( inflateEnd( &z_data
) != Z_OK
)
2234 msg_Warn( p_stream
, "read box: \"cmov\" error while uncompressing "
2238 free( p_cmvd
->data
.p_cmvd
->p_data
);
2239 p_cmvd
->data
.p_cmvd
->p_data
= p_data
;
2240 p_cmvd
->data
.p_cmvd
->b_compressed
= 0;
2242 msg_Dbg( p_stream
, "read box: \"cmov\" box successfully uncompressed" );
2244 /* now create a memory stream */
2246 stream_MemoryNew( VLC_OBJECT(p_stream
), p_cmvd
->data
.p_cmvd
->p_data
,
2247 p_cmvd
->data
.p_cmvd
->i_uncompressed_size
, true );
2249 /* and read uncompressd moov */
2250 p_box
->data
.p_cmov
->p_moov
= MP4_ReadBox( p_stream_memory
, NULL
);
2252 stream_Delete( p_stream_memory
);
2255 msg_Dbg( p_stream
, "read box: \"cmov\" compressed movie header completed");
2258 return p_box
->data
.p_cmov
->p_moov
? 1 : 0;
2259 #endif /* HAVE_ZLIB_H */
2262 static int MP4_ReadBox_rdrf( stream_t
*p_stream
, MP4_Box_t
*p_box
)
2265 MP4_READBOX_ENTER( MP4_Box_data_rdrf_t
);
2267 MP4_GETVERSIONFLAGS( p_box
->data
.p_rdrf
);
2268 MP4_GETFOURCC( p_box
->data
.p_rdrf
->i_ref_type
);
2269 MP4_GET4BYTES( i_len
);
2275 p_box
->data
.p_rdrf
->psz_ref
= malloc( i_len
);
2276 if( p_box
->data
.p_rdrf
->psz_ref
== NULL
)
2277 MP4_READBOX_EXIT( 0 );
2280 for( i
= 0; i
< i_len
; i
++ )
2282 MP4_GET1BYTE( p_box
->data
.p_rdrf
->psz_ref
[i
] );
2284 p_box
->data
.p_rdrf
->psz_ref
[i_len
] = '\0';
2288 p_box
->data
.p_rdrf
->psz_ref
= NULL
;
2293 "read box: \"rdrf\" type:%4.4s ref %s",
2294 (char*)&p_box
->data
.p_rdrf
->i_ref_type
,
2295 p_box
->data
.p_rdrf
->psz_ref
);
2297 MP4_READBOX_EXIT( 1 );
2300 static void MP4_FreeBox_rdrf( MP4_Box_t
*p_box
)
2302 FREENULL( p_box
->data
.p_rdrf
->psz_ref
);
2306 static int MP4_ReadBox_rmdr( stream_t
*p_stream
, MP4_Box_t
*p_box
)
2308 MP4_READBOX_ENTER( MP4_Box_data_rmdr_t
);
2310 MP4_GETVERSIONFLAGS( p_box
->data
.p_rmdr
);
2312 MP4_GET4BYTES( p_box
->data
.p_rmdr
->i_rate
);
2316 "read box: \"rmdr\" rate:%d",
2317 p_box
->data
.p_rmdr
->i_rate
);
2319 MP4_READBOX_EXIT( 1 );
2322 static int MP4_ReadBox_rmqu( stream_t
*p_stream
, MP4_Box_t
*p_box
)
2324 MP4_READBOX_ENTER( MP4_Box_data_rmqu_t
);
2326 MP4_GET4BYTES( p_box
->data
.p_rmqu
->i_quality
);
2330 "read box: \"rmqu\" quality:%d",
2331 p_box
->data
.p_rmqu
->i_quality
);
2333 MP4_READBOX_EXIT( 1 );
2336 static int MP4_ReadBox_rmvc( stream_t
*p_stream
, MP4_Box_t
*p_box
)
2338 MP4_READBOX_ENTER( MP4_Box_data_rmvc_t
);
2339 MP4_GETVERSIONFLAGS( p_box
->data
.p_rmvc
);
2341 MP4_GETFOURCC( p_box
->data
.p_rmvc
->i_gestaltType
);
2342 MP4_GET4BYTES( p_box
->data
.p_rmvc
->i_val1
);
2343 MP4_GET4BYTES( p_box
->data
.p_rmvc
->i_val2
);
2344 MP4_GET2BYTES( p_box
->data
.p_rmvc
->i_checkType
);
2348 "read box: \"rmvc\" gestaltType:%4.4s val1:0x%x val2:0x%x checkType:0x%x",
2349 (char*)&p_box
->data
.p_rmvc
->i_gestaltType
,
2350 p_box
->data
.p_rmvc
->i_val1
,p_box
->data
.p_rmvc
->i_val2
,
2351 p_box
->data
.p_rmvc
->i_checkType
);
2354 MP4_READBOX_EXIT( 1 );
2357 static int MP4_ReadBox_frma( stream_t
*p_stream
, MP4_Box_t
*p_box
)
2359 MP4_READBOX_ENTER( MP4_Box_data_frma_t
);
2361 MP4_GETFOURCC( p_box
->data
.p_frma
->i_type
);
2364 msg_Dbg( p_stream
, "read box: \"frma\" i_type:%4.4s",
2365 (char *)&p_box
->data
.p_frma
->i_type
);
2368 MP4_READBOX_EXIT( 1 );
2371 static int MP4_ReadBox_skcr( stream_t
*p_stream
, MP4_Box_t
*p_box
)
2373 MP4_READBOX_ENTER( MP4_Box_data_skcr_t
);
2375 MP4_GET4BYTES( p_box
->data
.p_skcr
->i_init
);
2376 MP4_GET4BYTES( p_box
->data
.p_skcr
->i_encr
);
2377 MP4_GET4BYTES( p_box
->data
.p_skcr
->i_decr
);
2380 msg_Dbg( p_stream
, "read box: \"skcr\" i_init:%d i_encr:%d i_decr:%d",
2381 p_box
->data
.p_skcr
->i_init
,
2382 p_box
->data
.p_skcr
->i_encr
,
2383 p_box
->data
.p_skcr
->i_decr
);
2386 MP4_READBOX_EXIT( 1 );
2389 static int MP4_ReadBox_drms( stream_t
*p_stream
, MP4_Box_t
*p_box
)
2391 MP4_Box_t
*p_drms_box
= p_box
;
2392 void *p_drms
= NULL
;
2394 MP4_READBOX_ENTER( uint8_t );
2398 p_drms_box
= p_drms_box
->p_father
;
2399 } while( p_drms_box
&& p_drms_box
->i_type
!= ATOM_drms
2400 && p_drms_box
->i_type
!= ATOM_drmi
);
2402 if( p_drms_box
&& p_drms_box
->i_type
== ATOM_drms
)
2403 p_drms
= p_drms_box
->data
.p_sample_soun
->p_drms
;
2404 else if( p_drms_box
&& p_drms_box
->i_type
== ATOM_drmi
)
2405 p_drms
= p_drms_box
->data
.p_sample_vide
->p_drms
;
2407 if( p_drms_box
&& p_drms
)
2409 int i_ret
= drms_init( p_drms
, p_box
->i_type
, p_peek
, i_read
);
2412 const char *psz_error
;
2416 case -1: psz_error
= "unimplemented"; break;
2417 case -2: psz_error
= "invalid argument"; break;
2418 case -3: psz_error
= "could not get system key"; break;
2419 case -4: psz_error
= "could not get SCI data"; break;
2420 case -5: psz_error
= "no user key found in SCI data"; break;
2421 case -6: psz_error
= "invalid user key"; break;
2422 default: psz_error
= "unknown error"; break;
2424 if MP4_BOX_TYPE_ASCII()
2425 msg_Err( p_stream
, "drms_init(%4.4s) failed (%s)",
2426 (char *)&p_box
->i_type
, psz_error
);
2428 msg_Err( p_stream
, "drms_init(c%3.3s) failed (%s)",
2429 (char *)&p_box
->i_type
+1, psz_error
);
2431 drms_free( p_drms
);
2433 if( p_drms_box
->i_type
== ATOM_drms
)
2434 p_drms_box
->data
.p_sample_soun
->p_drms
= NULL
;
2435 else if( p_drms_box
->i_type
== ATOM_drmi
)
2436 p_drms_box
->data
.p_sample_vide
->p_drms
= NULL
;
2440 MP4_READBOX_EXIT( 1 );
2443 static int MP4_ReadBox_name( stream_t
*p_stream
, MP4_Box_t
*p_box
)
2445 MP4_READBOX_ENTER( MP4_Box_data_name_t
);
2447 p_box
->data
.p_name
->psz_text
= malloc( p_box
->i_size
+ 1 - 8 ); /* +\0, -name, -size */
2448 if( p_box
->data
.p_name
->psz_text
== NULL
)
2449 MP4_READBOX_EXIT( 0 );
2451 memcpy( p_box
->data
.p_name
->psz_text
, p_peek
, p_box
->i_size
- 8 );
2452 p_box
->data
.p_name
->psz_text
[p_box
->i_size
- 8] = '\0';
2455 msg_Dbg( p_stream
, "read box: \"name\" text=`%s'",
2456 p_box
->data
.p_name
->psz_text
);
2458 MP4_READBOX_EXIT( 1 );
2461 static void MP4_FreeBox_name( MP4_Box_t
*p_box
)
2463 FREENULL( p_box
->data
.p_name
->psz_text
);
2466 static int MP4_ReadBox_0xa9xxx( stream_t
*p_stream
, MP4_Box_t
*p_box
)
2470 MP4_READBOX_ENTER( MP4_Box_data_0xa9xxx_t
);
2472 p_box
->data
.p_0xa9xxx
->psz_text
= NULL
;
2474 MP4_GET2BYTES( i16
);
2480 MP4_GET2BYTES( i16
);
2481 if( i_length
>= i_read
) i_length
= i_read
+ 1;
2483 p_box
->data
.p_0xa9xxx
->psz_text
= malloc( i_length
);
2484 if( p_box
->data
.p_0xa9xxx
->psz_text
== NULL
)
2485 MP4_READBOX_EXIT( 0 );
2488 memcpy( p_box
->data
.p_0xa9xxx
->psz_text
,
2490 p_box
->data
.p_0xa9xxx
->psz_text
[i_length
] = '\0';
2494 "read box: \"c%3.3s\" text=`%s'",
2495 ((char*)&p_box
->i_type
+ 1),
2496 p_box
->data
.p_0xa9xxx
->psz_text
);
2501 /* try iTune/Quicktime format, rewind to start */
2502 p_peek
-= 2; i_read
+= 2;
2503 // we are expecting a 'data' box
2504 uint32_t i_data_len
;
2505 uint32_t i_data_tag
;
2507 MP4_GET4BYTES( i_data_len
);
2508 if( i_data_len
> i_read
) i_data_len
= i_read
;
2509 MP4_GETFOURCC( i_data_tag
);
2510 if( (i_data_len
> 0) && (i_data_tag
== ATOM_data
) )
2512 /* data box contains a version/flags field */
2514 uint32_t i_reserved
;
2515 MP4_GET4BYTES( i_version
);
2516 MP4_GET4BYTES( i_reserved
);
2517 // version should be 0, flags should be 1 for text, 0 for data
2518 if( ( i_version
== 0x00000001 ) && (i_data_len
>= 12 ) )
2520 // the rest is the text
2522 p_box
->data
.p_0xa9xxx
->psz_text
= malloc( i_data_len
+ 1 );
2523 if( p_box
->data
.p_0xa9xxx
->psz_text
== NULL
)
2524 MP4_READBOX_EXIT( 0 );
2526 memcpy( p_box
->data
.p_0xa9xxx
->psz_text
,
2527 p_peek
, i_data_len
);
2528 p_box
->data
.p_0xa9xxx
->psz_text
[i_data_len
] = '\0';
2531 "read box: \"c%3.3s\" text=`%s'",
2532 ((char*)&p_box
->i_type
+1),
2533 p_box
->data
.p_0xa9xxx
->psz_text
);
2538 // TODO: handle data values for ID3 tag values, track num or cover art,etc...
2543 MP4_READBOX_EXIT( 1 );
2545 static void MP4_FreeBox_0xa9xxx( MP4_Box_t
*p_box
)
2547 FREENULL( p_box
->data
.p_0xa9xxx
->psz_text
);
2550 /* Chapter support */
2551 static void MP4_FreeBox_chpl( MP4_Box_t
*p_box
)
2553 MP4_Box_data_chpl_t
*p_chpl
= p_box
->data
.p_chpl
;
2555 for( i
= 0; i
< p_chpl
->i_chapter
; i
++ )
2556 free( p_chpl
->chapter
[i
].psz_name
);
2559 static int MP4_ReadBox_chpl( stream_t
*p_stream
, MP4_Box_t
*p_box
)
2561 MP4_Box_data_chpl_t
*p_chpl
;
2564 MP4_READBOX_ENTER( MP4_Box_data_chpl_t
);
2566 p_chpl
= p_box
->data
.p_chpl
;
2568 MP4_GETVERSIONFLAGS( p_chpl
);
2570 MP4_GET4BYTES( i_dummy
);
2572 MP4_GET1BYTE( p_chpl
->i_chapter
);
2574 for( i
= 0; i
< p_chpl
->i_chapter
; i
++ )
2579 MP4_GET8BYTES( i_start
);
2580 MP4_GET1BYTE( i_len
);
2582 p_chpl
->chapter
[i
].psz_name
= malloc( i_len
+ 1 );
2583 if( !p_chpl
->chapter
[i
].psz_name
)
2586 i_copy
= __MIN( i_len
, i_read
);
2588 memcpy( p_chpl
->chapter
[i
].psz_name
, p_peek
, i_copy
);
2589 p_chpl
->chapter
[i
].psz_name
[i_copy
] = '\0';
2590 p_chpl
->chapter
[i
].i_start
= i_start
;
2595 /* Bubble sort by increasing start date */
2598 for( i
= 0; i
< p_chpl
->i_chapter
- 1; i
++ )
2600 if( p_chpl
->chapter
[i
].i_start
> p_chpl
->chapter
[i
+1].i_start
)
2602 char *psz
= p_chpl
->chapter
[i
+1].psz_name
;
2603 int64_t i64
= p_chpl
->chapter
[i
+1].i_start
;
2605 p_chpl
->chapter
[i
+1].psz_name
= p_chpl
->chapter
[i
].psz_name
;
2606 p_chpl
->chapter
[i
+1].i_start
= p_chpl
->chapter
[i
].i_start
;
2608 p_chpl
->chapter
[i
].psz_name
= psz
;
2609 p_chpl
->chapter
[i
].i_start
= i64
;
2618 msg_Dbg( p_stream
, "read box: \"chpl\" %d chapters",
2619 p_chpl
->i_chapter
);
2621 MP4_READBOX_EXIT( 1 );
2624 MP4_READBOX_EXIT( 0 );
2627 static int MP4_ReadBox_tref_generic( stream_t
*p_stream
, MP4_Box_t
*p_box
)
2630 MP4_READBOX_ENTER( MP4_Box_data_tref_generic_t
);
2632 p_box
->data
.p_tref_generic
->i_track_ID
= NULL
;
2633 p_box
->data
.p_tref_generic
->i_entry_count
= i_read
/ sizeof(uint32_t);
2634 if( p_box
->data
.p_tref_generic
->i_entry_count
> 0 )
2635 p_box
->data
.p_tref_generic
->i_track_ID
= calloc( p_box
->data
.p_tref_generic
->i_entry_count
, sizeof(uint32_t) );
2636 if( p_box
->data
.p_tref_generic
->i_track_ID
== NULL
)
2637 MP4_READBOX_EXIT( 0 );
2639 for( i
= 0; i
< p_box
->data
.p_tref_generic
->i_entry_count
; i
++ )
2641 MP4_GET4BYTES( p_box
->data
.p_tref_generic
->i_track_ID
[i
] );
2644 msg_Dbg( p_stream
, "read box: \"chap\" %d references",
2645 p_box
->data
.p_tref_generic
->i_entry_count
);
2648 MP4_READBOX_EXIT( 1 );
2650 static void MP4_FreeBox_tref_generic( MP4_Box_t
*p_box
)
2652 FREENULL( p_box
->data
.p_tref_generic
->i_track_ID
);
2655 static int MP4_ReadBox_meta( stream_t
*p_stream
, MP4_Box_t
*p_box
)
2657 uint8_t meta_data
[8];
2658 int i_actually_read
;
2660 // skip over box header
2661 i_actually_read
= stream_Read( p_stream
, meta_data
, 8 );
2662 if( i_actually_read
< 8 )
2665 /* meta content starts with a 4 byte version/flags value (should be 0) */
2666 i_actually_read
= stream_Read( p_stream
, meta_data
, 4 );
2667 if( i_actually_read
< 4 )
2670 /* then it behaves like a container */
2671 return MP4_ReadBoxContainerRaw( p_stream
, p_box
);
2674 static int MP4_ReadBox_iods( stream_t
*p_stream
, MP4_Box_t
*p_box
)
2678 MP4_READBOX_ENTER( MP4_Box_data_iods_t
);
2679 MP4_GETVERSIONFLAGS( p_box
->data
.p_iods
);
2681 MP4_GET1BYTE( i_unused
); /* tag */
2682 MP4_GET1BYTE( i_unused
); /* length */
2684 MP4_GET2BYTES( p_box
->data
.p_iods
->i_object_descriptor
); /* 10bits, 6 other bits
2685 are used for other flags */
2686 MP4_GET1BYTE( p_box
->data
.p_iods
->i_OD_profile_level
);
2687 MP4_GET1BYTE( p_box
->data
.p_iods
->i_scene_profile_level
);
2688 MP4_GET1BYTE( p_box
->data
.p_iods
->i_audio_profile_level
);
2689 MP4_GET1BYTE( p_box
->data
.p_iods
->i_visual_profile_level
);
2690 MP4_GET1BYTE( p_box
->data
.p_iods
->i_graphics_profile_level
);
2694 "read box: \"iods\" objectDescriptorId: %i, OD: %i, scene: %i, audio: %i, "
2695 "visual: %i, graphics: %i",
2696 p_box
->data
.p_iods
->i_object_descriptor
>> 6,
2697 p_box
->data
.p_iods
->i_OD_profile_level
,
2698 p_box
->data
.p_iods
->i_scene_profile_level
,
2699 p_box
->data
.p_iods
->i_audio_profile_level
,
2700 p_box
->data
.p_iods
->i_visual_profile_level
,
2701 p_box
->data
.p_iods
->i_graphics_profile_level
);
2704 MP4_READBOX_EXIT( 1 );
2707 static int MP4_ReadBox_pasp( stream_t
*p_stream
, MP4_Box_t
*p_box
)
2709 MP4_READBOX_ENTER( MP4_Box_data_pasp_t
);
2711 MP4_GET4BYTES( p_box
->data
.p_pasp
->i_horizontal_spacing
);
2712 MP4_GET4BYTES( p_box
->data
.p_pasp
->i_vertical_spacing
);
2716 "read box: \"paps\" %dx%d",
2717 p_box
->data
.p_pasp
->i_horizontal_spacing
,
2718 p_box
->data
.p_pasp
->i_vertical_spacing
);
2721 MP4_READBOX_EXIT( 1 );
2726 static int MP4_ReadBox_default( stream_t
*p_stream
, MP4_Box_t
*p_box
)
2728 if( !p_box
->p_father
)
2732 if( p_box
->p_father
->i_type
== ATOM_stsd
)
2734 MP4_Box_t
*p_mdia
= MP4_BoxGet( p_box
, "../../../.." );
2737 if( p_mdia
== NULL
|| p_mdia
->i_type
!= ATOM_mdia
||
2738 (p_hdlr
= MP4_BoxGet( p_mdia
, "hdlr" )) == NULL
)
2742 switch( p_hdlr
->data
.p_hdlr
->i_handler_type
)
2745 return MP4_ReadBox_sample_soun( p_stream
, p_box
);
2747 return MP4_ReadBox_sample_vide( p_stream
, p_box
);
2749 return MP4_ReadBox_sample_text( p_stream
, p_box
);
2752 return MP4_ReadBox_sample_tx3g( p_stream
, p_box
);
2755 "unknown handler type in stsd (incompletely loaded)" );
2761 if MP4_BOX_TYPE_ASCII()
2763 "unknown box type %4.4s (incompletely loaded)",
2764 (char*)&p_box
->i_type
);
2767 "unknown box type c%3.3s (incompletely loaded)",
2768 (char*)&p_box
->i_type
+1 );
2773 /**** ------------------------------------------------------------------- ****/
2774 /**** "Higher level" Functions ****/
2775 /**** ------------------------------------------------------------------- ****/
2780 int (*MP4_ReadBox_function
)( stream_t
*p_stream
, MP4_Box_t
*p_box
);
2781 void (*MP4_FreeBox_function
)( MP4_Box_t
*p_box
);
2782 } MP4_Box_Function
[] =
2785 { ATOM_moov
, MP4_ReadBoxContainer
, MP4_FreeBox_Common
},
2786 { ATOM_trak
, MP4_ReadBoxContainer
, MP4_FreeBox_Common
},
2787 { ATOM_mdia
, MP4_ReadBoxContainer
, MP4_FreeBox_Common
},
2788 { ATOM_moof
, MP4_ReadBoxContainer
, MP4_FreeBox_Common
},
2789 { ATOM_minf
, MP4_ReadBoxContainer
, MP4_FreeBox_Common
},
2790 { ATOM_stbl
, MP4_ReadBoxContainer
, MP4_FreeBox_Common
},
2791 { ATOM_dinf
, MP4_ReadBoxContainer
, MP4_FreeBox_Common
},
2792 { ATOM_edts
, MP4_ReadBoxContainer
, MP4_FreeBox_Common
},
2793 { ATOM_udta
, MP4_ReadBoxContainer
, MP4_FreeBox_Common
},
2794 { ATOM_nmhd
, MP4_ReadBoxContainer
, MP4_FreeBox_Common
},
2795 { ATOM_hnti
, MP4_ReadBoxContainer
, MP4_FreeBox_Common
},
2796 { ATOM_rmra
, MP4_ReadBoxContainer
, MP4_FreeBox_Common
},
2797 { ATOM_rmda
, MP4_ReadBoxContainer
, MP4_FreeBox_Common
},
2798 { ATOM_tref
, MP4_ReadBoxContainer
, MP4_FreeBox_Common
},
2799 { ATOM_gmhd
, MP4_ReadBoxContainer
, MP4_FreeBox_Common
},
2800 { ATOM_wave
, MP4_ReadBoxContainer
, MP4_FreeBox_Common
},
2801 { ATOM_ilst
, MP4_ReadBoxContainer
, MP4_FreeBox_Common
},
2804 { ATOM_ftyp
, MP4_ReadBox_ftyp
, MP4_FreeBox_ftyp
},
2805 { ATOM_cmov
, MP4_ReadBox_cmov
, MP4_FreeBox_Common
},
2806 { ATOM_mvhd
, MP4_ReadBox_mvhd
, MP4_FreeBox_Common
},
2807 { ATOM_tkhd
, MP4_ReadBox_tkhd
, MP4_FreeBox_Common
},
2808 { ATOM_mdhd
, MP4_ReadBox_mdhd
, MP4_FreeBox_Common
},
2809 { ATOM_hdlr
, MP4_ReadBox_hdlr
, MP4_FreeBox_hdlr
},
2810 { ATOM_vmhd
, MP4_ReadBox_vmhd
, MP4_FreeBox_Common
},
2811 { ATOM_smhd
, MP4_ReadBox_smhd
, MP4_FreeBox_Common
},
2812 { ATOM_hmhd
, MP4_ReadBox_hmhd
, MP4_FreeBox_Common
},
2813 { ATOM_url
, MP4_ReadBox_url
, MP4_FreeBox_url
},
2814 { ATOM_urn
, MP4_ReadBox_urn
, MP4_FreeBox_urn
},
2815 { ATOM_dref
, MP4_ReadBox_dref
, MP4_FreeBox_Common
},
2816 { ATOM_stts
, MP4_ReadBox_stts
, MP4_FreeBox_stts
},
2817 { ATOM_ctts
, MP4_ReadBox_ctts
, MP4_FreeBox_ctts
},
2818 { ATOM_stsd
, MP4_ReadBox_stsd
, MP4_FreeBox_Common
},
2819 { ATOM_stsz
, MP4_ReadBox_stsz
, MP4_FreeBox_stsz
},
2820 { ATOM_stsc
, MP4_ReadBox_stsc
, MP4_FreeBox_stsc
},
2821 { ATOM_stco
, MP4_ReadBox_stco_co64
, MP4_FreeBox_stco_co64
},
2822 { ATOM_co64
, MP4_ReadBox_stco_co64
, MP4_FreeBox_stco_co64
},
2823 { ATOM_stss
, MP4_ReadBox_stss
, MP4_FreeBox_stss
},
2824 { ATOM_stsh
, MP4_ReadBox_stsh
, MP4_FreeBox_stsh
},
2825 { ATOM_stdp
, MP4_ReadBox_stdp
, MP4_FreeBox_stdp
},
2826 { ATOM_padb
, MP4_ReadBox_padb
, MP4_FreeBox_padb
},
2827 { ATOM_elst
, MP4_ReadBox_elst
, MP4_FreeBox_elst
},
2828 { ATOM_cprt
, MP4_ReadBox_cprt
, MP4_FreeBox_cprt
},
2829 { ATOM_esds
, MP4_ReadBox_esds
, MP4_FreeBox_esds
},
2830 { ATOM_dcom
, MP4_ReadBox_dcom
, MP4_FreeBox_Common
},
2831 { ATOM_cmvd
, MP4_ReadBox_cmvd
, MP4_FreeBox_cmvd
},
2832 { ATOM_avcC
, MP4_ReadBox_avcC
, MP4_FreeBox_avcC
},
2833 { ATOM_dac3
, MP4_ReadBox_dac3
, MP4_FreeBox_Common
},
2834 { ATOM_enda
, MP4_ReadBox_enda
, MP4_FreeBox_Common
},
2835 { ATOM_gnre
, MP4_ReadBox_gnre
, MP4_FreeBox_Common
},
2836 { ATOM_trkn
, MP4_ReadBox_trkn
, MP4_FreeBox_Common
},
2837 { ATOM_iods
, MP4_ReadBox_iods
, MP4_FreeBox_Common
},
2838 { ATOM_pasp
, MP4_ReadBox_pasp
, MP4_FreeBox_Common
},
2840 /* Nothing to do with this box */
2841 { ATOM_mdat
, MP4_ReadBoxSkip
, MP4_FreeBox_Common
},
2842 { ATOM_skip
, MP4_ReadBoxSkip
, MP4_FreeBox_Common
},
2843 { ATOM_free
, MP4_ReadBoxSkip
, MP4_FreeBox_Common
},
2844 { ATOM_wide
, MP4_ReadBoxSkip
, MP4_FreeBox_Common
},
2847 { ATOM_soun
, MP4_ReadBox_sample_soun
, MP4_FreeBox_sample_soun
},
2848 { ATOM_ms02
, MP4_ReadBox_sample_soun
, MP4_FreeBox_sample_soun
},
2849 { ATOM_ms11
, MP4_ReadBox_sample_soun
, MP4_FreeBox_sample_soun
},
2850 { ATOM_ms55
, MP4_ReadBox_sample_soun
, MP4_FreeBox_sample_soun
},
2851 { ATOM__mp3
, MP4_ReadBox_sample_soun
, MP4_FreeBox_sample_soun
},
2852 { ATOM_mp4a
, MP4_ReadBox_sample_soun
, MP4_FreeBox_sample_soun
},
2853 { ATOM_twos
, MP4_ReadBox_sample_soun
, MP4_FreeBox_sample_soun
},
2854 { ATOM_sowt
, MP4_ReadBox_sample_soun
, MP4_FreeBox_sample_soun
},
2855 { ATOM_QDMC
, MP4_ReadBox_sample_soun
, MP4_FreeBox_sample_soun
},
2856 { ATOM_QDM2
, MP4_ReadBox_sample_soun
, MP4_FreeBox_sample_soun
},
2857 { ATOM_ima4
, MP4_ReadBox_sample_soun
, MP4_FreeBox_sample_soun
},
2858 { ATOM_IMA4
, MP4_ReadBox_sample_soun
, MP4_FreeBox_sample_soun
},
2859 { ATOM_dvi
, MP4_ReadBox_sample_soun
, MP4_FreeBox_sample_soun
},
2860 { ATOM_alaw
, MP4_ReadBox_sample_soun
, MP4_FreeBox_sample_soun
},
2861 { ATOM_ulaw
, MP4_ReadBox_sample_soun
, MP4_FreeBox_sample_soun
},
2862 { ATOM_raw
, MP4_ReadBox_sample_soun
, MP4_FreeBox_sample_soun
},
2863 { ATOM_MAC3
, MP4_ReadBox_sample_soun
, MP4_FreeBox_sample_soun
},
2864 { ATOM_MAC6
, MP4_ReadBox_sample_soun
, MP4_FreeBox_sample_soun
},
2865 { ATOM_Qclp
, MP4_ReadBox_sample_soun
, MP4_FreeBox_sample_soun
},
2866 { ATOM_samr
, MP4_ReadBox_sample_soun
, MP4_FreeBox_sample_soun
},
2867 { ATOM_sawb
, MP4_ReadBox_sample_soun
, MP4_FreeBox_sample_soun
},
2868 { ATOM_OggS
, MP4_ReadBox_sample_soun
, MP4_FreeBox_sample_soun
},
2869 { ATOM_alac
, MP4_ReadBox_sample_soun
, MP4_FreeBox_sample_soun
},
2871 { ATOM_drmi
, MP4_ReadBox_sample_vide
, MP4_FreeBox_sample_vide
},
2872 { ATOM_vide
, MP4_ReadBox_sample_vide
, MP4_FreeBox_sample_vide
},
2873 { ATOM_mp4v
, MP4_ReadBox_sample_vide
, MP4_FreeBox_sample_vide
},
2874 { ATOM_SVQ1
, MP4_ReadBox_sample_vide
, MP4_FreeBox_sample_vide
},
2875 { ATOM_SVQ3
, MP4_ReadBox_sample_vide
, MP4_FreeBox_sample_vide
},
2876 { ATOM_ZyGo
, MP4_ReadBox_sample_vide
, MP4_FreeBox_sample_vide
},
2877 { ATOM_DIVX
, MP4_ReadBox_sample_vide
, MP4_FreeBox_sample_vide
},
2878 { ATOM_XVID
, MP4_ReadBox_sample_vide
, MP4_FreeBox_sample_vide
},
2879 { ATOM_h263
, MP4_ReadBox_sample_vide
, MP4_FreeBox_sample_vide
},
2880 { ATOM_s263
, MP4_ReadBox_sample_vide
, MP4_FreeBox_sample_vide
},
2881 { ATOM_cvid
, MP4_ReadBox_sample_vide
, MP4_FreeBox_sample_vide
},
2882 { ATOM_3IV1
, MP4_ReadBox_sample_vide
, MP4_FreeBox_sample_vide
},
2883 { ATOM_3iv1
, MP4_ReadBox_sample_vide
, MP4_FreeBox_sample_vide
},
2884 { ATOM_3IV2
, MP4_ReadBox_sample_vide
, MP4_FreeBox_sample_vide
},
2885 { ATOM_3iv2
, MP4_ReadBox_sample_vide
, MP4_FreeBox_sample_vide
},
2886 { ATOM_3IVD
, MP4_ReadBox_sample_vide
, MP4_FreeBox_sample_vide
},
2887 { ATOM_3ivd
, MP4_ReadBox_sample_vide
, MP4_FreeBox_sample_vide
},
2888 { ATOM_3VID
, MP4_ReadBox_sample_vide
, MP4_FreeBox_sample_vide
},
2889 { ATOM_3vid
, MP4_ReadBox_sample_vide
, MP4_FreeBox_sample_vide
},
2890 { ATOM_mjpa
, MP4_ReadBox_sample_vide
, MP4_FreeBox_sample_vide
},
2891 { ATOM_mjpb
, MP4_ReadBox_sample_vide
, MP4_FreeBox_sample_vide
},
2892 { ATOM_qdrw
, MP4_ReadBox_sample_vide
, MP4_FreeBox_sample_vide
},
2893 { ATOM_mp2v
, MP4_ReadBox_sample_vide
, MP4_FreeBox_sample_vide
},
2894 { ATOM_hdv2
, MP4_ReadBox_sample_vide
, MP4_FreeBox_sample_vide
},
2896 { ATOM_mjqt
, MP4_ReadBox_default
, NULL
}, /* found in mjpa/b */
2897 { ATOM_mjht
, MP4_ReadBox_default
, NULL
},
2899 { ATOM_dvc
, MP4_ReadBox_sample_vide
, MP4_FreeBox_sample_vide
},
2900 { ATOM_dvp
, MP4_ReadBox_sample_vide
, MP4_FreeBox_sample_vide
},
2901 { ATOM_dv5n
, MP4_ReadBox_sample_vide
, MP4_FreeBox_sample_vide
},
2902 { ATOM_dv5p
, MP4_ReadBox_sample_vide
, MP4_FreeBox_sample_vide
},
2903 { ATOM_VP31
, MP4_ReadBox_sample_vide
, MP4_FreeBox_sample_vide
},
2904 { ATOM_vp31
, MP4_ReadBox_sample_vide
, MP4_FreeBox_sample_vide
},
2905 { ATOM_h264
, MP4_ReadBox_sample_vide
, MP4_FreeBox_sample_vide
},
2907 { ATOM_jpeg
, MP4_ReadBox_sample_vide
, MP4_FreeBox_sample_vide
},
2908 { ATOM_avc1
, MP4_ReadBox_sample_vide
, MP4_FreeBox_sample_vide
},
2910 { ATOM_yv12
, MP4_ReadBox_sample_vide
, MP4_FreeBox_sample_vide
},
2911 { ATOM_yuv2
, MP4_ReadBox_sample_vide
, MP4_FreeBox_sample_vide
},
2913 { ATOM_mp4s
, MP4_ReadBox_sample_mp4s
, MP4_FreeBox_Common
},
2915 /* XXX there is 2 box where we could find this entry stbl and tref*/
2916 { ATOM_hint
, MP4_ReadBox_default
, MP4_FreeBox_Common
},
2918 /* found in tref box */
2919 { ATOM_dpnd
, MP4_ReadBox_default
, NULL
},
2920 { ATOM_ipir
, MP4_ReadBox_default
, NULL
},
2921 { ATOM_mpod
, MP4_ReadBox_default
, NULL
},
2922 { ATOM_chap
, MP4_ReadBox_tref_generic
, MP4_FreeBox_tref_generic
},
2925 { ATOM_rtp
, MP4_ReadBox_default
, NULL
},
2928 { ATOM_rdrf
, MP4_ReadBox_rdrf
, MP4_FreeBox_rdrf
},
2929 { ATOM_rmdr
, MP4_ReadBox_rmdr
, MP4_FreeBox_Common
},
2930 { ATOM_rmqu
, MP4_ReadBox_rmqu
, MP4_FreeBox_Common
},
2931 { ATOM_rmvc
, MP4_ReadBox_rmvc
, MP4_FreeBox_Common
},
2933 { ATOM_drms
, MP4_ReadBox_sample_soun
, MP4_FreeBox_sample_soun
},
2934 { ATOM_sinf
, MP4_ReadBoxContainer
, MP4_FreeBox_Common
},
2935 { ATOM_schi
, MP4_ReadBoxContainer
, MP4_FreeBox_Common
},
2936 { ATOM_user
, MP4_ReadBox_drms
, MP4_FreeBox_Common
},
2937 { ATOM_key
, MP4_ReadBox_drms
, MP4_FreeBox_Common
},
2938 { ATOM_iviv
, MP4_ReadBox_drms
, MP4_FreeBox_Common
},
2939 { ATOM_priv
, MP4_ReadBox_drms
, MP4_FreeBox_Common
},
2940 { ATOM_frma
, MP4_ReadBox_frma
, MP4_FreeBox_Common
},
2941 { ATOM_skcr
, MP4_ReadBox_skcr
, MP4_FreeBox_Common
},
2944 { ATOM_0xa9nam
, MP4_ReadBox_0xa9xxx
, MP4_FreeBox_0xa9xxx
},
2945 { ATOM_0xa9aut
, MP4_ReadBox_0xa9xxx
, MP4_FreeBox_0xa9xxx
},
2946 { ATOM_0xa9cpy
, MP4_ReadBox_0xa9xxx
, MP4_FreeBox_0xa9xxx
},
2947 { ATOM_0xa9swr
, MP4_ReadBox_0xa9xxx
, MP4_FreeBox_0xa9xxx
},
2948 { ATOM_0xa9inf
, MP4_ReadBox_0xa9xxx
, MP4_FreeBox_0xa9xxx
},
2949 { ATOM_0xa9ART
, MP4_ReadBox_0xa9xxx
, MP4_FreeBox_0xa9xxx
},
2950 { ATOM_0xa9dir
, MP4_ReadBox_0xa9xxx
, MP4_FreeBox_0xa9xxx
},
2951 { ATOM_0xa9cmt
, MP4_ReadBox_0xa9xxx
, MP4_FreeBox_0xa9xxx
},
2952 { ATOM_0xa9req
, MP4_ReadBox_0xa9xxx
, MP4_FreeBox_0xa9xxx
},
2953 { ATOM_0xa9day
, MP4_ReadBox_0xa9xxx
, MP4_FreeBox_0xa9xxx
},
2954 { ATOM_0xa9des
, MP4_ReadBox_0xa9xxx
, MP4_FreeBox_0xa9xxx
},
2955 { ATOM_0xa9fmt
, MP4_ReadBox_0xa9xxx
, MP4_FreeBox_0xa9xxx
},
2956 { ATOM_0xa9prd
, MP4_ReadBox_0xa9xxx
, MP4_FreeBox_0xa9xxx
},
2957 { ATOM_0xa9prf
, MP4_ReadBox_0xa9xxx
, MP4_FreeBox_0xa9xxx
},
2958 { ATOM_0xa9src
, MP4_ReadBox_0xa9xxx
, MP4_FreeBox_0xa9xxx
},
2959 { ATOM_0xa9alb
, MP4_ReadBox_0xa9xxx
, MP4_FreeBox_0xa9xxx
},
2960 { ATOM_0xa9dis
, MP4_ReadBox_0xa9xxx
, MP4_FreeBox_0xa9xxx
},
2961 { ATOM_0xa9enc
, MP4_ReadBox_0xa9xxx
, MP4_FreeBox_0xa9xxx
},
2962 { ATOM_0xa9gen
, MP4_ReadBox_0xa9xxx
, MP4_FreeBox_0xa9xxx
},
2963 { ATOM_0xa9trk
, MP4_ReadBox_0xa9xxx
, MP4_FreeBox_0xa9xxx
},
2964 { ATOM_0xa9dsa
, MP4_ReadBox_0xa9xxx
, MP4_FreeBox_0xa9xxx
},
2965 { ATOM_0xa9hst
, MP4_ReadBox_0xa9xxx
, MP4_FreeBox_0xa9xxx
},
2966 { ATOM_0xa9url
, MP4_ReadBox_0xa9xxx
, MP4_FreeBox_0xa9xxx
},
2967 { ATOM_0xa9ope
, MP4_ReadBox_0xa9xxx
, MP4_FreeBox_0xa9xxx
},
2968 { ATOM_0xa9com
, MP4_ReadBox_0xa9xxx
, MP4_FreeBox_0xa9xxx
},
2969 { ATOM_0xa9wrt
, MP4_ReadBox_0xa9xxx
, MP4_FreeBox_0xa9xxx
},
2970 { ATOM_0xa9too
, MP4_ReadBox_0xa9xxx
, MP4_FreeBox_0xa9xxx
},
2971 { ATOM_0xa9wrn
, MP4_ReadBox_0xa9xxx
, MP4_FreeBox_0xa9xxx
},
2972 { ATOM_0xa9mak
, MP4_ReadBox_0xa9xxx
, MP4_FreeBox_0xa9xxx
},
2973 { ATOM_0xa9mod
, MP4_ReadBox_0xa9xxx
, MP4_FreeBox_0xa9xxx
},
2974 { ATOM_0xa9PRD
, MP4_ReadBox_0xa9xxx
, MP4_FreeBox_0xa9xxx
},
2975 { ATOM_0xa9grp
, MP4_ReadBox_0xa9xxx
, MP4_FreeBox_0xa9xxx
},
2976 { ATOM_0xa9lyr
, MP4_ReadBox_0xa9xxx
, MP4_FreeBox_0xa9xxx
},
2978 { ATOM_chpl
, MP4_ReadBox_chpl
, MP4_FreeBox_chpl
},
2980 /* iTunes/Quicktime meta info */
2981 { ATOM_meta
, MP4_ReadBox_meta
, MP4_FreeBox_Common
},
2982 { ATOM_name
, MP4_ReadBox_name
, MP4_FreeBox_name
},
2984 /* found in smoothstreaming */
2985 { ATOM_traf
, MP4_ReadBoxContainer
, MP4_FreeBox_Common
},
2986 { ATOM_mfhd
, MP4_ReadBox_mfhd
, MP4_FreeBox_Common
},
2987 { ATOM_tfhd
, MP4_ReadBox_tfhd
, MP4_FreeBox_Common
},
2988 { ATOM_trun
, MP4_ReadBox_trun
, MP4_FreeBox_trun
},
2991 { 0, MP4_ReadBox_default
, NULL
}
2995 /*****************************************************************************
2996 * MP4_ReadBox : parse the actual box and the children
2997 * XXX : Do not go to the next box
2998 *****************************************************************************/
2999 static MP4_Box_t
*MP4_ReadBox( stream_t
*p_stream
, MP4_Box_t
*p_father
)
3001 MP4_Box_t
*p_box
= calloc( 1, sizeof( MP4_Box_t
) ); /* Needed to ensure simple on error handler */
3002 unsigned int i_index
;
3007 if( !MP4_ReadBoxCommon( p_stream
, p_box
) )
3009 msg_Warn( p_stream
, "cannot read one box" );
3013 if( !p_box
->i_size
)
3015 msg_Dbg( p_stream
, "found an empty box (null size)" );
3019 p_box
->p_father
= p_father
;
3021 /* Now search function to call */
3022 for( i_index
= 0; ; i_index
++ )
3024 if( ( MP4_Box_Function
[i_index
].i_type
== p_box
->i_type
)||
3025 ( MP4_Box_Function
[i_index
].i_type
== 0 ) )
3031 if( !(MP4_Box_Function
[i_index
].MP4_ReadBox_function
)( p_stream
, p_box
) )
3033 MP4_BoxFree( p_stream
, p_box
);
3040 /*****************************************************************************
3041 * MP4_FreeBox : free memory after read with MP4_ReadBox and all
3043 *****************************************************************************/
3044 void MP4_BoxFree( stream_t
*s
, MP4_Box_t
*p_box
)
3046 unsigned int i_index
;
3052 for( p_child
= p_box
->p_first
; p_child
!= NULL
; )
3056 p_next
= p_child
->p_next
;
3057 MP4_BoxFree( s
, p_child
);
3061 /* Now search function to call */
3062 if( p_box
->data
.p_data
)
3064 for( i_index
= 0; ; i_index
++ )
3066 if( ( MP4_Box_Function
[i_index
].i_type
== p_box
->i_type
)||
3067 ( MP4_Box_Function
[i_index
].i_type
== 0 ) )
3072 if( MP4_Box_Function
[i_index
].MP4_FreeBox_function
== NULL
)
3074 /* Should not happen */
3075 if MP4_BOX_TYPE_ASCII()
3077 "cannot free box %4.4s, type unknown",
3078 (char*)&p_box
->i_type
);
3081 "cannot free box c%3.3s, type unknown",
3082 (char*)&p_box
->i_type
+1 );
3086 MP4_Box_Function
[i_index
].MP4_FreeBox_function( p_box
);
3088 free( p_box
->data
.p_data
);
3093 /*****************************************************************************
3094 * MP4_BoxGetRoot : Parse the entire file, and create all boxes in memory
3095 *****************************************************************************
3096 * The first box is a virtual box "root" and is the father for all first
3097 * level boxes for the file, a sort of virtual contener
3098 *****************************************************************************/
3099 MP4_Box_t
*MP4_BoxGetRoot( stream_t
*s
)
3105 p_root
= malloc( sizeof( MP4_Box_t
) );
3106 if( p_root
== NULL
)
3110 p_root
->i_type
= ATOM_root
;
3111 p_root
->i_shortsize
= 1;
3112 p_root
->i_size
= stream_Size( s
);
3113 CreateUUID( &p_root
->i_uuid
, p_root
->i_type
);
3115 p_root
->data
.p_data
= NULL
;
3116 p_root
->p_father
= NULL
;
3117 p_root
->p_first
= NULL
;
3118 p_root
->p_last
= NULL
;
3119 p_root
->p_next
= NULL
;
3123 i_result
= MP4_ReadBoxContainerRaw( p_stream
, p_root
);
3130 /* check if there is a cmov, if so replace
3131 compressed moov by uncompressed one */
3132 if( ( ( p_moov
= MP4_BoxGet( p_root
, "moov" ) ) &&
3133 ( p_cmov
= MP4_BoxGet( p_root
, "moov/cmov" ) ) ) ||
3134 ( ( p_moov
= MP4_BoxGet( p_root
, "foov" ) ) &&
3135 ( p_cmov
= MP4_BoxGet( p_root
, "foov/cmov" ) ) ) )
3137 /* rename the compressed moov as a box to skip */
3138 p_moov
->i_type
= ATOM_skip
;
3140 /* get uncompressed p_moov */
3141 p_moov
= p_cmov
->data
.p_cmov
->p_moov
;
3142 p_cmov
->data
.p_cmov
->p_moov
= NULL
;
3144 /* make p_root father of this new moov */
3145 p_moov
->p_father
= p_root
;
3147 /* insert this new moov box as first child of p_root */
3148 p_moov
->p_next
= p_root
->p_first
;
3149 p_root
->p_first
= p_moov
;
3157 static void MP4_BoxDumpStructure_Internal( stream_t
*s
,
3158 MP4_Box_t
*p_box
, unsigned int i_level
)
3164 if MP4_BOX_TYPE_ASCII()
3165 msg_Dbg( s
, "dumping root Box \"%4.4s\"",
3166 (char*)&p_box
->i_type
);
3168 msg_Dbg( s
, "dumping root Box \"c%3.3s\"",
3169 (char*)&p_box
->i_type
+1 );
3176 if( i_level
>= (sizeof(str
) - 1)/4 )
3179 memset( str
, ' ', sizeof(str
) );
3180 for( i
= 0; i
< i_level
; i
++ )
3184 if( MP4_BOX_TYPE_ASCII() )
3185 snprintf( &str
[i_level
* 4], sizeof(str
) - 4*i_level
,
3187 (char*)&p_box
->i_type
, (uint32_t)p_box
->i_size
);
3189 snprintf( &str
[i_level
* 4], sizeof(str
) - 4*i_level
,
3191 (char*)&p_box
->i_type
+1, (uint32_t)p_box
->i_size
);
3192 msg_Dbg( s
, "%s", str
);
3194 p_child
= p_box
->p_first
;
3197 MP4_BoxDumpStructure_Internal( s
, p_child
, i_level
+ 1 );
3198 p_child
= p_child
->p_next
;
3202 void MP4_BoxDumpStructure( stream_t
*s
, MP4_Box_t
*p_box
)
3204 MP4_BoxDumpStructure_Internal( s
, p_box
, 0 );
3208 /*****************************************************************************
3209 *****************************************************************************
3211 ** High level methods to acces an MP4 file
3213 *****************************************************************************
3214 *****************************************************************************/
3215 static void get_token( char **ppsz_path
, char **ppsz_token
, int *pi_number
)
3218 if( !*ppsz_path
[0] )
3224 i_len
= strcspn( *ppsz_path
, "/[" );
3225 if( !i_len
&& **ppsz_path
== '/' )
3229 *ppsz_token
= xmalloc( i_len
+ 1 );
3231 memcpy( *ppsz_token
, *ppsz_path
, i_len
);
3233 (*ppsz_token
)[i_len
] = '\0';
3235 *ppsz_path
+= i_len
;
3237 if( **ppsz_path
== '[' )
3240 *pi_number
= strtol( *ppsz_path
, NULL
, 10 );
3241 while( **ppsz_path
&& **ppsz_path
!= ']' )
3245 if( **ppsz_path
== ']' )
3254 while( **ppsz_path
== '/' )
3260 static void MP4_BoxGet_Internal( MP4_Box_t
**pp_result
,
3261 MP4_Box_t
*p_box
, const char *psz_fmt
, va_list args
)
3273 if( vasprintf( &psz_path
, psz_fmt
, args
) == -1 )
3276 if( !psz_path
|| !psz_path
[0] )
3283 // fprintf( stderr, "path:'%s'\n", psz_path );
3284 psz_dup
= psz_path
; /* keep this pointer, as it need to be unallocated */
3289 get_token( &psz_path
, &psz_token
, &i_number
);
3290 // fprintf( stderr, "path:'%s', token:'%s' n:%d\n",
3291 // psz_path,psz_token,i_number );
3299 if( !strcmp( psz_token
, "/" ) )
3302 while( p_box
&& p_box
->i_type
!= ATOM_root
)
3304 p_box
= p_box
->p_father
;
3312 if( !strcmp( psz_token
, "." ) )
3317 if( !strcmp( psz_token
, ".." ) )
3319 p_box
= p_box
->p_father
;
3326 if( strlen( psz_token
) == 4 )
3329 i_fourcc
= VLC_FOURCC( psz_token
[0], psz_token
[1],
3330 psz_token
[2], psz_token
[3] );
3331 p_box
= p_box
->p_first
;
3338 if( p_box
->i_type
== i_fourcc
)
3346 p_box
= p_box
->p_next
;
3350 if( *psz_token
== '\0' )
3352 p_box
= p_box
->p_first
;
3364 p_box
= p_box
->p_next
;
3369 // fprintf( stderr, "Argg malformed token \"%s\"",psz_token );
3373 FREENULL( psz_token
);
3385 /*****************************************************************************
3386 * MP4_BoxGet: find a box given a path relative to p_box
3387 *****************************************************************************
3388 * Path Format: . .. / as usual
3389 * [number] to specifie box number ex: trak[12]
3391 * ex: /moov/trak[12]
3393 *****************************************************************************/
3394 MP4_Box_t
*MP4_BoxGet( MP4_Box_t
*p_box
, const char *psz_fmt
, ... )
3397 MP4_Box_t
*p_result
;
3399 va_start( args
, psz_fmt
);
3400 MP4_BoxGet_Internal( &p_result
, p_box
, psz_fmt
, args
);
3406 /*****************************************************************************
3407 * MP4_BoxCount: count box given a path relative to p_box
3408 *****************************************************************************
3409 * Path Format: . .. / as usual
3410 * [number] to specifie box number ex: trak[12]
3412 * ex: /moov/trak[12]
3414 *****************************************************************************/
3415 int MP4_BoxCount( MP4_Box_t
*p_box
, const char *psz_fmt
, ... )
3419 MP4_Box_t
*p_result
, *p_next
;
3421 va_start( args
, psz_fmt
);
3422 MP4_BoxGet_Internal( &p_result
, p_box
, psz_fmt
, args
);
3430 for( p_next
= p_result
->p_next
; p_next
!= NULL
; p_next
= p_next
->p_next
)
3432 if( p_next
->i_type
== p_result
->i_type
)