37
41
* *look* at the code.
39
43
*****************************************************************************/
40
#define FREENULL( p ) do { free( p ); p = NULL; } while(0)
42
#define MP4_BOX_HEADERSIZE( p_box ) \
43
( 8 + ( p_box->i_shortsize == 1 ? 8 : 0 ) \
44
#define MP4_BOX_HEADERSIZE( p_box ) \
45
( 8 + ( p_box->i_shortsize == 1 ? 8 : 0 ) \
44
46
+ ( p_box->i_type == FOURCC_uuid ? 16 : 0 ) )
46
#define MP4_GET1BYTE( dst ) \
47
dst = *p_peek; p_peek++; i_read--
49
#define MP4_GET2BYTES( dst ) \
50
dst = GetWBE( p_peek ); p_peek += 2; i_read -= 2
52
#define MP4_GET3BYTES( dst ) \
53
dst = Get24bBE( p_peek ); p_peek += 3; i_read -= 3
55
#define MP4_GET4BYTES( dst ) \
56
dst = GetDWBE( p_peek ); p_peek += 4; i_read -= 4
58
#define MP4_GETFOURCC( dst ) \
59
dst = VLC_FOURCC( p_peek[0], p_peek[1], p_peek[2], p_peek[3] ); \
60
p_peek += 4; i_read -= 4
62
#define MP4_GET8BYTES( dst ) \
63
dst = GetQWBE( p_peek ); p_peek += 8; i_read -= 8
48
#define MP4_GETX_PRIVATE(dst, code, size) do { \
49
if( (i_read) >= (size) ) { dst = (code); p_peek += (size); } \
54
#define MP4_GET1BYTE( dst ) MP4_GETX_PRIVATE( dst, *p_peek, 1 )
55
#define MP4_GET2BYTES( dst ) MP4_GETX_PRIVATE( dst, GetWBE(p_peek), 2 )
56
#define MP4_GET3BYTES( dst ) MP4_GETX_PRIVATE( dst, Get24bBE(p_peek), 3 )
57
#define MP4_GET4BYTES( dst ) MP4_GETX_PRIVATE( dst, GetDWBE(p_peek), 4 )
58
#define MP4_GET8BYTES( dst ) MP4_GETX_PRIVATE( dst, GetQWBE(p_peek), 8 )
59
#define MP4_GETFOURCC( dst ) MP4_GETX_PRIVATE( dst, \
60
VLC_FOURCC(p_peek[0],p_peek[1],p_peek[2],p_peek[3]), 4)
65
62
#define MP4_GETVERSIONFLAGS( p_void ) \
66
63
MP4_GET1BYTE( p_void->i_version ); \
67
64
MP4_GET3BYTES( p_void->i_flags )
69
#define MP4_GETSTRINGZ( p_str ) \
70
if( ( i_read > 0 )&&( p_peek[0] ) ) \
72
p_str = calloc( sizeof( char ), __MIN( strlen( (char*)p_peek ), i_read )+1);\
73
memcpy( p_str, p_peek, __MIN( strlen( (char*)p_peek ), i_read ) ); \
74
p_str[__MIN( strlen( (char*)p_peek ), i_read )] = 0; \
75
p_peek += strlen( (char *)p_str ) + 1; \
76
i_read -= strlen( (char *)p_str ) + 1; \
66
#define MP4_GETSTRINGZ( p_str ) \
67
if( (i_read > 0) && (p_peek[0]) ) \
69
const int __i_copy__ = strnlen( (char*)p_peek, i_read-1 ); \
70
p_str = malloc( __i_copy__+1 ); \
73
memcpy( p_str, p_peek, __i_copy__ ); \
74
p_str[__i_copy__] = 0; \
76
p_peek += __i_copy__ + 1; \
77
i_read -= __i_copy__ + 1; \
84
84
#define MP4_READBOX_ENTER( MP4_Box_data_TYPE_t ) \
85
85
int64_t i_read = p_box->i_size; \
86
86
uint8_t *p_peek, *p_buff; \
87
i_read = p_box->i_size; \
87
int i_actually_read; \
88
88
if( !( p_peek = p_buff = malloc( i_read ) ) ) \
92
if( stream_Read( p_stream, p_peek, i_read ) < i_read )\
92
i_actually_read = stream_Read( p_stream, p_peek, i_read ); \
93
if( i_actually_read < 0 || (int64_t)i_actually_read < i_read )\
97
98
p_peek += MP4_BOX_HEADERSIZE( p_box ); \
98
99
i_read -= MP4_BOX_HEADERSIZE( p_box ); \
99
if( !( p_box->data.p_data = malloc( sizeof( MP4_Box_data_TYPE_t ) ) ) ) \
100
if( !( p_box->data.p_data = calloc( 1, sizeof( MP4_Box_data_TYPE_t ) ) ) ) \
101
102
free( p_buff ); \
605
624
MP4_GET1BYTE( i_len );
606
625
i_copy = __MIN( i_read, i_len );
608
memcpy( p_box->data.p_hdlr->psz_name, p_peek, i_copy );
627
memcpy( psz, p_peek, i_copy );
609
628
p_box->data.p_hdlr->psz_name[i_copy] = '\0';
613
memcpy( p_box->data.p_hdlr->psz_name, p_peek, i_read );
632
memcpy( psz, p_peek, i_read );
614
633
p_box->data.p_hdlr->psz_name[i_read] = '\0';
618
637
#ifdef MP4_VERBOSE
619
msg_Dbg( p_stream, "read box: \"hdlr\" handler type %4.4s name %s",
620
(char*)&p_box->data.p_hdlr->i_handler_type,
621
p_box->data.p_hdlr->psz_name );
638
msg_Dbg( p_stream, "read box: \"hdlr\" handler type %4.4s name %s",
639
(char*)&p_box->data.p_hdlr->i_handler_type,
640
p_box->data.p_hdlr->psz_name );
624
643
MP4_READBOX_EXIT( 1 );
965
981
msg_Dbg( p_stream, "found esds MP4DecSpecificDescr (%dBytes)",
985
MP4_READBOX_EXIT( 0 );
969
987
es_descriptor.p_decConfigDescr->i_decoder_specific_info_len = i_len;
970
988
es_descriptor.p_decConfigDescr->p_decoder_specific_info = malloc( i_len );
971
989
if( es_descriptor.p_decConfigDescr->p_decoder_specific_info == NULL )
973
MP4_FreeBox_esds( p_box );
990
MP4_READBOX_EXIT( 0 );
976
992
memcpy( es_descriptor.p_decConfigDescr->p_decoder_specific_info,
981
MP4_READBOX_EXIT( code );
995
MP4_READBOX_EXIT( 1 );
983
996
#undef es_descriptor
999
static void MP4_FreeBox_avcC( MP4_Box_t *p_box )
1001
MP4_Box_data_avcC_t *p_avcC = p_box->data.p_avcC;
1004
if( p_avcC->i_avcC > 0 ) FREENULL( p_avcC->p_avcC );
1008
for( i = 0; i < p_avcC->i_sps; i++ )
1009
FREENULL( p_avcC->sps[i] );
1013
for( i = 0; i < p_avcC->i_pps; i++ )
1014
FREENULL( p_avcC->pps[i] );
1016
if( p_avcC->i_sps > 0 ) FREENULL( p_avcC->sps );
1017
if( p_avcC->i_sps > 0 ) FREENULL( p_avcC->i_sps_length );
1018
if( p_avcC->i_pps > 0 ) FREENULL( p_avcC->pps );
1019
if( p_avcC->i_pps > 0 ) FREENULL( p_avcC->i_pps_length );
987
1022
static int MP4_ReadBox_avcC( stream_t *p_stream, MP4_Box_t *p_box )
2169
2163
static int MP4_ReadBox_0xa9xxx( stream_t *p_stream, MP4_Box_t *p_box )
2171
int16_t i_length, i_dummy;
2173
2167
MP4_READBOX_ENTER( MP4_Box_data_0xa9xxx_t );
2175
2169
p_box->data.p_0xa9xxx->psz_text = NULL;
2177
MP4_GET2BYTES( i_length );
2178
MP4_GET2BYTES( i_dummy );
2171
MP4_GET2BYTES( i16 );
2182
if( i_length > i_read ) i_length = i_read;
2184
p_box->data.p_0xa9xxx->psz_text = malloc( i_length + 1 );
2177
MP4_GET2BYTES( i16 );
2178
if( i_length >= i_read ) i_length = i_read + 1;
2180
p_box->data.p_0xa9xxx->psz_text = malloc( i_length );
2185
2181
if( p_box->data.p_0xa9xxx->psz_text == NULL )
2186
2182
MP4_READBOX_EXIT( 0 );
2188
2185
memcpy( p_box->data.p_0xa9xxx->psz_text,
2189
2186
p_peek, i_length );
2190
2187
p_box->data.p_0xa9xxx->psz_text[i_length] = '\0';
2192
2189
#ifdef MP4_VERBOSE
2193
2190
msg_Dbg( p_stream,
2194
"read box: \"%4.4s\" text=`%s'",
2195
(char*)&p_box->i_type,
2196
p_box->data.p_0xa9xxx->psz_text );
2191
"read box: \"c%3.3s\" text=`%s'",
2192
((char*)&p_box->i_type + 1),
2193
p_box->data.p_0xa9xxx->psz_text );
2198
/* try iTune/Quicktime format, rewind to start */
2199
p_peek -= 2; i_read += 2;
2200
// we are expecting a 'data' box
2201
uint32_t i_data_len;
2202
uint32_t i_data_tag;
2204
MP4_GET4BYTES( i_data_len );
2205
if( i_data_len > i_read ) i_data_len = i_read;
2206
MP4_GETFOURCC( i_data_tag );
2207
if( (i_data_len > 0) && (i_data_tag == VLC_FOURCC('d', 'a', 't', 'a')) )
2209
/* data box contains a version/flags field */
2211
uint32_t i_reserved;
2212
MP4_GET4BYTES( i_version );
2213
MP4_GET4BYTES( i_reserved );
2214
// version should be 0, flags should be 1 for text, 0 for data
2215
if( ( i_version == 0x00000001 ) && (i_data_len >= 12 ) )
2217
// the rest is the text
2219
p_box->data.p_0xa9xxx->psz_text = malloc( i_data_len + 1 );
2220
if( p_box->data.p_0xa9xxx->psz_text == NULL )
2221
MP4_READBOX_EXIT( 0 );
2223
memcpy( p_box->data.p_0xa9xxx->psz_text,
2224
p_peek, i_data_len );
2225
p_box->data.p_0xa9xxx->psz_text[i_data_len] = '\0';
2228
"read box: \"c%3.3s\" text=`%s'",
2229
((char*)&p_box->i_type+1),
2230
p_box->data.p_0xa9xxx->psz_text );
2235
// TODO: handle data values for ID3 tag values, track num or cover art,etc...
2200
2240
MP4_READBOX_EXIT( 1 );
2202
2242
static void MP4_FreeBox_0xa9xxx( MP4_Box_t *p_box )
2204
FREE( p_box->data.p_0xa9xxx->psz_text );
2244
FREENULL( p_box->data.p_0xa9xxx->psz_text );
2247
/* Chapter support */
2248
static void MP4_FreeBox_chpl( MP4_Box_t *p_box )
2250
MP4_Box_data_chpl_t *p_chpl = p_box->data.p_chpl;
2252
for( i = 0; i < p_chpl->i_chapter; i++ )
2253
free( p_chpl->chapter[i].psz_name );
2256
static int MP4_ReadBox_chpl( stream_t *p_stream, MP4_Box_t *p_box )
2258
MP4_Box_data_chpl_t *p_chpl;
2261
MP4_READBOX_ENTER( MP4_Box_data_chpl_t );
2263
p_chpl = p_box->data.p_chpl;
2265
MP4_GETVERSIONFLAGS( p_chpl );
2267
MP4_GET4BYTES( i_dummy );
2269
MP4_GET1BYTE( p_chpl->i_chapter );
2271
for( i = 0; i < p_chpl->i_chapter; i++ )
2276
MP4_GET8BYTES( i_start );
2277
MP4_GET1BYTE( i_len );
2279
p_chpl->chapter[i].psz_name = malloc( i_len + 1 );
2280
if( !p_chpl->chapter[i].psz_name )
2283
i_copy = __MIN( i_len, i_read );
2285
memcpy( p_chpl->chapter[i].psz_name, p_peek, i_copy );
2286
p_chpl->chapter[i].psz_name[i_copy] = '\0';
2287
p_chpl->chapter[i].i_start = i_start;
2292
/* Bubble sort by increasing start date */
2295
for( i = 0; i < p_chpl->i_chapter - 1; i++ )
2297
if( p_chpl->chapter[i].i_start > p_chpl->chapter[i+1].i_start )
2299
char *psz = p_chpl->chapter[i+1].psz_name;
2300
int64_t i64 = p_chpl->chapter[i+1].i_start;
2302
p_chpl->chapter[i+1].psz_name = p_chpl->chapter[i].psz_name;
2303
p_chpl->chapter[i+1].i_start = p_chpl->chapter[i].i_start;
2305
p_chpl->chapter[i].psz_name = psz;
2306
p_chpl->chapter[i].i_start = i64;
2315
msg_Dbg( p_stream, "read box: \"chpl\" %d chapters",
2316
p_chpl->i_chapter );
2318
MP4_READBOX_EXIT( 1 );
2321
MP4_READBOX_EXIT( 0 );
2324
static int MP4_ReadBox_tref_generic( stream_t *p_stream, MP4_Box_t *p_box )
2327
MP4_READBOX_ENTER( MP4_Box_data_tref_generic_t );
2329
p_box->data.p_tref_generic->i_track_ID = NULL;
2330
p_box->data.p_tref_generic->i_entry_count = i_read / sizeof(uint32_t);
2331
if( p_box->data.p_tref_generic->i_entry_count > 0 )
2332
p_box->data.p_tref_generic->i_track_ID = calloc( p_box->data.p_tref_generic->i_entry_count, sizeof(uint32_t) );
2333
if( p_box->data.p_tref_generic->i_track_ID == NULL )
2334
MP4_READBOX_EXIT( 0 );
2336
for( i = 0; i < p_box->data.p_tref_generic->i_entry_count; i++ )
2338
MP4_GET4BYTES( p_box->data.p_tref_generic->i_track_ID[i] );
2341
msg_Dbg( p_stream, "read box: \"chap\" %d references",
2342
p_box->data.p_tref_generic->i_entry_count );
2345
MP4_READBOX_EXIT( 1 );
2347
static void MP4_FreeBox_tref_generic( MP4_Box_t *p_box )
2349
FREENULL( p_box->data.p_tref_generic->i_track_ID );
2352
static int MP4_ReadBox_meta( stream_t *p_stream, MP4_Box_t *p_box )
2354
uint8_t meta_data[8];
2355
int i_actually_read;
2357
// skip over box header
2358
i_actually_read = stream_Read( p_stream, meta_data, 8 );
2359
if( i_actually_read < 8 )
2362
/* meta content starts with a 4 byte version/flags value (should be 0) */
2363
i_actually_read = stream_Read( p_stream, meta_data, 4 );
2364
if( i_actually_read < 4 )
2367
/* then it behaves like a container */
2368
return MP4_ReadBoxContainerRaw( p_stream, p_box );
2207
2371
/* For generic */