00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <stdlib.h>
00024
00025 #include <vlc/vlc.h>
00026 #include <vlc/input.h>
00027
00028 #ifdef HAVE_ZLIB_H
00029 # include <zlib.h>
00030 #endif
00031
00032 #include "libmp4.h"
00033 #include "drms.h"
00034
00035
00036
00037
00038
00039
00040 #define MP4_BOX_HEADERSIZE( p_box ) \
00041 ( 8 + ( p_box->i_shortsize == 1 ? 8 : 0 ) \
00042 + ( p_box->i_type == FOURCC_uuid ? 16 : 0 ) )
00043
00044 #define MP4_GET1BYTE( dst ) \
00045 dst = *p_peek; p_peek++; i_read--
00046
00047 #define MP4_GET2BYTES( dst ) \
00048 dst = GetWBE( p_peek ); p_peek += 2; i_read -= 2
00049
00050 #define MP4_GET3BYTES( dst ) \
00051 dst = Get24bBE( p_peek ); p_peek += 3; i_read -= 3
00052
00053 #define MP4_GET4BYTES( dst ) \
00054 dst = GetDWBE( p_peek ); p_peek += 4; i_read -= 4
00055
00056 #define MP4_GETFOURCC( dst ) \
00057 dst = VLC_FOURCC( p_peek[0], p_peek[1], p_peek[2], p_peek[3] ); \
00058 p_peek += 4; i_read -= 4
00059
00060 #define MP4_GET8BYTES( dst ) \
00061 dst = GetQWBE( p_peek ); p_peek += 8; i_read -= 8
00062
00063 #define MP4_GETVERSIONFLAGS( p_void ) \
00064 MP4_GET1BYTE( p_void->i_version ); \
00065 MP4_GET3BYTES( p_void->i_flags )
00066
00067 #define MP4_GETSTRINGZ( p_str ) \
00068 if( ( i_read > 0 )&&(p_peek[0] ) ) \
00069 { \
00070 p_str = calloc( sizeof( char ), __MIN( strlen( p_peek ), i_read )+1);\
00071 memcpy( p_str, p_peek, __MIN( strlen( p_peek ), i_read ) ); \
00072 p_str[__MIN( strlen( p_peek ), i_read )] = 0; \
00073 p_peek += strlen( p_str ) + 1; \
00074 i_read -= strlen( p_str ) + 1; \
00075 } \
00076 else \
00077 { \
00078 p_str = NULL; \
00079 }
00080
00081
00082 #define MP4_READBOX_ENTER( MP4_Box_data_TYPE_t ) \
00083 int64_t i_read = p_box->i_size; \
00084 uint8_t *p_peek, *p_buff; \
00085 i_read = p_box->i_size; \
00086 if( !( p_peek = p_buff = malloc( i_read ) ) ) \
00087 { \
00088 return( 0 ); \
00089 } \
00090 if( stream_Read( p_stream, p_peek, i_read ) < i_read )\
00091 { \
00092 free( p_buff ); \
00093 return( 0 ); \
00094 } \
00095 p_peek += MP4_BOX_HEADERSIZE( p_box ); \
00096 i_read -= MP4_BOX_HEADERSIZE( p_box ); \
00097 if( !( p_box->data.p_data = malloc( sizeof( MP4_Box_data_TYPE_t ) ) ) ) \
00098 { \
00099 free( p_buff ); \
00100 return( 0 ); \
00101 }
00102
00103 #define MP4_READBOX_EXIT( i_code ) \
00104 free( p_buff ); \
00105 if( i_read < 0 ) \
00106 { \
00107 msg_Warn( p_stream, "Not enough data" ); \
00108 } \
00109 return( i_code )
00110
00111 #define FREE( p ) \
00112 if( p ) {free( p ); p = NULL; }
00113
00114
00115
00116
00117
00118
00119
00120
00121 static uint32_t Get24bBE( uint8_t *p )
00122 {
00123 return( ( p[0] <<16 ) + ( p[1] <<8 ) + p[2] );
00124 }
00125
00126 static void GetUUID( UUID_t *p_uuid, uint8_t *p_buff )
00127 {
00128 memcpy( p_uuid, p_buff, 16 );
00129 }
00130
00131 static void CreateUUID( UUID_t *p_uuid, uint32_t i_fourcc )
00132 {
00133
00134
00135
00136 }
00137
00138
00139
00140 static void MP4_ConvertDate2Str( char *psz, uint64_t i_date )
00141 {
00142 int i_day;
00143 int i_hour;
00144 int i_min;
00145 int i_sec;
00146
00147
00148 i_date += ((I64C(1904) * 365) + 17) * 24 * 60 * 60;
00149
00150 i_day = i_date / ( 60*60*24);
00151 i_hour = ( i_date /( 60*60 ) ) % 60;
00152 i_min = ( i_date / 60 ) % 60;
00153 i_sec = i_date % 60;
00154 sprintf( psz, "%dd-%2.2dh:%2.2dm:%2.2ds", i_day, i_hour, i_min, i_sec );
00155 }
00156
00157
00158
00159
00160 static MP4_Box_t *MP4_ReadBox( stream_t *p_stream, MP4_Box_t *p_father );
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171 int MP4_ReadBoxCommon( stream_t *p_stream, MP4_Box_t *p_box )
00172 {
00173 int i_read;
00174 uint8_t *p_peek;
00175
00176 if( ( ( i_read = stream_Peek( p_stream, &p_peek, 32 ) ) < 8 ) )
00177 {
00178 return 0;
00179 }
00180 p_box->i_pos = stream_Tell( p_stream );
00181
00182 p_box->data.p_data = NULL;
00183 p_box->p_father = NULL;
00184 p_box->p_first = NULL;
00185 p_box->p_last = NULL;
00186 p_box->p_next = NULL;
00187
00188 MP4_GET4BYTES( p_box->i_shortsize );
00189 MP4_GETFOURCC( p_box->i_type );
00190
00191
00192
00193 if( p_box->i_shortsize == 1 )
00194 {
00195
00196 MP4_GET8BYTES( p_box->i_size );
00197 }
00198 else
00199 {
00200 p_box->i_size = p_box->i_shortsize;
00201
00202 }
00203
00204 if( p_box->i_type == FOURCC_uuid )
00205 {
00206
00207 GetUUID( &p_box->i_uuid, p_peek );
00208 p_peek += 16; i_read -= 16;
00209 }
00210 else
00211 {
00212 CreateUUID( &p_box->i_uuid, p_box->i_type );
00213 }
00214 #ifdef MP4_VERBOSE
00215 if( p_box->i_size )
00216 {
00217 msg_Dbg( p_stream, "found Box: %4.4s size "I64Fd,
00218 (char*)&p_box->i_type, p_box->i_size );
00219 }
00220 #endif
00221
00222 return 1;
00223 }
00224
00225
00226
00227
00228
00229
00230 static int MP4_NextBox( stream_t *p_stream, MP4_Box_t *p_box )
00231 {
00232 MP4_Box_t box;
00233
00234 if( !p_box )
00235 {
00236 MP4_ReadBoxCommon( p_stream, &box );
00237 p_box = &box;
00238 }
00239
00240 if( !p_box->i_size )
00241 {
00242 return 2;
00243 }
00244
00245 if( p_box->p_father )
00246 {
00247
00248 if( p_box->i_size + p_box->i_pos >=
00249 p_box->p_father->i_size + p_box->p_father->i_pos )
00250 {
00251 return 0;
00252 }
00253 }
00254 if( stream_Seek( p_stream, p_box->i_size + p_box->i_pos ) )
00255 {
00256 return 0;
00257 }
00258
00259 return 1;
00260 }
00261
00262
00263
00264
00265
00266
00267
00268 static int MP4_ReadBoxContainerRaw( stream_t *p_stream, MP4_Box_t *p_container )
00269 {
00270 MP4_Box_t *p_box;
00271
00272 if( stream_Tell( p_stream ) + 8 >
00273 (off_t)(p_container->i_pos + p_container->i_size) )
00274 {
00275
00276 return 0;
00277 }
00278
00279 do
00280 {
00281 if( ( p_box = MP4_ReadBox( p_stream, p_container ) ) == NULL ) break;
00282
00283
00284 if( !p_container->p_first ) p_container->p_first = p_box;
00285 else p_container->p_last->p_next = p_box;
00286 p_container->p_last = p_box;
00287
00288 } while( MP4_NextBox( p_stream, p_box ) == 1 );
00289
00290 return 1;
00291 }
00292
00293 static int MP4_ReadBoxContainer( stream_t *p_stream, MP4_Box_t *p_container )
00294 {
00295 if( p_container->i_size <= (size_t)MP4_BOX_HEADERSIZE(p_container ) + 8 )
00296 {
00297
00298 return 1;
00299 }
00300
00301
00302 stream_Seek( p_stream, p_container->i_pos +
00303 MP4_BOX_HEADERSIZE( p_container ) );
00304
00305 return MP4_ReadBoxContainerRaw( p_stream, p_container );
00306 }
00307
00308 static void MP4_FreeBox_Common( MP4_Box_t *p_box )
00309 {
00310
00311 }
00312
00313 static int MP4_ReadBoxSkip( stream_t *p_stream, MP4_Box_t *p_box )
00314 {
00315
00316 if( p_box->p_father &&
00317 p_box->p_father->i_type == VLC_FOURCC( 'r', 'o', 'o', 't' ) &&
00318 p_box->i_type == FOURCC_free )
00319 {
00320 uint8_t *p_peek;
00321 int i_read;
00322 vlc_fourcc_t i_fcc;
00323
00324 i_read = stream_Peek( p_stream, &p_peek, 44 );
00325
00326 p_peek += MP4_BOX_HEADERSIZE( p_box ) + 4;
00327 i_read -= MP4_BOX_HEADERSIZE( p_box ) + 4;
00328
00329 if( i_read >= 8 )
00330 {
00331 i_fcc = VLC_FOURCC( p_peek[0], p_peek[1], p_peek[2], p_peek[3] );
00332
00333 if( i_fcc == FOURCC_cmov || i_fcc == FOURCC_mvhd )
00334 {
00335 msg_Warn( p_stream, "detected moov hidden in a free box ..." );
00336
00337 p_box->i_type = FOURCC_foov;
00338 return MP4_ReadBoxContainer( p_stream, p_box );
00339 }
00340 }
00341 }
00342
00343
00344 #ifdef MP4_VERBOSE
00345 msg_Dbg( p_stream, "skip box: \"%4.4s\"", (char*)&p_box->i_type );
00346 #endif
00347 return 1;
00348 }
00349
00350 static int MP4_ReadBox_ftyp( stream_t *p_stream, MP4_Box_t *p_box )
00351 {
00352 MP4_READBOX_ENTER( MP4_Box_data_ftyp_t );
00353
00354 MP4_GETFOURCC( p_box->data.p_ftyp->i_major_brand );
00355 MP4_GET4BYTES( p_box->data.p_ftyp->i_minor_version );
00356
00357 if( ( p_box->data.p_ftyp->i_compatible_brands_count = i_read / 4 ) )
00358 {
00359 unsigned int i;
00360 p_box->data.p_ftyp->i_compatible_brands =
00361 calloc( p_box->data.p_ftyp->i_compatible_brands_count, sizeof(uint32_t));
00362
00363 for( i =0; i < p_box->data.p_ftyp->i_compatible_brands_count; i++ )
00364 {
00365 MP4_GETFOURCC( p_box->data.p_ftyp->i_compatible_brands[i] );
00366 }
00367 }
00368 else
00369 {
00370 p_box->data.p_ftyp->i_compatible_brands = NULL;
00371 }
00372
00373 MP4_READBOX_EXIT( 1 );
00374 }
00375
00376 static void MP4_FreeBox_ftyp( MP4_Box_t *p_box )
00377 {
00378 FREE( p_box->data.p_ftyp->i_compatible_brands );
00379 }
00380
00381
00382 static int MP4_ReadBox_mvhd( stream_t *p_stream, MP4_Box_t *p_box )
00383 {
00384 unsigned int i;
00385 #ifdef MP4_VERBOSE
00386 char s_creation_time[128];
00387 char s_modification_time[128];
00388 char s_duration[128];
00389 #endif
00390 MP4_READBOX_ENTER( MP4_Box_data_mvhd_t );
00391
00392 MP4_GETVERSIONFLAGS( p_box->data.p_mvhd );
00393
00394 if( p_box->data.p_mvhd->i_version )
00395 {
00396 MP4_GET8BYTES( p_box->data.p_mvhd->i_creation_time );
00397 MP4_GET8BYTES( p_box->data.p_mvhd->i_modification_time );
00398 MP4_GET4BYTES( p_box->data.p_mvhd->i_timescale );
00399 MP4_GET8BYTES( p_box->data.p_mvhd->i_duration );
00400 }
00401 else
00402 {
00403 MP4_GET4BYTES( p_box->data.p_mvhd->i_creation_time );
00404 MP4_GET4BYTES( p_box->data.p_mvhd->i_modification_time );
00405 MP4_GET4BYTES( p_box->data.p_mvhd->i_timescale );
00406 MP4_GET4BYTES( p_box->data.p_mvhd->i_duration );
00407 }
00408 MP4_GET4BYTES( p_box->data.p_mvhd->i_rate );
00409 MP4_GET2BYTES( p_box->data.p_mvhd->i_volume );
00410 MP4_GET2BYTES( p_box->data.p_mvhd->i_reserved1 );
00411
00412
00413 for( i = 0; i < 2; i++ )
00414 {
00415 MP4_GET4BYTES( p_box->data.p_mvhd->i_reserved2[i] );
00416 }
00417 for( i = 0; i < 9; i++ )
00418 {
00419 MP4_GET4BYTES( p_box->data.p_mvhd->i_matrix[i] );
00420 }
00421 for( i = 0; i < 6; i++ )
00422 {
00423 MP4_GET4BYTES( p_box->data.p_mvhd->i_predefined[i] );
00424 }
00425
00426 MP4_GET4BYTES( p_box->data.p_mvhd->i_next_track_id );
00427
00428
00429 #ifdef MP4_VERBOSE
00430 MP4_ConvertDate2Str( s_creation_time, p_box->data.p_mvhd->i_creation_time );
00431 MP4_ConvertDate2Str( s_modification_time,
00432 p_box->data.p_mvhd->i_modification_time );
00433 if( p_box->data.p_mvhd->i_rate )
00434 {
00435 MP4_ConvertDate2Str( s_duration,
00436 p_box->data.p_mvhd->i_duration / p_box->data.p_mvhd->i_rate );
00437 }
00438 else
00439 {
00440 s_duration[0] = 0;
00441 }
00442 msg_Dbg( p_stream, "read box: \"mvhd\" creation %s modification %s time scale %d duration %s rate %f volume %f next track id %d",
00443 s_creation_time,
00444 s_modification_time,
00445 (uint32_t)p_box->data.p_mvhd->i_timescale,
00446 s_duration,
00447 (float)p_box->data.p_mvhd->i_rate / (1<<16 ),
00448 (float)p_box->data.p_mvhd->i_volume / 256 ,
00449 (uint32_t)p_box->data.p_mvhd->i_next_track_id );
00450 #endif
00451 MP4_READBOX_EXIT( 1 );
00452 }
00453
00454 static int MP4_ReadBox_tkhd( stream_t *p_stream, MP4_Box_t *p_box )
00455 {
00456 unsigned int i;
00457 #ifdef MP4_VERBOSE
00458 char s_creation_time[128];
00459 char s_modification_time[128];
00460 char s_duration[128];
00461 #endif
00462 MP4_READBOX_ENTER( MP4_Box_data_tkhd_t );
00463
00464 MP4_GETVERSIONFLAGS( p_box->data.p_tkhd );
00465
00466 if( p_box->data.p_tkhd->i_version )
00467 {
00468 MP4_GET8BYTES( p_box->data.p_tkhd->i_creation_time );
00469 MP4_GET8BYTES( p_box->data.p_tkhd->i_modification_time );
00470 MP4_GET4BYTES( p_box->data.p_tkhd->i_track_ID );
00471 MP4_GET4BYTES( p_box->data.p_tkhd->i_reserved );
00472 MP4_GET8BYTES( p_box->data.p_tkhd->i_duration );
00473 }
00474 else
00475 {
00476 MP4_GET4BYTES( p_box->data.p_tkhd->i_creation_time );
00477 MP4_GET4BYTES( p_box->data.p_tkhd->i_modification_time );
00478 MP4_GET4BYTES( p_box->data.p_tkhd->i_track_ID );
00479 MP4_GET4BYTES( p_box->data.p_tkhd->i_reserved );
00480 MP4_GET4BYTES( p_box->data.p_tkhd->i_duration );
00481 }
00482
00483 for( i = 0; i < 2; i++ )
00484 {
00485 MP4_GET4BYTES( p_box->data.p_tkhd->i_reserved2[i] );
00486 }
00487 MP4_GET2BYTES( p_box->data.p_tkhd->i_layer );
00488 MP4_GET2BYTES( p_box->data.p_tkhd->i_predefined );
00489 MP4_GET2BYTES( p_box->data.p_tkhd->i_volume );
00490 MP4_GET2BYTES( p_box->data.p_tkhd->i_reserved3 );
00491
00492 for( i = 0; i < 9; i++ )
00493 {
00494 MP4_GET4BYTES( p_box->data.p_tkhd->i_matrix[i] );
00495 }
00496 MP4_GET4BYTES( p_box->data.p_tkhd->i_width );
00497 MP4_GET4BYTES( p_box->data.p_tkhd->i_height );
00498
00499 #ifdef MP4_VERBOSE
00500 MP4_ConvertDate2Str( s_creation_time, p_box->data.p_mvhd->i_creation_time );
00501 MP4_ConvertDate2Str( s_modification_time, p_box->data.p_mvhd->i_modification_time );
00502 MP4_ConvertDate2Str( s_duration, p_box->data.p_mvhd->i_duration );
00503
00504 msg_Dbg( p_stream, "read box: \"tkhd\" creation %s modification %s duration %s track ID %d layer %d volume %f width %f height %f",
00505 s_creation_time,
00506 s_modification_time,
00507 s_duration,
00508 p_box->data.p_tkhd->i_track_ID,
00509 p_box->data.p_tkhd->i_layer,
00510 (float)p_box->data.p_tkhd->i_volume / 256 ,
00511 (float)p_box->data.p_tkhd->i_width / 65536,
00512 (float)p_box->data.p_tkhd->i_height / 65536 );
00513 #endif
00514 MP4_READBOX_EXIT( 1 );
00515 }
00516
00517
00518 static int MP4_ReadBox_mdhd( stream_t *p_stream, MP4_Box_t *p_box )
00519 {
00520 unsigned int i;
00521 uint16_t i_language;
00522 #ifdef MP4_VERBOSE
00523 char s_creation_time[128];
00524 char s_modification_time[128];
00525 char s_duration[128];
00526 #endif
00527 MP4_READBOX_ENTER( MP4_Box_data_mdhd_t );
00528
00529 MP4_GETVERSIONFLAGS( p_box->data.p_mdhd );
00530
00531 if( p_box->data.p_mdhd->i_version )
00532 {
00533 MP4_GET8BYTES( p_box->data.p_mdhd->i_creation_time );
00534 MP4_GET8BYTES( p_box->data.p_mdhd->i_modification_time );
00535 MP4_GET4BYTES( p_box->data.p_mdhd->i_timescale );
00536 MP4_GET8BYTES( p_box->data.p_mdhd->i_duration );
00537 }
00538 else
00539 {
00540 MP4_GET4BYTES( p_box->data.p_mdhd->i_creation_time );
00541 MP4_GET4BYTES( p_box->data.p_mdhd->i_modification_time );
00542 MP4_GET4BYTES( p_box->data.p_mdhd->i_timescale );
00543 MP4_GET4BYTES( p_box->data.p_mdhd->i_duration );
00544 }
00545 i_language = GetWBE( p_peek );
00546 for( i = 0; i < 3; i++ )
00547 {
00548 p_box->data.p_mdhd->i_language[i] =
00549 ( ( i_language >> ( (2-i)*5 ) )&0x1f ) + 0x60;
00550 }
00551
00552 MP4_GET2BYTES( p_box->data.p_mdhd->i_predefined );
00553
00554 #ifdef MP4_VERBOSE
00555 MP4_ConvertDate2Str( s_creation_time, p_box->data.p_mdhd->i_creation_time );
00556 MP4_ConvertDate2Str( s_modification_time, p_box->data.p_mdhd->i_modification_time );
00557 MP4_ConvertDate2Str( s_duration, p_box->data.p_mdhd->i_duration );
00558 msg_Dbg( p_stream, "read box: \"mdhd\" creation %s modification %s time scale %d duration %s language %c%c%c",
00559 s_creation_time,
00560 s_modification_time,
00561 (uint32_t)p_box->data.p_mdhd->i_timescale,
00562 s_duration,
00563 p_box->data.p_mdhd->i_language[0],
00564 p_box->data.p_mdhd->i_language[1],
00565 p_box->data.p_mdhd->i_language[2] );
00566 #endif
00567 MP4_READBOX_EXIT( 1 );
00568 }
00569
00570
00571 static int MP4_ReadBox_hdlr( stream_t *p_stream, MP4_Box_t *p_box )
00572 {
00573 int32_t i_reserved;
00574
00575 MP4_READBOX_ENTER( MP4_Box_data_hdlr_t );
00576
00577 MP4_GETVERSIONFLAGS( p_box->data.p_hdlr );
00578
00579 MP4_GETFOURCC( p_box->data.p_hdlr->i_predefined );
00580 MP4_GETFOURCC( p_box->data.p_hdlr->i_handler_type );
00581
00582 MP4_GET4BYTES( i_reserved );
00583 MP4_GET4BYTES( i_reserved );
00584 MP4_GET4BYTES( i_reserved );
00585
00586 p_box->data.p_hdlr->psz_name = calloc( sizeof( char ), i_read + 1 );
00587
00588
00589 if( p_box->data.p_hdlr->i_predefined == VLC_FOURCC( 'm', 'h', 'l', 'r' ) )
00590 {
00591 uint8_t i_len;
00592 int i_copy;
00593
00594 MP4_GET1BYTE( i_len );
00595 i_copy = __MIN( i_read, i_len );
00596
00597 memcpy( p_box->data.p_hdlr->psz_name, p_peek, i_copy );
00598 p_box->data.p_hdlr->psz_name[i_copy] = '\0';
00599 }
00600 else
00601 {
00602 memcpy( p_box->data.p_hdlr->psz_name, p_peek, i_read );
00603 p_box->data.p_hdlr->psz_name[i_read] = '\0';
00604 }
00605
00606
00607 #ifdef MP4_VERBOSE
00608 msg_Dbg( p_stream, "read box: \"hdlr\" hanler type %4.4s name %s",
00609 (char*)&p_box->data.p_hdlr->i_handler_type,
00610 p_box->data.p_hdlr->psz_name );
00611
00612 #endif
00613 MP4_READBOX_EXIT( 1 );
00614 }
00615
00616 static void MP4_FreeBox_hdlr( MP4_Box_t *p_box )
00617 {
00618 FREE( p_box->data.p_hdlr->psz_name );
00619 }
00620
00621 static int MP4_ReadBox_vmhd( stream_t *p_stream, MP4_Box_t *p_box )
00622 {
00623 unsigned int i;
00624
00625 MP4_READBOX_ENTER( MP4_Box_data_vmhd_t );
00626
00627 MP4_GETVERSIONFLAGS( p_box->data.p_vmhd );
00628
00629 MP4_GET2BYTES( p_box->data.p_vmhd->i_graphics_mode );
00630 for( i = 0; i < 3; i++ )
00631 {
00632 MP4_GET2BYTES( p_box->data.p_vmhd->i_opcolor[i] );
00633 }
00634
00635 #ifdef MP4_VERBOSE
00636 msg_Dbg( p_stream, "read box: \"vmhd\" graphics-mode %d opcolor (%d, %d, %d)",
00637 p_box->data.p_vmhd->i_graphics_mode,
00638 p_box->data.p_vmhd->i_opcolor[0],
00639 p_box->data.p_vmhd->i_opcolor[1],
00640 p_box->data.p_vmhd->i_opcolor[2] );
00641 #endif
00642 MP4_READBOX_EXIT( 1 );
00643 }
00644
00645 static int MP4_ReadBox_smhd( stream_t *p_stream, MP4_Box_t *p_box )
00646 {
00647 MP4_READBOX_ENTER( MP4_Box_data_smhd_t );
00648
00649 MP4_GETVERSIONFLAGS( p_box->data.p_smhd );
00650
00651
00652
00653 MP4_GET2BYTES( p_box->data.p_smhd->i_balance );
00654
00655 MP4_GET2BYTES( p_box->data.p_smhd->i_reserved );
00656
00657 #ifdef MP4_VERBOSE
00658 msg_Dbg( p_stream, "read box: \"smhd\" balance %f",
00659 (float)p_box->data.p_smhd->i_balance / 256 );
00660 #endif
00661 MP4_READBOX_EXIT( 1 );
00662 }
00663
00664
00665 static int MP4_ReadBox_hmhd( stream_t *p_stream, MP4_Box_t *p_box )
00666 {
00667 MP4_READBOX_ENTER( MP4_Box_data_hmhd_t );
00668
00669 MP4_GETVERSIONFLAGS( p_box->data.p_hmhd );
00670
00671 MP4_GET2BYTES( p_box->data.p_hmhd->i_max_PDU_size );
00672 MP4_GET2BYTES( p_box->data.p_hmhd->i_avg_PDU_size );
00673
00674 MP4_GET4BYTES( p_box->data.p_hmhd->i_max_bitrate );
00675 MP4_GET4BYTES( p_box->data.p_hmhd->i_avg_bitrate );
00676
00677 MP4_GET4BYTES( p_box->data.p_hmhd->i_reserved );
00678
00679 #ifdef MP4_VERBOSE
00680 msg_Dbg( p_stream, "read box: \"hmhd\" maxPDU-size %d avgPDU-size %d max-bitrate %d avg-bitrate %d",
00681 p_box->data.p_hmhd->i_max_PDU_size,
00682 p_box->data.p_hmhd->i_avg_PDU_size,
00683 p_box->data.p_hmhd->i_max_bitrate,
00684 p_box->data.p_hmhd->i_avg_bitrate );
00685 #endif
00686 MP4_READBOX_EXIT( 1 );
00687 }
00688
00689 static int MP4_ReadBox_url( stream_t *p_stream, MP4_Box_t *p_box )
00690 {
00691 MP4_READBOX_ENTER( MP4_Box_data_url_t );
00692
00693 MP4_GETVERSIONFLAGS( p_box->data.p_url );
00694 MP4_GETSTRINGZ( p_box->data.p_url->psz_location );
00695
00696 #ifdef MP4_VERBOSE
00697 msg_Dbg( p_stream, "read box: \"url\" url: %s",
00698 p_box->data.p_url->psz_location );
00699
00700 #endif
00701 MP4_READBOX_EXIT( 1 );
00702 }
00703
00704
00705 static void MP4_FreeBox_url( MP4_Box_t *p_box )
00706 {
00707 FREE( p_box->data.p_url->psz_location )
00708 }
00709
00710 static int MP4_ReadBox_urn( stream_t *p_stream, MP4_Box_t *p_box )
00711 {
00712 MP4_READBOX_ENTER( MP4_Box_data_urn_t );
00713
00714 MP4_GETVERSIONFLAGS( p_box->data.p_urn );
00715
00716 MP4_GETSTRINGZ( p_box->data.p_urn->psz_name );
00717 MP4_GETSTRINGZ( p_box->data.p_urn->psz_location );
00718
00719 #ifdef MP4_VERBOSE
00720 msg_Dbg( p_stream, "read box: \"urn\" name %s location %s",
00721 p_box->data.p_urn->psz_name,
00722 p_box->data.p_urn->psz_location );
00723 #endif
00724 MP4_READBOX_EXIT( 1 );
00725 }
00726 static void MP4_FreeBox_urn( MP4_Box_t *p_box )
00727 {
00728 FREE( p_box->data.p_urn->psz_name );
00729 FREE( p_box->data.p_urn->psz_location );
00730 }
00731
00732
00733 static int MP4_ReadBox_dref( stream_t *p_stream, MP4_Box_t *p_box )
00734 {
00735 MP4_READBOX_ENTER( MP4_Box_data_dref_t );
00736
00737 MP4_GETVERSIONFLAGS( p_box->data.p_dref );
00738
00739 MP4_GET4BYTES( p_box->data.p_dref->i_entry_count );
00740
00741 stream_Seek( p_stream, p_box->i_pos + MP4_BOX_HEADERSIZE( p_box ) + 8 );
00742 MP4_ReadBoxContainerRaw( p_stream, p_box );
00743
00744 #ifdef MP4_VERBOSE
00745 msg_Dbg( p_stream, "read box: \"dref\" entry-count %d",
00746 p_box->data.p_dref->i_entry_count );
00747
00748 #endif
00749 MP4_READBOX_EXIT( 1 );
00750 }
00751
00752
00753 static int MP4_ReadBox_stts( stream_t *p_stream, MP4_Box_t *p_box )
00754 {
00755 unsigned int i;
00756 MP4_READBOX_ENTER( MP4_Box_data_stts_t );
00757
00758 MP4_GETVERSIONFLAGS( p_box->data.p_stts );
00759 MP4_GET4BYTES( p_box->data.p_stts->i_entry_count );
00760
00761 p_box->data.p_stts->i_sample_count =
00762 calloc( sizeof( uint32_t ), p_box->data.p_stts->i_entry_count );
00763 p_box->data.p_stts->i_sample_delta =
00764 calloc( sizeof( uint32_t ), p_box->data.p_stts->i_entry_count );
00765
00766 for( i = 0; (i < p_box->data.p_stts->i_entry_count )&&( i_read >=8 ); i++ )
00767 {
00768 MP4_GET4BYTES( p_box->data.p_stts->i_sample_count[i] );
00769 MP4_GET4BYTES( p_box->data.p_stts->i_sample_delta[i] );
00770 }
00771
00772 #ifdef MP4_VERBOSE
00773 msg_Dbg( p_stream, "read box: \"stts\" entry-count %d",
00774 p_box->data.p_stts->i_entry_count );
00775
00776 #endif
00777 MP4_READBOX_EXIT( 1 );
00778 }
00779
00780 static void MP4_FreeBox_stts( MP4_Box_t *p_box )
00781 {
00782 FREE( p_box->data.p_stts->i_sample_count );
00783 FREE( p_box->data.p_stts->i_sample_delta );
00784 }
00785
00786 static int MP4_ReadBox_ctts( stream_t *p_stream, MP4_Box_t *p_box )
00787 {
00788 unsigned int i;
00789 MP4_READBOX_ENTER( MP4_Box_data_ctts_t );
00790
00791 MP4_GETVERSIONFLAGS( p_box->data.p_ctts );
00792
00793 MP4_GET4BYTES( p_box->data.p_ctts->i_entry_count );
00794
00795 p_box->data.p_ctts->i_sample_count =
00796 calloc( sizeof( uint32_t ), p_box->data.p_ctts->i_entry_count );
00797 p_box->data.p_ctts->i_sample_offset =
00798 calloc( sizeof( uint32_t ), p_box->data.p_ctts->i_entry_count );
00799
00800 for( i = 0; (i < p_box->data.p_ctts->i_entry_count )&&( i_read >=8 ); i++ )
00801 {
00802 MP4_GET4BYTES( p_box->data.p_ctts->i_sample_count[i] );
00803 MP4_GET4BYTES( p_box->data.p_ctts->i_sample_offset[i] );
00804 }
00805
00806 #ifdef MP4_VERBOSE
00807 msg_Dbg( p_stream, "read box: \"ctts\" entry-count %d",
00808 p_box->data.p_ctts->i_entry_count );
00809
00810 #endif
00811 MP4_READBOX_EXIT( 1 );
00812 }
00813
00814 static void MP4_FreeBox_ctts( MP4_Box_t *p_box )
00815 {
00816 FREE( p_box->data.p_ctts->i_sample_count );
00817 FREE( p_box->data.p_ctts->i_sample_offset );
00818 }
00819
00820 static int MP4_ReadLengthDescriptor( uint8_t **pp_peek, int64_t *i_read )
00821 {
00822 unsigned int i_b;
00823 unsigned int i_len = 0;
00824 do
00825 {
00826 i_b = **pp_peek;
00827
00828 (*pp_peek)++;
00829 (*i_read)--;
00830 i_len = ( i_len << 7 ) + ( i_b&0x7f );
00831 } while( i_b&0x80 );
00832 return( i_len );
00833 }
00834
00835 static int MP4_ReadBox_esds( stream_t *p_stream, MP4_Box_t *p_box )
00836 {
00837 #define es_descriptor p_box->data.p_esds->es_descriptor
00838 unsigned int i_len;
00839 unsigned int i_flags;
00840 unsigned int i_type;
00841
00842 MP4_READBOX_ENTER( MP4_Box_data_esds_t );
00843
00844 MP4_GETVERSIONFLAGS( p_box->data.p_esds );
00845
00846
00847 MP4_GET1BYTE( i_type );
00848 if( i_type == 0x03 )
00849 {
00850 i_len = MP4_ReadLengthDescriptor( &p_peek, &i_read );
00851
00852 #ifdef MP4_VERBOSE
00853 msg_Dbg( p_stream, "found esds MPEG4ESDescr (%dBytes)",
00854 i_len );
00855 #endif
00856
00857 MP4_GET2BYTES( es_descriptor.i_ES_ID );
00858 MP4_GET1BYTE( i_flags );
00859 es_descriptor.b_stream_dependence = ( (i_flags&0x80) != 0);
00860 es_descriptor.b_url = ( (i_flags&0x40) != 0);
00861 es_descriptor.b_OCRstream = ( (i_flags&0x20) != 0);
00862
00863 es_descriptor.i_stream_priority = i_flags&0x1f;
00864 if( es_descriptor.b_stream_dependence )
00865 {
00866 MP4_GET2BYTES( es_descriptor.i_depend_on_ES_ID );
00867 }
00868 if( es_descriptor.b_url )
00869 {
00870 unsigned int i_len;
00871
00872 MP4_GET1BYTE( i_len );
00873 es_descriptor.psz_URL = calloc( sizeof(char), i_len + 1 );
00874 memcpy( es_descriptor.psz_URL, p_peek, i_len );
00875 es_descriptor.psz_URL[i_len] = 0;
00876 p_peek += i_len;
00877 i_read -= i_len;
00878 }
00879 else
00880 {
00881 es_descriptor.psz_URL = NULL;
00882 }
00883 if( es_descriptor.b_OCRstream )
00884 {
00885 MP4_GET2BYTES( es_descriptor.i_OCR_ES_ID );
00886 }
00887 MP4_GET1BYTE( i_type );
00888 }
00889
00890 if( i_type != 0x04)
00891 {
00892 es_descriptor.p_decConfigDescr = NULL;
00893 MP4_READBOX_EXIT( 1 );
00894 }
00895
00896 i_len = MP4_ReadLengthDescriptor( &p_peek, &i_read );
00897
00898 #ifdef MP4_VERBOSE
00899 msg_Dbg( p_stream, "found esds MP4DecConfigDescr (%dBytes)",
00900 i_len );
00901 #endif
00902
00903 es_descriptor.p_decConfigDescr =
00904 malloc( sizeof( MP4_descriptor_decoder_config_t ));
00905
00906 MP4_GET1BYTE( es_descriptor.p_decConfigDescr->i_objectTypeIndication );
00907 MP4_GET1BYTE( i_flags );
00908 es_descriptor.p_decConfigDescr->i_streamType = i_flags >> 2;
00909 es_descriptor.p_decConfigDescr->b_upStream = ( i_flags >> 1 )&0x01;
00910 MP4_GET3BYTES( es_descriptor.p_decConfigDescr->i_buffer_sizeDB );
00911 MP4_GET4BYTES( es_descriptor.p_decConfigDescr->i_max_bitrate );
00912 MP4_GET4BYTES( es_descriptor.p_decConfigDescr->i_avg_bitrate );
00913 MP4_GET1BYTE( i_type );
00914 if( i_type != 0x05 )
00915 {
00916 es_descriptor.p_decConfigDescr->i_decoder_specific_info_len = 0;
00917 es_descriptor.p_decConfigDescr->p_decoder_specific_info = NULL;
00918 MP4_READBOX_EXIT( 1 );
00919 }
00920
00921 i_len = MP4_ReadLengthDescriptor( &p_peek, &i_read );
00922
00923 #ifdef MP4_VERBOSE
00924 msg_Dbg( p_stream, "found esds MP4DecSpecificDescr (%dBytes)",
00925 i_len );
00926 #endif
00927
00928 es_descriptor.p_decConfigDescr->i_decoder_specific_info_len = i_len;
00929 es_descriptor.p_decConfigDescr->p_decoder_specific_info = malloc( i_len );
00930 memcpy( es_descriptor.p_decConfigDescr->p_decoder_specific_info,
00931 p_peek, i_len );
00932
00933 MP4_READBOX_EXIT( 1 );
00934
00935 #undef es_descriptor
00936 }
00937
00938 static void MP4_FreeBox_esds( MP4_Box_t *p_box )
00939 {
00940 FREE( p_box->data.p_esds->es_descriptor.psz_URL );
00941 if( p_box->data.p_esds->es_descriptor.p_decConfigDescr )
00942 {
00943 FREE( p_box->data.p_esds->es_descriptor.p_decConfigDescr->p_decoder_specific_info );
00944 }
00945 FREE( p_box->data.p_esds->es_descriptor.p_decConfigDescr );
00946 }
00947
00948 static int MP4_ReadBox_avcC( stream_t *p_stream, MP4_Box_t *p_box )
00949 {
00950 MP4_Box_data_avcC_t *p_avcC;
00951 int i;
00952
00953 MP4_READBOX_ENTER( MP4_Box_data_avcC_t );
00954 p_avcC = p_box->data.p_avcC;
00955
00956 p_avcC->i_avcC = i_read;
00957 p_avcC->p_avcC = malloc( p_avcC->i_avcC );
00958 memcpy( p_avcC->p_avcC, p_peek, i_read );
00959
00960 MP4_GET1BYTE( p_avcC->i_version );
00961 MP4_GET1BYTE( p_avcC->i_profile );
00962 MP4_GET1BYTE( p_avcC->i_profile_compatibility );
00963 MP4_GET1BYTE( p_avcC->i_level );
00964 MP4_GET1BYTE( p_avcC->i_reserved1 );
00965 p_avcC->i_length_size = (p_avcC->i_reserved1&0x03) + 1;
00966 p_avcC->i_reserved1 >>= 2;
00967
00968 MP4_GET1BYTE( p_avcC->i_reserved2 );
00969 p_avcC->i_sps = p_avcC->i_reserved2&0x1f;
00970 p_avcC->i_reserved2 >>= 5;
00971
00972 if( p_avcC->i_sps > 0 )
00973 {
00974 p_avcC->i_sps_length = malloc( p_avcC->i_sps * sizeof( uint16_t ) );
00975 p_avcC->sps = malloc( p_avcC->i_sps * sizeof( uint8_t* ) );
00976
00977 for( i = 0; i < p_avcC->i_sps; i++ )
00978 {
00979 MP4_GET2BYTES( p_avcC->i_sps_length[i] );
00980 p_avcC->sps[i] = malloc( p_avcC->i_sps_length[i] );
00981 memcpy( p_avcC->sps[i], p_peek, p_avcC->i_sps_length[i] );
00982
00983 p_peek += p_avcC->i_sps_length[i];
00984 i_read -= p_avcC->i_sps_length[i];
00985 }
00986 }
00987
00988 MP4_GET1BYTE( p_avcC->i_pps );
00989 if( p_avcC->i_pps > 0 )
00990 {
00991 p_avcC->i_pps_length = malloc( p_avcC->i_pps * sizeof( uint16_t ) );
00992 p_avcC->pps = malloc( p_avcC->i_pps * sizeof( uint8_t* ) );
00993
00994 for( i = 0; i < p_avcC->i_pps; i++ )
00995 {
00996 MP4_GET2BYTES( p_avcC->i_pps_length[i] );
00997 p_avcC->pps[i] = malloc( p_avcC->i_pps_length[i] );
00998 memcpy( p_avcC->pps[i], p_peek, p_avcC->i_pps_length[i] );
00999
01000 p_peek += p_avcC->i_pps_length[i];
01001 i_read -= p_avcC->i_pps_length[i];
01002 }
01003 }
01004 #ifdef MP4_VERBOSE
01005 msg_Dbg( p_stream,
01006 "read box: \"avcC\" version=%d profile=0x%x level=0x%x length size=%d sps=%d pps=%d",
01007 p_avcC->i_version, p_avcC->i_profile, p_avcC->i_level,
01008 p_avcC->i_length_size,
01009 p_avcC->i_sps, p_avcC->i_pps );
01010 for( i = 0; i < p_avcC->i_sps; i++ )
01011 {
01012 msg_Dbg( p_stream, " - sps[%d] length=%d",
01013 i, p_avcC->i_sps_length[i] );
01014 }
01015 for( i = 0; i < p_avcC->i_pps; i++ )
01016 {
01017 msg_Dbg( p_stream, " - pps[%d] length=%d",
01018 i, p_avcC->i_pps_length[i] );
01019 }
01020
01021 #endif
01022 MP4_READBOX_EXIT( 1 );
01023 }
01024
01025 static void MP4_FreeBox_avcC( MP4_Box_t *p_box )
01026 {
01027 MP4_Box_data_avcC_t *p_avcC = p_box->data.p_avcC;
01028 int i;
01029
01030 for( i = 0; i < p_avcC->i_sps; i++ )
01031 {
01032 FREE( p_avcC->sps[i] );
01033 }
01034 for( i = 0; i < p_avcC->i_pps; i++ )
01035 {
01036 FREE( p_avcC->pps[i] );
01037 }
01038 if( p_avcC->i_sps > 0 ) FREE( p_avcC->sps );
01039 if( p_avcC->i_pps > 0 ) FREE( p_avcC->pps );
01040 }
01041
01042 static int MP4_ReadBox_sample_soun( stream_t *p_stream, MP4_Box_t *p_box )
01043 {
01044 unsigned int i;
01045
01046 MP4_READBOX_ENTER( MP4_Box_data_sample_soun_t );
01047 p_box->data.p_sample_soun->p_qt_description = NULL;
01048
01049
01050
01051 if( i_read < 28 )
01052 {
01053 i_read -= 30;
01054 MP4_READBOX_EXIT( 1 );
01055 }
01056
01057 for( i = 0; i < 6 ; i++ )
01058 {
01059 MP4_GET1BYTE( p_box->data.p_sample_soun->i_reserved1[i] );
01060 }
01061
01062 MP4_GET2BYTES( p_box->data.p_sample_soun->i_data_reference_index );
01063
01064
01065
01066
01067 if( i_read > 0 )
01068 {
01069 p_box->data.p_sample_soun->i_qt_description = i_read;
01070 p_box->data.p_sample_soun->p_qt_description = malloc( i_read );
01071 memcpy( p_box->data.p_sample_soun->p_qt_description, p_peek, i_read );
01072 }
01073 else
01074 {
01075 p_box->data.p_sample_soun->i_qt_description = 0;
01076 p_box->data.p_sample_soun->p_qt_description = NULL;
01077 }
01078
01079 MP4_GET2BYTES( p_box->data.p_sample_soun->i_qt_version );
01080 MP4_GET2BYTES( p_box->data.p_sample_soun->i_qt_revision_level );
01081 MP4_GET4BYTES( p_box->data.p_sample_soun->i_qt_vendor );
01082
01083 MP4_GET2BYTES( p_box->data.p_sample_soun->i_channelcount );
01084 MP4_GET2BYTES( p_box->data.p_sample_soun->i_samplesize );
01085 MP4_GET2BYTES( p_box->data.p_sample_soun->i_predefined );
01086 MP4_GET2BYTES( p_box->data.p_sample_soun->i_reserved3 );
01087 MP4_GET2BYTES( p_box->data.p_sample_soun->i_sampleratehi );
01088 MP4_GET2BYTES( p_box->data.p_sample_soun->i_sampleratelo );
01089
01090 if( p_box->data.p_sample_soun->i_qt_version == 1 && i_read >= 16 )
01091 {
01092
01093 MP4_GET4BYTES( p_box->data.p_sample_soun->i_sample_per_packet );
01094 MP4_GET4BYTES( p_box->data.p_sample_soun->i_bytes_per_packet );
01095 MP4_GET4BYTES( p_box->data.p_sample_soun->i_bytes_per_frame );
01096 MP4_GET4BYTES( p_box->data.p_sample_soun->i_bytes_per_sample );
01097
01098 #ifdef MP4_VERBOSE
01099 msg_Dbg( p_stream,
01100 "read box: \"soun\" qt3+ sample/packet=%d bytes/packet=%d "
01101 "bytes/frame=%d bytes/sample=%d",
01102 p_box->data.p_sample_soun->i_sample_per_packet,
01103 p_box->data.p_sample_soun->i_bytes_per_packet,
01104 p_box->data.p_sample_soun->i_bytes_per_frame,
01105 p_box->data.p_sample_soun->i_bytes_per_sample );
01106 #endif
01107 stream_Seek( p_stream, p_box->i_pos +
01108 MP4_BOX_HEADERSIZE( p_box ) + 44 );
01109 }
01110 else if( p_box->data.p_sample_soun->i_qt_version == 2 && i_read >= 36 )
01111 {
01112
01113 double f_sample_rate;
01114 uint32_t i_channel;
01115
01116 MP4_GET4BYTES( p_box->data.p_sample_soun->i_sample_per_packet );
01117 MP4_GET8BYTES( (*(int64_t *)&f_sample_rate) );
01118
01119 msg_Dbg( p_stream, "read box: %f Hz", f_sample_rate );
01120 p_box->data.p_sample_soun->i_sampleratehi = (int)f_sample_rate % 65536;
01121 p_box->data.p_sample_soun->i_sampleratelo = f_sample_rate / 65536;
01122
01123 MP4_GET4BYTES( i_channel );
01124 p_box->data.p_sample_soun->i_channelcount = i_channel;
01125
01126 #ifdef MP4_VERBOSE
01127 msg_Dbg( p_stream, "read box: \"soun\" V2" );
01128 #endif
01129 stream_Seek( p_stream, p_box->i_pos +
01130 MP4_BOX_HEADERSIZE( p_box ) + 28 + 36 );
01131 }
01132 else
01133 {
01134 p_box->data.p_sample_soun->i_sample_per_packet = 0;
01135 p_box->data.p_sample_soun->i_bytes_per_packet = 0;
01136 p_box->data.p_sample_soun->i_bytes_per_frame = 0;
01137 p_box->data.p_sample_soun->i_bytes_per_sample = 0;
01138
01139 msg_Dbg( p_stream, "read box: \"soun\" mp4 or qt1/2 (rest="I64Fd")",
01140 i_read );
01141 stream_Seek( p_stream, p_box->i_pos +
01142 MP4_BOX_HEADERSIZE( p_box ) + 28 );
01143 }
01144
01145 if( p_box->i_type == FOURCC_drms )
01146 {
01147 p_box->data.p_sample_soun->p_drms =
01148 drms_alloc( p_stream->p_vlc->psz_homedir );
01149
01150 if( p_box->data.p_sample_soun->p_drms == NULL )
01151 {
01152 msg_Err( p_stream, "drms_alloc() failed" );
01153 }
01154 }
01155
01156 if( p_box->i_type == FOURCC_samr || p_box->i_type == FOURCC_sawb )
01157 {
01158
01159 p_box->data.p_sample_soun->i_channelcount = 1;
01160 }
01161
01162 if( p_box->i_type == FOURCC_alac )
01163 {
01164 if( p_box->data.p_sample_soun->p_qt_description )
01165 free( p_box->data.p_sample_soun->p_qt_description );
01166
01167 p_box->data.p_sample_soun->p_qt_description = malloc( i_read );
01168 p_box->data.p_sample_soun->i_qt_description = i_read;
01169 memcpy( p_box->data.p_sample_soun->p_qt_description, p_peek, i_read );
01170 }
01171 else
01172 {
01173 MP4_ReadBoxContainerRaw( p_stream, p_box );
01174 }
01175
01176 #ifdef MP4_VERBOSE
01177 msg_Dbg( p_stream, "read box: \"soun\" in stsd channel %d "
01178 "sample size %d sample rate %f",
01179 p_box->data.p_sample_soun->i_channelcount,
01180 p_box->data.p_sample_soun->i_samplesize,
01181 (float)p_box->data.p_sample_soun->i_sampleratehi +
01182 (float)p_box->data.p_sample_soun->i_sampleratelo / 65536 );
01183
01184 #endif
01185 MP4_READBOX_EXIT( 1 );
01186 }
01187
01188
01189 static void MP4_FreeBox_sample_soun( MP4_Box_t *p_box )
01190 {
01191 FREE( p_box->data.p_sample_soun->p_qt_description );
01192
01193 if( p_box->i_type == FOURCC_drms )
01194 {
01195 if( p_box->data.p_sample_soun->p_drms )
01196 {
01197 drms_free( p_box->data.p_sample_soun->p_drms );
01198 }
01199 }
01200 }
01201
01202
01203 int MP4_ReadBox_sample_vide( stream_t *p_stream, MP4_Box_t *p_box )
01204 {
01205 unsigned int i;
01206
01207 MP4_READBOX_ENTER( MP4_Box_data_sample_vide_t );
01208
01209 for( i = 0; i < 6 ; i++ )
01210 {
01211 MP4_GET1BYTE( p_box->data.p_sample_vide->i_reserved1[i] );
01212 }
01213
01214 MP4_GET2BYTES( p_box->data.p_sample_vide->i_data_reference_index );
01215
01216
01217
01218
01219 if( i_read > 0 )
01220 {
01221 p_box->data.p_sample_vide->i_qt_image_description = i_read;
01222 p_box->data.p_sample_vide->p_qt_image_description = malloc( i_read );
01223 memcpy( p_box->data.p_sample_vide->p_qt_image_description,
01224 p_peek, i_read );
01225 }
01226 else
01227 {
01228 p_box->data.p_sample_vide->i_qt_image_description = 0;
01229 p_box->data.p_sample_vide->p_qt_image_description = NULL;
01230 }
01231
01232 MP4_GET2BYTES( p_box->data.p_sample_vide->i_qt_version );
01233 MP4_GET2BYTES( p_box->data.p_sample_vide->i_qt_revision_level );
01234 MP4_GET4BYTES( p_box->data.p_sample_vide->i_qt_vendor );
01235
01236 MP4_GET4BYTES( p_box->data.p_sample_vide->i_qt_temporal_quality );
01237 MP4_GET4BYTES( p_box->data.p_sample_vide->i_qt_spatial_quality );
01238
01239 MP4_GET2BYTES( p_box->data.p_sample_vide->i_width );
01240 MP4_GET2BYTES( p_box->data.p_sample_vide->i_height );
01241
01242 MP4_GET4BYTES( p_box->data.p_sample_vide->i_horizresolution );
01243 MP4_GET4BYTES( p_box->data.p_sample_vide->i_vertresolution );
01244
01245 MP4_GET4BYTES( p_box->data.p_sample_vide->i_qt_data_size );
01246 MP4_GET2BYTES( p_box->data.p_sample_vide->i_qt_frame_count );
01247
01248 memcpy( &p_box->data.p_sample_vide->i_compressorname, p_peek, 32 );
01249 p_peek += 32; i_read -= 32;
01250
01251 MP4_GET2BYTES( p_box->data.p_sample_vide->i_depth );
01252 MP4_GET2BYTES( p_box->data.p_sample_vide->i_qt_color_table );
01253
01254 stream_Seek( p_stream, p_box->i_pos + MP4_BOX_HEADERSIZE( p_box ) + 78);
01255 MP4_ReadBoxContainerRaw( p_stream, p_box );
01256
01257 #ifdef MP4_VERBOSE
01258 msg_Dbg( p_stream, "read box: \"vide\" in stsd %dx%d depth %d",
01259 p_box->data.p_sample_vide->i_width,
01260 p_box->data.p_sample_vide->i_height,
01261 p_box->data.p_sample_vide->i_depth );
01262
01263 #endif
01264 MP4_READBOX_EXIT( 1 );
01265 }
01266
01267
01268 void MP4_FreeBox_sample_vide( MP4_Box_t *p_box )
01269 {
01270 FREE( p_box->data.p_sample_vide->p_qt_image_description );
01271 }
01272
01273 static int MP4_ReadBox_sample_mp4s( stream_t *p_stream, MP4_Box_t *p_box )
01274 {
01275 stream_Seek( p_stream, p_box->i_pos + MP4_BOX_HEADERSIZE( p_box ) + 8 );
01276 MP4_ReadBoxContainerRaw( p_stream, p_box );
01277 return 1;
01278 }
01279
01280 static int MP4_ReadBox_sample_text( stream_t *p_stream, MP4_Box_t *p_box )
01281 {
01282 unsigned int i;
01283 int32_t t;
01284
01285 MP4_READBOX_ENTER( MP4_Box_data_sample_text_t );
01286
01287 MP4_GET4BYTES( p_box->data.p_sample_text->i_reserved1 );
01288 MP4_GET2BYTES( p_box->data.p_sample_text->i_reserved2 );
01289
01290 MP4_GET2BYTES( p_box->data.p_sample_text->i_data_reference_index );
01291
01292 MP4_GET4BYTES( p_box->data.p_sample_text->i_display_flags );
01293
01294 MP4_GET4BYTES( t );
01295 switch( t )
01296 {
01297
01298 case 1:
01299 p_box->data.p_sample_text->i_justification_horizontal = 1;
01300 p_box->data.p_sample_text->i_justification_vertical = 1;
01301 break;
01302 case -1:
01303 p_box->data.p_sample_text->i_justification_horizontal = -1;
01304 p_box->data.p_sample_text->i_justification_vertical = -1;
01305 break;
01306 case -2:
01307 p_box->data.p_sample_text->i_justification_horizontal = 0;
01308 p_box->data.p_sample_text->i_justification_vertical = 0;
01309 break;
01310 case 0:
01311 default:
01312 p_box->data.p_sample_text->i_justification_horizontal = 1;
01313 p_box->data.p_sample_text->i_justification_vertical = -1;
01314 break;
01315 }
01316
01317 MP4_GET2BYTES( p_box->data.p_sample_text->i_background_color[0] );
01318 MP4_GET2BYTES( p_box->data.p_sample_text->i_background_color[1] );
01319 MP4_GET2BYTES( p_box->data.p_sample_text->i_background_color[2] );
01320 p_box->data.p_sample_text->i_background_color[3] = 0;
01321
01322 MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_top );
01323 MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_left );
01324 MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_bottom );
01325 MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_right );
01326
01327 #ifdef MP4_VERBOSE
01328 msg_Dbg( p_stream, "read box: \"text\" in stsd text" );
01329 #endif
01330 MP4_READBOX_EXIT( 1 );
01331 }
01332
01333 static int MP4_ReadBox_sample_tx3g( stream_t *p_stream, MP4_Box_t *p_box )
01334 {
01335 unsigned int i;
01336 int32_t t;
01337
01338 MP4_READBOX_ENTER( MP4_Box_data_sample_text_t );
01339
01340 MP4_GET4BYTES( p_box->data.p_sample_text->i_reserved1 );
01341 MP4_GET2BYTES( p_box->data.p_sample_text->i_reserved2 );
01342
01343 MP4_GET2BYTES( p_box->data.p_sample_text->i_data_reference_index );
01344
01345 MP4_GET4BYTES( p_box->data.p_sample_text->i_display_flags );
01346
01347 MP4_GET1BYTE ( p_box->data.p_sample_text->i_justification_horizontal );
01348 MP4_GET1BYTE ( p_box->data.p_sample_text->i_justification_vertical );
01349
01350 MP4_GET1BYTE ( p_box->data.p_sample_text->i_background_color[0] );
01351 MP4_GET1BYTE ( p_box->data.p_sample_text->i_background_color[1] );
01352 MP4_GET1BYTE ( p_box->data.p_sample_text->i_background_color[2] );
01353 MP4_GET1BYTE ( p_box->data.p_sample_text->i_background_color[3] );
01354
01355 MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_top );
01356 MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_left );
01357 MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_bottom );
01358 MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_right );
01359
01360 #ifdef MP4_VERBOSE
01361 msg_Dbg( p_stream, "read box: \"text\" in stsd text" );
01362 #endif
01363 MP4_READBOX_EXIT( 1 );
01364 }
01365
01366
01367 #if 0
01368
01369 static void MP4_FreeBox_sample_text( MP4_Box_t *p_box )
01370 {
01371 FREE( p_box->data.p_sample_text->psz_text_name );
01372 }
01373 #endif
01374
01375
01376 static int MP4_ReadBox_stsd( stream_t *p_stream, MP4_Box_t *p_box )
01377 {
01378
01379 MP4_READBOX_ENTER( MP4_Box_data_stsd_t );
01380
01381 MP4_GETVERSIONFLAGS( p_box->data.p_stsd );
01382
01383 MP4_GET4BYTES( p_box->data.p_stsd->i_entry_count );
01384
01385 stream_Seek( p_stream, p_box->i_pos + MP4_BOX_HEADERSIZE( p_box ) + 8 );
01386
01387 MP4_ReadBoxContainerRaw( p_stream, p_box );
01388
01389 #ifdef MP4_VERBOSE
01390 msg_Dbg( p_stream, "read box: \"stsd\" entry-count %d",
01391 p_box->data.p_stsd->i_entry_count );
01392
01393 #endif
01394 MP4_READBOX_EXIT( 1 );
01395 }
01396
01397
01398 static int MP4_ReadBox_stsz( stream_t *p_stream, MP4_Box_t *p_box )
01399 {
01400 unsigned int i;
01401
01402 MP4_READBOX_ENTER( MP4_Box_data_stsz_t );
01403
01404 MP4_GETVERSIONFLAGS( p_box->data.p_stsz );
01405
01406 MP4_GET4BYTES( p_box->data.p_stsz->i_sample_size );
01407
01408 MP4_GET4BYTES( p_box->data.p_stsz->i_sample_count );
01409
01410 p_box->data.p_stsz->i_entry_size =
01411 calloc( sizeof( uint32_t ), p_box->data.p_stsz->i_sample_count );
01412
01413 if( !p_box->data.p_stsz->i_sample_size )
01414 {
01415 for( i=0; (i<p_box->data.p_stsz->i_sample_count)&&(i_read >= 4 ); i++ )
01416 {
01417 MP4_GET4BYTES( p_box->data.p_stsz->i_entry_size[i] );
01418 }
01419 }
01420
01421 #ifdef MP4_VERBOSE
01422 msg_Dbg( p_stream, "read box: \"stsz\" sample-size %d sample-count %d",
01423 p_box->data.p_stsz->i_sample_size,
01424 p_box->data.p_stsz->i_sample_count );
01425
01426 #endif
01427 MP4_READBOX_EXIT( 1 );
01428 }
01429
01430 static void MP4_FreeBox_stsz( MP4_Box_t *p_box )
01431 {
01432 FREE( p_box->data.p_stsz->i_entry_size );
01433 }
01434
01435 static int MP4_ReadBox_stsc( stream_t *p_stream, MP4_Box_t *p_box )
01436 {
01437 unsigned int i;
01438
01439 MP4_READBOX_ENTER( MP4_Box_data_stsc_t );
01440
01441 MP4_GETVERSIONFLAGS( p_box->data.p_stsc );
01442
01443 MP4_GET4BYTES( p_box->data.p_stsc->i_entry_count );
01444
01445 p_box->data.p_stsc->i_first_chunk =
01446 calloc( sizeof( uint32_t ), p_box->data.p_stsc->i_entry_count );
01447 p_box->data.p_stsc->i_samples_per_chunk =
01448 calloc( sizeof( uint32_t ), p_box->data.p_stsc->i_entry_count );
01449 p_box->data.p_stsc->i_sample_description_index =
01450 calloc( sizeof( uint32_t ), p_box->data.p_stsc->i_entry_count );
01451
01452 for( i = 0; (i < p_box->data.p_stsc->i_entry_count )&&( i_read >= 12 );i++ )
01453 {
01454 MP4_GET4BYTES( p_box->data.p_stsc->i_first_chunk[i] );
01455 MP4_GET4BYTES( p_box->data.p_stsc->i_samples_per_chunk[i] );
01456 MP4_GET4BYTES( p_box->data.p_stsc->i_sample_description_index[i] );
01457 }
01458
01459 #ifdef MP4_VERBOSE
01460 msg_Dbg( p_stream, "read box: \"stsc\" entry-count %d",
01461 p_box->data.p_stsc->i_entry_count );
01462
01463 #endif
01464 MP4_READBOX_EXIT( 1 );
01465 }
01466
01467 static void MP4_FreeBox_stsc( MP4_Box_t *p_box )
01468 {
01469 FREE( p_box->data.p_stsc->i_first_chunk );
01470 FREE( p_box->data.p_stsc->i_samples_per_chunk );
01471 FREE( p_box->data.p_stsc->i_sample_description_index );
01472 }
01473
01474 static int MP4_ReadBox_stco_co64( stream_t *p_stream, MP4_Box_t *p_box )
01475 {
01476 unsigned int i;
01477
01478 MP4_READBOX_ENTER( MP4_Box_data_co64_t );
01479
01480 MP4_GETVERSIONFLAGS( p_box->data.p_co64 );
01481
01482 MP4_GET4BYTES( p_box->data.p_co64->i_entry_count );
01483
01484 p_box->data.p_co64->i_chunk_offset =
01485 calloc( sizeof( uint64_t ), p_box->data.p_co64->i_entry_count );
01486
01487 for( i = 0; i < p_box->data.p_co64->i_entry_count; i++ )
01488 {
01489 if( p_box->i_type == FOURCC_stco )
01490 {
01491 if( i_read < 4 )
01492 {
01493 break;
01494 }
01495 MP4_GET4BYTES( p_box->data.p_co64->i_chunk_offset[i] );
01496 }
01497 else
01498 {
01499 if( i_read < 8 )
01500 {
01501 break;
01502 }
01503 MP4_GET8BYTES( p_box->data.p_co64->i_chunk_offset[i] );
01504 }
01505 }
01506
01507 #ifdef MP4_VERBOSE
01508 msg_Dbg( p_stream, "read box: \"co64\" entry-count %d",
01509 p_box->data.p_co64->i_entry_count );
01510
01511 #endif
01512 MP4_READBOX_EXIT( 1 );
01513 }
01514
01515 static void MP4_FreeBox_stco_co64( MP4_Box_t *p_box )
01516 {
01517 FREE( p_box->data.p_co64->i_chunk_offset );
01518 }
01519
01520 static int MP4_ReadBox_stss( stream_t *p_stream, MP4_Box_t *p_box )
01521 {
01522 unsigned int i;
01523
01524 MP4_READBOX_ENTER( MP4_Box_data_stss_t );
01525
01526 MP4_GETVERSIONFLAGS( p_box->data.p_stss );
01527
01528 MP4_GET4BYTES( p_box->data.p_stss->i_entry_count );
01529
01530 p_box->data.p_stss->i_sample_number =
01531 calloc( sizeof( uint32_t ), p_box->data.p_stss->i_entry_count );
01532
01533 for( i = 0; (i < p_box->data.p_stss->i_entry_count )&&( i_read >= 4 ); i++ )
01534 {
01535
01536 MP4_GET4BYTES( p_box->data.p_stss->i_sample_number[i] );
01537
01538 p_box->data.p_stss->i_sample_number[i]--;
01539 }
01540
01541 #ifdef MP4_VERBOSE
01542 msg_Dbg( p_stream, "read box: \"stss\" entry-count %d",
01543 p_box->data.p_stss->i_entry_count );
01544
01545 #endif
01546 MP4_READBOX_EXIT( 1 );
01547 }
01548
01549 static void MP4_FreeBox_stss( MP4_Box_t *p_box )
01550 {
01551 FREE( p_box->data.p_stss->i_sample_number )
01552 }
01553
01554 static int MP4_ReadBox_stsh( stream_t *p_stream, MP4_Box_t *p_box )
01555 {
01556 unsigned int i;
01557
01558 MP4_READBOX_ENTER( MP4_Box_data_stsh_t );
01559
01560 MP4_GETVERSIONFLAGS( p_box->data.p_stsh );
01561
01562
01563 MP4_GET4BYTES( p_box->data.p_stsh->i_entry_count );
01564
01565 p_box->data.p_stsh->i_shadowed_sample_number =
01566 calloc( sizeof( uint32_t ), p_box->data.p_stsh->i_entry_count );
01567
01568 p_box->data.p_stsh->i_sync_sample_number =
01569 calloc( sizeof( uint32_t ), p_box->data.p_stsh->i_entry_count );
01570
01571
01572 for( i = 0; (i < p_box->data.p_stss->i_entry_count )&&( i_read >= 8 ); i++ )
01573 {
01574
01575 MP4_GET4BYTES( p_box->data.p_stsh->i_shadowed_sample_number[i] );
01576 MP4_GET4BYTES( p_box->data.p_stsh->i_sync_sample_number[i] );
01577 }
01578
01579 #ifdef MP4_VERBOSE
01580 msg_Dbg( p_stream, "read box: \"stsh\" entry-count %d",
01581 p_box->data.p_stsh->i_entry_count );
01582 #endif
01583 MP4_READBOX_EXIT( 1 );
01584 }
01585
01586 static void MP4_FreeBox_stsh( MP4_Box_t *p_box )
01587 {
01588 FREE( p_box->data.p_stsh->i_shadowed_sample_number )
01589 FREE( p_box->data.p_stsh->i_sync_sample_number )
01590 }
01591
01592
01593 static int MP4_ReadBox_stdp( stream_t *p_stream, MP4_Box_t *p_box )
01594 {
01595 unsigned int i;
01596
01597 MP4_READBOX_ENTER( MP4_Box_data_stdp_t );
01598
01599 MP4_GETVERSIONFLAGS( p_box->data.p_stdp );
01600
01601 p_box->data.p_stdp->i_priority =
01602 calloc( sizeof( uint16_t ), i_read / 2 );
01603
01604 for( i = 0; i < i_read / 2 ; i++ )
01605 {
01606
01607 MP4_GET2BYTES( p_box->data.p_stdp->i_priority[i] );
01608 }
01609
01610 #ifdef MP4_VERBOSE
01611 msg_Dbg( p_stream, "read box: \"stdp\" entry-count "I64Fd,
01612 i_read / 2 );
01613
01614 #endif
01615 MP4_READBOX_EXIT( 1 );
01616 }
01617
01618 static void MP4_FreeBox_stdp( MP4_Box_t *p_box )
01619 {
01620 FREE( p_box->data.p_stdp->i_priority )
01621 }
01622
01623 static int MP4_ReadBox_padb( stream_t *p_stream, MP4_Box_t *p_box )
01624 {
01625 unsigned int i;
01626
01627 MP4_READBOX_ENTER( MP4_Box_data_padb_t );
01628
01629 MP4_GETVERSIONFLAGS( p_box->data.p_padb );
01630
01631
01632 MP4_GET4BYTES( p_box->data.p_padb->i_sample_count );
01633
01634 p_box->data.p_padb->i_reserved1 =
01635 calloc( sizeof( uint16_t ), ( p_box->data.p_padb->i_sample_count + 1 ) / 2 );
01636 p_box->data.p_padb->i_pad2 =
01637 calloc( sizeof( uint16_t ), ( p_box->data.p_padb->i_sample_count + 1 ) / 2 );
01638 p_box->data.p_padb->i_reserved2 =
01639 calloc( sizeof( uint16_t ), ( p_box->data.p_padb->i_sample_count + 1 ) / 2 );
01640 p_box->data.p_padb->i_pad1 =
01641 calloc( sizeof( uint16_t ), ( p_box->data.p_padb->i_sample_count + 1 ) / 2 );
01642
01643
01644 for( i = 0; i < i_read / 2 ; i++ )
01645 {
01646 p_box->data.p_padb->i_reserved1[i] = ( (*p_peek) >> 7 )&0x01;
01647 p_box->data.p_padb->i_pad2[i] = ( (*p_peek) >> 4 )&0x07;
01648 p_box->data.p_padb->i_reserved1[i] = ( (*p_peek) >> 3 )&0x01;
01649 p_box->data.p_padb->i_pad1[i] = ( (*p_peek) )&0x07;
01650
01651 p_peek += 1; i_read -= 1;
01652 }
01653
01654 #ifdef MP4_VERBOSE
01655 msg_Dbg( p_stream, "read box: \"stdp\" entry-count "I64Fd,
01656 i_read / 2 );
01657
01658 #endif
01659 MP4_READBOX_EXIT( 1 );
01660 }
01661
01662 static void MP4_FreeBox_padb( MP4_Box_t *p_box )
01663 {
01664 FREE( p_box->data.p_padb->i_reserved1 );
01665 FREE( p_box->data.p_padb->i_pad2 );
01666 FREE( p_box->data.p_padb->i_reserved2 );
01667 FREE( p_box->data.p_padb->i_pad1 );
01668 }
01669
01670 static int MP4_ReadBox_elst( stream_t *p_stream, MP4_Box_t *p_box )
01671 {
01672 unsigned int i;
01673
01674 MP4_READBOX_ENTER( MP4_Box_data_padb_t );
01675
01676 MP4_GETVERSIONFLAGS( p_box->data.p_elst );
01677
01678
01679 MP4_GET4BYTES( p_box->data.p_elst->i_entry_count );
01680
01681 p_box->data.p_elst->i_segment_duration =
01682 calloc( sizeof( uint64_t ), p_box->data.p_elst->i_entry_count );
01683 p_box->data.p_elst->i_media_time =
01684 calloc( sizeof( int64_t ), p_box->data.p_elst->i_entry_count );
01685 p_box->data.p_elst->i_media_rate_integer =
01686 calloc( sizeof( uint16_t ), p_box->data.p_elst->i_entry_count );
01687 p_box->data.p_elst->i_media_rate_fraction=
01688 calloc( sizeof( uint16_t ), p_box->data.p_elst->i_entry_count );
01689
01690
01691 for( i = 0; i < p_box->data.p_elst->i_entry_count; i++ )
01692 {
01693 if( p_box->data.p_elst->i_version == 1 )
01694 {
01695
01696 MP4_GET8BYTES( p_box->data.p_elst->i_segment_duration[i] );
01697
01698 MP4_GET8BYTES( p_box->data.p_elst->i_media_time[i] );
01699 }
01700 else
01701 {
01702
01703 MP4_GET4BYTES( p_box->data.p_elst->i_segment_duration[i] );
01704
01705 MP4_GET4BYTES( p_box->data.p_elst->i_media_time[i] );
01706 p_box->data.p_elst->i_media_time[i] = (int32_t)p_box->data.p_elst->i_media_time[i];
01707 }
01708
01709 MP4_GET2BYTES( p_box->data.p_elst->i_media_rate_integer[i] );
01710 MP4_GET2BYTES( p_box->data.p_elst->i_media_rate_fraction[i] );
01711 }
01712
01713 #ifdef MP4_VERBOSE
01714 msg_Dbg( p_stream, "read box: \"elst\" entry-count "I64Fd,
01715 i_read / 2 );
01716
01717 #endif
01718 MP4_READBOX_EXIT( 1 );
01719 }
01720
01721 static void MP4_FreeBox_elst( MP4_Box_t *p_box )
01722 {
01723 FREE( p_box->data.p_elst->i_segment_duration );
01724 FREE( p_box->data.p_elst->i_media_time );
01725 FREE( p_box->data.p_elst->i_media_rate_integer );
01726 FREE( p_box->data.p_elst->i_media_rate_fraction );
01727 }
01728
01729 static int MP4_ReadBox_cprt( stream_t *p_stream, MP4_Box_t *p_box )
01730 {
01731 unsigned int i_language;
01732 unsigned int i;
01733
01734 MP4_READBOX_ENTER( MP4_Box_data_cprt_t );
01735
01736 MP4_GETVERSIONFLAGS( p_box->data.p_cprt );
01737
01738 i_language = GetWBE( p_peek );
01739 for( i = 0; i < 3; i++ )
01740 {
01741 p_box->data.p_cprt->i_language[i] =
01742 ( ( i_language >> ( (2-i)*5 ) )&0x1f ) + 0x60;
01743 }
01744 p_peek += 2; i_read -= 2;
01745 MP4_GETSTRINGZ( p_box->data.p_cprt->psz_notice );
01746
01747 #ifdef MP4_VERBOSE
01748 msg_Dbg( p_stream, "read box: \"cprt\" language %c%c%c notice %s",
01749 p_box->data.p_cprt->i_language[0],
01750 p_box->data.p_cprt->i_language[1],
01751 p_box->data.p_cprt->i_language[2],
01752 p_box->data.p_cprt->psz_notice );
01753
01754 #endif
01755 MP4_READBOX_EXIT( 1 );
01756 }
01757
01758 static void MP4_FreeBox_cprt( MP4_Box_t *p_box )
01759 {
01760 FREE( p_box->data.p_cprt->psz_notice );
01761 }
01762
01763
01764 static int MP4_ReadBox_dcom( stream_t *p_stream, MP4_Box_t *p_box )
01765 {
01766 MP4_READBOX_ENTER( MP4_Box_data_dcom_t );
01767
01768 MP4_GETFOURCC( p_box->data.p_dcom->i_algorithm );
01769 #ifdef MP4_VERBOSE
01770 msg_Dbg( p_stream,
01771 "read box: \"dcom\" compression algorithm : %4.4s",
01772 (char*)&p_box->data.p_dcom->i_algorithm );
01773 #endif
01774 MP4_READBOX_EXIT( 1 );
01775 }
01776
01777 static int MP4_ReadBox_cmvd( stream_t *p_stream, MP4_Box_t *p_box )
01778 {
01779 MP4_READBOX_ENTER( MP4_Box_data_cmvd_t );
01780
01781 MP4_GET4BYTES( p_box->data.p_cmvd->i_uncompressed_size );
01782
01783 p_box->data.p_cmvd->i_compressed_size = i_read;
01784
01785 if( !( p_box->data.p_cmvd->p_data = malloc( i_read ) ) )
01786 {
01787 msg_Dbg( p_stream, "read box: \"cmvd\" not enough memory to load data" );
01788 return( 1 );
01789 }
01790
01791
01792 memcpy( p_box->data.p_cmvd->p_data,
01793 p_peek,
01794 i_read);
01795
01796 p_box->data.p_cmvd->b_compressed = 1;
01797
01798 #ifdef MP4_VERBOSE
01799 msg_Dbg( p_stream, "read box: \"cmvd\" compressed data size %d",
01800 p_box->data.p_cmvd->i_compressed_size );
01801 #endif
01802
01803 MP4_READBOX_EXIT( 1 );
01804 }
01805 static void MP4_FreeBox_cmvd( MP4_Box_t *p_box )
01806 {
01807 FREE( p_box->data.p_cmvd->p_data );
01808 }
01809
01810
01811 static int MP4_ReadBox_cmov( stream_t *p_stream, MP4_Box_t *p_box )
01812 {
01813 MP4_Box_t *p_dcom;
01814 MP4_Box_t *p_cmvd;
01815
01816 #ifdef HAVE_ZLIB_H
01817 stream_t *p_stream_memory;
01818 z_stream z_data;
01819 uint8_t *p_data;
01820 int i_result;
01821 #endif
01822
01823 if( !( p_box->data.p_cmov = malloc( sizeof( MP4_Box_data_cmov_t ) ) ) )
01824 {
01825 msg_Err( p_stream, "out of memory" );
01826 return 0;
01827 }
01828 memset( p_box->data.p_cmov, 0, sizeof( MP4_Box_data_cmov_t ) );
01829
01830 if( !p_box->p_father ||
01831 ( p_box->p_father->i_type != FOURCC_moov &&
01832 p_box->p_father->i_type != FOURCC_foov ) )
01833 {
01834 msg_Warn( p_stream, "Read box: \"cmov\" box alone" );
01835 return 1;
01836 }
01837
01838 if( !MP4_ReadBoxContainer( p_stream, p_box ) )
01839 {
01840 return 0;
01841 }
01842
01843 if( ( p_dcom = MP4_BoxGet( p_box, "dcom" ) ) == NULL ||
01844 ( p_cmvd = MP4_BoxGet( p_box, "cmvd" ) ) == NULL ||
01845 p_cmvd->data.p_cmvd->p_data == NULL )
01846 {
01847 msg_Warn( p_stream, "read box: \"cmov\" incomplete" );
01848 return 1;
01849 }
01850
01851 if( p_dcom->data.p_dcom->i_algorithm != FOURCC_zlib )
01852 {
01853 msg_Dbg( p_stream, "read box: \"cmov\" compression algorithm : %4.4s "
01854 "not supported", (char*)&p_dcom->data.p_dcom->i_algorithm );
01855 return 1;
01856 }
01857
01858 #ifndef HAVE_ZLIB_H
01859 msg_Dbg( p_stream, "read box: \"cmov\" zlib unsupported" );
01860 return 1;
01861
01862 #else
01863
01864
01865 if( !( p_data = malloc( p_cmvd->data.p_cmvd->i_uncompressed_size ) ) )
01866 {
01867 msg_Err( p_stream, "read box: \"cmov\" not enough memory to "
01868 "uncompress data" );
01869 return 1;
01870 }
01871
01872 z_data.next_in = p_cmvd->data.p_cmvd->p_data;
01873 z_data.avail_in = p_cmvd->data.p_cmvd->i_compressed_size;
01874 z_data.next_out = p_data;
01875 z_data.avail_out = p_cmvd->data.p_cmvd->i_uncompressed_size;
01876 z_data.zalloc = (alloc_func)Z_NULL;
01877 z_data.zfree = (free_func)Z_NULL;
01878 z_data.opaque = (voidpf)Z_NULL;
01879
01880
01881 if( inflateInit( &z_data ) != Z_OK )
01882 {
01883 msg_Err( p_stream, "read box: \"cmov\" error while uncompressing" );
01884 free( p_data );
01885 return 1;
01886 }
01887
01888
01889 i_result = inflate( &z_data, Z_NO_FLUSH );
01890 if( i_result != Z_OK && i_result != Z_STREAM_END )
01891 {
01892 msg_Err( p_stream, "read box: \"cmov\" error while uncompressing" );
01893 free( p_data );
01894 return 1;
01895 }
01896
01897 if( p_cmvd->data.p_cmvd->i_uncompressed_size != z_data.total_out )
01898 {
01899 msg_Warn( p_stream, "read box: \"cmov\" uncompressing data size "
01900 "mismatch" );
01901 }
01902 p_cmvd->data.p_cmvd->i_uncompressed_size = z_data.total_out;
01903
01904
01905 if( inflateEnd( &z_data ) != Z_OK )
01906 {
01907 msg_Warn( p_stream, "read box: \"cmov\" error while uncompressing "
01908 "data (ignored)" );
01909 }
01910
01911 free( p_cmvd->data.p_cmvd->p_data );
01912 p_cmvd->data.p_cmvd->p_data = p_data;
01913 p_cmvd->data.p_cmvd->b_compressed = 0;
01914
01915 msg_Dbg( p_stream, "read box: \"cmov\" box succesfully uncompressed" );
01916
01917
01918 p_stream_memory =
01919 stream_MemoryNew( VLC_OBJECT(p_stream), p_cmvd->data.p_cmvd->p_data,
01920 p_cmvd->data.p_cmvd->i_uncompressed_size, VLC_TRUE );
01921
01922
01923 p_box->data.p_cmov->p_moov = MP4_ReadBox( p_stream_memory, NULL );
01924
01925 stream_Delete( p_stream_memory );
01926
01927 #ifdef MP4_VERBOSE
01928 msg_Dbg( p_stream, "read box: \"cmov\" compressed movie header completed");
01929 #endif
01930
01931 return p_box->data.p_cmov->p_moov ? 1 : 0;
01932 #endif
01933 }
01934
01935 static int MP4_ReadBox_rdrf( stream_t *p_stream, MP4_Box_t *p_box )
01936 {
01937 uint32_t i_len;
01938 MP4_READBOX_ENTER( MP4_Box_data_rdrf_t );
01939
01940 MP4_GETVERSIONFLAGS( p_box->data.p_rdrf );
01941 MP4_GETFOURCC( p_box->data.p_rdrf->i_ref_type );
01942 MP4_GET4BYTES( i_len );
01943 if( i_len > 0 )
01944 {
01945 uint32_t i;
01946 p_box->data.p_rdrf->psz_ref = malloc( i_len + 1);
01947 for( i = 0; i < i_len; i++ )
01948 {
01949 MP4_GET1BYTE( p_box->data.p_rdrf->psz_ref[i] );
01950 }
01951 p_box->data.p_rdrf->psz_ref[i_len] = '\0';
01952 }
01953 else
01954 {
01955 p_box->data.p_rdrf->psz_ref = NULL;
01956 }
01957
01958 #ifdef MP4_VERBOSE
01959 msg_Dbg( p_stream,
01960 "read box: \"rdrf\" type:%4.4s ref %s",
01961 (char*)&p_box->data.p_rdrf->i_ref_type,
01962 p_box->data.p_rdrf->psz_ref );
01963
01964 #endif
01965 MP4_READBOX_EXIT( 1 );
01966 }
01967
01968 static void MP4_FreeBox_rdrf( MP4_Box_t *p_box )
01969 {
01970 FREE( p_box->data.p_rdrf->psz_ref )
01971 }
01972
01973
01974 static int MP4_ReadBox_rmdr( stream_t *p_stream, MP4_Box_t *p_box )
01975 {
01976 MP4_READBOX_ENTER( MP4_Box_data_rmdr_t );
01977
01978 MP4_GETVERSIONFLAGS( p_box->data.p_rmdr );
01979
01980 MP4_GET4BYTES( p_box->data.p_rmdr->i_rate );
01981
01982 #ifdef MP4_VERBOSE
01983 msg_Dbg( p_stream,
01984 "read box: \"rmdr\" rate:%d",
01985 p_box->data.p_rmdr->i_rate );
01986 #endif
01987 MP4_READBOX_EXIT( 1 );
01988 }
01989
01990 static int MP4_ReadBox_rmqu( stream_t *p_stream, MP4_Box_t *p_box )
01991 {
01992 MP4_READBOX_ENTER( MP4_Box_data_rmqu_t );
01993
01994 MP4_GET4BYTES( p_box->data.p_rmqu->i_quality );
01995
01996 #ifdef MP4_VERBOSE
01997 msg_Dbg( p_stream,
01998 "read box: \"rmqu\" quality:%d",
01999 p_box->data.p_rmqu->i_quality );
02000 #endif
02001 MP4_READBOX_EXIT( 1 );
02002 }
02003
02004 static int MP4_ReadBox_rmvc( stream_t *p_stream, MP4_Box_t *p_box )
02005 {
02006 MP4_READBOX_ENTER( MP4_Box_data_rmvc_t );
02007 MP4_GETVERSIONFLAGS( p_box->data.p_rmvc );
02008
02009 MP4_GETFOURCC( p_box->data.p_rmvc->i_gestaltType );
02010 MP4_GET4BYTES( p_box->data.p_rmvc->i_val1 );
02011 MP4_GET4BYTES( p_box->data.p_rmvc->i_val2 );
02012 MP4_GET2BYTES( p_box->data.p_rmvc->i_checkType );
02013
02014 #ifdef MP4_VERBOSE
02015 msg_Dbg( p_stream,
02016 "read box: \"rmvc\" gestaltType:%4.4s val1:0x%x val2:0x%x checkType:0x%x",
02017 (char*)&p_box->data.p_rmvc->i_gestaltType,
02018 p_box->data.p_rmvc->i_val1,p_box->data.p_rmvc->i_val2,
02019 p_box->data.p_rmvc->i_checkType );
02020 #endif
02021
02022 MP4_READBOX_EXIT( 1 );
02023 }
02024
02025 static int MP4_ReadBox_drms( stream_t *p_stream, MP4_Box_t *p_box )
02026 {
02027 MP4_Box_t *p_drms_box = p_box;
02028
02029 MP4_READBOX_ENTER( uint8_t );
02030
02031 do
02032 {
02033 p_drms_box = p_drms_box->p_father;
02034 } while( p_drms_box && p_drms_box->i_type != FOURCC_drms );
02035
02036 if( p_drms_box && p_drms_box->data.p_sample_soun->p_drms )
02037 {
02038 if( drms_init( p_drms_box->data.p_sample_soun->p_drms,
02039 p_box->i_type, p_peek, i_read ) )
02040 {
02041 msg_Err( p_stream, "drms_init( %4.4s ) failed",
02042 (char *)&p_box->i_type );
02043
02044 drms_free( p_drms_box->data.p_sample_soun->p_drms );
02045 p_drms_box->data.p_sample_soun->p_drms = NULL;
02046 }
02047 }
02048
02049 MP4_READBOX_EXIT( 1 );
02050 }
02051
02052 static int MP4_ReadBox_0xa9xxx( stream_t *p_stream, MP4_Box_t *p_box )
02053 {
02054 int16_t i_length, i_dummy;
02055
02056 MP4_READBOX_ENTER( MP4_Box_data_0xa9xxx_t );
02057
02058 p_box->data.p_0xa9xxx->psz_text = NULL;
02059
02060 MP4_GET2BYTES( i_length );
02061 MP4_GET2BYTES( i_dummy );
02062
02063 if( i_length > 0 )
02064 {
02065 if( i_length > i_read ) i_length = i_read;
02066
02067 p_box->data.p_0xa9xxx->psz_text = malloc( i_length + 1 );
02068
02069 memcpy( p_box->data.p_0xa9xxx->psz_text,
02070 p_peek, i_length );
02071 p_box->data.p_0xa9xxx->psz_text[i_length] = '\0';
02072
02073 #ifdef MP4_VERBOSE
02074 msg_Dbg( p_stream,
02075 "read box: \"%4.4s\" text=`%s'",
02076 (char*)&p_box->i_type,
02077 p_box->data.p_0xa9xxx->psz_text );
02078 #endif
02079 }
02080
02081 MP4_READBOX_EXIT( 1 );
02082 }
02083 static void MP4_FreeBox_0xa9xxx( MP4_Box_t *p_box )
02084 {
02085 FREE( p_box->data.p_0xa9xxx->psz_text );
02086 }
02087
02088
02089 static int MP4_ReadBox_default( stream_t *p_stream, MP4_Box_t *p_box )
02090 {
02091 if( !p_box->p_father )
02092 {
02093 goto unknown;
02094 }
02095 if( p_box->p_father->i_type == FOURCC_stsd )
02096 {
02097 MP4_Box_t *p_mdia = MP4_BoxGet( p_box, "../../../.." );
02098 MP4_Box_t *p_hdlr;
02099
02100 if( p_mdia == NULL || p_mdia->i_type != FOURCC_mdia ||
02101 (p_hdlr = MP4_BoxGet( p_mdia, "hdlr" )) == NULL )
02102 {
02103 goto unknown;
02104 }
02105 switch( p_hdlr->data.p_hdlr->i_handler_type )
02106 {
02107 case FOURCC_soun:
02108 return MP4_ReadBox_sample_soun( p_stream, p_box );
02109 case FOURCC_vide:
02110 return MP4_ReadBox_sample_vide( p_stream, p_box );
02111 case FOURCC_text:
02112 return MP4_ReadBox_sample_text( p_stream, p_box );
02113 case FOURCC_tx3g:
02114 return MP4_ReadBox_sample_tx3g( p_stream, p_box );
02115 default:
02116 msg_Warn( p_stream,
02117 "unknown handler type in stsd (uncompletetly loaded)" );
02118 return 1;
02119 }
02120 }
02121
02122 unknown:
02123 msg_Warn( p_stream,
02124 "unknown box type %4.4s (uncompletetly loaded)",
02125 (char*)&p_box->i_type );
02126
02127 return 1;
02128 }
02129
02130
02131
02132
02133
02134 static struct
02135 {
02136 uint32_t i_type;
02137 int (*MP4_ReadBox_function )( stream_t *p_stream, MP4_Box_t *p_box );
02138 void (*MP4_FreeBox_function )( MP4_Box_t *p_box );
02139 } MP4_Box_Function [] =
02140 {
02141
02142 { FOURCC_moov, MP4_ReadBoxContainer, MP4_FreeBox_Common },
02143 { FOURCC_trak, MP4_ReadBoxContainer, MP4_FreeBox_Common },
02144 { FOURCC_mdia, MP4_ReadBoxContainer, MP4_FreeBox_Common },
02145 { FOURCC_moof, MP4_ReadBoxContainer, MP4_FreeBox_Common },
02146 { FOURCC_minf, MP4_ReadBoxContainer, MP4_FreeBox_Common },
02147 { FOURCC_stbl, MP4_ReadBoxContainer, MP4_FreeBox_Common },
02148 { FOURCC_dinf, MP4_ReadBoxContainer, MP4_FreeBox_Common },
02149 { FOURCC_edts, MP4_ReadBoxContainer, MP4_FreeBox_Common },
02150 { FOURCC_udta, MP4_ReadBoxContainer, MP4_FreeBox_Common },
02151 { FOURCC_nmhd, MP4_ReadBoxContainer, MP4_FreeBox_Common },
02152 { FOURCC_hnti, MP4_ReadBoxContainer, MP4_FreeBox_Common },
02153 { FOURCC_rmra, MP4_ReadBoxContainer, MP4_FreeBox_Common },
02154 { FOURCC_rmda, MP4_ReadBoxContainer, MP4_FreeBox_Common },
02155 { FOURCC_tref, MP4_ReadBoxContainer, MP4_FreeBox_Common },
02156 { FOURCC_gmhd, MP4_ReadBoxContainer, MP4_FreeBox_Common },
02157 { FOURCC_wave, MP4_ReadBoxContainer, MP4_FreeBox_Common },
02158
02159
02160 { FOURCC_ftyp, MP4_ReadBox_ftyp, MP4_FreeBox_ftyp },
02161 { FOURCC_cmov, MP4_ReadBox_cmov, MP4_FreeBox_Common },
02162 { FOURCC_mvhd, MP4_ReadBox_mvhd, MP4_FreeBox_Common },
02163 { FOURCC_tkhd, MP4_ReadBox_tkhd, MP4_FreeBox_Common },
02164 { FOURCC_mdhd, MP4_ReadBox_mdhd, MP4_FreeBox_Common },
02165 { FOURCC_hdlr, MP4_ReadBox_hdlr, MP4_FreeBox_hdlr },
02166 { FOURCC_vmhd, MP4_ReadBox_vmhd, MP4_FreeBox_Common },
02167 { FOURCC_smhd, MP4_ReadBox_smhd, MP4_FreeBox_Common },
02168 { FOURCC_hmhd, MP4_ReadBox_hmhd, MP4_FreeBox_Common },
02169 { FOURCC_url, MP4_ReadBox_url, MP4_FreeBox_url },
02170 { FOURCC_urn, MP4_ReadBox_urn, MP4_FreeBox_urn },
02171 { FOURCC_dref, MP4_ReadBox_dref, MP4_FreeBox_Common },
02172 { FOURCC_stts, MP4_ReadBox_stts, MP4_FreeBox_stts },
02173 { FOURCC_ctts, MP4_ReadBox_ctts, MP4_FreeBox_ctts },
02174 { FOURCC_stsd, MP4_ReadBox_stsd, MP4_FreeBox_Common },
02175 { FOURCC_stsz, MP4_ReadBox_stsz, MP4_FreeBox_stsz },
02176 { FOURCC_stsc, MP4_ReadBox_stsc, MP4_FreeBox_stsc },
02177 { FOURCC_stco, MP4_ReadBox_stco_co64, MP4_FreeBox_stco_co64 },
02178 { FOURCC_co64, MP4_ReadBox_stco_co64, MP4_FreeBox_stco_co64 },
02179 { FOURCC_stss, MP4_ReadBox_stss, MP4_FreeBox_stss },
02180 { FOURCC_stsh, MP4_ReadBox_stsh, MP4_FreeBox_stsh },
02181 { FOURCC_stdp, MP4_ReadBox_stdp, MP4_FreeBox_stdp },
02182 { FOURCC_padb, MP4_ReadBox_padb, MP4_FreeBox_padb },
02183 { FOURCC_elst, MP4_ReadBox_elst, MP4_FreeBox_elst },
02184 { FOURCC_cprt, MP4_ReadBox_cprt, MP4_FreeBox_cprt },
02185 { FOURCC_esds, MP4_ReadBox_esds, MP4_FreeBox_esds },
02186 { FOURCC_dcom, MP4_ReadBox_dcom, MP4_FreeBox_Common },
02187 { FOURCC_cmvd, MP4_ReadBox_cmvd, MP4_FreeBox_cmvd },
02188 { FOURCC_avcC, MP4_ReadBox_avcC, MP4_FreeBox_avcC },
02189
02190
02191 { FOURCC_mdat, MP4_ReadBoxSkip, MP4_FreeBox_Common },
02192 { FOURCC_skip, MP4_ReadBoxSkip, MP4_FreeBox_Common },
02193 { FOURCC_free, MP4_ReadBoxSkip, MP4_FreeBox_Common },
02194 { FOURCC_wide, MP4_ReadBoxSkip, MP4_FreeBox_Common },
02195
02196
02197 { FOURCC_soun, MP4_ReadBox_sample_soun, MP4_FreeBox_sample_soun },
02198 { FOURCC_ms02, MP4_ReadBox_sample_soun, MP4_FreeBox_sample_soun },
02199 { FOURCC_ms11, MP4_ReadBox_sample_soun, MP4_FreeBox_sample_soun },
02200 { FOURCC_ms55, MP4_ReadBox_sample_soun, MP4_FreeBox_sample_soun },
02201 { FOURCC__mp3, MP4_ReadBox_sample_soun, MP4_FreeBox_sample_soun },
02202 { FOURCC_mp4a, MP4_ReadBox_sample_soun, MP4_FreeBox_sample_soun },
02203 { FOURCC_twos, MP4_ReadBox_sample_soun, MP4_FreeBox_sample_soun },
02204 { FOURCC_sowt, MP4_ReadBox_sample_soun, MP4_FreeBox_sample_soun },
02205 { FOURCC_QDMC, MP4_ReadBox_sample_soun, MP4_FreeBox_sample_soun },
02206 { FOURCC_QDM2, MP4_ReadBox_sample_soun, MP4_FreeBox_sample_soun },
02207 { FOURCC_ima4, MP4_ReadBox_sample_soun, MP4_FreeBox_sample_soun },
02208 { FOURCC_IMA4, MP4_ReadBox_sample_soun, MP4_FreeBox_sample_soun },
02209 { FOURCC_dvi, MP4_ReadBox_sample_soun, MP4_FreeBox_sample_soun },
02210 { FOURCC_alaw, MP4_ReadBox_sample_soun, MP4_FreeBox_sample_soun },
02211 { FOURCC_ulaw, MP4_ReadBox_sample_soun, MP4_FreeBox_sample_soun },
02212 { FOURCC_raw, MP4_ReadBox_sample_soun, MP4_FreeBox_sample_soun },
02213 { FOURCC_MAC3, MP4_ReadBox_sample_soun, MP4_FreeBox_sample_soun },
02214 { FOURCC_MAC6, MP4_ReadBox_sample_soun, MP4_FreeBox_sample_soun },
02215 { FOURCC_Qclp, MP4_ReadBox_sample_soun, MP4_FreeBox_sample_soun },
02216 { FOURCC_samr, MP4_ReadBox_sample_soun, MP4_FreeBox_sample_soun },
02217 { FOURCC_sawb, MP4_ReadBox_sample_soun, MP4_FreeBox_sample_soun },
02218 { FOURCC_OggS, MP4_ReadBox_sample_soun, MP4_FreeBox_sample_soun },
02219 { FOURCC_alac, MP4_ReadBox_sample_soun, MP4_FreeBox_sample_soun },
02220
02221 { FOURCC_vide, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
02222 { FOURCC_mp4v, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
02223 { FOURCC_SVQ1, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
02224 { FOURCC_SVQ3, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
02225 { FOURCC_ZyGo, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
02226 { FOURCC_DIVX, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
02227 { FOURCC_XVID, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
02228 { FOURCC_h263, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
02229 { FOURCC_s263, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
02230 { FOURCC_cvid, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
02231 { FOURCC_3IV1, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
02232 { FOURCC_3iv1, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
02233 { FOURCC_3IV2, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
02234 { FOURCC_3iv2, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
02235 { FOURCC_3IVD, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
02236 { FOURCC_3ivd, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
02237 { FOURCC_3VID, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
02238 { FOURCC_3vid, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
02239 { FOURCC_mjpa, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
02240 { FOURCC_mjpb, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
02241 { FOURCC_qdrw, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
02242 { FOURCC_mp2v, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
02243 { FOURCC_hdv2, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
02244
02245 { FOURCC_mjqt, MP4_ReadBox_default, NULL },
02246 { FOURCC_mjht, MP4_ReadBox_default, NULL },
02247
02248 { FOURCC_dvc, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
02249 { FOURCC_dvp, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
02250 { FOURCC_VP31, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
02251 { FOURCC_vp31, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
02252 { FOURCC_h264, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
02253
02254 { FOURCC_jpeg, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
02255 { FOURCC_avc1, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
02256
02257 { FOURCC_mp4s, MP4_ReadBox_sample_mp4s, MP4_FreeBox_Common },
02258
02259
02260 { FOURCC_hint, MP4_ReadBox_default, MP4_FreeBox_Common },
02261
02262
02263 { FOURCC_dpnd, MP4_ReadBox_default, NULL },
02264 { FOURCC_ipir, MP4_ReadBox_default, NULL },
02265 { FOURCC_mpod, MP4_ReadBox_default, NULL },
02266
02267
02268 { FOURCC_rtp, MP4_ReadBox_default, NULL },
02269
02270
02271 { FOURCC_rdrf, MP4_ReadBox_rdrf, MP4_FreeBox_rdrf },
02272 { FOURCC_rmdr, MP4_ReadBox_rmdr, MP4_FreeBox_Common },
02273 { FOURCC_rmqu, MP4_ReadBox_rmqu, MP4_FreeBox_Common },
02274 { FOURCC_rmvc, MP4_ReadBox_rmvc, MP4_FreeBox_Common },
02275
02276 { FOURCC_drms, MP4_ReadBox_sample_soun, MP4_FreeBox_sample_soun },
02277 { FOURCC_sinf, MP4_ReadBoxContainer, MP4_FreeBox_Common },
02278 { FOURCC_schi, MP4_ReadBoxContainer, MP4_FreeBox_Common },
02279 { FOURCC_user, MP4_ReadBox_drms, MP4_FreeBox_Common },
02280 { FOURCC_key, MP4_ReadBox_drms, MP4_FreeBox_Common },
02281 { FOURCC_iviv, MP4_ReadBox_drms, MP4_FreeBox_Common },
02282 { FOURCC_name, MP4_ReadBox_drms, MP4_FreeBox_Common },
02283 { FOURCC_priv, MP4_ReadBox_drms, MP4_FreeBox_Common },
02284
02285
02286 { FOURCC_0xa9nam,MP4_ReadBox_0xa9xxx, MP4_FreeBox_0xa9xxx },
02287 { FOURCC_0xa9aut,MP4_ReadBox_0xa9xxx, MP4_FreeBox_0xa9xxx },
02288 { FOURCC_0xa9cpy,MP4_ReadBox_0xa9xxx, MP4_FreeBox_0xa9xxx },
02289 { FOURCC_0xa9swr,MP4_ReadBox_0xa9xxx, MP4_FreeBox_0xa9xxx },
02290 { FOURCC_0xa9inf,MP4_ReadBox_0xa9xxx, MP4_FreeBox_0xa9xxx },
02291 { FOURCC_0xa9ART,MP4_ReadBox_0xa9xxx, MP4_FreeBox_0xa9xxx },
02292 { FOURCC_0xa9dir,MP4_ReadBox_0xa9xxx, MP4_FreeBox_0xa9xxx },
02293 { FOURCC_0xa9cmt,MP4_ReadBox_0xa9xxx, MP4_FreeBox_0xa9xxx },
02294 { FOURCC_0xa9req,MP4_ReadBox_0xa9xxx, MP4_FreeBox_0xa9xxx },
02295 { FOURCC_0xa9day,MP4_ReadBox_0xa9xxx, MP4_FreeBox_0xa9xxx },
02296 { FOURCC_0xa9des,MP4_ReadBox_0xa9xxx, MP4_FreeBox_0xa9xxx },
02297 { FOURCC_0xa9fmt,MP4_ReadBox_0xa9xxx, MP4_FreeBox_0xa9xxx },
02298 { FOURCC_0xa9prd,MP4_ReadBox_0xa9xxx, MP4_FreeBox_0xa9xxx },
02299 { FOURCC_0xa9prf,MP4_ReadBox_0xa9xxx, MP4_FreeBox_0xa9xxx },
02300 { FOURCC_0xa9src,MP4_ReadBox_0xa9xxx, MP4_FreeBox_0xa9xxx },
02301 { FOURCC_0xa9alb,MP4_ReadBox_0xa9xxx, MP4_FreeBox_0xa9xxx },
02302 { FOURCC_0xa9dis,MP4_ReadBox_0xa9xxx, MP4_FreeBox_0xa9xxx },
02303 { FOURCC_0xa9enc,MP4_ReadBox_0xa9xxx, MP4_FreeBox_0xa9xxx },
02304 { FOURCC_0xa9gen,MP4_ReadBox_0xa9xxx, MP4_FreeBox_0xa9xxx },
02305 { FOURCC_0xa9trk,MP4_ReadBox_0xa9xxx, MP4_FreeBox_0xa9xxx },
02306 { FOURCC_0xa9dsa,MP4_ReadBox_0xa9xxx, MP4_FreeBox_0xa9xxx },
02307 { FOURCC_0xa9hst,MP4_ReadBox_0xa9xxx, MP4_FreeBox_0xa9xxx },
02308 { FOURCC_0xa9url,MP4_ReadBox_0xa9xxx, MP4_FreeBox_0xa9xxx },
02309 { FOURCC_0xa9ope,MP4_ReadBox_0xa9xxx, MP4_FreeBox_0xa9xxx },
02310 { FOURCC_0xa9com,MP4_ReadBox_0xa9xxx, MP4_FreeBox_0xa9xxx },
02311
02312
02313 { 0, MP4_ReadBox_default, NULL }
02314 };
02315
02316
02317
02318
02319
02320
02321
02322 static MP4_Box_t *MP4_ReadBox( stream_t *p_stream, MP4_Box_t *p_father )
02323 {
02324 MP4_Box_t *p_box = malloc( sizeof( MP4_Box_t ) );
02325 unsigned int i_index;
02326
02327 if( !MP4_ReadBoxCommon( p_stream, p_box ) )
02328 {
02329 msg_Warn( p_stream, "cannot read one box" );
02330 free( p_box );
02331 return NULL;
02332 }
02333 if( !p_box->i_size )
02334 {
02335 msg_Dbg( p_stream, "found an empty box (null size)" );
02336 free( p_box );
02337 return NULL;
02338 }
02339 p_box->p_father = p_father;
02340
02341
02342 for( i_index = 0; ; i_index++ )
02343 {
02344 if( ( MP4_Box_Function[i_index].i_type == p_box->i_type )||
02345 ( MP4_Box_Function[i_index].i_type == 0 ) )
02346 {
02347 break;
02348 }
02349 }
02350
02351 if( !(MP4_Box_Function[i_index].MP4_ReadBox_function)( p_stream, p_box ) )
02352 {
02353 free( p_box );
02354 return NULL;
02355 }
02356
02357 return p_box;
02358 }
02359
02360
02361
02362
02363
02364 void MP4_BoxFree( stream_t *s, MP4_Box_t *p_box )
02365 {
02366 unsigned int i_index;
02367 MP4_Box_t *p_child;
02368
02369 if( !p_box )
02370 {
02371 return;
02372 }
02373
02374 for( p_child = p_box->p_first; p_child != NULL; )
02375 {
02376 MP4_Box_t *p_next;
02377
02378 p_next = p_child->p_next;
02379 MP4_BoxFree( s, p_child );
02380 p_child = p_next;
02381 }
02382
02383
02384 if( p_box->data.p_data )
02385 {
02386 for( i_index = 0; ; i_index++ )
02387 {
02388 if( ( MP4_Box_Function[i_index].i_type == p_box->i_type )||
02389 ( MP4_Box_Function[i_index].i_type == 0 ) )
02390 {
02391 break;
02392 }
02393 }
02394 if( MP4_Box_Function[i_index].MP4_FreeBox_function == NULL )
02395 {
02396
02397 msg_Warn( s,
02398 "cannot free box %4.4s, type unknown",
02399 (char*)&p_box->i_type );
02400 }
02401 else
02402 {
02403 MP4_Box_Function[i_index].MP4_FreeBox_function( p_box );
02404 }
02405
02406 free( p_box->data.p_data );
02407 }
02408
02409 free( p_box );
02410 }
02411
02412
02413
02414
02415
02416
02417
02418 MP4_Box_t *MP4_BoxGetRoot( stream_t *s )
02419 {
02420 MP4_Box_t *p_root;
02421 stream_t *p_stream;
02422 int i_result;
02423
02424 p_root = malloc( sizeof( MP4_Box_t ) );
02425 p_root->i_pos = 0;
02426 p_root->i_type = VLC_FOURCC( 'r', 'o', 'o', 't' );
02427 p_root->i_shortsize = 1;
02428 p_root->i_size = stream_Size( s );
02429 CreateUUID( &p_root->i_uuid, p_root->i_type );
02430
02431 p_root->data.p_data = NULL;
02432 p_root->p_father = NULL;
02433 p_root->p_first = NULL;
02434 p_root->p_last = NULL;
02435 p_root->p_next = NULL;
02436
02437 p_stream = s;
02438
02439 i_result = MP4_ReadBoxContainerRaw( p_stream, p_root );
02440
02441 if( i_result )
02442 {
02443 MP4_Box_t *p_child;
02444 MP4_Box_t *p_moov;
02445 MP4_Box_t *p_cmov;
02446
02447
02448
02449 if( ( ( p_moov = MP4_BoxGet( p_root, "moov" ) ) &&
02450 ( p_cmov = MP4_BoxGet( p_root, "moov/cmov" ) ) ) ||
02451 ( ( p_moov = MP4_BoxGet( p_root, "foov" ) ) &&
02452 ( p_cmov = MP4_BoxGet( p_root, "foov/cmov" ) ) ) )
02453 {
02454
02455 p_moov->i_type = FOURCC_skip;
02456
02457
02458 p_moov = p_cmov->data.p_cmov->p_moov;
02459 p_cmov->data.p_cmov->p_moov = NULL;
02460
02461
02462 p_moov->p_father = p_root;
02463
02464
02465 p_moov->p_next = p_child = p_root->p_first;
02466 p_root->p_first = p_moov;
02467 }
02468 }
02469
02470 return p_root;
02471 }
02472
02473
02474 static void __MP4_BoxDumpStructure( stream_t *s,
02475 MP4_Box_t *p_box, unsigned int i_level )
02476 {
02477 MP4_Box_t *p_child;
02478
02479 if( !i_level )
02480 {
02481 msg_Dbg( s, "dumping root Box \"%4.4s\"",
02482 (char*)&p_box->i_type );
02483 }
02484 else
02485 {
02486 char str[512];
02487 unsigned int i;
02488 memset( str, (uint8_t)' ', 512 );
02489 for( i = 0; i < i_level; i++ )
02490 {
02491 str[i*5] = '|';
02492 }
02493 sprintf( str + i_level * 5, "+ %4.4s size %d",
02494 (char*)&p_box->i_type,
02495 (uint32_t)p_box->i_size );
02496
02497 msg_Dbg( s, "%s", str );
02498 }
02499 p_child = p_box->p_first;
02500 while( p_child )
02501 {
02502 __MP4_BoxDumpStructure( s, p_child, i_level + 1 );
02503 p_child = p_child->p_next;
02504 }
02505 }
02506
02507 void MP4_BoxDumpStructure( stream_t *s, MP4_Box_t *p_box )
02508 {
02509 __MP4_BoxDumpStructure( s, p_box, 0 );
02510 }
02511
02512
02513
02514
02515
02516
02517
02518
02519
02520
02521 static void __get_token( char **ppsz_path, char **ppsz_token, int *pi_number )
02522 {
02523 size_t i_len ;
02524 if( !*ppsz_path[0] )
02525 {
02526 *ppsz_token = NULL;
02527 *pi_number = 0;
02528 return;
02529 }
02530 i_len = 0;
02531 while( (*ppsz_path)[i_len] &&
02532 (*ppsz_path)[i_len] != '/' && (*ppsz_path)[i_len] != '[' )
02533 {
02534 i_len++;
02535 }
02536 if( !i_len && **ppsz_path == '/' )
02537 {
02538 i_len = 1;
02539 }
02540 *ppsz_token = malloc( i_len + 1 );
02541
02542 memcpy( *ppsz_token, *ppsz_path, i_len );
02543
02544 (*ppsz_token)[i_len] = '\0';
02545
02546 *ppsz_path += i_len;
02547
02548 if( **ppsz_path == '[' )
02549 {
02550 (*ppsz_path)++;
02551 *pi_number = strtol( *ppsz_path, NULL, 10 );
02552 while( **ppsz_path && **ppsz_path != ']' )
02553 {
02554 (*ppsz_path)++;
02555 }
02556 if( **ppsz_path == ']' )
02557 {
02558 (*ppsz_path)++;
02559 }
02560 }
02561 else
02562 {
02563 *pi_number = 0;
02564 }
02565 while( **ppsz_path == '/' )
02566 {
02567 (*ppsz_path)++;
02568 }
02569 }
02570
02571 static void __MP4_BoxGet( MP4_Box_t **pp_result,
02572 MP4_Box_t *p_box, char *psz_fmt, va_list args)
02573 {
02574 char *psz_path;
02575
02576 if( !p_box )
02577 {
02578 *pp_result = NULL;
02579 return;
02580 }
02581
02582 vasprintf( &psz_path, psz_fmt, args );
02583
02584 if( !psz_path || !psz_path[0] )
02585 {
02586 FREE( psz_path );
02587 *pp_result = NULL;
02588 return;
02589 }
02590
02591
02592 psz_fmt = psz_path;
02593 for( ; ; )
02594 {
02595 char *psz_token;
02596 int i_number;
02597
02598 __get_token( &psz_path, &psz_token, &i_number );
02599
02600
02601 if( !psz_token )
02602 {
02603 FREE( psz_token );
02604 free( psz_fmt );
02605 *pp_result = p_box;
02606 return;
02607 }
02608 else
02609 if( !strcmp( psz_token, "/" ) )
02610 {
02611
02612 while( p_box && p_box->i_type != VLC_FOURCC( 'r', 'o', 'o', 't' ) )
02613 {
02614 p_box = p_box->p_father;
02615 }
02616 if( !p_box )
02617 {
02618 free( psz_token );
02619 free( psz_fmt );
02620 *pp_result = NULL;
02621 return;
02622 }
02623 }
02624 else
02625 if( !strcmp( psz_token, "." ) )
02626 {
02627
02628 }
02629 else
02630 if( !strcmp( psz_token, ".." ) )
02631 {
02632 p_box = p_box->p_father;
02633 if( !p_box )
02634 {
02635 free( psz_token );
02636 free( psz_fmt );
02637 *pp_result = NULL;
02638 return;
02639 }
02640 }
02641 else
02642 if( strlen( psz_token ) == 4 )
02643 {
02644 uint32_t i_fourcc;
02645 i_fourcc = VLC_FOURCC( psz_token[0], psz_token[1],
02646 psz_token[2], psz_token[3] );
02647 p_box = p_box->p_first;
02648 for( ; ; )
02649 {
02650 if( !p_box )
02651 {
02652 free( psz_token );
02653 free( psz_fmt );
02654 *pp_result = NULL;
02655 return;
02656 }
02657 if( p_box->i_type == i_fourcc )
02658 {
02659 if( !i_number )
02660 {
02661 break;
02662 }
02663 i_number--;
02664 }
02665 p_box = p_box->p_next;
02666 }
02667 }
02668 else
02669 if( strlen( psz_token ) == 0 )
02670 {
02671 p_box = p_box->p_first;
02672 for( ; ; )
02673 {
02674 if( !p_box )
02675 {
02676 free( psz_token );
02677 free( psz_fmt );
02678 *pp_result = NULL;
02679 return;
02680 }
02681 if( !i_number )
02682 {
02683 break;
02684 }
02685 i_number--;
02686 p_box = p_box->p_next;
02687 }
02688 }
02689 else
02690 {
02691
02692 FREE( psz_token );
02693 free( psz_fmt );
02694 *pp_result = NULL;
02695 return;
02696 }
02697
02698 free( psz_token );
02699 }
02700 }
02701
02702
02703
02704
02705
02706
02707
02708
02709
02710
02711 MP4_Box_t *MP4_BoxGet( MP4_Box_t *p_box, char *psz_fmt, ... )
02712 {
02713 va_list args;
02714 MP4_Box_t *p_result;
02715
02716 va_start( args, psz_fmt );
02717 __MP4_BoxGet( &p_result, p_box, psz_fmt, args );
02718 va_end( args );
02719
02720 return( p_result );
02721 }
02722
02723
02724
02725
02726
02727
02728
02729
02730
02731
02732 int MP4_BoxCount( MP4_Box_t *p_box, char *psz_fmt, ... )
02733 {
02734 va_list args;
02735 int i_count;
02736 MP4_Box_t *p_result, *p_next;
02737
02738 va_start( args, psz_fmt );
02739 __MP4_BoxGet( &p_result, p_box, psz_fmt, args );
02740 va_end( args );
02741 if( !p_result )
02742 {
02743 return( 0 );
02744 }
02745
02746 i_count = 1;
02747 for( p_next = p_result->p_next; p_next != NULL; p_next = p_next->p_next)
02748 {
02749 if( p_next->i_type == p_result->i_type)
02750 {
02751 i_count++;
02752 }
02753 }
02754 return( i_count );
02755 }