1 /*****************************************************************************
2 * avi.c : AVI file Stream input module for vlc
3 *****************************************************************************
4 * Copyright (C) 2001 VideoLAN
5 * $Id: avi.c,v 1.32 2002/07/23 00:39:16 sam 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 vlc_fourcc_t AVI_AudioGetType( u32 i_type )
187 /* case( WAVE_FORMAT_PCM ):
188 return VLC_FOURCC('l','p','c','m'); */
189 case( WAVE_FORMAT_AC3 ):
190 return VLC_FOURCC('a','5','2',' ');
191 case( WAVE_FORMAT_MPEG):
192 case( WAVE_FORMAT_MPEGLAYER3):
193 return VLC_FOURCC('m','p','g','a'); /* for mpeg2 layer 1 2 ou 3 */
199 /* Test if it seems that it's a key frame */
200 static int AVI_GetKeyFlag( vlc_fourcc_t i_fourcc, u8 *p_byte )
208 if( GetDWBE( p_byte ) != 0x00000100 )
209 /* startcode perhaps swapped, I haven't tested */
211 /* it's seems it's not an msmpegv1 stream
212 but perhaps I'm wrong so return yes */
213 return( AVIIF_KEYFRAME );
217 return( (*(p_byte+4))&0x06 ? 0 : AVIIF_KEYFRAME);
237 // printf( "\n Is a Key Frame %s", (*p_byte)&0xC0 ? "no" : "yes!!" );
238 return( (*p_byte)&0xC0 ? 0 : AVIIF_KEYFRAME );
251 if( GetDWBE( p_byte ) != 0x000001b6 )
253 /* not true , need to find the first VOP header
255 return( AVIIF_KEYFRAME );
259 // printf( "\n Is a Key Frame %s", (*(p_byte+4))&0xC0 ? "no" :
261 return( (*(p_byte+4))&0xC0 ? 0 : AVIIF_KEYFRAME );
264 /* I can't do it, so said yes */
265 return( AVIIF_KEYFRAME );
269 /*****************************************************************************
270 * Data and functions to manipulate pes buffer
271 *****************************************************************************/
272 #define BUFFER_MAXTOTALSIZE 512*1024 /* 1/2 Mo */
273 #define BUFFER_MAXSPESSIZE 1024*200
274 static int AVI_PESBuffer_IsFull( AVIStreamInfo_t *p_info )
276 return( p_info->i_pes_totalsize > BUFFER_MAXTOTALSIZE ? 1 : 0);
278 static void AVI_PESBuffer_Add( input_buffers_t *p_method_data,
279 AVIStreamInfo_t *p_info,
284 AVIESBuffer_t *p_buffer_pes;
286 if( p_info->i_pes_totalsize > BUFFER_MAXTOTALSIZE )
288 input_DeletePES( p_method_data, p_pes );
292 if( !( p_buffer_pes = malloc( sizeof( AVIESBuffer_t ) ) ) )
294 input_DeletePES( p_method_data, p_pes );
297 p_buffer_pes->p_next = NULL;
298 p_buffer_pes->p_pes = p_pes;
299 p_buffer_pes->i_posc = i_posc;
300 p_buffer_pes->i_posb = i_posb;
302 if( p_info->p_pes_last )
304 p_info->p_pes_last->p_next = p_buffer_pes;
306 p_info->p_pes_last = p_buffer_pes;
307 if( !p_info->p_pes_first )
309 p_info->p_pes_first = p_buffer_pes;
311 p_info->i_pes_count++;
312 p_info->i_pes_totalsize += p_pes->i_pes_size;
314 static pes_packet_t *AVI_PESBuffer_Get( AVIStreamInfo_t *p_info )
316 AVIESBuffer_t *p_buffer_pes;
318 if( p_info->p_pes_first )
320 p_buffer_pes = p_info->p_pes_first;
321 p_info->p_pes_first = p_buffer_pes->p_next;
322 if( !p_info->p_pes_first )
324 p_info->p_pes_last = NULL;
326 p_pes = p_buffer_pes->p_pes;
328 free( p_buffer_pes );
329 p_info->i_pes_count--;
330 p_info->i_pes_totalsize -= p_pes->i_pes_size;
338 static int AVI_PESBuffer_Drop( input_buffers_t *p_method_data,
339 AVIStreamInfo_t *p_info )
341 pes_packet_t *p_pes = AVI_PESBuffer_Get( p_info );
344 input_DeletePES( p_method_data, p_pes );
352 static void AVI_PESBuffer_Flush( input_buffers_t *p_method_data,
353 AVIStreamInfo_t *p_info )
355 while( p_info->p_pes_first )
357 AVI_PESBuffer_Drop( p_method_data, p_info );
361 static void AVI_ParseStreamHeader( u32 i_id, int *i_number, int *i_type )
365 c1 = ( i_id ) & 0xFF;
366 c2 = ( i_id >> 8 ) & 0xFF;
368 if( c1 < '0' || c1 > '9' || c2 < '0' || c2 > '9' )
370 *i_number = 100; /* > max stream number */
375 *i_number = (c1 - '0') * 10 + (c2 - '0' );
376 *i_type = ( i_id >> 16 ) & 0xFFFF;
380 /* Function to manipulate stream easily */
381 static off_t AVI_TellAbsolute( input_thread_t *p_input )
384 vlc_mutex_lock( &p_input->stream.stream_lock );
385 i_pos= p_input->stream.p_selected_area->i_tell -
386 ( p_input->p_last_data - p_input->p_current_data );
387 vlc_mutex_unlock( &p_input->stream.stream_lock );
392 static int AVI_SeekAbsolute( input_thread_t *p_input,
396 /* FIXME add support for not seekable stream */
398 i_filepos = AVI_TellAbsolute( p_input );
399 if( i_pos != i_filepos )
401 // msg_Err( p_input, "Seek --> delta %d", i_pos - i_filepos );
402 p_input->pf_seek( p_input, i_pos );
403 input_AccessReinit( p_input );
409 static void __AVI_AddEntryIndex( AVIStreamInfo_t *p_info,
410 AVIIndexEntry_t *p_index)
412 AVIIndexEntry_t *p_tmp;
413 if( p_info->p_index == NULL )
415 p_info->i_idxmax = 16384;
417 p_info->p_index = calloc( p_info->i_idxmax,
418 sizeof( AVIIndexEntry_t ) );
419 if( p_info->p_index == NULL ) {return;}
421 if( p_info->i_idxnb >= p_info->i_idxmax )
423 p_info->i_idxmax += 16384;
424 p_tmp = realloc( (void*)p_info->p_index,
426 sizeof( AVIIndexEntry_t ) );
429 p_info->i_idxmax -= 16384;
432 p_info->p_index = p_tmp;
434 /* calculate cumulate length */
435 if( p_info->i_idxnb > 0 )
437 p_index->i_lengthtotal = p_info->p_index[p_info->i_idxnb-1].i_length +
438 p_info->p_index[p_info->i_idxnb-1].i_lengthtotal;
442 p_index->i_lengthtotal = 0;
445 p_info->p_index[p_info->i_idxnb] = *p_index;
449 static void __AVI_GetIndex( input_thread_t *p_input )
451 AVIIndexEntry_t index;
458 int i_totalentry = 0;
459 demux_data_avi_file_t *p_avi_demux =
460 (demux_data_avi_file_t*)p_input->p_demux_data ;
462 if( RIFF_FindAndGotoDataChunk( p_input,
467 msg_Warn( p_input, "cannot find index" );
468 RIFF_GoToChunk( p_input, p_avi_demux->p_hdrl );
471 p_avi_demux->p_idx1 = p_idx1;
472 msg_Dbg( p_input, "loading index" );
475 i_read = __MIN( 16*1024, p_idx1->i_size - i_totalentry *16);
476 if( ((i_read = input_Peek( p_input, &p_buff, i_read )) < 16 )
477 ||( i_totalentry *16 >= p_idx1->i_size ) )
479 msg_Dbg( p_input, "read %d idx entries", i_totalentry );
483 for( i = 0; i < i_read; i++ )
485 byte_t *p_peek = p_buff + i * 16;
487 index.i_id = GetDWLE( p_peek );
488 index.i_flags = GetDWLE( p_peek+4)&(~AVIIF_FIXKEYFRAME);
489 index.i_pos = GetDWLE( p_peek+8);
490 index.i_length = GetDWLE(p_peek+12);
491 AVI_ParseStreamHeader( index.i_id, &i_number, &i_type );
493 if( ( i_number < p_avi_demux->i_streams )
494 &&(p_avi_demux->pp_info[i_number]->i_cat ==
495 AVI_GetESTypeFromTwoCC( i_type )))
497 __AVI_AddEntryIndex( p_avi_demux->pp_info[i_number],
501 __RIFF_SkipBytes( p_input, 16 * i_read );
506 /* XXX call after get p_movi */
507 static void __AVI_UpdateIndexOffset( input_thread_t *p_input )
510 int b_start = 1;/* if index pos is based on start of file or not (p_movi) */
511 demux_data_avi_file_t *p_avi_demux =
512 (demux_data_avi_file_t*)p_input->p_demux_data;
514 /* FIXME some work to do :
515 * test in the file if it's true, if not do a RIFF_Find...
517 #define p_info p_avi_demux->pp_info[i_stream]
518 for( i_stream = 0; i_stream < p_avi_demux->i_streams; i_stream++ )
520 if( ( p_info->p_index )
521 && ( p_info->p_index[0].i_pos < p_avi_demux->p_movi->i_pos + 8 ))
529 for( i_stream = 0; i_stream < p_avi_demux->i_streams; i_stream++ )
532 if( p_info->p_index )
534 for( i = 0; i < p_info->i_idxnb; i++ )
536 p_info->p_index[i].i_pos += p_avi_demux->p_movi->i_pos + 8;
544 /*****************************************************************************
545 * AVIEnd: frees unused data
546 *****************************************************************************/
547 static void AVIEnd( input_thread_t *p_input )
550 demux_data_avi_file_t *p_avi_demux;
551 p_avi_demux = (demux_data_avi_file_t*)p_input->p_demux_data ;
553 if( p_avi_demux->p_riff )
554 RIFF_DeleteChunk( p_input, p_avi_demux->p_riff );
555 if( p_avi_demux->p_hdrl )
556 RIFF_DeleteChunk( p_input, p_avi_demux->p_hdrl );
557 if( p_avi_demux->p_movi )
558 RIFF_DeleteChunk( p_input, p_avi_demux->p_movi );
559 if( p_avi_demux->p_idx1 )
560 RIFF_DeleteChunk( p_input, p_avi_demux->p_idx1 );
561 if( p_avi_demux->pp_info )
563 for( i = 0; i < p_avi_demux->i_streams; i++ )
565 if( p_avi_demux->pp_info[i] )
567 if( p_avi_demux->pp_info[i]->p_index )
569 free( p_avi_demux->pp_info[i]->p_index );
570 AVI_PESBuffer_Flush( p_input->p_method_data,
571 p_avi_demux->pp_info[i] );
573 free( p_avi_demux->pp_info[i] );
576 free( p_avi_demux->pp_info );
580 /*****************************************************************************
581 * AVIInit: check file and initializes AVI structures
582 *****************************************************************************/
583 static int AVIInit( input_thread_t *p_input )
585 riffchunk_t *p_riff,*p_hdrl,*p_movi;
587 riffchunk_t *p_strl,*p_strh,*p_strf;
588 demux_data_avi_file_t *p_avi_demux;
589 es_descriptor_t *p_es = NULL; /* for not warning */
592 if( !( p_input->p_demux_data =
593 p_avi_demux = malloc( sizeof(demux_data_avi_file_t) ) ) )
595 msg_Err( p_input, "out of memory" );
598 memset( p_avi_demux, 0, sizeof( demux_data_avi_file_t ) );
599 p_avi_demux->i_rate = DEFAULT_RATE;
600 p_avi_demux->b_seekable = ( ( p_input->stream.b_seekable )
601 &&( p_input->stream.i_method == INPUT_METHOD_FILE ) );
603 /* Initialize access plug-in structures. */
604 if( p_input->i_mtu == 0 )
607 p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
610 if( RIFF_TestFileHeader( p_input, &p_riff, FOURCC_AVI ) != 0 )
613 msg_Warn( p_input, "RIFF-AVI module discarded" );
616 p_avi_demux->p_riff = p_riff;
618 if ( RIFF_DescendChunk(p_input) != 0 )
621 msg_Err( p_input, "cannot look for subchunk" );
625 /* it's a riff-avi file, so search for LIST-hdrl */
626 if( RIFF_FindListChunk(p_input ,&p_hdrl,p_riff, FOURCC_hdrl) != 0 )
629 msg_Err( p_input, "cannot find \"LIST-hdrl\"" );
632 p_avi_demux->p_hdrl = p_hdrl;
634 if( RIFF_DescendChunk(p_input) != 0 )
637 msg_Err( p_input, "cannot look for subchunk" );
640 /* in LIST-hdrl search avih */
641 if( RIFF_FindAndLoadChunk( p_input, p_hdrl,
642 &p_avih, FOURCC_avih ) != 0 )
645 msg_Err( p_input, "cannot find \"avih\" chunk" );
648 AVI_Parse_avih( &p_avi_demux->avih, p_avih->p_data->p_payload_start );
649 RIFF_DeleteChunk( p_input, p_avih );
651 if( p_avi_demux->avih.i_streams == 0 )
652 /* no stream found, perhaps it would be cool to find it */
655 msg_Err( p_input, "no stream defined!" );
659 /* create one program */
660 vlc_mutex_lock( &p_input->stream.stream_lock );
661 if( input_InitStream( p_input, 0 ) == -1)
663 vlc_mutex_unlock( &p_input->stream.stream_lock );
665 msg_Err( p_input, "cannot init stream" );
668 if( input_AddProgram( p_input, 0, 0) == NULL )
670 vlc_mutex_unlock( &p_input->stream.stream_lock );
672 msg_Err( p_input, "cannot add program" );
675 p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
676 p_input->stream.i_mux_rate = p_avi_demux->avih.i_maxbytespersec / 50;
677 vlc_mutex_unlock( &p_input->stream.stream_lock );
679 /* now read info on each stream and create ES */
680 p_avi_demux->i_streams = p_avi_demux->avih.i_streams;
682 p_avi_demux->pp_info = calloc( p_avi_demux->i_streams,
683 sizeof( AVIStreamInfo_t* ) );
684 memset( p_avi_demux->pp_info,
686 sizeof( AVIStreamInfo_t* ) * p_avi_demux->i_streams );
688 for( i = 0 ; i < p_avi_demux->i_streams; i++ )
690 #define p_info p_avi_demux->pp_info[i]
691 p_info = malloc( sizeof(AVIStreamInfo_t ) );
692 memset( p_info, 0, sizeof( AVIStreamInfo_t ) );
694 if( ( RIFF_FindListChunk(p_input,
695 &p_strl,p_hdrl, FOURCC_strl) != 0 )
696 ||( RIFF_DescendChunk(p_input) != 0 ))
699 msg_Err( p_input, "cannot find \"LIST-strl\"" );
703 /* in LIST-strl search strh */
704 if( RIFF_FindAndLoadChunk( p_input, p_hdrl,
705 &p_strh, FOURCC_strh ) != 0 )
707 RIFF_DeleteChunk( p_input, p_strl );
709 msg_Err( p_input, "cannot find \"strh\"" );
712 AVI_Parse_Header( &p_info->header,
713 p_strh->p_data->p_payload_start);
714 RIFF_DeleteChunk( p_input, p_strh );
716 /* in LIST-strl search strf */
717 if( RIFF_FindAndLoadChunk( p_input, p_hdrl,
718 &p_strf, FOURCC_strf ) != 0 )
720 RIFF_DeleteChunk( p_input, p_strl );
722 msg_Err( p_input, "cannot find \"strf\"" );
725 /* we don't get strd, it's useless for divx,opendivx,mepgaudio */
726 if( RIFF_AscendChunk(p_input, p_strl) != 0 )
728 RIFF_DeleteChunk( p_input, p_strf );
729 RIFF_DeleteChunk( p_input, p_strl );
731 msg_Err( p_input, "cannot go out (\"strl\")" );
736 vlc_mutex_lock( &p_input->stream.stream_lock );
737 p_es = input_AddES( p_input,
738 p_input->stream.p_selected_program, 1+i,
740 vlc_mutex_unlock( &p_input->stream.stream_lock );
741 p_es->i_stream_id =i; /* XXX: i don't use it */
743 switch( p_info->header.i_type )
746 p_es->i_cat = AUDIO_ES;
747 AVI_Parse_WaveFormatEx( &p_info->audio_format,
748 p_strf->p_data->p_payload_start );
749 p_es->i_fourcc = AVI_AudioGetType(
750 p_info->audio_format.i_formattag );
754 p_es->i_cat = VIDEO_ES;
755 AVI_Parse_BitMapInfoHeader( &p_info->video_format,
756 p_strf->p_data->p_payload_start );
758 /* XXX quick hack for playing ffmpeg video, I don't know
759 who is doing something wrong */
760 p_info->header.i_samplesize = 0;
761 p_es->i_fourcc = p_info->video_format.i_compression;
764 msg_Err( p_input, "unknown stream(%d) type", i );
765 p_es->i_cat = UNKNOWN_ES;
769 p_info->i_cat = p_es->i_cat;
770 /* We copy strf for decoder in p_es->p_demux_data */
771 memcpy( p_es->p_demux_data,
772 p_strf->p_data->p_payload_start,
774 RIFF_DeleteChunk( p_input, p_strf );
775 RIFF_DeleteChunk( p_input, p_strl );
781 /* go out of p_hdrl */
782 if( RIFF_AscendChunk(p_input, p_hdrl) != 0)
785 msg_Err( p_input, "cannot go out (\"hdrl\")" );
789 /* go to movi chunk to get it*/
790 if( RIFF_FindListChunk(p_input ,&p_movi,p_riff, FOURCC_movi) != 0 )
792 msg_Err( p_input, "cannot find \"LIST-movi\"" );
796 p_avi_demux->p_movi = p_movi;
798 /* get index XXX need to have p_movi */
799 if( p_avi_demux->b_seekable )
802 __AVI_GetIndex( p_input );
803 /* try to get i_idxoffset for each stream */
804 __AVI_UpdateIndexOffset( p_input );
805 /* to make sure to go the begining unless demux will see a seek */
806 RIFF_GoToChunk( p_input, p_avi_demux->p_movi );
811 msg_Warn( p_input, "no index!" );
814 if( RIFF_DescendChunk( p_input ) != 0 )
817 msg_Err( p_input, "cannot go in (\"movi\")" );
821 /* print informations on streams */
822 msg_Dbg( p_input, "AVIH: %d stream, flags %s%s%s%s ",
823 p_avi_demux->i_streams,
824 p_avi_demux->avih.i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
825 p_avi_demux->avih.i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",
826 p_avi_demux->avih.i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
827 p_avi_demux->avih.i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"" );
829 for( i = 0; i < p_avi_demux->i_streams; i++ )
831 #define p_info p_avi_demux->pp_info[i]
832 switch( p_info->p_es->i_cat )
836 msg_Dbg( p_input, "video(%4.4s) %dx%d %dbpp %ffps",
837 (char*)&p_info->video_format.i_compression,
838 p_info->video_format.i_width,
839 p_info->video_format.i_height,
840 p_info->video_format.i_bitcount,
841 (float)p_info->header.i_rate /
842 (float)p_info->header.i_scale );
843 if( (p_avi_demux->p_info_video == NULL) )
845 p_avi_demux->p_info_video = p_info;
846 /* TODO add test to see if a decoder has been found */
847 vlc_mutex_lock( &p_input->stream.stream_lock );
848 input_SelectES( p_input, p_info->p_es );
849 vlc_mutex_unlock( &p_input->stream.stream_lock );
854 msg_Dbg( p_input, "audio(0x%x) %d channels %dHz %dbits",
855 p_info->audio_format.i_formattag,
856 p_info->audio_format.i_channels,
857 p_info->audio_format.i_samplespersec,
858 p_info->audio_format.i_bitspersample );
859 if( (p_avi_demux->p_info_audio == NULL) )
861 p_avi_demux->p_info_audio = p_info;
862 vlc_mutex_lock( &p_input->stream.stream_lock );
863 input_SelectES( p_input, p_info->p_es );
864 vlc_mutex_unlock( &p_input->stream.stream_lock );
874 /* we select the first audio and video ES */
875 vlc_mutex_lock( &p_input->stream.stream_lock );
876 if( !p_avi_demux->p_info_video )
878 msg_Warn( p_input, "no video stream found" );
880 if( !p_avi_demux->p_info_audio )
882 msg_Warn( p_input, "no audio stream found!" );
884 p_input->stream.p_selected_program->b_is_ok = 1;
885 vlc_mutex_unlock( &p_input->stream.stream_lock );
895 /*****************************************************************************
896 * Function to convert pts to chunk or byte
897 *****************************************************************************/
899 static inline mtime_t AVI_PTSToChunk( AVIStreamInfo_t *p_info,
902 return( (mtime_t)((s64)i_pts *
903 (s64)p_info->header.i_rate /
904 (s64)p_info->header.i_scale /
907 static inline mtime_t AVI_PTSToByte( AVIStreamInfo_t *p_info,
910 return( (mtime_t)((s64)i_pts *
911 (s64)p_info->header.i_samplesize *
912 (s64)p_info->header.i_rate /
913 (s64)p_info->header.i_scale /
917 static mtime_t AVI_GetPTS( AVIStreamInfo_t *p_info )
920 if( p_info->header.i_samplesize )
922 /* we need a valid entry we will emulate one */
924 if( p_info->i_idxposc == p_info->i_idxnb )
926 if( p_info->i_idxposc )
928 /* use the last entry */
929 i_len = p_info->p_index[p_info->i_idxnb - 1].i_lengthtotal
930 + p_info->p_index[p_info->i_idxnb - 1].i_length
931 + p_info->i_idxposb; /* should be 0 */
935 i_len = p_info->i_idxposb;
936 /* no valid entry use only offset*/
941 i_len = p_info->p_index[p_info->i_idxposc].i_lengthtotal
944 return( (mtime_t)( (s64)1000000 *
946 (s64)p_info->header.i_scale /
947 (s64)p_info->header.i_rate /
948 (s64)p_info->header.i_samplesize ) );
952 /* even if p_info->i_idxposc isn't valid, there isn't any probllem */
953 return( (mtime_t)( (s64)1000000 *
954 (s64)(p_info->i_idxposc ) *
955 (s64)p_info->header.i_scale /
956 (s64)p_info->header.i_rate) );
961 /*****************************************************************************
962 * Functions to acces streams data
963 * Uses it, because i plane to read unseekable stream
964 * Don't work for the moment for unseekable stream
965 * XXX NEVER set directly i_idxposc and i_idxposb unless you know what you do
966 *****************************************************************************/
968 /* FIXME FIXME change b_pad to number of bytes to skipp after reading */
969 static int __AVI_GetDataInPES( input_thread_t *p_input,
970 pes_packet_t **pp_pes,
976 data_packet_t *p_data;
979 if( !(*pp_pes = input_NewPES( p_input->p_method_data ) ) )
987 p_data = input_NewPacket( p_input->p_method_data, 0 );
988 (*pp_pes)->p_first = (*pp_pes)->p_last = p_data;
989 (*pp_pes)->i_nb_data = 1;
990 (*pp_pes)->i_pes_size = 0;
994 if( ( i_size&1 )&&( b_pad ) )
1006 i_read = input_SplitBuffer(p_input, &p_data, __MIN( i_size -
1007 (*pp_pes)->i_pes_size, 1024 ) );
1010 return( (*pp_pes)->i_pes_size );
1012 if( !(*pp_pes)->p_first )
1014 (*pp_pes)->p_first =
1015 (*pp_pes)->p_last = p_data;
1016 (*pp_pes)->i_nb_data = 1;
1017 (*pp_pes)->i_pes_size = i_read;
1021 (*pp_pes)->p_last->p_next =
1022 (*pp_pes)->p_last = p_data;
1023 (*pp_pes)->i_nb_data++;
1024 (*pp_pes)->i_pes_size += i_read;
1026 } while( ((*pp_pes)->i_pes_size < i_size)&&( i_read ) );
1030 (*pp_pes)->i_pes_size--;
1031 (*pp_pes)->p_last->p_payload_end--;
1038 static int __AVI_SeekAndGetChunk( input_thread_t *p_input,
1039 AVIStreamInfo_t *p_info )
1041 pes_packet_t *p_pes;
1044 i_length = __MIN( p_info->p_index[p_info->i_idxposc].i_length
1045 - p_info->i_idxposb,
1046 BUFFER_MAXSPESSIZE );
1048 AVI_SeekAbsolute( p_input,
1049 (off_t)p_info->p_index[p_info->i_idxposc].i_pos +
1050 p_info->i_idxposb + 8);
1052 if( __AVI_GetDataInPES( p_input,
1059 /* TODO test key frame if i_idxposb == 0*/
1060 AVI_PESBuffer_Add( p_input->p_method_data,
1064 p_info->i_idxposb );
1067 /* TODO check if it's correct (humm...) and optimisation ... */
1068 /* return 0 if we choose to get only the ck we want
1069 * 1 if index is invalid
1070 * 2 if there is a ck_other before ck_info and the last proced ck_info*/
1071 /* XXX XXX XXX avi file is some BIG shit, and sometime index give
1072 * a refenrence to the same chunk BUT with a different size ( usually 0 )
1075 static inline int __AVI_GetChunkMethod( input_thread_t *p_input,
1076 AVIStreamInfo_t *p_info,
1077 AVIStreamInfo_t *p_other )
1082 int i_info_pos_last;
1083 int i_other_pos_last;
1085 /*If we don't have a valid entry we need to parse from last
1086 defined chunk and it's the only way that we return 1*/
1087 if( p_info->i_idxposc >= p_info->i_idxnb )
1092 /* KNOW we have a valid entry for p_info */
1093 /* we return 0 if we haven't an valid entry for p_other */
1094 if( ( !p_other )||( p_other->i_idxposc >= p_other->i_idxnb ) )
1099 /* KNOW there are 2 streams with valid entry */
1101 /* we return 0 if for one of the two streams we will not read
1103 if( ( p_info->i_idxposb )||( p_other->i_idxposb ) )
1108 /* KNOW we have a valid entry for the 2 streams
1109 and for the 2 we want an aligned chunk (given by i_idxposc )*/
1110 /* if in stream, the next chunk is back than the one we
1111 have just read, it's useless to parse */
1112 i_info_pos = p_info->p_index[p_info->i_idxposc].i_pos;
1113 i_other_pos = p_other->p_index[p_other->i_idxposc].i_pos ;
1115 i_info_pos_last = p_info->i_idxposc ?
1116 p_info->p_index[p_info->i_idxposc - 1].i_pos : 0;
1117 i_other_pos_last = p_other->i_idxposc ?
1118 p_other->p_index[p_other->i_idxposc - 1].i_pos : 0 ;
1121 if( ( ( p_info->i_idxposc )&&( i_info_pos <= i_info_pos_last ) ) ||
1122 ( ( p_other->i_idxposc )&&( i_other_pos <= i_other_pos_last ) ) )
1127 /* KNOW for the 2 streams, the ck we want are after the last read
1128 or it's the first */
1130 /* if the first ck_other we want isn't between ck_info_last
1131 and ck_info, don't parse */
1132 /* TODO fix this, use also number in buffered PES */
1133 if( ( i_other_pos > i_info_pos) /* ck_other too far */
1134 ||( i_other_pos < i_info_pos_last ) ) /* it's too late for ck_other */
1139 /* we Know we will find ck_other, and before ck_info
1140 "if ck_info is too far" will be handle after */
1145 static inline int __AVI_ChooseSize( int l1, int l2 )
1147 /* XXX l2 is prefered if 0 otherwise min not equal to 0 */
1152 return( !l1 ? l2 : __MIN( l1,l2 ) );
1155 /* We know we will read chunk align */
1156 static int __AVI_GetAndPutChunkInBuffer( input_thread_t *p_input,
1157 AVIStreamInfo_t *p_info,
1162 pes_packet_t *p_pes;
1165 i_length = __MIN( i_size, BUFFER_MAXSPESSIZE );
1167 /* Skip chunk header */
1169 if( __AVI_GetDataInPES( p_input, &p_pes, i_length + 8,1 ) != i_length +8 )
1173 p_pes->p_first->p_payload_start += 8;
1174 p_pes->i_pes_size -= 8;
1176 i_size = GetDWLE( p_pes->p_first->p_demux_start + 4);
1178 AVI_PESBuffer_Add( p_input->p_method_data,
1183 /* skip unwanted bytes */
1184 if( i_length != i_size)
1186 msg_Err( p_input, "Chunk Size mismatch" );
1187 AVI_SeekAbsolute( p_input,
1188 __EVEN( AVI_TellAbsolute( p_input ) +
1189 i_size - i_length ) );
1194 /* XXX Don't use this function directly ! XXX */
1195 static int __AVI_GetChunk( input_thread_t *p_input,
1196 AVIStreamInfo_t *p_info,
1199 demux_data_avi_file_t *p_avi_demux =
1200 (demux_data_avi_file_t*)p_input->p_demux_data;
1201 AVIStreamInfo_t *p_other;
1206 #define p_info_i p_avi_demux->pp_info[i]
1207 while( p_info->p_pes_first )
1209 if( ( p_info->p_pes_first->i_posc == p_info->i_idxposc )
1210 &&( p_info->i_idxposb >= p_info->p_pes_first->i_posb )
1211 &&( p_info->i_idxposb < p_info->p_pes_first->i_posb +
1212 p_info->p_pes_first->p_pes->i_pes_size ) )
1215 return( 1 ); /* we have it in buffer */
1219 AVI_PESBuffer_Drop( p_input->p_method_data, p_info );
1222 /* up to now we handle only one audio and video streams at the same time */
1223 p_other = (p_info == p_avi_demux->p_info_video ) ?
1224 p_avi_demux->p_info_audio : p_avi_demux->p_info_video ;
1226 i_method = __AVI_GetChunkMethod( p_input, p_info, p_other );
1230 /* get directly the good chunk */
1231 return( b_load ? __AVI_SeekAndGetChunk( p_input, p_info ) : 1 );
1234 * because invalid index
1235 * or will find ck_other before ck_info
1237 // msg_Warn( p_input, "method %d", i_method );
1238 /* we will calculate the better position we have to reach */
1242 /* the position max we have already reached */
1243 /* FIXME this isn't the better because sometime will fail to
1244 put in buffer p_other since it could be too far */
1245 AVIStreamInfo_t *p_info_max = p_info;
1247 for( i = 0; i < p_avi_demux->i_streams; i++ )
1249 if( p_info_i->i_idxnb )
1251 if( p_info_max->i_idxnb )
1253 if( p_info_i->p_index[p_info_i->i_idxnb -1 ].i_pos >
1254 p_info_max->p_index[p_info_max->i_idxnb -1 ].i_pos )
1256 p_info_max = p_info_i;
1261 p_info_max = p_info_i;
1265 if( p_info_max->i_idxnb )
1267 /* be carefull that size between index and ck can sometime be
1268 different without any error (and other time it's an error) */
1269 i_posmax = p_info_max->p_index[p_info_max->i_idxnb -1 ].i_pos;
1270 /* so choose this, and I know that we have already reach it */
1274 i_posmax = p_avi_demux->p_movi->i_pos + 12;
1281 return( 1 ); /* all is ok */
1284 /* we know that the entry and the last one are valid for the 2 stream */
1285 /* and ck_other will come *before* index so go directly to it*/
1286 i_posmax = p_other->p_index[p_other->i_idxposc].i_pos;
1289 AVI_SeekAbsolute( p_input, i_posmax );
1290 /* the first chunk we will see is :
1291 * the last chunk that we have already seen for broken index
1292 * the first ck for other with good index */
1293 for( ; ; ) /* infinite parsing until the ck we want */
1298 /* Get the actual chunk in the stream */
1299 if( !(p_ck = RIFF_ReadChunk( p_input )) )
1303 // msg_Dbg( p_input, "ck: %4.4s len %d", &p_ck->i_id, p_ck->i_size );
1304 /* special case for LIST-rec chunk */
1305 if( ( p_ck->i_id == FOURCC_LIST )&&( p_ck->i_type == FOURCC_rec ) )
1307 RIFF_DescendChunk( p_input );
1308 RIFF_DeleteChunk( p_input, p_ck );
1311 AVI_ParseStreamHeader( p_ck->i_id, &i, &i_type );
1312 /* littles checks but not too much if you want to read all file */
1313 if( i >= p_avi_demux->i_streams )
1314 /* (AVI_GetESTypeFromTwoCC(i_type) != p_info_i->i_cat) perhaps add it*/
1317 RIFF_DeleteChunk( p_input, p_ck );
1318 if( RIFF_NextChunk( p_input, p_avi_demux->p_movi ) != 0 )
1327 /* have we found a new entry (not present in index)? */
1328 if( ( !p_info_i->i_idxnb )
1329 ||(p_info_i->p_index[p_info_i->i_idxnb-1].i_pos < p_ck->i_pos))
1331 AVIIndexEntry_t index;
1333 index.i_id = p_ck->i_id;
1334 index.i_flags = AVI_GetKeyFlag( p_info_i->p_es->i_fourcc,
1335 (u8*)&p_ck->i_8bytes);
1336 index.i_pos = p_ck->i_pos;
1337 index.i_length = p_ck->i_size;
1338 __AVI_AddEntryIndex( p_info_i, &index );
1342 /* TODO check if p_other is full and then if is possible
1343 go directly to the good chunk */
1344 if( ( p_info_i == p_other )
1345 &&( !AVI_PESBuffer_IsFull( p_other ) )
1346 &&( ( !p_other->p_pes_last )||
1347 ( p_other->p_pes_last->p_pes->i_pes_size !=
1348 BUFFER_MAXSPESSIZE ) ) )
1350 int i_ck = p_other->p_pes_last ?
1351 p_other->p_pes_last->i_posc + 1 : p_other->i_idxposc;
1352 i_size = __AVI_ChooseSize( p_ck->i_size,
1353 p_other->p_index[i_ck].i_length);
1355 if( p_other->p_index[i_ck].i_pos == p_ck->i_pos )
1357 if( !__AVI_GetAndPutChunkInBuffer( p_input, p_other,
1360 RIFF_DeleteChunk( p_input, p_ck );
1366 if( RIFF_NextChunk( p_input, p_avi_demux->p_movi ) != 0 )
1368 RIFF_DeleteChunk( p_input, p_ck );
1375 RIFF_DeleteChunk( p_input, p_ck );
1378 if( ( p_info_i == p_info)
1379 &&( p_info->i_idxposc < p_info->i_idxnb ) )
1381 /* the first ck_info is ok otherwise it should be
1382 loaded without parsing */
1383 i_size = __AVI_ChooseSize( p_ck->i_size,
1384 p_info->p_index[p_info->i_idxposc].i_length);
1387 RIFF_DeleteChunk( p_input, p_ck );
1389 return( b_load ? __AVI_GetAndPutChunkInBuffer( p_input,
1392 p_info->i_idxposc ) : 1 );
1397 RIFF_DeleteChunk( p_input, p_ck );
1398 if( RIFF_NextChunk( p_input, p_avi_demux->p_movi ) != 0 )
1411 /* be sure that i_ck will be a valid index entry */
1412 static int AVI_SetStreamChunk( input_thread_t *p_input,
1413 AVIStreamInfo_t *p_info,
1417 p_info->i_idxposc = i_ck;
1418 p_info->i_idxposb = 0;
1420 if( i_ck < p_info->i_idxnb )
1426 p_info->i_idxposc = p_info->i_idxnb - 1;
1429 p_info->i_idxposc++;
1430 if( !__AVI_GetChunk( p_input, p_info, 0 ) )
1434 } while( p_info->i_idxposc < i_ck );
1441 /* XXX FIXME up to now, we assume that all chunk are one after one */
1442 static int AVI_SetStreamBytes( input_thread_t *p_input,
1443 AVIStreamInfo_t *p_info,
1446 if( ( p_info->i_idxnb > 0 )
1447 &&( i_byte < p_info->p_index[p_info->i_idxnb - 1].i_lengthtotal +
1448 p_info->p_index[p_info->i_idxnb - 1].i_length ) )
1450 /* index is valid to find the ck */
1451 /* uses dichototmie to be fast enougth */
1452 int i_idxposc = __MIN( p_info->i_idxposc, p_info->i_idxnb - 1 );
1453 int i_idxmax = p_info->i_idxnb;
1457 if( p_info->p_index[i_idxposc].i_lengthtotal > i_byte )
1459 i_idxmax = i_idxposc ;
1460 i_idxposc = ( i_idxmin + i_idxposc ) / 2 ;
1464 if( p_info->p_index[i_idxposc].i_lengthtotal +
1465 p_info->p_index[i_idxposc].i_length <= i_byte)
1467 i_idxmin = i_idxposc ;
1468 i_idxposc = (i_idxmax + i_idxposc ) / 2 ;
1472 p_info->i_idxposc = i_idxposc;
1473 p_info->i_idxposb = i_byte -
1474 p_info->p_index[i_idxposc].i_lengthtotal;
1483 p_info->i_idxposc = p_info->i_idxnb - 1;
1484 p_info->i_idxposb = 0;
1487 p_info->i_idxposc++;
1488 if( !__AVI_GetChunk( p_input, p_info, 0 ) )
1492 } while( p_info->p_index[p_info->i_idxposc].i_lengthtotal +
1493 p_info->p_index[p_info->i_idxposc].i_length <= i_byte );
1495 p_info->i_idxposb = i_byte -
1496 p_info->p_index[p_info->i_idxposc].i_lengthtotal;
1501 static pes_packet_t *AVI_ReadStreamChunkInPES( input_thread_t *p_input,
1502 AVIStreamInfo_t *p_info )
1505 if( p_info->i_idxposc > p_info->i_idxnb )
1510 /* we want chunk (p_info->i_idxposc,0) */
1511 p_info->i_idxposb = 0;
1512 if( !__AVI_GetChunk( p_input, p_info, 1) )
1514 msg_Err( p_input, "Got one chunk : failed" );
1517 p_info->i_idxposc++;
1518 return( AVI_PESBuffer_Get( p_info ) );
1521 static pes_packet_t *AVI_ReadStreamBytesInPES( input_thread_t *p_input,
1522 AVIStreamInfo_t *p_info,
1525 pes_packet_t *p_pes;
1526 data_packet_t *p_data;
1531 if( !( p_pes = input_NewPES( p_input->p_method_data ) ) )
1535 if( !( p_data = input_NewPacket( p_input->p_method_data, i_byte ) ) )
1537 input_DeletePES( p_input->p_method_data, p_pes );
1542 p_pes->p_last = p_data;
1543 p_pes->i_nb_data = 1;
1544 p_pes->i_pes_size = i_byte;
1548 if( !__AVI_GetChunk( p_input, p_info, 1) )
1550 msg_Err( p_input, "Got one chunk : failed" );
1552 input_DeletePES( p_input->p_method_data, p_pes );
1556 i_read = __MIN( p_info->p_pes_first->p_pes->i_pes_size -
1557 ( p_info->i_idxposb - p_info->p_pes_first->i_posb ),
1559 /* FIXME FIXME FIXME follow all data packet */
1560 memcpy( p_data->p_payload_start + i_count,
1561 p_info->p_pes_first->p_pes->p_first->p_payload_start +
1562 p_info->i_idxposb - p_info->p_pes_first->i_posb,
1565 AVI_PESBuffer_Drop( p_input->p_method_data, p_info );
1569 p_info->i_idxposb += i_read;
1570 if( p_info->p_index[p_info->i_idxposc].i_length <= p_info->i_idxposb )
1572 p_info->i_idxposb -= p_info->p_index[p_info->i_idxposc].i_length;
1573 p_info->i_idxposc++;
1581 /* try to realign after a seek */
1582 static int AVI_ReAlign( input_thread_t *p_input,
1583 AVIStreamInfo_t *p_info )
1588 demux_data_avi_file_t *p_avi_demux =
1589 (demux_data_avi_file_t*)p_input->p_demux_data;
1592 for( i = 0; i < p_avi_demux->i_streams; i++ )
1594 AVI_PESBuffer_Flush( p_input->p_method_data, p_avi_demux->pp_info[i] );
1597 TODO use input_ClockInit instead but need to be exported
1598 p_input->stream.p_selected_program->last_cr = 0;
1599 p_input->stream.p_selected_program->last_syscr = 0;
1600 p_input->stream.p_selected_program->cr_ref = 0;
1601 p_input->stream.p_selected_program->sysdate_ref = 0;
1602 p_input->stream.p_selected_program->delta_cr = 0;
1603 p_input->stream.p_selected_program->c_average_count = 0; */
1605 i_pos = AVI_TellAbsolute( p_input );
1607 p_info->i_idxposc--; /* in fact p_info->i_idxposc is for ck to be read */
1610 if( ( p_info->i_idxposc <= 0)
1611 ||( i_pos <= p_info->p_index[0].i_pos ) )
1613 /* before beginning of stream */
1614 return( p_info->header.i_samplesize ?
1615 AVI_SetStreamBytes( p_input, p_info, 0 ) :
1616 AVI_SetStreamChunk( p_input, p_info, 0 ) );
1619 b_after = ( i_pos >= p_info->p_index[p_info->i_idxposc].i_pos );
1620 /* now find in what chunk we are */
1621 while( ( i_pos < p_info->p_index[p_info->i_idxposc].i_pos )
1622 &&( p_info->i_idxposc > 0 ) )
1624 /* search before i_idxposc */
1626 if( !AVI_SetStreamChunk( p_input, p_info, p_info->i_idxposc - 1 ) )
1632 while( i_pos >= p_info->p_index[p_info->i_idxposc].i_pos +
1633 p_info->p_index[p_info->i_idxposc].i_length + 8 )
1635 /* search after i_idxposc */
1637 if( !AVI_SetStreamChunk( p_input, p_info, p_info->i_idxposc + 1 ) )
1643 /* search nearest key frame, only for video */
1644 if( p_info->i_cat == VIDEO_ES )
1648 while(!(p_info->p_index[p_info->i_idxposc].i_flags&AVIIF_KEYFRAME) )
1650 if( !AVI_SetStreamChunk( p_input, p_info,
1651 p_info->i_idxposc + 1 ) )
1659 while( ( p_info->i_idxposc > 0 ) &&
1660 (!(p_info->p_index[p_info->i_idxposc].i_flags&AVIIF_KEYFRAME)) )
1663 if( !AVI_SetStreamChunk( p_input, p_info,
1664 p_info->i_idxposc - 1 ) )
1675 /* make difference between audio and video pts as little as possible */
1676 static void AVI_SynchroReInit( input_thread_t *p_input )
1678 demux_data_avi_file_t *p_avi_demux =
1679 (demux_data_avi_file_t*)p_input->p_demux_data;
1681 #define p_info_video p_avi_demux->p_info_video
1682 #define p_info_audio p_avi_demux->p_info_audio
1683 if( ( !p_info_audio )||( !p_info_video ) )
1687 /* now resynch audio video video */
1688 /*don't care of AVIF_KEYFRAME */
1689 if( !p_info_audio->header.i_samplesize )
1691 AVI_SetStreamChunk( p_input,
1693 AVI_PTSToChunk( p_info_audio,
1694 AVI_GetPTS( p_info_video ) ) );
1698 AVI_SetStreamBytes( p_input,
1700 AVI_PTSToByte( p_info_audio,
1701 AVI_GetPTS( p_info_video ) ) );
1707 /*****************************************************************************
1708 * AVI_GetFrameInPES : get dpts length(µs) in pes from stream
1709 *****************************************************************************
1710 * Handle multiple pes, and set pts to the good value
1711 *****************************************************************************/
1712 static pes_packet_t *AVI_GetFrameInPES( input_thread_t *p_input,
1713 AVIStreamInfo_t *p_info,
1717 pes_packet_t *p_pes = NULL;
1718 pes_packet_t *p_pes_tmp = NULL;
1719 pes_packet_t *p_pes_first = NULL;
1727 if( !p_info->header.i_samplesize )
1729 int i_chunk = __MAX( AVI_PTSToChunk( p_info, i_dpts), 1 );
1731 for( i = 0; i < i_chunk; i++ )
1733 /* get pts while is valid */
1734 i_pts = AVI_GetPTS( p_info );
1736 p_pes_tmp = AVI_ReadStreamChunkInPES( p_input, p_info );
1740 return( p_pes_first );
1742 p_pes_tmp->i_pts = i_pts;
1745 p_pes_first = p_pes_tmp;
1749 p_pes->p_next = p_pes_tmp;
1753 return( p_pes_first );
1757 /* stream is byte based */
1758 int i_byte = AVI_PTSToByte( p_info, i_dpts);
1759 if( i_byte < 50 ) /* to avoid some problem with audio */
1763 i_pts = AVI_GetPTS( p_info ); /* ok even with broken index */
1764 p_pes = AVI_ReadStreamBytesInPES( p_input, p_info, i_byte);
1768 p_pes->i_pts = i_pts;
1773 /*****************************************************************************
1774 * AVI_DecodePES : send a pes to decoder
1775 *****************************************************************************
1776 * Handle multiple pes, and update pts to the good value
1777 *****************************************************************************/
1778 static inline void AVI_DecodePES( input_thread_t *p_input,
1779 AVIStreamInfo_t *p_info,
1780 pes_packet_t *p_pes )
1782 pes_packet_t *p_pes_next;
1783 /* input_decode want only one pes, but AVI_GetFrameInPES give
1784 multiple pes so send one by one */
1787 p_pes_next = p_pes->p_next;
1788 p_pes->p_next = NULL;
1789 p_pes->i_pts = input_ClockGetTS( p_input,
1790 p_input->stream.p_selected_program,
1791 p_pes->i_pts * 9/100);
1792 input_DecodePES( p_info->p_es->p_decoder_fifo, p_pes );
1798 /*****************************************************************************
1799 * AVIDemux_Seekable: reads and demuxes data packets for stream seekable
1800 *****************************************************************************
1801 * Called by AVIDemux, that make common work
1802 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
1803 *****************************************************************************/
1804 static int AVIDemux_Seekable( input_thread_t *p_input,
1805 AVIStreamInfo_t *p_info_master,
1806 AVIStreamInfo_t *p_info_slave )
1808 demux_data_avi_file_t *p_avi_demux =
1809 (demux_data_avi_file_t*)p_input->p_demux_data;
1811 pes_packet_t *p_pes_master;
1812 pes_packet_t *p_pes_slave;
1814 /* check for signal from interface */
1815 if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
1817 /* we can supposed that is a seek */
1818 /* first wait for empty buffer, arbitrary time */
1819 msleep( DEFAULT_PTS_DELAY );
1820 /* then try to realign in stream */
1821 if( !AVI_ReAlign( p_input, p_info_master ) )
1823 return( 0 ); /* assume EOF */
1825 AVI_SynchroReInit( p_input );
1828 /* take care of newly selected audio ES */
1829 if( p_info_master->b_selected )
1831 p_info_master->b_selected = 0;
1832 AVI_SynchroReInit( p_input );
1834 if( ( p_info_slave )&&( p_info_slave->b_selected ) )
1836 p_info_slave->b_selected = 0;
1837 AVI_SynchroReInit( p_input );
1840 /* wait for the good time */
1841 input_ClockManageRef( p_input,
1842 p_input->stream.p_selected_program,
1843 p_avi_demux->i_pcr /*- DEFAULT_PTS_DELAY / 2 */);
1844 /* calculate pcr, time when we must read the next data */
1845 /* 9/100 kludge ->need to convert to 1/1000000 clock unit to 1/90000 */
1848 p_avi_demux->i_pcr = __MIN( AVI_GetPTS( p_info_master ),
1849 AVI_GetPTS( p_info_slave ) ) * 9/100;
1853 p_avi_demux->i_pcr = AVI_GetPTS( p_info_master ) * 9/100;
1856 /* get video and audio frames */
1857 p_pes_master = AVI_GetFrameInPES( p_input,
1859 100000 ); /* 100 ms */
1860 AVI_DecodePES( p_input,
1867 p_pes_slave = AVI_GetFrameInPES( p_input,
1869 AVI_GetPTS( p_info_master ) -
1870 AVI_GetPTS( p_info_slave) );
1871 AVI_DecodePES( p_input,
1878 return( p_pes_master ? 1 : 0 );
1882 /*****************************************************************************
1883 * AVIDemux_NotSeekable: reads and demuxes data packets for stream seekable
1884 *****************************************************************************
1885 * Called by AVIDemux, that makes common work
1886 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
1887 *****************************************************************************/
1889 /* 0 if can be load/updated, 1 if skip, 2 if descend into, 3 if exit, 4 if error and need recover */
1890 static int __AVIDemux_ChunkAction( int i_streams_max,
1896 AVI_ParseStreamHeader( p_ck->i_id, &i_stream, &i_type );
1897 if( i_stream < i_streams_max )
1899 return( 0 ); /* read and/or update stream info */
1902 if( i_stream <= 99 )
1904 /* should not happen but ... */
1908 /* now we know that it's not a stream */
1910 switch( p_ck->i_id )
1912 case( FOURCC_JUNK ):
1914 case( FOURCC_idx1 ):
1916 case( FOURCC_LIST ):
1917 if( p_ck->i_type == FOURCC_rec )
1930 if( ( p_ck->i_id & 0xFFFF ) == VLC_TWOCC( 'i','x' ) )
1938 static int AVI_NotSeekableRecover( input_thread_t *p_input )
1942 int i_number, i_type;
1943 data_packet_t *p_pack;
1947 if( input_Peek( p_input, &p_id, 4 ) < 4 )
1949 return( 0 ); /* Failed */
1951 i_id = GetDWLE( p_id );
1954 case( FOURCC_idx1 ):
1955 case( FOURCC_JUNK ):
1956 case( FOURCC_LIST ):
1959 AVI_ParseStreamHeader( i_id, &i_number, &i_type );
1960 if( i_number <= 99 )
1976 /* Read 1 byte VERY unoptimised */
1977 if( input_SplitBuffer( p_input, &p_pack, 1) < 1 )
1981 input_DeletePacket( p_input->p_method_data, p_pack);
1986 static int AVIDemux_NotSeekable( input_thread_t *p_input,
1987 AVIStreamInfo_t *p_info_master,
1988 AVIStreamInfo_t *p_info_slave )
1990 demux_data_avi_file_t *p_avi_demux =
1991 (demux_data_avi_file_t*)p_input->p_demux_data;
1997 pes_packet_t *p_pes;
2000 i_filepos = AVI_TellAbsolute( p_input );
2001 p_input->pf_seek( p_input, i_filepos );
2002 input_AccessReinit( p_input );
2005 #define p_info p_avi_demux->pp_info[i_stream]
2007 /* The managment is very basic, we will read packets, caclulate pts
2008 and send it to decoder, synchro made on video, and audio is very less
2011 /* wait the good time */
2012 input_ClockManageRef( p_input,
2013 p_input->stream.p_selected_program,
2014 p_avi_demux->i_pcr /*- DEFAULT_PTS_DELAY / 2 */);
2015 /* TODO be smart, seeing if we can wait for min( audio, video )
2016 or there is a too big deep */
2019 p_avi_demux->i_pcr = AVI_GetPTS( p_info_master ) * 9/100;
2023 p_avi_demux->i_pcr = __MIN( AVI_GetPTS( p_info_master ),
2024 AVI_GetPTS( p_info_slave ) ) * 9/100;
2025 p_avi_demux->i_pcr = AVI_GetPTS( p_info_master ) * 9/100;
2028 for( i_loop = 0; i_loop < 10; i_loop++ )
2032 /* first find a ck for master or slave */
2036 if( !(p_ck = RIFF_ReadChunk( p_input ) ) )
2038 msg_Err( p_input, "Badd" );
2039 return( 0 ); /* assume EOF */
2041 //msg_Err( p_input,"Looking ck: %4.4s %d",&p_ck->i_id, p_ck->i_size );
2043 switch( __AVIDemux_ChunkAction( p_avi_demux->i_streams, p_ck ) )
2045 case( 0 ): /* load it if possible */
2048 case( 1 ): /* skip it */
2049 RIFF_DeleteChunk( p_input, p_ck );
2050 if( RIFF_NextChunk( p_input, p_avi_demux->p_movi ) != 0 )
2056 case( 2 ): /* descend into */
2057 RIFF_DeleteChunk( p_input, p_ck );
2058 RIFF_DescendChunk( p_input );
2061 case( 3 ): /* exit */
2062 RIFF_DeleteChunk( p_input, p_ck );
2064 case( 4 ): /* Error */
2065 RIFF_DeleteChunk( p_input, p_ck );
2066 msg_Warn( p_input, "unknown chunk id 0x%8.8x, trying to recover", p_ck->i_id );
2067 if( !AVI_NotSeekableRecover( p_input ) )
2069 msg_Err( p_input, "cannot recover, dying" );
2074 msg_Warn( p_input, "recovered sucessfully" );
2082 AVI_ParseStreamHeader( p_ck->i_id, &i_stream, &i_type );
2083 /* now check if we really have to load it */
2084 if( ( p_info != p_info_master )&&( p_info != p_info_slave ) )
2090 if( p_info == p_info_master )
2097 i_dpts = AVI_GetPTS( p_info_slave ) -
2098 AVI_GetPTS( p_info_master );
2099 if( i_dpts < 0 ) {i_dpts = - i_dpts; }
2100 if( i_dpts < 600000 )
2112 /* now do we can load this chunk ? */
2116 if( __AVI_GetDataInPES( p_input, &p_pes, p_ck->i_size + 8, 1) != p_ck->i_size + 8)
2120 p_pes->p_first->p_payload_start += 8;
2121 p_pes->i_pes_size -= 8;
2123 p_pes->i_pts = AVI_GetPTS( p_info );
2124 AVI_DecodePES( p_input, p_info, p_pes );
2129 if( RIFF_NextChunk( p_input, p_avi_demux->p_movi ) != 0 )
2131 RIFF_DeleteChunk( p_input, p_ck );
2136 /* finaly update stream information */
2137 if( p_info->header.i_samplesize )
2139 p_info->i_idxposb += p_ck->i_size;
2143 p_info->i_idxposc++;
2146 RIFF_DeleteChunk( p_input, p_ck );
2152 /*****************************************************************************
2153 * AVIDemux: reads and demuxes data packets
2154 *****************************************************************************
2155 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
2156 * TODO add support for unstreable file, just read a chunk and send it
2157 * to the right decoder, very easy
2158 *****************************************************************************/
2160 static int AVIDemux( input_thread_t *p_input )
2163 AVIStreamInfo_t *p_info_master;
2164 AVIStreamInfo_t *p_info_slave;
2166 demux_data_avi_file_t *p_avi_demux =
2167 (demux_data_avi_file_t*)p_input->p_demux_data;
2169 /* search new video and audio stream selected
2170 if current have been unselected*/
2171 if( ( !p_avi_demux->p_info_video )
2172 || ( !p_avi_demux->p_info_video->p_es->p_decoder_fifo ) )
2174 p_avi_demux->p_info_video = NULL;
2175 for( i = 0; i < p_avi_demux->i_streams; i++ )
2177 if( ( p_avi_demux->pp_info[i]->i_cat == VIDEO_ES )
2178 &&( p_avi_demux->pp_info[i]->p_es->p_decoder_fifo ) )
2180 p_avi_demux->p_info_video = p_avi_demux->pp_info[i];
2181 p_avi_demux->p_info_video->b_selected = 1;
2186 if( ( !p_avi_demux->p_info_audio )
2187 ||( !p_avi_demux->p_info_audio->p_es->p_decoder_fifo ) )
2189 p_avi_demux->p_info_audio = NULL;
2190 for( i = 0; i < p_avi_demux->i_streams; i++ )
2192 if( ( p_avi_demux->pp_info[i]->i_cat == AUDIO_ES )
2193 &&( p_avi_demux->pp_info[i]->p_es->p_decoder_fifo ) )
2195 p_avi_demux->p_info_audio = p_avi_demux->pp_info[i];
2196 p_avi_demux->p_info_audio->b_selected = 1;
2201 /* by default video is master for resync audio (after a seek .. ) */
2202 if( p_avi_demux->p_info_video )
2204 p_info_master = p_avi_demux->p_info_video;
2205 p_info_slave = p_avi_demux->p_info_audio;
2209 p_info_master = p_avi_demux->p_info_audio;
2210 p_info_slave = NULL;
2213 if( !p_info_master )
2215 msg_Err( p_input, "no stream selected" );
2219 /* manage rate, if not default: skeep audio */
2220 vlc_mutex_lock( &p_input->stream.stream_lock );
2221 if( p_input->stream.control.i_rate != p_avi_demux->i_rate )
2223 if( p_avi_demux->p_info_audio)
2225 p_avi_demux->p_info_audio->b_selected = 1;
2227 p_avi_demux->i_rate = p_input->stream.control.i_rate;
2229 vlc_mutex_unlock( &p_input->stream.stream_lock );
2230 p_avi_demux->i_rate = DEFAULT_RATE;
2231 if( p_avi_demux->i_rate != DEFAULT_RATE )
2233 p_info_slave = NULL;
2236 if( p_avi_demux->b_seekable )
2238 return( AVIDemux_Seekable( p_input,
2244 return( AVIDemux_NotSeekable( p_input,