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
00031 #include "vlc_meta.h"
00032 #include "codecs.h"
00033
00034 #include "libavi.h"
00035
00036
00037
00038
00039
00040 #define INTERLEAVE_TEXT N_("Force interleaved method" )
00041 #define INTERLEAVE_LONGTEXT N_( "Force interleaved method" )
00042
00043 #define INDEX_TEXT N_("Force index creation")
00044 #define INDEX_LONGTEXT N_( \
00045 "Recreate a index for the AVI file. Use this if your AVI file is damaged "\
00046 "or incomplete (not seekable)" )
00047
00048 static int Open ( vlc_object_t * );
00049 static void Close( vlc_object_t * );
00050
00051 vlc_module_begin();
00052 set_shortname( "AVI" );
00053 set_description( _("AVI demuxer") );
00054 set_capability( "demux2", 212 );
00055 set_category( CAT_INPUT );
00056 set_subcategory( SUBCAT_INPUT_DEMUX );
00057
00058 add_bool( "avi-interleaved", 0, NULL,
00059 INTERLEAVE_TEXT, INTERLEAVE_LONGTEXT, VLC_TRUE );
00060 add_bool( "avi-index", 0, NULL,
00061 INDEX_TEXT, INDEX_LONGTEXT, VLC_FALSE );
00062
00063 set_callbacks( Open, Close );
00064 vlc_module_end();
00065
00066
00067
00068
00069 static int Control ( demux_t *, int, va_list );
00070 static int Seek ( demux_t *, mtime_t, int );
00071 static int Demux_Seekable ( demux_t * );
00072 static int Demux_UnSeekable( demux_t * );
00073
00074 #define FREE( p ) if( p ) { free( p ); (p) = NULL; }
00075 #define __ABS( x ) ( (x) < 0 ? (-(x)) : (x) )
00076
00077 typedef struct
00078 {
00079 vlc_fourcc_t i_fourcc;
00080 off_t i_pos;
00081 uint32_t i_size;
00082 vlc_fourcc_t i_type;
00083
00084 uint8_t i_peek[8];
00085
00086 unsigned int i_stream;
00087 unsigned int i_cat;
00088 } avi_packet_t;
00089
00090
00091 typedef struct
00092 {
00093 vlc_fourcc_t i_id;
00094 uint32_t i_flags;
00095 off_t i_pos;
00096 uint32_t i_length;
00097 uint32_t i_lengthtotal;
00098
00099 } avi_entry_t;
00100
00101 typedef struct
00102 {
00103 vlc_bool_t b_activated;
00104
00105 unsigned int i_cat;
00106 vlc_fourcc_t i_codec;
00107
00108 int i_rate;
00109 int i_scale;
00110 int i_samplesize;
00111
00112 es_out_id_t *p_es;
00113
00114 avi_entry_t *p_index;
00115 unsigned int i_idxnb;
00116 unsigned int i_idxmax;
00117
00118 unsigned int i_idxposc;
00119 unsigned int i_idxposb;
00120
00121
00122 unsigned int i_blockno;
00123 unsigned int i_blocksize;
00124 } avi_track_t;
00125
00126 struct demux_sys_t
00127 {
00128 mtime_t i_time;
00129 mtime_t i_length;
00130
00131 vlc_bool_t b_seekable;
00132 avi_chunk_t ck_root;
00133
00134 vlc_bool_t b_odml;
00135
00136 off_t i_movi_begin;
00137 off_t i_movi_lastchunk_pos;
00138
00139
00140 unsigned int i_track;
00141 avi_track_t **track;
00142
00143
00144 vlc_meta_t *meta;
00145 };
00146
00147 static inline off_t __EVEN( off_t i )
00148 {
00149 return (i & 1) ? i + 1 : i;
00150 }
00151
00152 static mtime_t AVI_PTSToChunk( avi_track_t *, mtime_t i_pts );
00153 static mtime_t AVI_PTSToByte ( avi_track_t *, mtime_t i_pts );
00154 static mtime_t AVI_GetDPTS ( avi_track_t *, int64_t i_count );
00155 static mtime_t AVI_GetPTS ( avi_track_t * );
00156
00157
00158 static int AVI_StreamChunkFind( demux_t *, unsigned int i_stream );
00159 static int AVI_StreamChunkSet ( demux_t *,
00160 unsigned int i_stream, unsigned int i_ck );
00161 static int AVI_StreamBytesSet ( demux_t *,
00162 unsigned int i_stream, off_t i_byte );
00163
00164 vlc_fourcc_t AVI_FourccGetCodec( unsigned int i_cat, vlc_fourcc_t );
00165 static int AVI_GetKeyFlag ( vlc_fourcc_t , uint8_t * );
00166
00167 static int AVI_PacketGetHeader( demux_t *, avi_packet_t *p_pk );
00168 static int AVI_PacketNext ( demux_t * );
00169 static int AVI_PacketRead ( demux_t *, avi_packet_t *, block_t **);
00170 static int AVI_PacketSearch ( demux_t * );
00171
00172 static void AVI_IndexLoad ( demux_t * );
00173 static void AVI_IndexCreate ( demux_t * );
00174 static void AVI_IndexAddEntry( demux_sys_t *, int, avi_entry_t * );
00175
00176 static mtime_t AVI_MovieGetLength( demux_t * );
00177
00178
00179
00180
00181 static int AVI_TrackSeek ( demux_t *, int, mtime_t );
00182 static int AVI_TrackStopFinishedStreams( demux_t *);
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196 static int Open( vlc_object_t * p_this )
00197 {
00198 demux_t *p_demux = (demux_t *)p_this;
00199 demux_sys_t *p_sys;
00200
00201 avi_chunk_t ck_riff;
00202 avi_chunk_list_t *p_riff = (avi_chunk_list_t*)&ck_riff;
00203 avi_chunk_list_t *p_hdrl, *p_movi;
00204 avi_chunk_avih_t *p_avih;
00205
00206 unsigned int i_track;
00207 unsigned int i, i_peeker;
00208
00209 uint8_t *p_peek;
00210
00211
00212 if( stream_Peek( p_demux->s, &p_peek, 200 ) < 200 ) return VLC_EGENERIC;
00213
00214 for( i_peeker = 0; i_peeker < 188; i_peeker++ )
00215 {
00216 if( !strncmp( (char *)&p_peek[0], "RIFF", 4 ) &&
00217 !strncmp( (char *)&p_peek[8], "AVI ", 4 ) ) break;
00218 p_peek++;
00219 }
00220 if( i_peeker == 188 )
00221 {
00222 return VLC_EGENERIC;
00223 }
00224
00225
00226 p_sys = p_demux->p_sys = malloc( sizeof(demux_sys_t) );
00227 memset( p_sys, 0, sizeof( demux_sys_t ) );
00228 p_sys->i_time = 0;
00229 p_sys->i_length = 0;
00230 p_sys->i_movi_lastchunk_pos = 0;
00231 p_sys->b_odml = VLC_FALSE;
00232 p_sys->i_track = 0;
00233 p_sys->track = NULL;
00234 p_sys->meta = NULL;
00235
00236 stream_Control( p_demux->s, STREAM_CAN_FASTSEEK, &p_sys->b_seekable );
00237
00238 p_demux->pf_control = Control;
00239 p_demux->pf_demux = Demux_Seekable;
00240
00241
00242 if( !p_sys->b_seekable || config_GetInt( p_demux, "avi-interleaved" ) )
00243 {
00244 p_demux->pf_demux = Demux_UnSeekable;
00245 }
00246
00247 if( i_peeker > 0 )
00248 {
00249 stream_Read( p_demux->s, NULL, i_peeker );
00250 }
00251
00252 if( AVI_ChunkReadRoot( p_demux->s, &p_sys->ck_root ) )
00253 {
00254 msg_Err( p_demux, "avi module discarded (invalid file)" );
00255 return VLC_EGENERIC;
00256 }
00257
00258 if( AVI_ChunkCount( &p_sys->ck_root, AVIFOURCC_RIFF ) > 1 )
00259 {
00260 unsigned int i_count =
00261 AVI_ChunkCount( &p_sys->ck_root, AVIFOURCC_RIFF );
00262
00263 msg_Warn( p_demux, "multiple riff -> OpenDML ?" );
00264 for( i = 1; i < i_count; i++ )
00265 {
00266 avi_chunk_list_t *p_sysx;
00267
00268 p_sysx = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, i );
00269 if( p_sysx->i_type == AVIFOURCC_AVIX )
00270 {
00271 msg_Warn( p_demux, "detected OpenDML file" );
00272 p_sys->b_odml = VLC_TRUE;
00273 break;
00274 }
00275 }
00276 }
00277
00278 p_riff = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0 );
00279 p_hdrl = AVI_ChunkFind( p_riff, AVIFOURCC_hdrl, 0 );
00280 p_movi = AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0 );
00281
00282 if( !p_hdrl || !p_movi )
00283 {
00284 msg_Err( p_demux, "avi module discarded (invalid file)" );
00285 goto error;
00286 }
00287
00288 if( !( p_avih = AVI_ChunkFind( p_hdrl, AVIFOURCC_avih, 0 ) ) )
00289 {
00290 msg_Err( p_demux, "cannot find avih chunk" );
00291 goto error;
00292 }
00293 i_track = AVI_ChunkCount( p_hdrl, AVIFOURCC_strl );
00294 if( p_avih->i_streams != i_track )
00295 {
00296 msg_Warn( p_demux,
00297 "found %d stream but %d are declared",
00298 i_track, p_avih->i_streams );
00299 }
00300 if( i_track == 0 )
00301 {
00302 msg_Err( p_demux, "no stream defined!" );
00303 goto error;
00304 }
00305
00306
00307 msg_Dbg( p_demux, "AVIH: %d stream, flags %s%s%s%s ",
00308 i_track,
00309 p_avih->i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
00310 p_avih->i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",
00311 p_avih->i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
00312 p_avih->i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"" );
00313 if( ( p_sys->meta = vlc_meta_New() ) )
00314 {
00315 char buffer[200];
00316 sprintf( buffer, "%s%s%s%s",
00317 p_avih->i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
00318 p_avih->i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",
00319 p_avih->i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
00320 p_avih->i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"" );
00321 vlc_meta_Add( p_sys->meta, VLC_META_SETTING, buffer );
00322 }
00323
00324
00325 for( i = 0 ; i < i_track; i++ )
00326 {
00327 avi_track_t *tk = malloc( sizeof( avi_track_t ) );
00328 avi_chunk_list_t *p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i );
00329 avi_chunk_strh_t *p_strh = AVI_ChunkFind( p_strl, AVIFOURCC_strh, 0 );
00330 avi_chunk_STRING_t *p_strn = AVI_ChunkFind( p_strl, AVIFOURCC_strn, 0 );
00331 avi_chunk_strf_auds_t *p_auds;
00332 avi_chunk_strf_vids_t *p_vids;
00333 es_format_t fmt;
00334
00335 tk->b_activated = VLC_FALSE;
00336 tk->p_index = 0;
00337 tk->i_idxnb = 0;
00338 tk->i_idxmax = 0;
00339 tk->i_idxposc = 0;
00340 tk->i_idxposb = 0;
00341
00342 tk->i_blockno = 0;
00343 tk->i_blocksize = 0;
00344
00345 p_vids = (avi_chunk_strf_vids_t*)AVI_ChunkFind( p_strl, AVIFOURCC_strf, 0 );
00346 p_auds = (avi_chunk_strf_auds_t*)AVI_ChunkFind( p_strl, AVIFOURCC_strf, 0 );
00347
00348 if( p_strl == NULL || p_strh == NULL || p_auds == NULL || p_vids == NULL )
00349 {
00350 msg_Warn( p_demux, "stream[%d] incomplete", i );
00351 continue;
00352 }
00353
00354 tk->i_rate = p_strh->i_rate;
00355 tk->i_scale = p_strh->i_scale;
00356 tk->i_samplesize = p_strh->i_samplesize;
00357 msg_Dbg( p_demux, "stream[%d] rate:%d scale:%d samplesize:%d",
00358 i, tk->i_rate, tk->i_scale, tk->i_samplesize );
00359
00360 switch( p_strh->i_type )
00361 {
00362 case( AVIFOURCC_auds ):
00363 tk->i_cat = AUDIO_ES;
00364 tk->i_codec = AVI_FourccGetCodec( AUDIO_ES,
00365 p_auds->p_wf->wFormatTag );
00366 if( ( tk->i_blocksize = p_auds->p_wf->nBlockAlign ) == 0 )
00367 {
00368 if( p_auds->p_wf->wFormatTag == 1 )
00369 {
00370 tk->i_blocksize = p_auds->p_wf->nChannels * (p_auds->p_wf->wBitsPerSample/8);
00371 }
00372 else
00373 {
00374 tk->i_blocksize = 1;
00375 }
00376 }
00377 es_format_Init( &fmt, AUDIO_ES, tk->i_codec );
00378
00379 fmt.audio.i_channels = p_auds->p_wf->nChannels;
00380 fmt.audio.i_rate = p_auds->p_wf->nSamplesPerSec;
00381 fmt.i_bitrate = p_auds->p_wf->nAvgBytesPerSec*8;
00382 fmt.audio.i_blockalign = p_auds->p_wf->nBlockAlign;
00383 fmt.audio.i_bitspersample = p_auds->p_wf->wBitsPerSample;
00384 fmt.i_extra = __MIN( p_auds->p_wf->cbSize,
00385 p_auds->i_chunk_size - sizeof(WAVEFORMATEX) );
00386 fmt.p_extra = &p_auds->p_wf[1];
00387 msg_Dbg( p_demux, "stream[%d] audio(0x%x) %d channels %dHz %dbits",
00388 i, p_auds->p_wf->wFormatTag, p_auds->p_wf->nChannels,
00389 p_auds->p_wf->nSamplesPerSec, p_auds->p_wf->wBitsPerSample);
00390 break;
00391
00392 case( AVIFOURCC_vids ):
00393 tk->i_cat = VIDEO_ES;
00394 tk->i_codec = AVI_FourccGetCodec( VIDEO_ES,
00395 p_vids->p_bih->biCompression );
00396 if( p_vids->p_bih->biCompression == 0x00 )
00397 {
00398 switch( p_vids->p_bih->biBitCount )
00399 {
00400 case 32:
00401 tk->i_codec = VLC_FOURCC('R','V','3','2');
00402 break;
00403 case 24:
00404 tk->i_codec = VLC_FOURCC('R','V','2','4');
00405 break;
00406 case 16:
00407
00408
00409 case 15:
00410 tk->i_codec = VLC_FOURCC('R','V','1','5');
00411 break;
00412 case 9:
00413 tk->i_codec = VLC_FOURCC( 'Y', 'V', 'U', '9' );
00414 break;
00415 }
00416 es_format_Init( &fmt, VIDEO_ES, tk->i_codec );
00417
00418 if( p_vids->p_bih->biBitCount == 24 )
00419 {
00420
00421 fmt.video.i_bmask = 0x00ff0000;
00422 fmt.video.i_gmask = 0x0000ff00;
00423 fmt.video.i_rmask = 0x000000ff;
00424 }
00425 }
00426 else
00427 {
00428 es_format_Init( &fmt, VIDEO_ES, p_vids->p_bih->biCompression );
00429 if( tk->i_codec == FOURCC_mp4v &&
00430 !strncasecmp( (char*)&p_strh->i_handler, "XVID", 4 ) )
00431 {
00432 fmt.i_codec = VLC_FOURCC( 'X', 'V', 'I', 'D' );
00433 }
00434 }
00435 tk->i_samplesize = 0;
00436 fmt.video.i_width = p_vids->p_bih->biWidth;
00437 fmt.video.i_height = p_vids->p_bih->biHeight;
00438 fmt.video.i_bits_per_pixel = p_vids->p_bih->biBitCount;
00439 fmt.video.i_frame_rate = tk->i_rate;
00440 fmt.video.i_frame_rate_base = tk->i_scale;
00441 fmt.i_extra =
00442 __MIN( p_vids->p_bih->biSize - sizeof( BITMAPINFOHEADER ),
00443 p_vids->i_chunk_size - sizeof(BITMAPINFOHEADER) );
00444 fmt.p_extra = &p_vids->p_bih[1];
00445 msg_Dbg( p_demux, "stream[%d] video(%4.4s) %dx%d %dbpp %ffps",
00446 i, (char*)&p_vids->p_bih->biCompression,
00447 p_vids->p_bih->biWidth,
00448 p_vids->p_bih->biHeight,
00449 p_vids->p_bih->biBitCount,
00450 (float)tk->i_rate/(float)tk->i_scale );
00451
00452 if( p_vids->p_bih->biCompression == 0x00 )
00453 {
00454
00455 fmt.video.i_height =
00456 (unsigned int)(-(int)p_vids->p_bih->biHeight);
00457 }
00458
00459
00460
00461
00462 if( fmt.i_extra && fmt.video.i_bits_per_pixel <= 8 &&
00463 fmt.video.i_bits_per_pixel > 0 )
00464 {
00465 int i;
00466
00467 fmt.video.p_palette = calloc( sizeof(video_palette_t), 1 );
00468 fmt.video.p_palette->i_entries = 1;
00469
00470
00471 fmt.i_extra =
00472 p_vids->i_chunk_size - sizeof(BITMAPINFOHEADER);
00473 for( i = 0; i < __MIN(fmt.i_extra/4, 256); i++ )
00474 {
00475 ((uint32_t *)&fmt.video.p_palette->palette[0][0])[i] =
00476 GetDWLE((uint32_t*)fmt.p_extra + i);
00477 }
00478 }
00479 break;
00480
00481 case( AVIFOURCC_txts):
00482 tk->i_cat = SPU_ES;
00483 tk->i_codec = VLC_FOURCC( 's', 'u', 'b', 't' );
00484 msg_Dbg( p_demux, "stream[%d] subtitles", i );
00485 es_format_Init( &fmt, SPU_ES, tk->i_codec );
00486 break;
00487
00488 case( AVIFOURCC_mids):
00489 msg_Dbg( p_demux, "stream[%d] midi is UNSUPPORTED", i );
00490
00491 default:
00492 msg_Warn( p_demux, "stream[%d] unknown type", i );
00493 free( tk );
00494 continue;
00495 }
00496 if( p_strn )
00497 {
00498 fmt.psz_description = strdup( p_strn->p_str );
00499 }
00500 tk->p_es = es_out_Add( p_demux->out, &fmt );
00501 TAB_APPEND( p_sys->i_track, p_sys->track, tk );
00502 }
00503
00504 if( p_sys->i_track <= 0 )
00505 {
00506 msg_Err( p_demux, "no valid track" );
00507 goto error;
00508 }
00509
00510 if( config_GetInt( p_demux, "avi-index" ) )
00511 {
00512 if( p_sys->b_seekable )
00513 {
00514 AVI_IndexCreate( p_demux );
00515 }
00516 else
00517 {
00518 msg_Warn( p_demux, "cannot create index (unseekable stream)" );
00519 AVI_IndexLoad( p_demux );
00520 }
00521 }
00522 else
00523 {
00524 AVI_IndexLoad( p_demux );
00525 }
00526
00527
00528 p_sys->i_length = AVI_MovieGetLength( p_demux );
00529 if( p_sys->i_length < (mtime_t)p_avih->i_totalframes *
00530 (mtime_t)p_avih->i_microsecperframe /
00531 (mtime_t)1000000 )
00532 {
00533 msg_Warn( p_demux, "broken or missing index, 'seek' will be axproximative or will have strange behavour" );
00534 }
00535
00536 for( i = 0 ; i < p_sys->i_track; i++ )
00537 {
00538 avi_track_t *tk = p_sys->track[i];
00539 avi_chunk_list_t *p_strl;
00540 avi_chunk_strh_t *p_strh;
00541 avi_chunk_strf_auds_t *p_auds;
00542
00543 if( tk->i_cat != AUDIO_ES )
00544 {
00545 continue;
00546 }
00547 if( tk->i_idxnb < 1 ||
00548 tk->i_scale != 1 ||
00549 tk->i_samplesize != 0 )
00550 {
00551 continue;
00552 }
00553 p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i );
00554 p_strh = AVI_ChunkFind( p_strl, AVIFOURCC_strh, 0 );
00555 p_auds = AVI_ChunkFind( p_strl, AVIFOURCC_strf, 0 );
00556
00557 if( p_auds->p_wf->wFormatTag != WAVE_FORMAT_PCM &&
00558 (unsigned int)tk->i_rate == p_auds->p_wf->nSamplesPerSec )
00559 {
00560 int64_t i_track_length =
00561 tk->p_index[tk->i_idxnb-1].i_length +
00562 tk->p_index[tk->i_idxnb-1].i_lengthtotal;
00563 mtime_t i_length = (mtime_t)p_avih->i_totalframes *
00564 (mtime_t)p_avih->i_microsecperframe;
00565
00566 if( i_length == 0 )
00567 {
00568 msg_Warn( p_demux, "track[%d] cannot be fixed (BeOS MediaKit generated)", i );
00569 continue;
00570 }
00571 tk->i_samplesize = 1;
00572 tk->i_rate = i_track_length * (int64_t)1000000/ i_length;
00573 msg_Warn( p_demux, "track[%d] fixed with rate=%d scale=%d (BeOS MediaKit generated)", i, tk->i_rate, tk->i_scale );
00574 }
00575 }
00576
00577 if( p_sys->b_seekable )
00578 {
00579
00580 stream_Seek( p_demux->s, p_movi->i_chunk_pos );
00581 }
00582
00583 stream_Read( p_demux->s, NULL, 12 );
00584
00585 p_sys->i_movi_begin = p_movi->i_chunk_pos;
00586 return VLC_SUCCESS;
00587
00588 error:
00589 if( p_sys->meta )
00590 {
00591 vlc_meta_Delete( p_sys->meta );
00592 }
00593 AVI_ChunkFreeRoot( p_demux->s, &p_sys->ck_root );
00594 free( p_sys );
00595 return VLC_EGENERIC;
00596 }
00597
00598
00599
00600
00601 static void Close ( vlc_object_t * p_this )
00602 {
00603 demux_t * p_demux = (demux_t *)p_this;
00604 unsigned int i;
00605 demux_sys_t *p_sys = p_demux->p_sys ;
00606
00607 for( i = 0; i < p_sys->i_track; i++ )
00608 {
00609 if( p_sys->track[i] )
00610 {
00611 FREE( p_sys->track[i]->p_index );
00612 free( p_sys->track[i] );
00613 }
00614 }
00615 FREE( p_sys->track );
00616 AVI_ChunkFreeRoot( p_demux->s, &p_sys->ck_root );
00617 vlc_meta_Delete( p_sys->meta );
00618
00619 free( p_sys );
00620 }
00621
00622
00623
00624
00625
00626
00627
00628
00629 typedef struct
00630 {
00631 vlc_bool_t b_ok;
00632
00633 int i_toread;
00634
00635 off_t i_posf;
00636
00637
00638 } avi_track_toread_t;
00639
00640 static int Demux_Seekable( demux_t *p_demux )
00641 {
00642 demux_sys_t *p_sys = p_demux->p_sys;
00643
00644 unsigned int i_track_count = 0;
00645 unsigned int i_track;
00646 vlc_bool_t b_stream;
00647
00648 avi_track_toread_t toread[100];
00649
00650
00651
00652 for( i_track = 0; i_track < p_sys->i_track; i_track++ )
00653 {
00654 avi_track_t *tk = p_sys->track[i_track];
00655 vlc_bool_t b;
00656
00657 es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE, tk->p_es, &b );
00658 if( b && !tk->b_activated )
00659 {
00660 if( p_sys->b_seekable)
00661 {
00662 AVI_TrackSeek( p_demux, i_track, p_sys->i_time );
00663 }
00664 tk->b_activated = VLC_TRUE;
00665 }
00666 else if( !b && tk->b_activated )
00667 {
00668 tk->b_activated = VLC_FALSE;
00669 }
00670 if( b )
00671 {
00672 i_track_count++;
00673 }
00674 }
00675
00676 if( i_track_count <= 0 )
00677 {
00678 int64_t i_length = p_sys->i_length * (mtime_t)1000000;
00679
00680 p_sys->i_time += 25*1000;
00681 if( i_length > 0 )
00682 {
00683 if( p_sys->i_time >= i_length )
00684 return 0;
00685 return 1;
00686 }
00687 msg_Warn( p_demux, "no track selected, exiting..." );
00688 return 0;
00689 }
00690
00691
00692 es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_time + 1 );
00693 p_sys->i_time += 25*1000;
00694
00695
00696 for( i_track = 0; i_track < p_sys->i_track; i_track++ )
00697 {
00698 avi_track_t *tk = p_sys->track[i_track];
00699 mtime_t i_dpts;
00700
00701 toread[i_track].b_ok = tk->b_activated;
00702 if( tk->i_idxposc < tk->i_idxnb )
00703 {
00704 toread[i_track].i_posf = tk->p_index[tk->i_idxposc].i_pos;
00705 if( tk->i_idxposb > 0 )
00706 {
00707 toread[i_track].i_posf += 8 + tk->i_idxposb;
00708 }
00709 }
00710 else
00711 {
00712 toread[i_track].i_posf = -1;
00713 }
00714
00715 i_dpts = p_sys->i_time - AVI_GetPTS( tk );
00716
00717 if( tk->i_samplesize )
00718 {
00719 toread[i_track].i_toread = AVI_PTSToByte( tk, __ABS( i_dpts ) );
00720 }
00721 else
00722 {
00723 toread[i_track].i_toread = AVI_PTSToChunk( tk, __ABS( i_dpts ) );
00724 }
00725
00726 if( i_dpts < 0 )
00727 {
00728 toread[i_track].i_toread *= -1;
00729 }
00730 }
00731
00732 b_stream = VLC_FALSE;
00733
00734 for( ;; )
00735 {
00736 avi_track_t *tk;
00737 vlc_bool_t b_done;
00738 block_t *p_frame;
00739 off_t i_pos;
00740 unsigned int i;
00741 size_t i_size;
00742
00743
00744 for( i = 0, b_done = VLC_TRUE, i_pos = -1; i < p_sys->i_track; i++ )
00745 {
00746 if( !toread[i].b_ok ||
00747 AVI_GetDPTS( p_sys->track[i],
00748 toread[i].i_toread ) <= -25 * 1000 )
00749 {
00750 continue;
00751 }
00752
00753 if( toread[i].i_toread > 0 )
00754 {
00755 b_done = VLC_FALSE;
00756 }
00757 if( toread[i].i_posf > 0 )
00758 {
00759 if( i_pos == -1 || i_pos > toread[i_track].i_posf )
00760 {
00761 i_track = i;
00762 i_pos = toread[i].i_posf;
00763 }
00764 }
00765 }
00766
00767 if( b_done )
00768 {
00769 return( 1 );
00770 }
00771
00772 if( i_pos == -1 )
00773 {
00774 int i_loop_count = 0;
00775
00776
00777
00778 if( p_sys->i_movi_lastchunk_pos >= p_sys->i_movi_begin + 12 )
00779 {
00780 stream_Seek( p_demux->s, p_sys->i_movi_lastchunk_pos );
00781 if( AVI_PacketNext( p_demux ) )
00782 {
00783 return( AVI_TrackStopFinishedStreams( p_demux ) ? 0 : 1 );
00784 }
00785 }
00786 else
00787 {
00788 stream_Seek( p_demux->s, p_sys->i_movi_begin + 12 );
00789 }
00790
00791 for( ;; )
00792 {
00793 avi_packet_t avi_pk;
00794
00795 if( AVI_PacketGetHeader( p_demux, &avi_pk ) )
00796 {
00797 msg_Warn( p_demux,
00798 "cannot get packet header, track disabled" );
00799 return( AVI_TrackStopFinishedStreams( p_demux ) ? 0 : 1 );
00800 }
00801 if( avi_pk.i_stream >= p_sys->i_track ||
00802 ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
00803 {
00804 if( AVI_PacketNext( p_demux ) )
00805 {
00806 msg_Warn( p_demux,
00807 "cannot skip packet, track disabled" );
00808 return( AVI_TrackStopFinishedStreams( p_demux ) ? 0 : 1 );
00809 }
00810
00811
00812
00813
00814 if( !(++i_loop_count % 1024) )
00815 {
00816 if( p_demux->b_die ) return -1;
00817 msleep( 10000 );
00818
00819 if( !(i_loop_count % (1024 * 10)) )
00820 msg_Warn( p_demux,
00821 "don't seem to find any data..." );
00822 }
00823 continue;
00824 }
00825 else
00826 {
00827
00828 avi_entry_t index;
00829
00830 index.i_id = avi_pk.i_fourcc;
00831 index.i_flags =
00832 AVI_GetKeyFlag(p_sys->track[avi_pk.i_stream]->i_codec,
00833 avi_pk.i_peek);
00834 index.i_pos = avi_pk.i_pos;
00835 index.i_length = avi_pk.i_size;
00836 AVI_IndexAddEntry( p_sys, avi_pk.i_stream, &index );
00837
00838 i_track = avi_pk.i_stream;
00839 tk = p_sys->track[i_track];
00840
00841 if( AVI_GetDPTS( tk, toread[i_track].i_toread ) > -25*1000 )
00842 {
00843 break;
00844 }
00845 else
00846 {
00847 if( AVI_PacketNext( p_demux ) )
00848 {
00849 msg_Warn( p_demux,
00850 "cannot skip packet, track disabled" );
00851 return( AVI_TrackStopFinishedStreams( p_demux ) ? 0 : 1 );
00852 }
00853 }
00854 }
00855 }
00856
00857 }
00858 else
00859 {
00860 stream_Seek( p_demux->s, i_pos );
00861 }
00862
00863
00864 tk = p_sys->track[i_track];
00865
00866
00867 if( tk->i_samplesize )
00868 {
00869 unsigned int i_toread;
00870
00871 if( ( i_toread = toread[i_track].i_toread ) <= 0 )
00872 {
00873 if( tk->i_samplesize > 1 )
00874 {
00875 i_toread = tk->i_samplesize;
00876 }
00877 else
00878 {
00879 i_toread = AVI_PTSToByte( tk, 20 * 1000 );
00880 i_toread = __MAX( i_toread, 100 );
00881 }
00882 }
00883 i_size = __MIN( tk->p_index[tk->i_idxposc].i_length -
00884 tk->i_idxposb,
00885 i_toread );
00886 }
00887 else
00888 {
00889 i_size = tk->p_index[tk->i_idxposc].i_length;
00890 }
00891
00892 if( tk->i_idxposb == 0 )
00893 {
00894 i_size += 8;
00895 }
00896
00897 if( ( p_frame = stream_Block( p_demux->s, __EVEN( i_size ) ) )==NULL )
00898 {
00899 msg_Warn( p_demux, "failed reading data" );
00900 tk->b_activated = VLC_FALSE;
00901 toread[i_track].b_ok = VLC_FALSE;
00902 continue;
00903 }
00904 if( i_size % 2 )
00905 {
00906 p_frame->i_buffer--;
00907 }
00908
00909 if( tk->i_idxposb == 0 )
00910 {
00911 p_frame->p_buffer += 8;
00912 p_frame->i_buffer -= 8;
00913 }
00914 p_frame->i_pts = AVI_GetPTS( tk ) + 1;
00915 if( tk->p_index[tk->i_idxposc].i_flags&AVIIF_KEYFRAME )
00916 {
00917 p_frame->i_flags = BLOCK_FLAG_TYPE_I;
00918 }
00919 else
00920 {
00921 p_frame->i_flags = BLOCK_FLAG_TYPE_PB;
00922 }
00923
00924
00925 if( tk->i_samplesize )
00926 {
00927 if( tk->i_idxposb == 0 )
00928 {
00929 i_size -= 8;
00930 }
00931 toread[i_track].i_toread -= i_size;
00932 tk->i_idxposb += i_size;
00933 if( tk->i_idxposb >=
00934 tk->p_index[tk->i_idxposc].i_length )
00935 {
00936 tk->i_idxposb = 0;
00937 tk->i_idxposc++;
00938 }
00939 }
00940 else
00941 {
00942 int i_length = tk->p_index[tk->i_idxposc].i_length;
00943
00944 tk->i_idxposc++;
00945 if( tk->i_cat == AUDIO_ES )
00946 {
00947 tk->i_blockno += tk->i_blocksize > 0 ? ( i_length + tk->i_blocksize - 1 ) / tk->i_blocksize : 1;
00948 }
00949 toread[i_track].i_toread--;
00950 }
00951
00952 if( tk->i_idxposc < tk->i_idxnb)
00953 {
00954 toread[i_track].i_posf =
00955 tk->p_index[tk->i_idxposc].i_pos;
00956 if( tk->i_idxposb > 0 )
00957 {
00958 toread[i_track].i_posf += 8 + tk->i_idxposb;
00959 }
00960
00961 }
00962 else
00963 {
00964 toread[i_track].i_posf = -1;
00965 }
00966
00967 b_stream = VLC_TRUE;
00968
00969 if( tk->i_cat != VIDEO_ES )
00970 p_frame->i_dts = p_frame->i_pts;
00971 else
00972 {
00973 p_frame->i_dts = p_frame->i_pts;
00974 p_frame->i_pts = 0;
00975 }
00976
00977
00978 es_out_Send( p_demux->out, tk->p_es, p_frame );
00979 }
00980 }
00981
00982
00983
00984
00985
00986
00987
00988 static int Demux_UnSeekable( demux_t *p_demux )
00989 {
00990 demux_sys_t *p_sys = p_demux->p_sys;
00991 avi_track_t *p_stream_master = NULL;
00992 unsigned int i_stream;
00993 unsigned int i_packet;
00994
00995 es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_time + 1 );
00996
00997
00998
00999 for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
01000 {
01001 avi_track_t *tk = p_sys->track[i_stream];
01002 vlc_bool_t b;
01003
01004 es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE, tk->p_es, &b );
01005
01006 if( b && tk->i_cat == VIDEO_ES )
01007 {
01008 p_stream_master = tk;
01009 }
01010 else if( b )
01011 {
01012 p_stream_master = tk;
01013 }
01014 }
01015
01016 if( !p_stream_master )
01017 {
01018 msg_Warn( p_demux, "no more stream selected" );
01019 return( 0 );
01020 }
01021
01022 p_sys->i_time = AVI_GetPTS( p_stream_master );
01023
01024 for( i_packet = 0; i_packet < 10; i_packet++)
01025 {
01026 #define p_stream p_sys->track[avi_pk.i_stream]
01027
01028 avi_packet_t avi_pk;
01029
01030 if( AVI_PacketGetHeader( p_demux, &avi_pk ) )
01031 {
01032 return( 0 );
01033 }
01034
01035 if( avi_pk.i_stream >= p_sys->i_track ||
01036 ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
01037 {
01038
01039
01040
01041
01042 switch( avi_pk.i_fourcc )
01043 {
01044 case AVIFOURCC_JUNK:
01045 case AVIFOURCC_LIST:
01046 case AVIFOURCC_RIFF:
01047 return( !AVI_PacketNext( p_demux ) ? 1 : 0 );
01048 case AVIFOURCC_idx1:
01049 if( p_sys->b_odml )
01050 {
01051 return( !AVI_PacketNext( p_demux ) ? 1 : 0 );
01052 }
01053 return( 0 );
01054 default:
01055 msg_Warn( p_demux,
01056 "seems to have lost position, resync" );
01057 if( AVI_PacketSearch( p_demux ) )
01058 {
01059 msg_Err( p_demux, "resync failed" );
01060 return( -1 );
01061 }
01062 }
01063 }
01064 else
01065 {
01066
01067 if( __ABS( AVI_GetPTS( p_stream ) -
01068 AVI_GetPTS( p_stream_master ) )< 600*1000 )
01069 {
01070
01071 block_t *p_frame;
01072 if( AVI_PacketRead( p_demux, &avi_pk, &p_frame ) || p_frame == NULL )
01073 {
01074 return( -1 );
01075 }
01076 p_frame->i_pts = AVI_GetPTS( p_stream ) + 1;
01077
01078 if( avi_pk.i_cat != VIDEO_ES )
01079 p_frame->i_dts = p_frame->i_pts;
01080 else
01081 {
01082 p_frame->i_dts = p_frame->i_pts;
01083 p_frame->i_pts = 0;
01084 }
01085
01086
01087 es_out_Send( p_demux->out, p_stream->p_es, p_frame );
01088 }
01089 else
01090 {
01091 if( AVI_PacketNext( p_demux ) )
01092 {
01093 return( 0 );
01094 }
01095 }
01096
01097
01098 if( p_stream->i_samplesize )
01099 {
01100 p_stream->i_idxposb += avi_pk.i_size;
01101 }
01102 else
01103 {
01104 if( p_stream->i_cat == AUDIO_ES )
01105 {
01106 p_stream->i_blockno += p_stream->i_blocksize > 0 ? ( avi_pk.i_size + p_stream->i_blocksize - 1 ) / p_stream->i_blocksize : 1;
01107 }
01108 p_stream->i_idxposc++;
01109 }
01110
01111 }
01112 #undef p_stream
01113 }
01114
01115 return( 1 );
01116 }
01117
01118
01119
01120
01121 static int Seek( demux_t *p_demux, mtime_t i_date, int i_percent )
01122 {
01123
01124 demux_sys_t *p_sys = p_demux->p_sys;
01125 unsigned int i_stream;
01126 msg_Dbg( p_demux, "seek requested: "I64Fd" secondes %d%%",
01127 i_date / 1000000, i_percent );
01128
01129 if( p_sys->b_seekable )
01130 {
01131 if( !p_sys->i_length )
01132 {
01133 avi_track_t *p_stream;
01134 int64_t i_pos;
01135
01136
01137 msg_Warn( p_demux, "mmh, seeking without index at %d%%"
01138 " work only for interleaved file", i_percent );
01139 if( i_percent >= 100 )
01140 {
01141 msg_Warn( p_demux, "cannot seek so far !" );
01142 return VLC_EGENERIC;
01143 }
01144 i_percent = __MAX( i_percent, 0 );
01145
01146
01147 i_pos = __MAX( i_percent * stream_Size( p_demux->s ) / 100,
01148 p_sys->i_movi_begin );
01149
01150 for( i_stream = 0, p_stream = NULL;
01151 i_stream < p_sys->i_track; i_stream++ )
01152 {
01153 p_stream = p_sys->track[i_stream];
01154 if( p_stream->b_activated )
01155 {
01156 break;
01157 }
01158 }
01159 if( !p_stream || !p_stream->b_activated )
01160 {
01161 msg_Warn( p_demux, "cannot find any selected stream" );
01162 return VLC_EGENERIC;
01163 }
01164
01165
01166 if( AVI_StreamChunkSet( p_demux, i_stream, 0 ) )
01167 {
01168 msg_Warn( p_demux, "cannot seek" );
01169 return VLC_EGENERIC;
01170 }
01171
01172 while( i_pos >= p_stream->p_index[p_stream->i_idxposc].i_pos +
01173 p_stream->p_index[p_stream->i_idxposc].i_length + 8 )
01174 {
01175
01176 if( AVI_StreamChunkSet( p_demux,
01177 i_stream, p_stream->i_idxposc + 1 ) )
01178 {
01179 msg_Warn( p_demux, "cannot seek" );
01180 return VLC_EGENERIC;
01181 }
01182 }
01183
01184 i_date = AVI_GetPTS( p_stream );
01185
01186 msg_Dbg( p_demux, "estimate date "I64Fd, i_date );
01187 }
01188
01189 #define p_stream p_sys->track[i_stream]
01190 p_sys->i_time = 0;
01191
01192 for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
01193 {
01194 if( p_stream->b_activated && !p_stream->i_samplesize )
01195
01196 {
01197 AVI_TrackSeek( p_demux, i_stream, i_date );
01198 p_sys->i_time = __MAX( AVI_GetPTS( p_stream ),
01199 p_sys->i_time );
01200 }
01201 }
01202 #if 1
01203 if( p_sys->i_time )
01204 {
01205 i_date = p_sys->i_time;
01206 }
01207
01208 for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
01209 {
01210 if( p_stream->b_activated && p_stream->i_samplesize )
01211 {
01212 AVI_TrackSeek( p_demux, i_stream, i_date );
01213
01214 }
01215 }
01216 msg_Dbg( p_demux, "seek: "I64Fd" seconds", p_sys->i_time /1000000 );
01217
01218 #endif
01219 if( !p_sys->i_time )
01220 {
01221 p_sys->i_time = i_date;
01222 }
01223 #undef p_stream
01224 return VLC_SUCCESS;
01225 }
01226 else
01227 {
01228 msg_Err( p_demux, "shouldn't yet be executed" );
01229 return VLC_EGENERIC;
01230 }
01231 }
01232
01233
01234
01235
01236
01237
01238 static double ControlGetPosition( demux_t *p_demux )
01239 {
01240 demux_sys_t *p_sys = p_demux->p_sys;
01241
01242 if( p_sys->i_length > 0 )
01243 {
01244 return (double)p_sys->i_time / (double)( p_sys->i_length * (mtime_t)1000000 );
01245 }
01246 else if( stream_Size( p_demux->s ) > 0 )
01247 {
01248 unsigned int i;
01249 int64_t i_tmp;
01250 int64_t i64 = 0;
01251
01252
01253 for( i = 0; i < p_sys->i_track; i++ )
01254 {
01255 avi_track_t *tk = p_sys->track[i];
01256 if( tk->b_activated && tk->i_idxposc < tk->i_idxnb )
01257 {
01258 i_tmp = tk->p_index[tk->i_idxposc].i_pos +
01259 tk->p_index[tk->i_idxposc].i_length + 8;
01260 if( i_tmp > i64 )
01261 {
01262 i64 = i_tmp;
01263 }
01264 }
01265 }
01266 return (double)i64 / (double)stream_Size( p_demux->s );
01267 }
01268 return 0.0;
01269 }
01270
01271 static int Control( demux_t *p_demux, int i_query, va_list args )
01272 {
01273 demux_sys_t *p_sys = p_demux->p_sys;
01274 int i;
01275 double f, *pf;
01276 int64_t i64, *pi64;
01277 vlc_meta_t **pp_meta;
01278
01279 switch( i_query )
01280 {
01281 case DEMUX_GET_POSITION:
01282 pf = (double*)va_arg( args, double * );
01283 *pf = ControlGetPosition( p_demux );
01284 return VLC_SUCCESS;
01285 case DEMUX_SET_POSITION:
01286 f = (double)va_arg( args, double );
01287 if( p_sys->b_seekable )
01288 {
01289 i64 = (mtime_t)(1000000.0 * p_sys->i_length * f );
01290 return Seek( p_demux, i64, (int)(f * 100) );
01291 }
01292 else
01293 {
01294 int64_t i_pos = stream_Size( p_demux->s ) * f;
01295 return stream_Seek( p_demux->s, i_pos );
01296 }
01297
01298 case DEMUX_GET_TIME:
01299 pi64 = (int64_t*)va_arg( args, int64_t * );
01300 *pi64 = p_sys->i_time;
01301 return VLC_SUCCESS;
01302
01303 case DEMUX_SET_TIME:
01304 {
01305 int i_percent = 0;
01306
01307 i64 = (int64_t)va_arg( args, int64_t );
01308 if( p_sys->i_length > 0 )
01309 {
01310 i_percent = 100 * i64 / (p_sys->i_length*1000000);
01311 }
01312 else if( p_sys->i_time > 0 )
01313 {
01314 i_percent = (int)( 100.0 * ControlGetPosition( p_demux ) *
01315 (double)i64 / (double)p_sys->i_time );
01316 }
01317 return Seek( p_demux, i64, i_percent );
01318 }
01319 case DEMUX_GET_LENGTH:
01320 pi64 = (int64_t*)va_arg( args, int64_t * );
01321 *pi64 = p_sys->i_length * (mtime_t)1000000;
01322 return VLC_SUCCESS;
01323
01324 case DEMUX_GET_FPS:
01325 pf = (double*)va_arg( args, double * );
01326 *pf = 0.0;
01327 for( i = 0; i < (int)p_sys->i_track; i++ )
01328 {
01329 avi_track_t *tk = p_sys->track[i];
01330 if( tk->i_cat == VIDEO_ES && tk->i_scale > 0)
01331 {
01332 *pf = (float)tk->i_rate / (float)tk->i_scale;
01333 break;
01334 }
01335 }
01336 return VLC_SUCCESS;
01337 case DEMUX_GET_META:
01338 pp_meta = (vlc_meta_t**)va_arg( args, vlc_meta_t** );
01339 *pp_meta = vlc_meta_Duplicate( p_sys->meta );
01340 return VLC_SUCCESS;
01341
01342 default:
01343 return VLC_EGENERIC;
01344 }
01345 }
01346
01347
01348
01349
01350
01351 static mtime_t AVI_PTSToChunk( avi_track_t *tk, mtime_t i_pts )
01352 {
01353 if( !tk->i_scale )
01354 return (mtime_t)0;
01355
01356 return (mtime_t)((int64_t)i_pts *
01357 (int64_t)tk->i_rate /
01358 (int64_t)tk->i_scale /
01359 (int64_t)1000000 );
01360 }
01361 static mtime_t AVI_PTSToByte( avi_track_t *tk, mtime_t i_pts )
01362 {
01363 if( !tk->i_scale || !tk->i_samplesize )
01364 return (mtime_t)0;
01365
01366 return (mtime_t)((int64_t)i_pts *
01367 (int64_t)tk->i_rate /
01368 (int64_t)tk->i_scale /
01369 (int64_t)1000000 *
01370 (int64_t)tk->i_samplesize );
01371 }
01372
01373 static mtime_t AVI_GetDPTS( avi_track_t *tk, int64_t i_count )
01374 {
01375 mtime_t i_dpts = 0;
01376
01377 if( !tk->i_rate )
01378 return i_dpts;
01379
01380 i_dpts = (mtime_t)( (int64_t)1000000 *
01381 (int64_t)i_count *
01382 (int64_t)tk->i_scale /
01383 (int64_t)tk->i_rate );
01384
01385 if( tk->i_samplesize )
01386 {
01387 return i_dpts / tk->i_samplesize;
01388 }
01389 return i_dpts;
01390 }
01391
01392 static mtime_t AVI_GetPTS( avi_track_t *tk )
01393 {
01394 if( tk->i_samplesize )
01395 {
01396 int64_t i_count = 0;
01397
01398
01399 if( tk->i_idxposc == tk->i_idxnb )
01400 {
01401 if( tk->i_idxposc )
01402 {
01403
01404 i_count = tk->p_index[tk->i_idxnb - 1].i_lengthtotal
01405 + tk->p_index[tk->i_idxnb - 1].i_length;
01406 }
01407 }
01408 else
01409 {
01410 i_count = tk->p_index[tk->i_idxposc].i_lengthtotal;
01411 }
01412 return AVI_GetDPTS( tk, i_count + tk->i_idxposb );
01413 }
01414 else
01415 {
01416 if( tk->i_cat == AUDIO_ES )
01417 {
01418 return AVI_GetDPTS( tk, tk->i_blockno );
01419 }
01420 else
01421 {
01422 return AVI_GetDPTS( tk, tk->i_idxposc );
01423 }
01424 }
01425 }
01426
01427 static int AVI_StreamChunkFind( demux_t *p_demux, unsigned int i_stream )
01428 {
01429 demux_sys_t *p_sys = p_demux->p_sys;
01430 avi_packet_t avi_pk;
01431 int i_loop_count = 0;
01432
01433
01434
01435 if( p_sys->i_movi_lastchunk_pos >= p_sys->i_movi_begin + 12 )
01436 {
01437 stream_Seek( p_demux->s, p_sys->i_movi_lastchunk_pos );
01438 if( AVI_PacketNext( p_demux ) )
01439 {
01440 return VLC_EGENERIC;
01441 }
01442 }
01443 else
01444 {
01445 stream_Seek( p_demux->s, p_sys->i_movi_begin + 12 );
01446 }
01447
01448 for( ;; )
01449 {
01450 if( p_demux->b_die ) return VLC_EGENERIC;
01451
01452 if( AVI_PacketGetHeader( p_demux, &avi_pk ) )
01453 {
01454 msg_Warn( p_demux, "cannot get packet header" );
01455 return VLC_EGENERIC;
01456 }
01457 if( avi_pk.i_stream >= p_sys->i_track ||
01458 ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
01459 {
01460 if( AVI_PacketNext( p_demux ) )
01461 {
01462 return VLC_EGENERIC;
01463 }
01464
01465
01466
01467
01468 if( !(++i_loop_count % 1024) )
01469 {
01470 if( p_demux->b_die ) return VLC_EGENERIC;
01471 msleep( 10000 );
01472
01473 if( !(i_loop_count % (1024 * 10)) )
01474 msg_Warn( p_demux, "don't seem to find any data..." );
01475 }
01476 }
01477 else
01478 {
01479
01480 avi_entry_t index;
01481
01482 index.i_id = avi_pk.i_fourcc;
01483 index.i_flags =
01484 AVI_GetKeyFlag(p_sys->track[avi_pk.i_stream]->i_codec,
01485 avi_pk.i_peek);
01486 index.i_pos = avi_pk.i_pos;
01487 index.i_length = avi_pk.i_size;
01488 AVI_IndexAddEntry( p_sys, avi_pk.i_stream, &index );
01489
01490 if( avi_pk.i_stream == i_stream )
01491 {
01492 return VLC_SUCCESS;
01493 }
01494
01495 if( AVI_PacketNext( p_demux ) )
01496 {
01497 return VLC_EGENERIC;
01498 }
01499 }
01500 }
01501 }
01502
01503
01504 static int AVI_StreamChunkSet( demux_t *p_demux, unsigned int i_stream,
01505 unsigned int i_ck )
01506 {
01507 demux_sys_t *p_sys = p_demux->p_sys;
01508 avi_track_t *p_stream = p_sys->track[i_stream];
01509
01510 p_stream->i_idxposc = i_ck;
01511 p_stream->i_idxposb = 0;
01512
01513 if( i_ck >= p_stream->i_idxnb )
01514 {
01515 p_stream->i_idxposc = p_stream->i_idxnb - 1;
01516 do
01517 {
01518 p_stream->i_idxposc++;
01519 if( AVI_StreamChunkFind( p_demux, i_stream ) )
01520 {
01521 return VLC_EGENERIC;
01522 }
01523
01524 } while( p_stream->i_idxposc < i_ck );
01525 }
01526
01527 return VLC_SUCCESS;
01528 }
01529
01530
01531 static int AVI_StreamBytesSet( demux_t *p_demux,
01532 unsigned int i_stream,
01533 off_t i_byte )
01534 {
01535 demux_sys_t *p_sys = p_demux->p_sys;
01536 avi_track_t *p_stream = p_sys->track[i_stream];
01537
01538 if( ( p_stream->i_idxnb > 0 )
01539 &&( i_byte < p_stream->p_index[p_stream->i_idxnb - 1].i_lengthtotal +
01540 p_stream->p_index[p_stream->i_idxnb - 1].i_length ) )
01541 {
01542
01543
01544 int i_idxposc = __MIN( p_stream->i_idxposc, p_stream->i_idxnb - 1 );
01545 int i_idxmax = p_stream->i_idxnb;
01546 int i_idxmin = 0;
01547 for( ;; )
01548 {
01549 if( p_stream->p_index[i_idxposc].i_lengthtotal > i_byte )
01550 {
01551 i_idxmax = i_idxposc ;
01552 i_idxposc = ( i_idxmin + i_idxposc ) / 2 ;
01553 }
01554 else
01555 {
01556 if( p_stream->p_index[i_idxposc].i_lengthtotal +
01557 p_stream->p_index[i_idxposc].i_length <= i_byte)
01558 {
01559 i_idxmin = i_idxposc ;
01560 i_idxposc = (i_idxmax + i_idxposc ) / 2 ;
01561 }
01562 else
01563 {
01564 p_stream->i_idxposc = i_idxposc;
01565 p_stream->i_idxposb = i_byte -
01566 p_stream->p_index[i_idxposc].i_lengthtotal;
01567 return VLC_SUCCESS;
01568 }
01569 }
01570 }
01571
01572 }
01573 else
01574 {
01575 p_stream->i_idxposc = p_stream->i_idxnb - 1;
01576 p_stream->i_idxposb = 0;
01577 do
01578 {
01579 p_stream->i_idxposc++;
01580 if( AVI_StreamChunkFind( p_demux, i_stream ) )
01581 {
01582 return VLC_EGENERIC;
01583 }
01584
01585 } while( p_stream->p_index[p_stream->i_idxposc].i_lengthtotal +
01586 p_stream->p_index[p_stream->i_idxposc].i_length <= i_byte );
01587
01588 p_stream->i_idxposb = i_byte -
01589 p_stream->p_index[p_stream->i_idxposc].i_lengthtotal;
01590 return VLC_SUCCESS;
01591 }
01592 }
01593
01594 static int AVI_TrackSeek( demux_t *p_demux,
01595 int i_stream,
01596 mtime_t i_date )
01597 {
01598 demux_sys_t *p_sys = p_demux->p_sys;
01599 avi_track_t *tk = p_sys->track[i_stream];
01600
01601 #define p_stream p_sys->track[i_stream]
01602 mtime_t i_oldpts;
01603
01604 i_oldpts = AVI_GetPTS( p_stream );
01605
01606 if( !p_stream->i_samplesize )
01607 {
01608 if( AVI_StreamChunkSet( p_demux,
01609 i_stream,
01610 AVI_PTSToChunk( p_stream, i_date ) ) )
01611 {
01612 return VLC_EGENERIC;
01613 }
01614
01615 if( p_stream->i_cat == AUDIO_ES )
01616 {
01617 unsigned int i;
01618 tk->i_blockno = 0;
01619 for( i = 0; i < tk->i_idxposc; i++ )
01620 {
01621 if( tk->i_blocksize > 0 )
01622 {
01623 tk->i_blockno += ( tk->p_index[i].i_length + tk->i_blocksize - 1 ) / tk->i_blocksize;
01624 }
01625 else
01626 {
01627 tk->i_blockno++;
01628 }
01629 }
01630 }
01631
01632 msg_Dbg( p_demux,
01633 "old:"I64Fd" %s new "I64Fd,
01634 i_oldpts,
01635 i_oldpts > i_date ? ">" : "<",
01636 i_date );
01637
01638 if( p_stream->i_cat == VIDEO_ES )
01639 {
01640
01641 if( i_date < i_oldpts )
01642 {
01643 while( p_stream->i_idxposc > 0 &&
01644 !( p_stream->p_index[p_stream->i_idxposc].i_flags &
01645 AVIIF_KEYFRAME ) )
01646 {
01647 if( AVI_StreamChunkSet( p_demux,
01648 i_stream,
01649 p_stream->i_idxposc - 1 ) )
01650 {
01651 return VLC_EGENERIC;
01652 }
01653 }
01654 }
01655 else
01656 {
01657 while( p_stream->i_idxposc < p_stream->i_idxnb &&
01658 !( p_stream->p_index[p_stream->i_idxposc].i_flags &
01659 AVIIF_KEYFRAME ) )
01660 {
01661 if( AVI_StreamChunkSet( p_demux,
01662 i_stream,
01663 p_stream->i_idxposc + 1 ) )
01664 {
01665 return VLC_EGENERIC;
01666 }
01667 }
01668 }
01669 }
01670 }
01671 else
01672 {
01673 if( AVI_StreamBytesSet( p_demux,
01674 i_stream,
01675 AVI_PTSToByte( p_stream, i_date ) ) )
01676 {
01677 return VLC_EGENERIC;
01678 }
01679 }
01680 return VLC_SUCCESS;
01681 #undef p_stream
01682 }
01683
01684
01685
01686
01687 static int AVI_GetKeyFlag( vlc_fourcc_t i_fourcc, uint8_t *p_byte )
01688 {
01689 switch( i_fourcc )
01690 {
01691 case FOURCC_DIV1:
01692
01693
01694
01695
01696
01697 if( GetDWBE( p_byte ) != 0x00000100 )
01698 {
01699
01700 return AVIIF_KEYFRAME;
01701 }
01702 return p_byte[4] & 0x06 ? 0 : AVIIF_KEYFRAME;
01703
01704 case FOURCC_DIV2:
01705 case FOURCC_DIV3:
01706
01707
01708
01709 return p_byte[0] & 0xC0 ? 0 : AVIIF_KEYFRAME;
01710 case FOURCC_mp4v:
01711
01712
01713
01714
01715 if( GetDWBE( p_byte ) != 0x000001b6 )
01716 {
01717
01718 return AVIIF_KEYFRAME;
01719 }
01720 return p_byte[4] & 0xC0 ? 0 : AVIIF_KEYFRAME;
01721
01722 default:
01723
01724 return AVIIF_KEYFRAME;
01725 }
01726 }
01727
01728 vlc_fourcc_t AVI_FourccGetCodec( unsigned int i_cat, vlc_fourcc_t i_codec )
01729 {
01730 switch( i_cat )
01731 {
01732 case AUDIO_ES:
01733 wf_tag_to_fourcc( i_codec, &i_codec, NULL );
01734 return i_codec;
01735
01736 case VIDEO_ES:
01737
01738 switch( i_codec )
01739 {
01740 case FOURCC_1:
01741 return VLC_FOURCC('m','r','l','e');
01742 case FOURCC_DIV1:
01743 case FOURCC_div1:
01744 case FOURCC_MPG4:
01745 case FOURCC_mpg4:
01746 return FOURCC_DIV1;
01747 case FOURCC_DIV2:
01748 case FOURCC_div2:
01749 case FOURCC_MP42:
01750 case FOURCC_mp42:
01751 case FOURCC_MPG3:
01752 case FOURCC_mpg3:
01753 return FOURCC_DIV2;
01754 case FOURCC_div3:
01755 case FOURCC_MP43:
01756 case FOURCC_mp43:
01757 case FOURCC_DIV3:
01758 case FOURCC_DIV4:
01759 case FOURCC_div4:
01760 case FOURCC_DIV5:
01761 case FOURCC_div5:
01762 case FOURCC_DIV6:
01763 case FOURCC_div6:
01764 case FOURCC_AP41:
01765 case FOURCC_3IV1:
01766 case FOURCC_3iv1:
01767 case FOURCC_3IVD:
01768 case FOURCC_3ivd:
01769 case FOURCC_3VID:
01770 case FOURCC_3vid:
01771 return FOURCC_DIV3;
01772 case FOURCC_DIVX:
01773 case FOURCC_divx:
01774 case FOURCC_MP4S:
01775 case FOURCC_mp4s:
01776 case FOURCC_M4S2:
01777 case FOURCC_m4s2:
01778 case FOURCC_xvid:
01779 case FOURCC_XVID:
01780 case FOURCC_XviD:
01781 case FOURCC_DX50:
01782 case FOURCC_dx50:
01783 case FOURCC_mp4v:
01784 case FOURCC_4:
01785 case FOURCC_3IV2:
01786 case FOURCC_3iv2:
01787 return FOURCC_mp4v;
01788 }
01789 default:
01790 return VLC_FOURCC( 'u', 'n', 'd', 'f' );
01791 }
01792 }
01793
01794
01795
01796
01797 static void AVI_ParseStreamHeader( vlc_fourcc_t i_id,
01798 int *pi_number, int *pi_type )
01799 {
01800 #define SET_PTR( p, v ) if( p ) *(p) = (v);
01801 int c1, c2;
01802
01803 c1 = ((uint8_t *)&i_id)[0];
01804 c2 = ((uint8_t *)&i_id)[1];
01805
01806 if( c1 < '0' || c1 > '9' || c2 < '0' || c2 > '9' )
01807 {
01808 SET_PTR( pi_number, 100 );
01809 SET_PTR( pi_type, UNKNOWN_ES );
01810 }
01811 else
01812 {
01813 SET_PTR( pi_number, (c1 - '0') * 10 + (c2 - '0' ) );
01814 switch( VLC_TWOCC( ((uint8_t *)&i_id)[2], ((uint8_t *)&i_id)[3] ) )
01815 {
01816 case AVITWOCC_wb:
01817 SET_PTR( pi_type, AUDIO_ES );
01818 break;
01819 case AVITWOCC_dc:
01820 case AVITWOCC_db:
01821 SET_PTR( pi_type, VIDEO_ES );
01822 break;
01823 default:
01824 SET_PTR( pi_type, UNKNOWN_ES );
01825 break;
01826 }
01827 }
01828 #undef SET_PTR
01829 }
01830
01831
01832
01833
01834 static int AVI_PacketGetHeader( demux_t *p_demux, avi_packet_t *p_pk )
01835 {
01836 uint8_t *p_peek;
01837
01838 if( stream_Peek( p_demux->s, &p_peek, 16 ) < 16 )
01839 {
01840 return VLC_EGENERIC;
01841 }
01842 p_pk->i_fourcc = VLC_FOURCC( p_peek[0], p_peek[1], p_peek[2], p_peek[3] );
01843 p_pk->i_size = GetDWLE( p_peek + 4 );
01844 p_pk->i_pos = stream_Tell( p_demux->s );
01845 if( p_pk->i_fourcc == AVIFOURCC_LIST || p_pk->i_fourcc == AVIFOURCC_RIFF )
01846 {
01847 p_pk->i_type = VLC_FOURCC( p_peek[8], p_peek[9],
01848 p_peek[10], p_peek[11] );
01849 }
01850 else
01851 {
01852 p_pk->i_type = 0;
01853 }
01854
01855 memcpy( p_pk->i_peek, p_peek + 8, 8 );
01856
01857 AVI_ParseStreamHeader( p_pk->i_fourcc, &p_pk->i_stream, &p_pk->i_cat );
01858 return VLC_SUCCESS;
01859 }
01860
01861 static int AVI_PacketNext( demux_t *p_demux )
01862 {
01863 avi_packet_t avi_ck;
01864 int i_skip = 0;
01865
01866 if( AVI_PacketGetHeader( p_demux, &avi_ck ) )
01867 {
01868 return VLC_EGENERIC;
01869 }
01870
01871 if( avi_ck.i_fourcc == AVIFOURCC_LIST &&
01872 ( avi_ck.i_type == AVIFOURCC_rec || avi_ck.i_type == AVIFOURCC_movi ) )
01873 {
01874 i_skip = 12;
01875 }
01876 else if( avi_ck.i_fourcc == AVIFOURCC_RIFF &&
01877 avi_ck.i_type == AVIFOURCC_AVIX )
01878 {
01879 i_skip = 24;
01880 }
01881 else
01882 {
01883 i_skip = __EVEN( avi_ck.i_size ) + 8;
01884 }
01885
01886 if( stream_Read( p_demux->s, NULL, i_skip ) != i_skip )
01887 {
01888 return VLC_EGENERIC;
01889 }
01890 return VLC_SUCCESS;
01891 }
01892
01893 static int AVI_PacketRead( demux_t *p_demux,
01894 avi_packet_t *p_pk,
01895 block_t **pp_frame )
01896 {
01897 size_t i_size;
01898
01899 i_size = __EVEN( p_pk->i_size + 8 );
01900
01901 if( ( *pp_frame = stream_Block( p_demux->s, i_size ) ) == NULL )
01902 {
01903 return VLC_EGENERIC;
01904 }
01905 (*pp_frame)->p_buffer += 8;
01906 (*pp_frame)->i_buffer -= 8;
01907
01908 if( i_size != p_pk->i_size + 8 )
01909 {
01910 (*pp_frame)->i_buffer--;
01911 }
01912
01913 return VLC_SUCCESS;
01914 }
01915
01916 static int AVI_PacketSearch( demux_t *p_demux )
01917 {
01918 demux_sys_t *p_sys = p_demux->p_sys;
01919 avi_packet_t avi_pk;
01920 int i_count = 0;
01921
01922 for( ;; )
01923 {
01924 if( stream_Read( p_demux->s, NULL, 1 ) != 1 )
01925 {
01926 return VLC_EGENERIC;
01927 }
01928 AVI_PacketGetHeader( p_demux, &avi_pk );
01929 if( avi_pk.i_stream < p_sys->i_track &&
01930 ( avi_pk.i_cat == AUDIO_ES || avi_pk.i_cat == VIDEO_ES ) )
01931 {
01932 return VLC_SUCCESS;
01933 }
01934 switch( avi_pk.i_fourcc )
01935 {
01936 case AVIFOURCC_JUNK:
01937 case AVIFOURCC_LIST:
01938 case AVIFOURCC_RIFF:
01939 case AVIFOURCC_idx1:
01940 return VLC_SUCCESS;
01941 }
01942
01943
01944
01945
01946
01947 if( !(++i_count % 1024) )
01948 {
01949 if( p_demux->b_die ) return VLC_EGENERIC;
01950
01951 msleep( 10000 );
01952 if( !(i_count % (1024 * 10)) )
01953 msg_Warn( p_demux, "trying to resync..." );
01954 }
01955 }
01956 }
01957
01958
01959
01960
01961 static void AVI_IndexAddEntry( demux_sys_t *p_sys,
01962 int i_stream,
01963 avi_entry_t *p_index)
01964 {
01965 avi_track_t *tk = p_sys->track[i_stream];
01966
01967
01968 if( p_sys->i_movi_lastchunk_pos < p_index->i_pos )
01969 {
01970 p_sys->i_movi_lastchunk_pos = p_index->i_pos;
01971 }
01972
01973
01974 if( tk->i_idxnb >= tk->i_idxmax )
01975 {
01976 tk->i_idxmax += 16384;
01977 tk->p_index = realloc( tk->p_index,
01978 tk->i_idxmax * sizeof( avi_entry_t ) );
01979 if( tk->p_index == NULL )
01980 {
01981 return;
01982 }
01983 }
01984
01985 if( tk->i_idxnb > 0 )
01986 {
01987 p_index->i_lengthtotal =
01988 tk->p_index[tk->i_idxnb - 1].i_length +
01989 tk->p_index[tk->i_idxnb - 1].i_lengthtotal;
01990 }
01991 else
01992 {
01993 p_index->i_lengthtotal = 0;
01994 }
01995
01996 tk->p_index[tk->i_idxnb++] = *p_index;
01997 }
01998
01999 static int AVI_IndexLoad_idx1( demux_t *p_demux )
02000 {
02001 demux_sys_t *p_sys = p_demux->p_sys;
02002
02003 avi_chunk_list_t *p_riff;
02004 avi_chunk_list_t *p_movi;
02005 avi_chunk_idx1_t *p_idx1;
02006
02007 unsigned int i_stream;
02008 unsigned int i_index;
02009 off_t i_offset;
02010 unsigned int i;
02011
02012 vlc_bool_t b_keyset[100];
02013
02014 p_riff = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0);
02015 p_idx1 = AVI_ChunkFind( p_riff, AVIFOURCC_idx1, 0);
02016 p_movi = AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0);
02017
02018 if( !p_idx1 )
02019 {
02020 msg_Warn( p_demux, "cannot find idx1 chunk, no index defined" );
02021 return VLC_EGENERIC;
02022 }
02023
02024
02025
02026
02027 i_offset = 0;
02028 for( i = 0; i < __MIN( p_idx1->i_entry_count, 10 ); i++ )
02029 {
02030 if( p_idx1->entry[i].i_pos < p_movi->i_chunk_pos )
02031 {
02032 i_offset = p_movi->i_chunk_pos + 8;
02033 break;
02034 }
02035 }
02036
02037
02038 for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
02039 b_keyset[i_stream] = VLC_FALSE;
02040
02041 for( i_index = 0; i_index < p_idx1->i_entry_count; i_index++ )
02042 {
02043 unsigned int i_cat;
02044
02045 AVI_ParseStreamHeader( p_idx1->entry[i_index].i_fourcc,
02046 &i_stream,
02047 &i_cat );
02048 if( i_stream < p_sys->i_track &&
02049 i_cat == p_sys->track[i_stream]->i_cat )
02050 {
02051 avi_entry_t index;
02052 index.i_id = p_idx1->entry[i_index].i_fourcc;
02053 index.i_flags =
02054 p_idx1->entry[i_index].i_flags&(~AVIIF_FIXKEYFRAME);
02055 index.i_pos = p_idx1->entry[i_index].i_pos + i_offset;
02056 index.i_length = p_idx1->entry[i_index].i_length;
02057 AVI_IndexAddEntry( p_sys, i_stream, &index );
02058
02059 if( index.i_flags&AVIIF_KEYFRAME )
02060 b_keyset[i_stream] = VLC_TRUE;
02061 }
02062 }
02063
02064 for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
02065 {
02066 if( !b_keyset[i_stream] )
02067 {
02068 avi_track_t *tk = p_sys->track[i_stream];
02069
02070 msg_Dbg( p_demux, "no key frame set for track %d", i_stream );
02071 for( i_index = 0; i_index < tk->i_idxnb; i_index++ )
02072 tk->p_index[i_index].i_flags |= AVIIF_KEYFRAME;
02073 }
02074 }
02075 return VLC_SUCCESS;
02076 }
02077
02078 static void __Parse_indx( demux_t *p_demux,
02079 int i_stream,
02080 avi_chunk_indx_t *p_indx )
02081 {
02082 demux_sys_t *p_sys = p_demux->p_sys;
02083 avi_entry_t index;
02084 int32_t i;
02085
02086 msg_Dbg( p_demux, "loading subindex(0x%x) %d entries", p_indx->i_indextype, p_indx->i_entriesinuse );
02087 if( p_indx->i_indexsubtype == 0 )
02088 {
02089 for( i = 0; i < p_indx->i_entriesinuse; i++ )
02090 {
02091 index.i_id = p_indx->i_id;
02092 index.i_flags = p_indx->idx.std[i].i_size & 0x80000000 ? 0 : AVIIF_KEYFRAME;
02093 index.i_pos = p_indx->i_baseoffset + p_indx->idx.std[i].i_offset - 8;
02094 index.i_length = p_indx->idx.std[i].i_size&0x7fffffff;
02095
02096 AVI_IndexAddEntry( p_sys, i_stream, &index );
02097 }
02098 }
02099 else if( p_indx->i_indexsubtype == AVI_INDEX_2FIELD )
02100 {
02101 for( i = 0; i < p_indx->i_entriesinuse; i++ )
02102 {
02103 index.i_id = p_indx->i_id;
02104 index.i_flags = p_indx->idx.field[i].i_size & 0x80000000 ? 0 : AVIIF_KEYFRAME;
02105 index.i_pos = p_indx->i_baseoffset + p_indx->idx.field[i].i_offset - 8;
02106 index.i_length = p_indx->idx.field[i].i_size;
02107
02108 AVI_IndexAddEntry( p_sys, i_stream, &index );
02109 }
02110 }
02111 else
02112 {
02113 msg_Warn( p_demux, "unknown subtype index(0x%x)", p_indx->i_indexsubtype );
02114 }
02115 }
02116
02117 static void AVI_IndexLoad_indx( demux_t *p_demux )
02118 {
02119 demux_sys_t *p_sys = p_demux->p_sys;
02120 unsigned int i_stream;
02121 int32_t i;
02122
02123 avi_chunk_list_t *p_riff;
02124 avi_chunk_list_t *p_hdrl;
02125
02126 p_riff = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0);
02127 p_hdrl = AVI_ChunkFind( p_riff, AVIFOURCC_hdrl, 0 );
02128
02129 for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
02130 {
02131 avi_chunk_list_t *p_strl;
02132 avi_chunk_indx_t *p_indx;
02133
02134 #define p_stream p_sys->track[i_stream]
02135 p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i_stream );
02136 p_indx = AVI_ChunkFind( p_strl, AVIFOURCC_indx, 0 );
02137
02138 if( !p_indx )
02139 {
02140 msg_Warn( p_demux, "cannot find indx (misdetect/broken OpenDML file?)" );
02141 continue;
02142 }
02143
02144 if( p_indx->i_indextype == AVI_INDEX_OF_CHUNKS )
02145 {
02146 __Parse_indx( p_demux, i_stream, p_indx );
02147 }
02148 else if( p_indx->i_indextype == AVI_INDEX_OF_INDEXES )
02149 {
02150 avi_chunk_t ck_sub;
02151 for( i = 0; i < p_indx->i_entriesinuse; i++ )
02152 {
02153 if( stream_Seek( p_demux->s, p_indx->idx.super[i].i_offset )||
02154 AVI_ChunkRead( p_demux->s, &ck_sub, NULL ) )
02155 {
02156 break;
02157 }
02158 __Parse_indx( p_demux, i_stream, &ck_sub.indx );
02159 }
02160 }
02161 else
02162 {
02163 msg_Warn( p_demux, "unknown type index(0x%x)", p_indx->i_indextype );
02164 }
02165 #undef p_stream
02166 }
02167 }
02168
02169 static void AVI_IndexLoad( demux_t *p_demux )
02170 {
02171 demux_sys_t *p_sys = p_demux->p_sys;
02172 unsigned int i_stream;
02173
02174 for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
02175 {
02176 p_sys->track[i_stream]->i_idxnb = 0;
02177 p_sys->track[i_stream]->i_idxmax = 0;
02178 p_sys->track[i_stream]->p_index = NULL;
02179 }
02180
02181 if( p_sys->b_odml )
02182 {
02183 AVI_IndexLoad_indx( p_demux );
02184 }
02185 else if( AVI_IndexLoad_idx1( p_demux ) )
02186 {
02187
02188 AVI_IndexLoad_indx( p_demux );
02189 }
02190
02191 for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
02192 {
02193 msg_Dbg( p_demux, "stream[%d] created %d index entries",
02194 i_stream, p_sys->track[i_stream]->i_idxnb );
02195 }
02196 }
02197
02198 static void AVI_IndexCreate( demux_t *p_demux )
02199 {
02200 demux_sys_t *p_sys = p_demux->p_sys;
02201
02202 avi_chunk_list_t *p_riff;
02203 avi_chunk_list_t *p_movi;
02204
02205 unsigned int i_stream;
02206 off_t i_movi_end;
02207
02208 p_riff = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0);
02209 p_movi = AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0);
02210
02211 if( !p_movi )
02212 {
02213 msg_Err( p_demux, "cannot find p_movi" );
02214 return;
02215 }
02216
02217 for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
02218 {
02219 p_sys->track[i_stream]->i_idxnb = 0;
02220 p_sys->track[i_stream]->i_idxmax = 0;
02221 p_sys->track[i_stream]->p_index = NULL;
02222 }
02223 i_movi_end = __MIN( (off_t)(p_movi->i_chunk_pos + p_movi->i_chunk_size),
02224 stream_Size( p_demux->s ) );
02225
02226 stream_Seek( p_demux->s, p_movi->i_chunk_pos + 12 );
02227 msg_Warn( p_demux, "creating index from LIST-movi, will take time !" );
02228 for( ;; )
02229 {
02230 avi_packet_t pk;
02231
02232 if( p_demux->b_die )
02233 {
02234 return;
02235 }
02236
02237 if( AVI_PacketGetHeader( p_demux, &pk ) )
02238 {
02239 break;
02240 }
02241 if( pk.i_stream < p_sys->i_track &&
02242 pk.i_cat == p_sys->track[pk.i_stream]->i_cat )
02243 {
02244 avi_entry_t index;
02245 index.i_id = pk.i_fourcc;
02246 index.i_flags =
02247 AVI_GetKeyFlag(p_sys->track[pk.i_stream]->i_codec, pk.i_peek);
02248 index.i_pos = pk.i_pos;
02249 index.i_length = pk.i_size;
02250 AVI_IndexAddEntry( p_sys, pk.i_stream, &index );
02251 }
02252 else
02253 {
02254 switch( pk.i_fourcc )
02255 {
02256 case AVIFOURCC_idx1:
02257 if( p_sys->b_odml )
02258 {
02259 avi_chunk_list_t *p_sysx;
02260 p_sysx = AVI_ChunkFind( &p_sys->ck_root,
02261 AVIFOURCC_RIFF, 1 );
02262
02263 msg_Dbg( p_demux, "looking for new RIFF chunk" );
02264 if( stream_Seek( p_demux->s, p_sysx->i_chunk_pos + 24))
02265 {
02266 goto print_stat;
02267 }
02268 break;
02269 }
02270 goto print_stat;
02271 case AVIFOURCC_RIFF:
02272 msg_Dbg( p_demux, "new RIFF chunk found" );
02273 case AVIFOURCC_rec:
02274 case AVIFOURCC_JUNK:
02275 break;
02276 default:
02277 msg_Warn( p_demux, "need resync, probably broken avi" );
02278 if( AVI_PacketSearch( p_demux ) )
02279 {
02280 msg_Warn( p_demux, "lost sync, abord index creation" );
02281 goto print_stat;
02282 }
02283 }
02284 }
02285
02286 if( ( !p_sys->b_odml && pk.i_pos + pk.i_size >= i_movi_end ) ||
02287 AVI_PacketNext( p_demux ) )
02288 {
02289 break;
02290 }
02291 }
02292
02293 print_stat:
02294 for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
02295 {
02296 msg_Dbg( p_demux,
02297 "stream[%d] creating %d index entries",
02298 i_stream,
02299 p_sys->track[i_stream]->i_idxnb );
02300 }
02301 }
02302
02303
02304
02305
02306 static int AVI_TrackStopFinishedStreams( demux_t *p_demux )
02307 {
02308 demux_sys_t *p_sys = p_demux->p_sys;
02309 unsigned int i;
02310 int b_end = VLC_TRUE;
02311
02312 for( i = 0; i < p_sys->i_track; i++ )
02313 {
02314 avi_track_t *tk = p_sys->track[i];
02315 if( tk->i_idxposc >= tk->i_idxnb )
02316 {
02317 tk->b_activated = VLC_FALSE;
02318 es_out_Control( p_demux->out, ES_OUT_SET_ES_STATE, tk->p_es, VLC_FALSE );
02319 }
02320 else
02321 {
02322 b_end = VLC_FALSE;
02323 }
02324 }
02325 return( b_end );
02326 }
02327
02328
02329
02330
02331 static mtime_t AVI_MovieGetLength( demux_t *p_demux )
02332 {
02333 demux_sys_t *p_sys = p_demux->p_sys;
02334 mtime_t i_maxlength = 0;
02335 unsigned int i;
02336
02337 for( i = 0; i < p_sys->i_track; i++ )
02338 {
02339 avi_track_t *tk = p_sys->track[i];
02340 mtime_t i_length;
02341
02342
02343 if( tk->i_idxnb < 1 || !tk->p_index )
02344 {
02345 continue;
02346 }
02347
02348 if( tk->i_samplesize )
02349 {
02350 i_length = AVI_GetDPTS( tk,
02351 tk->p_index[tk->i_idxnb-1].i_lengthtotal +
02352 tk->p_index[tk->i_idxnb-1].i_length );
02353 }
02354 else
02355 {
02356 i_length = AVI_GetDPTS( tk, tk->i_idxnb );
02357 }
02358 i_length /= (mtime_t)1000000;
02359
02360 msg_Dbg( p_demux,
02361 "stream[%d] length:"I64Fd" (based on index)",
02362 i,
02363 i_length );
02364 i_maxlength = __MAX( i_maxlength, i_length );
02365 }
02366
02367 return i_maxlength;
02368 }