1 /*****************************************************************************
2 * avi.c : AVI file Stream input module for vlc
3 *****************************************************************************
4 * Copyright (C) 2001 VideoLAN
5 * $Id: avi.c,v 1.5 2002/09/19 15:58:55 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 int AVIInit ( vlc_object_t * );
43 static void __AVIEnd ( vlc_object_t * );
44 static int AVIDemux ( input_thread_t * );
46 #define AVIEnd(a) __AVIEnd(VLC_OBJECT(a))
48 /*****************************************************************************
50 *****************************************************************************/
52 set_description( "RIFF-AVI demuxer" );
53 set_capability( "demux", 150 );
54 set_callbacks( AVIInit, __AVIEnd );
57 /*****************************************************************************
58 * Some usefull functions to manipulate memory
59 *****************************************************************************/
60 static u16 GetWLE( byte_t *p_buff )
62 return( p_buff[0] + ( p_buff[1] << 8 ) );
64 static u32 GetDWLE( byte_t *p_buff )
66 return( p_buff[0] + ( p_buff[1] << 8 ) +
67 ( p_buff[2] << 16 ) + ( p_buff[3] << 24 ) );
69 static u32 GetDWBE( byte_t *p_buff )
71 return( p_buff[3] + ( p_buff[2] << 8 ) +
72 ( p_buff[1] << 16 ) + ( p_buff[0] << 24 ) );
74 static vlc_fourcc_t GetFOURCC( byte_t *p_buff )
76 return( VLC_FOURCC( p_buff[0], p_buff[1], p_buff[2], p_buff[3] ) );
79 static inline off_t __EVEN( off_t i )
81 return( (i & 1) ? i+1 : i );
85 /*****************************************************************************
86 * Functions for parsing the headers in an avi file
87 *****************************************************************************/
88 static void AVI_Parse_avih( MainAVIHeader_t *p_avih, byte_t *p_buff )
90 p_avih->i_microsecperframe = GetDWLE( p_buff );
91 p_avih->i_maxbytespersec = GetDWLE( p_buff + 4);
92 p_avih->i_reserved1 = GetDWLE( p_buff + 8);
93 p_avih->i_flags = GetDWLE( p_buff + 12);
94 p_avih->i_totalframes = GetDWLE( p_buff + 16);
95 p_avih->i_initialframes = GetDWLE( p_buff + 20);
96 p_avih->i_streams = GetDWLE( p_buff + 24);
97 p_avih->i_suggestedbuffersize = GetDWLE( p_buff + 28);
98 p_avih->i_width = GetDWLE( p_buff + 32 );
99 p_avih->i_height = GetDWLE( p_buff + 36 );
100 p_avih->i_scale = GetDWLE( p_buff + 40 );
101 p_avih->i_rate = GetDWLE( p_buff + 44 );
102 p_avih->i_start = GetDWLE( p_buff + 48);
103 p_avih->i_length = GetDWLE( p_buff + 52);
105 static void AVI_Parse_Header( AVIStreamHeader_t *p_strh, byte_t *p_buff )
107 p_strh->i_type = GetDWLE( p_buff );
108 p_strh->i_handler = GetDWLE( p_buff + 4 );
109 p_strh->i_flags = GetDWLE( p_buff + 8 );
110 p_strh->i_reserved1 = GetDWLE( p_buff + 12);
111 p_strh->i_initialframes = GetDWLE( p_buff + 16);
112 p_strh->i_scale = GetDWLE( p_buff + 20);
113 p_strh->i_rate = GetDWLE( p_buff + 24);
114 p_strh->i_start = GetDWLE( p_buff + 28);
115 p_strh->i_length = GetDWLE( p_buff + 32);
116 p_strh->i_suggestedbuffersize = GetDWLE( p_buff + 36);
117 p_strh->i_quality = GetDWLE( p_buff + 40);
118 p_strh->i_samplesize = GetDWLE( p_buff + 44);
120 static void AVI_Parse_BitMapInfoHeader( bitmapinfoheader_t *h, byte_t *p_data )
122 h->i_size = GetDWLE( p_data );
123 h->i_width = GetDWLE( p_data + 4 );
124 h->i_height = GetDWLE( p_data + 8 );
125 h->i_planes = GetWLE( p_data + 12 );
126 h->i_bitcount = GetWLE( p_data + 14 );
127 h->i_compression = GetFOURCC( p_data + 16 );
128 h->i_sizeimage = GetDWLE( p_data + 20 );
129 h->i_xpelspermeter = GetDWLE( p_data + 24 );
130 h->i_ypelspermeter = GetDWLE( p_data + 28 );
131 h->i_clrused = GetDWLE( p_data + 32 );
132 h->i_clrimportant = GetDWLE( p_data + 36 );
134 static void AVI_Parse_WaveFormatEx( waveformatex_t *h, byte_t *p_data )
136 h->i_formattag = GetWLE( p_data );
137 h->i_channels = GetWLE( p_data + 2 );
138 h->i_samplespersec = GetDWLE( p_data + 4 );
139 h->i_avgbytespersec= GetDWLE( p_data + 8 );
140 h->i_blockalign = GetWLE( p_data + 12 );
141 h->i_bitspersample = GetWLE( p_data + 14 );
142 h->i_size = GetWLE( p_data + 16 );
145 static inline int AVI_GetESTypeFromTwoCC( u16 i_type )
155 return( UNKNOWN_ES );
159 static vlc_fourcc_t AVI_AudioGetType( u32 i_type )
163 /* case( WAVE_FORMAT_PCM ):
164 return VLC_FOURCC('l','p','c','m'); */
165 case( WAVE_FORMAT_A52 ):
166 return VLC_FOURCC('a','5','2',' ');
167 case( WAVE_FORMAT_MPEG):
168 case( WAVE_FORMAT_MPEGLAYER3):
169 return VLC_FOURCC('m','p','g','a'); /* for mpeg2 layer 1 2 ou 3 */
175 /* Test if it seems that it's a key frame */
176 static int AVI_GetKeyFlag( vlc_fourcc_t i_fourcc, u8 *p_byte )
184 if( GetDWBE( p_byte ) != 0x00000100 )
185 /* startcode perhaps swapped, I haven't tested */
187 /* it's seems it's not an msmpegv1 stream
188 but perhaps I'm wrong so return yes */
189 return( AVIIF_KEYFRAME );
193 return( (*(p_byte+4))&0x06 ? 0 : AVIIF_KEYFRAME);
213 return( (*p_byte)&0xC0 ? 0 : AVIIF_KEYFRAME );
226 if( GetDWBE( p_byte ) != 0x000001b6 )
228 /* not true , need to find the first VOP header
230 return( AVIIF_KEYFRAME );
234 return( (*(p_byte+4))&0xC0 ? 0 : AVIIF_KEYFRAME );
237 /* I can't do it, so said yes */
238 return( AVIIF_KEYFRAME );
242 /*****************************************************************************
243 * Data and functions to manipulate pes buffer
244 *****************************************************************************/
245 #define BUFFER_MAXTOTALSIZE 512*1024 /* 1/2 Mo */
246 #define BUFFER_MAXSPESSIZE 1024*200
247 static int AVI_PESBuffer_IsFull( AVIStreamInfo_t *p_info )
249 return( p_info->i_pes_totalsize > BUFFER_MAXTOTALSIZE ? 1 : 0);
251 static void AVI_PESBuffer_Add( input_buffers_t *p_method_data,
252 AVIStreamInfo_t *p_info,
257 AVIESBuffer_t *p_buffer_pes;
259 if( p_info->i_pes_totalsize > BUFFER_MAXTOTALSIZE )
261 input_DeletePES( p_method_data, p_pes );
265 if( !( p_buffer_pes = malloc( sizeof( AVIESBuffer_t ) ) ) )
267 input_DeletePES( p_method_data, p_pes );
270 p_buffer_pes->p_next = NULL;
271 p_buffer_pes->p_pes = p_pes;
272 p_buffer_pes->i_posc = i_posc;
273 p_buffer_pes->i_posb = i_posb;
275 if( p_info->p_pes_last )
277 p_info->p_pes_last->p_next = p_buffer_pes;
279 p_info->p_pes_last = p_buffer_pes;
280 if( !p_info->p_pes_first )
282 p_info->p_pes_first = p_buffer_pes;
284 p_info->i_pes_count++;
285 p_info->i_pes_totalsize += p_pes->i_pes_size;
287 static pes_packet_t *AVI_PESBuffer_Get( AVIStreamInfo_t *p_info )
289 AVIESBuffer_t *p_buffer_pes;
291 if( p_info->p_pes_first )
293 p_buffer_pes = p_info->p_pes_first;
294 p_info->p_pes_first = p_buffer_pes->p_next;
295 if( !p_info->p_pes_first )
297 p_info->p_pes_last = NULL;
299 p_pes = p_buffer_pes->p_pes;
301 free( p_buffer_pes );
302 p_info->i_pes_count--;
303 p_info->i_pes_totalsize -= p_pes->i_pes_size;
311 static int AVI_PESBuffer_Drop( input_buffers_t *p_method_data,
312 AVIStreamInfo_t *p_info )
314 pes_packet_t *p_pes = AVI_PESBuffer_Get( p_info );
317 input_DeletePES( p_method_data, p_pes );
325 static void AVI_PESBuffer_Flush( input_buffers_t *p_method_data,
326 AVIStreamInfo_t *p_info )
328 while( p_info->p_pes_first )
330 AVI_PESBuffer_Drop( p_method_data, p_info );
334 static void AVI_ParseStreamHeader( u32 i_id, int *i_number, int *i_type )
337 /* XXX i_id have to be read using MKFOURCC and NOT VLC_FOURCC */
338 c1 = ( i_id ) & 0xFF;
339 c2 = ( i_id >> 8 ) & 0xFF;
341 if( c1 < '0' || c1 > '9' || c2 < '0' || c2 > '9' )
343 *i_number = 100; /* > max stream number */
348 *i_number = (c1 - '0') * 10 + (c2 - '0' );
349 *i_type = ( i_id >> 16 ) & 0xFFFF;
353 /* Function to manipulate stream easily */
354 static off_t AVI_TellAbsolute( input_thread_t *p_input )
357 vlc_mutex_lock( &p_input->stream.stream_lock );
358 i_pos= p_input->stream.p_selected_area->i_tell -
359 ( p_input->p_last_data - p_input->p_current_data );
360 vlc_mutex_unlock( &p_input->stream.stream_lock );
365 static int AVI_SeekAbsolute( input_thread_t *p_input,
369 /* FIXME add support for not seekable stream */
371 i_filepos = AVI_TellAbsolute( p_input );
372 if( i_pos != i_filepos )
374 /* msg_Err( p_input, "Seek --> delta %d", i_pos - i_filepos );*/
375 p_input->pf_seek( p_input, i_pos );
376 input_AccessReinit( p_input );
382 static void __AVI_AddEntryIndex( AVIStreamInfo_t *p_info,
383 AVIIndexEntry_t *p_index)
385 AVIIndexEntry_t *p_tmp;
386 if( p_info->p_index == NULL )
388 p_info->i_idxmax = 16384;
390 p_info->p_index = calloc( p_info->i_idxmax,
391 sizeof( AVIIndexEntry_t ) );
392 if( p_info->p_index == NULL ) {return;}
394 if( p_info->i_idxnb >= p_info->i_idxmax )
396 p_info->i_idxmax += 16384;
397 p_tmp = realloc( (void*)p_info->p_index,
399 sizeof( AVIIndexEntry_t ) );
402 p_info->i_idxmax -= 16384;
405 p_info->p_index = p_tmp;
407 /* calculate cumulate length */
408 if( p_info->i_idxnb > 0 )
410 p_index->i_lengthtotal = p_info->p_index[p_info->i_idxnb-1].i_length +
411 p_info->p_index[p_info->i_idxnb-1].i_lengthtotal;
415 p_index->i_lengthtotal = 0;
418 p_info->p_index[p_info->i_idxnb] = *p_index;
422 static void __AVI_GetIndex( input_thread_t *p_input )
424 AVIIndexEntry_t index;
431 int i_totalentry = 0;
432 demux_sys_t *p_avi = p_input->p_demux_data;
434 if( RIFF_FindAndGotoDataChunk( p_input,
439 msg_Warn( p_input, "cannot find index" );
440 RIFF_GoToChunk( p_input, p_avi->p_hdrl );
443 p_avi->p_idx1 = p_idx1;
444 msg_Dbg( p_input, "loading index" );
447 i_read = __MIN( 16*1024, p_idx1->i_size - i_totalentry *16);
448 if( ((i_read = input_Peek( p_input, &p_buff, i_read )) < 16 )
449 ||( i_totalentry *16 >= p_idx1->i_size ) )
451 msg_Dbg( p_input, "read %d idx entries", i_totalentry );
455 for( i = 0; i < i_read; i++ )
457 byte_t *p_peek = p_buff + i * 16;
459 index.i_id = GetDWLE( p_peek );
460 index.i_flags = GetDWLE( p_peek+4)&(~AVIIF_FIXKEYFRAME);
461 index.i_pos = GetDWLE( p_peek+8);
462 index.i_length = GetDWLE(p_peek+12);
463 AVI_ParseStreamHeader( index.i_id, &i_number, &i_type );
465 if( ( i_number < p_avi->i_streams )
466 &&(p_avi->pp_info[i_number]->i_cat ==
467 AVI_GetESTypeFromTwoCC( i_type )))
469 __AVI_AddEntryIndex( p_avi->pp_info[i_number],
473 __RIFF_SkipBytes( p_input, 16 * i_read );
478 /* XXX call after get p_movi */
479 static void __AVI_UpdateIndexOffset( input_thread_t *p_input )
482 int b_start = 1;/* if index pos is based on start of file or not (p_movi) */
483 demux_sys_t *p_avi = p_input->p_demux_data;
485 /* FIXME some work to do :
486 * test in the file if it's true, if not do a RIFF_Find...
488 #define p_info p_avi->pp_info[i_stream]
489 for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
491 if( ( p_info->p_index )
492 && ( p_info->p_index[0].i_pos < p_avi->p_movi->i_pos + 8 ))
500 for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
503 if( p_info->p_index )
505 for( i = 0; i < p_info->i_idxnb; i++ )
507 p_info->p_index[i].i_pos += p_avi->p_movi->i_pos + 8;
515 /*****************************************************************************
516 * AVIEnd: frees unused data
517 *****************************************************************************/
518 static void __AVIEnd ( vlc_object_t * p_this )
520 input_thread_t * p_input = (input_thread_t *)p_this;
522 demux_sys_t *p_avi = p_input->p_demux_data ;
525 RIFF_DeleteChunk( p_input, p_avi->p_riff );
527 RIFF_DeleteChunk( p_input, p_avi->p_hdrl );
529 RIFF_DeleteChunk( p_input, p_avi->p_movi );
531 RIFF_DeleteChunk( p_input, p_avi->p_idx1 );
534 for( i = 0; i < p_avi->i_streams; i++ )
536 if( p_avi->pp_info[i] )
538 if( p_avi->pp_info[i]->p_index )
540 free( p_avi->pp_info[i]->p_index );
541 AVI_PESBuffer_Flush( p_input->p_method_data,
544 free( p_avi->pp_info[i] );
547 free( p_avi->pp_info );
551 /*****************************************************************************
552 * AVIInit: check file and initializes AVI structures
553 *****************************************************************************/
554 static int AVIInit( vlc_object_t * p_this )
556 input_thread_t * p_input = (input_thread_t *)p_this;
557 riffchunk_t *p_riff,*p_hdrl,*p_movi;
559 riffchunk_t *p_strl,*p_strh,*p_strf;
561 es_descriptor_t *p_es = NULL; /* for not warning */
564 p_input->pf_demux = AVIDemux;
566 if( !( p_input->p_demux_data =
567 p_avi = malloc( sizeof(demux_sys_t) ) ) )
569 msg_Err( p_input, "out of memory" );
572 memset( p_avi, 0, sizeof( demux_sys_t ) );
573 p_avi->i_rate = DEFAULT_RATE;
574 p_avi->b_seekable = ( ( p_input->stream.b_seekable )
575 &&( p_input->stream.i_method == INPUT_METHOD_FILE ) );
577 /* Initialize access plug-in structures. */
578 if( p_input->i_mtu == 0 )
581 p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
584 if( RIFF_TestFileHeader( p_input, &p_riff, AVIFOURCC_AVI ) != 0 )
587 msg_Warn( p_input, "RIFF-AVI module discarded" );
590 p_avi->p_riff = p_riff;
592 if ( RIFF_DescendChunk(p_input) != 0 )
595 msg_Err( p_input, "cannot look for subchunk" );
599 /* it's a riff-avi file, so search for LIST-hdrl */
600 if( RIFF_FindListChunk(p_input ,&p_hdrl,p_riff, AVIFOURCC_hdrl) != 0 )
603 msg_Err( p_input, "cannot find \"LIST-hdrl\"" );
606 p_avi->p_hdrl = p_hdrl;
608 if( RIFF_DescendChunk(p_input) != 0 )
611 msg_Err( p_input, "cannot look for subchunk" );
614 /* in LIST-hdrl search avih */
615 if( RIFF_FindAndLoadChunk( p_input, p_hdrl,
616 &p_avih, AVIFOURCC_avih ) != 0 )
619 msg_Err( p_input, "cannot find \"avih\" chunk" );
622 AVI_Parse_avih( &p_avi->avih, p_avih->p_data->p_payload_start );
623 RIFF_DeleteChunk( p_input, p_avih );
625 if( p_avi->avih.i_streams == 0 )
626 /* no stream found, perhaps it would be cool to find it */
629 msg_Err( p_input, "no stream defined!" );
633 /* create one program */
634 vlc_mutex_lock( &p_input->stream.stream_lock );
635 if( input_InitStream( p_input, 0 ) == -1)
637 vlc_mutex_unlock( &p_input->stream.stream_lock );
639 msg_Err( p_input, "cannot init stream" );
642 if( input_AddProgram( p_input, 0, 0) == NULL )
644 vlc_mutex_unlock( &p_input->stream.stream_lock );
646 msg_Err( p_input, "cannot add program" );
649 p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
650 p_input->stream.i_mux_rate = p_avi->avih.i_maxbytespersec / 50;
651 vlc_mutex_unlock( &p_input->stream.stream_lock );
653 /* now read info on each stream and create ES */
654 p_avi->i_streams = p_avi->avih.i_streams;
656 p_avi->pp_info = calloc( p_avi->i_streams,
657 sizeof( AVIStreamInfo_t* ) );
658 memset( p_avi->pp_info,
660 sizeof( AVIStreamInfo_t* ) * p_avi->i_streams );
662 for( i = 0 ; i < p_avi->i_streams; i++ )
664 #define p_info p_avi->pp_info[i]
665 p_info = malloc( sizeof(AVIStreamInfo_t ) );
666 memset( p_info, 0, sizeof( AVIStreamInfo_t ) );
668 if( ( RIFF_FindListChunk(p_input,
669 &p_strl,p_hdrl, AVIFOURCC_strl) != 0 )
670 ||( RIFF_DescendChunk(p_input) != 0 ))
673 msg_Err( p_input, "cannot find \"LIST-strl\"" );
677 /* in LIST-strl search strh */
678 if( RIFF_FindAndLoadChunk( p_input, p_hdrl,
679 &p_strh, AVIFOURCC_strh ) != 0 )
681 RIFF_DeleteChunk( p_input, p_strl );
683 msg_Err( p_input, "cannot find \"strh\"" );
686 AVI_Parse_Header( &p_info->header,
687 p_strh->p_data->p_payload_start);
688 RIFF_DeleteChunk( p_input, p_strh );
690 /* in LIST-strl search strf */
691 if( RIFF_FindAndLoadChunk( p_input, p_hdrl,
692 &p_strf, AVIFOURCC_strf ) != 0 )
694 RIFF_DeleteChunk( p_input, p_strl );
696 msg_Err( p_input, "cannot find \"strf\"" );
699 /* we don't get strd, it's useless for divx,opendivx,mepgaudio */
700 if( RIFF_AscendChunk(p_input, p_strl) != 0 )
702 RIFF_DeleteChunk( p_input, p_strf );
703 RIFF_DeleteChunk( p_input, p_strl );
705 msg_Err( p_input, "cannot go out (\"strl\")" );
710 vlc_mutex_lock( &p_input->stream.stream_lock );
711 p_es = input_AddES( p_input,
712 p_input->stream.p_selected_program, 1+i,
714 vlc_mutex_unlock( &p_input->stream.stream_lock );
715 p_es->i_stream_id =i; /* XXX: i don't use it */
717 switch( p_info->header.i_type )
719 case( AVIFOURCC_auds ):
720 p_es->i_cat = AUDIO_ES;
721 AVI_Parse_WaveFormatEx( &p_info->audio_format,
722 p_strf->p_data->p_payload_start );
723 p_es->i_fourcc = AVI_AudioGetType(
724 p_info->audio_format.i_formattag );
727 case( AVIFOURCC_vids ):
728 p_es->i_cat = VIDEO_ES;
729 AVI_Parse_BitMapInfoHeader( &p_info->video_format,
730 p_strf->p_data->p_payload_start );
732 /* XXX quick hack for playing ffmpeg video, I don't know
733 who is doing something wrong */
734 p_info->header.i_samplesize = 0;
735 p_es->i_fourcc = p_info->video_format.i_compression;
738 msg_Err( p_input, "unknown stream(%d) type", i );
739 p_es->i_cat = UNKNOWN_ES;
743 p_info->i_cat = p_es->i_cat;
744 /* We copy strf for decoder in p_es->p_demux_data */
745 memcpy( p_es->p_demux_data,
746 p_strf->p_data->p_payload_start,
748 RIFF_DeleteChunk( p_input, p_strf );
749 RIFF_DeleteChunk( p_input, p_strl );
755 /* go out of p_hdrl */
756 if( RIFF_AscendChunk(p_input, p_hdrl) != 0)
759 msg_Err( p_input, "cannot go out (\"hdrl\")" );
763 /* go to movi chunk to get it*/
764 if( RIFF_FindListChunk(p_input ,&p_movi,p_riff, AVIFOURCC_movi) != 0 )
766 msg_Err( p_input, "cannot find \"LIST-movi\"" );
770 p_avi->p_movi = p_movi;
772 /* get index XXX need to have p_movi */
773 if( p_avi->b_seekable )
776 __AVI_GetIndex( p_input );
777 /* try to get i_idxoffset for each stream */
778 __AVI_UpdateIndexOffset( p_input );
779 /* to make sure to go the begining unless demux will see a seek */
780 RIFF_GoToChunk( p_input, p_avi->p_movi );
785 msg_Warn( p_input, "no index!" );
788 if( RIFF_DescendChunk( p_input ) != 0 )
791 msg_Err( p_input, "cannot go in (\"movi\")" );
795 /* print informations on streams */
796 msg_Dbg( p_input, "AVIH: %d stream, flags %s%s%s%s ",
798 p_avi->avih.i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
799 p_avi->avih.i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",
800 p_avi->avih.i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
801 p_avi->avih.i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"" );
803 for( i = 0; i < p_avi->i_streams; i++ )
805 #define p_info p_avi->pp_info[i]
806 switch( p_info->p_es->i_cat )
810 msg_Dbg( p_input, "video(%4.4s) %dx%d %dbpp %ffps",
811 (char*)&p_info->video_format.i_compression,
812 p_info->video_format.i_width,
813 p_info->video_format.i_height,
814 p_info->video_format.i_bitcount,
815 (float)p_info->header.i_rate /
816 (float)p_info->header.i_scale );
817 if( (p_avi->p_info_video == NULL) )
819 p_avi->p_info_video = p_info;
820 /* TODO add test to see if a decoder has been found */
821 vlc_mutex_lock( &p_input->stream.stream_lock );
822 input_SelectES( p_input, p_info->p_es );
823 vlc_mutex_unlock( &p_input->stream.stream_lock );
828 msg_Dbg( p_input, "audio(0x%x) %d channels %dHz %dbits",
829 p_info->audio_format.i_formattag,
830 p_info->audio_format.i_channels,
831 p_info->audio_format.i_samplespersec,
832 p_info->audio_format.i_bitspersample );
833 if( (p_avi->p_info_audio == NULL) )
835 p_avi->p_info_audio = p_info;
836 vlc_mutex_lock( &p_input->stream.stream_lock );
837 input_SelectES( p_input, p_info->p_es );
838 vlc_mutex_unlock( &p_input->stream.stream_lock );
848 /* we select the first audio and video ES */
849 vlc_mutex_lock( &p_input->stream.stream_lock );
850 if( !p_avi->p_info_video )
852 msg_Warn( p_input, "no video stream found" );
854 if( !p_avi->p_info_audio )
856 msg_Warn( p_input, "no audio stream found!" );
858 p_input->stream.p_selected_program->b_is_ok = 1;
859 vlc_mutex_unlock( &p_input->stream.stream_lock );
869 /*****************************************************************************
870 * Function to convert pts to chunk or byte
871 *****************************************************************************/
873 static inline mtime_t AVI_PTSToChunk( AVIStreamInfo_t *p_info,
876 return( (mtime_t)((s64)i_pts *
877 (s64)p_info->header.i_rate /
878 (s64)p_info->header.i_scale /
881 static inline mtime_t AVI_PTSToByte( AVIStreamInfo_t *p_info,
884 return( (mtime_t)((s64)i_pts *
885 (s64)p_info->header.i_samplesize *
886 (s64)p_info->header.i_rate /
887 (s64)p_info->header.i_scale /
891 static mtime_t AVI_GetPTS( AVIStreamInfo_t *p_info )
894 if( p_info->header.i_samplesize )
896 /* we need a valid entry we will emulate one */
898 if( p_info->i_idxposc == p_info->i_idxnb )
900 if( p_info->i_idxposc )
902 /* use the last entry */
903 i_len = p_info->p_index[p_info->i_idxnb - 1].i_lengthtotal
904 + p_info->p_index[p_info->i_idxnb - 1].i_length
905 + p_info->i_idxposb; /* should be 0 */
909 i_len = p_info->i_idxposb;
910 /* no valid entry use only offset*/
915 i_len = p_info->p_index[p_info->i_idxposc].i_lengthtotal
918 return( (mtime_t)( (s64)1000000 *
920 (s64)p_info->header.i_scale /
921 (s64)p_info->header.i_rate /
922 (s64)p_info->header.i_samplesize ) );
926 /* even if p_info->i_idxposc isn't valid, there isn't any probllem */
927 return( (mtime_t)( (s64)1000000 *
928 (s64)(p_info->i_idxposc ) *
929 (s64)p_info->header.i_scale /
930 (s64)p_info->header.i_rate) );
935 /*****************************************************************************
936 * Functions to acces streams data
937 * Uses it, because i plane to read unseekable stream
938 * Don't work for the moment for unseekable stream
939 * XXX NEVER set directly i_idxposc and i_idxposb unless you know what you do
940 *****************************************************************************/
942 /* FIXME FIXME change b_pad to number of bytes to skipp after reading */
943 static int __AVI_GetDataInPES( input_thread_t *p_input,
944 pes_packet_t **pp_pes,
950 data_packet_t *p_data;
953 if( !(*pp_pes = input_NewPES( p_input->p_method_data ) ) )
961 p_data = input_NewPacket( p_input->p_method_data, 0 );
962 (*pp_pes)->p_first = (*pp_pes)->p_last = p_data;
963 (*pp_pes)->i_nb_data = 1;
964 (*pp_pes)->i_pes_size = 0;
968 if( ( i_size&1 )&&( b_pad ) )
980 i_read = input_SplitBuffer(p_input, &p_data, __MIN( i_size -
981 (*pp_pes)->i_pes_size, 1024 ) );
984 return( (*pp_pes)->i_pes_size );
986 if( !(*pp_pes)->p_first )
989 (*pp_pes)->p_last = p_data;
990 (*pp_pes)->i_nb_data = 1;
991 (*pp_pes)->i_pes_size = i_read;
995 (*pp_pes)->p_last->p_next =
996 (*pp_pes)->p_last = p_data;
997 (*pp_pes)->i_nb_data++;
998 (*pp_pes)->i_pes_size += i_read;
1000 } while( ((*pp_pes)->i_pes_size < i_size)&&( i_read ) );
1004 (*pp_pes)->i_pes_size--;
1005 (*pp_pes)->p_last->p_payload_end--;
1012 static int __AVI_SeekAndGetChunk( input_thread_t *p_input,
1013 AVIStreamInfo_t *p_info )
1015 pes_packet_t *p_pes;
1016 int i_length, i_ret;
1018 i_length = __MIN( p_info->p_index[p_info->i_idxposc].i_length
1019 - p_info->i_idxposb,
1020 BUFFER_MAXSPESSIZE );
1022 AVI_SeekAbsolute( p_input,
1023 (off_t)p_info->p_index[p_info->i_idxposc].i_pos +
1024 p_info->i_idxposb + 8);
1026 i_ret = __AVI_GetDataInPES( p_input, &p_pes, i_length , 0);
1028 if( i_ret != i_length )
1032 /* TODO test key frame if i_idxposb == 0*/
1033 AVI_PESBuffer_Add( p_input->p_method_data,
1037 p_info->i_idxposb );
1040 /* TODO check if it's correct (humm...) and optimisation ... */
1041 /* return 0 if we choose to get only the ck we want
1042 * 1 if index is invalid
1043 * 2 if there is a ck_other before ck_info and the last proced ck_info*/
1044 /* XXX XXX XXX avi file is some BIG shit, and sometime index give
1045 * a refenrence to the same chunk BUT with a different size ( usually 0 )
1048 static inline int __AVI_GetChunkMethod( input_thread_t *p_input,
1049 AVIStreamInfo_t *p_info,
1050 AVIStreamInfo_t *p_other )
1055 int i_info_pos_last;
1056 int i_other_pos_last;
1058 /*If we don't have a valid entry we need to parse from last
1059 defined chunk and it's the only way that we return 1*/
1060 if( p_info->i_idxposc >= p_info->i_idxnb )
1065 /* KNOW we have a valid entry for p_info */
1066 /* we return 0 if we haven't an valid entry for p_other */
1067 if( ( !p_other )||( p_other->i_idxposc >= p_other->i_idxnb ) )
1072 /* KNOW there are 2 streams with valid entry */
1074 /* we return 0 if for one of the two streams we will not read
1076 if( ( p_info->i_idxposb )||( p_other->i_idxposb ) )
1081 /* KNOW we have a valid entry for the 2 streams
1082 and for the 2 we want an aligned chunk (given by i_idxposc )*/
1083 /* if in stream, the next chunk is back than the one we
1084 have just read, it's useless to parse */
1085 i_info_pos = p_info->p_index[p_info->i_idxposc].i_pos;
1086 i_other_pos = p_other->p_index[p_other->i_idxposc].i_pos ;
1088 i_info_pos_last = p_info->i_idxposc ?
1089 p_info->p_index[p_info->i_idxposc - 1].i_pos : 0;
1090 i_other_pos_last = p_other->i_idxposc ?
1091 p_other->p_index[p_other->i_idxposc - 1].i_pos : 0 ;
1094 if( ( ( p_info->i_idxposc )&&( i_info_pos <= i_info_pos_last ) ) ||
1095 ( ( p_other->i_idxposc )&&( i_other_pos <= i_other_pos_last ) ) )
1100 /* KNOW for the 2 streams, the ck we want are after the last read
1101 or it's the first */
1103 /* if the first ck_other we want isn't between ck_info_last
1104 and ck_info, don't parse */
1105 /* TODO fix this, use also number in buffered PES */
1106 if( ( i_other_pos > i_info_pos) /* ck_other too far */
1107 ||( i_other_pos < i_info_pos_last ) ) /* it's too late for ck_other */
1112 /* we Know we will find ck_other, and before ck_info
1113 "if ck_info is too far" will be handle after */
1118 static inline int __AVI_ChooseSize( int l1, int l2 )
1120 /* XXX l2 is prefered if 0 otherwise min not equal to 0 */
1125 return( !l1 ? l2 : __MIN( l1,l2 ) );
1128 /* We know we will read chunk align */
1129 static int __AVI_GetAndPutChunkInBuffer( input_thread_t *p_input,
1130 AVIStreamInfo_t *p_info,
1135 pes_packet_t *p_pes;
1138 i_length = __MIN( i_size, BUFFER_MAXSPESSIZE );
1140 /* Skip chunk header */
1142 if( __AVI_GetDataInPES( p_input, &p_pes, i_length + 8,1 ) != i_length +8 )
1146 p_pes->p_first->p_payload_start += 8;
1147 p_pes->i_pes_size -= 8;
1149 i_size = GetDWLE( p_pes->p_first->p_demux_start + 4);
1151 AVI_PESBuffer_Add( p_input->p_method_data,
1156 /* skip unwanted bytes */
1157 if( i_length != i_size)
1159 msg_Err( p_input, "Chunk Size mismatch" );
1160 AVI_SeekAbsolute( p_input,
1161 __EVEN( AVI_TellAbsolute( p_input ) +
1162 i_size - i_length ) );
1167 /* XXX Don't use this function directly ! XXX */
1168 static int __AVI_GetChunk( input_thread_t *p_input,
1169 AVIStreamInfo_t *p_info,
1172 demux_sys_t *p_avi = p_input->p_demux_data;
1173 AVIStreamInfo_t *p_other;
1178 #define p_info_i p_avi->pp_info[i]
1179 while( p_info->p_pes_first )
1181 if( ( p_info->p_pes_first->i_posc == p_info->i_idxposc )
1182 &&( p_info->i_idxposb >= p_info->p_pes_first->i_posb )
1183 &&( p_info->i_idxposb < p_info->p_pes_first->i_posb +
1184 p_info->p_pes_first->p_pes->i_pes_size ) )
1187 return( 1 ); /* we have it in buffer */
1191 AVI_PESBuffer_Drop( p_input->p_method_data, p_info );
1194 /* up to now we handle only one audio and video streams at the same time */
1195 p_other = (p_info == p_avi->p_info_video ) ?
1196 p_avi->p_info_audio : p_avi->p_info_video ;
1198 i_method = __AVI_GetChunkMethod( p_input, p_info, p_other );
1202 /* get directly the good chunk */
1203 return( b_load ? __AVI_SeekAndGetChunk( p_input, p_info ) : 1 );
1206 * because invalid index
1207 * or will find ck_other before ck_info
1209 /* msg_Warn( p_input, "method %d", i_method ); */
1210 /* we will calculate the better position we have to reach */
1214 /* the position max we have already reached */
1215 /* FIXME this isn't the better because sometime will fail to
1216 put in buffer p_other since it could be too far */
1217 AVIStreamInfo_t *p_info_max = p_info;
1219 for( i = 0; i < p_avi->i_streams; i++ )
1221 if( p_info_i->i_idxnb )
1223 if( p_info_max->i_idxnb )
1225 if( p_info_i->p_index[p_info_i->i_idxnb -1 ].i_pos >
1226 p_info_max->p_index[p_info_max->i_idxnb -1 ].i_pos )
1228 p_info_max = p_info_i;
1233 p_info_max = p_info_i;
1237 if( p_info_max->i_idxnb )
1239 /* be carefull that size between index and ck can sometime be
1240 different without any error (and other time it's an error) */
1241 i_posmax = p_info_max->p_index[p_info_max->i_idxnb -1 ].i_pos;
1242 /* so choose this, and I know that we have already reach it */
1246 i_posmax = p_avi->p_movi->i_pos + 12;
1253 return( 1 ); /* all is ok */
1256 /* we know that the entry and the last one are valid for the 2 stream */
1257 /* and ck_other will come *before* index so go directly to it*/
1258 i_posmax = p_other->p_index[p_other->i_idxposc].i_pos;
1261 AVI_SeekAbsolute( p_input, i_posmax );
1262 /* the first chunk we will see is :
1263 * the last chunk that we have already seen for broken index
1264 * the first ck for other with good index */
1265 for( ; ; ) /* infinite parsing until the ck we want */
1270 /* Get the actual chunk in the stream */
1271 if( !(p_ck = RIFF_ReadChunk( p_input )) )
1275 /* msg_Dbg( p_input, "ck: %4.4s len %d", &p_ck->i_id, p_ck->i_size ); */
1276 /* special case for LIST-rec chunk */
1277 if( ( p_ck->i_id == AVIFOURCC_LIST )&&( p_ck->i_type == AVIFOURCC_rec ) )
1279 RIFF_DescendChunk( p_input );
1280 RIFF_DeleteChunk( p_input, p_ck );
1283 AVI_ParseStreamHeader( p_ck->i_id, &i, &i_type );
1284 /* littles checks but not too much if you want to read all file */
1285 if( i >= p_avi->i_streams )
1286 /* (AVI_GetESTypeFromTwoCC(i_type) != p_info_i->i_cat) perhaps add it*/
1289 RIFF_DeleteChunk( p_input, p_ck );
1290 if( RIFF_NextChunk( p_input, p_avi->p_movi ) != 0 )
1299 /* have we found a new entry (not present in index)? */
1300 if( ( !p_info_i->i_idxnb )
1301 ||(p_info_i->p_index[p_info_i->i_idxnb-1].i_pos < p_ck->i_pos))
1303 AVIIndexEntry_t index;
1305 index.i_id = p_ck->i_id;
1306 index.i_flags = AVI_GetKeyFlag( p_info_i->p_es->i_fourcc,
1307 (u8*)&p_ck->i_8bytes);
1308 index.i_pos = p_ck->i_pos;
1309 index.i_length = p_ck->i_size;
1310 __AVI_AddEntryIndex( p_info_i, &index );
1314 /* TODO check if p_other is full and then if is possible
1315 go directly to the good chunk */
1316 if( ( p_info_i == p_other )
1317 &&( !AVI_PESBuffer_IsFull( p_other ) )
1318 &&( ( !p_other->p_pes_last )||
1319 ( p_other->p_pes_last->p_pes->i_pes_size !=
1320 BUFFER_MAXSPESSIZE ) ) )
1322 int i_ck = p_other->p_pes_last ?
1323 p_other->p_pes_last->i_posc + 1 : p_other->i_idxposc;
1324 i_size = __AVI_ChooseSize( p_ck->i_size,
1325 p_other->p_index[i_ck].i_length);
1327 if( p_other->p_index[i_ck].i_pos == p_ck->i_pos )
1329 if( !__AVI_GetAndPutChunkInBuffer( p_input, p_other,
1332 RIFF_DeleteChunk( p_input, p_ck );
1338 if( RIFF_NextChunk( p_input, p_avi->p_movi ) != 0 )
1340 RIFF_DeleteChunk( p_input, p_ck );
1347 RIFF_DeleteChunk( p_input, p_ck );
1350 if( ( p_info_i == p_info)
1351 &&( p_info->i_idxposc < p_info->i_idxnb ) )
1353 /* the first ck_info is ok otherwise it should be
1354 loaded without parsing */
1355 i_size = __AVI_ChooseSize( p_ck->i_size,
1356 p_info->p_index[p_info->i_idxposc].i_length);
1359 RIFF_DeleteChunk( p_input, p_ck );
1361 return( b_load ? __AVI_GetAndPutChunkInBuffer( p_input,
1364 p_info->i_idxposc ) : 1 );
1369 RIFF_DeleteChunk( p_input, p_ck );
1370 if( RIFF_NextChunk( p_input, p_avi->p_movi ) != 0 )
1383 /* be sure that i_ck will be a valid index entry */
1384 static int AVI_SetStreamChunk( input_thread_t *p_input,
1385 AVIStreamInfo_t *p_info,
1389 p_info->i_idxposc = i_ck;
1390 p_info->i_idxposb = 0;
1392 if( i_ck < p_info->i_idxnb )
1398 p_info->i_idxposc = p_info->i_idxnb - 1;
1401 p_info->i_idxposc++;
1402 if( !__AVI_GetChunk( p_input, p_info, 0 ) )
1406 } while( p_info->i_idxposc < i_ck );
1413 /* XXX FIXME up to now, we assume that all chunk are one after one */
1414 static int AVI_SetStreamBytes( input_thread_t *p_input,
1415 AVIStreamInfo_t *p_info,
1418 if( ( p_info->i_idxnb > 0 )
1419 &&( i_byte < p_info->p_index[p_info->i_idxnb - 1].i_lengthtotal +
1420 p_info->p_index[p_info->i_idxnb - 1].i_length ) )
1422 /* index is valid to find the ck */
1423 /* uses dichototmie to be fast enougth */
1424 int i_idxposc = __MIN( p_info->i_idxposc, p_info->i_idxnb - 1 );
1425 int i_idxmax = p_info->i_idxnb;
1429 if( p_info->p_index[i_idxposc].i_lengthtotal > i_byte )
1431 i_idxmax = i_idxposc ;
1432 i_idxposc = ( i_idxmin + i_idxposc ) / 2 ;
1436 if( p_info->p_index[i_idxposc].i_lengthtotal +
1437 p_info->p_index[i_idxposc].i_length <= i_byte)
1439 i_idxmin = i_idxposc ;
1440 i_idxposc = (i_idxmax + i_idxposc ) / 2 ;
1444 p_info->i_idxposc = i_idxposc;
1445 p_info->i_idxposb = i_byte -
1446 p_info->p_index[i_idxposc].i_lengthtotal;
1455 p_info->i_idxposc = p_info->i_idxnb - 1;
1456 p_info->i_idxposb = 0;
1459 p_info->i_idxposc++;
1460 if( !__AVI_GetChunk( p_input, p_info, 0 ) )
1464 } while( p_info->p_index[p_info->i_idxposc].i_lengthtotal +
1465 p_info->p_index[p_info->i_idxposc].i_length <= i_byte );
1467 p_info->i_idxposb = i_byte -
1468 p_info->p_index[p_info->i_idxposc].i_lengthtotal;
1473 static pes_packet_t *AVI_ReadStreamChunkInPES( input_thread_t *p_input,
1474 AVIStreamInfo_t *p_info )
1477 if( p_info->i_idxposc > p_info->i_idxnb )
1482 /* we want chunk (p_info->i_idxposc,0) */
1483 p_info->i_idxposb = 0;
1484 if( !__AVI_GetChunk( p_input, p_info, 1) )
1486 msg_Err( p_input, "Got one chunk : failed" );
1489 p_info->i_idxposc++;
1490 return( AVI_PESBuffer_Get( p_info ) );
1493 static pes_packet_t *AVI_ReadStreamBytesInPES( input_thread_t *p_input,
1494 AVIStreamInfo_t *p_info,
1497 pes_packet_t *p_pes;
1498 data_packet_t *p_data;
1503 if( !( p_pes = input_NewPES( p_input->p_method_data ) ) )
1507 if( !( p_data = input_NewPacket( p_input->p_method_data, i_byte ) ) )
1509 input_DeletePES( p_input->p_method_data, p_pes );
1514 p_pes->p_last = p_data;
1515 p_pes->i_nb_data = 1;
1516 p_pes->i_pes_size = i_byte;
1520 if( !__AVI_GetChunk( p_input, p_info, 1) )
1522 msg_Err( p_input, "Got one chunk : failed" );
1524 input_DeletePES( p_input->p_method_data, p_pes );
1528 i_read = __MIN( p_info->p_pes_first->p_pes->i_pes_size -
1529 ( p_info->i_idxposb - p_info->p_pes_first->i_posb ),
1531 /* FIXME FIXME FIXME follow all data packet */
1532 memcpy( p_data->p_payload_start + i_count,
1533 p_info->p_pes_first->p_pes->p_first->p_payload_start +
1534 p_info->i_idxposb - p_info->p_pes_first->i_posb,
1537 AVI_PESBuffer_Drop( p_input->p_method_data, p_info );
1541 p_info->i_idxposb += i_read;
1542 if( p_info->p_index[p_info->i_idxposc].i_length <= p_info->i_idxposb )
1544 p_info->i_idxposb -= p_info->p_index[p_info->i_idxposc].i_length;
1545 p_info->i_idxposc++;
1553 /* try to realign after a seek */
1554 static int AVI_ReAlign( input_thread_t *p_input,
1555 AVIStreamInfo_t *p_info )
1560 demux_sys_t *p_avi = p_input->p_demux_data;
1563 for( i = 0; i < p_avi->i_streams; i++ )
1565 AVI_PESBuffer_Flush( p_input->p_method_data, p_avi->pp_info[i] );
1568 TODO use input_ClockInit instead but need to be exported
1569 p_input->stream.p_selected_program->last_cr = 0;
1570 p_input->stream.p_selected_program->last_syscr = 0;
1571 p_input->stream.p_selected_program->cr_ref = 0;
1572 p_input->stream.p_selected_program->sysdate_ref = 0;
1573 p_input->stream.p_selected_program->delta_cr = 0;
1574 p_input->stream.p_selected_program->c_average_count = 0; */
1576 i_pos = AVI_TellAbsolute( p_input );
1578 p_info->i_idxposc--; /* in fact p_info->i_idxposc is for ck to be read */
1581 if( ( p_info->i_idxposc <= 0)
1582 ||( i_pos <= p_info->p_index[0].i_pos ) )
1584 /* before beginning of stream */
1585 return( p_info->header.i_samplesize ?
1586 AVI_SetStreamBytes( p_input, p_info, 0 ) :
1587 AVI_SetStreamChunk( p_input, p_info, 0 ) );
1590 b_after = ( i_pos >= p_info->p_index[p_info->i_idxposc].i_pos );
1591 /* now find in what chunk we are */
1592 while( ( i_pos < p_info->p_index[p_info->i_idxposc].i_pos )
1593 &&( p_info->i_idxposc > 0 ) )
1595 /* search before i_idxposc */
1597 if( !AVI_SetStreamChunk( p_input, p_info, p_info->i_idxposc - 1 ) )
1603 while( i_pos >= p_info->p_index[p_info->i_idxposc].i_pos +
1604 p_info->p_index[p_info->i_idxposc].i_length + 8 )
1606 /* search after i_idxposc */
1608 if( !AVI_SetStreamChunk( p_input, p_info, p_info->i_idxposc + 1 ) )
1614 /* search nearest key frame, only for video */
1615 if( p_info->i_cat == VIDEO_ES )
1619 while(!(p_info->p_index[p_info->i_idxposc].i_flags&AVIIF_KEYFRAME) )
1621 if( !AVI_SetStreamChunk( p_input, p_info,
1622 p_info->i_idxposc + 1 ) )
1630 while( ( p_info->i_idxposc > 0 ) &&
1631 (!(p_info->p_index[p_info->i_idxposc].i_flags&AVIIF_KEYFRAME)) )
1634 if( !AVI_SetStreamChunk( p_input, p_info,
1635 p_info->i_idxposc - 1 ) )
1646 /* make difference between audio and video pts as little as possible */
1647 static void AVI_SynchroReInit( input_thread_t *p_input )
1649 demux_sys_t *p_avi = p_input->p_demux_data;
1651 #define p_info_video p_avi->p_info_video
1652 #define p_info_audio p_avi->p_info_audio
1653 if( ( !p_info_audio )||( !p_info_video ) )
1657 /* now resynch audio video video */
1658 /*don't care of AVIF_KEYFRAME */
1659 if( !p_info_audio->header.i_samplesize )
1661 AVI_SetStreamChunk( p_input,
1663 AVI_PTSToChunk( p_info_audio,
1664 AVI_GetPTS( p_info_video ) ) );
1668 AVI_SetStreamBytes( p_input,
1670 AVI_PTSToByte( p_info_audio,
1671 AVI_GetPTS( p_info_video ) ) );
1677 /*****************************************************************************
1678 * AVI_GetFrameInPES : get dpts length(µs) in pes from stream
1679 *****************************************************************************
1680 * Handle multiple pes, and set pts to the good value
1681 *****************************************************************************/
1682 static pes_packet_t *AVI_GetFrameInPES( input_thread_t *p_input,
1683 AVIStreamInfo_t *p_info,
1687 pes_packet_t *p_pes = NULL;
1688 pes_packet_t *p_pes_tmp = NULL;
1689 pes_packet_t *p_pes_first = NULL;
1697 if( !p_info->header.i_samplesize )
1699 int i_chunk = __MAX( AVI_PTSToChunk( p_info, i_dpts), 1 );
1701 for( i = 0; i < i_chunk; i++ )
1703 /* get pts while is valid */
1704 i_pts = AVI_GetPTS( p_info );
1706 p_pes_tmp = AVI_ReadStreamChunkInPES( p_input, p_info );
1710 return( p_pes_first );
1712 p_pes_tmp->i_pts = i_pts;
1715 p_pes_first = p_pes_tmp;
1719 p_pes->p_next = p_pes_tmp;
1723 return( p_pes_first );
1727 /* stream is byte based */
1728 int i_byte = AVI_PTSToByte( p_info, i_dpts);
1729 if( i_byte < 50 ) /* to avoid some problem with audio */
1733 i_pts = AVI_GetPTS( p_info ); /* ok even with broken index */
1734 p_pes = AVI_ReadStreamBytesInPES( p_input, p_info, i_byte);
1738 p_pes->i_pts = i_pts;
1743 /*****************************************************************************
1744 * AVI_DecodePES : send a pes to decoder
1745 *****************************************************************************
1746 * Handle multiple pes, and update pts to the good value
1747 *****************************************************************************/
1748 static inline void AVI_DecodePES( input_thread_t *p_input,
1749 AVIStreamInfo_t *p_info,
1750 pes_packet_t *p_pes )
1752 pes_packet_t *p_pes_next;
1753 /* input_decode want only one pes, but AVI_GetFrameInPES give
1754 multiple pes so send one by one */
1757 p_pes_next = p_pes->p_next;
1758 p_pes->p_next = NULL;
1759 p_pes->i_pts = input_ClockGetTS( p_input,
1760 p_input->stream.p_selected_program,
1761 p_pes->i_pts * 9/100);
1762 input_DecodePES( p_info->p_es->p_decoder_fifo, p_pes );
1768 /*****************************************************************************
1769 * AVIDemux_Seekable: reads and demuxes data packets for stream seekable
1770 *****************************************************************************
1771 * Called by AVIDemux, that make common work
1772 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
1773 *****************************************************************************/
1774 static int AVIDemux_Seekable( input_thread_t *p_input,
1775 AVIStreamInfo_t *p_info_master,
1776 AVIStreamInfo_t *p_info_slave )
1778 demux_sys_t *p_avi = p_input->p_demux_data;
1780 pes_packet_t *p_pes_master;
1781 pes_packet_t *p_pes_slave;
1783 /* check for signal from interface */
1784 if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
1786 /* we can supposed that is a seek */
1787 /* first wait for empty buffer, arbitrary time */
1788 msleep( DEFAULT_PTS_DELAY );
1789 /* then try to realign in stream */
1790 if( !AVI_ReAlign( p_input, p_info_master ) )
1792 return( 0 ); /* assume EOF */
1794 AVI_SynchroReInit( p_input );
1797 /* take care of newly selected audio ES */
1798 if( p_info_master->b_selected )
1800 p_info_master->b_selected = 0;
1801 AVI_SynchroReInit( p_input );
1803 if( ( p_info_slave )&&( p_info_slave->b_selected ) )
1805 p_info_slave->b_selected = 0;
1806 AVI_SynchroReInit( p_input );
1809 /* wait for the good time */
1810 input_ClockManageRef( p_input,
1811 p_input->stream.p_selected_program,
1812 p_avi->i_pcr /*- DEFAULT_PTS_DELAY / 2 */);
1813 /* calculate pcr, time when we must read the next data */
1814 /* 9/100 kludge ->need to convert to 1/1000000 clock unit to 1/90000 */
1817 p_avi->i_pcr = __MIN( AVI_GetPTS( p_info_master ),
1818 AVI_GetPTS( p_info_slave ) ) * 9/100;
1822 p_avi->i_pcr = AVI_GetPTS( p_info_master ) * 9/100;
1825 /* get video and audio frames */
1826 p_pes_master = AVI_GetFrameInPES( p_input,
1828 100000 ); /* 100 ms */
1829 AVI_DecodePES( p_input,
1836 p_pes_slave = AVI_GetFrameInPES( p_input,
1838 AVI_GetPTS( p_info_master ) -
1839 AVI_GetPTS( p_info_slave) );
1840 AVI_DecodePES( p_input,
1847 return( p_pes_master ? 1 : 0 );
1851 /*****************************************************************************
1852 * AVIDemux_NotSeekable: reads and demuxes data packets for stream seekable
1853 *****************************************************************************
1854 * Called by AVIDemux, that makes common work
1855 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
1856 *****************************************************************************/
1858 /* 0 if can be load/updated, 1 if skip, 2 if descend into, 3 if exit, 4 if error and need recover */
1859 static int __AVIDemux_ChunkAction( int i_streams_max,
1865 AVI_ParseStreamHeader( p_ck->i_id, &i_stream, &i_type );
1866 if( i_stream < i_streams_max )
1868 return( 0 ); /* read and/or update stream info */
1871 if( i_stream <= 99 )
1873 /* should not happen but ... */
1877 /* now we know that it's not a stream */
1879 switch( p_ck->i_id )
1881 case( AVIFOURCC_JUNK ):
1883 case( AVIFOURCC_idx1 ):
1885 case( AVIFOURCC_LIST ):
1886 if( p_ck->i_type == AVIFOURCC_rec )
1899 if( ( p_ck->i_id & 0xFFFF ) == MKTWOCC( 'i','x' ) )
1907 static int AVI_NotSeekableRecover( input_thread_t *p_input )
1911 int i_number, i_type;
1912 data_packet_t *p_pack;
1916 if( input_Peek( p_input, &p_id, 4 ) < 4 )
1918 return( 0 ); /* Failed */
1920 i_id = GetDWLE( p_id );
1923 case( AVIFOURCC_idx1 ):
1924 case( AVIFOURCC_JUNK ):
1925 case( AVIFOURCC_LIST ):
1928 AVI_ParseStreamHeader( i_id, &i_number, &i_type );
1929 if( i_number <= 99 )
1933 case( AVITWOCC_wb ):
1934 case( AVITWOCC_db ):
1935 case( AVITWOCC_dc ):
1936 case( AVITWOCC_pc ):
1945 /* Read 1 byte VERY unoptimised */
1946 if( input_SplitBuffer( p_input, &p_pack, 1) < 1 )
1950 input_DeletePacket( p_input->p_method_data, p_pack);
1955 static int AVIDemux_NotSeekable( input_thread_t *p_input,
1956 AVIStreamInfo_t *p_info_master,
1957 AVIStreamInfo_t *p_info_slave )
1959 demux_sys_t *p_avi = p_input->p_demux_data;
1965 pes_packet_t *p_pes;
1968 i_filepos = AVI_TellAbsolute( p_input );
1969 p_input->pf_seek( p_input, i_filepos );
1970 input_AccessReinit( p_input );
1973 #define p_info p_avi->pp_info[i_stream]
1975 /* The managment is very basic, we will read packets, caclulate pts
1976 and send it to decoder, synchro made on video, and audio is very less
1979 /* wait the good time */
1980 input_ClockManageRef( p_input,
1981 p_input->stream.p_selected_program,
1982 p_avi->i_pcr /*- DEFAULT_PTS_DELAY / 2 */);
1983 /* TODO be smart, seeing if we can wait for min( audio, video )
1984 or there is a too big deep */
1987 p_avi->i_pcr = AVI_GetPTS( p_info_master ) * 9/100;
1991 p_avi->i_pcr = __MIN( AVI_GetPTS( p_info_master ),
1992 AVI_GetPTS( p_info_slave ) ) * 9/100;
1993 p_avi->i_pcr = AVI_GetPTS( p_info_master ) * 9/100;
1996 for( i_loop = 0; i_loop < 10; i_loop++ )
2000 /* first find a ck for master or slave */
2004 if( !(p_ck = RIFF_ReadChunk( p_input ) ) )
2006 msg_Err( p_input, "Badd" );
2007 return( 0 ); /* assume EOF */
2009 /*msg_Err( p_input,"Looking ck: %4.4s %d",&p_ck->i_id, p_ck->i_size );*/
2011 switch( __AVIDemux_ChunkAction( p_avi->i_streams, p_ck ) )
2013 case( 0 ): /* load it if possible */
2016 case( 1 ): /* skip it */
2017 RIFF_DeleteChunk( p_input, p_ck );
2018 if( RIFF_NextChunk( p_input, p_avi->p_movi ) != 0 )
2024 case( 2 ): /* descend into */
2025 RIFF_DeleteChunk( p_input, p_ck );
2026 RIFF_DescendChunk( p_input );
2029 case( 3 ): /* exit */
2030 RIFF_DeleteChunk( p_input, p_ck );
2032 case( 4 ): /* Error */
2033 RIFF_DeleteChunk( p_input, p_ck );
2034 msg_Warn( p_input, "unknown chunk id 0x%8.8x, trying to recover", p_ck->i_id );
2035 if( !AVI_NotSeekableRecover( p_input ) )
2037 msg_Err( p_input, "cannot recover, dying" );
2042 msg_Warn( p_input, "recovered sucessfully" );
2050 AVI_ParseStreamHeader( p_ck->i_id, &i_stream, &i_type );
2051 /* now check if we really have to load it */
2052 if( ( p_info != p_info_master )&&( p_info != p_info_slave ) )
2058 if( p_info == p_info_master )
2065 i_dpts = AVI_GetPTS( p_info_slave ) -
2066 AVI_GetPTS( p_info_master );
2067 if( i_dpts < 0 ) {i_dpts = - i_dpts; }
2068 if( i_dpts < 600000 )
2080 /* now do we can load this chunk ? */
2084 if( __AVI_GetDataInPES( p_input, &p_pes, p_ck->i_size + 8, 1) != p_ck->i_size + 8)
2088 p_pes->p_first->p_payload_start += 8;
2089 p_pes->i_pes_size -= 8;
2091 p_pes->i_pts = AVI_GetPTS( p_info );
2092 AVI_DecodePES( p_input, p_info, p_pes );
2097 if( RIFF_NextChunk( p_input, p_avi->p_movi ) != 0 )
2099 RIFF_DeleteChunk( p_input, p_ck );
2104 /* finaly update stream information */
2105 if( p_info->header.i_samplesize )
2107 p_info->i_idxposb += p_ck->i_size;
2111 p_info->i_idxposc++;
2114 RIFF_DeleteChunk( p_input, p_ck );
2120 /*****************************************************************************
2121 * AVIDemux: reads and demuxes data packets
2122 *****************************************************************************
2123 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
2124 * TODO add support for unstreable file, just read a chunk and send it
2125 * to the right decoder, very easy
2126 *****************************************************************************/
2128 static int AVIDemux( input_thread_t *p_input )
2131 AVIStreamInfo_t *p_info_master;
2132 AVIStreamInfo_t *p_info_slave;
2134 demux_sys_t *p_avi = p_input->p_demux_data;
2136 /* search new video and audio stream selected
2137 if current have been unselected*/
2138 if( ( !p_avi->p_info_video )
2139 || ( !p_avi->p_info_video->p_es->p_decoder_fifo ) )
2141 p_avi->p_info_video = NULL;
2142 for( i = 0; i < p_avi->i_streams; i++ )
2144 if( ( p_avi->pp_info[i]->i_cat == VIDEO_ES )
2145 &&( p_avi->pp_info[i]->p_es->p_decoder_fifo ) )
2147 p_avi->p_info_video = p_avi->pp_info[i];
2148 p_avi->p_info_video->b_selected = 1;
2153 if( ( !p_avi->p_info_audio )
2154 ||( !p_avi->p_info_audio->p_es->p_decoder_fifo ) )
2156 p_avi->p_info_audio = NULL;
2157 for( i = 0; i < p_avi->i_streams; i++ )
2159 if( ( p_avi->pp_info[i]->i_cat == AUDIO_ES )
2160 &&( p_avi->pp_info[i]->p_es->p_decoder_fifo ) )
2162 p_avi->p_info_audio = p_avi->pp_info[i];
2163 p_avi->p_info_audio->b_selected = 1;
2168 /* by default video is master for resync audio (after a seek .. ) */
2169 if( p_avi->p_info_video )
2171 p_info_master = p_avi->p_info_video;
2172 p_info_slave = p_avi->p_info_audio;
2176 p_info_master = p_avi->p_info_audio;
2177 p_info_slave = NULL;
2180 if( !p_info_master )
2182 msg_Err( p_input, "no stream selected" );
2186 /* manage rate, if not default: skeep audio */
2187 vlc_mutex_lock( &p_input->stream.stream_lock );
2188 if( p_input->stream.control.i_rate != p_avi->i_rate )
2190 if( p_avi->p_info_audio)
2192 p_avi->p_info_audio->b_selected = 1;
2194 p_avi->i_rate = p_input->stream.control.i_rate;
2196 vlc_mutex_unlock( &p_input->stream.stream_lock );
2197 p_avi->i_rate = DEFAULT_RATE;
2198 if( p_avi->i_rate != DEFAULT_RATE )
2200 p_info_slave = NULL;
2203 if( p_avi->b_seekable )
2205 return( AVIDemux_Seekable( p_input,
2211 return( AVIDemux_NotSeekable( p_input,