1 /*****************************************************************************
2 * avi.c : AVI file Stream input module for vlc
3 *****************************************************************************
4 * Copyright (C) 2001 VideoLAN
5 * $Id: avi.c,v 1.4 2002/04/25 21:52: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>
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_demux_data, p_avi_demux->p_riff );
103 if( p_avi_demux->p_hdrl != NULL )
104 RIFF_DeleteChunk( p_input->p_demux_data, p_avi_demux->p_hdrl );
105 if( p_avi_demux->p_movi != NULL )
106 RIFF_DeleteChunk( p_input->p_demux_data, p_avi_demux->p_movi );
107 if( p_avi_demux->p_idx1 != NULL )
108 RIFF_DeleteChunk( p_input->p_demux_data, 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 #define p_info p_avi_demux->pp_info[i]
116 /* don't uses RIFF_DeleteChunk -> it will segfault here ( probably because of
117 data_packey already unallocated ? */
118 if( p_info->p_strl != NULL )
120 free( p_info->p_strl );
122 if( p_info->p_strh != NULL )
124 free( p_info->p_strh );
127 if( p_info->p_strf != NULL )
129 free( p_info->p_strf );
131 if( p_info->p_strd != NULL )
133 free( p_info->p_strd );
135 if( p_info->p_index != NULL )
137 free( p_info->p_index );
143 free( p_avi_demux->pp_info );
147 static void __AVI_Parse_avih( MainAVIHeader_t *p_avih, byte_t *p_buff )
149 p_avih->i_microsecperframe = __GetDoubleWordLittleEndianFromBuff( p_buff );
150 p_avih->i_maxbytespersec = __GetDoubleWordLittleEndianFromBuff( p_buff + 4);
151 p_avih->i_reserved1 = __GetDoubleWordLittleEndianFromBuff( p_buff + 8);
152 p_avih->i_flags = __GetDoubleWordLittleEndianFromBuff( p_buff + 12);
153 p_avih->i_totalframes = __GetDoubleWordLittleEndianFromBuff( p_buff + 16);
154 p_avih->i_initialframes = __GetDoubleWordLittleEndianFromBuff( p_buff + 20);
155 p_avih->i_streams = __GetDoubleWordLittleEndianFromBuff( p_buff + 24);
156 p_avih->i_suggestedbuffersize =
157 __GetDoubleWordLittleEndianFromBuff( p_buff + 28);
158 p_avih->i_width = __GetDoubleWordLittleEndianFromBuff( p_buff + 32 );
159 p_avih->i_height = __GetDoubleWordLittleEndianFromBuff( p_buff + 36 );
160 p_avih->i_scale = __GetDoubleWordLittleEndianFromBuff( p_buff + 40 );
161 p_avih->i_rate = __GetDoubleWordLittleEndianFromBuff( p_buff + 44 );
162 p_avih->i_start = __GetDoubleWordLittleEndianFromBuff( p_buff + 48);
163 p_avih->i_length = __GetDoubleWordLittleEndianFromBuff( p_buff + 52);
166 static void __AVI_Parse_Header( AVIStreamHeader_t *p_strh, byte_t *p_buff )
168 p_strh->i_type = __GetDoubleWordLittleEndianFromBuff( p_buff );
169 p_strh->i_handler = __GetDoubleWordLittleEndianFromBuff( p_buff + 4 );
170 p_strh->i_flags = __GetDoubleWordLittleEndianFromBuff( p_buff + 8 );
171 p_strh->i_reserved1 = __GetDoubleWordLittleEndianFromBuff( p_buff + 12);
172 p_strh->i_initialframes = __GetDoubleWordLittleEndianFromBuff( p_buff + 16);
173 p_strh->i_scale = __GetDoubleWordLittleEndianFromBuff( p_buff + 20);
174 p_strh->i_rate = __GetDoubleWordLittleEndianFromBuff( p_buff + 24);
175 p_strh->i_start = __GetDoubleWordLittleEndianFromBuff( p_buff + 28);
176 p_strh->i_length = __GetDoubleWordLittleEndianFromBuff( p_buff + 32);
177 p_strh->i_suggestedbuffersize =
178 __GetDoubleWordLittleEndianFromBuff( p_buff + 36);
179 p_strh->i_quality = __GetDoubleWordLittleEndianFromBuff( p_buff + 40);
180 p_strh->i_samplesize = __GetDoubleWordLittleEndianFromBuff( p_buff + 44);
183 int avi_ParseBitMapInfoHeader( bitmapinfoheader_t *h, byte_t *p_data )
185 h->i_size = __GetDoubleWordLittleEndianFromBuff( p_data );
186 h->i_width = __GetDoubleWordLittleEndianFromBuff( p_data + 4 );
187 h->i_height = __GetDoubleWordLittleEndianFromBuff( p_data + 8 );
188 h->i_planes = __GetWordLittleEndianFromBuff( p_data + 12 );
189 h->i_bitcount = __GetWordLittleEndianFromBuff( p_data + 14 );
190 h->i_compression = __GetDoubleWordLittleEndianFromBuff( p_data + 16 );
191 h->i_sizeimage = __GetDoubleWordLittleEndianFromBuff( p_data + 20 );
192 h->i_xpelspermeter = __GetDoubleWordLittleEndianFromBuff( p_data + 24 );
193 h->i_ypelspermeter = __GetDoubleWordLittleEndianFromBuff( p_data + 28 );
194 h->i_clrused = __GetDoubleWordLittleEndianFromBuff( p_data + 32 );
195 h->i_clrimportant = __GetDoubleWordLittleEndianFromBuff( p_data + 36 );
199 int avi_ParseWaveFormatEx( waveformatex_t *h, byte_t *p_data )
201 h->i_formattag = __GetWordLittleEndianFromBuff( p_data );
202 h->i_channels = __GetWordLittleEndianFromBuff( p_data + 2 );
203 h->i_samplespersec = __GetDoubleWordLittleEndianFromBuff( p_data + 4 );
204 h->i_avgbytespersec= __GetDoubleWordLittleEndianFromBuff( p_data + 8 );
205 h->i_blockalign = __GetWordLittleEndianFromBuff( p_data + 12 );
206 h->i_bitspersample = __GetWordLittleEndianFromBuff( p_data + 14 );
207 h->i_size = __GetWordLittleEndianFromBuff( p_data + 16 );
211 static int __AVI_ParseStreamHeader( u32 i_id, int *i_number, u16 *i_type )
215 c1 = ( i_id ) & 0xFF;
216 c2 = ( i_id >> 8 ) & 0xFF;
217 c3 = ( i_id >> 16 ) & 0xFF;
218 c4 = ( i_id >> 24 ) & 0xFF;
220 if( c1 < '0' || c1 > '9' || c2 < '0' || c2 > '9' )
224 *i_number = (c1 - '0') * 10 + (c2 - '0' );
225 *i_type = ( c3 << 8) + c4;
229 static int __AVI_HeaderMoviValid( u32 i_header )
231 switch( i_header&0xFFFF0000 )
250 static void __AVI_AddEntryIndex( AVIStreamInfo_t *p_info,
251 AVIIndexEntry_t *p_index)
253 if( p_info->p_index == NULL )
255 p_info->i_idxmax = 4096;
257 p_info->p_index = calloc( p_info->i_idxmax,
258 sizeof( AVIIndexEntry_t ) );
260 if( p_info->i_idxnb >= p_info->i_idxmax )
262 p_info->i_idxmax += 4096;
263 p_info->p_index = realloc( (void*)p_info->p_index,
265 sizeof( AVIIndexEntry_t ) );
267 /* calculate cumulate length */
268 if( p_info->i_idxnb > 0 )
270 p_index->i_lengthtotal = p_index->i_length +
271 p_info->p_index[p_info->i_idxnb-1].i_lengthtotal;
275 p_index->i_lengthtotal = 0;
278 p_info->p_index[p_info->i_idxnb] = *p_index;
282 static void __AVI_GetIndex( input_thread_t *p_input )
284 demux_data_avi_file_t *p_avi_demux;
285 AVIIndexEntry_t index;
293 p_avi_demux = (demux_data_avi_file_t*)p_input->p_demux_data ;
295 if( RIFF_FindAndGotoDataChunk( p_input,
300 intf_WarnMsg( 1, "input init: cannot find index" );
301 RIFF_GoToChunk( p_input, p_avi_demux->p_hdrl );
304 p_avi_demux->p_idx1 = p_idx1;
305 intf_WarnMsg( 1, "input init: loading index" );
308 if( (i_read = input_Peek( p_input, &p_buff, 16*1024 )) < 16 )
310 for( i = 0, i_read = 0; i < p_avi_demux->i_streams; i++ )
312 i_read += p_avi_demux->pp_info[i]->i_idxnb;
314 intf_WarnMsg( 1,"input info: read %d idx chunk", i_read );
318 /* TODO try to verify if we are beyond end of p_idx1 */
319 for( i = 0; i < i_read; i++ )
321 byte_t *p_peek = p_buff + i * 16;
322 index.i_id = __GetDoubleWordLittleEndianFromBuff( p_peek );
323 index.i_flags = __GetDoubleWordLittleEndianFromBuff( p_peek+4);
324 index.i_offset = __GetDoubleWordLittleEndianFromBuff( p_peek+8);
325 index.i_length = __GetDoubleWordLittleEndianFromBuff(p_peek+12);
327 if( (__AVI_ParseStreamHeader( index.i_id, &i_number, &i_type ) != 0)
328 ||(i_number > p_avi_demux->i_streams))
332 __AVI_AddEntryIndex( p_avi_demux->pp_info[i_number],
335 __RIFF_SkipBytes( p_input, 16 * i_read );
339 static int __AVI_SeekToChunk( input_thread_t *p_input, AVIStreamInfo_t *p_info )
341 demux_data_avi_file_t *p_avi_demux;
342 p_avi_demux = (demux_data_avi_file_t*)p_input->p_demux_data;
344 if( (p_info->p_index != NULL)&&(p_info->i_idxpos < p_info->i_idxnb) )
348 i_pos = (off_t)p_info->p_index[p_info->i_idxpos].i_offset +
351 p_input->pf_seek( p_input, i_pos );
352 input_AccessReinit( p_input );
355 /* index are no longer valid */
356 if( p_info->p_index != NULL )
365 /* XXX call after get p_movi */
366 static int __AVI_GetIndexOffset( input_thread_t *p_input )
368 riffchunk_t *p_chunk;
369 demux_data_avi_file_t *p_avi_demux;
372 p_avi_demux = (demux_data_avi_file_t*)p_input->p_demux_data;
373 for( i = 0; i < p_avi_demux->i_streams; i++ )
375 #define p_info p_avi_demux->pp_info[i]
376 if( p_info->p_index == NULL ) {continue;}
377 p_info->i_idxoffset = 0;
378 __AVI_SeekToChunk( p_input, p_info );
379 p_chunk = RIFF_ReadChunk( p_input );
380 if( (p_chunk == NULL)||(p_chunk->i_id != p_info->p_index[0].i_id) )
382 p_info->i_idxoffset = p_avi_demux->p_movi->i_pos + 8;
383 __AVI_SeekToChunk( p_input, p_info );
384 p_chunk = RIFF_ReadChunk( p_input );
385 if( (p_chunk == NULL)||(p_chunk->i_id != p_info->p_index[0].i_id) )
387 intf_WarnMsg( 1, "input demux: can't find offset for stream %d",
389 continue; /* TODO: search manually from p_movi */
396 static int __AVI_AudioGetType( u32 i_type )
400 /* case( WAVE_FORMAT_PCM ):
401 return( WAVE_AUDIO_ES ); */
402 case( WAVE_FORMAT_AC3 ):
403 return( AC3_AUDIO_ES );
404 case( WAVE_FORMAT_MPEG):
405 case( WAVE_FORMAT_MPEGLAYER3):
406 return( MPEG2_AUDIO_ES ); /* 2 for mpeg-2 layer 1 2 ou 3 */
412 static int __AVI_VideoGetType( u32 i_type )
428 return( MSMPEG4_VIDEO_ES );
437 return( MPEG4_VIDEO_ES );
443 /**************************************************************************/
445 /* Tention: bcp de test à ajouter mais aussi beaucoup de MEMOIRE a DESALLOUER pas fait */
446 static int AVIInit( input_thread_t *p_input )
448 riffchunk_t *p_riff,*p_hdrl,*p_movi;
450 riffchunk_t *p_strl,*p_strh,*p_strf/* ,*p_strd */;
452 demux_data_avi_file_t *p_avi_demux;
453 es_descriptor_t *p_es = NULL; /* for not warning */
454 es_descriptor_t *p_es_video = NULL;
455 es_descriptor_t *p_es_audio = NULL;
459 p_avi_demux = malloc( sizeof(demux_data_avi_file_t) );
460 memset( p_avi_demux, 0, sizeof( demux_data_avi_file_t ) );
461 p_input->p_demux_data = p_avi_demux;
463 /* FIXME FIXME Je sais pas trop a quoi ca sert juste copié de ESInit */
464 /* Initialize access plug-in structures. */
465 if( p_input->i_mtu == 0 )
468 p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
471 if( RIFF_TestFileHeader( p_input, &p_riff, FOURCC_AVI ) != 0 )
473 __AVIFreeDemuxData( p_input );
474 intf_ErrMsg( "input: RIFF-AVI plug-in discarded (avi_file)" );
477 p_avi_demux->p_riff = p_riff;
479 if ( RIFF_DescendChunk(p_input) != 0 )
481 __AVIFreeDemuxData( p_input );
482 intf_ErrMsg( "input error: cannot look for subchunk (avi_file)" );
486 /* it's a riff-avi file, so search for LIST-hdrl */
487 if( RIFF_FindListChunk(p_input ,&p_hdrl,p_riff, FOURCC_hdrl) != 0 )
489 __AVIFreeDemuxData( p_input );
490 intf_ErrMsg( "input error: cannot find \"LIST-hdrl\" (avi_file)" );
493 p_avi_demux->p_hdrl = p_hdrl;
495 if( RIFF_DescendChunk(p_input) != 0 )
497 __AVIFreeDemuxData( p_input );
498 intf_ErrMsg( "input error: cannot look for subchunk (avi_file)" );
501 /* ds LIST-hdrl cherche avih */
502 if( RIFF_FindAndLoadChunk( p_input, p_hdrl,
503 &p_avih, FOURCC_avih ) != 0 )
505 __AVIFreeDemuxData( p_input );
506 intf_ErrMsg( "input error: cannot find \"avih\" chunk (avi_file)" );
509 __AVI_Parse_avih( &p_avi_demux->avih, p_avih->p_data->p_payload_start );
510 RIFF_DeleteChunk( p_input, p_avih );
512 if( p_avi_demux->avih.i_streams == 0 )
513 /* aucun flux defini, peut etre essayer de trouver ss connaitre */
514 /* le nombre serait pas mal, a voir */
516 __AVIFreeDemuxData( p_input );
517 intf_ErrMsg( "input error: no defined stream !" );
521 /* On creer les tableau pr les flux */
522 p_avi_demux->i_streams = p_avi_demux->avih.i_streams;
524 p_avi_demux->pp_info = calloc( p_avi_demux->i_streams,
525 sizeof( AVIStreamInfo_t* ) );
526 memset( p_avi_demux->pp_info, 0,
527 sizeof( AVIStreamInfo_t* ) * p_avi_demux->i_streams );
529 for( i = 0 ; i < p_avi_demux->i_streams; i++ )
531 p_avi_demux->pp_info[i] = malloc( sizeof(AVIStreamInfo_t ) );
532 memset( p_avi_demux->pp_info[i], 0, sizeof( AVIStreamInfo_t ) );
534 /* pour chaque flux on cherche ses infos */
535 if( RIFF_FindListChunk(p_input,
536 &p_strl,p_hdrl, FOURCC_strl) != 0 )
538 __AVIFreeDemuxData( p_input );
539 intf_ErrMsg( "input error: cannot find \"LIST-strl\" (avi_file)" );
542 p_avi_demux->pp_info[i]->p_strl = p_strl;
544 if( RIFF_DescendChunk(p_input) != 0 )
546 __AVIFreeDemuxData( p_input );
547 intf_ErrMsg( "input error: cannot look for subchunk (avi_file)" );
550 /* ds LIST-strl cherche strh */
551 if( RIFF_FindAndLoadChunk( p_input, p_hdrl,
552 &p_strh, FOURCC_strh ) != 0 )
554 __AVIFreeDemuxData( p_input );
555 intf_ErrMsg( "input error: cannot find \"strh\" (avi_file)" );
558 p_avi_demux->pp_info[i]->p_strh = p_strh;
560 /* ds LIST-strl cherche strf */
561 if( RIFF_FindAndLoadChunk( p_input, p_hdrl,
562 &p_strf, FOURCC_strf ) != 0 )
564 __AVIFreeDemuxData( p_input );
565 intf_ErrMsg( "input error: cannot find \"strf\" (avi_file)" );
568 p_avi_demux->pp_info[i]->p_strf = p_strf;
569 /* FIXME faudrait cherche et charger strd */
570 /* mais a priori pas vraiment utile pr divx */
572 if( RIFF_AscendChunk(p_input, p_strl) != 0 )
574 __AVIFreeDemuxData( p_input );
575 intf_ErrMsg( "input error: cannot go out (\"strl\") (avi_file)" );
582 if( RIFF_AscendChunk(p_input, p_hdrl) != 0)
584 __AVIFreeDemuxData( p_input );
585 intf_ErrMsg( "input error: cannot go out (\"hdrl\") (avi_file)" );
589 intf_Msg( "input init: AVIH: %d stream, flags %s%s%s%s%s%s ",
590 p_avi_demux->i_streams,
591 p_avi_demux->avih.i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
592 p_avi_demux->avih.i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",
593 p_avi_demux->avih.i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
594 p_avi_demux->avih.i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"",
595 p_avi_demux->avih.i_flags&AVIF_WASCAPTUREFILE?" CAPTUREFILE":"",
596 p_avi_demux->avih.i_flags&AVIF_COPYRIGHTED?" COPYRIGHTED":"" );
598 /* go to movi chunk */
599 if( RIFF_FindListChunk(p_input ,&p_movi,p_riff, FOURCC_movi) != 0 )
601 intf_ErrMsg( "input error: cannot find \"LIST-movi\" (avi_file)" );
602 __AVIFreeDemuxData( p_input );
605 p_avi_demux->p_movi = p_movi;
608 if( (p_input->stream.b_seekable)
609 &&((p_avi_demux->avih.i_flags&AVIF_HASINDEX) != 0) )
611 __AVI_GetIndex( p_input );
612 /* try to get i_idxoffset with first stream*/
613 __AVI_GetIndexOffset( p_input );
614 RIFF_GoToChunk( p_input, p_avi_demux->p_movi );
618 intf_WarnMsg( 1, "input init: cannot get index" );
621 if( RIFF_DescendChunk( p_input ) != 0 )
623 __AVIFreeDemuxData( p_input );
624 intf_ErrMsg( "input error: cannot go in (\"movi\") (avi_file)" );
627 /* TODO: check for index and read it if possible( seekable )*/
629 /** We have now finished with reading the file **/
630 /** we make the last initialisation **/
632 if( input_InitStream( p_input, 0 ) == -1)
634 __AVIFreeDemuxData( p_input );
635 intf_ErrMsg( "input error: cannot init stream" );
639 if( input_AddProgram( p_input, 0, 0) == NULL )
641 __AVIFreeDemuxData( p_input );
642 intf_ErrMsg( "input error: cannot add program" );
645 p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
646 p_input->stream.p_new_program = p_input->stream.pp_programs[0] ;
648 vlc_mutex_lock( &p_input->stream.stream_lock );
649 for( i = 0; i < p_avi_demux->i_streams; i++ )
651 #define p_info p_avi_demux->pp_info[i]
652 __AVI_Parse_Header( &p_info->header,
653 p_info->p_strh->p_data->p_payload_start);
654 switch( p_info->header.i_type )
657 /* pour l'id j'ai mis 12+i pr audio et 42+i pour video */
658 /* et le numero du flux(ici i) dans i_stream_id */
659 avi_ParseWaveFormatEx( &p_info->audio_format,
660 p_info->p_strf->p_data->p_payload_start );
661 p_es = input_AddES( p_input,
662 p_input->stream.p_selected_program, 12+i,
663 p_info->p_strf->i_size );
666 __AVI_AudioGetType( p_info->audio_format.i_formattag );
667 p_es->i_stream_id =i; /* FIXME */
668 if( p_es->i_type == 0 )
670 intf_ErrMsg( "input error: stream(%d,0x%x) not supported",
672 p_info->audio_format.i_formattag );
673 p_es->i_cat = UNKNOWN_ES;
677 if( p_es_audio == NULL ) {p_es_audio = p_es;}
678 p_es->i_cat = AUDIO_ES;
683 avi_ParseBitMapInfoHeader( &p_info->video_format,
684 p_info->p_strf->p_data->p_payload_start );
686 p_es = input_AddES( p_input,
687 p_input->stream.p_selected_program, 42+i,
688 p_info->p_strf->i_size );
691 __AVI_VideoGetType( p_info->video_format.i_compression );
692 p_es->i_stream_id =i; /* FIXME */
693 if( p_es->i_type == 0 )
695 intf_ErrMsg( "input error: stream(%d,%4.4s) not supported",
697 (char*)&p_info->video_format.i_compression);
698 p_es->i_cat = UNKNOWN_ES;
702 if( p_es_video == NULL ) {p_es_video = p_es;}
703 p_es->i_cat = VIDEO_ES;
707 p_es = input_AddES( p_input,
708 p_input->stream.p_selected_program, 12,
709 p_info->p_strf->i_size );
710 intf_ErrMsg( "input error: unknown stream(%d) type",
712 p_es->i_cat = UNKNOWN_ES;
716 p_info->i_cat = p_es->i_cat;
717 /* We copy strf for decoder in p_es->p_demux_data */
718 memcpy( p_es->p_demux_data,
719 p_info->p_strf->p_data->p_payload_start,
720 p_info->p_strf->i_size );
721 /* print informations on stream */
722 switch( p_es->i_cat )
725 intf_Msg("input init: video(%4.4s) %dx%d %dbpp %ffps (size %d)",
726 (char*)&p_info->video_format.i_compression,
727 p_info->video_format.i_width,
728 p_info->video_format.i_height,
729 p_info->video_format.i_bitcount,
730 (float)p_info->header.i_rate /
731 (float)p_info->header.i_scale,
732 p_info->header.i_samplesize );
735 intf_Msg( "input init: audio(0x%x) %d channels %dHz %dbits %ffps (size %d)",
736 p_info->audio_format.i_formattag,
737 p_info->audio_format.i_channels,
738 p_info->audio_format.i_samplespersec,
739 p_info->audio_format.i_bitspersample,
740 (float)p_info->header.i_rate /
741 (float)p_info->header.i_scale,
742 p_info->header.i_samplesize );
749 /* we select the first audio and video ES */
750 if( p_es_video != NULL )
752 input_SelectES( p_input, p_es_video );
756 intf_ErrMsg( "input error: no video stream found !" );
757 vlc_mutex_unlock( &p_input->stream.stream_lock );
760 if( p_es_audio != NULL )
762 input_SelectES( p_input, p_es_audio );
766 intf_Msg( "input init: no audio stream found !" );
769 /* p_input->stream.p_selected_area->i_tell = 0; */
770 p_input->stream.i_mux_rate = p_avi_demux->avih.i_maxbytespersec / 50;
771 p_input->stream.p_selected_program->b_is_ok = 1;
772 vlc_mutex_unlock( &p_input->stream.stream_lock );
777 static void AVIEnd( input_thread_t *p_input )
779 __AVIFreeDemuxData( p_input );
784 static mtime_t __AVI_GetPTS( AVIStreamInfo_t *p_info )
786 /* XXX you need to had p_info->i_date to have correct pts */
787 /* p_info->p_index[p_info->i_idxpos] need to be valid !! */
790 /* be careful to *1000000 before round ! */
791 if( p_info->header.i_samplesize != 0 )
793 i_pts = (mtime_t)( (double)1000000.0 *
794 (double)p_info->p_index[p_info->i_idxpos].i_lengthtotal *
795 (double)p_info->header.i_scale /
796 (double)p_info->header.i_rate /
797 (double)p_info->header.i_samplesize );
801 i_pts = (mtime_t)( (double)1000000.0 *
802 (double)p_info->i_idxpos *
803 (double)p_info->header.i_scale /
804 (double)p_info->header.i_rate);
811 static void __AVI_NextIndexEntry( input_thread_t *p_input,
812 AVIStreamInfo_t *p_info )
815 if( p_info->i_idxpos >= p_info->i_idxnb )
817 /* we need to verify if we reach end of file
818 or if index is broken and search manually */
819 intf_WarnMsg( 1, "input demux: out of index" );
823 static int __AVI_ReAlign( input_thread_t *p_input,
824 AVIStreamInfo_t *p_info )
829 __RIFF_TellPos( p_input, &u32_pos );
830 i_pos = (off_t)u32_pos - (off_t)p_info->i_idxoffset;
832 /* TODO verifier si on est dans p_movi */
834 if( p_info->p_index[p_info->i_idxnb-1].i_offset <= i_pos )
836 p_info->i_idxpos = p_info->i_idxnb-1;
840 if( i_pos <= p_info->p_index[0].i_offset )
842 p_info->i_idxpos = 0;
845 /* if we have seek in the current chunk then do nothing
846 __AVI_SeekToChunk will correct */
847 if( (p_info->p_index[p_info->i_idxpos].i_offset <= i_pos)
848 && ( i_pos < p_info->p_index[p_info->i_idxpos].i_offset +
849 p_info->p_index[p_info->i_idxpos].i_length ) )
854 if( i_pos >= p_info->p_index[p_info->i_idxpos].i_offset )
856 /* search for a chunk after i_idxpos */
857 while( (p_info->p_index[p_info->i_idxpos].i_offset < i_pos)
858 &&( p_info->i_idxpos < p_info->i_idxnb - 1 ) )
862 while( ((p_info->p_index[p_info->i_idxpos].i_flags&AVIIF_KEYFRAME) == 0)
863 &&( p_info->i_idxpos < p_info->i_idxnb - 1 ) )
870 /* search for a chunk before i_idxpos */
871 while( (p_info->p_index[p_info->i_idxpos].i_offset +
872 p_info->p_index[p_info->i_idxpos].i_length >= i_pos)
873 &&( p_info->i_idxpos > 0 ) )
877 while( ((p_info->p_index[p_info->i_idxpos].i_flags&AVIIF_KEYFRAME) == 0)
878 &( p_info->i_idxpos > 0 ) )
886 static void __AVI_SynchroReInit( input_thread_t *p_input,
887 AVIStreamInfo_t *p_info_master,
888 AVIStreamInfo_t *p_info_slave )
890 demux_data_avi_file_t *p_avi_demux;
891 p_avi_demux = (demux_data_avi_file_t*)p_input->p_demux_data;
892 p_avi_demux->i_date = mdate() + DEFAULT_PTS_DELAY
893 - __AVI_GetPTS( p_info_master );
894 if( p_info_slave != NULL )
896 /* TODO: a optimiser */
897 p_info_slave->i_idxpos = 0;
898 p_info_slave->b_unselected = 1; /* to correct audio */
900 p_input->stream.p_selected_program->i_synchro_state = SYNCHRO_OK;
902 /** -1 in case of error, 0 of EOF, 1 otherwise **/
903 static int AVIDemux( input_thread_t *p_input )
905 /* on cherche un block
907 * encapsuler dans un chunk "rec "
908 * juste une succesion de 00dc 01wb ...
909 * pire tout audio puis tout video ou vice versa
911 /* TODO : * a better method to realign
912 * verify that we are reading in p_movi
913 * XXX be sure to send audio before video to avoid click
916 riffchunk_t *p_chunk;
919 demux_data_avi_file_t *p_avi_demux;
921 AVIStreamInfo_t *p_info_video;
922 AVIStreamInfo_t *p_info_audio;
923 AVIStreamInfo_t *p_info;
924 /* XXX arrive pas a avoir acces a cette fct°
925 input_ClockManageRef( p_input,
926 p_input->stream.p_selected_program,
928 p_avi_demux = (demux_data_avi_file_t*)p_input->p_demux_data;
930 /* search video and audio stream selected */
934 for( i = 0; i < p_avi_demux->i_streams; i++ )
936 if( p_avi_demux->pp_info[i]->p_es->p_decoder_fifo != NULL )
938 switch( p_avi_demux->pp_info[i]->p_es->i_cat )
941 p_info_video = p_avi_demux->pp_info[i];
944 p_info_audio = p_avi_demux->pp_info[i];
950 p_avi_demux->pp_info[i]->b_unselected = 1;
953 if( p_info_video == NULL )
955 intf_ErrMsg( "input error: no video ouput selected" );
959 if( input_ClockManageControl( p_input, p_input->stream.p_selected_program,
960 (mtime_t)0) == PAUSE_S )
962 __AVI_SynchroReInit( p_input, p_info_video, p_info_audio );
965 /* after updated p_avi_demux->pp_info[i]->b_unselected !! */
966 if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
968 __AVI_ReAlign( p_input, p_info_video ); /*on se realigne pr la video */
969 __AVI_SynchroReInit( p_input, p_info_video, p_info_audio );
972 /* update i_date if previously unselected ES (ex: 2 channels audio ) */
973 if( (p_info_audio != NULL)&&(p_info_audio->b_unselected ))
975 /* we have to go to the good pts */
976 /* we will reach p_info_ok pts */
977 while( __AVI_GetPTS( p_info_audio) < __AVI_GetPTS( p_info_video) )
979 __AVI_NextIndexEntry( p_input, p_info_audio );
981 p_info_audio->b_unselected = 0 ;
984 /* what stream we should read in first */
985 if( p_info_audio == NULL )
987 p_info = p_info_video;
991 if( __AVI_GetPTS( p_info_audio ) <=
992 __AVI_GetPTS( p_info_video ) )
994 p_info = p_info_audio;
998 p_info = p_info_video;
1002 /* go to the good chunk to read */
1004 __AVI_SeekToChunk( p_input, p_info );
1006 /* now we just need to read a chunk */
1007 if( (p_chunk = RIFF_ReadChunk( p_input )) == NULL )
1009 intf_ErrMsg( "input demux: cannot read chunk" );
1013 if( (p_chunk->i_id&0xFFFF0000) !=
1014 (p_info->p_index[p_info->i_idxpos].i_id&0xFFFF0000) )
1016 intf_WarnMsg( 2, "input demux: bad index entry" );
1017 __AVI_NextIndexEntry( p_input, p_info );
1021 intf_WarnMsg( 6, "input demux: read %4.4s chunk %d bytes",
1022 (char*)&p_chunk->i_id,
1025 if( RIFF_LoadChunkDataInPES(p_input, p_chunk, &p_pes) != 0 )
1027 intf_ErrMsg( "input error: cannot read data" );
1031 p_pes->i_rate = p_input->stream.control.i_rate;
1032 p_pes->i_pts = p_avi_demux->i_date + __AVI_GetPTS( p_info );
1035 /* send to decoder */
1036 vlc_mutex_lock( &p_info->p_es->p_decoder_fifo->data_lock );
1037 /* change MAX_PACKET and replace it to have same duration of audio
1038 and video in buffer, to avoid unsynchronization while seeking */
1039 if( p_info->p_es->p_decoder_fifo->i_depth >= MAX_PACKETS_IN_FIFO )
1041 /* Wait for the decoder. */
1042 vlc_cond_wait( &p_info->p_es->p_decoder_fifo->data_wait,
1043 &p_info->p_es->p_decoder_fifo->data_lock );
1045 vlc_mutex_unlock( &p_info->p_es->p_decoder_fifo->data_lock );
1046 input_DecodePES( p_info->p_es->p_decoder_fifo, p_pes );
1048 __AVI_NextIndexEntry( p_input, p_info );
1049 if( p_info->i_idxpos >= p_info->i_idxnb )
1051 /* reach end of p_index , to be corrected to use p_movi instead */