00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <stdlib.h>
00027
00028 #include <vlc/vlc.h>
00029 #include <vlc/input.h>
00030 #include <vlc_playlist.h>
00031 #include <vlc_md5.h>
00032 #include "iso_lang.h"
00033 #include "vlc_meta.h"
00034
00035 #include "libmp4.h"
00036 #include "drms.h"
00037
00038 #ifdef UNDER_CE
00039 #define uint64_t int64_t
00040 #endif
00041
00042
00043
00044
00045 static int Open ( vlc_object_t * );
00046 static void Close( vlc_object_t * );
00047
00048 vlc_module_begin();
00049 set_category( CAT_INPUT );
00050 set_subcategory( SUBCAT_INPUT_DEMUX );
00051 set_description( _("MP4 stream demuxer") );
00052 set_capability( "demux2", 242 );
00053 set_callbacks( Open, Close );
00054 vlc_module_end();
00055
00056
00057
00058
00059 static int Demux ( demux_t * );
00060 static int DemuxRef( demux_t *p_demux ){ return 0;}
00061 static int Seek ( demux_t *, mtime_t );
00062 static int Control ( demux_t *, int, va_list );
00063
00064
00065 typedef struct
00066 {
00067 uint64_t i_offset;
00068 uint32_t i_sample_description_index;
00069 uint32_t i_sample_count;
00070 uint32_t i_sample_first;
00071
00072
00073
00074
00075
00076 uint64_t i_first_dts;
00077 uint32_t *p_sample_count_dts;
00078 uint32_t *p_sample_delta_dts;
00079
00080 uint32_t *p_sample_count_pts;
00081 int32_t *p_sample_offset_pts;
00082
00083
00084
00085
00086 } mp4_chunk_t;
00087
00088
00089 typedef struct
00090 {
00091 int i_track_ID;
00092
00093 int b_ok;
00094 int b_enable;
00095 vlc_bool_t b_selected;
00096
00097 es_format_t fmt;
00098 es_out_id_t *p_es;
00099
00100
00101 int i_width;
00102 int i_height;
00103
00104
00105 uint64_t i_timescale;
00106
00107
00108 int i_elst;
00109 int64_t i_elst_time;
00110 MP4_Box_t *p_elst;
00111
00112
00113
00114 uint32_t i_sample;
00115 uint32_t i_chunk;
00116
00117 uint32_t i_chunk_count;
00118 uint32_t i_sample_count;
00119
00120 mp4_chunk_t *chunk;
00121
00122
00123
00124 uint32_t i_sample_size;
00125 uint32_t *p_sample_size;
00126
00127
00128 MP4_Box_t *p_stbl;
00129 MP4_Box_t *p_stsd;
00130 MP4_Box_t *p_sample;
00131
00132 vlc_bool_t b_drms;
00133 void *p_drms;
00134
00135 } mp4_track_t;
00136
00137
00138 struct demux_sys_t
00139 {
00140 MP4_Box_t *p_root;
00141
00142 mtime_t i_pcr;
00143
00144 uint64_t i_time;
00145
00146 uint64_t i_timescale;
00147 uint64_t i_duration;
00148 unsigned int i_tracks;
00149 mp4_track_t *track;
00150 };
00151
00152
00153
00154
00155 static void MP4_TrackCreate ( demux_t *, mp4_track_t *, MP4_Box_t *);
00156 static void MP4_TrackDestroy( demux_t *, mp4_track_t * );
00157
00158 static int MP4_TrackSelect ( demux_t *, mp4_track_t *, mtime_t );
00159 static void MP4_TrackUnselect(demux_t *, mp4_track_t * );
00160
00161 static int MP4_TrackSeek ( demux_t *, mp4_track_t *, mtime_t );
00162
00163 static uint64_t MP4_TrackGetPos ( mp4_track_t * );
00164 static int MP4_TrackSampleSize( mp4_track_t * );
00165 static int MP4_TrackNextSample( demux_t *, mp4_track_t * );
00166 static void MP4_TrackSetELST( demux_t *, mp4_track_t *, int64_t );
00167
00168
00169 static inline int64_t MP4_TrackGetDTS( demux_t *p_demux, mp4_track_t *p_track )
00170 {
00171 #define chunk p_track->chunk[p_track->i_chunk]
00172
00173 unsigned int i_index = 0;
00174 unsigned int i_sample = p_track->i_sample - chunk.i_sample_first;
00175 int64_t i_dts = chunk.i_first_dts;
00176
00177 while( i_sample > 0 )
00178 {
00179 if( i_sample > chunk.p_sample_count_dts[i_index] )
00180 {
00181 i_dts += chunk.p_sample_count_dts[i_index] *
00182 chunk.p_sample_delta_dts[i_index];
00183 i_sample -= chunk.p_sample_count_dts[i_index];
00184 i_index++;
00185 }
00186 else
00187 {
00188 i_dts += i_sample * chunk.p_sample_delta_dts[i_index];
00189 i_sample = 0;
00190 break;
00191 }
00192 }
00193
00194 #undef chunk
00195
00196
00197 if( p_track->p_elst )
00198 {
00199 demux_sys_t *p_sys = p_demux->p_sys;
00200 MP4_Box_data_elst_t *elst = p_track->p_elst->data.p_elst;
00201
00202
00203 if( ( elst->i_media_rate_integer[p_track->i_elst] > 0 ||
00204 elst->i_media_rate_fraction[p_track->i_elst] > 0 ) &&
00205 elst->i_media_time[p_track->i_elst] > 0 )
00206 {
00207 i_dts -= elst->i_media_time[p_track->i_elst];
00208 }
00209
00210
00211 i_dts += p_track->i_elst_time * p_track->i_timescale /
00212 p_sys->i_timescale;
00213
00214 if( i_dts < 0 ) i_dts = 0;
00215 }
00216
00217 return I64C(1000000) * i_dts / p_track->i_timescale;
00218 }
00219
00220 static inline int64_t MP4_TrackGetPTSDelta( demux_t *p_demux, mp4_track_t *p_track )
00221 {
00222 mp4_chunk_t *ck = &p_track->chunk[p_track->i_chunk];
00223 unsigned int i_index = 0;
00224 unsigned int i_sample = p_track->i_sample - ck->i_sample_first;
00225
00226 if( ck->p_sample_count_pts == NULL || ck->p_sample_offset_pts == NULL )
00227 return -1;
00228
00229 for( i_index = 0;; i_index++ )
00230 {
00231 if( i_sample < ck->p_sample_count_pts[i_index] )
00232 return ck->p_sample_offset_pts[i_index] * I64C(1000000) /
00233 (int64_t)p_track->i_timescale;
00234
00235 i_sample -= ck->p_sample_count_pts[i_index];
00236 }
00237 }
00238
00239 static inline int64_t MP4_GetMoviePTS(demux_sys_t *p_sys )
00240 {
00241 return I64C(1000000) * p_sys->i_time / p_sys->i_timescale;
00242 }
00243
00244 #define FREE( p ) if( p ) { free( p ); (p) = NULL;}
00245
00246
00247
00248
00249 static int Open( vlc_object_t * p_this )
00250 {
00251 demux_t *p_demux = (demux_t *)p_this;
00252 demux_sys_t *p_sys;
00253
00254 uint8_t *p_peek;
00255
00256 MP4_Box_t *p_ftyp;
00257 MP4_Box_t *p_rmra;
00258 MP4_Box_t *p_mvhd;
00259 MP4_Box_t *p_trak;
00260
00261 unsigned int i;
00262 vlc_bool_t b_seekable;
00263
00264
00265 if( stream_Peek( p_demux->s, &p_peek, 8 ) < 8 ) return VLC_EGENERIC;
00266
00267 switch( VLC_FOURCC( p_peek[4], p_peek[5], p_peek[6], p_peek[7] ) )
00268 {
00269 case FOURCC_ftyp:
00270 case FOURCC_moov:
00271 case FOURCC_foov:
00272 case FOURCC_moof:
00273 case FOURCC_mdat:
00274 case FOURCC_udta:
00275 case FOURCC_free:
00276 case FOURCC_skip:
00277 case FOURCC_wide:
00278 case VLC_FOURCC( 'p', 'n', 'o', 't' ):
00279 break;
00280 default:
00281 return VLC_EGENERIC;
00282 }
00283
00284
00285 stream_Control( p_demux->s, STREAM_CAN_SEEK, &b_seekable );
00286 if( !b_seekable )
00287 {
00288 msg_Warn( p_demux, "MP4 plugin discarded (unseekable)" );
00289 return VLC_EGENERIC;
00290 }
00291
00292
00293 p_demux->pf_demux = Demux;
00294 p_demux->pf_control = Control;
00295
00296
00297 p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
00298 memset( p_sys, 0, sizeof( demux_sys_t ) );
00299
00300
00301 if( ( p_sys->p_root = MP4_BoxGetRoot( p_demux->s ) ) == NULL )
00302 {
00303 msg_Warn( p_demux, "MP4 plugin discarded (not a valid file)" );
00304 goto error;
00305 }
00306
00307 MP4_BoxDumpStructure( p_demux->s, p_sys->p_root );
00308
00309 if( ( p_ftyp = MP4_BoxGet( p_sys->p_root, "/ftyp" ) ) )
00310 {
00311 switch( p_ftyp->data.p_ftyp->i_major_brand )
00312 {
00313 case( FOURCC_isom ):
00314 msg_Dbg( p_demux,
00315 "ISO Media file (isom) version %d.",
00316 p_ftyp->data.p_ftyp->i_minor_version );
00317 break;
00318 default:
00319 msg_Dbg( p_demux,
00320 "unrecognized major file specification (%4.4s).",
00321 (char*)&p_ftyp->data.p_ftyp->i_major_brand );
00322 break;
00323 }
00324 }
00325 else
00326 {
00327 msg_Dbg( p_demux, "file type box missing (assuming ISO Media file)" );
00328 }
00329
00330
00331 if( MP4_BoxCount( p_sys->p_root, "/moov" ) <= 0 )
00332 {
00333 MP4_Box_t *p_foov = MP4_BoxGet( p_sys->p_root, "/foov" );
00334
00335 if( !p_foov )
00336 {
00337 msg_Err( p_demux, "MP4 plugin discarded (no moov box)" );
00338 goto error;
00339 }
00340
00341 p_foov->i_type = FOURCC_moov;
00342 }
00343
00344 if( ( p_rmra = MP4_BoxGet( p_sys->p_root, "/moov/rmra" ) ) )
00345 {
00346 playlist_t *p_playlist;
00347 playlist_item_t *p_item;
00348 int i_count = MP4_BoxCount( p_rmra, "rmda" );
00349 int i;
00350 vlc_bool_t b_play = VLC_FALSE;
00351
00352 msg_Dbg( p_demux, "detected playlist mov file (%d ref)", i_count );
00353
00354 p_playlist =
00355 (playlist_t *)vlc_object_find( p_demux,
00356 VLC_OBJECT_PLAYLIST,
00357 FIND_ANYWHERE );
00358 if( p_playlist )
00359 {
00360 p_item = playlist_LockItemGetByInput( p_playlist,
00361 ((input_thread_t *)p_demux->p_parent)->input.p_item );
00362 playlist_ItemToNode( p_playlist, p_item );
00363
00364 for( i = 0; i < i_count; i++ )
00365 {
00366 MP4_Box_t *p_rdrf = MP4_BoxGet( p_rmra, "rmda[%d]/rdrf", i );
00367 char *psz_ref;
00368 uint32_t i_ref_type;
00369
00370 if( !p_rdrf || !( psz_ref = p_rdrf->data.p_rdrf->psz_ref ) )
00371 {
00372 continue;
00373 }
00374 i_ref_type = p_rdrf->data.p_rdrf->i_ref_type;
00375
00376 msg_Dbg( p_demux, "new ref=`%s' type=%4.4s",
00377 psz_ref, (char*)&i_ref_type );
00378
00379 if( i_ref_type == VLC_FOURCC( 'u', 'r', 'l', ' ' ) )
00380 {
00381 if( strstr( psz_ref, "qt5gateQT" ) )
00382 {
00383 msg_Dbg( p_demux, "ignoring pseudo ref =`%s'", psz_ref );
00384 continue;
00385 }
00386 if( !strncmp( psz_ref, "http://", 7 ) ||
00387 !strncmp( psz_ref, "rtsp://", 7 ) )
00388 {
00389 msg_Dbg( p_demux, "adding ref = `%s'", psz_ref );
00390 if( p_item )
00391 {
00392 playlist_item_t *p_child =
00393 playlist_ItemNew( p_playlist,
00394 psz_ref, psz_ref );
00395 if( p_child )
00396 {
00397 playlist_NodeAddItem( p_playlist, p_child,
00398 p_item->pp_parents[0]->i_view,
00399 p_item, PLAYLIST_APPEND,
00400 PLAYLIST_END );
00401 playlist_CopyParents( p_item, p_child );
00402 b_play = VLC_TRUE;
00403 }
00404 }
00405 }
00406 else
00407 {
00408
00409 char *psz_absolute = alloca( strlen( p_demux->psz_access ) + 3 + strlen( p_demux->psz_path ) + strlen( psz_ref ) + 1);
00410 char *end = strrchr( p_demux->psz_path, '/' );
00411
00412 if( end )
00413 {
00414 int i_len = end + 1 - p_demux->psz_path;
00415
00416 strcpy( psz_absolute, p_demux->psz_access );
00417 strcat( psz_absolute, "://" );
00418 strncat( psz_absolute, p_demux->psz_path, i_len);
00419 }
00420 else
00421 {
00422 strcpy( psz_absolute, "" );
00423 }
00424 strcat( psz_absolute, psz_ref );
00425 msg_Dbg( p_demux, "adding ref = `%s'", psz_absolute );
00426 if( p_item )
00427 {
00428 playlist_item_t *p_child =
00429 playlist_ItemNew( p_playlist,
00430 psz_absolute,
00431 psz_absolute );
00432 if( p_child )
00433 {
00434 playlist_NodeAddItem( p_playlist, p_child,
00435 p_item->pp_parents[0]->i_view,
00436 p_item, PLAYLIST_APPEND,
00437 PLAYLIST_END );
00438 playlist_CopyParents( p_item, p_child );
00439 b_play = VLC_TRUE;
00440 }
00441 }
00442 }
00443 }
00444 else
00445 {
00446 msg_Err( p_demux, "unknown ref type=%4.4s FIXME (send a bug report)",
00447 (char*)&p_rdrf->data.p_rdrf->i_ref_type );
00448 }
00449 }
00450 if( b_play == VLC_TRUE )
00451 {
00452 playlist_Control( p_playlist, PLAYLIST_VIEWPLAY,
00453 p_playlist->status.i_view,
00454 p_playlist->status.p_item, NULL );
00455 }
00456 vlc_object_release( p_playlist );
00457 }
00458 else
00459 {
00460 msg_Err( p_demux, "can't find playlist" );
00461 }
00462 }
00463
00464 if( !(p_mvhd = MP4_BoxGet( p_sys->p_root, "/moov/mvhd" ) ) )
00465 {
00466 if( !p_rmra )
00467 {
00468 msg_Err( p_demux, "cannot find /moov/mvhd" );
00469 goto error;
00470 }
00471 else
00472 {
00473 msg_Warn( p_demux, "cannot find /moov/mvhd (pure ref file)" );
00474 p_demux->pf_demux = DemuxRef;
00475 return VLC_SUCCESS;
00476 }
00477 }
00478 else
00479 {
00480 p_sys->i_timescale = p_mvhd->data.p_mvhd->i_timescale;
00481 p_sys->i_duration = p_mvhd->data.p_mvhd->i_duration;
00482 }
00483
00484 if( !( p_sys->i_tracks = MP4_BoxCount( p_sys->p_root, "/moov/trak" ) ) )
00485 {
00486 msg_Err( p_demux, "cannot find any /moov/trak" );
00487 goto error;
00488 }
00489 msg_Dbg( p_demux, "find %d track%c",
00490 p_sys->i_tracks,
00491 p_sys->i_tracks ? 's':' ' );
00492
00493
00494 p_sys->track = calloc( p_sys->i_tracks, sizeof( mp4_track_t ) );
00495 memset( p_sys->track, 0, p_sys->i_tracks * sizeof( mp4_track_t ) );
00496
00497
00498 for( i = 0; i < p_sys->i_tracks; i++ )
00499 {
00500 p_trak = MP4_BoxGet( p_sys->p_root, "/moov/trak[%d]", i );
00501 MP4_TrackCreate( p_demux, &p_sys->track[i], p_trak );
00502
00503 if( p_sys->track[i].b_ok )
00504 {
00505 char *psz_cat;
00506 switch( p_sys->track[i].fmt.i_cat )
00507 {
00508 case( VIDEO_ES ):
00509 psz_cat = "video";
00510 break;
00511 case( AUDIO_ES ):
00512 psz_cat = "audio";
00513 break;
00514 case( SPU_ES ):
00515 psz_cat = "subtitle";
00516 break;
00517
00518 default:
00519 psz_cat = "unknown";
00520 break;
00521 }
00522
00523 msg_Dbg( p_demux, "adding track[Id 0x%x] %s (%s) language %s",
00524 p_sys->track[i].i_track_ID, psz_cat,
00525 p_sys->track[i].b_enable ? "enable":"disable",
00526 p_sys->track[i].fmt.psz_language ?
00527 p_sys->track[i].fmt.psz_language : "undef" );
00528 }
00529 else
00530 {
00531 msg_Dbg( p_demux, "ignoring track[Id 0x%x]",
00532 p_sys->track[i].i_track_ID );
00533 }
00534
00535 }
00536 return VLC_SUCCESS;
00537
00538 error:
00539 if( p_sys->p_root )
00540 {
00541 MP4_BoxFree( p_demux->s, p_sys->p_root );
00542 }
00543 free( p_sys );
00544 return VLC_EGENERIC;
00545 }
00546
00547
00548
00549
00550
00551
00552 static int Demux( demux_t *p_demux )
00553 {
00554 demux_sys_t *p_sys = p_demux->p_sys;
00555 unsigned int i_track;
00556
00557
00558 unsigned int i_track_selected;
00559
00560
00561 for( i_track = 0, i_track_selected = 0; i_track < p_sys->i_tracks;
00562 i_track++ )
00563 {
00564 mp4_track_t *tk = &p_sys->track[i_track];
00565 vlc_bool_t b;
00566
00567 if( !tk->b_ok ||
00568 ( tk->b_selected && tk->i_sample >= tk->i_sample_count ) )
00569 {
00570 continue;
00571 }
00572
00573 es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE, tk->p_es, &b );
00574
00575 if( tk->b_selected && !b )
00576 {
00577 MP4_TrackUnselect( p_demux, tk );
00578 }
00579 else if( !tk->b_selected && b)
00580 {
00581 MP4_TrackSelect( p_demux, tk, MP4_GetMoviePTS( p_sys ) );
00582 }
00583
00584 if( tk->b_selected )
00585 {
00586 i_track_selected++;
00587 }
00588 }
00589
00590 if( i_track_selected <= 0 )
00591 {
00592 p_sys->i_time += __MAX( p_sys->i_timescale / 10 , 1 );
00593 if( p_sys->i_timescale > 0 )
00594 {
00595 int64_t i_length = (mtime_t)1000000 *
00596 (mtime_t)p_sys->i_duration /
00597 (mtime_t)p_sys->i_timescale;
00598 if( MP4_GetMoviePTS( p_sys ) >= i_length )
00599 return 0;
00600 return 1;
00601 }
00602
00603 msg_Warn( p_demux, "no track selected, exiting..." );
00604 return 0;
00605 }
00606
00607
00608 es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_pcr + 1 );
00609
00610 p_sys->i_pcr = MP4_GetMoviePTS( p_sys );
00611
00612
00613 p_sys->i_time += __MAX( p_sys->i_timescale / 10 , 1 );
00614
00615 for( i_track = 0; i_track < p_sys->i_tracks; i_track++ )
00616 {
00617 mp4_track_t *tk = &p_sys->track[i_track];
00618
00619 if( !tk->b_ok || !tk->b_selected || tk->i_sample >= tk->i_sample_count )
00620 {
00621 continue;
00622 }
00623
00624 while( MP4_TrackGetDTS( p_demux, tk ) < MP4_GetMoviePTS( p_sys ) )
00625 {
00626 #if 0
00627 msg_Dbg( p_demux, "tk(%i)=%lld mv=%lld", i_track,
00628 MP4_TrackGetDTS( p_demux, tk ),
00629 MP4_GetMoviePTS( p_sys ) );
00630 #endif
00631
00632 if( MP4_TrackSampleSize( tk ) > 0 )
00633 {
00634 block_t *p_block;
00635 int64_t i_delta;
00636
00637
00638 if( stream_Seek( p_demux->s, MP4_TrackGetPos( tk ) ) )
00639 {
00640 msg_Warn( p_demux, "track[0x%x] will be disabled (eof?)",
00641 tk->i_track_ID );
00642 MP4_TrackUnselect( p_demux, tk );
00643 break;
00644 }
00645
00646
00647 if( !(p_block =
00648 stream_Block( p_demux->s, MP4_TrackSampleSize(tk) )) )
00649 {
00650 msg_Warn( p_demux, "track[0x%x] will be disabled (eof?)",
00651 tk->i_track_ID );
00652 MP4_TrackUnselect( p_demux, tk );
00653 break;
00654 }
00655
00656 if( tk->b_drms && tk->p_drms )
00657 {
00658 drms_decrypt( tk->p_drms, (uint32_t*)p_block->p_buffer,
00659 p_block->i_buffer );
00660 }
00661 else if( tk->fmt.i_cat == SPU_ES )
00662 {
00663 if( tk->fmt.i_codec == VLC_FOURCC( 's', 'u', 'b', 't' ) &&
00664 p_block->i_buffer >= 2 )
00665 {
00666 uint16_t i_size = GetWBE( p_block->p_buffer );
00667
00668 if( i_size + 2 <= p_block->i_buffer )
00669 {
00670 char *p;
00671
00672 memmove( &p_block->p_buffer[0],
00673 &p_block->p_buffer[2], i_size );
00674 p_block->p_buffer[i_size] = '\0';
00675 p_block->i_buffer = i_size + 1;
00676
00677
00678 while( ( p = strchr( p_block->p_buffer, '\r' ) ) )
00679 {
00680 *p = '\n';
00681 }
00682 }
00683 else
00684 {
00685
00686 p_block->i_buffer = 0;
00687 }
00688 }
00689 }
00690
00691 p_block->i_dts = MP4_TrackGetDTS( p_demux, tk ) + 1;
00692
00693 i_delta = MP4_TrackGetPTSDelta( p_demux, tk );
00694 if( i_delta != -1 )
00695 p_block->i_pts = p_block->i_dts + i_delta;
00696 else if( tk->fmt.i_cat != VIDEO_ES )
00697 p_block->i_pts = p_block->i_dts;
00698 else
00699 p_block->i_pts = 0;
00700
00701 if( !tk->b_drms || ( tk->b_drms && tk->p_drms ) )
00702 es_out_Send( p_demux->out, tk->p_es, p_block );
00703 }
00704
00705
00706 if( MP4_TrackNextSample( p_demux, tk ) )
00707 {
00708 break;
00709 }
00710 }
00711 }
00712
00713 return 1;
00714 }
00715
00716
00717
00718 static int Seek( demux_t *p_demux, mtime_t i_date )
00719 {
00720 demux_sys_t *p_sys = p_demux->p_sys;
00721 unsigned int i_track;
00722
00723
00724 p_sys->i_time = i_date * p_sys->i_timescale / 1000000;
00725 p_sys->i_pcr = i_date;
00726
00727
00728 for( i_track = 0; i_track < p_sys->i_tracks; i_track++ )
00729 {
00730 mp4_track_t *tk = &p_sys->track[i_track];
00731 MP4_TrackSeek( p_demux, tk, i_date );
00732 }
00733 return VLC_SUCCESS;
00734 }
00735
00736
00737
00738
00739 static int Control( demux_t *p_demux, int i_query, va_list args )
00740 {
00741 demux_sys_t *p_sys = p_demux->p_sys;
00742
00743 double f, *pf;
00744 int64_t i64, *pi64;
00745
00746 switch( i_query )
00747 {
00748 case DEMUX_GET_POSITION:
00749 pf = (double*)va_arg( args, double * );
00750 if( p_sys->i_duration > 0 )
00751 {
00752 *pf = (double)p_sys->i_time / (double)p_sys->i_duration;
00753 }
00754 else
00755 {
00756 *pf = 0.0;
00757 }
00758 return VLC_SUCCESS;
00759
00760 case DEMUX_SET_POSITION:
00761 f = (double)va_arg( args, double );
00762 if( p_sys->i_timescale > 0 )
00763 {
00764 i64 = (int64_t)( f * (double)1000000 *
00765 (double)p_sys->i_duration /
00766 (double)p_sys->i_timescale );
00767 return Seek( p_demux, i64 );
00768 }
00769 else return VLC_SUCCESS;
00770
00771 case DEMUX_GET_TIME:
00772 pi64 = (int64_t*)va_arg( args, int64_t * );
00773 if( p_sys->i_timescale > 0 )
00774 {
00775 *pi64 = (mtime_t)1000000 *
00776 (mtime_t)p_sys->i_time /
00777 (mtime_t)p_sys->i_timescale;
00778 }
00779 else *pi64 = 0;
00780 return VLC_SUCCESS;
00781
00782 case DEMUX_SET_TIME:
00783 i64 = (int64_t)va_arg( args, int64_t );
00784 return Seek( p_demux, i64 );
00785
00786 case DEMUX_GET_LENGTH:
00787 pi64 = (int64_t*)va_arg( args, int64_t * );
00788 if( p_sys->i_timescale > 0 )
00789 {
00790 *pi64 = (mtime_t)1000000 *
00791 (mtime_t)p_sys->i_duration /
00792 (mtime_t)p_sys->i_timescale;
00793 }
00794 else *pi64 = 0;
00795 return VLC_SUCCESS;
00796
00797 case DEMUX_GET_FPS:
00798 msg_Warn( p_demux, "DEMUX_GET_FPS unimplemented !!" );
00799 return VLC_EGENERIC;
00800
00801 case DEMUX_GET_META:
00802 {
00803 vlc_meta_t **pp_meta = (vlc_meta_t**)va_arg( args, vlc_meta_t** );
00804 vlc_meta_t *meta;
00805 MP4_Box_t *p_udta = MP4_BoxGet( p_sys->p_root, "/moov/udta" );
00806 MP4_Box_t *p_0xa9xxx;
00807 if( p_udta == NULL )
00808 {
00809 return VLC_EGENERIC;
00810 }
00811 *pp_meta = meta = vlc_meta_New();
00812 for( p_0xa9xxx = p_udta->p_first; p_0xa9xxx != NULL;
00813 p_0xa9xxx = p_0xa9xxx->p_next )
00814 {
00815 switch( p_0xa9xxx->i_type )
00816 {
00817 case FOURCC_0xa9nam:
00818 vlc_meta_Add( meta, VLC_META_TITLE,
00819 p_0xa9xxx->data.p_0xa9xxx->psz_text );
00820 break;
00821 case FOURCC_0xa9aut:
00822 vlc_meta_Add( meta, VLC_META_AUTHOR,
00823 p_0xa9xxx->data.p_0xa9xxx->psz_text );
00824 break;
00825 case FOURCC_0xa9ART:
00826 vlc_meta_Add( meta, VLC_META_ARTIST,
00827 p_0xa9xxx->data.p_0xa9xxx->psz_text );
00828 break;
00829 case FOURCC_0xa9cpy:
00830 vlc_meta_Add( meta, VLC_META_COPYRIGHT,
00831 p_0xa9xxx->data.p_0xa9xxx->psz_text );
00832 break;
00833 case FOURCC_0xa9day:
00834 vlc_meta_Add( meta, VLC_META_DATE,
00835 p_0xa9xxx->data.p_0xa9xxx->psz_text );
00836 break;
00837 case FOURCC_0xa9des:
00838 vlc_meta_Add( meta, VLC_META_DESCRIPTION,
00839 p_0xa9xxx->data.p_0xa9xxx->psz_text );
00840 break;
00841 case FOURCC_0xa9gen:
00842 vlc_meta_Add( meta, VLC_META_GENRE,
00843 p_0xa9xxx->data.p_0xa9xxx->psz_text );
00844 break;
00845
00846 case FOURCC_0xa9swr:
00847 case FOURCC_0xa9inf:
00848 case FOURCC_0xa9alb:
00849 case FOURCC_0xa9dir:
00850 case FOURCC_0xa9dis:
00851 case FOURCC_0xa9enc:
00852 case FOURCC_0xa9trk:
00853 case FOURCC_0xa9cmt:
00854 case FOURCC_0xa9url:
00855 case FOURCC_0xa9req:
00856 case FOURCC_0xa9fmt:
00857 case FOURCC_0xa9dsa:
00858 case FOURCC_0xa9hst:
00859 case FOURCC_0xa9prd:
00860 case FOURCC_0xa9prf:
00861 case FOURCC_0xa9ope:
00862 case FOURCC_0xa9src:
00863 case FOURCC_0xa9wrt:
00864 case FOURCC_0xa9com:
00865 case FOURCC_WLOC:
00866
00867 break;
00868
00869 default:
00870 break;
00871 }
00872 }
00873 return VLC_SUCCESS;
00874 }
00875
00876 case DEMUX_GET_TITLE_INFO:
00877 case DEMUX_SET_NEXT_DEMUX_TIME:
00878 case DEMUX_SET_GROUP:
00879 return VLC_EGENERIC;
00880
00881 default:
00882 msg_Warn( p_demux, "control query unimplemented !!!" );
00883 return VLC_EGENERIC;
00884 }
00885 }
00886
00887
00888
00889
00890 static void Close ( vlc_object_t * p_this )
00891 {
00892 unsigned int i_track;
00893 demux_t * p_demux = (demux_t *)p_this;
00894 demux_sys_t *p_sys = p_demux->p_sys;
00895
00896 msg_Dbg( p_demux, "freeing all memory" );
00897
00898 MP4_BoxFree( p_demux->s, p_sys->p_root );
00899 for( i_track = 0; i_track < p_sys->i_tracks; i_track++ )
00900 {
00901 MP4_TrackDestroy( p_demux, &p_sys->track[i_track] );
00902 }
00903 FREE( p_sys->track );
00904
00905 free( p_sys );
00906 }
00907
00908
00909
00910
00911
00912
00913
00914
00915 static int TrackCreateChunksIndex( demux_t *p_demux,
00916 mp4_track_t *p_demux_track )
00917 {
00918 MP4_Box_t *p_co64;
00919 MP4_Box_t *p_stsc;
00920
00921 unsigned int i_chunk;
00922 unsigned int i_index, i_last;
00923
00924 if( ( !(p_co64 = MP4_BoxGet( p_demux_track->p_stbl, "stco" ) )&&
00925 !(p_co64 = MP4_BoxGet( p_demux_track->p_stbl, "co64" ) ) )||
00926 ( !(p_stsc = MP4_BoxGet( p_demux_track->p_stbl, "stsc" ) ) ))
00927 {
00928 return( VLC_EGENERIC );
00929 }
00930
00931 p_demux_track->i_chunk_count = p_co64->data.p_co64->i_entry_count;
00932 if( !p_demux_track->i_chunk_count )
00933 {
00934 msg_Warn( p_demux, "no chunk defined" );
00935 return( VLC_EGENERIC );
00936 }
00937 p_demux_track->chunk = calloc( p_demux_track->i_chunk_count,
00938 sizeof( mp4_chunk_t ) );
00939
00940
00941 for( i_chunk = 0; i_chunk < p_demux_track->i_chunk_count; i_chunk++ )
00942 {
00943 mp4_chunk_t *ck = &p_demux_track->chunk[i_chunk];
00944
00945 ck->i_offset = p_co64->data.p_co64->i_chunk_offset[i_chunk];
00946
00947 ck->i_first_dts = 0;
00948 ck->p_sample_count_dts = NULL;
00949 ck->p_sample_delta_dts = NULL;
00950 ck->p_sample_count_pts = NULL;
00951 ck->p_sample_offset_pts = NULL;
00952 }
00953
00954
00955
00956
00957 i_last = p_demux_track->i_chunk_count;
00958 i_index = p_stsc->data.p_stsc->i_entry_count;
00959 if( !i_index )
00960 {
00961 msg_Warn( p_demux, "cannot read chunk table or table empty" );
00962 return( VLC_EGENERIC );
00963 }
00964
00965 while( i_index-- )
00966 {
00967 for( i_chunk = p_stsc->data.p_stsc->i_first_chunk[i_index] - 1;
00968 i_chunk < i_last; i_chunk++ )
00969 {
00970 p_demux_track->chunk[i_chunk].i_sample_description_index =
00971 p_stsc->data.p_stsc->i_sample_description_index[i_index];
00972 p_demux_track->chunk[i_chunk].i_sample_count =
00973 p_stsc->data.p_stsc->i_samples_per_chunk[i_index];
00974 }
00975 i_last = p_stsc->data.p_stsc->i_first_chunk[i_index] - 1;
00976 }
00977
00978 p_demux_track->chunk[0].i_sample_first = 0;
00979 for( i_chunk = 1; i_chunk < p_demux_track->i_chunk_count; i_chunk++ )
00980 {
00981 p_demux_track->chunk[i_chunk].i_sample_first =
00982 p_demux_track->chunk[i_chunk-1].i_sample_first +
00983 p_demux_track->chunk[i_chunk-1].i_sample_count;
00984 }
00985
00986 msg_Dbg( p_demux, "track[Id 0x%x] read %d chunk",
00987 p_demux_track->i_track_ID, p_demux_track->i_chunk_count );
00988
00989 return VLC_SUCCESS;
00990 }
00991
00992 static int TrackCreateSamplesIndex( demux_t *p_demux,
00993 mp4_track_t *p_demux_track )
00994 {
00995 MP4_Box_t *p_box;
00996 MP4_Box_data_stsz_t *stsz;
00997 MP4_Box_data_stts_t *stts;
00998
00999
01000 int64_t i_sample;
01001 int64_t i_chunk;
01002
01003 int64_t i_index;
01004 int64_t i_index_sample_used;
01005
01006 int64_t i_last_dts;
01007
01008
01009
01010
01011 p_box = MP4_BoxGet( p_demux_track->p_stbl, "stsz" );
01012 if( !p_box )
01013 {
01014
01015 msg_Warn( p_demux, "cannot find STSZ box" );
01016 return VLC_EGENERIC;
01017 }
01018 stsz = p_box->data.p_stsz;
01019
01020
01021
01022
01023 p_box = MP4_BoxGet( p_demux_track->p_stbl, "stts" );
01024 if( !p_box )
01025 {
01026 msg_Warn( p_demux, "cannot find STTS box" );
01027 return VLC_EGENERIC;
01028 }
01029 stts = p_box->data.p_stts;
01030
01031
01032 p_demux_track->i_sample_count = stsz->i_sample_count;
01033 if( stsz->i_sample_size )
01034 {
01035
01036 p_demux_track->i_sample_size = stsz->i_sample_size;
01037 p_demux_track->p_sample_size = NULL;
01038 }
01039 else
01040 {
01041
01042 p_demux_track->i_sample_size = 0;
01043 p_demux_track->p_sample_size =
01044 calloc( p_demux_track->i_sample_count, sizeof( uint32_t ) );
01045
01046 for( i_sample = 0; i_sample < p_demux_track->i_sample_count; i_sample++ )
01047 {
01048 p_demux_track->p_sample_size[i_sample] =
01049 stsz->i_entry_size[i_sample];
01050 }
01051 }
01052
01053
01054
01055
01056
01057
01058
01059 i_last_dts = 0;
01060 i_index = 0; i_index_sample_used = 0;
01061 for( i_chunk = 0; i_chunk < p_demux_track->i_chunk_count; i_chunk++ )
01062 {
01063 mp4_chunk_t *ck = &p_demux_track->chunk[i_chunk];
01064 int64_t i_entry, i_sample_count, i;
01065
01066
01067 ck->i_first_dts = i_last_dts;
01068
01069
01070
01071 i_sample_count = ck->i_sample_count;
01072
01073 i_entry = 0;
01074 while( i_sample_count > 0 )
01075 {
01076 i_sample_count -= stts->i_sample_count[i_index+i_entry];
01077
01078 if( i_entry == 0 )
01079 i_sample_count += i_index_sample_used;
01080
01081 i_entry++;
01082 }
01083
01084
01085 ck->p_sample_count_dts = calloc( i_entry, sizeof( uint32_t ) );
01086 ck->p_sample_delta_dts = calloc( i_entry, sizeof( uint32_t ) );
01087
01088
01089 i_sample_count = ck->i_sample_count;
01090 for( i = 0; i < i_entry; i++ )
01091 {
01092 int64_t i_used;
01093 int64_t i_rest;
01094
01095 i_rest = stts->i_sample_count[i_index] - i_index_sample_used;
01096
01097 i_used = __MIN( i_rest, i_sample_count );
01098
01099 i_index_sample_used += i_used;
01100 i_sample_count -= i_used;
01101
01102 ck->p_sample_count_dts[i] = i_used;
01103 ck->p_sample_delta_dts[i] = stts->i_sample_delta[i_index];
01104
01105 i_last_dts += i_used * ck->p_sample_delta_dts[i];
01106
01107 if( i_index_sample_used >= stts->i_sample_count[i_index] )
01108 {
01109 i_index++;
01110 i_index_sample_used = 0;
01111 }
01112 }
01113 }
01114
01115
01116
01117
01118 p_box = MP4_BoxGet( p_demux_track->p_stbl, "ctts" );
01119 if( p_box )
01120 {
01121 MP4_Box_data_ctts_t *ctts = p_box->data.p_ctts;
01122
01123 msg_Warn( p_demux, "CTTS table" );
01124
01125
01126 i_index = 0; i_index_sample_used = 0;
01127 for( i_chunk = 0; i_chunk < p_demux_track->i_chunk_count; i_chunk++ )
01128 {
01129 mp4_chunk_t *ck = &p_demux_track->chunk[i_chunk];
01130 int64_t i_entry, i_sample_count, i;
01131
01132
01133
01134 i_sample_count = ck->i_sample_count;
01135
01136 i_entry = 0;
01137 while( i_sample_count > 0 )
01138 {
01139 i_sample_count -= ctts->i_sample_count[i_index+i_entry];
01140
01141
01142 if( i_entry == 0 )
01143 i_sample_count += i_index_sample_used;
01144
01145 i_entry++;
01146 }
01147
01148
01149 ck->p_sample_count_pts = calloc( i_entry, sizeof( uint32_t ) );
01150 ck->p_sample_offset_pts = calloc( i_entry, sizeof( int32_t ) );
01151
01152
01153 i_sample_count = ck->i_sample_count;
01154 for( i = 0; i < i_entry; i++ )
01155 {
01156 int64_t i_used;
01157 int64_t i_rest;
01158
01159 i_rest = ctts->i_sample_count[i_index] -
01160 i_index_sample_used;
01161
01162 i_used = __MIN( i_rest, i_sample_count );
01163
01164 i_index_sample_used += i_used;
01165 i_sample_count -= i_used;
01166
01167 ck->p_sample_count_pts[i] = i_used;
01168 ck->p_sample_offset_pts[i] = ctts->i_sample_offset[i_index];
01169
01170 if( i_index_sample_used >= ctts->i_sample_count[i_index] )
01171 {
01172 i_index++;
01173 i_index_sample_used = 0;
01174 }
01175 }
01176 }
01177 }
01178
01179 msg_Dbg( p_demux, "track[Id 0x%x] read %d samples length:"I64Fd"s",
01180 p_demux_track->i_track_ID, p_demux_track->i_sample_count,
01181 i_last_dts / p_demux_track->i_timescale );
01182
01183 return VLC_SUCCESS;
01184 }
01185
01186
01187
01188
01189
01190 static int TrackCreateES( demux_t *p_demux, mp4_track_t *p_track,
01191 unsigned int i_chunk, es_out_id_t **pp_es )
01192 {
01193 MP4_Box_t *p_sample;
01194 MP4_Box_t *p_esds;
01195 MP4_Box_t *p_box;
01196
01197 *pp_es = NULL;
01198
01199 if( !p_track->chunk[i_chunk].i_sample_description_index )
01200 {
01201 msg_Warn( p_demux, "invalid SampleEntry index (track[Id 0x%x])",
01202 p_track->i_track_ID );
01203 return VLC_EGENERIC;
01204 }
01205
01206 p_sample = MP4_BoxGet( p_track->p_stsd, "[%d]",
01207 p_track->chunk[i_chunk].i_sample_description_index - 1 );
01208
01209 if( !p_sample ||
01210 ( !p_sample->data.p_data && p_track->fmt.i_cat != SPU_ES ) )
01211 {
01212 msg_Warn( p_demux, "cannot find SampleEntry (track[Id 0x%x])",
01213 p_track->i_track_ID );
01214 return VLC_EGENERIC;
01215 }
01216
01217 p_track->p_sample = p_sample;
01218
01219 if( p_track->fmt.i_cat == AUDIO_ES && p_track->i_sample_size == 1 )
01220 {
01221 MP4_Box_data_sample_soun_t *p_soun;
01222
01223 p_soun = p_sample->data.p_sample_soun;
01224
01225 if( p_soun->i_qt_version == 0 )
01226 {
01227 switch( p_sample->i_type )
01228 {
01229 case VLC_FOURCC( 'i', 'm', 'a', '4' ):
01230 p_soun->i_qt_version = 1;
01231 p_soun->i_sample_per_packet = 64;
01232 p_soun->i_bytes_per_packet = 34;
01233 p_soun->i_bytes_per_frame = 34 * p_soun->i_channelcount;
01234 p_soun->i_bytes_per_sample = 2;
01235 break;
01236 case VLC_FOURCC( 'M', 'A', 'C', '3' ):
01237 p_soun->i_qt_version = 1;
01238 p_soun->i_sample_per_packet = 6;
01239 p_soun->i_bytes_per_packet = 2;
01240 p_soun->i_bytes_per_frame = 2 * p_soun->i_channelcount;
01241 p_soun->i_bytes_per_sample = 2;
01242 break;
01243 case VLC_FOURCC( 'M', 'A', 'C', '6' ):
01244 p_soun->i_qt_version = 1;
01245 p_soun->i_sample_per_packet = 12;
01246 p_soun->i_bytes_per_packet = 2;
01247 p_soun->i_bytes_per_frame = 2 * p_soun->i_channelcount;
01248 p_soun->i_bytes_per_sample = 2;
01249 break;
01250 case VLC_FOURCC( 'a', 'l', 'a', 'w' ):
01251 case VLC_FOURCC( 'u', 'l', 'a', 'w' ):
01252 p_soun->i_samplesize = 8;
01253 break;
01254 default:
01255 break;
01256 }
01257
01258 }
01259 else if( p_soun->i_qt_version == 1 && p_soun->i_sample_per_packet <= 0 )
01260 {
01261 p_soun->i_qt_version = 0;
01262 }
01263 }
01264
01265
01266
01267 switch( p_sample->i_type )
01268 {
01269 case( VLC_FOURCC( '.', 'm', 'p', '3' ) ):
01270 case( VLC_FOURCC( 'm', 's', 0x00, 0x55 ) ):
01271 p_track->fmt.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'a' );
01272 break;
01273
01274 case( VLC_FOURCC( 'r', 'a', 'w', ' ' ) ):
01275 p_track->fmt.i_codec = VLC_FOURCC( 'a', 'r', 'a', 'w' );
01276
01277
01278 if( p_sample->data.p_sample_soun && (p_track->i_timescale !=
01279 p_sample->data.p_sample_soun->i_sampleratehi) )
01280 {
01281 MP4_Box_data_sample_soun_t *p_soun =
01282 p_sample->data.p_sample_soun;
01283
01284 msg_Warn( p_demux, "i_timescale ("I64Fu") != i_sampleratehi "
01285 "(%u), making both equal (report any problem).",
01286 p_track->i_timescale, p_soun->i_sampleratehi );
01287
01288 if( p_soun->i_sampleratehi )
01289 p_track->i_timescale = p_soun->i_sampleratehi;
01290 else
01291 p_soun->i_sampleratehi = p_track->i_timescale;
01292 }
01293 break;
01294
01295 case( VLC_FOURCC( 's', '2', '6', '3' ) ):
01296 p_track->fmt.i_codec = VLC_FOURCC( 'h', '2', '6', '3' );
01297 break;
01298
01299 case( VLC_FOURCC( 't', 'e', 'x', 't' ) ):
01300 case( VLC_FOURCC( 't', 'x', '3', 'g' ) ):
01301 p_track->fmt.i_codec = VLC_FOURCC( 's', 'u', 'b', 't' );
01302
01303
01304
01305 break;
01306
01307 default:
01308 p_track->fmt.i_codec = p_sample->i_type;
01309 break;
01310 }
01311
01312
01313
01314 #define p_decconfig p_esds->data.p_esds->es_descriptor.p_decConfigDescr
01315 if( ( ( p_esds = MP4_BoxGet( p_sample, "esds" ) ) ||
01316 ( p_esds = MP4_BoxGet( p_sample, "wave/esds" ) ) )&&
01317 ( p_esds->data.p_esds )&&
01318 ( p_decconfig ) )
01319 {
01320
01321 switch( p_decconfig->i_objectTypeIndication )
01322 {
01323 case( 0x20 ):
01324 p_track->fmt.i_codec = VLC_FOURCC( 'm','p','4','v' );
01325 break;
01326 case( 0x40):
01327 p_track->fmt.i_codec = VLC_FOURCC( 'm','p','4','a' );
01328 break;
01329 case( 0x60):
01330 case( 0x61):
01331 case( 0x62):
01332 case( 0x63):
01333 case( 0x64):
01334 case( 0x65):
01335 p_track->fmt.i_codec = VLC_FOURCC( 'm','p','g','v' );
01336 break;
01337
01338 case( 0x66):
01339 case( 0x67):
01340 case( 0x68):
01341 p_track->fmt.i_codec = VLC_FOURCC( 'm','p','4','a' );
01342 break;
01343
01344 case( 0x69):
01345 p_track->fmt.i_codec = VLC_FOURCC( 'm','p','g','a' );
01346 break;
01347 case( 0x6a):
01348 p_track->fmt.i_codec = VLC_FOURCC( 'm','p','g','v' );
01349 break;
01350 case( 0x6b):
01351 p_track->fmt.i_codec = VLC_FOURCC( 'm','p','g','a' );
01352 break;
01353 case( 0x6c ):
01354 p_track->fmt.i_codec = VLC_FOURCC( 'j','p','e','g' );
01355 break;
01356
01357
01358 case( 0xe0 ):
01359 if( p_track->fmt.i_cat == SPU_ES )
01360 {
01361 p_track->fmt.i_codec = VLC_FOURCC( 's','p','u',' ' );
01362 break;
01363 }
01364
01365 default:
01366
01367 msg_Warn( p_demux,
01368 "unknown objectTypeIndication(0x%x) (Track[ID 0x%x])",
01369 p_decconfig->i_objectTypeIndication,
01370 p_track->i_track_ID );
01371 break;
01372 }
01373 p_track->fmt.i_extra = p_decconfig->i_decoder_specific_info_len;
01374 if( p_track->fmt.i_extra > 0 )
01375 {
01376 p_track->fmt.p_extra = malloc( p_track->fmt.i_extra );
01377 memcpy( p_track->fmt.p_extra, p_decconfig->p_decoder_specific_info,
01378 p_track->fmt.i_extra );
01379 }
01380 }
01381 else
01382 {
01383 switch( p_sample->i_type )
01384 {
01385
01386 case VLC_FOURCC( 'S', 'V', 'Q', '3' ):
01387 case VLC_FOURCC( 'S', 'V', 'Q', '1' ):
01388 case VLC_FOURCC( 'V', 'P', '3', '1' ):
01389 case VLC_FOURCC( '3', 'I', 'V', '1' ):
01390 case VLC_FOURCC( 'Z', 'y', 'G', 'o' ):
01391 p_track->fmt.i_extra =
01392 p_sample->data.p_sample_vide->i_qt_image_description;
01393 if( p_track->fmt.i_extra > 0 )
01394 {
01395 p_track->fmt.p_extra = malloc( p_track->fmt.i_extra );
01396 memcpy( p_track->fmt.p_extra,
01397 p_sample->data.p_sample_vide->p_qt_image_description,
01398 p_track->fmt.i_extra);
01399 }
01400 break;
01401 case VLC_FOURCC( 'Q', 'D', 'M', 'C' ):
01402 case VLC_FOURCC( 'Q', 'D', 'M', '2' ):
01403 case VLC_FOURCC( 'Q', 'c', 'l', 'p' ):
01404 case VLC_FOURCC( 's', 'a', 'm', 'r' ):
01405 case VLC_FOURCC( 'a', 'l', 'a', 'c' ):
01406 p_track->fmt.i_extra =
01407 p_sample->data.p_sample_soun->i_qt_description;
01408 if( p_track->fmt.i_extra > 0 )
01409 {
01410 p_track->fmt.p_extra = malloc( p_track->fmt.i_extra );
01411 memcpy( p_track->fmt.p_extra,
01412 p_sample->data.p_sample_soun->p_qt_description,
01413 p_track->fmt.i_extra);
01414 }
01415 break;
01416
01417
01418 case VLC_FOURCC( 'a', 'v', 'c', '1' ):
01419 {
01420 MP4_Box_t *p_avcC = MP4_BoxGet( p_sample, "avcC" );
01421
01422 if( p_avcC )
01423 {
01424 p_track->fmt.i_extra = p_avcC->data.p_avcC->i_avcC;
01425 p_track->fmt.p_extra = malloc( p_avcC->data.p_avcC->i_avcC );
01426 memcpy( p_track->fmt.p_extra, p_avcC->data.p_avcC->p_avcC,
01427 p_track->fmt.i_extra );
01428 }
01429 else
01430 {
01431 msg_Err( p_demux, "missing avcC" );
01432 }
01433 break;
01434 }
01435
01436 default:
01437 break;
01438 }
01439 }
01440
01441 #undef p_decconfig
01442
01443
01444 switch( p_track->fmt.i_cat )
01445 {
01446 case( VIDEO_ES ):
01447 p_track->fmt.video.i_width = p_sample->data.p_sample_vide->i_width;
01448 p_track->fmt.video.i_height = p_sample->data.p_sample_vide->i_height;
01449 p_track->fmt.video.i_bits_per_pixel =
01450 p_sample->data.p_sample_vide->i_depth;
01451
01452
01453 if( p_track->fmt.video.i_width <= 0 )
01454 p_track->fmt.video.i_width = p_track->i_width;
01455 if( p_track->fmt.video.i_height <= 0 )
01456 p_track->fmt.video.i_height = p_track->i_height;
01457
01458
01459 if( p_track->i_width > 0 && p_track->i_height > 0 &&
01460
01461 p_sample->data.p_sample_vide->i_width != p_track->i_width )
01462 p_track->fmt.video.i_aspect =
01463 VOUT_ASPECT_FACTOR * p_track->i_width / p_track->i_height;
01464
01465
01466 p_track->fmt.video.i_frame_rate = p_track->i_timescale;
01467 p_track->fmt.video.i_frame_rate_base = 1;
01468
01469 if( p_track->fmt.video.i_frame_rate &&
01470 (p_box = MP4_BoxGet( p_track->p_stbl, "stts" )) &&
01471 p_box->data.p_stts->i_entry_count >= 1 )
01472 {
01473 p_track->fmt.video.i_frame_rate_base =
01474 p_box->data.p_stts->i_sample_delta[0];
01475 }
01476
01477 break;
01478
01479 case( AUDIO_ES ):
01480 p_track->fmt.audio.i_channels =
01481 p_sample->data.p_sample_soun->i_channelcount;
01482 p_track->fmt.audio.i_rate =
01483 p_sample->data.p_sample_soun->i_sampleratehi;
01484 p_track->fmt.i_bitrate = p_sample->data.p_sample_soun->i_channelcount *
01485 p_sample->data.p_sample_soun->i_sampleratehi *
01486 p_sample->data.p_sample_soun->i_samplesize;
01487 p_track->fmt.audio.i_bitspersample =
01488 p_sample->data.p_sample_soun->i_samplesize;
01489 break;
01490
01491 default:
01492 break;
01493 }
01494
01495 *pp_es = es_out_Add( p_demux->out, &p_track->fmt );
01496
01497 return VLC_SUCCESS;
01498 }
01499
01500
01501
01502
01503 static int TrackTimeToSampleChunk( demux_t *p_demux, mp4_track_t *p_track,
01504 int64_t i_start, uint32_t *pi_chunk,
01505 uint32_t *pi_sample )
01506 {
01507 demux_sys_t *p_sys = p_demux->p_sys;
01508 MP4_Box_t *p_stss;
01509 uint64_t i_dts;
01510 unsigned int i_sample;
01511 unsigned int i_chunk;
01512 int i_index;
01513
01514
01515 if( !p_track->b_ok || p_track->i_chunk_count == 0 )
01516 {
01517 return( VLC_EGENERIC );
01518 }
01519
01520
01521 MP4_TrackSetELST( p_demux, p_track, i_start );
01522 if( p_track->p_elst && p_track->p_elst->data.p_elst->i_entry_count > 0 )
01523 {
01524 MP4_Box_data_elst_t *elst = p_track->p_elst->data.p_elst;
01525 int64_t i_mvt= i_start * p_sys->i_timescale / (int64_t)1000000;
01526
01527
01528
01529 i_start -= p_track->i_elst_time * I64C(1000000) / p_sys->i_timescale;
01530 if( i_start < 0 )
01531 {
01532 *pi_chunk = 0;
01533 *pi_sample= 0;
01534
01535 return VLC_SUCCESS;
01536 }
01537
01538 i_start = i_start * p_track->i_timescale / (int64_t)1000000;
01539
01540 if( ( elst->i_media_rate_integer[p_track->i_elst] > 0 ||
01541 elst->i_media_rate_fraction[p_track->i_elst] > 0 ) &&
01542 elst->i_media_time[p_track->i_elst] > 0 )
01543 {
01544 i_start += elst->i_media_time[p_track->i_elst];
01545 }
01546
01547 msg_Dbg( p_demux, "elst (%d) gives "I64Fd"ms (movie)-> "I64Fd
01548 "ms (track)", p_track->i_elst,
01549 i_mvt * 1000 / p_sys->i_timescale,
01550 i_start * 1000 / p_track->i_timescale );
01551 }
01552 else
01553 {
01554
01555 i_start = i_start * p_track->i_timescale / (int64_t)1000000;
01556 }
01557
01558
01559
01560 for( i_chunk = 0; ; i_chunk++ )
01561 {
01562 if( i_chunk + 1 >= p_track->i_chunk_count )
01563 {
01564
01565
01566 i_chunk = p_track->i_chunk_count - 1;
01567 break;
01568 }
01569
01570 if( (uint64_t)i_start >= p_track->chunk[i_chunk].i_first_dts &&
01571 (uint64_t)i_start < p_track->chunk[i_chunk + 1].i_first_dts )
01572 {
01573 break;
01574 }
01575 }
01576
01577
01578 i_sample = p_track->chunk[i_chunk].i_sample_first;
01579 i_dts = p_track->chunk[i_chunk].i_first_dts;
01580 for( i_index = 0; i_sample < p_track->chunk[i_chunk].i_sample_count; )
01581 {
01582 if( i_dts +
01583 p_track->chunk[i_chunk].p_sample_count_dts[i_index] *
01584 p_track->chunk[i_chunk].p_sample_delta_dts[i_index] < (uint64_t)i_start )
01585 {
01586 i_dts +=
01587 p_track->chunk[i_chunk].p_sample_count_dts[i_index] *
01588 p_track->chunk[i_chunk].p_sample_delta_dts[i_index];
01589
01590 i_sample += p_track->chunk[i_chunk].p_sample_count_dts[i_index];
01591 i_index++;
01592 }
01593 else
01594 {
01595 if( p_track->chunk[i_chunk].p_sample_delta_dts[i_index] <= 0 )
01596 {
01597 break;
01598 }
01599 i_sample += ( i_start - i_dts ) /
01600 p_track->chunk[i_chunk].p_sample_delta_dts[i_index];
01601 break;
01602 }
01603 }
01604
01605 if( i_sample >= p_track->i_sample_count )
01606 {
01607 msg_Warn( p_demux, "track[Id 0x%x] will be disabled "
01608 "(seeking too far) chunk=%d sample=%d",
01609 p_track->i_track_ID, i_chunk, i_sample );
01610 return( VLC_EGENERIC );
01611 }
01612
01613
01614
01615 if( ( p_stss = MP4_BoxGet( p_track->p_stbl, "stss" ) ) )
01616 {
01617 unsigned int i_index;
01618 msg_Dbg( p_demux,
01619 "track[Id 0x%x] using Sync Sample Box (stss)",
01620 p_track->i_track_ID );
01621 for( i_index = 0; i_index < p_stss->data.p_stss->i_entry_count; i_index++ )
01622 {
01623 if( p_stss->data.p_stss->i_sample_number[i_index] >= i_sample )
01624 {
01625 if( i_index > 0 )
01626 {
01627 msg_Dbg( p_demux, "stts gives %d --> %d (sample number)",
01628 i_sample,
01629 p_stss->data.p_stss->i_sample_number[i_index-1] );
01630 i_sample = p_stss->data.p_stss->i_sample_number[i_index-1];
01631
01632 while( i_chunk > 0 &&
01633 i_sample < p_track->chunk[i_chunk].i_sample_first )
01634 {
01635 i_chunk--;
01636 }
01637 }
01638 else
01639 {
01640 msg_Dbg( p_demux, "stts gives %d --> %d (sample number)",
01641 i_sample,
01642 p_stss->data.p_stss->i_sample_number[i_index] );
01643 i_sample = p_stss->data.p_stss->i_sample_number[i_index];
01644
01645 while( i_chunk < p_track->i_chunk_count - 1 &&
01646 i_sample >= p_track->chunk[i_chunk].i_sample_first +
01647 p_track->chunk[i_chunk].i_sample_count )
01648 {
01649 i_chunk++;
01650 }
01651 }
01652 break;
01653 }
01654 }
01655 }
01656 else
01657 {
01658 msg_Dbg( p_demux, "track[Id 0x%x] does not provide Sync "
01659 "Sample Box (stss)", p_track->i_track_ID );
01660 }
01661
01662 *pi_chunk = i_chunk;
01663 *pi_sample = i_sample;
01664
01665 return VLC_SUCCESS;
01666 }
01667
01668 static int TrackGotoChunkSample( demux_t *p_demux, mp4_track_t *p_track,
01669 unsigned int i_chunk, unsigned int i_sample )
01670 {
01671 vlc_bool_t b_reselect = VLC_FALSE;
01672
01673
01674 if( p_track->i_chunk < 0 ||
01675 p_track->i_chunk >= p_track->i_chunk_count - 1 ||
01676 p_track->chunk[p_track->i_chunk].i_sample_description_index !=
01677 p_track->chunk[i_chunk].i_sample_description_index )
01678 {
01679 msg_Warn( p_demux, "recreate ES for track[Id 0x%x]",
01680 p_track->i_track_ID );
01681
01682 es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE,
01683 p_track->p_es, &b_reselect );
01684
01685 es_out_Del( p_demux->out, p_track->p_es );
01686
01687 p_track->p_es = NULL;
01688
01689 if( TrackCreateES( p_demux, p_track, i_chunk, &p_track->p_es ) )
01690 {
01691 msg_Err( p_demux, "cannot create es for track[Id 0x%x]",
01692 p_track->i_track_ID );
01693
01694 p_track->b_ok = VLC_FALSE;
01695 p_track->b_selected = VLC_FALSE;
01696 return VLC_EGENERIC;
01697 }
01698 }
01699
01700
01701 if( b_reselect )
01702 {
01703 es_out_Control( p_demux->out, ES_OUT_SET_ES, p_track->p_es );
01704 }
01705
01706 p_track->i_chunk = i_chunk;
01707 p_track->i_sample = i_sample;
01708
01709 return p_track->b_selected ? VLC_SUCCESS : VLC_EGENERIC;
01710 }
01711
01712
01713
01714
01715
01716
01717
01718 static void MP4_TrackCreate( demux_t *p_demux, mp4_track_t *p_track,
01719 MP4_Box_t *p_box_trak )
01720 {
01721 demux_sys_t *p_sys = p_demux->p_sys;
01722
01723 MP4_Box_t *p_tkhd = MP4_BoxGet( p_box_trak, "tkhd" );
01724 MP4_Box_t *p_tref = MP4_BoxGet( p_box_trak, "tref" );
01725 MP4_Box_t *p_elst;
01726
01727 MP4_Box_t *p_mdhd;
01728 MP4_Box_t *p_udta;
01729 MP4_Box_t *p_hdlr;
01730
01731 MP4_Box_t *p_vmhd;
01732 MP4_Box_t *p_smhd;
01733
01734 MP4_Box_t *p_drms;
01735
01736 unsigned int i;
01737 char language[4];
01738
01739
01740
01741
01742 p_track->b_ok = VLC_FALSE;
01743 p_track->b_enable = VLC_FALSE;
01744 p_track->b_selected = VLC_FALSE;
01745
01746 es_format_Init( &p_track->fmt, UNKNOWN_ES, 0 );
01747
01748 if( !p_tkhd )
01749 {
01750 return;
01751 }
01752
01753
01754 p_track->b_enable =
01755 ( ( p_tkhd->data.p_tkhd->i_flags&MP4_TRACK_ENABLED ) != 0 );
01756
01757 p_track->i_track_ID = p_tkhd->data.p_tkhd->i_track_ID;
01758 p_track->i_width = p_tkhd->data.p_tkhd->i_width / 65536;
01759 p_track->i_height = p_tkhd->data.p_tkhd->i_height / 65536;
01760
01761 if( p_tref )
01762 {
01763
01764 }
01765
01766 p_mdhd = MP4_BoxGet( p_box_trak, "mdia/mdhd" );
01767 p_hdlr = MP4_BoxGet( p_box_trak, "mdia/hdlr" );
01768
01769 if( ( !p_mdhd )||( !p_hdlr ) )
01770 {
01771 return;
01772 }
01773
01774 p_track->i_timescale = p_mdhd->data.p_mdhd->i_timescale;
01775
01776 for( i = 0; i < 3; i++ )
01777 {
01778 language[i] = p_mdhd->data.p_mdhd->i_language[i];
01779 }
01780 language[3] = '\0';
01781
01782 switch( p_hdlr->data.p_hdlr->i_handler_type )
01783 {
01784 case( FOURCC_soun ):
01785 if( !( p_smhd = MP4_BoxGet( p_box_trak, "mdia/minf/smhd" ) ) )
01786 {
01787 return;
01788 }
01789 p_track->fmt.i_cat = AUDIO_ES;
01790 break;
01791
01792 case( FOURCC_vide ):
01793 if( !( p_vmhd = MP4_BoxGet( p_box_trak, "mdia/minf/vmhd" ) ) )
01794 {
01795 return;
01796 }
01797 p_track->fmt.i_cat = VIDEO_ES;
01798 break;
01799
01800 case( FOURCC_text ):
01801 case( FOURCC_subp ):
01802 case( FOURCC_tx3g ):
01803 p_track->fmt.i_cat = SPU_ES;
01804 break;
01805
01806 default:
01807 return;
01808 }
01809
01810 p_track->i_elst = 0;
01811 p_track->i_elst_time = 0;
01812 if( ( p_track->p_elst = p_elst = MP4_BoxGet( p_box_trak, "edts/elst" ) ) )
01813 {
01814 MP4_Box_data_elst_t *elst = p_elst->data.p_elst;
01815 unsigned int i;
01816
01817 msg_Warn( p_demux, "elst box found" );
01818 for( i = 0; i < elst->i_entry_count; i++ )
01819 {
01820 msg_Dbg( p_demux, " - [%d] duration="I64Fd"ms media time="I64Fd
01821 "ms) rate=%d.%d", i,
01822 elst->i_segment_duration[i] * 1000 / p_sys->i_timescale,
01823 elst->i_media_time[i] >= 0 ?
01824 (int64_t)(elst->i_media_time[i] * 1000 / p_track->i_timescale) :
01825 I64C(-1),
01826 elst->i_media_rate_integer[i],
01827 elst->i_media_rate_fraction[i] );
01828 }
01829 }
01830
01831
01832
01833
01834
01835
01836 if( !( p_track->p_stbl = MP4_BoxGet( p_box_trak,"mdia/minf/stbl" ) ) ||
01837 !( p_track->p_stsd = MP4_BoxGet( p_box_trak,"mdia/minf/stbl/stsd") ) )
01838 {
01839 return;
01840 }
01841
01842 p_drms = MP4_BoxGet( p_track->p_stsd, "drms" );
01843 p_track->b_drms = p_drms != NULL;
01844 p_track->p_drms = p_track->b_drms ?
01845 p_drms->data.p_sample_soun->p_drms : NULL;
01846
01847
01848 if( strcmp( language, "```" ) && strcmp( language, "und" ) )
01849 {
01850 p_track->fmt.psz_language = strdup( language );
01851 }
01852
01853 p_udta = MP4_BoxGet( p_box_trak, "udta" );
01854 if( p_udta )
01855 {
01856 MP4_Box_t *p_0xa9xxx;
01857 for( p_0xa9xxx = p_udta->p_first; p_0xa9xxx != NULL;
01858 p_0xa9xxx = p_0xa9xxx->p_next )
01859 {
01860 switch( p_0xa9xxx->i_type )
01861 {
01862 case FOURCC_0xa9nam:
01863 p_track->fmt.psz_description =
01864 strdup( p_0xa9xxx->data.p_0xa9xxx->psz_text );
01865 break;
01866 }
01867 }
01868 }
01869
01870
01871 if( TrackCreateChunksIndex( p_demux,p_track ) ||
01872 TrackCreateSamplesIndex( p_demux, p_track ) )
01873 {
01874 return;
01875 }
01876
01877 p_track->i_chunk = 0;
01878 p_track->i_sample = 0;
01879
01880
01881 if( TrackCreateES( p_demux,
01882 p_track, p_track->i_chunk,
01883 &p_track->p_es ) )
01884 {
01885 msg_Err( p_demux, "cannot create es for track[Id 0x%x]",
01886 p_track->i_track_ID );
01887 return;
01888 }
01889
01890 #if 0
01891 {
01892 int i;
01893 for( i = 0; i < p_track->i_chunk_count; i++ )
01894 {
01895 fprintf( stderr, "%-5d sample_count=%d pts=%lld\n",
01896 i, p_track->chunk[i].i_sample_count,
01897 p_track->chunk[i].i_first_dts );
01898
01899 }
01900 }
01901 #endif
01902 p_track->b_ok = VLC_TRUE;
01903 }
01904
01905
01906
01907
01908
01909
01910 static void MP4_TrackDestroy( demux_t *p_demux, mp4_track_t *p_track )
01911 {
01912 unsigned int i_chunk;
01913
01914 p_track->b_ok = VLC_FALSE;
01915 p_track->b_enable = VLC_FALSE;
01916 p_track->b_selected = VLC_FALSE;
01917
01918 es_format_Clean( &p_track->fmt );
01919
01920 for( i_chunk = 0; i_chunk < p_track->i_chunk_count; i_chunk++ )
01921 {
01922 if( p_track->chunk )
01923 {
01924 FREE(p_track->chunk[i_chunk].p_sample_count_dts);
01925 FREE(p_track->chunk[i_chunk].p_sample_delta_dts );
01926
01927 FREE(p_track->chunk[i_chunk].p_sample_count_pts);
01928 FREE(p_track->chunk[i_chunk].p_sample_offset_pts );
01929 }
01930 }
01931 FREE( p_track->chunk );
01932
01933 if( !p_track->i_sample_size )
01934 {
01935 FREE( p_track->p_sample_size );
01936 }
01937 }
01938
01939 static int MP4_TrackSelect( demux_t *p_demux, mp4_track_t *p_track,
01940 mtime_t i_start )
01941 {
01942 if( !p_track->b_ok )
01943 {
01944 return VLC_EGENERIC;
01945 }
01946
01947 if( p_track->b_selected )
01948 {
01949 msg_Warn( p_demux, "track[Id 0x%x] already selected",
01950 p_track->i_track_ID );
01951 return VLC_SUCCESS;
01952 }
01953
01954 return MP4_TrackSeek( p_demux, p_track, i_start );
01955 }
01956
01957 static void MP4_TrackUnselect( demux_t *p_demux, mp4_track_t *p_track )
01958 {
01959 if( !p_track->b_ok )
01960 {
01961 return;
01962 }
01963
01964 if( !p_track->b_selected )
01965 {
01966 msg_Warn( p_demux, "track[Id 0x%x] already unselected",
01967 p_track->i_track_ID );
01968 return;
01969 }
01970 if( p_track->p_es )
01971 {
01972 es_out_Control( p_demux->out, ES_OUT_SET_ES_STATE,
01973 p_track->p_es, VLC_FALSE );
01974 }
01975
01976 p_track->b_selected = VLC_FALSE;
01977 }
01978
01979 static int MP4_TrackSeek( demux_t *p_demux, mp4_track_t *p_track,
01980 mtime_t i_start )
01981 {
01982 uint32_t i_chunk;
01983 uint32_t i_sample;
01984
01985 if( !p_track->b_ok )
01986 {
01987 return( VLC_EGENERIC );
01988 }
01989
01990 p_track->b_selected = VLC_FALSE;
01991
01992 if( TrackTimeToSampleChunk( p_demux, p_track, i_start,
01993 &i_chunk, &i_sample ) )
01994 {
01995 msg_Warn( p_demux, "cannot select track[Id 0x%x]",
01996 p_track->i_track_ID );
01997 return( VLC_EGENERIC );
01998 }
01999
02000 p_track->b_selected = VLC_TRUE;
02001
02002 if( TrackGotoChunkSample( p_demux, p_track, i_chunk, i_sample ) ==
02003 VLC_SUCCESS )
02004 {
02005 p_track->b_selected = VLC_TRUE;
02006
02007 es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME,
02008 p_track->p_es, i_start );
02009 }
02010
02011 return( p_track->b_selected ? VLC_SUCCESS : VLC_EGENERIC );
02012 }
02013
02014
02015
02016
02017
02018
02019 #define QT_V0_MAX_SAMPLES 1024
02020 static int MP4_TrackSampleSize( mp4_track_t *p_track )
02021 {
02022 int i_size;
02023 MP4_Box_data_sample_soun_t *p_soun;
02024
02025 if( p_track->i_sample_size == 0 )
02026 {
02027
02028 return p_track->p_sample_size[p_track->i_sample];
02029 }
02030 if( p_track->fmt.i_cat != AUDIO_ES )
02031 {
02032 return p_track->i_sample_size;
02033 }
02034
02035 p_soun = p_track->p_sample->data.p_sample_soun;
02036
02037 if( p_soun->i_qt_version == 1 )
02038 {
02039 i_size = p_track->chunk[p_track->i_chunk].i_sample_count /
02040 p_soun->i_sample_per_packet * p_soun->i_bytes_per_frame;
02041 }
02042 else if( p_track->i_sample_size > 256 )
02043 {
02044
02045
02046 i_size = p_track->i_sample_size;
02047 }
02048 else
02049 {
02050
02051 int i_samples = p_track->chunk[p_track->i_chunk].i_sample_count -
02052 ( p_track->i_sample -
02053 p_track->chunk[p_track->i_chunk].i_sample_first );
02054
02055 i_samples = __MIN( QT_V0_MAX_SAMPLES, i_samples );
02056 i_size = i_samples * p_track->i_sample_size;
02057 }
02058
02059
02060 return i_size;
02061 }
02062
02063 static uint64_t MP4_TrackGetPos( mp4_track_t *p_track )
02064 {
02065 unsigned int i_sample;
02066 uint64_t i_pos;
02067
02068 i_pos = p_track->chunk[p_track->i_chunk].i_offset;
02069
02070 if( p_track->i_sample_size )
02071 {
02072 MP4_Box_data_sample_soun_t *p_soun =
02073 p_track->p_sample->data.p_sample_soun;
02074
02075 if( p_soun->i_qt_version == 0 )
02076 {
02077 i_pos += ( p_track->i_sample -
02078 p_track->chunk[p_track->i_chunk].i_sample_first ) *
02079 p_track->i_sample_size;
02080 }
02081 else
02082 {
02083
02084 i_pos += 0;
02085 }
02086 }
02087 else
02088 {
02089 for( i_sample = p_track->chunk[p_track->i_chunk].i_sample_first;
02090 i_sample < p_track->i_sample; i_sample++ )
02091 {
02092 i_pos += p_track->p_sample_size[i_sample];
02093 }
02094 }
02095
02096 return i_pos;
02097 }
02098
02099 static int MP4_TrackNextSample( demux_t *p_demux, mp4_track_t *p_track )
02100 {
02101 if( p_track->fmt.i_cat == AUDIO_ES && p_track->i_sample_size != 0 )
02102 {
02103 MP4_Box_data_sample_soun_t *p_soun;
02104
02105 p_soun = p_track->p_sample->data.p_sample_soun;
02106
02107 if( p_soun->i_qt_version == 1 )
02108 {
02109
02110 p_track->i_sample =
02111 p_track->chunk[p_track->i_chunk].i_sample_first +
02112 p_track->chunk[p_track->i_chunk].i_sample_count;
02113 }
02114 else if( p_track->i_sample_size > 256 )
02115 {
02116
02117
02118 p_track->i_sample += 1;
02119 }
02120 else
02121 {
02122
02123 p_track->i_sample += QT_V0_MAX_SAMPLES;
02124 if( p_track->i_sample >
02125 p_track->chunk[p_track->i_chunk].i_sample_first +
02126 p_track->chunk[p_track->i_chunk].i_sample_count )
02127 {
02128 p_track->i_sample =
02129 p_track->chunk[p_track->i_chunk].i_sample_first +
02130 p_track->chunk[p_track->i_chunk].i_sample_count;
02131 }
02132 }
02133 }
02134 else
02135 {
02136 p_track->i_sample++;
02137 }
02138
02139 if( p_track->i_sample >= p_track->i_sample_count )
02140 return VLC_EGENERIC;
02141
02142
02143 if( p_track->i_sample >=
02144 p_track->chunk[p_track->i_chunk].i_sample_first +
02145 p_track->chunk[p_track->i_chunk].i_sample_count )
02146 {
02147 if( TrackGotoChunkSample( p_demux, p_track, p_track->i_chunk + 1,
02148 p_track->i_sample ) )
02149 {
02150 msg_Warn( p_demux, "track[0x%x] will be disabled "
02151 "(cannot restart decoder)", p_track->i_track_ID );
02152 MP4_TrackUnselect( p_demux, p_track );
02153 return VLC_EGENERIC;
02154 }
02155 }
02156
02157
02158 if( p_track->p_elst && p_track->p_elst->data.p_elst->i_entry_count > 0 )
02159 {
02160 demux_sys_t *p_sys = p_demux->p_sys;
02161 MP4_Box_data_elst_t *elst = p_track->p_elst->data.p_elst;
02162 uint64_t i_mvt = MP4_TrackGetDTS( p_demux, p_track ) *
02163 p_sys->i_timescale / (int64_t)1000000;
02164
02165 if( (unsigned int)p_track->i_elst < elst->i_entry_count &&
02166 i_mvt >= p_track->i_elst_time +
02167 elst->i_segment_duration[p_track->i_elst] )
02168 {
02169 MP4_TrackSetELST( p_demux, p_track,
02170 MP4_TrackGetDTS( p_demux, p_track ) );
02171 }
02172 }
02173
02174 return VLC_SUCCESS;
02175 }
02176
02177 static void MP4_TrackSetELST( demux_t *p_demux, mp4_track_t *tk,
02178 int64_t i_time )
02179 {
02180 demux_sys_t *p_sys = p_demux->p_sys;
02181 int i_elst_last = tk->i_elst;
02182
02183
02184 tk->i_elst = 0;
02185 tk->i_elst_time = 0;
02186 if( tk->p_elst && tk->p_elst->data.p_elst->i_entry_count > 0 )
02187 {
02188 MP4_Box_data_elst_t *elst = tk->p_elst->data.p_elst;
02189 int64_t i_mvt= i_time * p_sys->i_timescale / (int64_t)1000000;
02190
02191 for( tk->i_elst = 0; (unsigned int)tk->i_elst < elst->i_entry_count; tk->i_elst++ )
02192 {
02193 mtime_t i_dur = elst->i_segment_duration[tk->i_elst];
02194
02195 if( tk->i_elst_time <= i_mvt && i_mvt < tk->i_elst_time + i_dur )
02196 {
02197 break;
02198 }
02199 tk->i_elst_time += i_dur;
02200 }
02201
02202 if( (unsigned int)tk->i_elst >= elst->i_entry_count )
02203 {
02204
02205 tk->i_elst = elst->i_entry_count - 1;
02206 tk->i_elst_time -= elst->i_segment_duration[tk->i_elst];
02207 }
02208
02209 if( elst->i_media_time[tk->i_elst] < 0 )
02210 {
02211
02212 tk->i_elst_time += elst->i_segment_duration[tk->i_elst];
02213 }
02214 }
02215 if( i_elst_last != tk->i_elst )
02216 {
02217 msg_Warn( p_demux, "elst old=%d new=%d", i_elst_last, tk->i_elst );
02218 }
02219 }