1 /*****************************************************************************
2 * avi.c : AVI file Stream input module for vlc
3 *****************************************************************************
4 * Copyright (C) 2001 VideoLAN
5 * $Id: avi.c,v 1.1 2002/08/04 17:23:42 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 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 )
63 i = (*p_buff) + ( *(p_buff + 1) <<8 );
66 static u32 GetDWLE( byte_t *p_buff )
69 i = (*p_buff) + ( *(p_buff + 1) <<8 ) +
70 ( *(p_buff + 2) <<16 ) + ( *(p_buff + 3) <<24 );
73 static u32 GetDWBE( byte_t *p_buff )
76 i = ((*p_buff)<<24) + ( *(p_buff + 1) <<16 ) +
77 ( *(p_buff + 2) <<8 ) + ( *(p_buff + 3) );
80 static inline off_t __EVEN( off_t i )
82 return( (i & 1) ? i+1 : i );
86 /*****************************************************************************
87 * Functions for parsing the headers in an avi file
88 *****************************************************************************/
89 static void AVI_Parse_avih( MainAVIHeader_t *p_avih, byte_t *p_buff )
91 p_avih->i_microsecperframe = GetDWLE( p_buff );
92 p_avih->i_maxbytespersec = GetDWLE( p_buff + 4);
93 p_avih->i_reserved1 = GetDWLE( p_buff + 8);
94 p_avih->i_flags = GetDWLE( p_buff + 12);
95 p_avih->i_totalframes = GetDWLE( p_buff + 16);
96 p_avih->i_initialframes = GetDWLE( p_buff + 20);
97 p_avih->i_streams = GetDWLE( p_buff + 24);
98 p_avih->i_suggestedbuffersize = GetDWLE( p_buff + 28);
99 p_avih->i_width = GetDWLE( p_buff + 32 );
100 p_avih->i_height = GetDWLE( p_buff + 36 );
101 p_avih->i_scale = GetDWLE( p_buff + 40 );
102 p_avih->i_rate = GetDWLE( p_buff + 44 );
103 p_avih->i_start = GetDWLE( p_buff + 48);
104 p_avih->i_length = GetDWLE( p_buff + 52);
106 static void AVI_Parse_Header( AVIStreamHeader_t *p_strh, byte_t *p_buff )
108 p_strh->i_type = GetDWLE( p_buff );
109 p_strh->i_handler = GetDWLE( p_buff + 4 );
110 p_strh->i_flags = GetDWLE( p_buff + 8 );
111 p_strh->i_reserved1 = GetDWLE( p_buff + 12);
112 p_strh->i_initialframes = GetDWLE( p_buff + 16);
113 p_strh->i_scale = GetDWLE( p_buff + 20);
114 p_strh->i_rate = GetDWLE( p_buff + 24);
115 p_strh->i_start = GetDWLE( p_buff + 28);
116 p_strh->i_length = GetDWLE( p_buff + 32);
117 p_strh->i_suggestedbuffersize = GetDWLE( p_buff + 36);
118 p_strh->i_quality = GetDWLE( p_buff + 40);
119 p_strh->i_samplesize = GetDWLE( p_buff + 44);
121 static void AVI_Parse_BitMapInfoHeader( bitmapinfoheader_t *h, byte_t *p_data )
123 h->i_size = GetDWLE( p_data );
124 h->i_width = GetDWLE( p_data + 4 );
125 h->i_height = GetDWLE( p_data + 8 );
126 h->i_planes = GetWLE( p_data + 12 );
127 h->i_bitcount = GetWLE( p_data + 14 );
128 h->i_compression = GetDWLE( p_data + 16 );
129 h->i_sizeimage = GetDWLE( p_data + 20 );
130 h->i_xpelspermeter = GetDWLE( p_data + 24 );
131 h->i_ypelspermeter = GetDWLE( p_data + 28 );
132 h->i_clrused = GetDWLE( p_data + 32 );
133 h->i_clrimportant = GetDWLE( p_data + 36 );
135 static void AVI_Parse_WaveFormatEx( waveformatex_t *h, byte_t *p_data )
137 h->i_formattag = GetWLE( p_data );
138 h->i_channels = GetWLE( p_data + 2 );
139 h->i_samplespersec = GetDWLE( p_data + 4 );
140 h->i_avgbytespersec= GetDWLE( p_data + 8 );
141 h->i_blockalign = GetWLE( p_data + 12 );
142 h->i_bitspersample = GetWLE( p_data + 14 );
143 h->i_size = GetWLE( p_data + 16 );
146 static inline int AVI_GetESTypeFromTwoCC( u16 i_type )
156 return( UNKNOWN_ES );
160 static vlc_fourcc_t AVI_AudioGetType( u32 i_type )
164 /* case( WAVE_FORMAT_PCM ):
165 return VLC_FOURCC('l','p','c','m'); */
166 case( WAVE_FORMAT_A52 ):
167 return VLC_FOURCC('a','5','2',' ');
168 case( WAVE_FORMAT_MPEG):
169 case( WAVE_FORMAT_MPEGLAYER3):
170 return VLC_FOURCC('m','p','g','a'); /* for mpeg2 layer 1 2 ou 3 */
176 /* Test if it seems that it's a key frame */
177 static int AVI_GetKeyFlag( vlc_fourcc_t i_fourcc, u8 *p_byte )
185 if( GetDWBE( p_byte ) != 0x00000100 )
186 /* startcode perhaps swapped, I haven't tested */
188 /* it's seems it's not an msmpegv1 stream
189 but perhaps I'm wrong so return yes */
190 return( AVIIF_KEYFRAME );
194 return( (*(p_byte+4))&0x06 ? 0 : AVIIF_KEYFRAME);
214 return( (*p_byte)&0xC0 ? 0 : AVIIF_KEYFRAME );
227 if( GetDWBE( p_byte ) != 0x000001b6 )
229 /* not true , need to find the first VOP header
231 return( AVIIF_KEYFRAME );
235 return( (*(p_byte+4))&0xC0 ? 0 : AVIIF_KEYFRAME );
238 /* I can't do it, so said yes */
239 return( AVIIF_KEYFRAME );
243 /*****************************************************************************
244 * Data and functions to manipulate pes buffer
245 *****************************************************************************/
246 #define BUFFER_MAXTOTALSIZE 512*1024 /* 1/2 Mo */
247 #define BUFFER_MAXSPESSIZE 1024*200
248 static int AVI_PESBuffer_IsFull( AVIStreamInfo_t *p_info )
250 return( p_info->i_pes_totalsize > BUFFER_MAXTOTALSIZE ? 1 : 0);
252 static void AVI_PESBuffer_Add( input_buffers_t *p_method_data,
253 AVIStreamInfo_t *p_info,
258 AVIESBuffer_t *p_buffer_pes;
260 if( p_info->i_pes_totalsize > BUFFER_MAXTOTALSIZE )
262 input_DeletePES( p_method_data, p_pes );
266 if( !( p_buffer_pes = malloc( sizeof( AVIESBuffer_t ) ) ) )
268 input_DeletePES( p_method_data, p_pes );
271 p_buffer_pes->p_next = NULL;
272 p_buffer_pes->p_pes = p_pes;
273 p_buffer_pes->i_posc = i_posc;
274 p_buffer_pes->i_posb = i_posb;
276 if( p_info->p_pes_last )
278 p_info->p_pes_last->p_next = p_buffer_pes;
280 p_info->p_pes_last = p_buffer_pes;
281 if( !p_info->p_pes_first )
283 p_info->p_pes_first = p_buffer_pes;
285 p_info->i_pes_count++;
286 p_info->i_pes_totalsize += p_pes->i_pes_size;
288 static pes_packet_t *AVI_PESBuffer_Get( AVIStreamInfo_t *p_info )
290 AVIESBuffer_t *p_buffer_pes;
292 if( p_info->p_pes_first )
294 p_buffer_pes = p_info->p_pes_first;
295 p_info->p_pes_first = p_buffer_pes->p_next;
296 if( !p_info->p_pes_first )
298 p_info->p_pes_last = NULL;
300 p_pes = p_buffer_pes->p_pes;
302 free( p_buffer_pes );
303 p_info->i_pes_count--;
304 p_info->i_pes_totalsize -= p_pes->i_pes_size;
312 static int AVI_PESBuffer_Drop( input_buffers_t *p_method_data,
313 AVIStreamInfo_t *p_info )
315 pes_packet_t *p_pes = AVI_PESBuffer_Get( p_info );
318 input_DeletePES( p_method_data, p_pes );
326 static void AVI_PESBuffer_Flush( input_buffers_t *p_method_data,
327 AVIStreamInfo_t *p_info )
329 while( p_info->p_pes_first )
331 AVI_PESBuffer_Drop( p_method_data, p_info );
335 static void AVI_ParseStreamHeader( u32 i_id, int *i_number, int *i_type )
339 c1 = ( i_id ) & 0xFF;
340 c2 = ( i_id >> 8 ) & 0xFF;
342 if( c1 < '0' || c1 > '9' || c2 < '0' || c2 > '9' )
344 *i_number = 100; /* > max stream number */
349 *i_number = (c1 - '0') * 10 + (c2 - '0' );
350 *i_type = ( i_id >> 16 ) & 0xFFFF;
354 /* Function to manipulate stream easily */
355 static off_t AVI_TellAbsolute( input_thread_t *p_input )
358 vlc_mutex_lock( &p_input->stream.stream_lock );
359 i_pos= p_input->stream.p_selected_area->i_tell -
360 ( p_input->p_last_data - p_input->p_current_data );
361 vlc_mutex_unlock( &p_input->stream.stream_lock );
366 static int AVI_SeekAbsolute( input_thread_t *p_input,
370 /* FIXME add support for not seekable stream */
372 i_filepos = AVI_TellAbsolute( p_input );
373 if( i_pos != i_filepos )
375 // msg_Err( p_input, "Seek --> delta %d", i_pos - i_filepos );
376 p_input->pf_seek( p_input, i_pos );
377 input_AccessReinit( p_input );
383 static void __AVI_AddEntryIndex( AVIStreamInfo_t *p_info,
384 AVIIndexEntry_t *p_index)
386 AVIIndexEntry_t *p_tmp;
387 if( p_info->p_index == NULL )
389 p_info->i_idxmax = 16384;
391 p_info->p_index = calloc( p_info->i_idxmax,
392 sizeof( AVIIndexEntry_t ) );
393 if( p_info->p_index == NULL ) {return;}
395 if( p_info->i_idxnb >= p_info->i_idxmax )
397 p_info->i_idxmax += 16384;
398 p_tmp = realloc( (void*)p_info->p_index,
400 sizeof( AVIIndexEntry_t ) );
403 p_info->i_idxmax -= 16384;
406 p_info->p_index = p_tmp;
408 /* calculate cumulate length */
409 if( p_info->i_idxnb > 0 )
411 p_index->i_lengthtotal = p_info->p_index[p_info->i_idxnb-1].i_length +
412 p_info->p_index[p_info->i_idxnb-1].i_lengthtotal;
416 p_index->i_lengthtotal = 0;
419 p_info->p_index[p_info->i_idxnb] = *p_index;
423 static void __AVI_GetIndex( input_thread_t *p_input )
425 AVIIndexEntry_t index;
432 int i_totalentry = 0;
433 demux_data_avi_file_t *p_avi_demux =
434 (demux_data_avi_file_t*)p_input->p_demux_data ;
436 if( RIFF_FindAndGotoDataChunk( p_input,
441 msg_Warn( p_input, "cannot find index" );
442 RIFF_GoToChunk( p_input, p_avi_demux->p_hdrl );
445 p_avi_demux->p_idx1 = p_idx1;
446 msg_Dbg( p_input, "loading index" );
449 i_read = __MIN( 16*1024, p_idx1->i_size - i_totalentry *16);
450 if( ((i_read = input_Peek( p_input, &p_buff, i_read )) < 16 )
451 ||( i_totalentry *16 >= p_idx1->i_size ) )
453 msg_Dbg( p_input, "read %d idx entries", i_totalentry );
457 for( i = 0; i < i_read; i++ )
459 byte_t *p_peek = p_buff + i * 16;
461 index.i_id = GetDWLE( p_peek );
462 index.i_flags = GetDWLE( p_peek+4)&(~AVIIF_FIXKEYFRAME);
463 index.i_pos = GetDWLE( p_peek+8);
464 index.i_length = GetDWLE(p_peek+12);
465 AVI_ParseStreamHeader( index.i_id, &i_number, &i_type );
467 if( ( i_number < p_avi_demux->i_streams )
468 &&(p_avi_demux->pp_info[i_number]->i_cat ==
469 AVI_GetESTypeFromTwoCC( i_type )))
471 __AVI_AddEntryIndex( p_avi_demux->pp_info[i_number],
475 __RIFF_SkipBytes( p_input, 16 * i_read );
480 /* XXX call after get p_movi */
481 static void __AVI_UpdateIndexOffset( input_thread_t *p_input )
484 int b_start = 1;/* if index pos is based on start of file or not (p_movi) */
485 demux_data_avi_file_t *p_avi_demux =
486 (demux_data_avi_file_t*)p_input->p_demux_data;
488 /* FIXME some work to do :
489 * test in the file if it's true, if not do a RIFF_Find...
491 #define p_info p_avi_demux->pp_info[i_stream]
492 for( i_stream = 0; i_stream < p_avi_demux->i_streams; i_stream++ )
494 if( ( p_info->p_index )
495 && ( p_info->p_index[0].i_pos < p_avi_demux->p_movi->i_pos + 8 ))
503 for( i_stream = 0; i_stream < p_avi_demux->i_streams; i_stream++ )
506 if( p_info->p_index )
508 for( i = 0; i < p_info->i_idxnb; i++ )
510 p_info->p_index[i].i_pos += p_avi_demux->p_movi->i_pos + 8;
518 /*****************************************************************************
519 * AVIEnd: frees unused data
520 *****************************************************************************/
521 static void __AVIEnd ( vlc_object_t * p_this )
523 input_thread_t * p_input = (input_thread_t *)p_this;
525 demux_data_avi_file_t *p_avi_demux;
526 p_avi_demux = (demux_data_avi_file_t*)p_input->p_demux_data ;
528 if( p_avi_demux->p_riff )
529 RIFF_DeleteChunk( p_input, p_avi_demux->p_riff );
530 if( p_avi_demux->p_hdrl )
531 RIFF_DeleteChunk( p_input, p_avi_demux->p_hdrl );
532 if( p_avi_demux->p_movi )
533 RIFF_DeleteChunk( p_input, p_avi_demux->p_movi );
534 if( p_avi_demux->p_idx1 )
535 RIFF_DeleteChunk( p_input, p_avi_demux->p_idx1 );
536 if( p_avi_demux->pp_info )
538 for( i = 0; i < p_avi_demux->i_streams; i++ )
540 if( p_avi_demux->pp_info[i] )
542 if( p_avi_demux->pp_info[i]->p_index )
544 free( p_avi_demux->pp_info[i]->p_index );
545 AVI_PESBuffer_Flush( p_input->p_method_data,
546 p_avi_demux->pp_info[i] );
548 free( p_avi_demux->pp_info[i] );
551 free( p_avi_demux->pp_info );
555 /*****************************************************************************
556 * AVIInit: check file and initializes AVI structures
557 *****************************************************************************/
558 static int AVIInit( vlc_object_t * p_this )
560 input_thread_t * p_input = (input_thread_t *)p_this;
561 riffchunk_t *p_riff,*p_hdrl,*p_movi;
563 riffchunk_t *p_strl,*p_strh,*p_strf;
564 demux_data_avi_file_t *p_avi_demux;
565 es_descriptor_t *p_es = NULL; /* for not warning */
568 p_input->pf_demux = AVIDemux;
570 if( !( p_input->p_demux_data =
571 p_avi_demux = malloc( sizeof(demux_data_avi_file_t) ) ) )
573 msg_Err( p_input, "out of memory" );
576 memset( p_avi_demux, 0, sizeof( demux_data_avi_file_t ) );
577 p_avi_demux->i_rate = DEFAULT_RATE;
578 p_avi_demux->b_seekable = ( ( p_input->stream.b_seekable )
579 &&( p_input->stream.i_method == INPUT_METHOD_FILE ) );
581 /* Initialize access plug-in structures. */
582 if( p_input->i_mtu == 0 )
585 p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
588 if( RIFF_TestFileHeader( p_input, &p_riff, FOURCC_AVI ) != 0 )
591 msg_Warn( p_input, "RIFF-AVI module discarded" );
594 p_avi_demux->p_riff = p_riff;
596 if ( RIFF_DescendChunk(p_input) != 0 )
599 msg_Err( p_input, "cannot look for subchunk" );
603 /* it's a riff-avi file, so search for LIST-hdrl */
604 if( RIFF_FindListChunk(p_input ,&p_hdrl,p_riff, FOURCC_hdrl) != 0 )
607 msg_Err( p_input, "cannot find \"LIST-hdrl\"" );
610 p_avi_demux->p_hdrl = p_hdrl;
612 if( RIFF_DescendChunk(p_input) != 0 )
615 msg_Err( p_input, "cannot look for subchunk" );
618 /* in LIST-hdrl search avih */
619 if( RIFF_FindAndLoadChunk( p_input, p_hdrl,
620 &p_avih, FOURCC_avih ) != 0 )
623 msg_Err( p_input, "cannot find \"avih\" chunk" );
626 AVI_Parse_avih( &p_avi_demux->avih, p_avih->p_data->p_payload_start );
627 RIFF_DeleteChunk( p_input, p_avih );
629 if( p_avi_demux->avih.i_streams == 0 )
630 /* no stream found, perhaps it would be cool to find it */
633 msg_Err( p_input, "no stream defined!" );
637 /* create one program */
638 vlc_mutex_lock( &p_input->stream.stream_lock );
639 if( input_InitStream( p_input, 0 ) == -1)
641 vlc_mutex_unlock( &p_input->stream.stream_lock );
643 msg_Err( p_input, "cannot init stream" );
646 if( input_AddProgram( p_input, 0, 0) == NULL )
648 vlc_mutex_unlock( &p_input->stream.stream_lock );
650 msg_Err( p_input, "cannot add program" );
653 p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
654 p_input->stream.i_mux_rate = p_avi_demux->avih.i_maxbytespersec / 50;
655 vlc_mutex_unlock( &p_input->stream.stream_lock );
657 /* now read info on each stream and create ES */
658 p_avi_demux->i_streams = p_avi_demux->avih.i_streams;
660 p_avi_demux->pp_info = calloc( p_avi_demux->i_streams,
661 sizeof( AVIStreamInfo_t* ) );
662 memset( p_avi_demux->pp_info,
664 sizeof( AVIStreamInfo_t* ) * p_avi_demux->i_streams );
666 for( i = 0 ; i < p_avi_demux->i_streams; i++ )
668 #define p_info p_avi_demux->pp_info[i]
669 p_info = malloc( sizeof(AVIStreamInfo_t ) );
670 memset( p_info, 0, sizeof( AVIStreamInfo_t ) );
672 if( ( RIFF_FindListChunk(p_input,
673 &p_strl,p_hdrl, FOURCC_strl) != 0 )
674 ||( RIFF_DescendChunk(p_input) != 0 ))
677 msg_Err( p_input, "cannot find \"LIST-strl\"" );
681 /* in LIST-strl search strh */
682 if( RIFF_FindAndLoadChunk( p_input, p_hdrl,
683 &p_strh, FOURCC_strh ) != 0 )
685 RIFF_DeleteChunk( p_input, p_strl );
687 msg_Err( p_input, "cannot find \"strh\"" );
690 AVI_Parse_Header( &p_info->header,
691 p_strh->p_data->p_payload_start);
692 RIFF_DeleteChunk( p_input, p_strh );
694 /* in LIST-strl search strf */
695 if( RIFF_FindAndLoadChunk( p_input, p_hdrl,
696 &p_strf, FOURCC_strf ) != 0 )
698 RIFF_DeleteChunk( p_input, p_strl );
700 msg_Err( p_input, "cannot find \"strf\"" );
703 /* we don't get strd, it's useless for divx,opendivx,mepgaudio */
704 if( RIFF_AscendChunk(p_input, p_strl) != 0 )
706 RIFF_DeleteChunk( p_input, p_strf );
707 RIFF_DeleteChunk( p_input, p_strl );
709 msg_Err( p_input, "cannot go out (\"strl\")" );
714 vlc_mutex_lock( &p_input->stream.stream_lock );
715 p_es = input_AddES( p_input,
716 p_input->stream.p_selected_program, 1+i,
718 vlc_mutex_unlock( &p_input->stream.stream_lock );
719 p_es->i_stream_id =i; /* XXX: i don't use it */
721 switch( p_info->header.i_type )
724 p_es->i_cat = AUDIO_ES;
725 AVI_Parse_WaveFormatEx( &p_info->audio_format,
726 p_strf->p_data->p_payload_start );
727 p_es->i_fourcc = AVI_AudioGetType(
728 p_info->audio_format.i_formattag );
732 p_es->i_cat = VIDEO_ES;
733 AVI_Parse_BitMapInfoHeader( &p_info->video_format,
734 p_strf->p_data->p_payload_start );
736 /* XXX quick hack for playing ffmpeg video, I don't know
737 who is doing something wrong */
738 p_info->header.i_samplesize = 0;
739 p_es->i_fourcc = p_info->video_format.i_compression;
742 msg_Err( p_input, "unknown stream(%d) type", i );
743 p_es->i_cat = UNKNOWN_ES;
747 p_info->i_cat = p_es->i_cat;
748 /* We copy strf for decoder in p_es->p_demux_data */
749 memcpy( p_es->p_demux_data,
750 p_strf->p_data->p_payload_start,
752 RIFF_DeleteChunk( p_input, p_strf );
753 RIFF_DeleteChunk( p_input, p_strl );
759 /* go out of p_hdrl */
760 if( RIFF_AscendChunk(p_input, p_hdrl) != 0)
763 msg_Err( p_input, "cannot go out (\"hdrl\")" );
767 /* go to movi chunk to get it*/
768 if( RIFF_FindListChunk(p_input ,&p_movi,p_riff, FOURCC_movi) != 0 )
770 msg_Err( p_input, "cannot find \"LIST-movi\"" );
774 p_avi_demux->p_movi = p_movi;
776 /* get index XXX need to have p_movi */
777 if( p_avi_demux->b_seekable )
780 __AVI_GetIndex( p_input );
781 /* try to get i_idxoffset for each stream */
782 __AVI_UpdateIndexOffset( p_input );
783 /* to make sure to go the begining unless demux will see a seek */
784 RIFF_GoToChunk( p_input, p_avi_demux->p_movi );
789 msg_Warn( p_input, "no index!" );
792 if( RIFF_DescendChunk( p_input ) != 0 )
795 msg_Err( p_input, "cannot go in (\"movi\")" );
799 /* print informations on streams */
800 msg_Dbg( p_input, "AVIH: %d stream, flags %s%s%s%s ",
801 p_avi_demux->i_streams,
802 p_avi_demux->avih.i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
803 p_avi_demux->avih.i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",
804 p_avi_demux->avih.i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
805 p_avi_demux->avih.i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"" );
807 for( i = 0; i < p_avi_demux->i_streams; i++ )
809 #define p_info p_avi_demux->pp_info[i]
810 switch( p_info->p_es->i_cat )
814 msg_Dbg( p_input, "video(%4.4s) %dx%d %dbpp %ffps",
815 (char*)&p_info->video_format.i_compression,
816 p_info->video_format.i_width,
817 p_info->video_format.i_height,
818 p_info->video_format.i_bitcount,
819 (float)p_info->header.i_rate /
820 (float)p_info->header.i_scale );
821 if( (p_avi_demux->p_info_video == NULL) )
823 p_avi_demux->p_info_video = p_info;
824 /* TODO add test to see if a decoder has been found */
825 vlc_mutex_lock( &p_input->stream.stream_lock );
826 input_SelectES( p_input, p_info->p_es );
827 vlc_mutex_unlock( &p_input->stream.stream_lock );
832 msg_Dbg( p_input, "audio(0x%x) %d channels %dHz %dbits",
833 p_info->audio_format.i_formattag,
834 p_info->audio_format.i_channels,
835 p_info->audio_format.i_samplespersec,
836 p_info->audio_format.i_bitspersample );
837 if( (p_avi_demux->p_info_audio == NULL) )
839 p_avi_demux->p_info_audio = p_info;
840 vlc_mutex_lock( &p_input->stream.stream_lock );
841 input_SelectES( p_input, p_info->p_es );
842 vlc_mutex_unlock( &p_input->stream.stream_lock );
852 /* we select the first audio and video ES */
853 vlc_mutex_lock( &p_input->stream.stream_lock );
854 if( !p_avi_demux->p_info_video )
856 msg_Warn( p_input, "no video stream found" );
858 if( !p_avi_demux->p_info_audio )
860 msg_Warn( p_input, "no audio stream found!" );
862 p_input->stream.p_selected_program->b_is_ok = 1;
863 vlc_mutex_unlock( &p_input->stream.stream_lock );
873 /*****************************************************************************
874 * Function to convert pts to chunk or byte
875 *****************************************************************************/
877 static inline mtime_t AVI_PTSToChunk( AVIStreamInfo_t *p_info,
880 return( (mtime_t)((s64)i_pts *
881 (s64)p_info->header.i_rate /
882 (s64)p_info->header.i_scale /
885 static inline mtime_t AVI_PTSToByte( AVIStreamInfo_t *p_info,
888 return( (mtime_t)((s64)i_pts *
889 (s64)p_info->header.i_samplesize *
890 (s64)p_info->header.i_rate /
891 (s64)p_info->header.i_scale /
895 static mtime_t AVI_GetPTS( AVIStreamInfo_t *p_info )
898 if( p_info->header.i_samplesize )
900 /* we need a valid entry we will emulate one */
902 if( p_info->i_idxposc == p_info->i_idxnb )
904 if( p_info->i_idxposc )
906 /* use the last entry */
907 i_len = p_info->p_index[p_info->i_idxnb - 1].i_lengthtotal
908 + p_info->p_index[p_info->i_idxnb - 1].i_length
909 + p_info->i_idxposb; /* should be 0 */
913 i_len = p_info->i_idxposb;
914 /* no valid entry use only offset*/
919 i_len = p_info->p_index[p_info->i_idxposc].i_lengthtotal
922 return( (mtime_t)( (s64)1000000 *
924 (s64)p_info->header.i_scale /
925 (s64)p_info->header.i_rate /
926 (s64)p_info->header.i_samplesize ) );
930 /* even if p_info->i_idxposc isn't valid, there isn't any probllem */
931 return( (mtime_t)( (s64)1000000 *
932 (s64)(p_info->i_idxposc ) *
933 (s64)p_info->header.i_scale /
934 (s64)p_info->header.i_rate) );
939 /*****************************************************************************
940 * Functions to acces streams data
941 * Uses it, because i plane to read unseekable stream
942 * Don't work for the moment for unseekable stream
943 * XXX NEVER set directly i_idxposc and i_idxposb unless you know what you do
944 *****************************************************************************/
946 /* FIXME FIXME change b_pad to number of bytes to skipp after reading */
947 static int __AVI_GetDataInPES( input_thread_t *p_input,
948 pes_packet_t **pp_pes,
954 data_packet_t *p_data;
957 if( !(*pp_pes = input_NewPES( p_input->p_method_data ) ) )
965 p_data = input_NewPacket( p_input->p_method_data, 0 );
966 (*pp_pes)->p_first = (*pp_pes)->p_last = p_data;
967 (*pp_pes)->i_nb_data = 1;
968 (*pp_pes)->i_pes_size = 0;
972 if( ( i_size&1 )&&( b_pad ) )
984 i_read = input_SplitBuffer(p_input, &p_data, __MIN( i_size -
985 (*pp_pes)->i_pes_size, 1024 ) );
988 return( (*pp_pes)->i_pes_size );
990 if( !(*pp_pes)->p_first )
993 (*pp_pes)->p_last = p_data;
994 (*pp_pes)->i_nb_data = 1;
995 (*pp_pes)->i_pes_size = i_read;
999 (*pp_pes)->p_last->p_next =
1000 (*pp_pes)->p_last = p_data;
1001 (*pp_pes)->i_nb_data++;
1002 (*pp_pes)->i_pes_size += i_read;
1004 } while( ((*pp_pes)->i_pes_size < i_size)&&( i_read ) );
1008 (*pp_pes)->i_pes_size--;
1009 (*pp_pes)->p_last->p_payload_end--;
1016 static int __AVI_SeekAndGetChunk( input_thread_t *p_input,
1017 AVIStreamInfo_t *p_info )
1019 pes_packet_t *p_pes;
1020 int i_length, i_ret;
1022 i_length = __MIN( p_info->p_index[p_info->i_idxposc].i_length
1023 - p_info->i_idxposb,
1024 BUFFER_MAXSPESSIZE );
1026 AVI_SeekAbsolute( p_input,
1027 (off_t)p_info->p_index[p_info->i_idxposc].i_pos +
1028 p_info->i_idxposb + 8);
1030 i_ret = __AVI_GetDataInPES( p_input, &p_pes, i_length , 0);
1032 if( i_ret != i_length )
1036 /* TODO test key frame if i_idxposb == 0*/
1037 AVI_PESBuffer_Add( p_input->p_method_data,
1041 p_info->i_idxposb );
1044 /* TODO check if it's correct (humm...) and optimisation ... */
1045 /* return 0 if we choose to get only the ck we want
1046 * 1 if index is invalid
1047 * 2 if there is a ck_other before ck_info and the last proced ck_info*/
1048 /* XXX XXX XXX avi file is some BIG shit, and sometime index give
1049 * a refenrence to the same chunk BUT with a different size ( usually 0 )
1052 static inline int __AVI_GetChunkMethod( input_thread_t *p_input,
1053 AVIStreamInfo_t *p_info,
1054 AVIStreamInfo_t *p_other )
1059 int i_info_pos_last;
1060 int i_other_pos_last;
1062 /*If we don't have a valid entry we need to parse from last
1063 defined chunk and it's the only way that we return 1*/
1064 if( p_info->i_idxposc >= p_info->i_idxnb )
1069 /* KNOW we have a valid entry for p_info */
1070 /* we return 0 if we haven't an valid entry for p_other */
1071 if( ( !p_other )||( p_other->i_idxposc >= p_other->i_idxnb ) )
1076 /* KNOW there are 2 streams with valid entry */
1078 /* we return 0 if for one of the two streams we will not read
1080 if( ( p_info->i_idxposb )||( p_other->i_idxposb ) )
1085 /* KNOW we have a valid entry for the 2 streams
1086 and for the 2 we want an aligned chunk (given by i_idxposc )*/
1087 /* if in stream, the next chunk is back than the one we
1088 have just read, it's useless to parse */
1089 i_info_pos = p_info->p_index[p_info->i_idxposc].i_pos;
1090 i_other_pos = p_other->p_index[p_other->i_idxposc].i_pos ;
1092 i_info_pos_last = p_info->i_idxposc ?
1093 p_info->p_index[p_info->i_idxposc - 1].i_pos : 0;
1094 i_other_pos_last = p_other->i_idxposc ?
1095 p_other->p_index[p_other->i_idxposc - 1].i_pos : 0 ;
1098 if( ( ( p_info->i_idxposc )&&( i_info_pos <= i_info_pos_last ) ) ||
1099 ( ( p_other->i_idxposc )&&( i_other_pos <= i_other_pos_last ) ) )
1104 /* KNOW for the 2 streams, the ck we want are after the last read
1105 or it's the first */
1107 /* if the first ck_other we want isn't between ck_info_last
1108 and ck_info, don't parse */
1109 /* TODO fix this, use also number in buffered PES */
1110 if( ( i_other_pos > i_info_pos) /* ck_other too far */
1111 ||( i_other_pos < i_info_pos_last ) ) /* it's too late for ck_other */
1116 /* we Know we will find ck_other, and before ck_info
1117 "if ck_info is too far" will be handle after */
1122 static inline int __AVI_ChooseSize( int l1, int l2 )
1124 /* XXX l2 is prefered if 0 otherwise min not equal to 0 */
1129 return( !l1 ? l2 : __MIN( l1,l2 ) );
1132 /* We know we will read chunk align */
1133 static int __AVI_GetAndPutChunkInBuffer( input_thread_t *p_input,
1134 AVIStreamInfo_t *p_info,
1139 pes_packet_t *p_pes;
1142 i_length = __MIN( i_size, BUFFER_MAXSPESSIZE );
1144 /* Skip chunk header */
1146 if( __AVI_GetDataInPES( p_input, &p_pes, i_length + 8,1 ) != i_length +8 )
1150 p_pes->p_first->p_payload_start += 8;
1151 p_pes->i_pes_size -= 8;
1153 i_size = GetDWLE( p_pes->p_first->p_demux_start + 4);
1155 AVI_PESBuffer_Add( p_input->p_method_data,
1160 /* skip unwanted bytes */
1161 if( i_length != i_size)
1163 msg_Err( p_input, "Chunk Size mismatch" );
1164 AVI_SeekAbsolute( p_input,
1165 __EVEN( AVI_TellAbsolute( p_input ) +
1166 i_size - i_length ) );
1171 /* XXX Don't use this function directly ! XXX */
1172 static int __AVI_GetChunk( input_thread_t *p_input,
1173 AVIStreamInfo_t *p_info,
1176 demux_data_avi_file_t *p_avi_demux =
1177 (demux_data_avi_file_t*)p_input->p_demux_data;
1178 AVIStreamInfo_t *p_other;
1183 #define p_info_i p_avi_demux->pp_info[i]
1184 while( p_info->p_pes_first )
1186 if( ( p_info->p_pes_first->i_posc == p_info->i_idxposc )
1187 &&( p_info->i_idxposb >= p_info->p_pes_first->i_posb )
1188 &&( p_info->i_idxposb < p_info->p_pes_first->i_posb +
1189 p_info->p_pes_first->p_pes->i_pes_size ) )
1192 return( 1 ); /* we have it in buffer */
1196 AVI_PESBuffer_Drop( p_input->p_method_data, p_info );
1199 /* up to now we handle only one audio and video streams at the same time */
1200 p_other = (p_info == p_avi_demux->p_info_video ) ?
1201 p_avi_demux->p_info_audio : p_avi_demux->p_info_video ;
1203 i_method = __AVI_GetChunkMethod( p_input, p_info, p_other );
1207 /* get directly the good chunk */
1208 return( b_load ? __AVI_SeekAndGetChunk( p_input, p_info ) : 1 );
1211 * because invalid index
1212 * or will find ck_other before ck_info
1214 // msg_Warn( p_input, "method %d", i_method );
1215 /* we will calculate the better position we have to reach */
1219 /* the position max we have already reached */
1220 /* FIXME this isn't the better because sometime will fail to
1221 put in buffer p_other since it could be too far */
1222 AVIStreamInfo_t *p_info_max = p_info;
1224 for( i = 0; i < p_avi_demux->i_streams; i++ )
1226 if( p_info_i->i_idxnb )
1228 if( p_info_max->i_idxnb )
1230 if( p_info_i->p_index[p_info_i->i_idxnb -1 ].i_pos >
1231 p_info_max->p_index[p_info_max->i_idxnb -1 ].i_pos )
1233 p_info_max = p_info_i;
1238 p_info_max = p_info_i;
1242 if( p_info_max->i_idxnb )
1244 /* be carefull that size between index and ck can sometime be
1245 different without any error (and other time it's an error) */
1246 i_posmax = p_info_max->p_index[p_info_max->i_idxnb -1 ].i_pos;
1247 /* so choose this, and I know that we have already reach it */
1251 i_posmax = p_avi_demux->p_movi->i_pos + 12;
1258 return( 1 ); /* all is ok */
1261 /* we know that the entry and the last one are valid for the 2 stream */
1262 /* and ck_other will come *before* index so go directly to it*/
1263 i_posmax = p_other->p_index[p_other->i_idxposc].i_pos;
1266 AVI_SeekAbsolute( p_input, i_posmax );
1267 /* the first chunk we will see is :
1268 * the last chunk that we have already seen for broken index
1269 * the first ck for other with good index */
1270 for( ; ; ) /* infinite parsing until the ck we want */
1275 /* Get the actual chunk in the stream */
1276 if( !(p_ck = RIFF_ReadChunk( p_input )) )
1280 // msg_Dbg( p_input, "ck: %4.4s len %d", &p_ck->i_id, p_ck->i_size );
1281 /* special case for LIST-rec chunk */
1282 if( ( p_ck->i_id == FOURCC_LIST )&&( p_ck->i_type == FOURCC_rec ) )
1284 RIFF_DescendChunk( p_input );
1285 RIFF_DeleteChunk( p_input, p_ck );
1288 AVI_ParseStreamHeader( p_ck->i_id, &i, &i_type );
1289 /* littles checks but not too much if you want to read all file */
1290 if( i >= p_avi_demux->i_streams )
1291 /* (AVI_GetESTypeFromTwoCC(i_type) != p_info_i->i_cat) perhaps add it*/
1294 RIFF_DeleteChunk( p_input, p_ck );
1295 if( RIFF_NextChunk( p_input, p_avi_demux->p_movi ) != 0 )
1304 /* have we found a new entry (not present in index)? */
1305 if( ( !p_info_i->i_idxnb )
1306 ||(p_info_i->p_index[p_info_i->i_idxnb-1].i_pos < p_ck->i_pos))
1308 AVIIndexEntry_t index;
1310 index.i_id = p_ck->i_id;
1311 index.i_flags = AVI_GetKeyFlag( p_info_i->p_es->i_fourcc,
1312 (u8*)&p_ck->i_8bytes);
1313 index.i_pos = p_ck->i_pos;
1314 index.i_length = p_ck->i_size;
1315 __AVI_AddEntryIndex( p_info_i, &index );
1319 /* TODO check if p_other is full and then if is possible
1320 go directly to the good chunk */
1321 if( ( p_info_i == p_other )
1322 &&( !AVI_PESBuffer_IsFull( p_other ) )
1323 &&( ( !p_other->p_pes_last )||
1324 ( p_other->p_pes_last->p_pes->i_pes_size !=
1325 BUFFER_MAXSPESSIZE ) ) )
1327 int i_ck = p_other->p_pes_last ?
1328 p_other->p_pes_last->i_posc + 1 : p_other->i_idxposc;
1329 i_size = __AVI_ChooseSize( p_ck->i_size,
1330 p_other->p_index[i_ck].i_length);
1332 if( p_other->p_index[i_ck].i_pos == p_ck->i_pos )
1334 if( !__AVI_GetAndPutChunkInBuffer( p_input, p_other,
1337 RIFF_DeleteChunk( p_input, p_ck );
1343 if( RIFF_NextChunk( p_input, p_avi_demux->p_movi ) != 0 )
1345 RIFF_DeleteChunk( p_input, p_ck );
1352 RIFF_DeleteChunk( p_input, p_ck );
1355 if( ( p_info_i == p_info)
1356 &&( p_info->i_idxposc < p_info->i_idxnb ) )
1358 /* the first ck_info is ok otherwise it should be
1359 loaded without parsing */
1360 i_size = __AVI_ChooseSize( p_ck->i_size,
1361 p_info->p_index[p_info->i_idxposc].i_length);
1364 RIFF_DeleteChunk( p_input, p_ck );
1366 return( b_load ? __AVI_GetAndPutChunkInBuffer( p_input,
1369 p_info->i_idxposc ) : 1 );
1374 RIFF_DeleteChunk( p_input, p_ck );
1375 if( RIFF_NextChunk( p_input, p_avi_demux->p_movi ) != 0 )
1388 /* be sure that i_ck will be a valid index entry */
1389 static int AVI_SetStreamChunk( input_thread_t *p_input,
1390 AVIStreamInfo_t *p_info,
1394 p_info->i_idxposc = i_ck;
1395 p_info->i_idxposb = 0;
1397 if( i_ck < p_info->i_idxnb )
1403 p_info->i_idxposc = p_info->i_idxnb - 1;
1406 p_info->i_idxposc++;
1407 if( !__AVI_GetChunk( p_input, p_info, 0 ) )
1411 } while( p_info->i_idxposc < i_ck );
1418 /* XXX FIXME up to now, we assume that all chunk are one after one */
1419 static int AVI_SetStreamBytes( input_thread_t *p_input,
1420 AVIStreamInfo_t *p_info,
1423 if( ( p_info->i_idxnb > 0 )
1424 &&( i_byte < p_info->p_index[p_info->i_idxnb - 1].i_lengthtotal +
1425 p_info->p_index[p_info->i_idxnb - 1].i_length ) )
1427 /* index is valid to find the ck */
1428 /* uses dichototmie to be fast enougth */
1429 int i_idxposc = __MIN( p_info->i_idxposc, p_info->i_idxnb - 1 );
1430 int i_idxmax = p_info->i_idxnb;
1434 if( p_info->p_index[i_idxposc].i_lengthtotal > i_byte )
1436 i_idxmax = i_idxposc ;
1437 i_idxposc = ( i_idxmin + i_idxposc ) / 2 ;
1441 if( p_info->p_index[i_idxposc].i_lengthtotal +
1442 p_info->p_index[i_idxposc].i_length <= i_byte)
1444 i_idxmin = i_idxposc ;
1445 i_idxposc = (i_idxmax + i_idxposc ) / 2 ;
1449 p_info->i_idxposc = i_idxposc;
1450 p_info->i_idxposb = i_byte -
1451 p_info->p_index[i_idxposc].i_lengthtotal;
1460 p_info->i_idxposc = p_info->i_idxnb - 1;
1461 p_info->i_idxposb = 0;
1464 p_info->i_idxposc++;
1465 if( !__AVI_GetChunk( p_input, p_info, 0 ) )
1469 } while( p_info->p_index[p_info->i_idxposc].i_lengthtotal +
1470 p_info->p_index[p_info->i_idxposc].i_length <= i_byte );
1472 p_info->i_idxposb = i_byte -
1473 p_info->p_index[p_info->i_idxposc].i_lengthtotal;
1478 static pes_packet_t *AVI_ReadStreamChunkInPES( input_thread_t *p_input,
1479 AVIStreamInfo_t *p_info )
1482 if( p_info->i_idxposc > p_info->i_idxnb )
1487 /* we want chunk (p_info->i_idxposc,0) */
1488 p_info->i_idxposb = 0;
1489 if( !__AVI_GetChunk( p_input, p_info, 1) )
1491 msg_Err( p_input, "Got one chunk : failed" );
1494 p_info->i_idxposc++;
1495 return( AVI_PESBuffer_Get( p_info ) );
1498 static pes_packet_t *AVI_ReadStreamBytesInPES( input_thread_t *p_input,
1499 AVIStreamInfo_t *p_info,
1502 pes_packet_t *p_pes;
1503 data_packet_t *p_data;
1508 if( !( p_pes = input_NewPES( p_input->p_method_data ) ) )
1512 if( !( p_data = input_NewPacket( p_input->p_method_data, i_byte ) ) )
1514 input_DeletePES( p_input->p_method_data, p_pes );
1519 p_pes->p_last = p_data;
1520 p_pes->i_nb_data = 1;
1521 p_pes->i_pes_size = i_byte;
1525 if( !__AVI_GetChunk( p_input, p_info, 1) )
1527 msg_Err( p_input, "Got one chunk : failed" );
1529 input_DeletePES( p_input->p_method_data, p_pes );
1533 i_read = __MIN( p_info->p_pes_first->p_pes->i_pes_size -
1534 ( p_info->i_idxposb - p_info->p_pes_first->i_posb ),
1536 /* FIXME FIXME FIXME follow all data packet */
1537 memcpy( p_data->p_payload_start + i_count,
1538 p_info->p_pes_first->p_pes->p_first->p_payload_start +
1539 p_info->i_idxposb - p_info->p_pes_first->i_posb,
1542 AVI_PESBuffer_Drop( p_input->p_method_data, p_info );
1546 p_info->i_idxposb += i_read;
1547 if( p_info->p_index[p_info->i_idxposc].i_length <= p_info->i_idxposb )
1549 p_info->i_idxposb -= p_info->p_index[p_info->i_idxposc].i_length;
1550 p_info->i_idxposc++;
1558 /* try to realign after a seek */
1559 static int AVI_ReAlign( input_thread_t *p_input,
1560 AVIStreamInfo_t *p_info )
1565 demux_data_avi_file_t *p_avi_demux =
1566 (demux_data_avi_file_t*)p_input->p_demux_data;
1569 for( i = 0; i < p_avi_demux->i_streams; i++ )
1571 AVI_PESBuffer_Flush( p_input->p_method_data, p_avi_demux->pp_info[i] );
1574 TODO use input_ClockInit instead but need to be exported
1575 p_input->stream.p_selected_program->last_cr = 0;
1576 p_input->stream.p_selected_program->last_syscr = 0;
1577 p_input->stream.p_selected_program->cr_ref = 0;
1578 p_input->stream.p_selected_program->sysdate_ref = 0;
1579 p_input->stream.p_selected_program->delta_cr = 0;
1580 p_input->stream.p_selected_program->c_average_count = 0; */
1582 i_pos = AVI_TellAbsolute( p_input );
1584 p_info->i_idxposc--; /* in fact p_info->i_idxposc is for ck to be read */
1587 if( ( p_info->i_idxposc <= 0)
1588 ||( i_pos <= p_info->p_index[0].i_pos ) )
1590 /* before beginning of stream */
1591 return( p_info->header.i_samplesize ?
1592 AVI_SetStreamBytes( p_input, p_info, 0 ) :
1593 AVI_SetStreamChunk( p_input, p_info, 0 ) );
1596 b_after = ( i_pos >= p_info->p_index[p_info->i_idxposc].i_pos );
1597 /* now find in what chunk we are */
1598 while( ( i_pos < p_info->p_index[p_info->i_idxposc].i_pos )
1599 &&( p_info->i_idxposc > 0 ) )
1601 /* search before i_idxposc */
1603 if( !AVI_SetStreamChunk( p_input, p_info, p_info->i_idxposc - 1 ) )
1609 while( i_pos >= p_info->p_index[p_info->i_idxposc].i_pos +
1610 p_info->p_index[p_info->i_idxposc].i_length + 8 )
1612 /* search after i_idxposc */
1614 if( !AVI_SetStreamChunk( p_input, p_info, p_info->i_idxposc + 1 ) )
1620 /* search nearest key frame, only for video */
1621 if( p_info->i_cat == VIDEO_ES )
1625 while(!(p_info->p_index[p_info->i_idxposc].i_flags&AVIIF_KEYFRAME) )
1627 if( !AVI_SetStreamChunk( p_input, p_info,
1628 p_info->i_idxposc + 1 ) )
1636 while( ( p_info->i_idxposc > 0 ) &&
1637 (!(p_info->p_index[p_info->i_idxposc].i_flags&AVIIF_KEYFRAME)) )
1640 if( !AVI_SetStreamChunk( p_input, p_info,
1641 p_info->i_idxposc - 1 ) )
1652 /* make difference between audio and video pts as little as possible */
1653 static void AVI_SynchroReInit( input_thread_t *p_input )
1655 demux_data_avi_file_t *p_avi_demux =
1656 (demux_data_avi_file_t*)p_input->p_demux_data;
1658 #define p_info_video p_avi_demux->p_info_video
1659 #define p_info_audio p_avi_demux->p_info_audio
1660 if( ( !p_info_audio )||( !p_info_video ) )
1664 /* now resynch audio video video */
1665 /*don't care of AVIF_KEYFRAME */
1666 if( !p_info_audio->header.i_samplesize )
1668 AVI_SetStreamChunk( p_input,
1670 AVI_PTSToChunk( p_info_audio,
1671 AVI_GetPTS( p_info_video ) ) );
1675 AVI_SetStreamBytes( p_input,
1677 AVI_PTSToByte( p_info_audio,
1678 AVI_GetPTS( p_info_video ) ) );
1684 /*****************************************************************************
1685 * AVI_GetFrameInPES : get dpts length(µs) in pes from stream
1686 *****************************************************************************
1687 * Handle multiple pes, and set pts to the good value
1688 *****************************************************************************/
1689 static pes_packet_t *AVI_GetFrameInPES( input_thread_t *p_input,
1690 AVIStreamInfo_t *p_info,
1694 pes_packet_t *p_pes = NULL;
1695 pes_packet_t *p_pes_tmp = NULL;
1696 pes_packet_t *p_pes_first = NULL;
1704 if( !p_info->header.i_samplesize )
1706 int i_chunk = __MAX( AVI_PTSToChunk( p_info, i_dpts), 1 );
1708 for( i = 0; i < i_chunk; i++ )
1710 /* get pts while is valid */
1711 i_pts = AVI_GetPTS( p_info );
1713 p_pes_tmp = AVI_ReadStreamChunkInPES( p_input, p_info );
1717 return( p_pes_first );
1719 p_pes_tmp->i_pts = i_pts;
1722 p_pes_first = p_pes_tmp;
1726 p_pes->p_next = p_pes_tmp;
1730 return( p_pes_first );
1734 /* stream is byte based */
1735 int i_byte = AVI_PTSToByte( p_info, i_dpts);
1736 if( i_byte < 50 ) /* to avoid some problem with audio */
1740 i_pts = AVI_GetPTS( p_info ); /* ok even with broken index */
1741 p_pes = AVI_ReadStreamBytesInPES( p_input, p_info, i_byte);
1745 p_pes->i_pts = i_pts;
1750 /*****************************************************************************
1751 * AVI_DecodePES : send a pes to decoder
1752 *****************************************************************************
1753 * Handle multiple pes, and update pts to the good value
1754 *****************************************************************************/
1755 static inline void AVI_DecodePES( input_thread_t *p_input,
1756 AVIStreamInfo_t *p_info,
1757 pes_packet_t *p_pes )
1759 pes_packet_t *p_pes_next;
1760 /* input_decode want only one pes, but AVI_GetFrameInPES give
1761 multiple pes so send one by one */
1764 p_pes_next = p_pes->p_next;
1765 p_pes->p_next = NULL;
1766 p_pes->i_pts = input_ClockGetTS( p_input,
1767 p_input->stream.p_selected_program,
1768 p_pes->i_pts * 9/100);
1769 input_DecodePES( p_info->p_es->p_decoder_fifo, p_pes );
1775 /*****************************************************************************
1776 * AVIDemux_Seekable: reads and demuxes data packets for stream seekable
1777 *****************************************************************************
1778 * Called by AVIDemux, that make common work
1779 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
1780 *****************************************************************************/
1781 static int AVIDemux_Seekable( input_thread_t *p_input,
1782 AVIStreamInfo_t *p_info_master,
1783 AVIStreamInfo_t *p_info_slave )
1785 demux_data_avi_file_t *p_avi_demux =
1786 (demux_data_avi_file_t*)p_input->p_demux_data;
1788 pes_packet_t *p_pes_master;
1789 pes_packet_t *p_pes_slave;
1791 /* check for signal from interface */
1792 if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
1794 /* we can supposed that is a seek */
1795 /* first wait for empty buffer, arbitrary time */
1796 msleep( DEFAULT_PTS_DELAY );
1797 /* then try to realign in stream */
1798 if( !AVI_ReAlign( p_input, p_info_master ) )
1800 return( 0 ); /* assume EOF */
1802 AVI_SynchroReInit( p_input );
1805 /* take care of newly selected audio ES */
1806 if( p_info_master->b_selected )
1808 p_info_master->b_selected = 0;
1809 AVI_SynchroReInit( p_input );
1811 if( ( p_info_slave )&&( p_info_slave->b_selected ) )
1813 p_info_slave->b_selected = 0;
1814 AVI_SynchroReInit( p_input );
1817 /* wait for the good time */
1818 input_ClockManageRef( p_input,
1819 p_input->stream.p_selected_program,
1820 p_avi_demux->i_pcr /*- DEFAULT_PTS_DELAY / 2 */);
1821 /* calculate pcr, time when we must read the next data */
1822 /* 9/100 kludge ->need to convert to 1/1000000 clock unit to 1/90000 */
1825 p_avi_demux->i_pcr = __MIN( AVI_GetPTS( p_info_master ),
1826 AVI_GetPTS( p_info_slave ) ) * 9/100;
1830 p_avi_demux->i_pcr = AVI_GetPTS( p_info_master ) * 9/100;
1833 /* get video and audio frames */
1834 p_pes_master = AVI_GetFrameInPES( p_input,
1836 100000 ); /* 100 ms */
1837 AVI_DecodePES( p_input,
1844 p_pes_slave = AVI_GetFrameInPES( p_input,
1846 AVI_GetPTS( p_info_master ) -
1847 AVI_GetPTS( p_info_slave) );
1848 AVI_DecodePES( p_input,
1855 return( p_pes_master ? 1 : 0 );
1859 /*****************************************************************************
1860 * AVIDemux_NotSeekable: reads and demuxes data packets for stream seekable
1861 *****************************************************************************
1862 * Called by AVIDemux, that makes common work
1863 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
1864 *****************************************************************************/
1866 /* 0 if can be load/updated, 1 if skip, 2 if descend into, 3 if exit, 4 if error and need recover */
1867 static int __AVIDemux_ChunkAction( int i_streams_max,
1873 AVI_ParseStreamHeader( p_ck->i_id, &i_stream, &i_type );
1874 if( i_stream < i_streams_max )
1876 return( 0 ); /* read and/or update stream info */
1879 if( i_stream <= 99 )
1881 /* should not happen but ... */
1885 /* now we know that it's not a stream */
1887 switch( p_ck->i_id )
1889 case( FOURCC_JUNK ):
1891 case( FOURCC_idx1 ):
1893 case( FOURCC_LIST ):
1894 if( p_ck->i_type == FOURCC_rec )
1907 if( ( p_ck->i_id & 0xFFFF ) == VLC_TWOCC( 'i','x' ) )
1915 static int AVI_NotSeekableRecover( input_thread_t *p_input )
1919 int i_number, i_type;
1920 data_packet_t *p_pack;
1924 if( input_Peek( p_input, &p_id, 4 ) < 4 )
1926 return( 0 ); /* Failed */
1928 i_id = GetDWLE( p_id );
1931 case( FOURCC_idx1 ):
1932 case( FOURCC_JUNK ):
1933 case( FOURCC_LIST ):
1936 AVI_ParseStreamHeader( i_id, &i_number, &i_type );
1937 if( i_number <= 99 )
1953 /* Read 1 byte VERY unoptimised */
1954 if( input_SplitBuffer( p_input, &p_pack, 1) < 1 )
1958 input_DeletePacket( p_input->p_method_data, p_pack);
1963 static int AVIDemux_NotSeekable( input_thread_t *p_input,
1964 AVIStreamInfo_t *p_info_master,
1965 AVIStreamInfo_t *p_info_slave )
1967 demux_data_avi_file_t *p_avi_demux =
1968 (demux_data_avi_file_t*)p_input->p_demux_data;
1974 pes_packet_t *p_pes;
1977 i_filepos = AVI_TellAbsolute( p_input );
1978 p_input->pf_seek( p_input, i_filepos );
1979 input_AccessReinit( p_input );
1982 #define p_info p_avi_demux->pp_info[i_stream]
1984 /* The managment is very basic, we will read packets, caclulate pts
1985 and send it to decoder, synchro made on video, and audio is very less
1988 /* wait the good time */
1989 input_ClockManageRef( p_input,
1990 p_input->stream.p_selected_program,
1991 p_avi_demux->i_pcr /*- DEFAULT_PTS_DELAY / 2 */);
1992 /* TODO be smart, seeing if we can wait for min( audio, video )
1993 or there is a too big deep */
1996 p_avi_demux->i_pcr = AVI_GetPTS( p_info_master ) * 9/100;
2000 p_avi_demux->i_pcr = __MIN( AVI_GetPTS( p_info_master ),
2001 AVI_GetPTS( p_info_slave ) ) * 9/100;
2002 p_avi_demux->i_pcr = AVI_GetPTS( p_info_master ) * 9/100;
2005 for( i_loop = 0; i_loop < 10; i_loop++ )
2009 /* first find a ck for master or slave */
2013 if( !(p_ck = RIFF_ReadChunk( p_input ) ) )
2015 msg_Err( p_input, "Badd" );
2016 return( 0 ); /* assume EOF */
2018 //msg_Err( p_input,"Looking ck: %4.4s %d",&p_ck->i_id, p_ck->i_size );
2020 switch( __AVIDemux_ChunkAction( p_avi_demux->i_streams, p_ck ) )
2022 case( 0 ): /* load it if possible */
2025 case( 1 ): /* skip it */
2026 RIFF_DeleteChunk( p_input, p_ck );
2027 if( RIFF_NextChunk( p_input, p_avi_demux->p_movi ) != 0 )
2033 case( 2 ): /* descend into */
2034 RIFF_DeleteChunk( p_input, p_ck );
2035 RIFF_DescendChunk( p_input );
2038 case( 3 ): /* exit */
2039 RIFF_DeleteChunk( p_input, p_ck );
2041 case( 4 ): /* Error */
2042 RIFF_DeleteChunk( p_input, p_ck );
2043 msg_Warn( p_input, "unknown chunk id 0x%8.8x, trying to recover", p_ck->i_id );
2044 if( !AVI_NotSeekableRecover( p_input ) )
2046 msg_Err( p_input, "cannot recover, dying" );
2051 msg_Warn( p_input, "recovered sucessfully" );
2059 AVI_ParseStreamHeader( p_ck->i_id, &i_stream, &i_type );
2060 /* now check if we really have to load it */
2061 if( ( p_info != p_info_master )&&( p_info != p_info_slave ) )
2067 if( p_info == p_info_master )
2074 i_dpts = AVI_GetPTS( p_info_slave ) -
2075 AVI_GetPTS( p_info_master );
2076 if( i_dpts < 0 ) {i_dpts = - i_dpts; }
2077 if( i_dpts < 600000 )
2089 /* now do we can load this chunk ? */
2093 if( __AVI_GetDataInPES( p_input, &p_pes, p_ck->i_size + 8, 1) != p_ck->i_size + 8)
2097 p_pes->p_first->p_payload_start += 8;
2098 p_pes->i_pes_size -= 8;
2100 p_pes->i_pts = AVI_GetPTS( p_info );
2101 AVI_DecodePES( p_input, p_info, p_pes );
2106 if( RIFF_NextChunk( p_input, p_avi_demux->p_movi ) != 0 )
2108 RIFF_DeleteChunk( p_input, p_ck );
2113 /* finaly update stream information */
2114 if( p_info->header.i_samplesize )
2116 p_info->i_idxposb += p_ck->i_size;
2120 p_info->i_idxposc++;
2123 RIFF_DeleteChunk( p_input, p_ck );
2129 /*****************************************************************************
2130 * AVIDemux: reads and demuxes data packets
2131 *****************************************************************************
2132 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
2133 * TODO add support for unstreable file, just read a chunk and send it
2134 * to the right decoder, very easy
2135 *****************************************************************************/
2137 static int AVIDemux( input_thread_t *p_input )
2140 AVIStreamInfo_t *p_info_master;
2141 AVIStreamInfo_t *p_info_slave;
2143 demux_data_avi_file_t *p_avi_demux =
2144 (demux_data_avi_file_t*)p_input->p_demux_data;
2146 /* search new video and audio stream selected
2147 if current have been unselected*/
2148 if( ( !p_avi_demux->p_info_video )
2149 || ( !p_avi_demux->p_info_video->p_es->p_decoder_fifo ) )
2151 p_avi_demux->p_info_video = NULL;
2152 for( i = 0; i < p_avi_demux->i_streams; i++ )
2154 if( ( p_avi_demux->pp_info[i]->i_cat == VIDEO_ES )
2155 &&( p_avi_demux->pp_info[i]->p_es->p_decoder_fifo ) )
2157 p_avi_demux->p_info_video = p_avi_demux->pp_info[i];
2158 p_avi_demux->p_info_video->b_selected = 1;
2163 if( ( !p_avi_demux->p_info_audio )
2164 ||( !p_avi_demux->p_info_audio->p_es->p_decoder_fifo ) )
2166 p_avi_demux->p_info_audio = NULL;
2167 for( i = 0; i < p_avi_demux->i_streams; i++ )
2169 if( ( p_avi_demux->pp_info[i]->i_cat == AUDIO_ES )
2170 &&( p_avi_demux->pp_info[i]->p_es->p_decoder_fifo ) )
2172 p_avi_demux->p_info_audio = p_avi_demux->pp_info[i];
2173 p_avi_demux->p_info_audio->b_selected = 1;
2178 /* by default video is master for resync audio (after a seek .. ) */
2179 if( p_avi_demux->p_info_video )
2181 p_info_master = p_avi_demux->p_info_video;
2182 p_info_slave = p_avi_demux->p_info_audio;
2186 p_info_master = p_avi_demux->p_info_audio;
2187 p_info_slave = NULL;
2190 if( !p_info_master )
2192 msg_Err( p_input, "no stream selected" );
2196 /* manage rate, if not default: skeep audio */
2197 vlc_mutex_lock( &p_input->stream.stream_lock );
2198 if( p_input->stream.control.i_rate != p_avi_demux->i_rate )
2200 if( p_avi_demux->p_info_audio)
2202 p_avi_demux->p_info_audio->b_selected = 1;
2204 p_avi_demux->i_rate = p_input->stream.control.i_rate;
2206 vlc_mutex_unlock( &p_input->stream.stream_lock );
2207 p_avi_demux->i_rate = DEFAULT_RATE;
2208 if( p_avi_demux->i_rate != DEFAULT_RATE )
2210 p_info_slave = NULL;
2213 if( p_avi_demux->b_seekable )
2215 return( AVIDemux_Seekable( p_input,
2221 return( AVIDemux_NotSeekable( p_input,