1 /*****************************************************************************
2 * avi.c : AVI file Stream input module for vlc
3 *****************************************************************************
4 * Copyright (C) 2001 VideoLAN
5 * $Id: avi.c,v 1.28 2002/06/30 15:07:57 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() */
27 #include <string.h> /* strdup() */
29 #include <sys/types.h>
32 #include <vlc/input.h>
36 #include "libioRIFF.h"
39 /*****************************************************************************
41 *****************************************************************************/
42 static void input_getfunctions( function_list_t * );
43 static int AVIDemux ( input_thread_t * );
44 static int AVIInit ( input_thread_t * );
45 static void AVIEnd ( input_thread_t * );
47 /*****************************************************************************
48 * Build configuration tree.
49 *****************************************************************************/
54 SET_DESCRIPTION( "RIFF-AVI Stream input" )
55 ADD_CAPABILITY( DEMUX, 150 )
59 input_getfunctions( &p_module->p_functions->demux );
62 MODULE_DEACTIVATE_START
63 MODULE_DEACTIVATE_STOP
65 /*****************************************************************************
66 * Functions exported as capabilities. They are declared as static so that
67 * we don't pollute the namespace too much.
68 *****************************************************************************/
69 static void input_getfunctions( function_list_t * p_function_list )
71 #define input p_function_list->functions.demux
72 input.pf_init = AVIInit;
73 input.pf_end = AVIEnd;
74 input.pf_demux = AVIDemux;
75 input.pf_rewind = NULL;
80 /*****************************************************************************
81 * Some usefull functions to manipulate memory
82 *****************************************************************************/
83 static u16 GetWLE( byte_t *p_buff )
86 i = (*p_buff) + ( *(p_buff + 1) <<8 );
89 static u32 GetDWLE( byte_t *p_buff )
92 i = (*p_buff) + ( *(p_buff + 1) <<8 ) +
93 ( *(p_buff + 2) <<16 ) + ( *(p_buff + 3) <<24 );
96 static u32 GetDWBE( byte_t *p_buff )
99 i = ((*p_buff)<<24) + ( *(p_buff + 1) <<16 ) +
100 ( *(p_buff + 2) <<8 ) + ( *(p_buff + 3) );
103 static inline off_t __EVEN( off_t i )
105 return( (i & 1) ? i+1 : i );
109 /*****************************************************************************
110 * Functions for parsing the headers in an avi file
111 *****************************************************************************/
112 static void AVI_Parse_avih( MainAVIHeader_t *p_avih, byte_t *p_buff )
114 p_avih->i_microsecperframe = GetDWLE( p_buff );
115 p_avih->i_maxbytespersec = GetDWLE( p_buff + 4);
116 p_avih->i_reserved1 = GetDWLE( p_buff + 8);
117 p_avih->i_flags = GetDWLE( p_buff + 12);
118 p_avih->i_totalframes = GetDWLE( p_buff + 16);
119 p_avih->i_initialframes = GetDWLE( p_buff + 20);
120 p_avih->i_streams = GetDWLE( p_buff + 24);
121 p_avih->i_suggestedbuffersize = GetDWLE( p_buff + 28);
122 p_avih->i_width = GetDWLE( p_buff + 32 );
123 p_avih->i_height = GetDWLE( p_buff + 36 );
124 p_avih->i_scale = GetDWLE( p_buff + 40 );
125 p_avih->i_rate = GetDWLE( p_buff + 44 );
126 p_avih->i_start = GetDWLE( p_buff + 48);
127 p_avih->i_length = GetDWLE( p_buff + 52);
129 static void AVI_Parse_Header( AVIStreamHeader_t *p_strh, byte_t *p_buff )
131 p_strh->i_type = GetDWLE( p_buff );
132 p_strh->i_handler = GetDWLE( p_buff + 4 );
133 p_strh->i_flags = GetDWLE( p_buff + 8 );
134 p_strh->i_reserved1 = GetDWLE( p_buff + 12);
135 p_strh->i_initialframes = GetDWLE( p_buff + 16);
136 p_strh->i_scale = GetDWLE( p_buff + 20);
137 p_strh->i_rate = GetDWLE( p_buff + 24);
138 p_strh->i_start = GetDWLE( p_buff + 28);
139 p_strh->i_length = GetDWLE( p_buff + 32);
140 p_strh->i_suggestedbuffersize = GetDWLE( p_buff + 36);
141 p_strh->i_quality = GetDWLE( p_buff + 40);
142 p_strh->i_samplesize = GetDWLE( p_buff + 44);
144 static void AVI_Parse_BitMapInfoHeader( bitmapinfoheader_t *h, byte_t *p_data )
146 h->i_size = GetDWLE( p_data );
147 h->i_width = GetDWLE( p_data + 4 );
148 h->i_height = GetDWLE( p_data + 8 );
149 h->i_planes = GetWLE( p_data + 12 );
150 h->i_bitcount = GetWLE( p_data + 14 );
151 h->i_compression = GetDWLE( p_data + 16 );
152 h->i_sizeimage = GetDWLE( p_data + 20 );
153 h->i_xpelspermeter = GetDWLE( p_data + 24 );
154 h->i_ypelspermeter = GetDWLE( p_data + 28 );
155 h->i_clrused = GetDWLE( p_data + 32 );
156 h->i_clrimportant = GetDWLE( p_data + 36 );
158 static void AVI_Parse_WaveFormatEx( waveformatex_t *h, byte_t *p_data )
160 h->i_formattag = GetWLE( p_data );
161 h->i_channels = GetWLE( p_data + 2 );
162 h->i_samplespersec = GetDWLE( p_data + 4 );
163 h->i_avgbytespersec= GetDWLE( p_data + 8 );
164 h->i_blockalign = GetWLE( p_data + 12 );
165 h->i_bitspersample = GetWLE( p_data + 14 );
166 h->i_size = GetWLE( p_data + 16 );
169 static inline int AVI_GetESTypeFromTwoCC( u16 i_type )
179 return( UNKNOWN_ES );
183 static int AVI_AudioGetType( u32 i_type )
187 /* case( WAVE_FORMAT_PCM ):
188 return( WAVE_AUDIO_ES ); */
189 case( WAVE_FORMAT_AC3 ):
190 return( AC3_AUDIO_ES );
191 case( WAVE_FORMAT_MPEG):
192 case( WAVE_FORMAT_MPEGLAYER3):
193 return( MPEG2_AUDIO_ES ); /* 2 for mpeg-2 layer 1 2 ou 3 */
198 static int AVI_VideoGetType( u32 i_type )
202 case( FOURCC_DIV1 ): /* FIXME it is for msmpeg4v1 or old mpeg4 ?? */
206 return( MSMPEG4v1_VIDEO_ES );
212 return( MSMPEG4v2_VIDEO_ES );
228 return( MSMPEG4v3_VIDEO_ES );
242 return( MPEG4_VIDEO_ES );
248 /* Test if it seems that it's a key frame */
249 static int AVI_GetKeyFlag( int i_type, u8 *p_byte )
253 case( MSMPEG4v1_VIDEO_ES ):
254 if( GetDWBE( p_byte ) != 0x00000100 )
255 /* startcode perhaps swapped, I haven't tested */
257 /* it's seems it's not an msmpegv1 stream
258 but perhaps I'm wrong so return yes */
259 return( AVIIF_KEYFRAME );
263 return( (*(p_byte+4))&0x06 ? 0 : AVIIF_KEYFRAME);
265 case( MSMPEG4v2_VIDEO_ES ):
266 case( MSMPEG4v3_VIDEO_ES ):
267 // printf( "\n Is a Key Frame %s", (*p_byte)&0xC0 ? "no" : "yes!!" );
268 return( (*p_byte)&0xC0 ? 0 : AVIIF_KEYFRAME );
269 case( MPEG4_VIDEO_ES ):
270 if( GetDWBE( p_byte ) != 0x000001b6 )
272 /* not true , need to find the first VOP header
274 return( AVIIF_KEYFRAME );
278 // printf( "\n Is a Key Frame %s", (*(p_byte+4))&0xC0 ? "no" :
280 return( (*(p_byte+4))&0xC0 ? 0 : AVIIF_KEYFRAME );
283 /* I can't do it, so said yes */
284 return( AVIIF_KEYFRAME );
288 /*****************************************************************************
289 * Data and functions to manipulate pes buffer
290 *****************************************************************************/
291 #define BUFFER_MAXTOTALSIZE 512*1024 /* 1/2 Mo */
292 #define BUFFER_MAXSPESSIZE 1024*200
293 static int AVI_PESBuffer_IsFull( AVIStreamInfo_t *p_info )
295 return( p_info->i_pes_totalsize > BUFFER_MAXTOTALSIZE ? 1 : 0);
297 static void AVI_PESBuffer_Add( input_buffers_t *p_method_data,
298 AVIStreamInfo_t *p_info,
303 AVIESBuffer_t *p_buffer_pes;
305 if( p_info->i_pes_totalsize > BUFFER_MAXTOTALSIZE )
307 input_DeletePES( p_method_data, p_pes );
311 if( !( p_buffer_pes = malloc( sizeof( AVIESBuffer_t ) ) ) )
313 input_DeletePES( p_method_data, p_pes );
316 p_buffer_pes->p_next = NULL;
317 p_buffer_pes->p_pes = p_pes;
318 p_buffer_pes->i_posc = i_posc;
319 p_buffer_pes->i_posb = i_posb;
321 if( p_info->p_pes_last )
323 p_info->p_pes_last->p_next = p_buffer_pes;
325 p_info->p_pes_last = p_buffer_pes;
326 if( !p_info->p_pes_first )
328 p_info->p_pes_first = p_buffer_pes;
330 p_info->i_pes_count++;
331 p_info->i_pes_totalsize += p_pes->i_pes_size;
333 static pes_packet_t *AVI_PESBuffer_Get( AVIStreamInfo_t *p_info )
335 AVIESBuffer_t *p_buffer_pes;
337 if( p_info->p_pes_first )
339 p_buffer_pes = p_info->p_pes_first;
340 p_info->p_pes_first = p_buffer_pes->p_next;
341 if( !p_info->p_pes_first )
343 p_info->p_pes_last = NULL;
345 p_pes = p_buffer_pes->p_pes;
347 free( p_buffer_pes );
348 p_info->i_pes_count--;
349 p_info->i_pes_totalsize -= p_pes->i_pes_size;
357 static int AVI_PESBuffer_Drop( input_buffers_t *p_method_data,
358 AVIStreamInfo_t *p_info )
360 pes_packet_t *p_pes = AVI_PESBuffer_Get( p_info );
363 input_DeletePES( p_method_data, p_pes );
371 static void AVI_PESBuffer_Flush( input_buffers_t *p_method_data,
372 AVIStreamInfo_t *p_info )
374 while( p_info->p_pes_first )
376 AVI_PESBuffer_Drop( p_method_data, p_info );
380 static void AVI_ParseStreamHeader( u32 i_id, int *i_number, int *i_type )
384 c1 = ( i_id ) & 0xFF;
385 c2 = ( i_id >> 8 ) & 0xFF;
387 if( c1 < '0' || c1 > '9' || c2 < '0' || c2 > '9' )
389 *i_number = 100; /* > max stream number */
394 *i_number = (c1 - '0') * 10 + (c2 - '0' );
395 *i_type = ( i_id >> 16 ) & 0xFFFF;
399 /* Function to manipulate stream easily */
400 static off_t AVI_TellAbsolute( input_thread_t *p_input )
403 vlc_mutex_lock( &p_input->stream.stream_lock );
404 i_pos= p_input->stream.p_selected_area->i_tell -
405 ( p_input->p_last_data - p_input->p_current_data );
406 vlc_mutex_unlock( &p_input->stream.stream_lock );
411 static int AVI_SeekAbsolute( input_thread_t *p_input,
415 /* FIXME add support for not seekable stream */
417 i_filepos = AVI_TellAbsolute( p_input );
418 if( i_pos != i_filepos )
420 // msg_Err( p_input, "Seek --> delta %d", i_pos - i_filepos );
421 p_input->pf_seek( p_input, i_pos );
422 input_AccessReinit( p_input );
428 static void __AVI_AddEntryIndex( AVIStreamInfo_t *p_info,
429 AVIIndexEntry_t *p_index)
431 AVIIndexEntry_t *p_tmp;
432 if( p_info->p_index == NULL )
434 p_info->i_idxmax = 16384;
436 p_info->p_index = calloc( p_info->i_idxmax,
437 sizeof( AVIIndexEntry_t ) );
438 if( p_info->p_index == NULL ) {return;}
440 if( p_info->i_idxnb >= p_info->i_idxmax )
442 p_info->i_idxmax += 16384;
443 p_tmp = realloc( (void*)p_info->p_index,
445 sizeof( AVIIndexEntry_t ) );
448 p_info->i_idxmax -= 16384;
451 p_info->p_index = p_tmp;
453 /* calculate cumulate length */
454 if( p_info->i_idxnb > 0 )
456 p_index->i_lengthtotal = p_info->p_index[p_info->i_idxnb-1].i_length +
457 p_info->p_index[p_info->i_idxnb-1].i_lengthtotal;
461 p_index->i_lengthtotal = 0;
464 p_info->p_index[p_info->i_idxnb] = *p_index;
468 static void __AVI_GetIndex( input_thread_t *p_input )
470 AVIIndexEntry_t index;
477 int i_totalentry = 0;
478 demux_data_avi_file_t *p_avi_demux =
479 (demux_data_avi_file_t*)p_input->p_demux_data ;
481 if( RIFF_FindAndGotoDataChunk( p_input,
486 msg_Warn( p_input, "cannot find index" );
487 RIFF_GoToChunk( p_input, p_avi_demux->p_hdrl );
490 p_avi_demux->p_idx1 = p_idx1;
491 msg_Dbg( p_input, "loading index" );
494 i_read = __MIN( 16*1024, p_idx1->i_size - i_totalentry *16);
495 if( ((i_read = input_Peek( p_input, &p_buff, i_read )) < 16 )
496 ||( i_totalentry *16 >= p_idx1->i_size ) )
498 msg_Dbg( p_input, "read %d idx entries", i_totalentry );
502 for( i = 0; i < i_read; i++ )
504 byte_t *p_peek = p_buff + i * 16;
506 index.i_id = GetDWLE( p_peek );
507 index.i_flags = GetDWLE( p_peek+4)&(~AVIIF_FIXKEYFRAME);
508 index.i_pos = GetDWLE( p_peek+8);
509 index.i_length = GetDWLE(p_peek+12);
510 AVI_ParseStreamHeader( index.i_id, &i_number, &i_type );
512 if( ( i_number < p_avi_demux->i_streams )
513 &&(p_avi_demux->pp_info[i_number]->i_cat ==
514 AVI_GetESTypeFromTwoCC( i_type )))
516 __AVI_AddEntryIndex( p_avi_demux->pp_info[i_number],
520 __RIFF_SkipBytes( p_input, 16 * i_read );
525 /* XXX call after get p_movi */
526 static void __AVI_UpdateIndexOffset( input_thread_t *p_input )
529 int b_start = 1;/* if index pos is based on start of file or not (p_movi) */
530 demux_data_avi_file_t *p_avi_demux =
531 (demux_data_avi_file_t*)p_input->p_demux_data;
533 /* FIXME some work to do :
534 * test in the file if it's true, if not do a RIFF_Find...
536 #define p_info p_avi_demux->pp_info[i_stream]
537 for( i_stream = 0; i_stream < p_avi_demux->i_streams; i_stream++ )
539 if( ( p_info->p_index )
540 && ( p_info->p_index[0].i_pos < p_avi_demux->p_movi->i_pos + 8 ))
548 for( i_stream = 0; i_stream < p_avi_demux->i_streams; i_stream++ )
551 if( p_info->p_index )
553 for( i = 0; i < p_info->i_idxnb; i++ )
555 p_info->p_index[i].i_pos += p_avi_demux->p_movi->i_pos + 8;
563 /*****************************************************************************
564 * AVIEnd: frees unused data
565 *****************************************************************************/
566 static void AVIEnd( input_thread_t *p_input )
569 demux_data_avi_file_t *p_avi_demux;
570 p_avi_demux = (demux_data_avi_file_t*)p_input->p_demux_data ;
572 if( p_avi_demux->p_riff )
573 RIFF_DeleteChunk( p_input, p_avi_demux->p_riff );
574 if( p_avi_demux->p_hdrl )
575 RIFF_DeleteChunk( p_input, p_avi_demux->p_hdrl );
576 if( p_avi_demux->p_movi )
577 RIFF_DeleteChunk( p_input, p_avi_demux->p_movi );
578 if( p_avi_demux->p_idx1 )
579 RIFF_DeleteChunk( p_input, p_avi_demux->p_idx1 );
580 if( p_avi_demux->pp_info )
582 for( i = 0; i < p_avi_demux->i_streams; i++ )
584 if( p_avi_demux->pp_info[i] )
586 if( p_avi_demux->pp_info[i]->p_index )
588 free( p_avi_demux->pp_info[i]->p_index );
589 AVI_PESBuffer_Flush( p_input->p_method_data,
590 p_avi_demux->pp_info[i] );
592 free( p_avi_demux->pp_info[i] );
595 free( p_avi_demux->pp_info );
599 /*****************************************************************************
600 * AVIInit: check file and initializes AVI structures
601 *****************************************************************************/
602 static int AVIInit( input_thread_t *p_input )
604 riffchunk_t *p_riff,*p_hdrl,*p_movi;
606 riffchunk_t *p_strl,*p_strh,*p_strf;
607 demux_data_avi_file_t *p_avi_demux;
608 es_descriptor_t *p_es = NULL; /* for not warning */
612 if( !( p_input->p_demux_data =
613 p_avi_demux = malloc( sizeof(demux_data_avi_file_t) ) ) )
615 msg_Err( p_input, "out of memory" );
618 memset( p_avi_demux, 0, sizeof( demux_data_avi_file_t ) );
619 p_avi_demux->i_rate = DEFAULT_RATE;
620 p_avi_demux->b_seekable = ( ( p_input->stream.b_seekable )
621 &&( p_input->stream.i_method == INPUT_METHOD_FILE ) );
623 /* Initialize access plug-in structures. */
624 if( p_input->i_mtu == 0 )
627 p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
630 if( RIFF_TestFileHeader( p_input, &p_riff, FOURCC_AVI ) != 0 )
633 msg_Warn( p_input, "RIFF-AVI module discarded" );
636 p_avi_demux->p_riff = p_riff;
638 if ( RIFF_DescendChunk(p_input) != 0 )
641 msg_Err( p_input, "cannot look for subchunk" );
645 /* it's a riff-avi file, so search for LIST-hdrl */
646 if( RIFF_FindListChunk(p_input ,&p_hdrl,p_riff, FOURCC_hdrl) != 0 )
649 msg_Err( p_input, "cannot find \"LIST-hdrl\"" );
652 p_avi_demux->p_hdrl = p_hdrl;
654 if( RIFF_DescendChunk(p_input) != 0 )
657 msg_Err( p_input, "cannot look for subchunk" );
660 /* in LIST-hdrl search avih */
661 if( RIFF_FindAndLoadChunk( p_input, p_hdrl,
662 &p_avih, FOURCC_avih ) != 0 )
665 msg_Err( p_input, "cannot find \"avih\" chunk" );
668 AVI_Parse_avih( &p_avi_demux->avih, p_avih->p_data->p_payload_start );
669 RIFF_DeleteChunk( p_input, p_avih );
671 if( p_avi_demux->avih.i_streams == 0 )
672 /* no stream found, perhaps it would be cool to find it */
675 msg_Err( p_input, "no stream defined!" );
679 /* create one program */
680 vlc_mutex_lock( &p_input->stream.stream_lock );
681 if( input_InitStream( p_input, 0 ) == -1)
683 vlc_mutex_unlock( &p_input->stream.stream_lock );
685 msg_Err( p_input, "cannot init stream" );
688 if( input_AddProgram( p_input, 0, 0) == NULL )
690 vlc_mutex_unlock( &p_input->stream.stream_lock );
692 msg_Err( p_input, "cannot add program" );
695 p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
696 p_input->stream.i_mux_rate = p_avi_demux->avih.i_maxbytespersec / 50;
697 vlc_mutex_unlock( &p_input->stream.stream_lock );
699 /* now read info on each stream and create ES */
700 p_avi_demux->i_streams = p_avi_demux->avih.i_streams;
702 p_avi_demux->pp_info = calloc( p_avi_demux->i_streams,
703 sizeof( AVIStreamInfo_t* ) );
704 memset( p_avi_demux->pp_info,
706 sizeof( AVIStreamInfo_t* ) * p_avi_demux->i_streams );
708 for( i = 0 ; i < p_avi_demux->i_streams; i++ )
710 #define p_info p_avi_demux->pp_info[i]
711 p_info = malloc( sizeof(AVIStreamInfo_t ) );
712 memset( p_info, 0, sizeof( AVIStreamInfo_t ) );
714 if( ( RIFF_FindListChunk(p_input,
715 &p_strl,p_hdrl, FOURCC_strl) != 0 )
716 ||( RIFF_DescendChunk(p_input) != 0 ))
719 msg_Err( p_input, "cannot find \"LIST-strl\"" );
723 /* in LIST-strl search strh */
724 if( RIFF_FindAndLoadChunk( p_input, p_hdrl,
725 &p_strh, FOURCC_strh ) != 0 )
727 RIFF_DeleteChunk( p_input, p_strl );
729 msg_Err( p_input, "cannot find \"strh\"" );
732 AVI_Parse_Header( &p_info->header,
733 p_strh->p_data->p_payload_start);
734 RIFF_DeleteChunk( p_input, p_strh );
736 /* in LIST-strl search strf */
737 if( RIFF_FindAndLoadChunk( p_input, p_hdrl,
738 &p_strf, FOURCC_strf ) != 0 )
740 RIFF_DeleteChunk( p_input, p_strl );
742 msg_Err( p_input, "cannot find \"strf\"" );
745 /* we don't get strd, it's useless for divx,opendivx,mepgaudio */
746 if( RIFF_AscendChunk(p_input, p_strl) != 0 )
748 RIFF_DeleteChunk( p_input, p_strf );
749 RIFF_DeleteChunk( p_input, p_strl );
751 msg_Err( p_input, "cannot go out (\"strl\")" );
756 vlc_mutex_lock( &p_input->stream.stream_lock );
757 p_es = input_AddES( p_input,
758 p_input->stream.p_selected_program, 1+i,
760 vlc_mutex_unlock( &p_input->stream.stream_lock );
761 p_es->i_stream_id =i; /* XXX: i don't use it */
763 switch( p_info->header.i_type )
766 p_es->i_cat = AUDIO_ES;
767 AVI_Parse_WaveFormatEx( &p_info->audio_format,
768 p_strf->p_data->p_payload_start );
771 AVI_AudioGetType( p_info->audio_format.i_formattag );
774 msg_Warn( p_input, "stream(%d,0x%x) not supported", i,
775 p_info->audio_format.i_formattag );
776 p_es->i_cat = UNKNOWN_ES;
781 p_es->i_cat = VIDEO_ES;
782 AVI_Parse_BitMapInfoHeader( &p_info->video_format,
783 p_strf->p_data->p_payload_start );
786 AVI_VideoGetType( p_info->video_format.i_compression );
789 msg_Warn( p_input, "stream(%d,%4.4s) not supported", i,
790 (char*)&p_info->video_format.i_compression);
791 p_es->i_cat = UNKNOWN_ES;
795 msg_Err( p_input, "unknown stream(%d) type", i );
796 p_es->i_cat = UNKNOWN_ES;
800 p_info->i_cat = p_es->i_cat;
801 /* We copy strf for decoder in p_es->p_demux_data */
802 memcpy( p_es->p_demux_data,
803 p_strf->p_data->p_payload_start,
805 RIFF_DeleteChunk( p_input, p_strf );
806 RIFF_DeleteChunk( p_input, p_strl );
812 /* go out of p_hdrl */
813 if( RIFF_AscendChunk(p_input, p_hdrl) != 0)
816 msg_Err( p_input, "cannot go out (\"hdrl\")" );
820 /* go to movi chunk to get it*/
821 if( RIFF_FindListChunk(p_input ,&p_movi,p_riff, FOURCC_movi) != 0 )
823 msg_Err( p_input, "cannot find \"LIST-movi\"" );
827 p_avi_demux->p_movi = p_movi;
829 /* get index XXX need to have p_movi */
830 if( ( p_avi_demux->b_seekable )
831 &&( p_avi_demux->avih.i_flags&AVIF_HASINDEX ) )
834 __AVI_GetIndex( p_input );
835 /* try to get i_idxoffset for each stream */
836 __AVI_UpdateIndexOffset( p_input );
837 /* to make sure to go the begining unless demux will see a seek */
838 RIFF_GoToChunk( p_input, p_avi_demux->p_movi );
839 if( RIFF_DescendChunk( p_input ) != 0 )
842 msg_Err( p_input, "cannot go in (\"movi\")" );
848 msg_Warn( p_input, "no index!" );
852 /* print informations on streams */
853 msg_Dbg( p_input, "AVIH: %d stream, flags %s%s%s%s ",
854 p_avi_demux->i_streams,
855 p_avi_demux->avih.i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
856 p_avi_demux->avih.i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",
857 p_avi_demux->avih.i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
858 p_avi_demux->avih.i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"" );
860 for( i = 0; i < p_avi_demux->i_streams; i++ )
862 #define p_info p_avi_demux->pp_info[i]
863 switch( p_info->p_es->i_cat )
866 msg_Dbg( p_input, "video(%4.4s) %dx%d %dbpp %ffps",
867 (char*)&p_info->video_format.i_compression,
868 p_info->video_format.i_width,
869 p_info->video_format.i_height,
870 p_info->video_format.i_bitcount,
871 (float)p_info->header.i_rate /
872 (float)p_info->header.i_scale );
873 if( (p_avi_demux->p_info_video == NULL) )
875 p_avi_demux->p_info_video = p_info;
876 /* TODO add test to see if a decoder has been found */
877 vlc_mutex_lock( &p_input->stream.stream_lock );
878 input_SelectES( p_input, p_info->p_es );
879 vlc_mutex_unlock( &p_input->stream.stream_lock );
884 msg_Dbg( p_input, "audio(0x%x) %d channels %dHz %dbits",
885 p_info->audio_format.i_formattag,
886 p_info->audio_format.i_channels,
887 p_info->audio_format.i_samplespersec,
888 p_info->audio_format.i_bitspersample );
889 if( (p_avi_demux->p_info_audio == NULL) )
891 p_avi_demux->p_info_audio = p_info;
892 vlc_mutex_lock( &p_input->stream.stream_lock );
893 input_SelectES( p_input, p_info->p_es );
894 vlc_mutex_unlock( &p_input->stream.stream_lock );
904 /* we select the first audio and video ES */
905 vlc_mutex_lock( &p_input->stream.stream_lock );
906 if( !p_avi_demux->p_info_video )
908 msg_Warn( p_input, "no video stream found" );
910 if( !p_avi_demux->p_info_audio )
912 msg_Warn( p_input, "no audio stream found!" );
914 p_input->stream.p_selected_program->b_is_ok = 1;
915 vlc_mutex_unlock( &p_input->stream.stream_lock );
925 /*****************************************************************************
926 * Function to convert pts to chunk or byte
927 *****************************************************************************/
929 static inline mtime_t AVI_PTSToChunk( AVIStreamInfo_t *p_info,
932 return( (mtime_t)((s64)i_pts *
933 (s64)p_info->header.i_rate /
934 (s64)p_info->header.i_scale /
937 static inline mtime_t AVI_PTSToByte( AVIStreamInfo_t *p_info,
940 return( (mtime_t)((s64)i_pts *
941 (s64)p_info->header.i_samplesize *
942 (s64)p_info->header.i_rate /
943 (s64)p_info->header.i_scale /
947 static mtime_t AVI_GetPTS( AVIStreamInfo_t *p_info )
950 if( p_info->header.i_samplesize )
952 /* we need a valid entry we will emulate one */
954 if( p_info->i_idxposc == p_info->i_idxnb )
956 if( p_info->i_idxposc )
958 /* use the last entry */
959 i_len = p_info->p_index[p_info->i_idxnb - 1].i_lengthtotal
960 + p_info->p_index[p_info->i_idxnb - 1].i_length
961 + p_info->i_idxposb; /* should be 0 */
965 i_len = 0; /* no valid zntry */
970 i_len = p_info->p_index[p_info->i_idxposc].i_lengthtotal
973 return( (mtime_t)( (s64)1000000 *
975 (s64)p_info->header.i_scale /
976 (s64)p_info->header.i_rate /
977 (s64)p_info->header.i_samplesize ) );
981 /* even if p_info->i_idxposc isn't valid, there isn't any probllem */
982 return( (mtime_t)( (s64)1000000 *
983 (s64)(p_info->i_idxposc ) *
984 (s64)p_info->header.i_scale /
985 (s64)p_info->header.i_rate) );
990 /*****************************************************************************
991 * Functions to acces streams data
992 * Uses it, because i plane to read unseekable stream
993 * Don't work for the moment for unseekable stream
994 * XXX NEVER set directly i_idxposc and i_idxposb unless you know what you do
995 *****************************************************************************/
997 /* FIXME FIXME change b_pad to number of bytes to skipp after reading */
998 static int __AVI_GetDataInPES( input_thread_t *p_input,
999 pes_packet_t **pp_pes,
1005 data_packet_t *p_data;
1007 if( !(*pp_pes = input_NewPES( p_input->p_method_data ) ) )
1012 if( ( i_size&1 )&&( b_pad ) )
1024 (*pp_pes)->p_first = (*pp_pes)->p_last = NULL;
1025 (*pp_pes)->i_nb_data = 0;
1026 (*pp_pes)->i_pes_size = 0;
1032 i_read = input_SplitBuffer(p_input, &p_data, i_size -
1033 (*pp_pes)->i_pes_size );
1036 return( (*pp_pes)->i_pes_size );
1038 if( !(*pp_pes)->p_first )
1040 (*pp_pes)->p_first =
1041 (*pp_pes)->p_last = p_data;
1042 (*pp_pes)->i_nb_data = 1;
1043 (*pp_pes)->i_pes_size = i_read;
1047 (*pp_pes)->p_last->p_next =
1048 (*pp_pes)->p_last = p_data;
1049 (*pp_pes)->i_nb_data++;
1050 (*pp_pes)->i_pes_size += i_read;
1052 } while( ((*pp_pes)->i_pes_size < i_size)&&( i_read ) );
1056 (*pp_pes)->i_pes_size--;
1057 (*pp_pes)->p_last->p_payload_end--;
1064 static int __AVI_SeekAndGetChunk( input_thread_t *p_input,
1065 AVIStreamInfo_t *p_info )
1067 pes_packet_t *p_pes;
1070 i_length = __MIN( p_info->p_index[p_info->i_idxposc].i_length
1071 - p_info->i_idxposb,
1072 BUFFER_MAXSPESSIZE );
1074 AVI_SeekAbsolute( p_input,
1075 (off_t)p_info->p_index[p_info->i_idxposc].i_pos +
1076 p_info->i_idxposb + 8);
1078 if( __AVI_GetDataInPES( p_input,
1085 /* TODO test key frame if i_idxposb == 0*/
1086 AVI_PESBuffer_Add( p_input->p_method_data,
1090 p_info->i_idxposb );
1093 /* TODO check if it's correct (humm...) and optimisation ... */
1094 /* return 0 if we choose to get only the ck we want
1095 * 1 if index is invalid
1096 * 2 if there is a ck_other before ck_info and the last proced ck_info*/
1097 /* XXX XXX XXX avi file is some BIG shit, and sometime index give
1098 * a refenrence to the same chunk BUT with a different size ( usually 0 )
1101 static inline int __AVI_GetChunkMethod( input_thread_t *p_input,
1102 AVIStreamInfo_t *p_info,
1103 AVIStreamInfo_t *p_other )
1108 int i_info_pos_last;
1109 int i_other_pos_last;
1111 /*If we don't have a valid entry we need to parse from last
1112 defined chunk and it's the only way that we return 1*/
1113 if( p_info->i_idxposc >= p_info->i_idxnb )
1118 /* KNOW we have a valid entry for p_info */
1119 /* we return 0 if we haven't an valid entry for p_other */
1120 if( ( !p_other )||( p_other->i_idxposc >= p_other->i_idxnb ) )
1125 /* KNOW there are 2 streams with valid entry */
1127 /* we return 0 if for one of the two streams we will not read
1129 if( ( p_info->i_idxposb )||( p_other->i_idxposb ) )
1134 /* KNOW we have a valid entry for the 2 streams
1135 and for the 2 we want an aligned chunk (given by i_idxposc )*/
1136 /* if in stream, the next chunk is back than the one we
1137 have just read, it's useless to parse */
1138 i_info_pos = p_info->p_index[p_info->i_idxposc].i_pos;
1139 i_other_pos = p_other->p_index[p_other->i_idxposc].i_pos ;
1141 i_info_pos_last = p_info->i_idxposc ?
1142 p_info->p_index[p_info->i_idxposc - 1].i_pos : 0;
1143 i_other_pos_last = p_other->i_idxposc ?
1144 p_other->p_index[p_other->i_idxposc - 1].i_pos : 0 ;
1147 if( ( ( p_info->i_idxposc )&&( i_info_pos <= i_info_pos_last ) ) ||
1148 ( ( p_other->i_idxposc )&&( i_other_pos <= i_other_pos_last ) ) )
1153 /* KNOW for the 2 streams, the ck we want are after the last read
1154 or it's the first */
1156 /* if the first ck_other we want isn't between ck_info_last
1157 and ck_info, don't parse */
1158 /* TODO fix this, use also number in buffered PES */
1159 if( ( i_other_pos > i_info_pos) /* ck_other too far */
1160 ||( i_other_pos < i_info_pos_last ) ) /* it's too late for ck_other */
1165 /* we Know we will find ck_other, and before ck_info
1166 "if ck_info is too far" will be handle after */
1171 static inline int __AVI_ChooseSize( int l1, int l2 )
1173 /* XXX l2 is prefered if 0 otherwise min not equal to 0 */
1178 return( !l1 ? l2 : __MIN( l1,l2 ) );
1181 /* We know we will read chunk align */
1182 static int __AVI_GetAndPutChunkInBuffer( input_thread_t *p_input,
1183 AVIStreamInfo_t *p_info,
1188 pes_packet_t *p_pes;
1191 i_length = __MIN( i_size, BUFFER_MAXSPESSIZE );
1193 /* Skip chunk header */
1195 if( __AVI_GetDataInPES( p_input, &p_pes, i_length + 8,1 ) != i_length +8 )
1199 p_pes->p_first->p_payload_start += 8;
1201 i_size = GetDWLE( p_pes->p_first->p_demux_start + 4);
1203 AVI_PESBuffer_Add( p_input->p_method_data,
1208 /* skip unwanted bytes */
1209 if( i_length != i_size)
1211 msg_Err( p_input, "Chunk Size mismatch" );
1212 AVI_SeekAbsolute( p_input,
1213 __EVEN( AVI_TellAbsolute( p_input ) +
1214 i_size - i_length ) );
1219 /* XXX Don't use this function directly ! XXX */
1220 static int __AVI_GetChunk( input_thread_t *p_input,
1221 AVIStreamInfo_t *p_info,
1224 demux_data_avi_file_t *p_avi_demux =
1225 (demux_data_avi_file_t*)p_input->p_demux_data;
1226 AVIStreamInfo_t *p_other;
1231 #define p_info_i p_avi_demux->pp_info[i]
1232 while( p_info->p_pes_first )
1234 if( ( p_info->p_pes_first->i_posc == p_info->i_idxposc )
1235 &&( p_info->i_idxposb >= p_info->p_pes_first->i_posb )
1236 &&( p_info->i_idxposb < p_info->p_pes_first->i_posb +
1237 p_info->p_pes_first->p_pes->i_pes_size ) )
1240 return( 1 ); /* we have it in buffer */
1244 AVI_PESBuffer_Drop( p_input->p_method_data, p_info );
1247 /* up to now we handle only one audio and video streams at the same time */
1248 p_other = (p_info == p_avi_demux->p_info_video ) ?
1249 p_avi_demux->p_info_audio : p_avi_demux->p_info_video ;
1251 i_method = __AVI_GetChunkMethod( p_input, p_info, p_other );
1255 /* get directly the good chunk */
1256 return( b_load ? __AVI_SeekAndGetChunk( p_input, p_info ) : 1 );
1259 * because invalid index
1260 * or will find ck_other before ck_info
1262 // msg_Warn( p_input, "method %d", i_method );
1263 /* we will calculate the better position we have to reach */
1267 /* the position max we have already reached */
1268 /* FIXME this isn't the better because sometime will fail to
1269 put in buffer p_other since it could be too far */
1270 AVIStreamInfo_t *p_info_max = p_info;
1272 for( i = 0; i < p_avi_demux->i_streams; i++ )
1274 if( p_info_i->i_idxnb )
1276 if( p_info_max->i_idxnb )
1278 if( p_info_i->p_index[p_info_i->i_idxnb -1 ].i_pos >
1279 p_info_max->p_index[p_info_max->i_idxnb -1 ].i_pos )
1281 p_info_max = p_info_i;
1286 p_info_max = p_info_i;
1290 if( p_info_max->i_idxnb )
1292 /* be carefull that size between index and ck can sometime be
1293 different without any error (and other time it's an error) */
1294 i_posmax = p_info_max->p_index[p_info_max->i_idxnb -1 ].i_pos;
1295 /* so choose this, and I know that we have already reach it */
1299 i_posmax = p_avi_demux->p_movi->i_pos + 12;
1306 return( 1 ); /* all is ok */
1309 /* we know that the entry and the last one are valid for the 2 stream */
1310 /* and ck_other will come *before* index so go directly to it*/
1311 i_posmax = p_other->p_index[p_other->i_idxposc].i_pos;
1314 AVI_SeekAbsolute( p_input, i_posmax );
1315 /* the first chunk we will see is :
1316 * the last chunk that we have already seen for broken index
1317 * the first ck for other with good index */
1318 for( ; ; ) /* infinite parsing until the ck we want */
1323 /* Get the actual chunk in the stream */
1324 if( !(p_ck = RIFF_ReadChunk( p_input )) )
1328 // msg_Dbg( p_input, "ck: %4.4s len %d", &p_ck->i_id, p_ck->i_size );
1329 /* special case for LIST-rec chunk */
1330 if( ( p_ck->i_id == FOURCC_LIST )&&( p_ck->i_type == FOURCC_rec ) )
1332 RIFF_DescendChunk( p_input );
1333 RIFF_DeleteChunk( p_input, p_ck );
1336 AVI_ParseStreamHeader( p_ck->i_id, &i, &i_type );
1337 /* littles checks but not too much if you want to read all file */
1338 if( i >= p_avi_demux->i_streams )
1339 /* (AVI_GetESTypeFromTwoCC(i_type) != p_info_i->i_cat) perhaps add it*/
1342 RIFF_DeleteChunk( p_input, p_ck );
1343 if( RIFF_NextChunk( p_input, p_avi_demux->p_movi ) != 0 )
1352 /* have we found a new entry (not present in index)? */
1353 if( ( !p_info_i->i_idxnb )
1354 ||(p_info_i->p_index[p_info_i->i_idxnb-1].i_pos < p_ck->i_pos))
1356 AVIIndexEntry_t index;
1358 index.i_id = p_ck->i_id;
1359 index.i_flags = AVI_GetKeyFlag( p_info_i->p_es->i_type,
1360 (u8*)&p_ck->i_8bytes);
1361 index.i_pos = p_ck->i_pos;
1362 index.i_length = p_ck->i_size;
1363 __AVI_AddEntryIndex( p_info_i, &index );
1367 /* TODO check if p_other is full and then if is possible
1368 go directly to the good chunk */
1369 if( ( p_info_i == p_other )
1370 &&( !AVI_PESBuffer_IsFull( p_other ) )
1371 &&( ( !p_other->p_pes_last )||
1372 ( p_other->p_pes_last->p_pes->i_pes_size !=
1373 BUFFER_MAXSPESSIZE ) ) )
1375 int i_ck = p_other->p_pes_last ?
1376 p_other->p_pes_last->i_posc + 1 : p_other->i_idxposc;
1377 i_size = __AVI_ChooseSize( p_ck->i_size,
1378 p_other->p_index[i_ck].i_length);
1380 if( p_other->p_index[i_ck].i_pos == p_ck->i_pos )
1382 if( !__AVI_GetAndPutChunkInBuffer( p_input, p_other,
1385 RIFF_DeleteChunk( p_input, p_ck );
1391 if( RIFF_NextChunk( p_input, p_avi_demux->p_movi ) != 0 )
1393 RIFF_DeleteChunk( p_input, p_ck );
1400 RIFF_DeleteChunk( p_input, p_ck );
1403 if( ( p_info_i == p_info)
1404 &&( p_info->i_idxposc < p_info->i_idxnb ) )
1406 /* the first ck_info is ok otherwise it should be
1407 loaded without parsing */
1408 i_size = __AVI_ChooseSize( p_ck->i_size,
1409 p_info->p_index[p_info->i_idxposc].i_length);
1412 RIFF_DeleteChunk( p_input, p_ck );
1414 return( b_load ? __AVI_GetAndPutChunkInBuffer( p_input,
1417 p_info->i_idxposc ) : 1 );
1422 RIFF_DeleteChunk( p_input, p_ck );
1423 if( RIFF_NextChunk( p_input, p_avi_demux->p_movi ) != 0 )
1436 /* be sure that i_ck will be a valid index entry */
1437 static int AVI_SetStreamChunk( input_thread_t *p_input,
1438 AVIStreamInfo_t *p_info,
1442 p_info->i_idxposc = i_ck;
1443 p_info->i_idxposb = 0;
1445 if( i_ck < p_info->i_idxnb )
1451 p_info->i_idxposc = p_info->i_idxnb - 1;
1454 p_info->i_idxposc++;
1455 if( !__AVI_GetChunk( p_input, p_info, 0 ) )
1459 } while( p_info->i_idxposc < i_ck );
1466 /* XXX FIXME up to now, we assume that all chunk are one after one */
1467 static int AVI_SetStreamBytes( input_thread_t *p_input,
1468 AVIStreamInfo_t *p_info,
1471 if( ( p_info->i_idxnb > 0 )
1472 &&( i_byte < p_info->p_index[p_info->i_idxnb - 1].i_lengthtotal +
1473 p_info->p_index[p_info->i_idxnb - 1].i_length ) )
1475 /* index is valid to find the ck */
1476 /* uses dichototmie to be fast enougth */
1477 int i_idxposc = __MIN( p_info->i_idxposc, p_info->i_idxnb - 1 );
1478 int i_idxmax = p_info->i_idxnb;
1482 if( p_info->p_index[i_idxposc].i_lengthtotal > i_byte )
1484 i_idxmax = i_idxposc ;
1485 i_idxposc = ( i_idxmin + i_idxposc ) / 2 ;
1489 if( p_info->p_index[i_idxposc].i_lengthtotal +
1490 p_info->p_index[i_idxposc].i_length <= i_byte)
1492 i_idxmin = i_idxposc ;
1493 i_idxposc = (i_idxmax + i_idxposc ) / 2 ;
1497 p_info->i_idxposc = i_idxposc;
1498 p_info->i_idxposb = i_byte -
1499 p_info->p_index[i_idxposc].i_lengthtotal;
1508 p_info->i_idxposc = p_info->i_idxnb - 1;
1509 p_info->i_idxposb = 0;
1512 p_info->i_idxposc++;
1513 if( !__AVI_GetChunk( p_input, p_info, 0 ) )
1517 } while( p_info->p_index[p_info->i_idxposc].i_lengthtotal +
1518 p_info->p_index[p_info->i_idxposc].i_length <= i_byte );
1520 p_info->i_idxposb = i_byte -
1521 p_info->p_index[p_info->i_idxposc].i_lengthtotal;
1526 static pes_packet_t *AVI_ReadStreamChunkInPES( input_thread_t *p_input,
1527 AVIStreamInfo_t *p_info )
1530 if( p_info->i_idxposc > p_info->i_idxnb )
1535 /* we want chunk (p_info->i_idxposc,0) */
1536 p_info->i_idxposb = 0;
1537 if( !__AVI_GetChunk( p_input, p_info, 1) )
1539 msg_Err( p_input, "Got one chunk : failed" );
1542 p_info->i_idxposc++;
1543 return( AVI_PESBuffer_Get( p_info ) );
1546 static pes_packet_t *AVI_ReadStreamBytesInPES( input_thread_t *p_input,
1547 AVIStreamInfo_t *p_info,
1550 pes_packet_t *p_pes;
1551 data_packet_t *p_data;
1556 if( !( p_pes = input_NewPES( p_input->p_method_data ) ) )
1560 if( !( p_data = input_NewPacket( p_input->p_method_data, i_byte ) ) )
1562 input_DeletePES( p_input->p_method_data, p_pes );
1567 p_pes->p_last = p_data;
1568 p_pes->i_nb_data = 1;
1569 p_pes->i_pes_size = i_byte;
1573 if( !__AVI_GetChunk( p_input, p_info, 1) )
1575 msg_Err( p_input, "Got one chunk : failed" );
1577 input_DeletePES( p_input->p_method_data, p_pes );
1581 i_read = __MIN( p_info->p_pes_first->p_pes->i_pes_size -
1582 ( p_info->i_idxposb - p_info->p_pes_first->i_posb ),
1584 /* FIXME FIXME FIXME follow all data packet */
1585 memcpy( p_data->p_payload_start + i_count,
1586 p_info->p_pes_first->p_pes->p_first->p_payload_start +
1587 p_info->i_idxposb - p_info->p_pes_first->i_posb,
1590 AVI_PESBuffer_Drop( p_input->p_method_data, p_info );
1594 p_info->i_idxposb += i_read;
1595 if( p_info->p_index[p_info->i_idxposc].i_length <= p_info->i_idxposb )
1597 p_info->i_idxposb -= p_info->p_index[p_info->i_idxposc].i_length;
1598 p_info->i_idxposc++;
1606 /* try to realign after a seek */
1607 static int AVI_ReAlign( input_thread_t *p_input,
1608 AVIStreamInfo_t *p_info )
1613 demux_data_avi_file_t *p_avi_demux =
1614 (demux_data_avi_file_t*)p_input->p_demux_data;
1617 for( i = 0; i < p_avi_demux->i_streams; i++ )
1619 AVI_PESBuffer_Flush( p_input->p_method_data, p_avi_demux->pp_info[i] );
1622 TODO use input_ClockInit instead but need to be exported
1623 p_input->stream.p_selected_program->last_cr = 0;
1624 p_input->stream.p_selected_program->last_syscr = 0;
1625 p_input->stream.p_selected_program->cr_ref = 0;
1626 p_input->stream.p_selected_program->sysdate_ref = 0;
1627 p_input->stream.p_selected_program->delta_cr = 0;
1628 p_input->stream.p_selected_program->c_average_count = 0; */
1630 i_pos = AVI_TellAbsolute( p_input );
1632 p_info->i_idxposc--; /* in fact p_info->i_idxposc is for ck to be read */
1635 if( ( p_info->i_idxposc <= 0)
1636 ||( i_pos <= p_info->p_index[0].i_pos ) )
1638 /* before beginning of stream */
1639 return( p_info->header.i_samplesize ?
1640 AVI_SetStreamBytes( p_input, p_info, 0 ) :
1641 AVI_SetStreamChunk( p_input, p_info, 0 ) );
1644 b_after = ( i_pos >= p_info->p_index[p_info->i_idxposc].i_pos );
1645 /* now find in what chunk we are */
1646 while( ( i_pos < p_info->p_index[p_info->i_idxposc].i_pos )
1647 &&( p_info->i_idxposc > 0 ) )
1649 /* search before i_idxposc */
1651 if( !AVI_SetStreamChunk( p_input, p_info, p_info->i_idxposc - 1 ) )
1657 while( i_pos >= p_info->p_index[p_info->i_idxposc].i_pos +
1658 p_info->p_index[p_info->i_idxposc].i_length + 8 )
1660 /* search after i_idxposc */
1662 if( !AVI_SetStreamChunk( p_input, p_info, p_info->i_idxposc + 1 ) )
1668 /* search nearest key frame, only for video */
1669 if( p_info->i_cat == VIDEO_ES )
1673 while(!(p_info->p_index[p_info->i_idxposc].i_flags&AVIIF_KEYFRAME) )
1675 if( !AVI_SetStreamChunk( p_input, p_info,
1676 p_info->i_idxposc + 1 ) )
1684 while( ( p_info->i_idxposc > 0 ) &&
1685 (!(p_info->p_index[p_info->i_idxposc].i_flags&AVIIF_KEYFRAME)) )
1688 if( !AVI_SetStreamChunk( p_input, p_info,
1689 p_info->i_idxposc - 1 ) )
1700 /* make difference between audio and video pts as little as possible */
1701 static void AVI_SynchroReInit( input_thread_t *p_input )
1703 demux_data_avi_file_t *p_avi_demux =
1704 (demux_data_avi_file_t*)p_input->p_demux_data;
1706 #define p_info_video p_avi_demux->p_info_video
1707 #define p_info_audio p_avi_demux->p_info_audio
1708 if( ( !p_info_audio )||( !p_info_video ) )
1712 /* now resynch audio video video */
1713 /*don't care of AVIF_KEYFRAME */
1714 if( !p_info_audio->header.i_samplesize )
1716 AVI_SetStreamChunk( p_input,
1718 AVI_PTSToChunk( p_info_audio,
1719 AVI_GetPTS( p_info_video ) ) );
1723 AVI_SetStreamBytes( p_input,
1725 AVI_PTSToByte( p_info_audio,
1726 AVI_GetPTS( p_info_video ) ) );
1732 /*****************************************************************************
1733 * AVI_GetFrameInPES : get dpts length(µs) in pes from stream
1734 *****************************************************************************
1735 * Handle multiple pes, and set pts to the good value
1736 *****************************************************************************/
1737 static pes_packet_t *AVI_GetFrameInPES( input_thread_t *p_input,
1738 AVIStreamInfo_t *p_info,
1742 pes_packet_t *p_pes = NULL;
1743 pes_packet_t *p_pes_tmp = NULL;
1744 pes_packet_t *p_pes_first = NULL;
1752 if( !p_info->header.i_samplesize )
1754 int i_chunk = __MAX( AVI_PTSToChunk( p_info, i_dpts), 1 );
1756 for( i = 0; i < i_chunk; i++ )
1758 /* get pts while is valid */
1759 i_pts = AVI_GetPTS( p_info );
1761 p_pes_tmp = AVI_ReadStreamChunkInPES( p_input, p_info );
1765 return( p_pes_first );
1767 p_pes_tmp->i_pts = i_pts;
1770 p_pes_first = p_pes_tmp;
1774 p_pes->p_next = p_pes_tmp;
1778 return( p_pes_first );
1782 /* stream is byte based */
1783 int i_byte = AVI_PTSToByte( p_info, i_dpts);
1784 if( i_byte < 50 ) /* to avoid some problem with audio */
1788 i_pts = AVI_GetPTS( p_info ); /* ok even with broken index */
1789 p_pes = AVI_ReadStreamBytesInPES( p_input, p_info, i_byte);
1793 p_pes->i_pts = i_pts;
1798 /*****************************************************************************
1799 * AVI_DecodePES : send a pes to decoder
1800 *****************************************************************************
1801 * Handle multiple pes, and update pts to the good value
1802 *****************************************************************************/
1803 static inline void AVI_DecodePES( input_thread_t *p_input,
1804 AVIStreamInfo_t *p_info,
1805 pes_packet_t *p_pes )
1807 pes_packet_t *p_pes_next;
1808 /* input_decode want only one pes, but AVI_GetFrameInPES give
1809 multiple pes so send one by one */
1812 p_pes_next = p_pes->p_next;
1813 p_pes->p_next = NULL;
1814 p_pes->i_pts = input_ClockGetTS( p_input,
1815 p_input->stream.p_selected_program,
1816 p_pes->i_pts * 9/100);
1817 input_DecodePES( p_info->p_es->p_decoder_fifo, p_pes );
1823 /*****************************************************************************
1824 * AVIDemux: reads and demuxes data packets
1825 *****************************************************************************
1826 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
1827 * TODO add support for unstreable file, just read a chunk and send it
1828 * to the right decoder, very easy
1829 *****************************************************************************/
1831 static int AVIDemux( input_thread_t *p_input )
1834 pes_packet_t *p_pes;
1835 AVIStreamInfo_t *p_info_master;
1836 AVIStreamInfo_t *p_info_slave;
1838 demux_data_avi_file_t *p_avi_demux =
1839 (demux_data_avi_file_t*)p_input->p_demux_data;
1841 /* search new video and audio stream selected
1842 if current have been unselected*/
1843 if( ( !p_avi_demux->p_info_video )
1844 || ( !p_avi_demux->p_info_video->p_es->p_decoder_fifo ) )
1846 p_avi_demux->p_info_video = NULL;
1847 for( i = 0; i < p_avi_demux->i_streams; i++ )
1849 if( ( p_avi_demux->pp_info[i]->i_cat == VIDEO_ES )
1850 &&( p_avi_demux->pp_info[i]->p_es->p_decoder_fifo ) )
1852 p_avi_demux->p_info_video = p_avi_demux->pp_info[i];
1853 p_avi_demux->p_info_video->b_selected = 1;
1858 if( ( !p_avi_demux->p_info_audio )
1859 ||( !p_avi_demux->p_info_audio->p_es->p_decoder_fifo ) )
1861 p_avi_demux->p_info_audio = NULL;
1862 for( i = 0; i < p_avi_demux->i_streams; i++ )
1864 if( ( p_avi_demux->pp_info[i]->i_cat == AUDIO_ES )
1865 &&( p_avi_demux->pp_info[i]->p_es->p_decoder_fifo ) )
1867 p_avi_demux->p_info_audio = p_avi_demux->pp_info[i];
1868 p_avi_demux->p_info_audio->b_selected = 1;
1873 /* by default video is master for resync audio (after a seek .. ) */
1874 if( p_avi_demux->p_info_video )
1876 p_info_master = p_avi_demux->p_info_video;
1877 p_info_slave = p_avi_demux->p_info_audio;
1881 p_info_master = p_avi_demux->p_info_audio;
1882 p_info_slave = NULL;
1885 if( !p_info_master )
1887 msg_Err( p_input, "no stream selected" );
1891 /* check for signal from interface */
1892 if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
1894 /* we can supposed that is a seek */
1895 /* first wait for empty buffer, arbitrary time */
1896 msleep( DEFAULT_PTS_DELAY );
1897 /* then try to realign in stream */
1898 if( !AVI_ReAlign( p_input, p_info_master ) )
1900 return( 0 ); /* assume EOF */
1902 AVI_SynchroReInit( p_input );
1905 /* manage rate, if not default: skeep audio */
1906 vlc_mutex_lock( &p_input->stream.stream_lock );
1907 if( p_input->stream.control.i_rate != p_avi_demux->i_rate )
1909 if( p_avi_demux->p_info_audio)
1911 p_avi_demux->p_info_audio->b_selected = 1;
1913 p_avi_demux->i_rate = p_input->stream.control.i_rate;
1915 vlc_mutex_unlock( &p_input->stream.stream_lock );
1916 if( p_avi_demux->i_rate != DEFAULT_RATE )
1918 p_info_slave = NULL;
1921 /* take care of newly selected audio ES */
1922 if( p_info_master->b_selected )
1924 p_info_master->b_selected = 0;
1925 AVI_SynchroReInit( p_input );
1927 if( ( p_info_slave )&&( p_info_slave->b_selected ) )
1929 p_info_slave->b_selected = 0;
1930 AVI_SynchroReInit( p_input );
1933 /* wait for the good time */
1934 input_ClockManageRef( p_input,
1935 p_input->stream.p_selected_program,
1936 p_avi_demux->i_pcr /*- DEFAULT_PTS_DELAY / 2 */);
1937 /* calculate pcr, time when we must read the next data */
1938 /* 9/100 kludge ->need to convert to 1/1000000 clock unit to 1/90000 */
1941 p_avi_demux->i_pcr = __MIN( AVI_GetPTS( p_info_master ),
1942 AVI_GetPTS( p_info_slave ) ) * 9/100;
1946 p_avi_demux->i_pcr = AVI_GetPTS( p_info_master ) * 9/100;
1949 /* get video and audio frames */
1950 p_pes = AVI_GetFrameInPES( p_input,
1952 100000 ); /* 100 ms */
1957 pes_packet_t *p_pes_slave;
1958 p_pes_slave = AVI_GetFrameInPES( p_input,
1960 AVI_GetPTS( p_info_master ) -
1961 AVI_GetPTS( p_info_slave) );
1962 AVI_DecodePES( p_input,
1967 AVI_DecodePES( p_input,
1972 return( p_pes ? 1 : 0 );