1 /*****************************************************************************
2 * avi.c : AVI file Stream input module for vlc
3 *****************************************************************************
4 * Copyright (C) 2001 VideoLAN
5 * $Id: avi.c,v 1.18 2002/05/17 15:47:01 fenrir Exp $
6 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
21 *****************************************************************************/
23 /*****************************************************************************
25 *****************************************************************************/
26 #include <stdlib.h> /* malloc(), free() */
27 #include <string.h> /* strdup() */
29 #include <sys/types.h>
31 #include <videolan/vlc.h>
33 #include "stream_control.h"
34 #include "input_ext-intf.h"
35 #include "input_ext-dec.h"
36 #include "input_ext-plugins.h"
40 /*****************************************************************************
42 *****************************************************************************/
44 /*****************************************************************************
46 *****************************************************************************/
47 static void input_getfunctions( function_list_t * p_function_list );
48 static int AVIDemux ( struct input_thread_s * );
49 static int AVIInit ( struct input_thread_s * );
50 static void AVIEnd ( struct input_thread_s * );
52 /*****************************************************************************
53 * Build configuration tree.
54 *****************************************************************************/
59 SET_DESCRIPTION( "RIFF-AVI Stream input" )
60 ADD_CAPABILITY( DEMUX, 150 )
65 input_getfunctions( &p_module->p_functions->demux );
68 MODULE_DEACTIVATE_START
69 MODULE_DEACTIVATE_STOP
71 /*****************************************************************************
72 * Definition of structures and libraries for this plugins
73 *****************************************************************************/
75 #include "libioRIFF.c"
78 /*****************************************************************************
79 * Functions exported as capabilities. They are declared as static so that
80 * we don't pollute the namespace too much.
81 *****************************************************************************/
82 static void input_getfunctions( function_list_t * p_function_list )
84 #define input p_function_list->functions.demux
85 input.pf_init = AVIInit;
86 input.pf_end = AVIEnd;
87 input.pf_demux = AVIDemux;
88 input.pf_rewind = NULL;
92 /********************************************************************/
95 static void __AVIFreeDemuxData( input_thread_t *p_input )
98 demux_data_avi_file_t *p_avi_demux;
99 p_avi_demux = (demux_data_avi_file_t*)p_input->p_demux_data ;
101 if( p_avi_demux->p_riff != NULL )
102 RIFF_DeleteChunk( p_input, p_avi_demux->p_riff );
103 if( p_avi_demux->p_hdrl != NULL )
104 RIFF_DeleteChunk( p_input, p_avi_demux->p_hdrl );
105 if( p_avi_demux->p_movi != NULL )
106 RIFF_DeleteChunk( p_input, p_avi_demux->p_movi );
107 if( p_avi_demux->p_idx1 != NULL )
108 RIFF_DeleteChunk( p_input, p_avi_demux->p_idx1 );
109 if( p_avi_demux->pp_info != NULL )
111 for( i = 0; i < p_avi_demux->i_streams; i++ )
113 if( p_avi_demux->pp_info[i] != NULL )
115 if( p_avi_demux->pp_info[i]->p_index != NULL )
117 free( p_avi_demux->pp_info[i]->p_index );
119 free( p_avi_demux->pp_info[i] );
122 free( p_avi_demux->pp_info );
126 static void __AVI_Parse_avih( MainAVIHeader_t *p_avih, byte_t *p_buff )
128 p_avih->i_microsecperframe = __GetDoubleWordLittleEndianFromBuff( p_buff );
129 p_avih->i_maxbytespersec = __GetDoubleWordLittleEndianFromBuff( p_buff + 4);
130 p_avih->i_reserved1 = __GetDoubleWordLittleEndianFromBuff( p_buff + 8);
131 p_avih->i_flags = __GetDoubleWordLittleEndianFromBuff( p_buff + 12);
132 p_avih->i_totalframes = __GetDoubleWordLittleEndianFromBuff( p_buff + 16);
133 p_avih->i_initialframes = __GetDoubleWordLittleEndianFromBuff( p_buff + 20);
134 p_avih->i_streams = __GetDoubleWordLittleEndianFromBuff( p_buff + 24);
135 p_avih->i_suggestedbuffersize =
136 __GetDoubleWordLittleEndianFromBuff( p_buff + 28);
137 p_avih->i_width = __GetDoubleWordLittleEndianFromBuff( p_buff + 32 );
138 p_avih->i_height = __GetDoubleWordLittleEndianFromBuff( p_buff + 36 );
139 p_avih->i_scale = __GetDoubleWordLittleEndianFromBuff( p_buff + 40 );
140 p_avih->i_rate = __GetDoubleWordLittleEndianFromBuff( p_buff + 44 );
141 p_avih->i_start = __GetDoubleWordLittleEndianFromBuff( p_buff + 48);
142 p_avih->i_length = __GetDoubleWordLittleEndianFromBuff( p_buff + 52);
145 static void __AVI_Parse_Header( AVIStreamHeader_t *p_strh, byte_t *p_buff )
147 p_strh->i_type = __GetDoubleWordLittleEndianFromBuff( p_buff );
148 p_strh->i_handler = __GetDoubleWordLittleEndianFromBuff( p_buff + 4 );
149 p_strh->i_flags = __GetDoubleWordLittleEndianFromBuff( p_buff + 8 );
150 p_strh->i_reserved1 = __GetDoubleWordLittleEndianFromBuff( p_buff + 12);
151 p_strh->i_initialframes = __GetDoubleWordLittleEndianFromBuff( p_buff + 16);
152 p_strh->i_scale = __GetDoubleWordLittleEndianFromBuff( p_buff + 20);
153 p_strh->i_rate = __GetDoubleWordLittleEndianFromBuff( p_buff + 24);
154 p_strh->i_start = __GetDoubleWordLittleEndianFromBuff( p_buff + 28);
155 p_strh->i_length = __GetDoubleWordLittleEndianFromBuff( p_buff + 32);
156 p_strh->i_suggestedbuffersize =
157 __GetDoubleWordLittleEndianFromBuff( p_buff + 36);
158 p_strh->i_quality = __GetDoubleWordLittleEndianFromBuff( p_buff + 40);
159 p_strh->i_samplesize = __GetDoubleWordLittleEndianFromBuff( p_buff + 44);
162 int avi_ParseBitMapInfoHeader( bitmapinfoheader_t *h, byte_t *p_data )
164 h->i_size = __GetDoubleWordLittleEndianFromBuff( p_data );
165 h->i_width = __GetDoubleWordLittleEndianFromBuff( p_data + 4 );
166 h->i_height = __GetDoubleWordLittleEndianFromBuff( p_data + 8 );
167 h->i_planes = __GetWordLittleEndianFromBuff( p_data + 12 );
168 h->i_bitcount = __GetWordLittleEndianFromBuff( p_data + 14 );
169 h->i_compression = __GetDoubleWordLittleEndianFromBuff( p_data + 16 );
170 h->i_sizeimage = __GetDoubleWordLittleEndianFromBuff( p_data + 20 );
171 h->i_xpelspermeter = __GetDoubleWordLittleEndianFromBuff( p_data + 24 );
172 h->i_ypelspermeter = __GetDoubleWordLittleEndianFromBuff( p_data + 28 );
173 h->i_clrused = __GetDoubleWordLittleEndianFromBuff( p_data + 32 );
174 h->i_clrimportant = __GetDoubleWordLittleEndianFromBuff( p_data + 36 );
178 int avi_ParseWaveFormatEx( waveformatex_t *h, byte_t *p_data )
180 h->i_formattag = __GetWordLittleEndianFromBuff( p_data );
181 h->i_channels = __GetWordLittleEndianFromBuff( p_data + 2 );
182 h->i_samplespersec = __GetDoubleWordLittleEndianFromBuff( p_data + 4 );
183 h->i_avgbytespersec= __GetDoubleWordLittleEndianFromBuff( p_data + 8 );
184 h->i_blockalign = __GetWordLittleEndianFromBuff( p_data + 12 );
185 h->i_bitspersample = __GetWordLittleEndianFromBuff( p_data + 14 );
186 h->i_size = __GetWordLittleEndianFromBuff( p_data + 16 );
190 static __inline__ int __AVIGetESTypeFromTwoCC( u16 i_type )
200 return( UNKNOWN_ES );
204 static int __AVI_ParseStreamHeader( u32 i_id, int *i_number, u16 *i_type )
208 c1 = ( i_id ) & 0xFF;
209 c2 = ( i_id >> 8 ) & 0xFF;
210 c3 = ( i_id >> 16 ) & 0xFF;
211 c4 = ( i_id >> 24 ) & 0xFF;
213 if( c1 < '0' || c1 > '9' || c2 < '0' || c2 > '9' )
217 *i_number = (c1 - '0') * 10 + (c2 - '0' );
218 *i_type = ( c4 << 8) + c3;
222 static void __AVI_AddEntryIndex( AVIStreamInfo_t *p_info,
223 AVIIndexEntry_t *p_index)
225 AVIIndexEntry_t *p_tmp;
226 if( p_info->p_index == NULL )
228 p_info->i_idxmax = 16384;
230 p_info->p_index = calloc( p_info->i_idxmax,
231 sizeof( AVIIndexEntry_t ) );
232 if( p_info->p_index == NULL ) {return;}
234 if( p_info->i_idxnb >= p_info->i_idxmax )
236 p_info->i_idxmax += 16384;
237 p_tmp = realloc( (void*)p_info->p_index,
239 sizeof( AVIIndexEntry_t ) );
242 p_info->i_idxmax -= 16384;
245 p_info->p_index = p_tmp;
247 /* calculate cumulate length */
248 if( p_info->i_idxnb > 0 )
250 p_index->i_lengthtotal = p_info->p_index[p_info->i_idxnb-1].i_length +
251 p_info->p_index[p_info->i_idxnb-1].i_lengthtotal;
255 p_index->i_lengthtotal = 0;
258 p_info->p_index[p_info->i_idxnb] = *p_index;
262 static void __AVI_GetIndex( input_thread_t *p_input )
264 AVIIndexEntry_t index;
271 int i_totalentry = 0;
272 demux_data_avi_file_t *p_avi_demux =
273 (demux_data_avi_file_t*)p_input->p_demux_data ;
275 if( RIFF_FindAndGotoDataChunk( p_input,
280 intf_WarnMsg( 1, "input init: cannot find index" );
281 RIFF_GoToChunk( p_input, p_avi_demux->p_hdrl );
284 p_avi_demux->p_idx1 = p_idx1;
285 intf_WarnMsg( 1, "input init: loading index" );
288 i_read = __MIN( 16*1024, p_idx1->i_size - i_totalentry *16);
289 if( ((i_read = input_Peek( p_input, &p_buff, i_read )) < 16 )
290 ||( i_totalentry *16 >= p_idx1->i_size ) )
292 intf_WarnMsg( 1,"input info: read %d idx entries", i_totalentry );
296 for( i = 0; i < i_read; i++ )
298 byte_t *p_peek = p_buff + i * 16;
300 index.i_id = __GetDoubleWordLittleEndianFromBuff( p_peek );
301 index.i_flags = __GetDoubleWordLittleEndianFromBuff( p_peek+4);
302 index.i_pos = __GetDoubleWordLittleEndianFromBuff( p_peek+8);
303 index.i_length = __GetDoubleWordLittleEndianFromBuff(p_peek+12);
305 if( (__AVI_ParseStreamHeader( index.i_id, &i_number, &i_type ) == 0)
306 &&(i_number < p_avi_demux->i_streams )
307 &&(p_avi_demux->pp_info[i_number]->i_cat ==
308 __AVIGetESTypeFromTwoCC( i_type )))
310 __AVI_AddEntryIndex( p_avi_demux->pp_info[i_number],
314 __RIFF_SkipBytes( p_input, 16 * i_read );
318 static int __AVI_SeekToChunk( input_thread_t *p_input, AVIStreamInfo_t *p_info )
320 if( (p_info->p_index )&&(p_info->i_idxposc < p_info->i_idxnb) )
322 p_input->pf_seek( p_input,
323 (off_t)p_info->p_index[p_info->i_idxposc].i_pos);
324 input_AccessReinit( p_input );
327 /* no index can't arrive but ...*/
328 intf_WarnMsg( 1, "input error: can't seek");
333 /* XXX call after get p_movi */
334 static void __AVI_UpdateIndexOffset( input_thread_t *p_input )
337 int b_start = 1;/* if index pos is based on start of file or not (p_movi) */
338 demux_data_avi_file_t *p_avi_demux =
339 (demux_data_avi_file_t*)p_input->p_demux_data;
341 /* FIXME some work to do :
342 * test in the ile if it's true, if not do a RIFF_Find...
344 #define p_info p_avi_demux->pp_info[i_stream]
345 for( i_stream = 0; i_stream < p_avi_demux->i_streams; i_stream++ )
347 if( ( p_info->p_index )
348 && ( p_info->p_index[0].i_pos < p_avi_demux->p_movi->i_pos + 8 ))
356 for( i_stream = 0; i_stream < p_avi_demux->i_streams; i_stream++ )
359 if( p_info->p_index )
361 for( i = 0; i < p_info->i_idxnb; i++ )
363 p_info->p_index[i].i_pos +=
364 p_avi_demux->p_movi->i_pos + 8;
372 static int __AVI_AudioGetType( u32 i_type )
376 /* case( WAVE_FORMAT_PCM ):
377 return( WAVE_AUDIO_ES ); */
378 case( WAVE_FORMAT_AC3 ):
379 return( AC3_AUDIO_ES );
380 case( WAVE_FORMAT_MPEG):
381 case( WAVE_FORMAT_MPEGLAYER3):
382 return( MPEG2_AUDIO_ES ); /* 2 for mpeg-2 layer 1 2 ou 3 */
388 static int __AVI_VideoGetType( u32 i_type )
392 /* FIXME FIXME : what are the correct tag for msmpeg4 v1 */
399 return( MSMPEG4v2_VIDEO_ES );
415 return( MSMPEG4v3_VIDEO_ES );
432 return( MPEG4_VIDEO_ES );
439 /*****************************************************************************
440 * AVIInit: check file and initializes AVI structures
441 *****************************************************************************/
442 static int AVIInit( input_thread_t *p_input )
444 riffchunk_t *p_riff,*p_hdrl,*p_movi;
446 riffchunk_t *p_strl,*p_strh,*p_strf;
447 demux_data_avi_file_t *p_avi_demux;
448 es_descriptor_t *p_es = NULL; /* for not warning */
452 /* we need to seek to be able to readcorrectly */
453 if( !p_input->stream.b_seekable )
455 intf_WarnMsg( 2,"input: RIFF-AVI plug-in discarded (no seekable)" );
458 p_input->p_demux_data =
459 p_avi_demux = malloc( sizeof(demux_data_avi_file_t) );
460 if( p_avi_demux == NULL )
462 intf_ErrMsg( "input error: not enough memory" );
465 memset( p_avi_demux, 0, sizeof( demux_data_avi_file_t ) );
466 p_avi_demux->i_rate = DEFAULT_RATE;
467 /* FIXME I don't know what it's do, copied from ESInit */
468 /* Initialize access plug-in structures. */
469 if( p_input->i_mtu == 0 )
472 p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
475 if( RIFF_TestFileHeader( p_input, &p_riff, FOURCC_AVI ) != 0 )
477 __AVIFreeDemuxData( p_input );
478 intf_WarnMsg( 2,"input: RIFF-AVI plug-in discarded (avi_file)" );
481 p_avi_demux->p_riff = p_riff;
483 if ( RIFF_DescendChunk(p_input) != 0 )
485 __AVIFreeDemuxData( p_input );
486 intf_ErrMsg( "input error: cannot look for subchunk (avi_file)" );
490 /* it's a riff-avi file, so search for LIST-hdrl */
491 if( RIFF_FindListChunk(p_input ,&p_hdrl,p_riff, FOURCC_hdrl) != 0 )
493 __AVIFreeDemuxData( p_input );
494 intf_ErrMsg( "input error: cannot find \"LIST-hdrl\" (avi_file)" );
497 p_avi_demux->p_hdrl = p_hdrl;
499 if( RIFF_DescendChunk(p_input) != 0 )
501 __AVIFreeDemuxData( p_input );
502 intf_ErrMsg( "input error: cannot look for subchunk (avi_file)" );
505 /* in LIST-hdrl search avih */
506 if( RIFF_FindAndLoadChunk( p_input, p_hdrl,
507 &p_avih, FOURCC_avih ) != 0 )
509 __AVIFreeDemuxData( p_input );
510 intf_ErrMsg( "input error: cannot find \"avih\" chunk (avi_file)" );
513 __AVI_Parse_avih( &p_avi_demux->avih, p_avih->p_data->p_payload_start );
514 RIFF_DeleteChunk( p_input, p_avih );
516 if( p_avi_demux->avih.i_streams == 0 )
517 /* no stream found, perhaps it would be cool to find it */
519 __AVIFreeDemuxData( p_input );
520 intf_ErrMsg( "input error: no defined stream !" );
524 /* create one program */
525 vlc_mutex_lock( &p_input->stream.stream_lock );
526 if( input_InitStream( p_input, 0 ) == -1)
528 vlc_mutex_unlock( &p_input->stream.stream_lock );
529 __AVIFreeDemuxData( p_input );
530 intf_ErrMsg( "input error: cannot init stream" );
533 if( input_AddProgram( p_input, 0, 0) == NULL )
535 vlc_mutex_unlock( &p_input->stream.stream_lock );
536 __AVIFreeDemuxData( p_input );
537 intf_ErrMsg( "input error: cannot add program" );
540 p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
541 p_input->stream.p_new_program = p_input->stream.pp_programs[0] ;
542 p_input->stream.i_mux_rate = p_avi_demux->avih.i_maxbytespersec / 50;
543 vlc_mutex_unlock( &p_input->stream.stream_lock );
545 /* now read info on each stream and create ES */
546 p_avi_demux->i_streams = p_avi_demux->avih.i_streams;
548 p_avi_demux->pp_info = calloc( p_avi_demux->i_streams,
549 sizeof( AVIStreamInfo_t* ) );
550 memset( p_avi_demux->pp_info, 0,
551 sizeof( AVIStreamInfo_t* ) * p_avi_demux->i_streams );
553 for( i = 0 ; i < p_avi_demux->i_streams; i++ )
555 #define p_info p_avi_demux->pp_info[i]
556 p_info = malloc( sizeof(AVIStreamInfo_t ) );
557 memset( p_info, 0, sizeof( AVIStreamInfo_t ) );
559 if( ( RIFF_FindListChunk(p_input,
560 &p_strl,p_hdrl, FOURCC_strl) != 0 )
561 ||( RIFF_DescendChunk(p_input) != 0 ))
563 __AVIFreeDemuxData( p_input );
564 intf_ErrMsg( "input error: cannot find \"LIST-strl\" (avi_file)" );
568 /* in LIST-strl search strh */
569 if( RIFF_FindAndLoadChunk( p_input, p_hdrl,
570 &p_strh, FOURCC_strh ) != 0 )
572 RIFF_DeleteChunk( p_input, p_strl );
573 __AVIFreeDemuxData( p_input );
574 intf_ErrMsg( "input error: cannot find \"strh\" (avi_file)" );
577 __AVI_Parse_Header( &p_info->header,
578 p_strh->p_data->p_payload_start);
579 RIFF_DeleteChunk( p_input, p_strh );
581 /* in LIST-strl search strf */
582 if( RIFF_FindAndLoadChunk( p_input, p_hdrl,
583 &p_strf, FOURCC_strf ) != 0 )
585 RIFF_DeleteChunk( p_input, p_strl );
586 __AVIFreeDemuxData( p_input );
587 intf_ErrMsg( "input error: cannot find \"strf\" (avi_file)" );
590 /* we don't get strd, it's useless for divx,opendivx,mepgaudio */
591 if( RIFF_AscendChunk(p_input, p_strl) != 0 )
593 RIFF_DeleteChunk( p_input, p_strf );
594 RIFF_DeleteChunk( p_input, p_strl );
595 __AVIFreeDemuxData( p_input );
596 intf_ErrMsg( "input error: cannot go out (\"strl\") (avi_file)" );
601 vlc_mutex_lock( &p_input->stream.stream_lock );
602 p_es = input_AddES( p_input,
603 p_input->stream.p_selected_program, 1+i,
605 vlc_mutex_unlock( &p_input->stream.stream_lock );
606 p_es->i_stream_id =i; /* XXX: i don't use it */
608 switch( p_info->header.i_type )
611 p_es->i_cat = AUDIO_ES;
612 avi_ParseWaveFormatEx( &p_info->audio_format,
613 p_strf->p_data->p_payload_start );
616 __AVI_AudioGetType( p_info->audio_format.i_formattag );
617 if( p_es->i_type == 0 )
619 intf_ErrMsg( "input error: stream(%d,0x%x) not supported",
621 p_info->audio_format.i_formattag );
622 p_es->i_cat = UNKNOWN_ES;
627 p_es->i_cat = VIDEO_ES;
628 avi_ParseBitMapInfoHeader( &p_info->video_format,
629 p_strf->p_data->p_payload_start );
632 __AVI_VideoGetType( p_info->video_format.i_compression );
633 if( p_es->i_type == 0 )
635 intf_ErrMsg( "input error: stream(%d,%4.4s) not supported",
637 (char*)&p_info->video_format.i_compression);
638 p_es->i_cat = UNKNOWN_ES;
642 intf_ErrMsg( "input error: unknown stream(%d) type",
644 p_es->i_cat = UNKNOWN_ES;
648 p_info->i_cat = p_es->i_cat;
649 /* We copy strf for decoder in p_es->p_demux_data */
650 memcpy( p_es->p_demux_data,
651 p_strf->p_data->p_payload_start,
653 RIFF_DeleteChunk( p_input, p_strf );
654 RIFF_DeleteChunk( p_input, p_strl );
660 /* go out of p_hdrl */
661 if( RIFF_AscendChunk(p_input, p_hdrl) != 0)
663 __AVIFreeDemuxData( p_input );
664 intf_ErrMsg( "input error: cannot go out (\"hdrl\") (avi_file)" );
668 /* go to movi chunk to get it*/
669 if( RIFF_FindListChunk(p_input ,&p_movi,p_riff, FOURCC_movi) != 0 )
671 intf_ErrMsg( "input error: cannot find \"LIST-movi\" (avi_file)" );
672 __AVIFreeDemuxData( p_input );
675 p_avi_demux->p_movi = p_movi;
677 /* get index XXX need to have p_movi */
678 if( (p_avi_demux->avih.i_flags&AVIF_HASINDEX) != 0 )
681 __AVI_GetIndex( p_input );
682 /* try to get i_idxoffset for each stream */
683 __AVI_UpdateIndexOffset( p_input );
687 intf_WarnMsg( 1, "input init: no index !" );
691 /* we verify that each stream have at least one entry or create it */
692 for( i = 0; i < p_avi_demux->i_streams ; i++ )
694 AVIIndexEntry_t index;
695 riffchunk_t *p_chunk;
696 #define p_info p_avi_demux->pp_info[i]
697 if( p_info->p_index == NULL )
699 RIFF_GoToChunk( p_input, p_avi_demux->p_movi );
700 if( RIFF_DescendChunk(p_input) != 0 ) { continue; }
702 switch( p_info->i_cat )
705 if( RIFF_FindChunk( p_input,
706 MAKEFOURCC('0'+i/10, '0'+i%10,'w','b' ),
709 p_chunk = RIFF_ReadChunk( p_input );
714 if( (RIFF_FindChunk( p_input,
715 MAKEFOURCC('0'+i/10, '0'+i%10,'d','c' ),
718 p_chunk = RIFF_ReadChunk( p_input );
722 RIFF_GoToChunk( p_input, p_avi_demux->p_movi );
723 if( RIFF_DescendChunk(p_input) != 0 ) { continue; }
724 if( (RIFF_FindChunk( p_input,
725 MAKEFOURCC('0'+i/10, '0'+i%10,'d','b' ),
728 p_chunk = RIFF_ReadChunk( p_input );
733 if( p_chunk != NULL )
735 index.i_id = p_chunk->i_id;
736 index.i_flags = AVIIF_KEYFRAME;
737 index.i_pos = p_chunk->i_pos;
738 index.i_length = p_chunk->i_size;
739 __AVI_AddEntryIndex( p_info, &index );
740 intf_WarnMsg( 3, "input init: add index entry (%4.4s) (%d)",
741 (char*)&p_chunk->i_id,
749 /* to make sure to go the begining because unless demux will see a seek */
750 RIFF_GoToChunk( p_input, p_avi_demux->p_movi );
751 if( RIFF_DescendChunk( p_input ) != 0 )
753 __AVIFreeDemuxData( p_input );
754 intf_ErrMsg( "input error: cannot go in (\"movi\") (avi_file)" );
758 /* print informations on streams */
759 intf_Msg( "input init: AVIH: %d stream, flags %s%s%s%s%s%s ",
760 p_avi_demux->i_streams,
761 p_avi_demux->avih.i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
762 p_avi_demux->avih.i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",
763 p_avi_demux->avih.i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
764 p_avi_demux->avih.i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"",
765 p_avi_demux->avih.i_flags&AVIF_WASCAPTUREFILE?" CAPTUREFILE":"",
766 p_avi_demux->avih.i_flags&AVIF_COPYRIGHTED?" COPYRIGHTED":"" );
768 for( i = 0; i < p_avi_demux->i_streams; i++ )
770 #define p_info p_avi_demux->pp_info[i]
771 switch( p_info->p_es->i_cat )
774 intf_Msg("input init: video(%4.4s) %dx%d %dbpp %ffps (size %d)",
775 (char*)&p_info->video_format.i_compression,
776 p_info->video_format.i_width,
777 p_info->video_format.i_height,
778 p_info->video_format.i_bitcount,
779 (float)p_info->header.i_rate /
780 (float)p_info->header.i_scale,
781 p_info->header.i_samplesize );
782 if( (p_avi_demux->p_info_video == NULL) )
784 p_avi_demux->p_info_video = p_info;
789 intf_Msg( "input init: audio(0x%x) %d channels %dHz %dbits %ffps (size %d)",
790 p_info->audio_format.i_formattag,
791 p_info->audio_format.i_channels,
792 p_info->audio_format.i_samplespersec,
793 p_info->audio_format.i_bitspersample,
794 (float)p_info->header.i_rate /
795 (float)p_info->header.i_scale,
796 p_info->header.i_samplesize );
797 if( (p_avi_demux->p_info_audio == NULL) )
799 p_avi_demux->p_info_audio = p_info;
803 intf_Msg( "input init: unhanled stream %d", i );
808 /* we select the first audio and video ES */
809 vlc_mutex_lock( &p_input->stream.stream_lock );
810 if( p_avi_demux->p_info_video != NULL )
812 input_SelectES( p_input, p_avi_demux->p_info_video->p_es );
813 /* it seems that it's useless to select es because there are selected
814 * by the interface but i'm not sure of that */
818 intf_Msg( "input error: no video stream found !" );
820 if( p_avi_demux->p_info_audio != NULL )
822 input_SelectES( p_input, p_avi_demux->p_info_audio->p_es );
826 intf_Msg( "input init: no audio stream found !" );
828 p_input->stream.p_selected_program->b_is_ok = 1;
829 vlc_mutex_unlock( &p_input->stream.stream_lock );
835 /*****************************************************************************
836 * AVIEnd: frees unused data
837 *****************************************************************************/
838 static void AVIEnd( input_thread_t *p_input )
840 __AVIFreeDemuxData( p_input );
845 static mtime_t AVI_GetPTS( AVIStreamInfo_t *p_info )
847 /* p_info->p_index[p_info->i_idxposc] need to be valid !! */
848 /* be careful to *1000000 before round ! */
849 if( p_info->header.i_samplesize != 0 )
851 return( (mtime_t)( (double)1000000.0 *
852 (double)(p_info->p_index[p_info->i_idxposc].i_lengthtotal +
854 (double)p_info->header.i_scale /
855 (double)p_info->header.i_rate /
856 (double)p_info->header.i_samplesize ) );
860 return( (mtime_t)( (double)1000000.0 *
861 (double)(p_info->i_idxposc ) *
862 (double)p_info->header.i_scale /
863 (double)p_info->header.i_rate) );
869 static int __AVI_NextIndexEntry( input_thread_t *p_input,
870 AVIStreamInfo_t *p_info )
872 AVIIndexEntry_t index;
873 riffchunk_t *p_chunk;
874 AVIStreamInfo_t *p_info_tmp;
878 demux_data_avi_file_t *p_avi_demux =
879 (demux_data_avi_file_t*)p_input->p_demux_data;
883 if( p_info->i_idxposc < p_info->i_idxnb )
887 if( p_info->i_idxposc > p_info->i_idxnb )
893 /* create entry on the fly */
894 /* search for the more advance stream and parse from it for all streams*/
896 for( i = 0; i < p_avi_demux->i_streams; i++ )
898 #define p_info_i p_avi_demux->pp_info[i]
899 if( ( p_info_i->p_index )
900 && ( p_info_i->p_index[p_info_i->i_idxnb - 1].i_pos >
901 p_info_tmp->p_index[p_info_tmp->i_idxnb - 1].i_pos ) )
903 p_info_tmp = p_info_i;
908 /* go to last defined entry */
909 i_idxposc = p_info_tmp->i_idxposc; /* save p_info_tmp->i_idxposc */
910 p_info_tmp->i_idxposc = p_info_tmp->i_idxnb - 1;
911 __AVI_SeekToChunk( p_input, p_info_tmp );
912 p_info_tmp->i_idxposc = i_idxposc;
914 if( RIFF_NextChunk( p_input, p_avi_demux->p_movi ) != 0 )
920 /* save idxpos of p_info */
921 /* now parse for all stream and stop when reach next chunk for p_info */
922 for( i = 0; (i < 15)||(!b_inc); i++)
926 if( (p_chunk = RIFF_ReadChunk( p_input )) == NULL )
929 return( b_inc == 1 ? 0 : -1 );
932 index.i_id = p_chunk->i_id;
933 index.i_flags = AVIIF_KEYFRAME;
934 index.i_pos = p_chunk->i_pos;
935 index.i_length = p_chunk->i_size;
936 RIFF_DeleteChunk( p_input, p_chunk );
937 #define p_info_i p_avi_demux->pp_info[i_number]
938 if( (__AVI_ParseStreamHeader( index.i_id, &i_number, &i_type ) == 0)
939 &&( i_number < p_avi_demux->i_streams )
940 &&( p_info_i->p_index )
941 &&( p_info_i->p_index[p_info_i->i_idxnb - 1].i_pos +
942 p_info_i->p_index[p_info_i->i_idxnb - 1].i_length + 8<=
944 &&( __AVIGetESTypeFromTwoCC( i_type ) == p_info_i->i_cat ) )
946 __AVI_AddEntryIndex( p_info_i, &index );
947 if( (p_info_i == p_info)&&(!b_inc) )
953 if( RIFF_NextChunk( p_input, p_avi_demux->p_movi ) != 0 )
956 return( b_inc == 1 ? 0 : -1 );
965 /*****************************************************************************
966 * Functions to acces streams data
967 * Uses it, because i plane to read unseekable stream
968 * Don't work for the moment for unseekable stream
969 *****************************************************************************/
971 /* __AVI_ReadStreamChunkInPES; load an entire chunk
972 __AVI_ReadStreamBytesInPES; load bytes
973 __AVI_GoToStreamChunk; go to chunk
974 __AVI_GoToStreamBytes; go to bytes in the all stream
975 not seekable file is not yet supported
978 static int __AVI_GoToStreamChunk( input_thread_t *p_input,
979 AVIStreamInfo_t *p_info,
985 if( !p_input->stream.b_seekable )
987 intf_ErrMsg( "input error: need the ability to seek in stream" );
991 if( p_info->p_index != NULL )
993 if( i_chunk >= p_info->i_idxnb )
995 p_info->i_idxposc = p_info->i_idxnb-1;
996 while( p_info->i_idxposc < i_chunk )
998 if( __AVI_NextIndexEntry( p_input, p_info ) != 0)
1006 p_info->i_idxposc = i_chunk;
1009 /* now do we have valid index for the chunk */
1010 __RIFF_TellPos( p_input, &u32_pos );
1012 i_pos = (off_t)p_info->p_index[i_chunk].i_pos;
1013 if( i_pos != u32_pos )
1015 p_input->pf_seek( p_input, i_pos );
1016 input_AccessReinit( p_input );
1018 p_info->i_idxposb = 0;
1027 static int __AVI_GoToStreamBytes( input_thread_t *p_input,
1028 AVIStreamInfo_t *p_info,
1034 if( !p_input->stream.b_seekable )
1036 intf_ErrMsg( "input error: need the ability to seek in stream" );
1040 /* now do we have valid index for the chunk */
1041 if( p_info->p_index != NULL )
1043 if( p_info->p_index[p_info->i_idxnb - 1].i_lengthtotal +
1044 p_info->p_index[p_info->i_idxnb - 1].i_length <= i_byte)
1046 p_info->i_idxposc = p_info->i_idxnb - 1;
1047 while( p_info->p_index[p_info->i_idxposc].i_lengthtotal +
1048 p_info->p_index[p_info->i_idxposc].i_length <= i_byte)
1050 if( __AVI_NextIndexEntry( p_input, p_info ) != 0)
1058 /* uses dichototmie to be fast enougth */
1059 int i_idxposc = p_info->i_idxposc;
1060 int i_idxmax = p_info->i_idxnb;
1064 if( p_info->p_index[i_idxposc].i_lengthtotal > i_byte )
1066 i_idxmax = i_idxposc ;
1067 i_idxposc = ( i_idxmin + i_idxposc ) / 2 ;
1071 if( p_info->p_index[i_idxposc].i_lengthtotal +
1072 p_info->p_index[i_idxposc].i_length <= i_byte)
1074 i_idxmin = i_idxposc ;
1075 i_idxposc = (i_idxmax + i_idxposc ) / 2 ;
1079 p_info->i_idxposc = i_idxposc;
1086 p_info->i_idxposb = i_byte -
1087 p_info->p_index[p_info->i_idxposc].i_lengthtotal;
1089 i_pos = (off_t)p_info->p_index[p_info->i_idxposc].i_pos +
1090 p_info->i_idxposb + 8;
1091 __RIFF_TellPos( p_input, &u32_pos );
1092 if( u32_pos != i_pos )
1094 p_input->pf_seek( p_input, i_pos );
1095 input_AccessReinit( p_input );
1105 static pes_packet_t *__AVI_ReadStreamChunkInPES( input_thread_t *p_input,
1106 AVIStreamInfo_t *p_info )
1108 pes_packet_t *p_pes;
1109 if( p_info->i_idxposc >= p_info->i_idxnb )
1114 if( ( __AVI_GoToStreamChunk( p_input, p_info, p_info->i_idxposc ) != 0 )
1115 ||( RIFF_LoadChunkDataInPES( p_input, &p_pes) != 0 ) )
1121 __AVI_NextIndexEntry( p_input, p_info);
1122 p_info->i_idxposb = 0;
1127 static pes_packet_t *__AVI_ReadStreamBytesInPES( input_thread_t *p_input,
1128 AVIStreamInfo_t *p_info,
1131 pes_packet_t *p_pes = NULL;
1132 data_packet_t *p_data;
1135 if( ( p_pes = input_NewPES( p_input->p_method_data ) ) == NULL )
1142 if( p_info->i_idxposc >= p_info->i_idxnb )
1144 input_DeletePES( p_input->p_method_data, p_pes );
1147 if( __AVI_GoToStreamBytes( p_input, p_info,
1148 p_info->p_index[p_info->i_idxposc].i_lengthtotal +
1149 p_info->i_idxposb ) != 0 )
1151 input_DeletePES( p_input->p_method_data, p_pes );
1155 i_read = input_SplitBuffer(p_input, &p_data,
1157 p_info->p_index[p_info->i_idxposc].i_length
1158 - p_info->i_idxposb ) );
1161 input_DeletePES( p_input->p_method_data, p_pes );
1165 if( !p_pes->p_first )
1167 p_pes->p_first = p_data;
1171 p_pes->p_last->p_next = p_data;
1173 p_pes->p_last = p_data;
1174 p_pes->i_pes_size += i_read;
1177 p_info->i_idxposb += i_read;
1179 if( p_info->i_idxposb >= p_info->p_index[p_info->i_idxposc].i_length )
1181 p_info->i_idxposb = 0;
1182 if( __AVI_NextIndexEntry( p_input, p_info) != 0 )
1184 input_DeletePES( p_input->p_method_data, p_pes );
1192 /*****************************************************************************
1193 * Function to convert pts to chunk or byte
1194 *****************************************************************************/
1196 static __inline__ mtime_t __AVI_PTSToChunk( AVIStreamInfo_t *p_info,
1199 return( (mtime_t)((double)i_pts *
1200 (double)p_info->header.i_rate /
1201 (double)p_info->header.i_scale /
1202 (double)1000000.0 ) );
1205 static __inline__ mtime_t __AVI_PTSToByte( AVIStreamInfo_t *p_info,
1208 return( (mtime_t)((double)i_pts *
1209 (double)p_info->header.i_samplesize *
1210 (double)p_info->header.i_rate /
1211 (double)p_info->header.i_scale /
1212 (double)1000000.0 ) );
1216 /* try to realign after a seek */
1217 static int AVI_ReAlign( input_thread_t *p_input )
1222 AVIStreamInfo_t *p_info;
1223 demux_data_avi_file_t *p_avi_demux =
1224 (demux_data_avi_file_t*)p_input->p_demux_data;
1226 p_info = (p_avi_demux->p_info_video != NULL ) ?
1227 p_avi_demux->p_info_video :
1228 p_avi_demux->p_info_audio;
1230 __RIFF_TellPos( p_input, &u32_pos );
1232 i_pos = (off_t)u32_pos;
1234 if( i_pos <= p_info->p_index[0].i_pos )
1236 /* before beginning of stream */
1237 if( !p_info->header.i_samplesize )
1239 __AVI_GoToStreamChunk( p_input,
1245 __AVI_GoToStreamBytes( p_input,
1252 if( (p_info->p_index[p_info->i_idxposc].i_pos <= i_pos)
1253 && ( i_pos < p_info->p_index[p_info->i_idxposc].i_pos +
1254 p_info->p_index[p_info->i_idxposc].i_length ) )
1256 /* FIXME if master == audio and samplesize != 0 */
1257 /* don't work with big chunk */
1258 /* don't do anything we are in the current chunk */
1261 if( i_pos < p_info->p_index[p_info->i_idxposc].i_pos )
1269 /* now find in what chunk we are */
1270 while( ( i_pos < p_info->p_index[p_info->i_idxposc].i_pos )
1271 &&( p_info->i_idxposc > 0 ) )
1273 /* search before i_idxposc */
1274 p_info->i_idxposc--;
1277 while( i_pos >= p_info->p_index[p_info->i_idxposc].i_pos +
1278 p_info->p_index[p_info->i_idxposc].i_length + 8 )
1280 /* search after i_idxposc */
1281 if( __AVI_NextIndexEntry( p_input, p_info ) != 0 )
1286 /* search nearest key frame */
1287 if( ( !p_info->header.i_samplesize ) && ( p_info->i_cat == VIDEO_ES ) )
1289 /* only for chunk stream */
1292 while(!(p_info->p_index[p_info->i_idxposc].i_flags&AVIIF_KEYFRAME) )
1294 if( __AVI_NextIndexEntry( p_input, p_info ) != 0 )
1302 while( ( p_info->i_idxposc > 0 ) &&
1303 (!(p_info->p_index[p_info->i_idxposc].i_flags&AVIIF_KEYFRAME)) )
1305 p_info->i_idxposc--;
1309 __AVI_GoToStreamChunk( p_input, p_info, p_info->i_idxposc );
1314 /* make difference between audio and video pts as little as possible */
1315 static void AVI_SynchroReInit( input_thread_t *p_input )
1317 demux_data_avi_file_t *p_avi_demux =
1318 (demux_data_avi_file_t*)p_input->p_demux_data;
1319 #define p_info_video p_avi_demux->p_info_video
1320 #define p_info_audio p_avi_demux->p_info_audio
1321 if( ( p_info_video )&&( p_info_audio ) )
1323 /* now resynch audio video video */
1324 /*don't care of AVIF_KEYFRAME */
1325 if( !p_info_audio->header.i_samplesize )
1327 int i_chunk = __AVI_PTSToChunk( p_info_audio,
1328 AVI_GetPTS( p_info_video ));
1329 __AVI_GoToStreamChunk( p_input,
1335 int i_byte = __AVI_PTSToByte( p_info_audio,
1336 AVI_GetPTS( p_info_video ) ) ;
1337 __AVI_GoToStreamBytes( p_input,
1346 /*****************************************************************************
1347 * AVI_GetFrameInPES : get dpts length(µs) in pes from stream
1348 *****************************************************************************
1349 * Handle multiple pes, and set pts to the good value
1350 *****************************************************************************/
1351 static pes_packet_t *AVI_GetFrameInPES( input_thread_t *p_input,
1352 AVIStreamInfo_t *p_info,
1356 pes_packet_t *p_pes = NULL;
1357 pes_packet_t *p_pes_tmp = NULL;
1358 pes_packet_t *p_pes_first = NULL;
1361 /* we now that p_info != NULL */
1367 if( !p_info->header.i_samplesize )
1369 /* stream is chunk based , easy */
1370 int i_chunk = __MAX( __AVI_PTSToChunk( p_info, i_dpts), 1 );
1371 /* at least one frame */
1374 for( i = 0; i < i_chunk; i++ )
1376 /* get pts while is valid */
1377 i_pts = AVI_GetPTS( p_info );
1378 p_pes_tmp = __AVI_ReadStreamChunkInPES( p_input, p_info );
1382 return( p_pes_first );
1384 p_pes_tmp->i_pts = i_pts;
1387 p_pes_first = p_pes_tmp;
1391 p_pes->p_next = p_pes_tmp;
1395 return( p_pes_first );
1399 /* stream is byte based */
1400 int i_byte = __AVI_PTSToByte( p_info, i_dpts);
1405 /* at least one Kbyte */
1406 /*i_byte = __MIN( 1024*1000, i_byte ); *//* but no more than 1000ko */
1407 i_pts = AVI_GetPTS( p_info );
1409 p_pes = __AVI_ReadStreamBytesInPES( p_input, p_info, i_byte);
1413 p_pes->i_pts = i_pts;
1418 /*****************************************************************************
1419 * AVI_DecodePES : send a pes to decoder
1420 *****************************************************************************
1421 * Handle multiple pes, and set pts to the good value
1422 *****************************************************************************/
1423 static __inline__ void AVI_DecodePES( input_thread_t *p_input,
1424 AVIStreamInfo_t *p_info,
1425 pes_packet_t *p_pes )
1427 pes_packet_t *p_pes_next;
1428 /* input_decode want only one pes, but AVI_GetFrameInPES give
1429 multiple pes so send one by one */
1430 /* we now that p_info != NULL */
1433 p_pes_next = p_pes->p_next;
1434 p_pes->p_next = NULL;
1435 p_pes->i_pts = input_ClockGetTS( p_input,
1436 p_input->stream.p_selected_program,
1437 p_pes->i_pts * 9/100);
1438 input_DecodePES( p_info->p_es->p_decoder_fifo, p_pes );
1444 /*****************************************************************************
1445 * AVIDemux: reads and demuxes data packets
1446 *****************************************************************************
1447 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
1448 *****************************************************************************/
1449 static int AVIDemux( input_thread_t *p_input )
1452 pes_packet_t *p_pes;
1453 AVIStreamInfo_t *p_info_master;
1454 AVIStreamInfo_t *p_info_slave;
1456 demux_data_avi_file_t *p_avi_demux =
1457 (demux_data_avi_file_t*)p_input->p_demux_data;
1459 /* search new video and audio stream selected
1460 if current have been unselected*/
1461 if( ( !p_avi_demux->p_info_video )
1462 || ( !p_avi_demux->p_info_video->p_es->p_decoder_fifo ) )
1464 p_avi_demux->p_info_video = NULL;
1465 for( i = 0; i < p_avi_demux->i_streams; i++ )
1467 if( ( p_avi_demux->pp_info[i]->i_cat == VIDEO_ES )
1468 &&( p_avi_demux->pp_info[i]->p_es->p_decoder_fifo != NULL ) )
1470 p_avi_demux->p_info_video = p_avi_demux->pp_info[i];
1471 p_avi_demux->p_info_video->b_selected = 1;
1476 if( ( !p_avi_demux->p_info_audio )
1477 ||( !p_avi_demux->p_info_audio->p_es->p_decoder_fifo ) )
1479 p_avi_demux->p_info_audio = NULL;
1480 for( i = 0; i < p_avi_demux->i_streams; i++ )
1482 if( ( p_avi_demux->pp_info[i]->i_cat == AUDIO_ES )
1483 &&( p_avi_demux->pp_info[i]->p_es->p_decoder_fifo != NULL ) )
1485 p_avi_demux->p_info_audio = p_avi_demux->pp_info[i];
1486 p_avi_demux->p_info_audio->b_selected = 1;
1491 /* by default video is master for resync audio (after a seek .. ) */
1492 if( p_avi_demux->p_info_video )
1494 p_info_master = p_avi_demux->p_info_video;
1495 p_info_slave = p_avi_demux->p_info_audio;
1499 p_info_master = p_avi_demux->p_info_audio;
1500 p_info_slave = NULL;
1503 if( !p_info_master )
1505 intf_ErrMsg( "input error: no stream selected" );
1509 /* check for signal from interface */
1510 if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
1512 /* we can supposed that is a seek */
1513 /* first wait for empty buffer, arbitrary time */
1514 msleep( DEFAULT_PTS_DELAY );
1515 /* then try to realign in stream */
1516 if( AVI_ReAlign( p_input ) != 0 )
1518 return( 0 ); /* assume EOF */
1520 AVI_SynchroReInit( p_input );
1522 /* manage rate, if not default: skeep audio */
1523 vlc_mutex_lock( &p_input->stream.stream_lock );
1524 if( p_input->stream.control.i_rate != p_avi_demux->i_rate )
1526 if( p_avi_demux->p_info_audio)
1528 p_avi_demux->p_info_audio->b_selected = 1;
1530 p_avi_demux->i_rate = p_input->stream.control.i_rate;
1532 vlc_mutex_unlock( &p_input->stream.stream_lock );
1533 if( p_avi_demux->i_rate != DEFAULT_RATE )
1535 p_info_slave = NULL;
1538 /* take care of newly selected audio ES */
1539 if( p_info_master->b_selected )
1541 p_info_master->b_selected = 0;
1542 AVI_SynchroReInit( p_input );
1544 if( ( p_info_slave )&&( p_info_slave->b_selected ) )
1546 p_info_slave->b_selected = 0;
1547 AVI_SynchroReInit( p_input );
1550 /* wait for the good time */
1551 input_ClockManageRef( p_input,
1552 p_input->stream.p_selected_program,
1553 p_avi_demux->i_pcr );
1554 /* calculate pcr, time when we must read the next data */
1555 /* 9/100 kludge ->need to convert to 1/1000000 clock unit to 1/90000 */
1558 p_avi_demux->i_pcr = __MIN( AVI_GetPTS( p_info_master ),
1559 AVI_GetPTS( p_info_slave ) ) * 9/100;
1563 p_avi_demux->i_pcr = AVI_GetPTS( p_info_master ) * 9/100;
1566 /* get video and audio frames */
1567 p_pes = AVI_GetFrameInPES( p_input,
1569 100000 ); /* 100 ms */
1571 AVI_DecodePES( p_input,
1577 p_pes = AVI_GetFrameInPES( p_input,
1579 AVI_GetPTS( p_info_master ) -
1580 AVI_GetPTS( p_info_slave));
1581 AVI_DecodePES( p_input,
1586 return( p_info_master->i_idxposc >= p_info_master->i_idxnb ? 0 : 1 );