1 /*****************************************************************************
2 * avi.c : AVI file Stream input module for vlc
3 *****************************************************************************
4 * Copyright (C) 2001 VideoLAN
5 * $Id: avi.c,v 1.3 2002/08/08 22:28:22 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_sys_t *p_avi = p_input->p_demux_data;
435 if( RIFF_FindAndGotoDataChunk( p_input,
440 msg_Warn( p_input, "cannot find index" );
441 RIFF_GoToChunk( p_input, p_avi->p_hdrl );
444 p_avi->p_idx1 = p_idx1;
445 msg_Dbg( p_input, "loading index" );
448 i_read = __MIN( 16*1024, p_idx1->i_size - i_totalentry *16);
449 if( ((i_read = input_Peek( p_input, &p_buff, i_read )) < 16 )
450 ||( i_totalentry *16 >= p_idx1->i_size ) )
452 msg_Dbg( p_input, "read %d idx entries", i_totalentry );
456 for( i = 0; i < i_read; i++ )
458 byte_t *p_peek = p_buff + i * 16;
460 index.i_id = GetDWLE( p_peek );
461 index.i_flags = GetDWLE( p_peek+4)&(~AVIIF_FIXKEYFRAME);
462 index.i_pos = GetDWLE( p_peek+8);
463 index.i_length = GetDWLE(p_peek+12);
464 AVI_ParseStreamHeader( index.i_id, &i_number, &i_type );
466 if( ( i_number < p_avi->i_streams )
467 &&(p_avi->pp_info[i_number]->i_cat ==
468 AVI_GetESTypeFromTwoCC( i_type )))
470 __AVI_AddEntryIndex( p_avi->pp_info[i_number],
474 __RIFF_SkipBytes( p_input, 16 * i_read );
479 /* XXX call after get p_movi */
480 static void __AVI_UpdateIndexOffset( input_thread_t *p_input )
483 int b_start = 1;/* if index pos is based on start of file or not (p_movi) */
484 demux_sys_t *p_avi = p_input->p_demux_data;
486 /* FIXME some work to do :
487 * test in the file if it's true, if not do a RIFF_Find...
489 #define p_info p_avi->pp_info[i_stream]
490 for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
492 if( ( p_info->p_index )
493 && ( p_info->p_index[0].i_pos < p_avi->p_movi->i_pos + 8 ))
501 for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
504 if( p_info->p_index )
506 for( i = 0; i < p_info->i_idxnb; i++ )
508 p_info->p_index[i].i_pos += p_avi->p_movi->i_pos + 8;
516 /*****************************************************************************
517 * AVIEnd: frees unused data
518 *****************************************************************************/
519 static void __AVIEnd ( vlc_object_t * p_this )
521 input_thread_t * p_input = (input_thread_t *)p_this;
523 demux_sys_t *p_avi = p_input->p_demux_data ;
526 RIFF_DeleteChunk( p_input, p_avi->p_riff );
528 RIFF_DeleteChunk( p_input, p_avi->p_hdrl );
530 RIFF_DeleteChunk( p_input, p_avi->p_movi );
532 RIFF_DeleteChunk( p_input, p_avi->p_idx1 );
535 for( i = 0; i < p_avi->i_streams; i++ )
537 if( p_avi->pp_info[i] )
539 if( p_avi->pp_info[i]->p_index )
541 free( p_avi->pp_info[i]->p_index );
542 AVI_PESBuffer_Flush( p_input->p_method_data,
545 free( p_avi->pp_info[i] );
548 free( p_avi->pp_info );
552 /*****************************************************************************
553 * AVIInit: check file and initializes AVI structures
554 *****************************************************************************/
555 static int AVIInit( vlc_object_t * p_this )
557 input_thread_t * p_input = (input_thread_t *)p_this;
558 riffchunk_t *p_riff,*p_hdrl,*p_movi;
560 riffchunk_t *p_strl,*p_strh,*p_strf;
562 es_descriptor_t *p_es = NULL; /* for not warning */
565 p_input->pf_demux = AVIDemux;
567 if( !( p_input->p_demux_data =
568 p_avi = malloc( sizeof(demux_sys_t) ) ) )
570 msg_Err( p_input, "out of memory" );
573 memset( p_avi, 0, sizeof( demux_sys_t ) );
574 p_avi->i_rate = DEFAULT_RATE;
575 p_avi->b_seekable = ( ( p_input->stream.b_seekable )
576 &&( p_input->stream.i_method == INPUT_METHOD_FILE ) );
578 /* Initialize access plug-in structures. */
579 if( p_input->i_mtu == 0 )
582 p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
585 if( RIFF_TestFileHeader( p_input, &p_riff, FOURCC_AVI ) != 0 )
588 msg_Warn( p_input, "RIFF-AVI module discarded" );
591 p_avi->p_riff = p_riff;
593 if ( RIFF_DescendChunk(p_input) != 0 )
596 msg_Err( p_input, "cannot look for subchunk" );
600 /* it's a riff-avi file, so search for LIST-hdrl */
601 if( RIFF_FindListChunk(p_input ,&p_hdrl,p_riff, FOURCC_hdrl) != 0 )
604 msg_Err( p_input, "cannot find \"LIST-hdrl\"" );
607 p_avi->p_hdrl = p_hdrl;
609 if( RIFF_DescendChunk(p_input) != 0 )
612 msg_Err( p_input, "cannot look for subchunk" );
615 /* in LIST-hdrl search avih */
616 if( RIFF_FindAndLoadChunk( p_input, p_hdrl,
617 &p_avih, FOURCC_avih ) != 0 )
620 msg_Err( p_input, "cannot find \"avih\" chunk" );
623 AVI_Parse_avih( &p_avi->avih, p_avih->p_data->p_payload_start );
624 RIFF_DeleteChunk( p_input, p_avih );
626 if( p_avi->avih.i_streams == 0 )
627 /* no stream found, perhaps it would be cool to find it */
630 msg_Err( p_input, "no stream defined!" );
634 /* create one program */
635 vlc_mutex_lock( &p_input->stream.stream_lock );
636 if( input_InitStream( p_input, 0 ) == -1)
638 vlc_mutex_unlock( &p_input->stream.stream_lock );
640 msg_Err( p_input, "cannot init stream" );
643 if( input_AddProgram( p_input, 0, 0) == NULL )
645 vlc_mutex_unlock( &p_input->stream.stream_lock );
647 msg_Err( p_input, "cannot add program" );
650 p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
651 p_input->stream.i_mux_rate = p_avi->avih.i_maxbytespersec / 50;
652 vlc_mutex_unlock( &p_input->stream.stream_lock );
654 /* now read info on each stream and create ES */
655 p_avi->i_streams = p_avi->avih.i_streams;
657 p_avi->pp_info = calloc( p_avi->i_streams,
658 sizeof( AVIStreamInfo_t* ) );
659 memset( p_avi->pp_info,
661 sizeof( AVIStreamInfo_t* ) * p_avi->i_streams );
663 for( i = 0 ; i < p_avi->i_streams; i++ )
665 #define p_info p_avi->pp_info[i]
666 p_info = malloc( sizeof(AVIStreamInfo_t ) );
667 memset( p_info, 0, sizeof( AVIStreamInfo_t ) );
669 if( ( RIFF_FindListChunk(p_input,
670 &p_strl,p_hdrl, FOURCC_strl) != 0 )
671 ||( RIFF_DescendChunk(p_input) != 0 ))
674 msg_Err( p_input, "cannot find \"LIST-strl\"" );
678 /* in LIST-strl search strh */
679 if( RIFF_FindAndLoadChunk( p_input, p_hdrl,
680 &p_strh, FOURCC_strh ) != 0 )
682 RIFF_DeleteChunk( p_input, p_strl );
684 msg_Err( p_input, "cannot find \"strh\"" );
687 AVI_Parse_Header( &p_info->header,
688 p_strh->p_data->p_payload_start);
689 RIFF_DeleteChunk( p_input, p_strh );
691 /* in LIST-strl search strf */
692 if( RIFF_FindAndLoadChunk( p_input, p_hdrl,
693 &p_strf, FOURCC_strf ) != 0 )
695 RIFF_DeleteChunk( p_input, p_strl );
697 msg_Err( p_input, "cannot find \"strf\"" );
700 /* we don't get strd, it's useless for divx,opendivx,mepgaudio */
701 if( RIFF_AscendChunk(p_input, p_strl) != 0 )
703 RIFF_DeleteChunk( p_input, p_strf );
704 RIFF_DeleteChunk( p_input, p_strl );
706 msg_Err( p_input, "cannot go out (\"strl\")" );
711 vlc_mutex_lock( &p_input->stream.stream_lock );
712 p_es = input_AddES( p_input,
713 p_input->stream.p_selected_program, 1+i,
715 vlc_mutex_unlock( &p_input->stream.stream_lock );
716 p_es->i_stream_id =i; /* XXX: i don't use it */
718 switch( p_info->header.i_type )
721 p_es->i_cat = AUDIO_ES;
722 AVI_Parse_WaveFormatEx( &p_info->audio_format,
723 p_strf->p_data->p_payload_start );
724 p_es->i_fourcc = AVI_AudioGetType(
725 p_info->audio_format.i_formattag );
729 p_es->i_cat = VIDEO_ES;
730 AVI_Parse_BitMapInfoHeader( &p_info->video_format,
731 p_strf->p_data->p_payload_start );
733 /* XXX quick hack for playing ffmpeg video, I don't know
734 who is doing something wrong */
735 p_info->header.i_samplesize = 0;
736 p_es->i_fourcc = p_info->video_format.i_compression;
739 msg_Err( p_input, "unknown stream(%d) type", i );
740 p_es->i_cat = UNKNOWN_ES;
744 p_info->i_cat = p_es->i_cat;
745 /* We copy strf for decoder in p_es->p_demux_data */
746 memcpy( p_es->p_demux_data,
747 p_strf->p_data->p_payload_start,
749 RIFF_DeleteChunk( p_input, p_strf );
750 RIFF_DeleteChunk( p_input, p_strl );
756 /* go out of p_hdrl */
757 if( RIFF_AscendChunk(p_input, p_hdrl) != 0)
760 msg_Err( p_input, "cannot go out (\"hdrl\")" );
764 /* go to movi chunk to get it*/
765 if( RIFF_FindListChunk(p_input ,&p_movi,p_riff, FOURCC_movi) != 0 )
767 msg_Err( p_input, "cannot find \"LIST-movi\"" );
771 p_avi->p_movi = p_movi;
773 /* get index XXX need to have p_movi */
774 if( p_avi->b_seekable )
777 __AVI_GetIndex( p_input );
778 /* try to get i_idxoffset for each stream */
779 __AVI_UpdateIndexOffset( p_input );
780 /* to make sure to go the begining unless demux will see a seek */
781 RIFF_GoToChunk( p_input, p_avi->p_movi );
786 msg_Warn( p_input, "no index!" );
789 if( RIFF_DescendChunk( p_input ) != 0 )
792 msg_Err( p_input, "cannot go in (\"movi\")" );
796 /* print informations on streams */
797 msg_Dbg( p_input, "AVIH: %d stream, flags %s%s%s%s ",
799 p_avi->avih.i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
800 p_avi->avih.i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",
801 p_avi->avih.i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
802 p_avi->avih.i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"" );
804 for( i = 0; i < p_avi->i_streams; i++ )
806 #define p_info p_avi->pp_info[i]
807 switch( p_info->p_es->i_cat )
811 msg_Dbg( p_input, "video(%4.4s) %dx%d %dbpp %ffps",
812 (char*)&p_info->video_format.i_compression,
813 p_info->video_format.i_width,
814 p_info->video_format.i_height,
815 p_info->video_format.i_bitcount,
816 (float)p_info->header.i_rate /
817 (float)p_info->header.i_scale );
818 if( (p_avi->p_info_video == NULL) )
820 p_avi->p_info_video = p_info;
821 /* TODO add test to see if a decoder has been found */
822 vlc_mutex_lock( &p_input->stream.stream_lock );
823 input_SelectES( p_input, p_info->p_es );
824 vlc_mutex_unlock( &p_input->stream.stream_lock );
829 msg_Dbg( p_input, "audio(0x%x) %d channels %dHz %dbits",
830 p_info->audio_format.i_formattag,
831 p_info->audio_format.i_channels,
832 p_info->audio_format.i_samplespersec,
833 p_info->audio_format.i_bitspersample );
834 if( (p_avi->p_info_audio == NULL) )
836 p_avi->p_info_audio = p_info;
837 vlc_mutex_lock( &p_input->stream.stream_lock );
838 input_SelectES( p_input, p_info->p_es );
839 vlc_mutex_unlock( &p_input->stream.stream_lock );
849 /* we select the first audio and video ES */
850 vlc_mutex_lock( &p_input->stream.stream_lock );
851 if( !p_avi->p_info_video )
853 msg_Warn( p_input, "no video stream found" );
855 if( !p_avi->p_info_audio )
857 msg_Warn( p_input, "no audio stream found!" );
859 p_input->stream.p_selected_program->b_is_ok = 1;
860 vlc_mutex_unlock( &p_input->stream.stream_lock );
870 /*****************************************************************************
871 * Function to convert pts to chunk or byte
872 *****************************************************************************/
874 static inline mtime_t AVI_PTSToChunk( AVIStreamInfo_t *p_info,
877 return( (mtime_t)((s64)i_pts *
878 (s64)p_info->header.i_rate /
879 (s64)p_info->header.i_scale /
882 static inline mtime_t AVI_PTSToByte( AVIStreamInfo_t *p_info,
885 return( (mtime_t)((s64)i_pts *
886 (s64)p_info->header.i_samplesize *
887 (s64)p_info->header.i_rate /
888 (s64)p_info->header.i_scale /
892 static mtime_t AVI_GetPTS( AVIStreamInfo_t *p_info )
895 if( p_info->header.i_samplesize )
897 /* we need a valid entry we will emulate one */
899 if( p_info->i_idxposc == p_info->i_idxnb )
901 if( p_info->i_idxposc )
903 /* use the last entry */
904 i_len = p_info->p_index[p_info->i_idxnb - 1].i_lengthtotal
905 + p_info->p_index[p_info->i_idxnb - 1].i_length
906 + p_info->i_idxposb; /* should be 0 */
910 i_len = p_info->i_idxposb;
911 /* no valid entry use only offset*/
916 i_len = p_info->p_index[p_info->i_idxposc].i_lengthtotal
919 return( (mtime_t)( (s64)1000000 *
921 (s64)p_info->header.i_scale /
922 (s64)p_info->header.i_rate /
923 (s64)p_info->header.i_samplesize ) );
927 /* even if p_info->i_idxposc isn't valid, there isn't any probllem */
928 return( (mtime_t)( (s64)1000000 *
929 (s64)(p_info->i_idxposc ) *
930 (s64)p_info->header.i_scale /
931 (s64)p_info->header.i_rate) );
936 /*****************************************************************************
937 * Functions to acces streams data
938 * Uses it, because i plane to read unseekable stream
939 * Don't work for the moment for unseekable stream
940 * XXX NEVER set directly i_idxposc and i_idxposb unless you know what you do
941 *****************************************************************************/
943 /* FIXME FIXME change b_pad to number of bytes to skipp after reading */
944 static int __AVI_GetDataInPES( input_thread_t *p_input,
945 pes_packet_t **pp_pes,
951 data_packet_t *p_data;
954 if( !(*pp_pes = input_NewPES( p_input->p_method_data ) ) )
962 p_data = input_NewPacket( p_input->p_method_data, 0 );
963 (*pp_pes)->p_first = (*pp_pes)->p_last = p_data;
964 (*pp_pes)->i_nb_data = 1;
965 (*pp_pes)->i_pes_size = 0;
969 if( ( i_size&1 )&&( b_pad ) )
981 i_read = input_SplitBuffer(p_input, &p_data, __MIN( i_size -
982 (*pp_pes)->i_pes_size, 1024 ) );
985 return( (*pp_pes)->i_pes_size );
987 if( !(*pp_pes)->p_first )
990 (*pp_pes)->p_last = p_data;
991 (*pp_pes)->i_nb_data = 1;
992 (*pp_pes)->i_pes_size = i_read;
996 (*pp_pes)->p_last->p_next =
997 (*pp_pes)->p_last = p_data;
998 (*pp_pes)->i_nb_data++;
999 (*pp_pes)->i_pes_size += i_read;
1001 } while( ((*pp_pes)->i_pes_size < i_size)&&( i_read ) );
1005 (*pp_pes)->i_pes_size--;
1006 (*pp_pes)->p_last->p_payload_end--;
1013 static int __AVI_SeekAndGetChunk( input_thread_t *p_input,
1014 AVIStreamInfo_t *p_info )
1016 pes_packet_t *p_pes;
1017 int i_length, i_ret;
1019 i_length = __MIN( p_info->p_index[p_info->i_idxposc].i_length
1020 - p_info->i_idxposb,
1021 BUFFER_MAXSPESSIZE );
1023 AVI_SeekAbsolute( p_input,
1024 (off_t)p_info->p_index[p_info->i_idxposc].i_pos +
1025 p_info->i_idxposb + 8);
1027 i_ret = __AVI_GetDataInPES( p_input, &p_pes, i_length , 0);
1029 if( i_ret != i_length )
1033 /* TODO test key frame if i_idxposb == 0*/
1034 AVI_PESBuffer_Add( p_input->p_method_data,
1038 p_info->i_idxposb );
1041 /* TODO check if it's correct (humm...) and optimisation ... */
1042 /* return 0 if we choose to get only the ck we want
1043 * 1 if index is invalid
1044 * 2 if there is a ck_other before ck_info and the last proced ck_info*/
1045 /* XXX XXX XXX avi file is some BIG shit, and sometime index give
1046 * a refenrence to the same chunk BUT with a different size ( usually 0 )
1049 static inline int __AVI_GetChunkMethod( input_thread_t *p_input,
1050 AVIStreamInfo_t *p_info,
1051 AVIStreamInfo_t *p_other )
1056 int i_info_pos_last;
1057 int i_other_pos_last;
1059 /*If we don't have a valid entry we need to parse from last
1060 defined chunk and it's the only way that we return 1*/
1061 if( p_info->i_idxposc >= p_info->i_idxnb )
1066 /* KNOW we have a valid entry for p_info */
1067 /* we return 0 if we haven't an valid entry for p_other */
1068 if( ( !p_other )||( p_other->i_idxposc >= p_other->i_idxnb ) )
1073 /* KNOW there are 2 streams with valid entry */
1075 /* we return 0 if for one of the two streams we will not read
1077 if( ( p_info->i_idxposb )||( p_other->i_idxposb ) )
1082 /* KNOW we have a valid entry for the 2 streams
1083 and for the 2 we want an aligned chunk (given by i_idxposc )*/
1084 /* if in stream, the next chunk is back than the one we
1085 have just read, it's useless to parse */
1086 i_info_pos = p_info->p_index[p_info->i_idxposc].i_pos;
1087 i_other_pos = p_other->p_index[p_other->i_idxposc].i_pos ;
1089 i_info_pos_last = p_info->i_idxposc ?
1090 p_info->p_index[p_info->i_idxposc - 1].i_pos : 0;
1091 i_other_pos_last = p_other->i_idxposc ?
1092 p_other->p_index[p_other->i_idxposc - 1].i_pos : 0 ;
1095 if( ( ( p_info->i_idxposc )&&( i_info_pos <= i_info_pos_last ) ) ||
1096 ( ( p_other->i_idxposc )&&( i_other_pos <= i_other_pos_last ) ) )
1101 /* KNOW for the 2 streams, the ck we want are after the last read
1102 or it's the first */
1104 /* if the first ck_other we want isn't between ck_info_last
1105 and ck_info, don't parse */
1106 /* TODO fix this, use also number in buffered PES */
1107 if( ( i_other_pos > i_info_pos) /* ck_other too far */
1108 ||( i_other_pos < i_info_pos_last ) ) /* it's too late for ck_other */
1113 /* we Know we will find ck_other, and before ck_info
1114 "if ck_info is too far" will be handle after */
1119 static inline int __AVI_ChooseSize( int l1, int l2 )
1121 /* XXX l2 is prefered if 0 otherwise min not equal to 0 */
1126 return( !l1 ? l2 : __MIN( l1,l2 ) );
1129 /* We know we will read chunk align */
1130 static int __AVI_GetAndPutChunkInBuffer( input_thread_t *p_input,
1131 AVIStreamInfo_t *p_info,
1136 pes_packet_t *p_pes;
1139 i_length = __MIN( i_size, BUFFER_MAXSPESSIZE );
1141 /* Skip chunk header */
1143 if( __AVI_GetDataInPES( p_input, &p_pes, i_length + 8,1 ) != i_length +8 )
1147 p_pes->p_first->p_payload_start += 8;
1148 p_pes->i_pes_size -= 8;
1150 i_size = GetDWLE( p_pes->p_first->p_demux_start + 4);
1152 AVI_PESBuffer_Add( p_input->p_method_data,
1157 /* skip unwanted bytes */
1158 if( i_length != i_size)
1160 msg_Err( p_input, "Chunk Size mismatch" );
1161 AVI_SeekAbsolute( p_input,
1162 __EVEN( AVI_TellAbsolute( p_input ) +
1163 i_size - i_length ) );
1168 /* XXX Don't use this function directly ! XXX */
1169 static int __AVI_GetChunk( input_thread_t *p_input,
1170 AVIStreamInfo_t *p_info,
1173 demux_sys_t *p_avi = p_input->p_demux_data;
1174 AVIStreamInfo_t *p_other;
1179 #define p_info_i p_avi->pp_info[i]
1180 while( p_info->p_pes_first )
1182 if( ( p_info->p_pes_first->i_posc == p_info->i_idxposc )
1183 &&( p_info->i_idxposb >= p_info->p_pes_first->i_posb )
1184 &&( p_info->i_idxposb < p_info->p_pes_first->i_posb +
1185 p_info->p_pes_first->p_pes->i_pes_size ) )
1188 return( 1 ); /* we have it in buffer */
1192 AVI_PESBuffer_Drop( p_input->p_method_data, p_info );
1195 /* up to now we handle only one audio and video streams at the same time */
1196 p_other = (p_info == p_avi->p_info_video ) ?
1197 p_avi->p_info_audio : p_avi->p_info_video ;
1199 i_method = __AVI_GetChunkMethod( p_input, p_info, p_other );
1203 /* get directly the good chunk */
1204 return( b_load ? __AVI_SeekAndGetChunk( p_input, p_info ) : 1 );
1207 * because invalid index
1208 * or will find ck_other before ck_info
1210 /* msg_Warn( p_input, "method %d", i_method ); */
1211 /* we will calculate the better position we have to reach */
1215 /* the position max we have already reached */
1216 /* FIXME this isn't the better because sometime will fail to
1217 put in buffer p_other since it could be too far */
1218 AVIStreamInfo_t *p_info_max = p_info;
1220 for( i = 0; i < p_avi->i_streams; i++ )
1222 if( p_info_i->i_idxnb )
1224 if( p_info_max->i_idxnb )
1226 if( p_info_i->p_index[p_info_i->i_idxnb -1 ].i_pos >
1227 p_info_max->p_index[p_info_max->i_idxnb -1 ].i_pos )
1229 p_info_max = p_info_i;
1234 p_info_max = p_info_i;
1238 if( p_info_max->i_idxnb )
1240 /* be carefull that size between index and ck can sometime be
1241 different without any error (and other time it's an error) */
1242 i_posmax = p_info_max->p_index[p_info_max->i_idxnb -1 ].i_pos;
1243 /* so choose this, and I know that we have already reach it */
1247 i_posmax = p_avi->p_movi->i_pos + 12;
1254 return( 1 ); /* all is ok */
1257 /* we know that the entry and the last one are valid for the 2 stream */
1258 /* and ck_other will come *before* index so go directly to it*/
1259 i_posmax = p_other->p_index[p_other->i_idxposc].i_pos;
1262 AVI_SeekAbsolute( p_input, i_posmax );
1263 /* the first chunk we will see is :
1264 * the last chunk that we have already seen for broken index
1265 * the first ck for other with good index */
1266 for( ; ; ) /* infinite parsing until the ck we want */
1271 /* Get the actual chunk in the stream */
1272 if( !(p_ck = RIFF_ReadChunk( p_input )) )
1276 /* msg_Dbg( p_input, "ck: %4.4s len %d", &p_ck->i_id, p_ck->i_size ); */
1277 /* special case for LIST-rec chunk */
1278 if( ( p_ck->i_id == FOURCC_LIST )&&( p_ck->i_type == FOURCC_rec ) )
1280 RIFF_DescendChunk( p_input );
1281 RIFF_DeleteChunk( p_input, p_ck );
1284 AVI_ParseStreamHeader( p_ck->i_id, &i, &i_type );
1285 /* littles checks but not too much if you want to read all file */
1286 if( i >= p_avi->i_streams )
1287 /* (AVI_GetESTypeFromTwoCC(i_type) != p_info_i->i_cat) perhaps add it*/
1290 RIFF_DeleteChunk( p_input, p_ck );
1291 if( RIFF_NextChunk( p_input, p_avi->p_movi ) != 0 )
1300 /* have we found a new entry (not present in index)? */
1301 if( ( !p_info_i->i_idxnb )
1302 ||(p_info_i->p_index[p_info_i->i_idxnb-1].i_pos < p_ck->i_pos))
1304 AVIIndexEntry_t index;
1306 index.i_id = p_ck->i_id;
1307 index.i_flags = AVI_GetKeyFlag( p_info_i->p_es->i_fourcc,
1308 (u8*)&p_ck->i_8bytes);
1309 index.i_pos = p_ck->i_pos;
1310 index.i_length = p_ck->i_size;
1311 __AVI_AddEntryIndex( p_info_i, &index );
1315 /* TODO check if p_other is full and then if is possible
1316 go directly to the good chunk */
1317 if( ( p_info_i == p_other )
1318 &&( !AVI_PESBuffer_IsFull( p_other ) )
1319 &&( ( !p_other->p_pes_last )||
1320 ( p_other->p_pes_last->p_pes->i_pes_size !=
1321 BUFFER_MAXSPESSIZE ) ) )
1323 int i_ck = p_other->p_pes_last ?
1324 p_other->p_pes_last->i_posc + 1 : p_other->i_idxposc;
1325 i_size = __AVI_ChooseSize( p_ck->i_size,
1326 p_other->p_index[i_ck].i_length);
1328 if( p_other->p_index[i_ck].i_pos == p_ck->i_pos )
1330 if( !__AVI_GetAndPutChunkInBuffer( p_input, p_other,
1333 RIFF_DeleteChunk( p_input, p_ck );
1339 if( RIFF_NextChunk( p_input, p_avi->p_movi ) != 0 )
1341 RIFF_DeleteChunk( p_input, p_ck );
1348 RIFF_DeleteChunk( p_input, p_ck );
1351 if( ( p_info_i == p_info)
1352 &&( p_info->i_idxposc < p_info->i_idxnb ) )
1354 /* the first ck_info is ok otherwise it should be
1355 loaded without parsing */
1356 i_size = __AVI_ChooseSize( p_ck->i_size,
1357 p_info->p_index[p_info->i_idxposc].i_length);
1360 RIFF_DeleteChunk( p_input, p_ck );
1362 return( b_load ? __AVI_GetAndPutChunkInBuffer( p_input,
1365 p_info->i_idxposc ) : 1 );
1370 RIFF_DeleteChunk( p_input, p_ck );
1371 if( RIFF_NextChunk( p_input, p_avi->p_movi ) != 0 )
1384 /* be sure that i_ck will be a valid index entry */
1385 static int AVI_SetStreamChunk( input_thread_t *p_input,
1386 AVIStreamInfo_t *p_info,
1390 p_info->i_idxposc = i_ck;
1391 p_info->i_idxposb = 0;
1393 if( i_ck < p_info->i_idxnb )
1399 p_info->i_idxposc = p_info->i_idxnb - 1;
1402 p_info->i_idxposc++;
1403 if( !__AVI_GetChunk( p_input, p_info, 0 ) )
1407 } while( p_info->i_idxposc < i_ck );
1414 /* XXX FIXME up to now, we assume that all chunk are one after one */
1415 static int AVI_SetStreamBytes( input_thread_t *p_input,
1416 AVIStreamInfo_t *p_info,
1419 if( ( p_info->i_idxnb > 0 )
1420 &&( i_byte < p_info->p_index[p_info->i_idxnb - 1].i_lengthtotal +
1421 p_info->p_index[p_info->i_idxnb - 1].i_length ) )
1423 /* index is valid to find the ck */
1424 /* uses dichototmie to be fast enougth */
1425 int i_idxposc = __MIN( p_info->i_idxposc, p_info->i_idxnb - 1 );
1426 int i_idxmax = p_info->i_idxnb;
1430 if( p_info->p_index[i_idxposc].i_lengthtotal > i_byte )
1432 i_idxmax = i_idxposc ;
1433 i_idxposc = ( i_idxmin + i_idxposc ) / 2 ;
1437 if( p_info->p_index[i_idxposc].i_lengthtotal +
1438 p_info->p_index[i_idxposc].i_length <= i_byte)
1440 i_idxmin = i_idxposc ;
1441 i_idxposc = (i_idxmax + i_idxposc ) / 2 ;
1445 p_info->i_idxposc = i_idxposc;
1446 p_info->i_idxposb = i_byte -
1447 p_info->p_index[i_idxposc].i_lengthtotal;
1456 p_info->i_idxposc = p_info->i_idxnb - 1;
1457 p_info->i_idxposb = 0;
1460 p_info->i_idxposc++;
1461 if( !__AVI_GetChunk( p_input, p_info, 0 ) )
1465 } while( p_info->p_index[p_info->i_idxposc].i_lengthtotal +
1466 p_info->p_index[p_info->i_idxposc].i_length <= i_byte );
1468 p_info->i_idxposb = i_byte -
1469 p_info->p_index[p_info->i_idxposc].i_lengthtotal;
1474 static pes_packet_t *AVI_ReadStreamChunkInPES( input_thread_t *p_input,
1475 AVIStreamInfo_t *p_info )
1478 if( p_info->i_idxposc > p_info->i_idxnb )
1483 /* we want chunk (p_info->i_idxposc,0) */
1484 p_info->i_idxposb = 0;
1485 if( !__AVI_GetChunk( p_input, p_info, 1) )
1487 msg_Err( p_input, "Got one chunk : failed" );
1490 p_info->i_idxposc++;
1491 return( AVI_PESBuffer_Get( p_info ) );
1494 static pes_packet_t *AVI_ReadStreamBytesInPES( input_thread_t *p_input,
1495 AVIStreamInfo_t *p_info,
1498 pes_packet_t *p_pes;
1499 data_packet_t *p_data;
1504 if( !( p_pes = input_NewPES( p_input->p_method_data ) ) )
1508 if( !( p_data = input_NewPacket( p_input->p_method_data, i_byte ) ) )
1510 input_DeletePES( p_input->p_method_data, p_pes );
1515 p_pes->p_last = p_data;
1516 p_pes->i_nb_data = 1;
1517 p_pes->i_pes_size = i_byte;
1521 if( !__AVI_GetChunk( p_input, p_info, 1) )
1523 msg_Err( p_input, "Got one chunk : failed" );
1525 input_DeletePES( p_input->p_method_data, p_pes );
1529 i_read = __MIN( p_info->p_pes_first->p_pes->i_pes_size -
1530 ( p_info->i_idxposb - p_info->p_pes_first->i_posb ),
1532 /* FIXME FIXME FIXME follow all data packet */
1533 memcpy( p_data->p_payload_start + i_count,
1534 p_info->p_pes_first->p_pes->p_first->p_payload_start +
1535 p_info->i_idxposb - p_info->p_pes_first->i_posb,
1538 AVI_PESBuffer_Drop( p_input->p_method_data, p_info );
1542 p_info->i_idxposb += i_read;
1543 if( p_info->p_index[p_info->i_idxposc].i_length <= p_info->i_idxposb )
1545 p_info->i_idxposb -= p_info->p_index[p_info->i_idxposc].i_length;
1546 p_info->i_idxposc++;
1554 /* try to realign after a seek */
1555 static int AVI_ReAlign( input_thread_t *p_input,
1556 AVIStreamInfo_t *p_info )
1561 demux_sys_t *p_avi = p_input->p_demux_data;
1564 for( i = 0; i < p_avi->i_streams; i++ )
1566 AVI_PESBuffer_Flush( p_input->p_method_data, p_avi->pp_info[i] );
1569 TODO use input_ClockInit instead but need to be exported
1570 p_input->stream.p_selected_program->last_cr = 0;
1571 p_input->stream.p_selected_program->last_syscr = 0;
1572 p_input->stream.p_selected_program->cr_ref = 0;
1573 p_input->stream.p_selected_program->sysdate_ref = 0;
1574 p_input->stream.p_selected_program->delta_cr = 0;
1575 p_input->stream.p_selected_program->c_average_count = 0; */
1577 i_pos = AVI_TellAbsolute( p_input );
1579 p_info->i_idxposc--; /* in fact p_info->i_idxposc is for ck to be read */
1582 if( ( p_info->i_idxposc <= 0)
1583 ||( i_pos <= p_info->p_index[0].i_pos ) )
1585 /* before beginning of stream */
1586 return( p_info->header.i_samplesize ?
1587 AVI_SetStreamBytes( p_input, p_info, 0 ) :
1588 AVI_SetStreamChunk( p_input, p_info, 0 ) );
1591 b_after = ( i_pos >= p_info->p_index[p_info->i_idxposc].i_pos );
1592 /* now find in what chunk we are */
1593 while( ( i_pos < p_info->p_index[p_info->i_idxposc].i_pos )
1594 &&( p_info->i_idxposc > 0 ) )
1596 /* search before i_idxposc */
1598 if( !AVI_SetStreamChunk( p_input, p_info, p_info->i_idxposc - 1 ) )
1604 while( i_pos >= p_info->p_index[p_info->i_idxposc].i_pos +
1605 p_info->p_index[p_info->i_idxposc].i_length + 8 )
1607 /* search after i_idxposc */
1609 if( !AVI_SetStreamChunk( p_input, p_info, p_info->i_idxposc + 1 ) )
1615 /* search nearest key frame, only for video */
1616 if( p_info->i_cat == VIDEO_ES )
1620 while(!(p_info->p_index[p_info->i_idxposc].i_flags&AVIIF_KEYFRAME) )
1622 if( !AVI_SetStreamChunk( p_input, p_info,
1623 p_info->i_idxposc + 1 ) )
1631 while( ( p_info->i_idxposc > 0 ) &&
1632 (!(p_info->p_index[p_info->i_idxposc].i_flags&AVIIF_KEYFRAME)) )
1635 if( !AVI_SetStreamChunk( p_input, p_info,
1636 p_info->i_idxposc - 1 ) )
1647 /* make difference between audio and video pts as little as possible */
1648 static void AVI_SynchroReInit( input_thread_t *p_input )
1650 demux_sys_t *p_avi = p_input->p_demux_data;
1652 #define p_info_video p_avi->p_info_video
1653 #define p_info_audio p_avi->p_info_audio
1654 if( ( !p_info_audio )||( !p_info_video ) )
1658 /* now resynch audio video video */
1659 /*don't care of AVIF_KEYFRAME */
1660 if( !p_info_audio->header.i_samplesize )
1662 AVI_SetStreamChunk( p_input,
1664 AVI_PTSToChunk( p_info_audio,
1665 AVI_GetPTS( p_info_video ) ) );
1669 AVI_SetStreamBytes( p_input,
1671 AVI_PTSToByte( p_info_audio,
1672 AVI_GetPTS( p_info_video ) ) );
1678 /*****************************************************************************
1679 * AVI_GetFrameInPES : get dpts length(µs) in pes from stream
1680 *****************************************************************************
1681 * Handle multiple pes, and set pts to the good value
1682 *****************************************************************************/
1683 static pes_packet_t *AVI_GetFrameInPES( input_thread_t *p_input,
1684 AVIStreamInfo_t *p_info,
1688 pes_packet_t *p_pes = NULL;
1689 pes_packet_t *p_pes_tmp = NULL;
1690 pes_packet_t *p_pes_first = NULL;
1698 if( !p_info->header.i_samplesize )
1700 int i_chunk = __MAX( AVI_PTSToChunk( p_info, i_dpts), 1 );
1702 for( i = 0; i < i_chunk; i++ )
1704 /* get pts while is valid */
1705 i_pts = AVI_GetPTS( p_info );
1707 p_pes_tmp = AVI_ReadStreamChunkInPES( p_input, p_info );
1711 return( p_pes_first );
1713 p_pes_tmp->i_pts = i_pts;
1716 p_pes_first = p_pes_tmp;
1720 p_pes->p_next = p_pes_tmp;
1724 return( p_pes_first );
1728 /* stream is byte based */
1729 int i_byte = AVI_PTSToByte( p_info, i_dpts);
1730 if( i_byte < 50 ) /* to avoid some problem with audio */
1734 i_pts = AVI_GetPTS( p_info ); /* ok even with broken index */
1735 p_pes = AVI_ReadStreamBytesInPES( p_input, p_info, i_byte);
1739 p_pes->i_pts = i_pts;
1744 /*****************************************************************************
1745 * AVI_DecodePES : send a pes to decoder
1746 *****************************************************************************
1747 * Handle multiple pes, and update pts to the good value
1748 *****************************************************************************/
1749 static inline void AVI_DecodePES( input_thread_t *p_input,
1750 AVIStreamInfo_t *p_info,
1751 pes_packet_t *p_pes )
1753 pes_packet_t *p_pes_next;
1754 /* input_decode want only one pes, but AVI_GetFrameInPES give
1755 multiple pes so send one by one */
1758 p_pes_next = p_pes->p_next;
1759 p_pes->p_next = NULL;
1760 p_pes->i_pts = input_ClockGetTS( p_input,
1761 p_input->stream.p_selected_program,
1762 p_pes->i_pts * 9/100);
1763 input_DecodePES( p_info->p_es->p_decoder_fifo, p_pes );
1769 /*****************************************************************************
1770 * AVIDemux_Seekable: reads and demuxes data packets for stream seekable
1771 *****************************************************************************
1772 * Called by AVIDemux, that make common work
1773 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
1774 *****************************************************************************/
1775 static int AVIDemux_Seekable( input_thread_t *p_input,
1776 AVIStreamInfo_t *p_info_master,
1777 AVIStreamInfo_t *p_info_slave )
1779 demux_sys_t *p_avi = p_input->p_demux_data;
1781 pes_packet_t *p_pes_master;
1782 pes_packet_t *p_pes_slave;
1784 /* check for signal from interface */
1785 if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
1787 /* we can supposed that is a seek */
1788 /* first wait for empty buffer, arbitrary time */
1789 msleep( DEFAULT_PTS_DELAY );
1790 /* then try to realign in stream */
1791 if( !AVI_ReAlign( p_input, p_info_master ) )
1793 return( 0 ); /* assume EOF */
1795 AVI_SynchroReInit( p_input );
1798 /* take care of newly selected audio ES */
1799 if( p_info_master->b_selected )
1801 p_info_master->b_selected = 0;
1802 AVI_SynchroReInit( p_input );
1804 if( ( p_info_slave )&&( p_info_slave->b_selected ) )
1806 p_info_slave->b_selected = 0;
1807 AVI_SynchroReInit( p_input );
1810 /* wait for the good time */
1811 input_ClockManageRef( p_input,
1812 p_input->stream.p_selected_program,
1813 p_avi->i_pcr /*- DEFAULT_PTS_DELAY / 2 */);
1814 /* calculate pcr, time when we must read the next data */
1815 /* 9/100 kludge ->need to convert to 1/1000000 clock unit to 1/90000 */
1818 p_avi->i_pcr = __MIN( AVI_GetPTS( p_info_master ),
1819 AVI_GetPTS( p_info_slave ) ) * 9/100;
1823 p_avi->i_pcr = AVI_GetPTS( p_info_master ) * 9/100;
1826 /* get video and audio frames */
1827 p_pes_master = AVI_GetFrameInPES( p_input,
1829 100000 ); /* 100 ms */
1830 AVI_DecodePES( p_input,
1837 p_pes_slave = AVI_GetFrameInPES( p_input,
1839 AVI_GetPTS( p_info_master ) -
1840 AVI_GetPTS( p_info_slave) );
1841 AVI_DecodePES( p_input,
1848 return( p_pes_master ? 1 : 0 );
1852 /*****************************************************************************
1853 * AVIDemux_NotSeekable: reads and demuxes data packets for stream seekable
1854 *****************************************************************************
1855 * Called by AVIDemux, that makes common work
1856 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
1857 *****************************************************************************/
1859 /* 0 if can be load/updated, 1 if skip, 2 if descend into, 3 if exit, 4 if error and need recover */
1860 static int __AVIDemux_ChunkAction( int i_streams_max,
1866 AVI_ParseStreamHeader( p_ck->i_id, &i_stream, &i_type );
1867 if( i_stream < i_streams_max )
1869 return( 0 ); /* read and/or update stream info */
1872 if( i_stream <= 99 )
1874 /* should not happen but ... */
1878 /* now we know that it's not a stream */
1880 switch( p_ck->i_id )
1882 case( FOURCC_JUNK ):
1884 case( FOURCC_idx1 ):
1886 case( FOURCC_LIST ):
1887 if( p_ck->i_type == FOURCC_rec )
1900 if( ( p_ck->i_id & 0xFFFF ) == VLC_TWOCC( 'i','x' ) )
1908 static int AVI_NotSeekableRecover( input_thread_t *p_input )
1912 int i_number, i_type;
1913 data_packet_t *p_pack;
1917 if( input_Peek( p_input, &p_id, 4 ) < 4 )
1919 return( 0 ); /* Failed */
1921 i_id = GetDWLE( p_id );
1924 case( FOURCC_idx1 ):
1925 case( FOURCC_JUNK ):
1926 case( FOURCC_LIST ):
1929 AVI_ParseStreamHeader( i_id, &i_number, &i_type );
1930 if( i_number <= 99 )
1946 /* Read 1 byte VERY unoptimised */
1947 if( input_SplitBuffer( p_input, &p_pack, 1) < 1 )
1951 input_DeletePacket( p_input->p_method_data, p_pack);
1956 static int AVIDemux_NotSeekable( input_thread_t *p_input,
1957 AVIStreamInfo_t *p_info_master,
1958 AVIStreamInfo_t *p_info_slave )
1960 demux_sys_t *p_avi = p_input->p_demux_data;
1966 pes_packet_t *p_pes;
1969 i_filepos = AVI_TellAbsolute( p_input );
1970 p_input->pf_seek( p_input, i_filepos );
1971 input_AccessReinit( p_input );
1974 #define p_info p_avi->pp_info[i_stream]
1976 /* The managment is very basic, we will read packets, caclulate pts
1977 and send it to decoder, synchro made on video, and audio is very less
1980 /* wait the good time */
1981 input_ClockManageRef( p_input,
1982 p_input->stream.p_selected_program,
1983 p_avi->i_pcr /*- DEFAULT_PTS_DELAY / 2 */);
1984 /* TODO be smart, seeing if we can wait for min( audio, video )
1985 or there is a too big deep */
1988 p_avi->i_pcr = AVI_GetPTS( p_info_master ) * 9/100;
1992 p_avi->i_pcr = __MIN( AVI_GetPTS( p_info_master ),
1993 AVI_GetPTS( p_info_slave ) ) * 9/100;
1994 p_avi->i_pcr = AVI_GetPTS( p_info_master ) * 9/100;
1997 for( i_loop = 0; i_loop < 10; i_loop++ )
2001 /* first find a ck for master or slave */
2005 if( !(p_ck = RIFF_ReadChunk( p_input ) ) )
2007 msg_Err( p_input, "Badd" );
2008 return( 0 ); /* assume EOF */
2010 /*msg_Err( p_input,"Looking ck: %4.4s %d",&p_ck->i_id, p_ck->i_size );*/
2012 switch( __AVIDemux_ChunkAction( p_avi->i_streams, p_ck ) )
2014 case( 0 ): /* load it if possible */
2017 case( 1 ): /* skip it */
2018 RIFF_DeleteChunk( p_input, p_ck );
2019 if( RIFF_NextChunk( p_input, p_avi->p_movi ) != 0 )
2025 case( 2 ): /* descend into */
2026 RIFF_DeleteChunk( p_input, p_ck );
2027 RIFF_DescendChunk( p_input );
2030 case( 3 ): /* exit */
2031 RIFF_DeleteChunk( p_input, p_ck );
2033 case( 4 ): /* Error */
2034 RIFF_DeleteChunk( p_input, p_ck );
2035 msg_Warn( p_input, "unknown chunk id 0x%8.8x, trying to recover", p_ck->i_id );
2036 if( !AVI_NotSeekableRecover( p_input ) )
2038 msg_Err( p_input, "cannot recover, dying" );
2043 msg_Warn( p_input, "recovered sucessfully" );
2051 AVI_ParseStreamHeader( p_ck->i_id, &i_stream, &i_type );
2052 /* now check if we really have to load it */
2053 if( ( p_info != p_info_master )&&( p_info != p_info_slave ) )
2059 if( p_info == p_info_master )
2066 i_dpts = AVI_GetPTS( p_info_slave ) -
2067 AVI_GetPTS( p_info_master );
2068 if( i_dpts < 0 ) {i_dpts = - i_dpts; }
2069 if( i_dpts < 600000 )
2081 /* now do we can load this chunk ? */
2085 if( __AVI_GetDataInPES( p_input, &p_pes, p_ck->i_size + 8, 1) != p_ck->i_size + 8)
2089 p_pes->p_first->p_payload_start += 8;
2090 p_pes->i_pes_size -= 8;
2092 p_pes->i_pts = AVI_GetPTS( p_info );
2093 AVI_DecodePES( p_input, p_info, p_pes );
2098 if( RIFF_NextChunk( p_input, p_avi->p_movi ) != 0 )
2100 RIFF_DeleteChunk( p_input, p_ck );
2105 /* finaly update stream information */
2106 if( p_info->header.i_samplesize )
2108 p_info->i_idxposb += p_ck->i_size;
2112 p_info->i_idxposc++;
2115 RIFF_DeleteChunk( p_input, p_ck );
2121 /*****************************************************************************
2122 * AVIDemux: reads and demuxes data packets
2123 *****************************************************************************
2124 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
2125 * TODO add support for unstreable file, just read a chunk and send it
2126 * to the right decoder, very easy
2127 *****************************************************************************/
2129 static int AVIDemux( input_thread_t *p_input )
2132 AVIStreamInfo_t *p_info_master;
2133 AVIStreamInfo_t *p_info_slave;
2135 demux_sys_t *p_avi = p_input->p_demux_data;
2137 /* search new video and audio stream selected
2138 if current have been unselected*/
2139 if( ( !p_avi->p_info_video )
2140 || ( !p_avi->p_info_video->p_es->p_decoder_fifo ) )
2142 p_avi->p_info_video = NULL;
2143 for( i = 0; i < p_avi->i_streams; i++ )
2145 if( ( p_avi->pp_info[i]->i_cat == VIDEO_ES )
2146 &&( p_avi->pp_info[i]->p_es->p_decoder_fifo ) )
2148 p_avi->p_info_video = p_avi->pp_info[i];
2149 p_avi->p_info_video->b_selected = 1;
2154 if( ( !p_avi->p_info_audio )
2155 ||( !p_avi->p_info_audio->p_es->p_decoder_fifo ) )
2157 p_avi->p_info_audio = NULL;
2158 for( i = 0; i < p_avi->i_streams; i++ )
2160 if( ( p_avi->pp_info[i]->i_cat == AUDIO_ES )
2161 &&( p_avi->pp_info[i]->p_es->p_decoder_fifo ) )
2163 p_avi->p_info_audio = p_avi->pp_info[i];
2164 p_avi->p_info_audio->b_selected = 1;
2169 /* by default video is master for resync audio (after a seek .. ) */
2170 if( p_avi->p_info_video )
2172 p_info_master = p_avi->p_info_video;
2173 p_info_slave = p_avi->p_info_audio;
2177 p_info_master = p_avi->p_info_audio;
2178 p_info_slave = NULL;
2181 if( !p_info_master )
2183 msg_Err( p_input, "no stream selected" );
2187 /* manage rate, if not default: skeep audio */
2188 vlc_mutex_lock( &p_input->stream.stream_lock );
2189 if( p_input->stream.control.i_rate != p_avi->i_rate )
2191 if( p_avi->p_info_audio)
2193 p_avi->p_info_audio->b_selected = 1;
2195 p_avi->i_rate = p_input->stream.control.i_rate;
2197 vlc_mutex_unlock( &p_input->stream.stream_lock );
2198 p_avi->i_rate = DEFAULT_RATE;
2199 if( p_avi->i_rate != DEFAULT_RATE )
2201 p_info_slave = NULL;
2204 if( p_avi->b_seekable )
2206 return( AVIDemux_Seekable( p_input,
2212 return( AVIDemux_NotSeekable( p_input,