1 /*****************************************************************************
2 * avi.c : AVI file Stream input module for vlc
3 *****************************************************************************
4 * Copyright (C) 2001 VideoLAN
5 * $Id: avi.c,v 1.58 2003/08/22 22:52:48 fenrir Exp $
6 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
21 *****************************************************************************/
23 /*****************************************************************************
25 *****************************************************************************/
26 #include <stdlib.h> /* malloc(), free() */
29 #include <vlc/input.h>
33 #include "../util/sub.h"
38 /*****************************************************************************
40 *****************************************************************************/
41 static int Open ( vlc_object_t * );
42 static void Close ( vlc_object_t * );
45 add_category_hint( N_("avi-demuxer"), NULL, VLC_TRUE );
46 add_bool( "avi-interleaved", 0, NULL,
47 N_("force interleaved method"),
48 N_("force interleaved method"), VLC_TRUE );
49 add_bool( "avi-index", 0, NULL,
50 N_("force index creation"),
51 N_("force index creation"), VLC_TRUE );
53 set_description( N_("AVI demuxer") );
54 set_capability( "demux", 212 );
55 set_callbacks( Open, Close );
58 /*****************************************************************************
60 *****************************************************************************/
61 static int Seek ( input_thread_t *, mtime_t, int );
62 static int Demux_Seekable ( input_thread_t * );
63 static int Demux_UnSeekable( input_thread_t *p_input );
65 #define FREE( p ) if( p ) { free( p ); (p) = NULL; }
66 #define __ABS( x ) ( (x) < 0 ? (-(x)) : (x) )
68 static inline off_t __EVEN( off_t i )
70 return (i & 1) ? i + 1 : i;
73 static mtime_t AVI_PTSToChunk( avi_stream_t *, mtime_t i_pts );
74 static mtime_t AVI_PTSToByte ( avi_stream_t *, mtime_t i_pts );
75 static mtime_t AVI_GetDPTS ( avi_stream_t *, int64_t i_count );
76 static mtime_t AVI_GetPTS ( avi_stream_t * );
79 static int AVI_StreamChunkFind( input_thread_t *, unsigned int i_stream );
80 static int AVI_StreamChunkSet ( input_thread_t *,
81 unsigned int i_stream, unsigned int i_ck );
82 static int AVI_StreamBytesSet ( input_thread_t *,
83 unsigned int i_stream, off_t i_byte );
85 vlc_fourcc_t AVI_FourccGetCodec( unsigned int i_cat, vlc_fourcc_t );
86 static int AVI_GetKeyFlag ( vlc_fourcc_t , uint8_t * );
88 static vlc_bool_t AVI_Interleaved( input_thread_t *p_input );
90 static int AVI_PacketGetHeader( input_thread_t *, avi_packet_t *p_pk );
91 static int AVI_PacketNext ( input_thread_t * );
92 static int AVI_PacketRead ( input_thread_t *, avi_packet_t *, pes_packet_t **);
93 static int AVI_PacketSearch ( input_thread_t * );
95 static void AVI_IndexLoad ( input_thread_t * );
96 static void AVI_IndexCreate ( input_thread_t * );
97 static void AVI_IndexAddEntry( demux_sys_t *, int, AVIIndexEntry_t * );
99 static mtime_t AVI_MovieGetLength( input_thread_t * );
101 /*****************************************************************************
103 *****************************************************************************/
104 static vlc_bool_t AVI_StreamStart ( input_thread_t *, int );
105 static void AVI_StreamStop ( input_thread_t *, int );
106 static int AVI_StreamSeek ( input_thread_t *, int, mtime_t );
107 static int AVI_StreamStopFinishedStreams( input_thread_t *);
109 /*****************************************************************************
110 * Open: check file and initializes AVI structures
111 *****************************************************************************/
112 static int Open( vlc_object_t * p_this )
114 input_thread_t * p_input = (input_thread_t *)p_this;
116 avi_chunk_list_t *p_riff = (avi_chunk_list_t*)&ck_riff;
117 avi_chunk_list_t *p_hdrl, *p_movi;
119 avi_chunk_list_t *p_INFO;
120 avi_chunk_strz_t *p_name;
122 avi_chunk_avih_t *p_avih;
124 es_descriptor_t *p_es = NULL; /* avoid warning */
126 mtime_t i_microsecperframe = 0; // for some subtitle format
128 vlc_bool_t b_stream_audio, b_stream_video;
132 /* Is it an avi file ? */
133 if( input_Peek( p_input, &p_peek, 12 ) < 12 )
135 msg_Err( p_input, "cannot peek()" );
138 if( strncmp( &p_peek[0], "RIFF", 4 ) || strncmp( &p_peek[8], "AVI ", 4 ) )
140 msg_Warn( p_input, "avi module discarded (invalid header)" );
144 /* Initialize input structures. */
145 p_avi = p_input->p_demux_data = malloc( sizeof(demux_sys_t) );
146 memset( p_avi, 0, sizeof( demux_sys_t ) );
149 p_avi->i_movi_lastchunk_pos = 0;
150 p_avi->b_odml = VLC_FALSE;
151 p_avi->b_interleaved = VLC_FALSE;
153 /* Create stream facilities */
154 if( ( p_avi->s = stream_OpenInput( p_input ) ) == NULL )
156 msg_Err( p_input, "cannot create stream_t" );
160 stream_Control( p_avi->s, STREAM_CAN_FASTSEEK, &p_avi->b_seekable );
162 p_input->pf_demux = Demux_Seekable;
163 /* For unseekable stream, automaticaly use Demux_UnSeekable */
164 if( !p_avi->b_seekable || config_GetInt( p_input, "avi-interleaved" ) )
166 p_input->pf_demux = Demux_UnSeekable;
169 if( AVI_ChunkReadRoot( p_avi->s, &p_avi->ck_root ) )
171 msg_Err( p_input, "avi module discarded (invalid file)" );
175 if( AVI_ChunkCount( &p_avi->ck_root, AVIFOURCC_RIFF ) > 1 )
177 unsigned int i_count =
178 AVI_ChunkCount( &p_avi->ck_root, AVIFOURCC_RIFF );
180 msg_Warn( p_input, "multiple riff -> OpenDML ?" );
181 for( i = 1; i < i_count; i++ )
183 avi_chunk_list_t *p_avix;
185 p_avix = AVI_ChunkFind( &p_avi->ck_root, AVIFOURCC_RIFF, i );
186 if( p_avix->i_type == AVIFOURCC_AVIX )
188 msg_Warn( p_input, "detected OpenDML file" );
189 p_avi->b_odml = VLC_TRUE;
195 p_riff = AVI_ChunkFind( &p_avi->ck_root, AVIFOURCC_RIFF, 0 );
196 p_hdrl = AVI_ChunkFind( p_riff, AVIFOURCC_hdrl, 0 );
197 p_movi = AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0 );
199 p_INFO = AVI_ChunkFind( p_riff, AVIFOURCC_INFO, 0 );
200 p_name = AVI_ChunkFind( p_INFO, AVIFOURCC_INAM, 0 );
203 if( !p_hdrl || !p_movi )
205 msg_Err( p_input, "avi module discarded (invalid file)" );
209 if( !( p_avih = AVI_ChunkFind( p_hdrl, AVIFOURCC_avih, 0 ) ) )
211 msg_Err( p_input, "cannot find avih chunk" );
214 p_avi->i_streams = AVI_ChunkCount( p_hdrl, AVIFOURCC_strl );
215 if( p_avih->i_streams != p_avi->i_streams )
218 "found %d stream but %d are declared",
222 if( p_avi->i_streams == 0 )
224 msg_Err( p_input, "no stream defined!" );
228 /* create one program */
229 vlc_mutex_lock( &p_input->stream.stream_lock );
230 if( input_InitStream( p_input, 0 ) == -1)
232 vlc_mutex_unlock( &p_input->stream.stream_lock );
233 msg_Err( p_input, "cannot init stream" );
236 if( input_AddProgram( p_input, 0, 0) == NULL )
238 vlc_mutex_unlock( &p_input->stream.stream_lock );
239 msg_Err( p_input, "cannot add program" );
242 p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
243 p_input->stream.i_mux_rate = 0; /* Fixed later */
244 vlc_mutex_unlock( &p_input->stream.stream_lock );
246 /* print informations on streams */
247 msg_Dbg( p_input, "AVIH: %d stream, flags %s%s%s%s ",
249 p_avih->i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
250 p_avih->i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",
251 p_avih->i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
252 p_avih->i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"" );
254 input_info_category_t *p_cat = input_InfoCategory( p_input, _("Avi") );
255 input_AddInfo( p_cat, _("Number of Streams"), "%d", p_avi->i_streams );
256 input_AddInfo( p_cat, _("Flags"), "%s%s%s%s",
257 p_avih->i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
258 p_avih->i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",
259 p_avih->i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
260 p_avih->i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"" );
263 /* now read info on each stream and create ES */
264 p_avi->pp_info = calloc( p_avi->i_streams,
265 sizeof( avi_stream_t* ) );
266 memset( p_avi->pp_info,
268 sizeof( avi_stream_t* ) * p_avi->i_streams );
270 for( i = 0 ; i < p_avi->i_streams; i++ )
272 avi_chunk_list_t *p_avi_strl;
273 avi_chunk_strh_t *p_avi_strh;
274 avi_chunk_strf_auds_t *p_avi_strf_auds;
275 avi_chunk_strf_vids_t *p_avi_strf_vids;
278 #define p_info p_avi->pp_info[i]
279 p_info = malloc( sizeof(avi_stream_t ) );
280 memset( p_info, 0, sizeof( avi_stream_t ) );
282 p_info->p_index = NULL;
284 p_info->i_idxmax = 0;
286 p_avi_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i );
287 p_avi_strh = AVI_ChunkFind( p_avi_strl, AVIFOURCC_strh, 0 );
288 p_avi_strf_auds = (void*)
289 p_avi_strf_vids = (void*)
290 AVI_ChunkFind( p_avi_strl, AVIFOURCC_strf, 0 );
292 if( !p_avi_strl || !p_avi_strh ||
293 ( !p_avi_strf_auds && !p_avi_strf_vids ) )
295 msg_Warn( p_input, "stream[%d] incomplete", i );
299 /* *** Init p_info *** */
300 p_info->i_rate = p_avi_strh->i_rate;
301 p_info->i_scale = p_avi_strh->i_scale;
302 p_info->i_samplesize = p_avi_strh->i_samplesize;
303 msg_Dbg( p_input, "stream[%d] rate:%d scale:%d samplesize:%d",
305 p_info->i_rate, p_info->i_scale, p_info->i_samplesize );
306 switch( p_avi_strh->i_type )
308 case( AVIFOURCC_auds ):
309 p_info->i_cat = AUDIO_ES;
311 AVI_FourccGetCodec( AUDIO_ES,
312 p_avi_strf_auds->p_wf->wFormatTag );
313 p_info->i_codec = p_info->i_fourcc;
314 i_init_size = p_avi_strf_auds->i_chunk_size;
315 p_init_data = p_avi_strf_auds->p_wf;
316 msg_Dbg( p_input, "stream[%d] audio(0x%x) %d channels %dHz %dbits",
318 p_avi_strf_auds->p_wf->wFormatTag,
319 p_avi_strf_auds->p_wf->nChannels,
320 p_avi_strf_auds->p_wf->nSamplesPerSec,
321 p_avi_strf_auds->p_wf->wBitsPerSample );
323 char psz_cat[ sizeof("Stream") + 10 ];
324 input_info_category_t *p_cat;
325 sprintf( psz_cat, _("Stream %d"), i );
326 p_cat = input_InfoCategory( p_input, psz_cat );
327 input_AddInfo( p_cat, _("Type"), "Audio(0x%x)",
328 p_avi_strf_auds->p_wf->wFormatTag );
329 input_AddInfo( p_cat, _("Codec"), "%4.4s",
330 (const char*)&(p_info->i_codec) );
331 input_AddInfo( p_cat, _("FOURCC"), "0x%x",
333 input_AddInfo( p_cat, _("Channels"), "%d",
334 p_avi_strf_auds->p_wf->nChannels );
335 input_AddInfo( p_cat, _("Sample Rate"), "%d",
336 p_avi_strf_auds->p_wf->nSamplesPerSec );
337 if( p_avi_strf_auds->p_wf->wBitsPerSample > 0
338 && p_info->i_scale != 0 )
340 input_AddInfo( p_cat, _("Bits Per Sample"), "%d",
341 p_avi_strf_auds->p_wf->wBitsPerSample );
342 input_AddInfo( p_cat, _("Audio Bitrate"), "%d",
343 p_info->i_samplesize * p_info->i_rate
349 case( AVIFOURCC_vids ):
350 p_info->i_cat = VIDEO_ES;
351 /* XXX quick hack for playing ffmpeg video, I don't know
352 who is doing something wrong */
353 p_info->i_samplesize = 0;
354 p_info->i_fourcc = p_avi_strf_vids->p_bih->biCompression;
356 AVI_FourccGetCodec( VIDEO_ES, p_info->i_fourcc );
357 i_init_size = p_avi_strf_vids->i_chunk_size;
358 p_init_data = p_avi_strf_vids->p_bih;
359 msg_Dbg( p_input, "stream[%d] video(%4.4s) %dx%d %dbpp %ffps",
361 (char*)&p_avi_strf_vids->p_bih->biCompression,
362 p_avi_strf_vids->p_bih->biWidth,
363 p_avi_strf_vids->p_bih->biHeight,
364 p_avi_strf_vids->p_bih->biBitCount,
365 (float)p_info->i_rate /
366 (float)p_info->i_scale );
368 char psz_cat[ sizeof("Stream") + 10 ];
369 input_info_category_t *p_cat;
370 sprintf( psz_cat, "Stream %d", i );
371 p_cat = input_InfoCategory( p_input, psz_cat );
372 input_AddInfo( p_cat, _("Type"), _("Video") );
373 input_AddInfo( p_cat, _("Codec"), "%4.4s",
374 (const char*)&(p_info->i_codec) );
375 input_AddInfo( p_cat, _("FOURCC"), "0x%x",
377 input_AddInfo( p_cat, _("Resolution"), "%dx%d",
378 p_avi_strf_vids->p_bih->biWidth,
379 p_avi_strf_vids->p_bih->biHeight );
380 input_AddInfo( p_cat, _("Frame Rate"), "%f",
381 (float)p_info->i_rate /
382 (float)p_info->i_scale );
383 input_AddInfo( p_cat, _("Bits Per Pixel"), "%d",
384 p_avi_strf_vids->p_bih->biBitCount );
386 if( i_microsecperframe == 0 )
388 i_microsecperframe = (mtime_t)1000000 *
389 (mtime_t)p_info->i_scale /
390 (mtime_t)p_info->i_rate;
394 msg_Warn( p_input, "stream[%d] unknown type", i );
395 p_info->i_cat = UNKNOWN_ES;
399 char psz_cat[32]; /* We'll clip i just in case */
400 input_info_category_t *p_cat;
401 sprintf( psz_cat, "Stream %d", __MIN( i, 100000 ) );
402 p_cat = input_InfoCategory( p_input, psz_cat );
403 input_AddInfo( p_cat, _("Type"), _("Unknown") );
407 p_info->b_activated = VLC_FALSE;
409 vlc_mutex_lock( &p_input->stream.stream_lock );
411 p_es = input_AddES( p_input, p_input->stream.p_selected_program,
412 1+i, p_info->i_cat, NULL, 0 );
413 vlc_mutex_unlock( &p_input->stream.stream_lock );
414 p_es->i_stream_id =i; /* XXX: i don't use it */
415 p_es->i_fourcc = p_info->i_fourcc;
416 if( p_es->i_cat == AUDIO_ES )
418 if( i_init_size < (int)sizeof( WAVEFORMATEX ) )
420 i_init_size = sizeof( WAVEFORMATEX );
422 p_es->p_waveformatex = malloc( i_init_size );
423 memcpy( p_es->p_waveformatex, p_init_data, i_init_size );
425 else if( p_es->i_cat == VIDEO_ES )
427 p_es->p_bitmapinfoheader = malloc( i_init_size );
428 memcpy( p_es->p_bitmapinfoheader, p_init_data, i_init_size );
433 if( ( p_avi->p_sub = subtitle_New( p_input, NULL, i_microsecperframe ) ) )
435 subtitle_Select( p_avi->p_sub );
438 if( config_GetInt( p_input, "avi-index" ) )
440 if( p_avi->b_seekable )
442 AVI_IndexCreate( p_input );
446 msg_Warn( p_input, "cannot create index (unseekable stream)" );
447 AVI_IndexLoad( p_input );
452 AVI_IndexLoad( p_input );
455 /* *** movie length in sec *** */
456 p_avi->i_length = AVI_MovieGetLength( p_input );
457 if( p_avi->i_length < (mtime_t)p_avih->i_totalframes *
458 (mtime_t)p_avih->i_microsecperframe /
461 msg_Warn( p_input, "broken or missing index, 'seek' will be axproximative or will have strange behavour" );
464 /* fix some BeOS MediaKit generated file */
465 for( i = 0 ; i < p_avi->i_streams; i++ )
467 avi_chunk_list_t *p_avi_strl;
468 avi_chunk_strh_t *p_avi_strh;
469 avi_chunk_strf_auds_t *p_avi_strf_auds;
470 #define p_stream p_avi->pp_info[i]
472 if( p_stream->i_cat != AUDIO_ES )
476 if( p_stream->i_idxnb < 1 ||
477 p_stream->i_scale != 1 ||
478 p_stream->i_samplesize != 0 )
482 p_avi_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i );
483 p_avi_strh = AVI_ChunkFind( p_avi_strl, AVIFOURCC_strh, 0 );
484 p_avi_strf_auds = AVI_ChunkFind( p_avi_strl, AVIFOURCC_strf, 0 );
486 if( p_avi_strf_auds->p_wf->wFormatTag != WAVE_FORMAT_PCM &&
487 (unsigned int)p_stream->i_rate == p_avi_strf_auds->p_wf->nSamplesPerSec )
489 int64_t i_track_length =
490 p_stream->p_index[p_stream->i_idxnb-1].i_length +
491 p_stream->p_index[p_stream->i_idxnb-1].i_lengthtotal;
492 mtime_t i_length = (mtime_t)p_avih->i_totalframes *
493 (mtime_t)p_avih->i_microsecperframe;
497 msg_Warn( p_input, "track[%d] cannot be fixed (BeOS MediaKit generated)", i );
500 p_stream->i_samplesize = 1;
501 p_stream->i_rate = i_track_length * (int64_t)1000000/ i_length;
502 msg_Warn( p_input, "track[%d] fixed with rate=%d scale=%d (BeOS MediaKit generated)", i, p_stream->i_rate, p_stream->i_scale );
507 vlc_mutex_lock( &p_input->stream.stream_lock );
508 if( p_avi->i_length )
510 p_input->stream.i_mux_rate =
511 stream_Size( p_avi->s ) / 50 / p_avi->i_length;
513 p_avi->b_interleaved = AVI_Interleaved( p_input );
514 msg_Dbg( p_input, "interleaved=%s",
515 p_avi->b_interleaved ? "yes" : "no" );
517 vlc_mutex_unlock( &p_input->stream.stream_lock );
519 b_stream_audio = VLC_FALSE;
520 b_stream_video = VLC_FALSE;
522 for( i = 0; i < p_avi->i_streams; i++ )
524 #define tk p_avi->pp_info[i]
525 if( tk->p_es->i_cat == VIDEO_ES && !b_stream_video )
527 b_stream_video = AVI_StreamStart( p_input, i );
529 else if(tk->p_es->i_cat == AUDIO_ES && !b_stream_audio )
531 b_stream_audio = AVI_StreamStart( p_input, i );
536 if( !b_stream_video )
538 msg_Warn( p_input, "no video stream found" );
540 if( !b_stream_audio )
542 msg_Warn( p_input, "no audio stream found!" );
545 vlc_mutex_lock( &p_input->stream.stream_lock );
546 p_input->stream.p_selected_program->b_is_ok = 1;
547 vlc_mutex_unlock( &p_input->stream.stream_lock );
549 if( p_avi->b_seekable )
551 /* we have read all chunk so go back to movi */
552 stream_Seek( p_avi->s, p_movi->i_chunk_pos );
554 /* Skip movi header */
555 stream_Read( p_avi->s, NULL, 12 );
557 p_avi->i_movi_begin = p_movi->i_chunk_pos;
561 AVI_ChunkFreeRoot( p_avi->s, &p_avi->ck_root );
562 stream_Release( p_avi->s );
567 /*****************************************************************************
568 * Close: frees unused data
569 *****************************************************************************/
570 static void Close ( vlc_object_t * p_this )
572 input_thread_t * p_input = (input_thread_t *)p_this;
574 demux_sys_t *p_avi = p_input->p_demux_data ;
576 for( i = 0; i < p_avi->i_streams; i++ )
578 if( p_avi->pp_info[i] )
580 FREE( p_avi->pp_info[i]->p_index );
581 free( p_avi->pp_info[i] );
584 FREE( p_avi->pp_info );
587 subtitle_Close( p_avi->p_sub );
589 AVI_ChunkFreeRoot( p_avi->s, &p_avi->ck_root );
591 stream_Release( p_avi->s );
595 /*****************************************************************************
596 * Demux_Seekable: reads and demuxes data packets for stream seekable
597 *****************************************************************************
598 * AVIDemux: reads and demuxes data packets
599 *****************************************************************************
600 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
601 *****************************************************************************/
602 typedef struct avi_stream_toread_s
608 off_t i_posf; // where we will read :
609 // if i_idxposb == 0 : begining of chunk (+8 to acces data)
610 // else : point on data directly
611 } avi_stream_toread_t;
613 static int Demux_Seekable( input_thread_t *p_input )
615 unsigned int i_stream_count;
616 unsigned int i_stream;
618 vlc_bool_t b_play_audio;
619 vlc_bool_t b_video; /* is there some video track selected */
620 // cannot be more than 100 stream (dcXX or wbXX)
621 avi_stream_toread_t toread[100];
623 demux_sys_t *p_avi = p_input->p_demux_data;
626 /* detect new selected/unselected streams */
627 for( i_stream = 0,i_stream_count= 0, b_video = VLC_FALSE;
628 i_stream < p_avi->i_streams; i_stream++ )
630 #define p_stream p_avi->pp_info[i_stream]
633 if( p_stream->p_es->p_decoder_fifo &&
634 !p_stream->b_activated )
636 AVI_StreamStart( p_input, i_stream );
639 if( !p_stream->p_es->p_decoder_fifo &&
640 p_stream->b_activated )
642 AVI_StreamStop( p_input, i_stream );
645 if( p_stream->b_activated )
648 if( p_stream->i_cat == VIDEO_ES )
656 if( i_stream_count <= 0 )
658 msg_Warn( p_input, "no track selected, exiting..." );
662 if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
666 /* first wait for empty buffer, arbitrary time FIXME */
667 //msleep( DEFAULT_PTS_DELAY );
669 i_date = (mtime_t)1000000 *
670 (mtime_t)p_avi->i_length *
671 (mtime_t)stream_Tell( p_avi->s ) /
672 (mtime_t)stream_Size( p_avi->s );
673 i_percent = 100 * stream_Tell( p_avi->s ) /
674 stream_Size( p_avi->s );
676 Seek( p_input, i_date, i_percent);
680 subtitle_Seek( p_avi->p_sub, p_avi->i_time );
685 /* wait for the good time */
687 p_avi->i_pcr = p_avi->i_time * 9 / 100;
689 input_ClockManageRef( p_input,
690 p_input->stream.p_selected_program,
694 p_avi->i_time += 25*1000; /* read 25ms */
698 subtitle_Demux( p_avi->p_sub, p_avi->i_time );
701 /* Check if we need to send the audio data to decoder */
702 b_play_audio = !p_input->stream.control.b_mute;
705 for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
707 #define p_stream p_avi->pp_info[i_stream]
710 toread[i_stream].b_ok = p_stream->b_activated;
711 if( p_stream->i_idxposc < p_stream->i_idxnb )
713 toread[i_stream].i_posf =
714 p_stream->p_index[p_stream->i_idxposc].i_pos;
715 if( p_stream->i_idxposb > 0 )
717 toread[i_stream].i_posf += 8 + p_stream->i_idxposb;
722 toread[i_stream].i_posf = -1;
725 i_dpts = p_avi->i_time - AVI_GetPTS( p_stream );
727 if( p_stream->i_samplesize )
729 toread[i_stream].i_toread = AVI_PTSToByte( p_stream,
734 toread[i_stream].i_toread = AVI_PTSToChunk( p_stream,
740 toread[i_stream].i_toread *= -1;
745 b_stream = VLC_FALSE;
749 #define p_stream p_avi->pp_info[i_stream]
756 /* search for first chunk to be read */
757 for( i = 0, b_done = VLC_TRUE, i_pos = -1; i < p_avi->i_streams; i++ )
759 if( !toread[i].b_ok ||
760 AVI_GetDPTS( p_avi->pp_info[i],
761 toread[i].i_toread ) <= -25 * 1000 )
766 if( toread[i].i_toread > 0 )
768 b_done = VLC_FALSE; // not yet finished
771 if( toread[i].i_posf > 0 )
773 if( i_pos == -1 || i_pos > toread[i_stream].i_posf )
776 i_pos = toread[i].i_posf;
783 // return( b_stream ? 1 : 0 );
789 /* no valid index, we will parse directly the stream
790 * in case we fail we will disable all finished stream */
791 if( p_avi->i_movi_lastchunk_pos >= p_avi->i_movi_begin + 12 )
793 stream_Seek( p_avi->s, p_avi->i_movi_lastchunk_pos );
794 if( AVI_PacketNext( p_input ) )
796 return( AVI_StreamStopFinishedStreams( p_input ) ? 0 : 1 );
801 stream_Seek( p_avi->s, p_avi->i_movi_begin + 12 );
808 if( AVI_PacketGetHeader( p_input, &avi_pk ) )
811 "cannot get packet header, track disabled" );
812 return( AVI_StreamStopFinishedStreams( p_input ) ? 0 : 1 );
814 if( avi_pk.i_stream >= p_avi->i_streams ||
815 ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
817 if( AVI_PacketNext( p_input ) )
820 "cannot skip packet, track disabled" );
821 return( AVI_StreamStopFinishedStreams( p_input ) ? 0 : 1 );
827 /* add this chunk to the index */
828 AVIIndexEntry_t index;
830 index.i_id = avi_pk.i_fourcc;
832 AVI_GetKeyFlag(p_avi->pp_info[avi_pk.i_stream]->i_codec,
834 index.i_pos = avi_pk.i_pos;
835 index.i_length = avi_pk.i_size;
836 AVI_IndexAddEntry( p_avi, avi_pk.i_stream, &index );
838 i_stream = avi_pk.i_stream;
839 /* do we will read this data ? */
840 if( AVI_GetDPTS( p_stream,
841 toread[i_stream].i_toread ) > -25 * 1000 )
847 if( AVI_PacketNext( p_input ) )
850 "cannot skip packet, track disabled" );
851 return( AVI_StreamStopFinishedStreams( p_input ) ? 0 : 1 );
860 stream_Seek( p_avi->s, i_pos );
863 /* read thoses data */
864 if( p_stream->i_samplesize )
866 unsigned int i_toread;
868 if( ( i_toread = toread[i_stream].i_toread ) <= 0 )
870 if( p_stream->i_samplesize > 1 )
872 i_toread = p_stream->i_samplesize;
876 i_toread = __MAX( AVI_PTSToByte( p_stream, 20 * 1000 ), 100 );
879 i_size = __MIN( p_stream->p_index[p_stream->i_idxposc].i_length -
885 i_size = p_stream->p_index[p_stream->i_idxposc].i_length;
888 if( p_stream->i_idxposb == 0 )
890 i_size += 8; // need to read and skip header
893 if( ( p_pes = stream_PesPacket( p_avi->s, __EVEN( i_size ) ) ) == NULL )
895 msg_Warn( p_input, "failled reading data" );
896 AVI_StreamStop( p_input, i_stream );
897 toread[i_stream].b_ok = VLC_FALSE;
900 if( i_size % 2 ) // read was padded on word boundary
902 p_pes->p_last->p_payload_end--;
906 if( p_stream->i_idxposb == 0 )
908 p_pes->p_first->p_payload_start += 8;
909 p_pes->i_pes_size -= 8;
912 p_pes->i_pts = AVI_GetPTS( p_stream );
915 /* fix pts for audio: ie pts sould be for the first byte of the first frame */
916 if( p_stream->i_samplesize == 1 )
918 AVI_FixPTS( p_stream, p_pes );
923 if( p_stream->i_samplesize )
925 if( p_stream->i_idxposb == 0 )
929 toread[i_stream].i_toread -= i_size;
930 p_stream->i_idxposb += i_size;
931 if( p_stream->i_idxposb >=
932 p_stream->p_index[p_stream->i_idxposc].i_length )
934 p_stream->i_idxposb = 0;
935 p_stream->i_idxposc++;
940 toread[i_stream].i_toread--;
941 p_stream->i_idxposc++;
944 if( p_stream->i_idxposc < p_stream->i_idxnb)
946 toread[i_stream].i_posf =
947 p_stream->p_index[p_stream->i_idxposc].i_pos;
948 if( p_stream->i_idxposb > 0 )
950 toread[i_stream].i_posf += 8 + p_stream->i_idxposb;
956 toread[i_stream].i_posf = -1;
959 b_stream = VLC_TRUE; // at least one read succeed
961 if( p_stream->p_es && p_stream->p_es->p_decoder_fifo &&
962 ( b_play_audio || p_stream->i_cat != AUDIO_ES ) )
966 input_ClockGetTS( p_input,
967 p_input->stream.p_selected_program,
968 p_pes->i_pts * 9/100);
970 p_pes->i_rate = p_input->stream.control.i_rate;
972 input_DecodePES( p_stream->p_es->p_decoder_fifo, p_pes );
976 input_DeletePES( p_input->p_method_data, p_pes );
982 /*****************************************************************************
983 * Demux_UnSeekable: reads and demuxes data packets for unseekable file
984 *****************************************************************************
985 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
986 *****************************************************************************/
987 static int Demux_UnSeekable( input_thread_t *p_input )
989 demux_sys_t *p_avi = p_input->p_demux_data;
990 avi_stream_t *p_stream_master;
992 unsigned int i_stream;
993 unsigned int i_packet;
995 /* Check if we need to send the audio data to decoder */
996 b_audio = !p_input->stream.control.b_mute;
998 input_ClockManageRef( p_input,
999 p_input->stream.p_selected_program,
1001 /* *** find master stream for data packet skipping algo *** */
1002 /* *** -> first video, if any, or first audio ES *** */
1003 for( i_stream = 0, p_stream_master = NULL;
1004 i_stream < p_avi->i_streams; i_stream++ )
1006 #define p_stream p_avi->pp_info[i_stream]
1007 if( p_stream->p_es &&
1008 p_stream->p_es->p_decoder_fifo )
1010 if( p_stream->i_cat == VIDEO_ES )
1012 p_stream_master = p_stream;
1015 if( p_stream->i_cat == AUDIO_ES && !p_stream_master )
1017 p_stream_master = p_stream;
1022 if( !p_stream_master )
1024 msg_Warn( p_input, "no more stream selected" );
1028 p_avi->i_pcr = AVI_GetPTS( p_stream_master ) * 9 / 100;
1030 for( i_packet = 0; i_packet < 10; i_packet++)
1032 #define p_stream p_avi->pp_info[avi_pk.i_stream]
1034 avi_packet_t avi_pk;
1036 if( AVI_PacketGetHeader( p_input, &avi_pk ) )
1041 if( avi_pk.i_stream >= p_avi->i_streams ||
1042 ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
1044 /* we haven't found an audio or video packet:
1045 * - we have seek, found first next packet
1046 * - others packets could be found, skip them
1048 switch( avi_pk.i_fourcc )
1050 case AVIFOURCC_JUNK:
1051 case AVIFOURCC_LIST:
1052 case AVIFOURCC_RIFF:
1053 return( !AVI_PacketNext( p_input ) ? 1 : 0 );
1054 case AVIFOURCC_idx1:
1057 return( !AVI_PacketNext( p_input ) ? 1 : 0 );
1062 "seems to have lost position, resync" );
1063 if( AVI_PacketSearch( p_input ) )
1065 msg_Err( p_input, "resync failed" );
1072 /* do will send this packet to decoder ? */
1073 if( ( !b_audio && avi_pk.i_cat == AUDIO_ES )||
1075 !p_stream->p_es->p_decoder_fifo )
1077 if( AVI_PacketNext( p_input ) )
1084 /* it's a selected stream, check for time */
1085 if( __ABS( AVI_GetPTS( p_stream ) -
1086 AVI_GetPTS( p_stream_master ) )< 600*1000 )
1088 /* load it and send to decoder */
1089 pes_packet_t *p_pes;
1090 if( AVI_PacketRead( p_input, &avi_pk, &p_pes ) || !p_pes)
1096 input_ClockGetTS( p_input,
1097 p_input->stream.p_selected_program,
1098 AVI_GetPTS( p_stream ) * 9/100);
1100 p_pes->i_rate = p_input->stream.control.i_rate;
1102 input_DecodePES( p_stream->p_es->p_decoder_fifo, p_pes );
1106 if( AVI_PacketNext( p_input ) )
1113 /* *** update stream time position *** */
1114 if( p_stream->i_samplesize )
1116 p_stream->i_idxposb += avi_pk.i_size;
1120 p_stream->i_idxposc++;
1131 /*****************************************************************************
1132 * Seek: goto to i_date or i_percent
1133 *****************************************************************************
1134 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
1135 *****************************************************************************/
1136 static int Seek ( input_thread_t *p_input,
1137 mtime_t i_date, int i_percent )
1140 demux_sys_t *p_avi = p_input->p_demux_data;
1141 unsigned int i_stream;
1143 "seek requested: "I64Fd" secondes %d%%",
1147 if( p_avi->b_seekable )
1149 if( !p_avi->i_length || p_avi->b_interleaved )
1151 avi_stream_t *p_stream;
1154 /* use i_percent to create a true i_date */
1155 if( !p_avi->b_interleaved )
1158 "mmh, seeking without index at %d%%"
1159 " work only for interleaved file", i_percent );
1162 if( i_percent >= 100 )
1164 msg_Warn( p_input, "cannot seek so far !" );
1167 i_percent = __MAX( i_percent, 0 );
1169 /* try to find chunk that is at i_percent or the file */
1170 i_pos = __MAX( i_percent *
1171 stream_Size( p_avi->s ) / 100,
1172 p_avi->i_movi_begin );
1173 /* search first selected stream */
1174 for( i_stream = 0, p_stream = NULL;
1175 i_stream < p_avi->i_streams; i_stream++ )
1177 p_stream = p_avi->pp_info[i_stream];
1178 if( p_stream->b_activated )
1183 if( !p_stream || !p_stream->b_activated )
1185 msg_Warn( p_input, "cannot find any selected stream" );
1189 /* be sure that the index exit */
1190 if( AVI_StreamChunkSet( p_input,
1194 msg_Warn( p_input, "cannot seek" );
1198 while( i_pos >= p_stream->p_index[p_stream->i_idxposc].i_pos +
1199 p_stream->p_index[p_stream->i_idxposc].i_length + 8 )
1201 /* search after i_idxposc */
1202 if( AVI_StreamChunkSet( p_input,
1203 i_stream, p_stream->i_idxposc + 1 ) )
1205 msg_Warn( p_input, "cannot seek" );
1209 i_date = AVI_GetPTS( p_stream );
1210 /* TODO better support for i_samplesize != 0 */
1211 msg_Dbg( p_input, "estimate date "I64Fd, i_date );
1214 #define p_stream p_avi->pp_info[i_stream]
1216 /* seek for chunk based streams */
1217 for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
1219 if( p_stream->b_activated && !p_stream->i_samplesize )
1220 // if( p_stream->b_activated )
1222 AVI_StreamSeek( p_input, i_stream, i_date );
1223 p_avi->i_time = __MAX( AVI_GetPTS( p_stream ),
1230 i_date = p_avi->i_time;
1232 /* seek for bytes based streams */
1233 for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
1235 if( p_stream->b_activated && p_stream->i_samplesize )
1237 AVI_StreamSeek( p_input, i_stream, i_date );
1238 // p_avi->i_time = __MAX( AVI_GetPTS( p_stream ), p_avi->i_time );
1241 msg_Dbg( p_input, "seek: "I64Fd" secondes", p_avi->i_time /1000000 );
1242 /* set true movie time */
1244 if( !p_avi->i_time )
1246 p_avi->i_time = i_date;
1253 msg_Err( p_input, "shouldn't yet be executed" );
1259 /*****************************************************************************
1260 * Function to convert pts to chunk or byte
1261 *****************************************************************************/
1263 static mtime_t AVI_PTSToChunk( avi_stream_t *tk, mtime_t i_pts )
1265 return (mtime_t)((int64_t)i_pts *
1266 (int64_t)tk->i_rate /
1267 (int64_t)tk->i_scale /
1270 static mtime_t AVI_PTSToByte( avi_stream_t *tk, mtime_t i_pts )
1272 return (mtime_t)((int64_t)i_pts *
1273 (int64_t)tk->i_rate /
1274 (int64_t)tk->i_scale /
1276 (int64_t)tk->i_samplesize );
1279 static mtime_t AVI_GetDPTS( avi_stream_t *tk, int64_t i_count )
1283 i_dpts = (mtime_t)( (int64_t)1000000 *
1285 (int64_t)tk->i_scale /
1286 (int64_t)tk->i_rate );
1288 if( tk->i_samplesize )
1290 return i_dpts / tk->i_samplesize;
1295 static mtime_t AVI_GetPTS( avi_stream_t *tk )
1297 if( tk->i_samplesize )
1299 int64_t i_count = 0;
1301 /* we need a valid entry we will emulate one */
1302 if( tk->i_idxposc == tk->i_idxnb )
1306 /* use the last entry */
1307 i_count = tk->p_index[tk->i_idxnb - 1].i_lengthtotal
1308 + tk->p_index[tk->i_idxnb - 1].i_length;
1313 i_count = tk->p_index[tk->i_idxposc].i_lengthtotal;
1315 return AVI_GetDPTS( tk, i_count + tk->i_idxposb );
1319 return AVI_GetDPTS( tk, tk->i_idxposc );
1324 static void AVI_FixPTS( avi_stream_t *p_stream, pes_packet_t *p_pes )
1326 data_packet_t *p_data;
1330 switch( p_stream->i_fourcc )
1332 case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
1333 p_data = p_pes->p_first;
1336 p = p_data->p_payload_start;
1337 while( p < p_data->p_payload_end - 2 )
1339 if( p[0] == 0xff && ( p[1]&0xe0) == 0xe0 )
1341 mtime_t i_diff = AVI_GetDPTS( p_stream, i_pos );
1342 p_pes->i_dts += i_diff;
1343 p_pes->i_pts += i_diff;
1348 p_data = p_data->p_next;
1351 case VLC_FOURCC( 'a', '5', '2', ' ' ):
1352 p_data = p_pes->p_first;
1355 p = p_data->p_payload_start;
1356 while( p < p_data->p_payload_end - 2 )
1358 if( p[0] == 0x0b && p[1] == 0x77 )
1360 mtime_t i_diff = AVI_GetDPTS( p_stream, i_pos );
1361 p_pes->i_dts += i_diff;
1362 p_pes->i_pts += i_diff;
1366 p_data = p_data->p_next;
1370 /* we can't fix :( */
1376 static int AVI_StreamChunkFind( input_thread_t *p_input,
1377 unsigned int i_stream )
1379 demux_sys_t *p_avi = p_input->p_demux_data;
1380 avi_packet_t avi_pk;
1382 /* find first chunk of i_stream that isn't in index */
1384 if( p_avi->i_movi_lastchunk_pos >= p_avi->i_movi_begin + 12 )
1386 stream_Seek( p_avi->s, p_avi->i_movi_lastchunk_pos );
1387 if( AVI_PacketNext( p_input ) )
1389 return VLC_EGENERIC;
1394 stream_Seek( p_avi->s, p_avi->i_movi_begin + 12 );
1400 if( AVI_PacketGetHeader( p_input, &avi_pk ) )
1402 msg_Warn( p_input, "cannot get packet header" );
1403 return VLC_EGENERIC;
1405 if( avi_pk.i_stream >= p_avi->i_streams ||
1406 ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
1408 if( AVI_PacketNext( p_input ) )
1410 return VLC_EGENERIC;
1415 /* add this chunk to the index */
1416 AVIIndexEntry_t index;
1418 index.i_id = avi_pk.i_fourcc;
1420 AVI_GetKeyFlag(p_avi->pp_info[avi_pk.i_stream]->i_codec,
1422 index.i_pos = avi_pk.i_pos;
1423 index.i_length = avi_pk.i_size;
1424 AVI_IndexAddEntry( p_avi, avi_pk.i_stream, &index );
1426 if( avi_pk.i_stream == i_stream )
1431 if( AVI_PacketNext( p_input ) )
1433 return VLC_EGENERIC;
1440 /* be sure that i_ck will be a valid index entry */
1441 static int AVI_StreamChunkSet( input_thread_t *p_input,
1442 unsigned int i_stream,
1445 demux_sys_t *p_avi = p_input->p_demux_data;
1446 avi_stream_t *p_stream = p_avi->pp_info[i_stream];
1448 p_stream->i_idxposc = i_ck;
1449 p_stream->i_idxposb = 0;
1451 if( i_ck >= p_stream->i_idxnb )
1453 p_stream->i_idxposc = p_stream->i_idxnb - 1;
1456 p_stream->i_idxposc++;
1457 if( AVI_StreamChunkFind( p_input, i_stream ) )
1459 return VLC_EGENERIC;
1462 } while( p_stream->i_idxposc < i_ck );
1469 /* XXX FIXME up to now, we assume that all chunk are one after one */
1470 static int AVI_StreamBytesSet( input_thread_t *p_input,
1471 unsigned int i_stream,
1474 demux_sys_t *p_avi = p_input->p_demux_data;
1475 avi_stream_t *p_stream = p_avi->pp_info[i_stream];
1477 if( ( p_stream->i_idxnb > 0 )
1478 &&( i_byte < p_stream->p_index[p_stream->i_idxnb - 1].i_lengthtotal +
1479 p_stream->p_index[p_stream->i_idxnb - 1].i_length ) )
1481 /* index is valid to find the ck */
1482 /* uses dichototmie to be fast enougth */
1483 int i_idxposc = __MIN( p_stream->i_idxposc, p_stream->i_idxnb - 1 );
1484 int i_idxmax = p_stream->i_idxnb;
1488 if( p_stream->p_index[i_idxposc].i_lengthtotal > i_byte )
1490 i_idxmax = i_idxposc ;
1491 i_idxposc = ( i_idxmin + i_idxposc ) / 2 ;
1495 if( p_stream->p_index[i_idxposc].i_lengthtotal +
1496 p_stream->p_index[i_idxposc].i_length <= i_byte)
1498 i_idxmin = i_idxposc ;
1499 i_idxposc = (i_idxmax + i_idxposc ) / 2 ;
1503 p_stream->i_idxposc = i_idxposc;
1504 p_stream->i_idxposb = i_byte -
1505 p_stream->p_index[i_idxposc].i_lengthtotal;
1514 p_stream->i_idxposc = p_stream->i_idxnb - 1;
1515 p_stream->i_idxposb = 0;
1518 p_stream->i_idxposc++;
1519 if( AVI_StreamChunkFind( p_input, i_stream ) )
1521 return VLC_EGENERIC;
1524 } while( p_stream->p_index[p_stream->i_idxposc].i_lengthtotal +
1525 p_stream->p_index[p_stream->i_idxposc].i_length <= i_byte );
1527 p_stream->i_idxposb = i_byte -
1528 p_stream->p_index[p_stream->i_idxposc].i_lengthtotal;
1533 static int AVI_StreamSeek( input_thread_t *p_input,
1537 demux_sys_t *p_avi = p_input->p_demux_data;
1538 #define p_stream p_avi->pp_info[i_stream]
1541 i_oldpts = AVI_GetPTS( p_stream );
1543 if( !p_stream->i_samplesize )
1545 if( AVI_StreamChunkSet( p_input,
1547 AVI_PTSToChunk( p_stream, i_date ) ) )
1549 return VLC_EGENERIC;
1553 "old:"I64Fd" %s new "I64Fd,
1555 i_oldpts > i_date ? ">" : "<",
1558 if( p_stream->i_cat == VIDEO_ES )
1560 /* search key frame */
1561 if( i_date < i_oldpts )
1563 while( p_stream->i_idxposc > 0 &&
1564 !( p_stream->p_index[p_stream->i_idxposc].i_flags &
1567 if( AVI_StreamChunkSet( p_input,
1569 p_stream->i_idxposc - 1 ) )
1571 return VLC_EGENERIC;
1577 while( p_stream->i_idxposc < p_stream->i_idxnb &&
1578 !( p_stream->p_index[p_stream->i_idxposc].i_flags &
1581 if( AVI_StreamChunkSet( p_input,
1583 p_stream->i_idxposc + 1 ) )
1585 return VLC_EGENERIC;
1593 if( AVI_StreamBytesSet( p_input,
1595 AVI_PTSToByte( p_stream, i_date ) ) )
1597 return VLC_EGENERIC;
1604 /*****************************************************************************
1605 * AVI_Interleaved: check weither a file is interleaved or not.
1606 *****************************************************************************/
1607 static vlc_bool_t AVI_Interleaved( input_thread_t *p_input )
1609 demux_sys_t *p_sys = p_input->p_demux_data;
1612 vlc_bool_t b_ret = VLC_TRUE;
1616 if( stream_Size( p_sys->s ) <= 100 )
1621 i_max = __MIN( 2000000, stream_Size( p_sys->s ) / 100 );
1623 #define tk p_sys->pp_info[i]
1624 while( i_time < p_sys->i_length * (mtime_t)1000000)
1630 for( i = 0; i < p_sys->i_streams; i++ )
1632 while( AVI_GetPTS( tk ) < i_time && tk->i_idxposc < tk->i_idxnb - 1 )
1639 i_ref = tk->p_index[tk->i_idxposc].i_pos;
1641 if( __ABS( tk->p_index[tk->i_idxposc].i_pos - i_ref ) > i_max ||
1642 tk->p_index[tk->i_idxposc].i_length > i_max )
1644 msg_Dbg( p_input, "interleaved=no because ref=%lld pos=%lld length=%d (max=%lld)",
1645 i_ref, tk->p_index[tk->i_idxposc].i_pos, tk->p_index[tk->i_idxposc].i_length, i_max );
1653 for( i = 0; i < p_sys->i_streams; i++ )
1662 /****************************************************************************
1663 * Return VLC_TRUE if it's a key frame
1664 ****************************************************************************/
1665 static int AVI_GetKeyFlag( vlc_fourcc_t i_fourcc, uint8_t *p_byte )
1671 * startcode: 0x00000100 32bits
1672 * framenumber ? 5bits
1673 * piture type 0(I),1(P) 2bits
1675 if( GetDWBE( p_byte ) != 0x00000100 )
1677 /* it's not an msmpegv1 stream, strange...*/
1678 return AVIIF_KEYFRAME;
1682 return p_byte[4] & 0x06 ? 0 : AVIIF_KEYFRAME;
1685 case FOURCC_DIV3: // wmv1 also
1687 * picture type 0(I),1(P) 2bits
1689 return p_byte[0] & 0xC0 ? 0 : AVIIF_KEYFRAME;
1691 /* we should find first occurence of 0x000001b6 (32bits)
1692 * startcode: 0x000001b6 32bits
1693 * piture type 0(I),1(P) 2bits
1695 if( GetDWBE( p_byte ) != 0x000001b6 )
1697 /* not true , need to find the first VOP header */
1698 return AVIIF_KEYFRAME;
1702 return p_byte[4] & 0xC0 ? 0 : AVIIF_KEYFRAME;
1705 /* I can't do it, so say yes */
1706 return AVIIF_KEYFRAME;
1710 vlc_fourcc_t AVI_FourccGetCodec( unsigned int i_cat, vlc_fourcc_t i_codec )
1715 wf_tag_to_fourcc( i_codec, &i_codec, NULL );
1719 // XXX DIV1 <- msmpeg4v1, DIV2 <- msmpeg4v2, DIV3 <- msmpeg4v3, mp4v for mpeg4
1769 return VLC_FOURCC( 'u', 'n', 'd', 'f' );
1773 /****************************************************************************
1775 ****************************************************************************/
1776 static void AVI_ParseStreamHeader( vlc_fourcc_t i_id,
1777 int *pi_number, int *pi_type )
1779 #define SET_PTR( p, v ) if( p ) *(p) = (v);
1782 c1 = ((uint8_t *)&i_id)[0];
1783 c2 = ((uint8_t *)&i_id)[1];
1785 if( c1 < '0' || c1 > '9' || c2 < '0' || c2 > '9' )
1787 SET_PTR( pi_number, 100 ); /* > max stream number */
1788 SET_PTR( pi_type, UNKNOWN_ES );
1792 SET_PTR( pi_number, (c1 - '0') * 10 + (c2 - '0' ) );
1793 switch( VLC_TWOCC( ((uint8_t *)&i_id)[2], ((uint8_t *)&i_id)[3] ) )
1796 SET_PTR( pi_type, AUDIO_ES );
1800 SET_PTR( pi_type, VIDEO_ES );
1803 SET_PTR( pi_type, UNKNOWN_ES );
1810 /****************************************************************************
1812 ****************************************************************************/
1813 static int AVI_PacketGetHeader( input_thread_t *p_input, avi_packet_t *p_pk )
1815 demux_sys_t *p_sys = p_input->p_demux_data;
1818 if( stream_Peek( p_sys->s, &p_peek, 16 ) < 16 )
1820 return VLC_EGENERIC;
1822 p_pk->i_fourcc = VLC_FOURCC( p_peek[0], p_peek[1], p_peek[2], p_peek[3] );
1823 p_pk->i_size = GetDWLE( p_peek + 4 );
1824 p_pk->i_pos = stream_Tell( p_sys->s );
1825 if( p_pk->i_fourcc == AVIFOURCC_LIST || p_pk->i_fourcc == AVIFOURCC_RIFF )
1827 p_pk->i_type = VLC_FOURCC( p_peek[8], p_peek[9],
1828 p_peek[10], p_peek[11] );
1835 memcpy( p_pk->i_peek, p_peek + 8, 8 );
1837 AVI_ParseStreamHeader( p_pk->i_fourcc, &p_pk->i_stream, &p_pk->i_cat );
1841 static int AVI_PacketNext( input_thread_t *p_input )
1843 demux_sys_t *p_sys = p_input->p_demux_data;
1844 avi_packet_t avi_ck;
1847 if( AVI_PacketGetHeader( p_input, &avi_ck ) )
1849 return VLC_EGENERIC;
1852 if( avi_ck.i_fourcc == AVIFOURCC_LIST &&
1853 ( avi_ck.i_type == AVIFOURCC_rec || avi_ck.i_type == AVIFOURCC_movi ) )
1857 else if( avi_ck.i_fourcc == AVIFOURCC_RIFF &&
1858 avi_ck.i_type == AVIFOURCC_AVIX )
1864 i_skip = __EVEN( avi_ck.i_size ) + 8;
1867 if( stream_Read( p_sys->s, NULL, i_skip ) != i_skip )
1869 return VLC_EGENERIC;
1873 static int AVI_PacketRead( input_thread_t *p_input,
1875 pes_packet_t **pp_pes )
1877 demux_sys_t *p_sys = p_input->p_demux_data;
1881 i_size = __EVEN( p_pk->i_size + 8 );
1883 if( ( *pp_pes = stream_PesPacket( p_sys->s, i_size ) ) == NULL )
1885 return VLC_EGENERIC;
1887 (*pp_pes)->p_first->p_payload_start += 8;
1888 (*pp_pes)->i_pes_size -= 8;
1890 if( i_size != p_pk->i_size + 8 )
1892 (*pp_pes)->p_last->p_payload_end--;
1893 (*pp_pes)->i_pes_size--;
1899 static int AVI_PacketSearch( input_thread_t *p_input )
1901 demux_sys_t *p_avi = p_input->p_demux_data;
1903 avi_packet_t avi_pk;
1906 if( stream_Read( p_avi->s, NULL, 1 ) != 1 )
1908 return VLC_EGENERIC;
1910 AVI_PacketGetHeader( p_input, &avi_pk );
1911 if( avi_pk.i_stream < p_avi->i_streams &&
1912 ( avi_pk.i_cat == AUDIO_ES || avi_pk.i_cat == VIDEO_ES ) )
1916 switch( avi_pk.i_fourcc )
1918 case AVIFOURCC_JUNK:
1919 case AVIFOURCC_LIST:
1920 case AVIFOURCC_RIFF:
1921 case AVIFOURCC_idx1:
1927 /****************************************************************************
1929 ****************************************************************************/
1930 static void AVI_IndexAddEntry( demux_sys_t *p_avi,
1932 AVIIndexEntry_t *p_index)
1934 avi_stream_t *tk = p_avi->pp_info[i_stream];
1936 /* Update i_movi_lastchunk_pos */
1937 if( p_avi->i_movi_lastchunk_pos < p_index->i_pos )
1939 p_avi->i_movi_lastchunk_pos = p_index->i_pos;
1943 if( tk->i_idxnb >= tk->i_idxmax )
1945 tk->i_idxmax += 16384;
1946 tk->p_index = realloc( tk->p_index,
1947 tk->i_idxmax * sizeof( AVIIndexEntry_t ) );
1948 if( tk->p_index == NULL )
1953 /* calculate cumulate length */
1954 if( tk->i_idxnb > 0 )
1956 p_index->i_lengthtotal =
1957 tk->p_index[tk->i_idxnb - 1].i_length +
1958 tk->p_index[tk->i_idxnb - 1].i_lengthtotal;
1962 p_index->i_lengthtotal = 0;
1965 tk->p_index[tk->i_idxnb++] = *p_index;
1968 static int AVI_IndexLoad_idx1( input_thread_t *p_input )
1970 demux_sys_t *p_avi = p_input->p_demux_data;
1972 avi_chunk_list_t *p_riff;
1973 avi_chunk_list_t *p_movi;
1974 avi_chunk_idx1_t *p_idx1;
1976 unsigned int i_stream;
1977 unsigned int i_index;
1981 p_riff = AVI_ChunkFind( &p_avi->ck_root, AVIFOURCC_RIFF, 0);
1982 p_idx1 = AVI_ChunkFind( p_riff, AVIFOURCC_idx1, 0);
1983 p_movi = AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0);
1987 msg_Warn( p_input, "cannot find idx1 chunk, no index defined" );
1988 return VLC_EGENERIC;
1991 /* *** calculate offset *** */
1992 /* Well, avi is __SHIT__ so test more than one entry
1993 * (needed for some avi files) */
1995 for( i = 0; i < __MIN( p_idx1->i_entry_count, 10 ); i++ )
1997 if( p_idx1->entry[i].i_pos < p_movi->i_chunk_pos )
1999 i_offset = p_movi->i_chunk_pos + 8;
2004 for( i_index = 0; i_index < p_idx1->i_entry_count; i_index++ )
2008 AVI_ParseStreamHeader( p_idx1->entry[i_index].i_fourcc,
2011 if( i_stream < p_avi->i_streams &&
2012 i_cat == p_avi->pp_info[i_stream]->i_cat )
2014 AVIIndexEntry_t index;
2015 index.i_id = p_idx1->entry[i_index].i_fourcc;
2017 p_idx1->entry[i_index].i_flags&(~AVIIF_FIXKEYFRAME);
2018 index.i_pos = p_idx1->entry[i_index].i_pos + i_offset;
2019 index.i_length = p_idx1->entry[i_index].i_length;
2020 AVI_IndexAddEntry( p_avi, i_stream, &index );
2026 static void __Parse_indx( input_thread_t *p_input,
2028 avi_chunk_indx_t *p_indx )
2030 demux_sys_t *p_avi = p_input->p_demux_data;
2031 AVIIndexEntry_t index;
2034 msg_Dbg( p_input, "loading subindex(0x%x) %d entries", p_indx->i_indextype, p_indx->i_entriesinuse );
2035 if( p_indx->i_indexsubtype == 0 )
2037 for( i = 0; i < p_indx->i_entriesinuse; i++ )
2039 index.i_id = p_indx->i_id;
2040 index.i_flags = p_indx->idx.std[i].i_size & 0x80000000 ? 0 : AVIIF_KEYFRAME;
2041 index.i_pos = p_indx->i_baseoffset + p_indx->idx.std[i].i_offset - 8;
2042 index.i_length = p_indx->idx.std[i].i_size&0x7fffffff;
2044 AVI_IndexAddEntry( p_avi, i_stream, &index );
2047 else if( p_indx->i_indexsubtype == AVI_INDEX_2FIELD )
2049 for( i = 0; i < p_indx->i_entriesinuse; i++ )
2051 index.i_id = p_indx->i_id;
2052 index.i_flags = p_indx->idx.field[i].i_size & 0x80000000 ? 0 : AVIIF_KEYFRAME;
2053 index.i_pos = p_indx->i_baseoffset + p_indx->idx.field[i].i_offset - 8;
2054 index.i_length = p_indx->idx.field[i].i_size;
2056 AVI_IndexAddEntry( p_avi, i_stream, &index );
2061 msg_Warn( p_input, "unknow subtype index(0x%x)", p_indx->i_indexsubtype );
2065 static void AVI_IndexLoad_indx( input_thread_t *p_input )
2067 demux_sys_t *p_avi = p_input->p_demux_data;
2068 unsigned int i_stream;
2071 avi_chunk_list_t *p_riff;
2072 avi_chunk_list_t *p_hdrl;
2074 p_riff = AVI_ChunkFind( &p_avi->ck_root, AVIFOURCC_RIFF, 0);
2075 p_hdrl = AVI_ChunkFind( p_riff, AVIFOURCC_hdrl, 0 );
2077 for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
2079 avi_chunk_list_t *p_strl;
2080 avi_chunk_indx_t *p_indx;
2082 #define p_stream p_avi->pp_info[i_stream]
2083 p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i_stream );
2084 p_indx = AVI_ChunkFind( p_strl, AVIFOURCC_indx, 0 );
2088 msg_Warn( p_input, "cannot find indx (misdetect/broken OpenDML file?)" );
2092 if( p_indx->i_indextype == AVI_INDEX_OF_CHUNKS )
2094 __Parse_indx( p_input, i_stream, p_indx );
2096 else if( p_indx->i_indextype == AVI_INDEX_OF_INDEXES )
2098 avi_chunk_indx_t ck_sub;
2099 for( i = 0; i < p_indx->i_entriesinuse; i++ )
2101 if( stream_Seek( p_avi->s, p_indx->idx.super[i].i_offset )||
2102 AVI_ChunkRead( p_avi->s, &ck_sub, NULL ) )
2106 __Parse_indx( p_input, i_stream, &ck_sub );
2111 msg_Warn( p_input, "unknow type index(0x%x)", p_indx->i_indextype );
2117 static void AVI_IndexLoad( input_thread_t *p_input )
2119 demux_sys_t *p_avi = p_input->p_demux_data;
2120 unsigned int i_stream;
2122 for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
2124 p_avi->pp_info[i_stream]->i_idxnb = 0;
2125 p_avi->pp_info[i_stream]->i_idxmax = 0;
2126 p_avi->pp_info[i_stream]->p_index = NULL;
2131 AVI_IndexLoad_indx( p_input );
2133 else if( AVI_IndexLoad_idx1( p_input ) )
2135 /* try indx if idx1 failed as some "normal" file have indx too */
2136 AVI_IndexLoad_indx( p_input );
2139 for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
2141 msg_Dbg( p_input, "stream[%d] created %d index entries",
2142 i_stream, p_avi->pp_info[i_stream]->i_idxnb );
2146 static void AVI_IndexCreate( input_thread_t *p_input )
2148 demux_sys_t *p_avi = p_input->p_demux_data;
2150 avi_chunk_list_t *p_riff;
2151 avi_chunk_list_t *p_movi;
2153 unsigned int i_stream;
2156 p_riff = AVI_ChunkFind( &p_avi->ck_root, AVIFOURCC_RIFF, 0);
2157 p_movi = AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0);
2161 msg_Err( p_input, "cannot find p_movi" );
2165 for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
2167 p_avi->pp_info[i_stream]->i_idxnb = 0;
2168 p_avi->pp_info[i_stream]->i_idxmax = 0;
2169 p_avi->pp_info[i_stream]->p_index = NULL;
2171 i_movi_end = __MIN( (off_t)(p_movi->i_chunk_pos + p_movi->i_chunk_size),
2172 stream_Size( p_avi->s ) );
2174 stream_Seek( p_avi->s, p_movi->i_chunk_pos + 12 );
2175 msg_Warn( p_input, "creating index from LIST-movi, will take time !" );
2180 if( AVI_PacketGetHeader( p_input, &pk ) )
2184 if( pk.i_stream < p_avi->i_streams &&
2185 pk.i_cat == p_avi->pp_info[pk.i_stream]->i_cat )
2187 AVIIndexEntry_t index;
2188 index.i_id = pk.i_fourcc;
2190 AVI_GetKeyFlag(p_avi->pp_info[pk.i_stream]->i_codec, pk.i_peek);
2191 index.i_pos = pk.i_pos;
2192 index.i_length = pk.i_size;
2193 AVI_IndexAddEntry( p_avi, pk.i_stream, &index );
2197 switch( pk.i_fourcc )
2199 case AVIFOURCC_idx1:
2202 avi_chunk_list_t *p_avix;
2203 p_avix = AVI_ChunkFind( &p_avi->ck_root,
2204 AVIFOURCC_RIFF, 1 );
2206 msg_Dbg( p_input, "looking for new RIFF chunk" );
2207 if( stream_Seek( p_avi->s, p_avix->i_chunk_pos + 24 ) )
2214 case AVIFOURCC_RIFF:
2215 msg_Dbg( p_input, "new RIFF chunk found" );
2217 case AVIFOURCC_JUNK:
2220 msg_Warn( p_input, "need resync, probably broken avi" );
2221 if( AVI_PacketSearch( p_input ) )
2223 msg_Warn( p_input, "lost sync, abord index creation" );
2229 if( ( !p_avi->b_odml && pk.i_pos + pk.i_size >= i_movi_end ) ||
2230 AVI_PacketNext( p_input ) )
2237 for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
2240 "stream[%d] creating %d index entries",
2242 p_avi->pp_info[i_stream]->i_idxnb );
2246 /*****************************************************************************
2248 *****************************************************************************/
2249 static vlc_bool_t AVI_StreamStart( input_thread_t *p_input, int i_stream )
2251 demux_sys_t *p_avi = p_input->p_demux_data;
2252 avi_stream_t *tk = p_avi->pp_info[i_stream];
2256 msg_Warn( p_input, "stream[%d] unselectable", i_stream );
2259 if( tk->b_activated )
2261 msg_Warn( p_input, "stream[%d] already selected", i_stream );
2265 if( !tk->p_es->p_decoder_fifo )
2267 vlc_mutex_lock( &p_input->stream.stream_lock );
2268 input_SelectES( p_input, tk->p_es );
2269 vlc_mutex_unlock( &p_input->stream.stream_lock );
2271 tk->b_activated = tk->p_es->p_decoder_fifo ? VLC_TRUE : VLC_FALSE;
2272 if( tk->b_activated && p_avi->b_seekable)
2274 AVI_StreamSeek( p_input, i_stream, p_avi->i_time );
2277 return tk->b_activated;
2280 static void AVI_StreamStop( input_thread_t *p_input, int i_stream )
2282 demux_sys_t *p_avi = p_input->p_demux_data;
2283 avi_stream_t *tk = p_avi->pp_info[i_stream];
2285 if( !tk->b_activated )
2287 msg_Warn( p_input, "stream[%d] already unselected", i_stream );
2291 if( tk->p_es->p_decoder_fifo )
2293 vlc_mutex_lock( &p_input->stream.stream_lock );
2294 input_UnselectES( p_input, tk->p_es );
2295 vlc_mutex_unlock( &p_input->stream.stream_lock );
2298 tk->b_activated = VLC_FALSE;
2301 static int AVI_StreamStopFinishedStreams( input_thread_t *p_input )
2303 demux_sys_t *p_avi = p_input->p_demux_data;
2305 int b_end = VLC_TRUE;
2307 for( i = 0; i < p_avi->i_streams; i++ )
2309 #define tk p_avi->pp_info[i]
2310 if( tk->i_idxposc >= tk->i_idxnb )
2312 AVI_StreamStop( p_input, i );
2323 /****************************************************************************
2324 * AVI_MovieGetLength give max streams length in second
2325 ****************************************************************************/
2326 static mtime_t AVI_MovieGetLength( input_thread_t *p_input )
2328 demux_sys_t *p_sys = p_input->p_demux_data;
2329 mtime_t i_maxlength = 0;
2332 for( i = 0; i < p_sys->i_streams; i++ )
2334 #define tk p_sys->pp_info[i]
2337 /* fix length for each stream */
2338 if( tk->i_idxnb < 1 || !tk->p_index )
2343 if( tk->i_samplesize )
2345 i_length = AVI_GetDPTS( tk,
2346 tk->p_index[tk->i_idxnb-1].i_lengthtotal +
2347 tk->p_index[tk->i_idxnb-1].i_length );
2351 i_length = AVI_GetDPTS( tk, tk->i_idxnb );
2353 i_length /= (mtime_t)1000000; /* in seconds */
2356 "stream[%d] length:"I64Fd" (based on index)",
2359 i_maxlength = __MAX( i_maxlength, i_length );