]> git.sesse.net Git - vlc/commitdiff
* ./plugins/ac3_adec/* use _M to avoid conflict with libavcodec.a
authorLaurent Aimar <fenrir@videolan.org>
Tue, 23 Apr 2002 23:44:36 +0000 (23:44 +0000)
committerLaurent Aimar <fenrir@videolan.org>
Tue, 23 Apr 2002 23:44:36 +0000 (23:44 +0000)
* ./plugins/avi a light  avi demux
* ./plugins/ffmpeg a video decoder for divx v3 and opendivx

18 files changed:
include/input_ext-dec.h
plugins/ac3_adec/ac3_adec.c
plugins/ac3_adec/ac3_decoder.c
plugins/ac3_adec/ac3_decoder.h
plugins/ac3_adec/ac3_imdct.c
plugins/ac3_adec/ac3_internal.h
plugins/avi/Makefile
plugins/avi/avi.c [new file with mode: 0644]
plugins/avi/avi.h [new file with mode: 0644]
plugins/avi/fourcc.h [new file with mode: 0644]
plugins/avi/libLE.c [new file with mode: 0644]
plugins/avi/libioRIFF.c [new file with mode: 0644]
plugins/ffmpeg/Makefile
plugins/ffmpeg/ffmpeg.c [new file with mode: 0644]
plugins/ffmpeg/ffmpeg.h [new file with mode: 0644]
plugins/mad/mad_adec.c
plugins/mpeg_adec/mpeg_adec.c
src/input/input_programs.c

index 8b7a2a1c0f1c3e2773dc0d1fbe27e6f7fc9110d7..ea2657ac150187babc66ebabe0ca18bf3b1e4f29 100644 (file)
@@ -2,7 +2,7 @@
  * input_ext-dec.h: structures exported to the VideoLAN decoders
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: input_ext-dec.h,v 1.54 2002/03/14 01:35:28 stef Exp $
+ * $Id: input_ext-dec.h,v 1.55 2002/04/23 23:44:36 fenrir Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *          Michel Kaempf <maxx@via.ecp.fr>
@@ -31,6 +31,8 @@
 /* These ones might violate the norm : */
 #define DVD_SPU_ES          0x82
 #define LPCM_AUDIO_ES       0x83
+#define MSMPEG4_VIDEO_ES    0x90
+#define MPEG4_VIDEO_ES      0x91
 #define UNKNOWN_ES          0xFF
 
 /* Structures exported to the decoders */
index 102c553586c673d2a6c900251f6cd12ec46d4825..d427c8c213d5534d52c7045cb38beed9b24dfcd8 100644 (file)
@@ -2,7 +2,7 @@
  * ac3_adec.c: ac3 decoder module main file
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: ac3_adec.c,v 1.27 2002/04/23 14:16:20 sam Exp $
+ * $Id: ac3_adec.c,v 1.28 2002/04/23 23:44:36 fenrir Exp $
  *
  * Authors: Michel Lespinasse <walken@zoy.org>
  *
@@ -214,7 +214,7 @@ static int InitThread( ac3dec_thread_t * p_ac3thread )
     IMDCT->w_64   = vlc_memalign( 16, 64 * sizeof(complex_t),
                                   &IMDCT->w_64_orig );
 
-    ac3_init( p_ac3thread->ac3_decoder );
+    _M( ac3_init )( p_ac3thread->ac3_decoder );
 
     /*
      * Initialize the output properties
index f895cbcca0b21157ccbfc92cc3bd84b60718fe6a..6768d9af6e07ba96f7ec0b1c1dd758ef8c9c20b4 100644 (file)
@@ -2,7 +2,7 @@
  * ac3_decoder.c: core ac3 decoder
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: ac3_decoder.c,v 1.6 2001/12/30 07:09:54 sam Exp $
+ * $Id: ac3_decoder.c,v 1.7 2002/04/23 23:44:36 fenrir Exp $
  *
  * Authors: Michel Kaempf <maxx@via.ecp.fr>
  *          Michel Lespinasse <walken@zoy.org>
 static const float cmixlev_lut[4] = { 0.707, 0.595, 0.500, 0.707 };
 static const float smixlev_lut[4] = { 0.707, 0.500, 0.0  , 0.500 };
 
-int ac3_init (ac3dec_t * p_ac3dec)
+int _M( ac3_init )(ac3dec_t * p_ac3dec)
 {
     p_ac3dec->mantissa.lfsr_state = 1;          /* dither_gen initialization */
-    imdct_init(p_ac3dec->imdct);
+    _M( imdct_init )(p_ac3dec->imdct) ;
     
     return 0;
 }
index 609776dc580f1d57a8d88764cc20955b9b1a4eea..a21ab06e821f03fb51f62764dcf8460708fbb96d 100644 (file)
@@ -2,7 +2,7 @@
  * ac3_decoder.h : ac3 decoder interface
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
- * $Id: ac3_decoder.h,v 1.3 2002/04/05 01:05:22 gbazin Exp $
+ * $Id: ac3_decoder.h,v 1.4 2002/04/23 23:44:36 fenrir Exp $
  *
  * Authors: Michel Kaempf <maxx@via.ecp.fr>
  *          Renaud Dartus <reno@videolan.org>
@@ -35,7 +35,7 @@ typedef struct ac3_sync_info_s {
 
 /**** ac3 decoder API - functions publically provided by the ac3 decoder ****/
 
-int ac3_init (ac3dec_t * p_ac3dec);
+int _M( ac3_init )(ac3dec_t * p_ac3dec);
 int ac3_sync_frame (ac3dec_t * p_ac3dec, ac3_sync_info_t * p_sync_info);
 int ac3_decode_frame (ac3dec_t * p_ac3dec, s16 * buffer);
 
index 2bd40e2ca7b82bbed0477f28ade17e427a1c4018..ae9e67abc90840f7e897518e55c6571fc78f6703 100644 (file)
@@ -2,7 +2,7 @@
  * ac3_imdct.c: ac3 DCT
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: ac3_imdct.c,v 1.7 2001/12/30 07:09:54 sam Exp $
+ * $Id: ac3_imdct.c,v 1.8 2002/04/23 23:44:36 fenrir Exp $
  *
  * Authors: Michel Kaempf <maxx@via.ecp.fr>
  *          Aaron Holtzman <aholtzma@engr.uvic.ca>
@@ -44,7 +44,7 @@
 #   define M_PI 3.14159265358979323846
 #endif
 
-void imdct_init(imdct_t * p_imdct)
+void _M( imdct_init )(imdct_t * p_imdct)
 {
     int i;
     float scale = 181.019;
index 3768304b125b2d9b4f0a5a9e805a147b49fe76da..e6923ec24b45b5be4b44586cd20eeb8efe0d0db3 100644 (file)
@@ -2,7 +2,7 @@
  * ac3_internals.h: needed by the ac3 decoder
  *****************************************************************************
  * Copyright (C) 2000 VideoLAN
- * $Id: ac3_internal.h,v 1.1 2001/11/13 12:09:17 henri Exp $
+ * $Id: ac3_internal.h,v 1.2 2002/04/23 23:44:36 fenrir Exp $
  *
  * Authors: Michel Lespinasse <walken@zoy.org>
  *
@@ -40,7 +40,7 @@ void bit_allocate (ac3dec_t *);
 int exponent_unpack (ac3dec_t *);
 
 /* ac3_imdct.c */
-void imdct_init (imdct_t * p_imdct);
+void _M( imdct_init )(imdct_t * p_imdct);
 void imdct (ac3dec_t * p_ac3dec, s16 * buffer);
 
 /* ac3_mantissa.c */
index 573ef264ec0dcb044da88ee22e157c289e4ccffd..c2cc066714f3c291acd0541a6cc6a737a2a27521 100644 (file)
@@ -1 +1,2 @@
-avi_SOURCES = 
+avi_SOURCES = avi.c
+
diff --git a/plugins/avi/avi.c b/plugins/avi/avi.c
new file mode 100644 (file)
index 0000000..b86d4b6
--- /dev/null
@@ -0,0 +1,1076 @@
+/*****************************************************************************
+ * avi.c : AVI file Stream input module for vlc
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: avi.c,v 1.1 2002/04/23 23:44:36 fenrir Exp $
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h>                                      /* malloc(), free() */
+#include <string.h>                                              /* strdup() */
+#include <errno.h>
+#include <sys/types.h>
+
+#include <videolan/vlc.h>
+
+#include "stream_control.h"
+#include "input_ext-intf.h"
+#include "input_ext-dec.h"
+#include "input_ext-plugins.h"
+
+/*****************************************************************************
+ * Constants
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static void input_getfunctions( function_list_t * p_function_list );
+static int  AVIDemux         ( struct input_thread_s * );
+static int  AVIInit          ( struct input_thread_s * );
+static void AVIEnd           ( struct input_thread_s * );
+
+/*****************************************************************************
+ * Build configuration tree.
+ *****************************************************************************/
+MODULE_CONFIG_START
+MODULE_CONFIG_STOP
+
+MODULE_INIT_START
+    SET_DESCRIPTION( "RIFF-AVI Stream input" )
+    ADD_CAPABILITY( DEMUX, 150 )
+    ADD_SHORTCUT( "avi" )
+MODULE_INIT_STOP
+
+MODULE_ACTIVATE_START
+    input_getfunctions( &p_module->p_functions->demux );
+MODULE_ACTIVATE_STOP
+
+MODULE_DEACTIVATE_START
+MODULE_DEACTIVATE_STOP
+
+/*****************************************************************************
+ * Definition of structures and libraries for this plugins 
+ *****************************************************************************/
+#include "fourcc.h"
+#include "libLE.c"
+#include "libioRIFF.c"
+#include "avi.h"
+
+/*****************************************************************************
+ * Functions exported as capabilities. They are declared as static so that
+ * we don't pollute the namespace too much.
+ *****************************************************************************/
+static void input_getfunctions( function_list_t * p_function_list )
+{
+#define input p_function_list->functions.demux
+    input.pf_init             = AVIInit;
+    input.pf_end              = AVIEnd;
+    input.pf_demux            = AVIDemux;
+    input.pf_rewind           = NULL;
+#undef input
+}
+
+/********************************************************************/
+
+
+static void __AVIFreeDemuxData( input_thread_t *p_input )
+{
+    int i;
+    demux_data_avi_file_t *p_avi_demux;
+    p_avi_demux = (demux_data_avi_file_t*)p_input->p_demux_data  ; 
+    
+    if( p_avi_demux->p_riff != NULL ) 
+            RIFF_DeleteChunk( p_input->p_demux_data, p_avi_demux->p_riff );
+    if( p_avi_demux->p_hdrl != NULL ) 
+            RIFF_DeleteChunk( p_input->p_demux_data, p_avi_demux->p_hdrl );
+    if( p_avi_demux->p_movi != NULL ) 
+            RIFF_DeleteChunk( p_input->p_demux_data, p_avi_demux->p_movi );
+    if( p_avi_demux->p_idx1 != NULL ) 
+            RIFF_DeleteChunk( p_input->p_demux_data, p_avi_demux->p_idx1 );
+    return;
+    if( p_avi_demux->pp_info != NULL )
+    {
+        for( i = 0; i < p_avi_demux->i_streams; i++ )
+        {
+            if( p_avi_demux->pp_info[i] != NULL ) 
+            {
+#define p_info p_avi_demux->pp_info[i]
+                if( p_info->p_strl != NULL ) 
+                      RIFF_DeleteChunk( p_input->p_demux_data, p_info->p_strl );
+                if( p_info->p_strh != NULL ) 
+                      RIFF_DeleteChunk( p_input->p_demux_data,p_info->p_strh );
+                if( p_info->p_strf != NULL ) 
+                      RIFF_DeleteChunk( p_input->p_demux_data,p_info->p_strf );
+                if( p_info->p_strd != NULL ) 
+                      RIFF_DeleteChunk( p_input->p_demux_data,p_info->p_strd );
+                if( p_info->p_index != NULL )
+                      free( p_info->p_index ); 
+                free( p_info ); 
+#undef  p_info
+            }
+        }
+         free( p_avi_demux->pp_info );
+    }
+}
+
+static void __AVI_Parse_avih( MainAVIHeader_t *p_avih, byte_t *p_buff )
+{
+    p_avih->i_microsecperframe = __GetDoubleWordLittleEndianFromBuff( p_buff );
+    p_avih->i_maxbytespersec = __GetDoubleWordLittleEndianFromBuff( p_buff + 4);
+    p_avih->i_reserved1 = __GetDoubleWordLittleEndianFromBuff( p_buff + 8);
+    p_avih->i_flags = __GetDoubleWordLittleEndianFromBuff( p_buff + 12);
+    p_avih->i_totalframes = __GetDoubleWordLittleEndianFromBuff( p_buff + 16);
+    p_avih->i_initialframes = __GetDoubleWordLittleEndianFromBuff( p_buff + 20);
+    p_avih->i_streams = __GetDoubleWordLittleEndianFromBuff( p_buff + 24);
+    p_avih->i_suggestedbuffersize = 
+                        __GetDoubleWordLittleEndianFromBuff( p_buff + 28);
+    p_avih->i_width = __GetDoubleWordLittleEndianFromBuff( p_buff + 32 );
+    p_avih->i_height = __GetDoubleWordLittleEndianFromBuff( p_buff + 36 );
+    p_avih->i_scale = __GetDoubleWordLittleEndianFromBuff( p_buff + 40 );
+    p_avih->i_rate = __GetDoubleWordLittleEndianFromBuff( p_buff + 44 );
+    p_avih->i_start = __GetDoubleWordLittleEndianFromBuff( p_buff + 48);
+    p_avih->i_length = __GetDoubleWordLittleEndianFromBuff( p_buff + 52);
+}
+
+static void __AVI_Parse_Header( AVIStreamHeader_t *p_strh, byte_t *p_buff )
+{
+    p_strh->i_type = __GetDoubleWordLittleEndianFromBuff( p_buff );
+    p_strh->i_handler = __GetDoubleWordLittleEndianFromBuff( p_buff + 4 );
+    p_strh->i_flags = __GetDoubleWordLittleEndianFromBuff( p_buff + 8 );
+    p_strh->i_reserved1 = __GetDoubleWordLittleEndianFromBuff( p_buff + 12);
+    p_strh->i_initialframes = __GetDoubleWordLittleEndianFromBuff( p_buff + 16);
+    p_strh->i_scale = __GetDoubleWordLittleEndianFromBuff( p_buff + 20);
+    p_strh->i_rate = __GetDoubleWordLittleEndianFromBuff( p_buff + 24);
+    p_strh->i_start = __GetDoubleWordLittleEndianFromBuff( p_buff + 28);
+    p_strh->i_length = __GetDoubleWordLittleEndianFromBuff( p_buff + 32);
+    p_strh->i_suggestedbuffersize = 
+                        __GetDoubleWordLittleEndianFromBuff( p_buff + 36);
+    p_strh->i_quality = __GetDoubleWordLittleEndianFromBuff( p_buff + 40);
+    p_strh->i_samplesize = __GetDoubleWordLittleEndianFromBuff( p_buff + 44);
+}
+
+int avi_ParseBitMapInfoHeader( bitmapinfoheader_t *h, byte_t *p_data )
+{
+    h->i_size          = __GetDoubleWordLittleEndianFromBuff( p_data );
+    h->i_width         = __GetDoubleWordLittleEndianFromBuff( p_data + 4 );
+    h->i_height        = __GetDoubleWordLittleEndianFromBuff( p_data + 8 );
+    h->i_planes        = __GetWordLittleEndianFromBuff( p_data + 12 );
+    h->i_bitcount      = __GetWordLittleEndianFromBuff( p_data + 14 );
+    h->i_compression   = __GetDoubleWordLittleEndianFromBuff( p_data + 16 );
+    h->i_sizeimage     = __GetDoubleWordLittleEndianFromBuff( p_data + 20 );
+    h->i_xpelspermeter = __GetDoubleWordLittleEndianFromBuff( p_data + 24 );
+    h->i_ypelspermeter = __GetDoubleWordLittleEndianFromBuff( p_data + 28 );
+    h->i_clrused       = __GetDoubleWordLittleEndianFromBuff( p_data + 32 );
+    h->i_clrimportant  = __GetDoubleWordLittleEndianFromBuff( p_data + 36 );
+    return( 0 );
+}
+
+int avi_ParseWaveFormatEx( waveformatex_t *h, byte_t *p_data )
+{
+    h->i_formattag     = __GetWordLittleEndianFromBuff( p_data );
+    h->i_channels      = __GetWordLittleEndianFromBuff( p_data + 2 );
+    h->i_samplespersec = __GetDoubleWordLittleEndianFromBuff( p_data + 4 );
+    h->i_avgbytespersec= __GetDoubleWordLittleEndianFromBuff( p_data + 8 );
+    h->i_blockalign    = __GetWordLittleEndianFromBuff( p_data + 12 );
+    h->i_bitspersample = __GetWordLittleEndianFromBuff( p_data + 14 );
+    h->i_size          = __GetWordLittleEndianFromBuff( p_data + 16 );
+    return( 0 );
+}
+
+static int __AVI_ParseStreamHeader( u32 i_id, int *i_number, u16 *i_type )
+{
+    int c1,c2,c3,c4;
+    char str[3];
+
+    c1 = ( i_id ) & 0xFF;
+    c2 = ( i_id >>  8 ) & 0xFF;
+    c3 = ( i_id >> 16 ) & 0xFF;
+    c4 = ( i_id >> 24 ) & 0xFF;
+
+    if( c1 < '0' || c1 > '9' || c2 < '0' || c2 > '9' )
+    {
+        return( -1 );
+    }
+    str[0] = c1;
+    str[1] = c2;
+    str[2] = 0;
+    *i_number = atoi( str );
+    *i_type = ( c3 << 8) + c4;
+    return( 0 );
+}   
+
+static int __AVI_HeaderMoviValid( u32 i_header )
+{
+    switch( i_header&0xFFFF0000 )
+    {
+        case( TWOCC_wb ):
+        case( TWOCC_db ):
+        case( TWOCC_dc ):
+        case( TWOCC_pc ):
+            return( 1 );
+            break;
+    }
+    switch( i_header )
+    {
+        case( FOURCC_LIST ):
+        case( FOURCC_JUNK ):
+            return( 1 );
+            break;
+    }
+    return( 0 );
+}
+
+static void __AVI_AddEntryIndex( AVIStreamInfo_t *p_info,
+                                 AVIIndexEntry_t *p_index)
+{
+    if( p_info->p_index == NULL )
+    {
+        p_info->i_idxmax = 4096;
+        p_info->i_idxnb = 0;
+        p_info->p_index = calloc( p_info->i_idxmax, 
+                                  sizeof( AVIIndexEntry_t ) );
+    }
+    if( p_info->i_idxnb >= p_info->i_idxmax )
+    {
+        p_info->i_idxmax += 4096;
+        p_info->p_index = realloc( (void*)p_info->p_index,
+                                    p_info->i_idxmax * 
+                                    sizeof( AVIIndexEntry_t ) );
+    }
+    /* calculate cumulate length */
+    if( p_info->i_idxnb > 0 )
+    {
+        p_index->i_lengthtotal = p_index->i_length +
+            p_info->p_index[p_info->i_idxnb-1].i_lengthtotal;
+    }
+    else
+    {
+        p_index->i_lengthtotal = 0;
+    }
+
+    p_info->p_index[p_info->i_idxnb] = *p_index;
+    p_info->i_idxnb++;
+}
+
+static void __AVI_GetIndex( input_thread_t *p_input )
+{
+    demux_data_avi_file_t *p_avi_demux;
+    AVIIndexEntry_t index;
+    byte_t          *p_buff;
+    riffchunk_t     *p_idx1;
+    int             i_read;
+    int             i;
+    int             i_number;
+    u16             i_type;
+    
+    p_avi_demux = (demux_data_avi_file_t*)p_input->p_demux_data  ;    
+
+    if( RIFF_FindAndGotoDataChunk( p_input,
+                                   p_avi_demux->p_riff, 
+                                   &p_idx1, 
+                                   FOURCC_idx1)!=0 )
+    {
+        intf_WarnMsg( 1, "input init: cannot find index" );
+        RIFF_GoToChunk( p_input, p_avi_demux->p_hdrl );        
+        return;
+    }
+    p_avi_demux->p_idx1 = p_idx1;
+    intf_WarnMsg( 1, "input init: loading index" ); 
+    for(;;)
+    {
+        if( (i_read = input_Peek( p_input, &p_buff, 16*1024 )) < 16 )
+        {
+            for( i = 0, i_read = 0; i < p_avi_demux->i_streams; i++ )
+            {
+                i_read += p_avi_demux->pp_info[i]->i_idxnb;
+            }
+            intf_WarnMsg( 1,"input info: read %d idx chunk", i_read );
+            return;
+        }
+        i_read /= 16 ;
+        /* try to verify if we are beyond end of p_idx1 */
+        for( i = 0; i < i_read; i++ )
+        {
+            byte_t  *p_peek = p_buff + i * 16;
+            index.i_id = __GetDoubleWordLittleEndianFromBuff( p_peek );
+            index.i_flags = __GetDoubleWordLittleEndianFromBuff( p_peek+4);
+            index.i_offset = __GetDoubleWordLittleEndianFromBuff( p_peek+8);
+            index.i_length = __GetDoubleWordLittleEndianFromBuff(p_peek+12);
+            
+            if( (__AVI_ParseStreamHeader( index.i_id, &i_number, &i_type ) != 0)
+             ||(i_number > p_avi_demux->i_streams)) 
+            {
+                continue;
+            }
+            __AVI_AddEntryIndex( p_avi_demux->pp_info[i_number],
+                                 &index );
+        }
+        __RIFF_SkipBytes( p_input, 16 * i_read );
+    }
+
+}
+static int __AVI_SeekToChunk( input_thread_t *p_input, AVIStreamInfo_t *p_info )
+{
+    demux_data_avi_file_t *p_avi_demux;
+    p_avi_demux = (demux_data_avi_file_t*)p_input->p_demux_data;
+    
+    if( (p_info->p_index != NULL)&&(p_info->i_idxpos < p_info->i_idxnb) )
+    {
+        /* perfect */
+        off_t i_pos;
+        i_pos = (off_t)p_info->p_index[p_info->i_idxpos].i_offset +
+                    p_info->i_idxoffset;
+
+        p_input->pf_seek( p_input, i_pos );
+        input_AccessReinit( p_input );
+        return( 0 );
+    }
+    /* index are no longer valid */
+    if( p_info->p_index != NULL )
+    {
+        return( -1 );
+    }
+    /* no index */
+    return( -1 );
+}
+
+
+/* XXX call after get p_movi */
+static int __AVI_GetIndexOffset( input_thread_t *p_input )
+{
+    riffchunk_t *p_chunk;
+    demux_data_avi_file_t *p_avi_demux;
+    int i;
+
+    p_avi_demux = (demux_data_avi_file_t*)p_input->p_demux_data;
+    for( i = 0; i < p_avi_demux->i_streams; i++ )
+    {
+#define p_info p_avi_demux->pp_info[i]
+        if( p_info->p_index == NULL ) {continue;}
+        p_info->i_idxoffset = 0;
+        __AVI_SeekToChunk( p_input, p_info );
+        p_chunk = RIFF_ReadChunk( p_input );
+        if( (p_chunk == NULL)||(p_chunk->i_id != p_info->p_index[0].i_id) )
+        {
+            p_info->i_idxoffset = p_avi_demux->p_movi->i_pos + 8;
+            __AVI_SeekToChunk( p_input, p_info );
+            p_chunk = RIFF_ReadChunk( p_input );
+            if( (p_chunk == NULL)||(p_chunk->i_id != p_info->p_index[0].i_id) )
+            {
+                intf_WarnMsg( 1, "input demux: can't find offset for stream %d",
+                                i);
+                continue; /* TODO: search manually from p_movi */
+            }
+        }
+#undef p_info
+    }
+    return( 0 );
+}
+static int __AVI_AudioGetType( u32 i_type )
+{
+    switch( i_type )
+    {
+/*        case( WAVE_FORMAT_PCM ):
+            return( WAVE_AUDIO_ES ); */
+        case( WAVE_FORMAT_AC3 ):
+            return( AC3_AUDIO_ES );
+        case( WAVE_FORMAT_MPEG):
+        case( WAVE_FORMAT_MPEGLAYER3):
+            return( MPEG2_AUDIO_ES ); /* 2 for mpeg-2 layer 1 2 ou 3 */
+        default:
+            return( 0 );
+    }
+}
+
+static int __AVI_VideoGetType( u32 i_type )
+{
+    switch( i_type )
+    {
+        case( FOURCC_DIV3 ):
+        case( FOURCC_div3 ):
+        case( FOURCC_DIV4 ):
+        case( FOURCC_div4 ):
+        case( FOURCC_DIV5 ):
+        case( FOURCC_div5 ):
+        case( FOURCC_DIV6 ):
+        case( FOURCC_div6 ):
+        case( FOURCC_3IV1 ):
+        case( FOURCC_AP41 ):
+        case( FOURCC_MP43 ):
+        case( FOURCC_mp43 ):
+            return( MSMPEG4_VIDEO_ES );
+
+        case( FOURCC_DIVX ):
+        case( FOURCC_divx ):
+        case( FOURCC_DX50 ):
+        case( FOURCC_MP4S ):
+        case( FOURCC_MPG4 ):
+        case( FOURCC_mpg4 ):
+        case( FOURCC_mp4v ):
+            return( MPEG4_VIDEO_ES );
+
+        default:
+            return( 0 );
+    }
+}
+/**************************************************************************/
+
+/* Tention: bcp de test Ă  ajouter mais aussi beaucoup de MEMOIRE a DESALLOUER pas fait */
+static int AVIInit( input_thread_t *p_input )
+{
+    riffchunk_t *p_riff,*p_hdrl,*p_movi;
+    riffchunk_t *p_avih;
+    riffchunk_t *p_strl,*p_strh,*p_strf/* ,*p_strd */;
+    
+    demux_data_avi_file_t *p_avi_demux;
+    es_descriptor_t *p_es = NULL; /* for not warning */
+    es_descriptor_t *p_es_video = NULL; 
+    es_descriptor_t *p_es_audio = NULL;
+
+    int i,j;
+    
+    p_avi_demux = malloc( sizeof(demux_data_avi_file_t) );
+    memset( p_avi_demux, 0, sizeof( demux_data_avi_file_t ) );
+    p_input->p_demux_data = p_avi_demux;
+
+    /* FIXME FIXME Je sais pas trop a quoi ca sert juste copiĂ© de ESInit */
+    /* Initialize access plug-in structures. */
+    if( p_input->i_mtu == 0 )
+    {
+        /* Improve speed. */
+        p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
+    }
+
+    if( RIFF_TestFileHeader( p_input, &p_riff, FOURCC_AVI ) != 0 )    
+    {
+        __AVIFreeDemuxData( p_input );
+        intf_ErrMsg( "input: RIFF-AVI plug-in discarded (avi_file)" );
+        return( -1 );
+    }
+    p_avi_demux->p_riff = p_riff;
+
+    if ( RIFF_DescendChunk(p_input) != 0 )
+    {
+        __AVIFreeDemuxData( p_input );
+        intf_ErrMsg( "input error: cannot look for subchunk (avi_file)" );
+        return ( -1 );
+    }
+
+    /* it's a riff-avi file, so search for LIST-hdrl */
+    if( RIFF_FindListChunk(p_input ,&p_hdrl,p_riff, FOURCC_hdrl) != 0 )
+    {
+        __AVIFreeDemuxData( p_input );
+        intf_ErrMsg( "input error: cannot find \"LIST-hdrl\" (avi_file)" );
+        return( -1 );
+    }
+    p_avi_demux->p_hdrl = p_hdrl;
+
+    if( RIFF_DescendChunk(p_input) != 0 )
+    {
+        __AVIFreeDemuxData( p_input );
+        intf_ErrMsg( "input error: cannot look for subchunk (avi_file)" );
+        return ( -1 );
+    }
+    /* ds  LIST-hdrl cherche avih */
+    if( RIFF_FindAndLoadChunk( p_input, p_hdrl, 
+                                    &p_avih, FOURCC_avih ) != 0 )
+    {
+        __AVIFreeDemuxData( p_input );
+        intf_ErrMsg( "input error: cannot find \"avih\" chunk (avi_file)" );
+        return( -1 );
+    }
+    __AVI_Parse_avih( &p_avi_demux->avih, p_avih->p_data->p_payload_start );
+    RIFF_DeleteChunk( p_input, p_avih );
+    
+    if( p_avi_demux->avih.i_streams == 0 )  
+            /* aucun flux defini, peut etre essayer de trouver ss connaitre */
+                                      /* le nombre serait pas mal, a voir */
+    {
+        __AVIFreeDemuxData( p_input );
+        intf_ErrMsg( "input error: no defined stream !" );
+        return( -1 );
+    }
+    
+    /* On creer les tableau pr les flux */
+    p_avi_demux->i_streams = p_avi_demux->avih.i_streams;
+    
+    p_avi_demux->pp_info = calloc( p_avi_demux->i_streams, 
+                                    sizeof( AVIStreamInfo_t* ) );
+    memset( p_avi_demux->pp_info, 0, 
+                        sizeof( AVIStreamInfo_t* ) * p_avi_demux->i_streams );
+    
+    for( i = 0 ; i < p_avi_demux->i_streams; i++ )
+    {
+        p_avi_demux->pp_info[i] = malloc( sizeof(AVIStreamInfo_t ) );
+        memset( p_avi_demux->pp_info[i], 0, sizeof( AVIStreamInfo_t ) );        
+
+        /* pour chaque flux on cherche ses infos */
+        if( RIFF_FindListChunk(p_input,
+                                &p_strl,p_hdrl, FOURCC_strl) != 0 )
+        {
+            __AVIFreeDemuxData( p_input );
+            intf_ErrMsg( "input error: cannot find \"LIST-strl\" (avi_file)" );
+            return( -1 );
+        }
+        p_avi_demux->pp_info[i]->p_strl = p_strl;
+        
+        if( RIFF_DescendChunk(p_input) != 0 )
+        {
+            __AVIFreeDemuxData( p_input );
+            intf_ErrMsg( "input error: cannot look for subchunk (avi_file)" );
+            return ( -1 );
+        }
+        /* ds  LIST-strl cherche strh */
+        if( RIFF_FindAndLoadChunk( p_input, p_hdrl, 
+                                &p_strh, FOURCC_strh ) != 0 )
+        {
+            __AVIFreeDemuxData( p_input );
+            intf_ErrMsg( "input error: cannot find \"strh\" (avi_file)" );
+            return( -1 );
+        }
+        p_avi_demux->pp_info[i]->p_strh = p_strh;
+        
+        /* ds  LIST-strl cherche strf */
+        if( RIFF_FindAndLoadChunk( p_input, p_hdrl, 
+                                &p_strf, FOURCC_strf ) != 0 )
+        {
+            __AVIFreeDemuxData( p_input );
+            intf_ErrMsg( "input error: cannot find \"strf\" (avi_file)" );
+            return( -1 );
+        }
+         p_avi_demux->pp_info[i]->p_strf = p_strf;
+        /* FIXME faudrait cherche et charger strd */
+        /* mais a priori pas vraiment utile pr divx */
+
+         if( RIFF_AscendChunk(p_input, p_strl) != 0 )
+        {
+            __AVIFreeDemuxData( p_input );
+            intf_ErrMsg( "input error: cannot go out (\"strl\") (avi_file)" );
+            return( -1 );
+        }
+        
+    }
+    
+
+    if( RIFF_AscendChunk(p_input, p_hdrl) != 0)
+    {
+        __AVIFreeDemuxData( p_input );
+        intf_ErrMsg( "input error: cannot go out (\"hdrl\") (avi_file)" );
+        return( -1 );
+    }
+
+    intf_Msg( "input init: AVIH: %d stream, flags %s%s%s%s%s%s ", 
+            p_avi_demux->i_streams,
+            p_avi_demux->avih.i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
+            p_avi_demux->avih.i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",
+            p_avi_demux->avih.i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
+            p_avi_demux->avih.i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"",
+            p_avi_demux->avih.i_flags&AVIF_WASCAPTUREFILE?" CAPTUREFILE":"",
+            p_avi_demux->avih.i_flags&AVIF_COPYRIGHTED?" COPYRIGHTED":"" );
+
+    /* go to movi chunk */
+    if( RIFF_FindListChunk(p_input ,&p_movi,p_riff, FOURCC_movi) != 0 )
+    {
+        intf_ErrMsg( "input error: cannot find \"LIST-movi\" (avi_file)" );
+        __AVIFreeDemuxData( p_input );
+        return( -1 );
+    }
+    p_avi_demux->p_movi = p_movi;
+    
+    /* get index */
+    if( (p_input->stream.b_seekable)
+         &&((p_avi_demux->avih.i_flags&AVIF_HASINDEX) != 0) )
+    {
+        __AVI_GetIndex( p_input );
+        /* try to get i_idxoffset with first stream*/
+        __AVI_GetIndexOffset( p_input );
+        RIFF_GoToChunk( p_input, p_avi_demux->p_movi );
+    }
+    else
+    {
+        intf_WarnMsg( 1, "input init: cannot get index" );
+    }
+
+    if( RIFF_DescendChunk( p_input ) != 0 )
+    {
+        __AVIFreeDemuxData( p_input );
+        intf_ErrMsg( "input error: cannot go in (\"movi\") (avi_file)" );
+        return( -1 );
+    }
+   /* TODO: check for index and read it if possible( seekable )*/
+
+   /** We have now finished with reading the file **/
+   /** we make the last initialisation  **/
+
+    if( input_InitStream( p_input, 0 ) == -1)
+    {
+        __AVIFreeDemuxData( p_input );
+        intf_ErrMsg( "input error: cannot init stream" );
+        return( -1 );
+    }
+
+    if( input_AddProgram( p_input, 0, 0) == NULL )
+    {
+        __AVIFreeDemuxData( p_input );
+        intf_ErrMsg( "input error: cannot add program" );
+        return( -1 );
+    }
+    p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
+    p_input->stream.p_new_program = p_input->stream.pp_programs[0] ;
+            
+    /* FIXME FIXME id des es doit etre unique FIXME FIXME */
+    vlc_mutex_lock( &p_input->stream.stream_lock );
+    for( i = 0; i < p_avi_demux->i_streams; i++ )
+    {
+#define p_info  p_avi_demux->pp_info[i]
+        __AVI_Parse_Header( &p_info->header,
+                        p_info->p_strh->p_data->p_payload_start);
+        switch( p_info->header.i_type )
+        {
+            case( FOURCC_auds ):
+                /* pour l'id j'ai mis 12 pr audio et 42 pour video */
+                /* et le numero du flux(ici i) dans i_stream_id */
+               avi_ParseWaveFormatEx( &p_info->audio_format,
+                                   p_info->p_strf->p_data->p_payload_start ); 
+               p_es = input_AddES( p_input, 
+                                p_input->stream.p_selected_program, 12+i, 
+                                    p_info->p_strf->i_size );
+                p_es->i_cat = AUDIO_ES;
+                p_es->b_audio = 1;
+                p_es->i_type = 
+                    __AVI_AudioGetType( p_info->audio_format.i_formattag );
+                if( p_es->i_type == 0 )
+                {
+                    intf_ErrMsg( "input error: stream(%d,0x%x) not supported",
+                                    i,
+                                    p_info->audio_format.i_formattag );
+                    p_es->i_cat = UNKNOWN_ES;
+                }
+                else
+                {
+                    if( p_es_audio == NULL ) p_es_audio = p_es;
+                }
+                p_es->i_stream_id =i; /* FIXME */                
+                break;
+                
+            case( FOURCC_vids ):
+                avi_ParseBitMapInfoHeader( &p_info->video_format,
+                                   p_info->p_strf->p_data->p_payload_start ); 
+
+                p_es = input_AddES( p_input, 
+                                p_input->stream.p_selected_program, 42+i,
+                                    p_info->p_strf->i_size );
+                p_es->i_cat = VIDEO_ES;
+                p_es->b_audio = 0;
+                p_es->i_type = 
+                    __AVI_VideoGetType( p_info->video_format.i_compression );
+                if( p_es->i_type == 0 )
+                {
+                    intf_ErrMsg( "input error: stream(%d,%4.4s) not supported",
+                               i,
+                               (char*)&p_info->video_format.i_compression);
+                }
+                else
+                {
+                    if( p_es_video == NULL ) p_es_video = p_es;
+                }
+                p_es->i_stream_id =i; /* FIXME */                
+                break;
+            default:
+                p_es = input_AddES( p_input, 
+                                p_input->stream.p_selected_program, 12, 
+                                    p_info->p_strf->i_size );
+                intf_ErrMsg( "input error: unknown stream(%d) type",
+                            i );
+                p_es->i_cat = UNKNOWN_ES;
+                break;
+        }
+        p_info->p_es = p_es;
+        p_info->i_cat = p_es->i_cat;
+        /* We copy strf for decoder in p_es->p_demux_data */
+        for( j = 0; j < p_info->p_strf->i_size; j++ )
+        {
+            *((byte_t*)p_es->p_demux_data + j) =
+                       *(p_info->p_strf->p_data->p_payload_start + j);
+        }
+
+        /* print informations on stream */
+        switch( p_es->i_cat )
+        {
+            case( VIDEO_ES ):
+                intf_Msg("input init: video(%4.4s) %dx%d %dbpp %ffps (size %d)",
+                        (char*)&p_info->video_format.i_compression,
+                        p_info->video_format.i_width,
+                        p_info->video_format.i_height,
+                        p_info->video_format.i_bitcount,
+                        (float)p_info->header.i_rate /
+                            (float)p_info->header.i_scale,
+                        p_info->header.i_samplesize );
+                break;
+            case( AUDIO_ES ):
+                intf_Msg( "input init: audio(0x%x) %d channels %dHz %dbits %ffps (size %d)",
+                        p_info->audio_format.i_formattag,
+                        p_info->audio_format.i_channels,
+                        p_info->audio_format.i_samplespersec,
+                        p_info->audio_format.i_bitspersample,
+                        (float)p_info->header.i_rate /
+                            (float)p_info->header.i_scale,
+                        p_info->header.i_samplesize );
+                break;
+        }
+
+#undef p_info    
+    }
+
+    /* we select the first audio and video ES */
+    if( p_es_audio != NULL ) 
+    {
+        input_SelectES( p_input, p_es_audio );
+    }
+    else
+    {
+        intf_Msg( "input init: no audio stream found !" );
+    }
+    if( p_es_video != NULL ) 
+    {
+        input_SelectES( p_input, p_es_video );
+    }
+    else
+    {
+        intf_ErrMsg( "input error: no video stream found !" );
+        return( -1 );
+        vlc_mutex_unlock( &p_input->stream.stream_lock );
+   }
+    /* p_input->stream.p_selected_area->i_tell = 0; */
+    p_input->stream.i_mux_rate = p_avi_demux->avih.i_maxbytespersec / 50;
+    p_input->stream.p_selected_program->b_is_ok = 1;
+    vlc_mutex_unlock( &p_input->stream.stream_lock );
+    
+    /* stoker les donnes p_demux_data dans p_input */
+    return( 0 );
+}
+
+static void AVIEnd( input_thread_t *p_input )
+{   
+    __AVIFreeDemuxData( p_input ); 
+    return;
+}
+
+
+static mtime_t __AVI_GetPTSAudio( AVIStreamInfo_t *p_info )
+{
+    /* XXX you need to had p_info->i_date to have correct pts */
+    /* p_info->p_index[p_info->i_idxpos] need to be valid !! */
+    mtime_t i_pts;
+
+    /* be careful to  *1000000 before round  ! */
+    if( p_info->header.i_samplesize != 0 )
+    {
+        i_pts = (mtime_t)( (double)1000000.0 *
+                    (double)p_info->p_index[p_info->i_idxpos].i_lengthtotal *
+                    (double)p_info->header.i_scale /
+                    (double)p_info->header.i_rate);
+    }
+    else
+    {
+        i_pts = (mtime_t)( (double)1000000.0 *
+                    (double)p_info->i_idxpos *
+                    (double)p_info->header.i_scale /
+                    (double)p_info->header.i_rate);
+    }
+    return( i_pts );
+}
+
+static mtime_t  __AVI_GetPTSVideo( AVIStreamInfo_t *p_info )
+{
+    /* XXX you need to had p_info->i_date to have correct pts */
+    mtime_t i_pts;
+    i_pts = (mtime_t)( (double)1000000.0 *
+                (double)p_info->i_idxpos  *
+                (double)p_info->header.i_scale /
+                (double)p_info->header.i_rate);
+    return( i_pts );
+}
+
+static mtime_t __AVI_GetPTS( AVIStreamInfo_t *p_info )
+{
+    switch( p_info->i_cat )
+    {
+        case( AUDIO_ES ):
+            return( __AVI_GetPTSAudio( p_info ) );
+        case( VIDEO_ES ):
+            return( __AVI_GetPTSVideo( p_info ) );
+        default:
+            return( mdate() + DEFAULT_PTS_DELAY ); 
+    }
+}
+
+static void __AVI_ControleUnPause()
+{
+}
+
+static void __AVI_NextIndexEntry( input_thread_t *p_input, 
+                                  AVIStreamInfo_t *p_info )
+{
+   p_info->i_idxpos++;
+   if( p_info->i_idxpos >= p_info->i_idxnb )
+   {
+        /* we need to verify if we reach end of file
+            or if index is broken and search manually */
+   }
+}
+
+static void __AVI_ReInitDate( demux_data_avi_file_t *p_avi_demux )
+{
+    mtime_t i_ptsmin = 0;
+    int i;
+    int b_first = 1;
+    for( i = 0; i < p_avi_demux->i_streams; i++ )
+    {
+#define p_info p_avi_demux->pp_info[i]
+        if( (p_info->p_es->p_decoder_fifo != NULL)
+             &&( !p_info->b_unselected ) )
+        {
+            i_ptsmin = __MIN( i_ptsmin, 
+                              __AVI_GetPTS( p_info ) );
+            if( b_first )
+            {
+                i_ptsmin = __AVI_GetPTS( p_info );
+                b_first = 0;
+            }
+        }
+#undef p_info
+    }
+    
+    p_avi_demux->i_date = mdate() + DEFAULT_PTS_DELAY - i_ptsmin;
+}
+
+static int __AVI_ReAlign( input_thread_t *p_input, 
+                            AVIStreamInfo_t  *p_info )
+{
+    u32     i_pos;
+    int     i_idxpos;
+    __RIFF_TellPos( p_input, &i_pos );
+    
+    /* TODO verifier si on est dans p_movi */
+    
+    if( p_info->p_index[p_info->i_idxnb-1].i_offset + 
+                    p_info->i_idxoffset < i_pos )
+    {
+        return( -1 ); 
+    }
+    
+    i_idxpos = p_info->i_idxpos;
+    i_pos -= p_info->i_idxoffset;
+    if( i_pos < 0 )    
+    {
+        p_info->i_idxpos = 0;
+        return( 0 );
+    }
+
+    while( p_info->p_index[i_idxpos].i_offset > i_pos )
+    {
+        i_idxpos--;
+        if( i_idxpos <= 0 ) { return( -1 );}
+    }
+    
+    while( p_info->p_index[i_idxpos].i_offset + 
+                    p_info->p_index[i_idxpos].i_length < i_pos )
+    {
+        i_idxpos++;
+        if( i_idxpos >= p_info->i_idxnb ) { return( -1 );}
+    }
+
+    p_info->i_idxpos = i_idxpos; 
+    return( 0 );
+}
+        
+/** -1 in case of error, 0 of EOF, 1 otherwise **/
+static int AVIDemux( input_thread_t *p_input )
+{
+    /* on cherche un block
+       plusieurs cas :
+        * encapsuler dans un chunk "rec "
+        * juste une succesion de 00dc 01wb ...
+        * pire tout audio puis tout video ou vice versa
+     */
+    /*  
+From xine-lib :
+static uint32_t get_audio_pts (demux_avi_t *this, long posc, long posb) 
+{   
+    if (this->avi->dwSampleSize==0)
+        return posc * (double) this->avi->dwScale_audio / this->avi->dwRate_audio * 90000.0;
+    else
+        return (this->avi->audio_index[posc].tot+posb)/this->avi->dwSampleSize * (double) this->avi->dwScale_audio / this->avi->dwRate_audio * 90000.0;
+}
+static uint32_t get_video_pts (demux_avi_t *this, long pos) 
+{
+    return pos * (double) this->avi->dwScale / this->avi->dwRate * 90000.0;
+}
+     */
+/* TODO :   * a better method to realign
+            * verify that we are reading in p_movi 
+            * XXX be sure to send audio before video to avoid click
+            * 
+ */
+    riffchunk_t *p_chunk;
+    int i;
+    pes_packet_t *p_pes;
+    demux_data_avi_file_t *p_avi_demux;
+
+    AVIStreamInfo_t *p_info_video;
+    AVIStreamInfo_t *p_info_audio;
+    AVIStreamInfo_t *p_info;
+    /* XXX arrive pas a avoir acces a cette fct° 
+    input_ClockManageRef( p_input,
+                            p_input->stream.p_selected_program,
+                            (mtime_t)0 ); */
+    p_avi_demux = (demux_data_avi_file_t*)p_input->p_demux_data;
+
+    /* search video and audio stream selected */
+    p_info_video = NULL;
+    p_info_audio = NULL;
+    
+    for( i = 0; i < p_avi_demux->i_streams; i++ )
+    {
+        if( p_avi_demux->pp_info[i]->p_es->p_decoder_fifo != NULL )
+        {
+            switch( p_avi_demux->pp_info[i]->p_es->i_cat )
+            {
+                case( VIDEO_ES ):
+                    p_info_video = p_avi_demux->pp_info[i];
+                    break;
+                case( AUDIO_ES ):
+                    p_info_audio = p_avi_demux->pp_info[i];
+                    break;
+            }
+        }
+        else
+        {
+            p_avi_demux->pp_info[i]->b_unselected = 1;
+        }
+    }
+    if( p_info_video == NULL )
+    {
+        intf_ErrMsg( "input error: no video ouput selected" );
+        return( -1 );
+    }
+    if( input_ClockManageControl( p_input, p_input->stream.p_selected_program,
+                            (mtime_t)0) == PAUSE_S )
+    {   
+        __AVI_ControleUnPause();
+        p_input->stream.p_selected_program->i_synchro_state = SYNCHRO_REINIT;
+    }
+
+    /* after updated p_avi_demux->pp_info[i]->b_unselected  !! */
+    if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
+    { 
+        /* TODO check if we have seek */
+        __AVI_ReAlign( p_input, p_info_video ); /*on se realigne pr la video */
+        p_input->stream.p_selected_program->i_synchro_state = SYNCHRO_OK;
+        p_avi_demux->i_date = mdate() + DEFAULT_PTS_DELAY 
+                        - __AVI_GetPTSVideo( p_info_video );
+        /* TODO: a optimiser */
+        p_info_audio->i_idxpos = 0; 
+        p_info_audio->b_unselected = 1; /* to correct audio */
+       p_input->stream.p_selected_program->i_synchro_state = SYNCHRO_OK;
+    }
+
+     /* update i_date if previously unselected ES (ex: 2 channels audio ) */
+    if( (p_info_audio != NULL)&&(p_info_audio->b_unselected ))
+    {
+         intf_WarnMsg( 1, "input demux: reinit synchro for unselected es" );
+        /* we have to go to the good pts */
+        /* we will reach p_info_ok pts */
+        while( __AVI_GetPTS( p_info_audio) < __AVI_GetPTS( p_info_video) )
+        {
+            __AVI_NextIndexEntry( p_input, p_info_audio );
+        }
+       p_info_audio->b_unselected = 0 ;
+    }
+  
+    /* what stream we should read in first */
+    if( p_info_audio == NULL )
+    {
+        p_info = p_info_video;
+    }
+    else
+    {
+        if( __AVI_GetPTSAudio( p_info_audio ) <= 
+                        __AVI_GetPTSVideo( p_info_video ) )
+        {
+            p_info = p_info_audio;
+        }
+        else
+        {
+            p_info = p_info_video;
+        }
+    }
+
+    /* go the good chunk to read */
+
+    __AVI_SeekToChunk( p_input, p_info );
+    
+    /* now we just need to read a chunk */
+    if( (p_chunk = RIFF_ReadChunk( p_input )) == NULL )
+    {   
+        intf_ErrMsg( "input demux: cannot read chunk" );
+        return( -1 );
+    }
+
+    if( (p_chunk->i_id&0xFFFF0000) != 
+                    (p_info->p_index[p_info->i_idxpos].i_id&0xFFFF0000) )
+    {
+        intf_WarnMsg( 2, "input demux: bad index entry" );
+        __AVI_NextIndexEntry( p_input, p_info );
+        return( 1 );
+    }
+    /*
+    intf_WarnMsg( 6, "input demux: read %4.4s chunk",
+                    (char*)&p_chunk->i_id);
+                    */
+    if( RIFF_LoadChunkDataInPES(p_input, p_chunk, &p_pes) != 0 )
+    {
+        intf_ErrMsg( "input error: cannot read data" );
+        return( -1 );
+    }
+
+    p_pes->i_rate = p_input->stream.control.i_rate; 
+    p_pes->i_pts = p_avi_demux->i_date + __AVI_GetPTS( p_info );
+    p_pes->i_dts = 0;
+    
+    /* on update les donnĂ©es */
+    __AVI_NextIndexEntry( p_input, p_info );
+    /* send to decoder */
+
+    vlc_mutex_lock( &p_info->p_es->p_decoder_fifo->data_lock );
+    if( p_info->p_es->p_decoder_fifo->i_depth >= MAX_PACKETS_IN_FIFO )
+    {
+        /* Wait for the decoder. */
+        vlc_cond_wait( &p_info->p_es->p_decoder_fifo->data_wait, 
+                        &p_info->p_es->p_decoder_fifo->data_lock );
+    }
+    vlc_mutex_unlock( &p_info->p_es->p_decoder_fifo->data_lock );
+    input_DecodePES( p_info->p_es->p_decoder_fifo, p_pes );
+
+    return( 1 );
+
+}
diff --git a/plugins/avi/avi.h b/plugins/avi/avi.h
new file mode 100644 (file)
index 0000000..8733866
--- /dev/null
@@ -0,0 +1,153 @@
+/*****************************************************************************
+ * avi.h : AVI file Stream input module for vlc
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: avi.h,v 1.1 2002/04/23 23:44:36 fenrir Exp $
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#define        MAX_PACKETS_IN_FIFO     10
+
+/* flags for use in <dwFlags> in AVIFileHdr */
+#define AVIF_HASINDEX       0x00000010  /* Index at end of file? */
+#define AVIF_MUSTUSEINDEX   0x00000020
+#define AVIF_ISINTERLEAVED  0x00000100
+#define AVIF_TRUSTCKTYPE    0x00000800  /* Use CKType to find key frames? */
+#define AVIF_WASCAPTUREFILE 0x00010000
+#define AVIF_COPYRIGHTED    0x00020000
+
+/* Flags for index */
+#define AVIIF_LIST          0x00000001L /* chunk is a 'LIST' */
+#define AVIIF_KEYFRAME      0x00000010L /* this frame is a key frame.*/
+#define AVIIF_NOTIME        0x00000100L /* this frame doesn't take any time */
+#define AVIIF_COMPUSE       0x0FFF0000L /* these bits are for compressor use */
+
+typedef struct bitmapinfoheader_s
+{
+    u32 i_size; /* size of header */
+    u32 i_width;
+    u32 i_height;
+    u16 i_planes;
+    u16 i_bitcount;
+    u32 i_compression;
+    u32 i_sizeimage;
+    u32 i_xpelspermeter;
+    u32 i_ypelspermeter;
+    u32 i_clrused;
+    u32 i_clrimportant;
+} bitmapinfoheader_t;
+
+typedef struct waveformatex_s
+{
+    u16 i_formattag;
+    u16 i_channels;
+    u32 i_samplespersec;
+    u32 i_avgbytespersec;
+    u16 i_blockalign;
+    u16 i_bitspersample;
+    u16 i_size; /* the extra size in bytes */
+} waveformatex_t;
+
+
+typedef struct MainAVIHeader_s
+{
+    u32 i_microsecperframe;
+    u32 i_maxbytespersec;
+    u32 i_reserved1; /* dwPaddingGranularity;    pad to multiples of this
+                         size; normally 2K */
+    u32 i_flags;
+    u32 i_totalframes;
+    u32 i_initialframes;
+    u32 i_streams;
+    u32 i_suggestedbuffersize;
+    u32 i_width;
+    u32 i_height;
+    u32 i_scale;
+    u32 i_rate;
+    u32 i_start;
+    u32 i_length;
+
+} MainAVIHeader_t;
+
+typedef struct AVIStreamHeader_s
+{
+    u32 i_type;
+    u32 i_handler;
+    u32 i_flags;
+    u32 i_reserved1;    /* wPriority wLanguage */
+    u32 i_initialframes;
+    u32 i_scale;
+    u32 i_rate;
+    u32 i_start;
+    u32 i_length;       /* In units above... */
+    u32 i_suggestedbuffersize;
+    u32 i_quality;
+    u32 i_samplesize;
+
+} AVIStreamHeader_t;
+
+typedef struct AVIIndexEntry_s
+{
+    u32 i_id;
+    u32 i_flags;
+    u32 i_offset;
+    u32 i_length;
+    u32 i_lengthtotal;
+} AVIIndexEntry_t;
+
+typedef struct AVIStreamInfo_s
+{
+
+    riffchunk_t *p_strl;
+    riffchunk_t *p_strh;
+    riffchunk_t *p_strf;
+    riffchunk_t *p_strd; /* not used */
+    
+    AVIStreamHeader_t header;
+    
+    u8 i_cat;           /* AUDIO_ES, VIDEO_ES */
+    bitmapinfoheader_t  video_format;
+    waveformatex_t      audio_format;
+    es_descriptor_t     *p_es;   
+    int                 b_unselected; /* previously unselected */
+    AVIIndexEntry_t     *p_index;
+    int                 i_idxnb;
+    int                 i_idxmax; 
+    int                 i_idxpos;
+    off_t               i_idxoffset; /* how many to add to index.i_pos */
+} AVIStreamInfo_t;
+
+typedef struct demux_data_avi_file_s
+{
+    mtime_t i_date;       /* date correspondant Ă  i_chunkread = 0 */
+
+    riffchunk_t *p_riff;
+    riffchunk_t *p_hdrl;
+    riffchunk_t *p_movi;
+    riffchunk_t *p_idx1;
+
+    /* Info extraites de avih */
+    MainAVIHeader_t avih;
+
+    /* les differents stream */
+    int i_streams;
+    AVIStreamInfo_t   **pp_info; 
+
+/* absolument pas definitif */
+
+} demux_data_avi_file_t;
+
diff --git a/plugins/avi/fourcc.h b/plugins/avi/fourcc.h
new file mode 100644 (file)
index 0000000..c269944
--- /dev/null
@@ -0,0 +1,86 @@
+/*****************************************************************************
+ * fourcc.h : AVI file Stream input module for vlc
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: fourcc.h,v 1.1 2002/04/23 23:44:36 fenrir Exp $
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+
+#define mmioFOURCC( ch0, ch1, ch2, ch3 ) \
+   ( ((u32)ch0) | ( ((u32)ch1) << 8 ) | \
+     ( ((u32)ch2) << 16 ) | ( ((u32)ch3) << 24 ) )
+
+#define mmioTWOCC( ch0, ch1 ) \
+        ( (u32)(ch0) | ( (u32)(ch1) << 8 ) )
+        
+#define WAVE_FORMAT_UNKNOWN         0x0000
+#define WAVE_FORMAT_PCM             0x0001
+#define WAVE_FORMAT_MPEG            0x0050
+#define WAVE_FORMAT_MPEGLAYER3      0x0055
+#define WAVE_FORMAT_AC3             0x2000
+        
+#define FOURCC_RIFF                 mmioFOURCC( 'R', 'I', 'F', 'F' )
+#define FOURCC_LIST                 mmioFOURCC( 'L', 'I', 'S', 'T' )
+#define FOURCC_JUNK                 mmioFOURCC( 'J', 'U', 'N', 'K' )
+#define FOURCC_AVI                  mmioFOURCC( 'A', 'V', 'I', ' ' )
+#define FOURCC_WAVE                 mmioFOURCC( 'W', 'A', 'V', 'E' )
+
+#define FOURCC_avih                 mmioFOURCC( 'a', 'v', 'i', 'h' )
+#define FOURCC_hdrl                 mmioFOURCC( 'h', 'd', 'r', 'l' )
+#define FOURCC_movi                 mmioFOURCC( 'm', 'o', 'v', 'i' )
+#define FOURCC_idx1                 mmioFOURCC( 'i', 'd', 'x', '1' )
+
+#define FOURCC_strl                 mmioFOURCC( 's', 't', 'r', 'l' )
+#define FOURCC_strh                 mmioFOURCC( 's', 't', 'r', 'h' )
+#define FOURCC_strf                 mmioFOURCC( 's', 't', 'r', 'f' )
+#define FOURCC_strd                 mmioFOURCC( 's', 't', 'r', 'd' )
+
+#define FOURCC_rec                  mmioFOURCC( 'r', 'e', 'c', ' ' )
+#define FOURCC_auds                 mmioFOURCC( 'a', 'u', 'd', 's' )
+#define FOURCC_vids                 mmioFOURCC( 'v', 'i', 'd', 's' )
+        
+
+#define TWOCC_wb                    mmioTWOCC( 'w', 'b' )
+#define TWOCC_db                    mmioTWOCC( 'd', 'b' )
+#define TWOCC_dc                    mmioTWOCC( 'd', 'c' )
+#define TWOCC_pc                    mmioTWOCC( 'p', 'c' )
+        
+        
+/* definition of mpeg4 (opendivx) codec */
+#define FOURCC_DIVX         mmioFOURCC( 'D', 'I', 'V', 'X' )
+#define FOURCC_divx         mmioFOURCC( 'd', 'i', 'v', 'x' )
+#define FOURCC_DX50         mmioFOURCC( 'D', 'X', '5', '0' )
+#define FOURCC_MP4S         mmioFOURCC( 'M', 'P', '4', 'S' )
+#define FOURCC_MPG4         mmioFOURCC( 'M', 'P', 'G', '4' )
+#define FOURCC_mpg4         mmioFOURCC( 'm', 'p', 'g', '4' )
+#define FOURCC_mp4v         mmioFOURCC( 'm', 'p', '4', 'v' )
+        
+/* definition of msmepg (divx v3) codec */
+#define FOURCC_DIV3         mmioFOURCC( 'D', 'I', 'V', '3' )
+#define FOURCC_div3         mmioFOURCC( 'd', 'i', 'v', '3' )
+#define FOURCC_DIV4         mmioFOURCC( 'D', 'I', 'V', '4' )
+#define FOURCC_div4         mmioFOURCC( 'd', 'i', 'v', '4' )
+#define FOURCC_DIV5         mmioFOURCC( 'D', 'I', 'V', '5' )
+#define FOURCC_div5         mmioFOURCC( 'd', 'i', 'v', '5' )
+#define FOURCC_DIV6         mmioFOURCC( 'D', 'I', 'V', '6' )
+#define FOURCC_div6         mmioFOURCC( 'd', 'i', 'v', '6' )
+#define FOURCC_3IV1         mmioFOURCC( '3', 'I', 'V', '1' )
+#define FOURCC_AP41         mmioFOURCC( 'A', 'P', '4', '1' )
+#define FOURCC_MP43         mmioFOURCC( 'M', 'P', '4', '3' )
+#define FOURCC_mp43         mmioFOURCC( 'm', 'p', '4', '3' )
+        
diff --git a/plugins/avi/libLE.c b/plugins/avi/libLE.c
new file mode 100644 (file)
index 0000000..4eccfdf
--- /dev/null
@@ -0,0 +1,57 @@
+/*****************************************************************************
+ * avi_file.c : AVI file Stream input module for vlc
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: libLE.c,v 1.1 2002/04/23 23:44:36 fenrir Exp $
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+/*
+ * Data reading functions
+ */
+
+static u16 __GetWordLittleEndianFromBuff( byte_t *p_buff )
+{
+    u16 i;
+    i = (*p_buff) + ( *(p_buff + 1) <<8 );
+    return ( i );
+}
+
+static u32 __GetDoubleWordLittleEndianFromBuff( byte_t *p_buff )
+{
+    u32 i;
+    i = (*p_buff) + ( *(p_buff + 1) <<8 ) + ( *(p_buff + 2) <<16 ) + ( *(p_buff + 3) <<24 );
+    return ( i );
+}
+
+static void __SetWordLittleEndianToBuff( byte_t *p_buff, u16 i)
+{
+    *(p_buff)     = (i & 0xFF);
+    *(p_buff + 1) = ( ( i >>8 ) & 0xFF);
+    return;
+}
+
+static void __SetDoubleWordLittleEndianToBuff( byte_t *p_buff, u32 i)
+{
+    *(p_buff)     = ( i & 0xFF );
+    *(p_buff + 1) = (( i >>8 ) & 0xFF);
+    *(p_buff + 2) = (( i >>16 ) & 0xFF);
+    *(p_buff + 3) = (( i >>24 ) & 0xFF);
+    return;
+}
+
+
diff --git a/plugins/avi/libioRIFF.c b/plugins/avi/libioRIFF.c
new file mode 100644 (file)
index 0000000..4cc09cc
--- /dev/null
@@ -0,0 +1,483 @@
+/*****************************************************************************
+ * libioRIFF.c : AVI file Stream input module for vlc
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: libioRIFF.c,v 1.1 2002/04/23 23:44:36 fenrir Exp $
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+typedef struct riffchunk_s
+{
+    u32 i_id;
+    u32 i_size;
+    u32 i_type;
+    u32 i_pos;   /* peut etre a changer */
+    data_packet_t *p_data; /* pas forcement utilise */
+    struct riffchunk_s *p_next;
+    struct riffchunk_s *p_subchunk;
+} riffchunk_t;
+
+/* ttes ces fonctions permettent un acces lineaire sans avoir besoin de revenrir en arriere */
+static riffchunk_t  * RIFF_ReadChunk(input_thread_t * p_input);
+static int            RIFF_NextChunk(input_thread_t * p_input,riffchunk_t *p_rifffather);
+static int            RIFF_DescendChunk(input_thread_t * p_input);
+static int            RIFF_AscendChunk(input_thread_t * p_input,riffchunk_t *p_rifffather);
+static int            RIFF_FindChunk(input_thread_t * p_input,u32 i_id,riffchunk_t *p_rifffather);
+static int            RIFF_GoToChunkData(input_thread_t * p_input);
+static int            RIFF_LoadChunkData(input_thread_t * p_input,riffchunk_t *p_riff);
+static int            RIFF_TestFileHeader(input_thread_t * p_input, riffchunk_t **pp_riff, u32 i_type);
+static int            RIFF_FindAndLoadChunk( input_thread_t * p_input, riffchunk_t *p_riff, riffchunk_t **pp_fmt, u32 i_type );
+static int            RIFF_FindAndGotoDataChunk( input_thread_t * p_input, riffchunk_t *p_riff, riffchunk_t **pp_data, u32 i_type );
+static int            RIFF_FindListChunk( input_thread_t *p_input, riffchunk_t **pp_riff, riffchunk_t *p_rifffather, u32 i_type );
+
+static void           RIFF_DeleteChunk( input_thread_t * p_input, riffchunk_t *p_chunk );
+
+
+/* 
+ ces fonctions on besoin de pouvoir faire des seek 
+ static int            RIFF_GoToChunk(input_thread_t * p_input,riffchunk_t *p_riff);
+*/
+
+static u32            RIFF_4cToI(char c1,char c2,char c3,char c4);
+static char         * RIFF_IToStr(u32 i);
+
+/*************************************************************************/
+
+/********************************************
+ * Fonction locale maintenant               *
+ ********************************************/
+
+static int __RIFF_TellPos( input_thread_t *p_input, u32 *pos )
+{ /* pas sur que ca marche */
+    u32 i;
+    
+    vlc_mutex_lock( &p_input->stream.stream_lock );
+    i = p_input->stream.p_selected_area->i_tell - ( p_input->p_last_data - p_input->p_current_data  );
+    vlc_mutex_unlock( &p_input->stream.stream_lock );
+    *pos = i; 
+    return 0;
+}
+
+static int     __RIFF_SkipBytes(input_thread_t * p_input,int nb)
+{  
+    data_packet_t *p_pack;
+    int i;
+    int i_rest;
+    if( p_input->stream.b_seekable )
+    {
+        u32 i_pos;
+        __RIFF_TellPos( p_input, &i_pos);
+        p_input->pf_seek( p_input, (off_t)(i_pos + nb) );
+        input_AccessReinit( p_input );
+    }
+    else
+    {
+        intf_WarnMsg( 1, "input demux: cannot seek, it will take times" );
+        if( nb < 0 ) { return( -1 ); }
+        i_rest = nb;
+        while (i_rest != 0 )
+        {
+            if ( i_rest >= 4096 )
+            {
+                i = input_SplitBuffer( p_input, &p_pack, 4096);
+            }
+            else
+            {
+                i = input_SplitBuffer( p_input, &p_pack, i_rest);
+            }
+                    
+            if ( i < 0 ) { return ( -1 ); }
+            i_rest-=i;
+            input_DeletePacket( p_input->p_method_data, p_pack);
+        }
+    }
+       return ( 0 );
+}
+
+
+static void             RIFF_DeleteChunk( input_thread_t *p_input, riffchunk_t *p_chunk )
+{
+    if( p_chunk != NULL)
+    {
+        if( p_chunk->p_data != NULL )
+        {
+            input_DeletePacket( p_input->p_method_data, p_chunk->p_data );
+        }
+        free( p_chunk );
+    }
+}
+
+/* ******************************************
+ * lit une structure riffchunk sans avancer *
+ ********************************************/
+static riffchunk_t     * RIFF_ReadChunk(input_thread_t * p_input)
+{
+    riffchunk_t * p_riff;
+    int count;
+    byte_t * p_peek;
+       if((p_riff = malloc( sizeof(riffchunk_t))) == NULL)
+       {
+               intf_ErrMsg("input error: not enough memory (ioriff)" );
+               return NULL;
+       }
+       
+       p_riff->p_data = NULL;  /* Par defaut */
+       p_riff->p_next = NULL;
+       p_riff->p_subchunk = NULL;
+       /* peek to have the begining, 8+4 where 4 are to get type */
+       count=input_Peek( p_input, &p_peek, 12 );
+       if( count < 8 )
+       {
+               intf_ErrMsg( "input error: cannot peek() (ioriff)" );
+               free(p_riff);
+               return NULL;
+       }
+       
+       p_riff->i_id = __GetDoubleWordLittleEndianFromBuff( p_peek );
+       p_riff->i_size =__GetDoubleWordLittleEndianFromBuff( p_peek + 4 );
+       if( count == 12 )
+       {
+               p_riff->i_type = __GetDoubleWordLittleEndianFromBuff( p_peek + 8 );
+       }
+       else
+       {
+               p_riff->i_type = 0;
+       }
+       __RIFF_TellPos(p_input, &(p_riff->i_pos) );
+       
+       return( p_riff );       
+}
+
+/**************************************************
+ * Va au chunk juste d'apres si il en a encore    *
+ * -1 si erreur , 1 si y'en a plus                *
+ **************************************************/
+static int RIFF_NextChunk( input_thread_t * p_input,riffchunk_t *p_rifffather)
+{
+    int i_len;
+    int i_lenfather;
+    riffchunk_t *p_riff;
+
+       if( ( p_riff = RIFF_ReadChunk( p_input ) ) == NULL )
+       {
+               intf_ErrMsg( "ioriff: cannot read chunk." );
+               return( -1 );
+       }
+       i_len = p_riff->i_size;
+    if( i_len%2 != 0 ) {i_len++;} /* alignĂ© sur un mot */
+
+       if ( p_rifffather != NULL )
+       {
+               i_lenfather=p_rifffather->i_size; 
+        if ( i_lenfather%2 !=0 ) {i_lenfather++;}
+               if ( p_rifffather->i_pos + i_lenfather <= p_riff->i_pos + i_len )
+               {
+            intf_ErrMsg( "ioriff: next chunk out of bound" );
+                       free( p_riff );
+                       return( 1 ); /* pas dans nos frontiere */
+               }
+       }
+       if ( __RIFF_SkipBytes( p_input,i_len + 8 ) != 0 )
+       { 
+               free( p_riff );
+               intf_ErrMsg( "input error: cannot go to the next chunk (ioriff)." );
+               return( -1 );
+       }
+       free( p_riff );
+       return( 0 );
+}
+
+/****************************************************************
+ * Permet de rentrer dans un ck RIFF ou LIST                    *
+ ****************************************************************/
+static int     RIFF_DescendChunk(input_thread_t * p_input)
+{
+       if ( __RIFF_SkipBytes(p_input,12) != 0)
+       {
+               intf_ErrMsg( "input error: cannot go into chunk." );
+               return ( -1 );
+       }
+       return( 0 );
+}
+
+/***************************************************************
+ * Permet de sortir d'un sous chunk et d'aller sur le suivant  *
+ * chunk                                                       *
+ ***************************************************************/
+
+static int     RIFF_AscendChunk(input_thread_t * p_input ,riffchunk_t *p_rifffather)
+{
+    int i_skip;
+    u32 i_posactu;
+
+       i_skip  = p_rifffather->i_pos + p_rifffather->i_size + 8;
+    if ( i_skip%2 != 0) {i_skip++;} 
+
+    __RIFF_TellPos(p_input, &i_posactu);
+    i_skip-=i_posactu;
+
+    if (( __RIFF_SkipBytes(p_input,i_skip)) != 0)
+       {
+               intf_ErrMsg( "ioriff: cannot exit from subchunk.");
+               return( -1 );
+       }
+       return( 0 );
+}
+
+/***************************************************************
+ * Permet de se deplacer jusqu'au premier chunk avec le bon id *
+ * *************************************************************/
+static int     RIFF_FindChunk(input_thread_t * p_input ,u32 i_id,riffchunk_t *p_rifffather)
+{
+ riffchunk_t *p_riff=NULL;
+       do
+       {
+               if (p_riff!=NULL) 
+               { 
+                       free(p_riff); 
+                       if ( RIFF_NextChunk(p_input ,p_rifffather) != 0 ) 
+            { 
+                return( -1 );
+            }
+               }
+               p_riff=RIFF_ReadChunk(p_input);
+       } while ( ( p_riff != NULL )&&( p_riff->i_id != i_id ) );
+
+    if ( ( p_riff == NULL )||( p_riff->i_id != i_id ) )
+    { 
+        return( -1 );
+    }
+    free( p_riff );
+       return( 0 );
+}
+
+/*****************************************************************
+ * Permet de pointer sur la zone de donnĂ© du chunk courant       *
+ *****************************************************************/
+static int               RIFF_GoToChunkData(input_thread_t * p_input)
+{
+       if ( __RIFF_SkipBytes(p_input,8) != 0 ) 
+    { 
+        return( -1 );
+    }
+       return( 0 );
+}
+
+static int     RIFF_LoadChunkData(input_thread_t * p_input,riffchunk_t *p_riff )
+{
+    
+       RIFF_GoToChunkData(p_input);
+       if ( input_SplitBuffer( p_input, &p_riff->p_data, p_riff->i_size ) != p_riff->i_size )
+       {
+        intf_ErrMsg( "ioriff: cannot read enough data " );
+               return ( -1 );
+       }
+       if ( p_riff->i_size%2 != 0) 
+    {
+       __RIFF_SkipBytes(p_input,1);
+    } /* aligne sur un mot */
+       return( 0 );
+}
+
+static int     RIFF_LoadChunkDataInPES(input_thread_t * p_input,riffchunk_t *p_riff,pes_packet_t **pp_pes)
+{
+    u32 i_read;
+    data_packet_t *p_data;
+    
+       RIFF_GoToChunkData(p_input);
+    *pp_pes = input_NewPES( p_input->p_method_data );
+
+    if( *pp_pes == NULL )
+    {
+        return( -1 );
+    }
+    if( p_riff->i_size == 0 )
+    {
+        p_data = input_NewPacket( p_input->p_method_data, 0 );
+        (*pp_pes)->p_first = p_data;
+        (*pp_pes)->p_last  = p_data;
+        (*pp_pes)->i_nb_data = 1;
+        (*pp_pes)->i_pes_size = 0;
+        return( 0 );
+    }
+        
+    do
+    {
+        i_read = input_SplitBuffer(p_input, &p_data, p_riff->i_size - 
+                                                    (*pp_pes)->i_pes_size );
+        if( i_read < 0 )
+        {
+            /* FIXME free sur tout les packets */
+            return( -1 );
+        }
+        if( (*pp_pes)->p_first == NULL )
+        {
+            (*pp_pes)->p_first = p_data;
+            (*pp_pes)->p_last  = p_data;
+            (*pp_pes)->i_nb_data = 1;
+            (*pp_pes)->i_pes_size = ( p_data->p_payload_end - 
+                                        p_data->p_payload_start );
+        }
+        else
+        {
+            (*pp_pes)->p_last->p_next = p_data;
+            (*pp_pes)->p_last = p_data;
+            (*pp_pes)->i_nb_data++;
+            (*pp_pes)->i_pes_size += ( p_data->p_payload_end -
+                                       p_data->p_payload_start );
+        }
+    } while( ((*pp_pes)->i_pes_size < p_riff->i_size)&&(i_read != 0) );
+   /* i_read =  0 si fin du stream sinon block */
+       if ( p_riff->i_size%2 != 0) 
+    {
+       __RIFF_SkipBytes(p_input,1);
+    } /* aligne sur un mot */
+       return( 0 );
+}
+
+
+
+
+static int     RIFF_GoToChunk(input_thread_t * p_input, riffchunk_t *p_riff)
+{
+    /* TODO rajouter les test */
+    if( p_input->stream.b_seekable )
+    {
+        p_input->pf_seek( p_input, (off_t)p_riff->i_pos );
+        input_AccessReinit( p_input );
+           return 0;
+    }
+
+    return( -1 );
+}
+
+
+static u32   RIFF_4cToI(char c1,char c2,char c3,char c4)
+{
+ u32 i;
+       i = ( ((u32)c1) << 24 ) + ( ((u32)c2) << 16 ) + ( ((u32)c3) << 8 ) + (u32)c4;
+       return i;
+}
+
+
+static char    * RIFF_IToStr(u32 l)
+{
+ char *str;
+ int i;
+       str=calloc(5,sizeof(char));
+       for( i = 0; i < 4; i++)
+       {
+               str[i] = ( l >> ( (3-i) * 8) )&0xFF;
+       }
+       str[5] = 0;
+       return( str );
+}
+
+static int   RIFF_TestFileHeader( input_thread_t * p_input, riffchunk_t ** pp_riff, u32 i_type )
+{
+    *pp_riff = RIFF_ReadChunk( p_input );
+    
+    if( *pp_riff == NULL )
+    {
+        intf_ErrMsg( "input error: cannot retrieve header" );
+        return( -1 );
+    }
+    if( (*pp_riff)->i_id != FOURCC_RIFF ) 
+    {
+        free( *pp_riff );
+        return( -1 );
+    }
+    if( (*pp_riff)->i_type != i_type )
+    {
+        free( *pp_riff );
+        return( -1 );
+    } 
+    return( 0 );  
+}
+
+
+static int   RIFF_FindAndLoadChunk( input_thread_t * p_input, riffchunk_t *p_riff, riffchunk_t **pp_fmt, u32 i_type )
+{
+    *pp_fmt = NULL;
+    if ( RIFF_FindChunk( p_input, i_type, p_riff ) != 0)
+    {
+        return( -1 );
+    }
+    if ( ( (*pp_fmt = RIFF_ReadChunk( p_input )) == NULL) || ( RIFF_LoadChunkData( p_input, *pp_fmt ) != 0 ) )
+    {
+        if( *pp_fmt != NULL ) { RIFF_DeleteChunk( p_input, *pp_fmt ); }
+        return( -1 );
+    }
+    return( 0 );
+}
+
+static int   RIFF_FindAndGotoDataChunk( input_thread_t * p_input, riffchunk_t *p_riff, riffchunk_t **pp_data, u32 i_type )
+{
+    *pp_data = NULL;
+    if ( RIFF_FindChunk( p_input, i_type, p_riff ) != 0)
+    {
+        return( -1 );
+    }
+    if ( ( *pp_data = RIFF_ReadChunk( p_input ) ) == NULL )
+    {
+        return( -1 );
+    }
+    if ( RIFF_GoToChunkData( p_input ) != 0 )
+    {
+        RIFF_DeleteChunk( p_input, *pp_data );
+        return( -1 );
+    }
+    return( 0 );
+}
+
+static int   RIFF_FindListChunk( input_thread_t *p_input, riffchunk_t **pp_riff, riffchunk_t *p_rifffather, u32 i_type )
+{
+    int i_ok;
+    
+    *pp_riff = NULL;
+    i_ok = 0;
+    while( i_ok == 0 )
+    {
+        if( *pp_riff != NULL )
+        {
+            free( *pp_riff );
+        }
+        if( RIFF_FindChunk( p_input, FOURCC_LIST, p_rifffather) != 0 )
+        {
+            return( -1 );
+        }
+        *pp_riff = RIFF_ReadChunk( p_input );
+                        
+        if( *pp_riff == NULL )
+        {
+            return( -1 );
+        }
+        if( (*pp_riff)->i_type != i_type )
+        {
+            if( RIFF_NextChunk( p_input, p_rifffather ) != 0 )
+            {
+                return( -1 );
+            }
+        }
+        else
+        {
+            i_ok = 1;
+        }
+    }
+    return( 0 );  
+}
index be1746e1f8f609d5eebb51a3144122af27c67d1f..72fe65366aa21360d093be91adf037fa4f19af3d 100644 (file)
@@ -1 +1,2 @@
-ffmpeg_SOURCES = 
+ffmpeg_SOURCES = ffmpeg.c
+
diff --git a/plugins/ffmpeg/ffmpeg.c b/plugins/ffmpeg/ffmpeg.c
new file mode 100644 (file)
index 0000000..583a340
--- /dev/null
@@ -0,0 +1,638 @@
+/*****************************************************************************
+ * ffmpeg.c: video decoder using ffmpeg library
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: ffmpeg.c,v 1.1 2002/04/23 23:44:36 fenrir Exp $
+ *
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h>                                      /* malloc(), free() */
+
+#include <videolan/vlc.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>                                              /* getpid() */
+#endif
+
+#include <errno.h>
+#include <string.h>
+
+#ifdef HAVE_SYS_TIMES_H
+#   include <sys/times.h>
+#endif
+
+#include "video.h"
+#include "video_output.h"
+
+#include "stream_control.h"
+#include "input_ext-dec.h"
+#include "input_ext-intf.h"
+#include "input_ext-plugins.h"
+
+
+#include "vdec_ext-plugins.h"
+#include "avcodec.h"                                            /* ffmpeg */
+#include "ffmpeg.h"
+
+/*
+ * Local prototypes
+ */
+static int      decoder_Probe   ( u8 * );
+static int      decoder_Run     ( decoder_config_t * );
+static int      InitThread      ( videodec_thread_t * );
+static void     EndThread       ( videodec_thread_t * );
+static void     DecodeThread    ( videodec_thread_t * );
+
+/* FIXME make this variable global */
+static int      b_ffmpeginit = 0;
+
+/*****************************************************************************
+ * Capabilities
+ *****************************************************************************/
+void _M( vdec_getfunctions )( function_list_t * p_function_list )
+{
+    p_function_list->functions.dec.pf_probe = decoder_Probe;
+    p_function_list->functions.dec.pf_run   = decoder_Run;
+}
+
+/*****************************************************************************
+ * Build configuration tree.
+ *****************************************************************************/
+
+MODULE_CONFIG_START
+MODULE_CONFIG_STOP
+
+MODULE_INIT_START
+    SET_DESCRIPTION( "ffmpeg video decoder module (MSMPEG4,MPEG4)" )
+    ADD_CAPABILITY( DECODER, 50 )
+    ADD_SHORTCUT( "ffmpeg_vdec" )
+MODULE_INIT_STOP
+
+MODULE_ACTIVATE_START
+    _M( vdec_getfunctions )( &p_module->p_functions->dec );
+MODULE_ACTIVATE_STOP
+
+MODULE_DEACTIVATE_START
+MODULE_DEACTIVATE_STOP
+
+
+static u16 __GetWordLittleEndianFromBuff( byte_t *p_buff )
+{
+    u16 i;
+    i = (*p_buff) + ( *(p_buff + 1) <<8 );
+    return ( i );
+}
+
+static u32 __GetDoubleWordLittleEndianFromBuff( byte_t *p_buff )
+{
+    u32 i;
+    i = (*p_buff) + ( *(p_buff + 1) <<8 ) + ( *(p_buff + 2) <<16 ) + ( *(p_buff + 3) <<24 );
+    return ( i );
+}
+
+/*****************************************************************************
+ * decoder_Probe: probe the decoder and return score
+ *****************************************************************************
+ * Tries to launch a decoder and return score so that the interface is able 
+ * to chose.
+ *****************************************************************************/
+static int decoder_Probe( u8 *pi_type )
+{
+    switch( *pi_type )
+    {
+/*        case( MPEG1_VIDEO_ES ): marche pas pr le moment 
+        case( MPEG2_VIDEO_ES ): */
+        case( MSMPEG4_VIDEO_ES ):
+        case( MPEG4_VIDEO_ES ):
+            return( 0 );
+        default:
+            return( -1 );
+    }
+}
+
+/*****************************************************************************
+ * Functions locales 
+ *****************************************************************************/
+
+static int __ParseBitMapInfoHeader( bitmapinfoheader_t *h, byte_t *p_data )
+{
+    h->i_size          = __GetDoubleWordLittleEndianFromBuff( p_data );
+    h->i_width         = __GetDoubleWordLittleEndianFromBuff( p_data + 4 );
+    h->i_height        = __GetDoubleWordLittleEndianFromBuff( p_data + 8 );
+    h->i_planes        = __GetWordLittleEndianFromBuff( p_data + 12 );
+    h->i_bitcount      = __GetWordLittleEndianFromBuff( p_data + 14 );
+    h->i_compression   = __GetDoubleWordLittleEndianFromBuff( p_data + 16 );
+    h->i_sizeimage     = __GetDoubleWordLittleEndianFromBuff( p_data + 20 );
+    h->i_xpelspermeter = __GetDoubleWordLittleEndianFromBuff( p_data + 24 );
+    h->i_ypelspermeter = __GetDoubleWordLittleEndianFromBuff( p_data + 28 );
+    h->i_clrused       = __GetDoubleWordLittleEndianFromBuff( p_data + 32 );
+    h->i_clrimportant  = __GetDoubleWordLittleEndianFromBuff( p_data + 36 );
+    return( 0 );
+}
+/* get the first pes from fifo */
+static pes_packet_t *__PES_GET( decoder_fifo_t *p_fifo )
+{
+    pes_packet_t *p_pes;
+    /* get a p_pes ie data for a frame ! */
+    vlc_mutex_lock( &p_fifo->data_lock );
+
+    /* if fifo is emty wait */
+    while( p_fifo->p_first == NULL )
+    {
+        if( p_fifo->b_die )
+        {
+            vlc_mutex_unlock( &p_fifo->data_lock );
+            return( NULL );
+        }
+        vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
+    }
+    p_pes = p_fifo->p_first;
+
+    vlc_mutex_unlock( &p_fifo->data_lock );
+    
+    return( p_pes );
+}
+/* free the first pes and go to next */
+static void __PES_NEXT( decoder_fifo_t *p_fifo )
+{
+    pes_packet_t *p_next;
+
+    vlc_mutex_lock( &p_fifo->data_lock );
+    
+    p_next = p_fifo->p_first->p_next;
+    p_fifo->p_first->p_next = NULL;
+    input_DeletePES( p_fifo->p_packets_mgt, p_fifo->p_first );
+    p_fifo->p_first = p_next;
+    p_fifo->i_depth--;
+
+    if( p_fifo->p_first == NULL )
+    {
+        /* No PES in the fifo */
+        /* pp_last no longer valid */
+        p_fifo->pp_last = &p_fifo->p_first;
+        while( p_fifo->p_first == NULL )
+        {
+            vlc_cond_signal( &p_fifo->data_wait );
+            vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
+        }
+    }
+    vlc_mutex_unlock( &p_fifo->data_lock );
+}
+
+static void __PACKET_REINIT( videodec_thread_t *p_vdec )
+{
+    pes_packet_t *p_pes;
+
+    p_pes = __PES_GET( p_vdec->p_fifo );
+    if( p_vdec->p_fifo->b_die )
+    {
+        return;
+    }
+    p_vdec->p_data = p_pes->p_first;
+    p_vdec->p_buff = p_vdec->p_data->p_payload_start;
+    p_vdec->i_data_size = p_vdec->p_data->p_payload_end - 
+                                p_vdec->p_data->p_payload_start;
+}
+
+static void __PACKET_NEXT( videodec_thread_t *p_vdec )
+{
+    do
+    {
+        p_vdec->p_data = p_vdec->p_data->p_next;
+        if( p_vdec->p_data == NULL )
+        {
+            __PES_NEXT( p_vdec->p_fifo );
+            if( p_vdec->p_fifo->b_die )
+            {
+                return;
+            }
+            __PACKET_REINIT( p_vdec ); 
+        }
+        else
+        {
+            p_vdec->p_buff = p_vdec->p_data->p_payload_start;
+            p_vdec->i_data_size = p_vdec->p_data->p_payload_end -
+                                    p_vdec->p_data->p_payload_start;
+        }
+        if( p_vdec->i_data_size == 0 )
+        {
+            p_vdec->p_data = NULL;
+        } 
+        
+    } while( p_vdec->i_data_size <= 0 );
+}
+
+static void __PACKET_FILL( videodec_thread_t *p_vdec ) 
+{
+    if( p_vdec->i_data_size <= 0 )
+    {
+        __PACKET_NEXT( p_vdec );
+    }
+}
+/* call only two times so inline for faster */
+static __inline__ void __ConvertAVPictureToPicture( AVPicture *p_avpicture, 
+                                                    picture_t *p_picture )
+{
+    int i_plane, i_line;
+    u8 *p_dest,*p_src;
+    
+    for( i_plane = 0; i_plane < p_picture->i_planes; i_plane++ )
+    {
+        p_dest = p_picture->p[i_plane].p_pixels;
+        p_src  = p_avpicture->data[i_plane];
+        if( (p_dest == NULL)||( p_src == NULL)||(i_plane >= 3) ) { return; }
+        for( i_line = 0; i_line < p_picture->p[i_plane].i_lines; i_line++ )
+        {
+            FAST_MEMCPY( p_dest, 
+                         p_src, 
+                         __MIN( p_picture->p[i_plane].i_pitch,
+                                p_avpicture->linesize[i_plane] ) );
+            p_dest += p_picture->p[i_plane].i_pitch;
+            p_src  += p_avpicture->linesize[i_plane];
+        }
+    }
+}
+
+static __inline__ u32 __FfmpegChromaToFourCC( int i_ffmpegchroma )
+{
+    switch( i_ffmpegchroma )
+    {
+        case( PIX_FMT_YUV420P ):
+            return FOURCC_I420;
+        case( PIX_FMT_YUV422 ):
+            return FOURCC_I420;
+        case( PIX_FMT_RGB24 ):
+            return FOURCC_RV24;
+        case( PIX_FMT_BGR24 ):
+            return 0; /* FIXME pas trouvĂ© ds video.h */
+        case( PIX_FMT_YUV422P ):
+            return FOURCC_Y422;
+        case( PIX_FMT_YUV444P ):
+            return  0; /* FIXME pas trouvĂ© FOURCC_IYU2; */
+        default:
+            return  0;
+    }
+
+}
+/*****************************************************************************
+ * decoder_Run: this function is called just after the thread is created
+ *****************************************************************************/
+static int decoder_Run ( decoder_config_t * p_config )
+{
+    videodec_thread_t   *p_vdec;
+    int b_error;
+    
+    if ( (p_vdec = (videodec_thread_t*)malloc( sizeof(videodec_thread_t))) 
+                    == NULL )
+    {
+        intf_ErrMsg( "vdec error: not enough memory "
+                     "for vdec_CreateThread() to create the new thread");
+        DecoderError( p_config->p_decoder_fifo );
+        return( -1 );
+    }
+    memset( p_vdec, 0, sizeof( videodec_thread_t ) );
+
+    p_vdec->p_fifo = p_config->p_decoder_fifo;
+    p_vdec->p_config = p_config;
+    p_vdec->p_vout = NULL;
+
+    if( InitThread( p_vdec ) != 0 )
+    {
+        DecoderError( p_config->p_decoder_fifo );
+        return( -1 );
+    }
+     
+    while( (!p_vdec->p_fifo->b_die) && (!p_vdec->p_fifo->b_error) )
+    {
+        /* decode a picture */
+        DecodeThread( p_vdec );
+    }
+
+    if( ( b_error = p_vdec->p_fifo->b_error ) )
+    {
+        DecoderError( p_vdec->p_fifo );
+    }
+
+    EndThread( p_vdec );
+
+    if( b_error )
+    {
+        return( -1 );
+    }
+   
+    return( 0 );
+} 
+
+/*****************************************************************************
+ * InitThread: initialize vdec output thread
+ *****************************************************************************
+ * This function is called from decoder_Run and performs the second step 
+ * of the initialization. It returns 0 on success. Note that the thread's 
+ * flag are not modified inside this function.
+ *****************************************************************************/
+static int InitThread( videodec_thread_t *p_vdec )
+{
+    
+    if( p_vdec->p_config->p_demux_data != NULL )
+    {
+        __ParseBitMapInfoHeader( &p_vdec->format, 
+                                (byte_t*)p_vdec->p_config->p_demux_data );
+    }
+    else
+    {
+        memset( &p_vdec->format, 0, sizeof( bitmapinfoheader_t ) );
+    }
+    /* some codec need to have height and width initialized (msmepg4,mpeg4) */
+    /* we cannot create vout because we don't know what chroma */
+
+    /*init ffmpeg */
+    /* XXX maybe it's not multi thread capable */
+    /* TODO: add a global variable to know if init was already done */
+    if( b_ffmpeginit == 0 )
+    {
+        avcodec_init();
+        avcodec_register_all();
+        b_ffmpeginit = 1;
+        intf_WarnMsg( 1, "vdec init: library ffmpeg initialised" );
+   }
+   else
+   {
+        intf_WarnMsg( 1, "vdec init: library ffmpeg already initialised" );
+   }
+
+    switch( p_vdec->p_config->i_type)
+    {
+        case( MPEG1_VIDEO_ES ): /* marche pas pr le moment */
+        case( MPEG2_VIDEO_ES ):
+            p_vdec->p_codec = avcodec_find_decoder( CODEC_ID_MPEG1VIDEO );
+            p_vdec->psz_namecodec = "MPEG-1";
+            break;
+        case( MSMPEG4_VIDEO_ES):
+            p_vdec->p_codec = avcodec_find_decoder( CODEC_ID_MSMPEG4 );
+            p_vdec->psz_namecodec = "MS MPEG-4";
+            break;
+        case( MPEG4_VIDEO_ES):
+            p_vdec->p_codec = avcodec_find_decoder( CODEC_ID_MPEG4 );
+            p_vdec->psz_namecodec = "MPEG-4";
+            break;
+        default:
+            p_vdec->p_codec = NULL;
+            p_vdec->psz_namecodec = "Unknown";
+    }
+
+    if( p_vdec->p_codec == NULL )
+    {
+        intf_ErrMsg( "vdec error: codec not found (%s)",
+                     p_vdec->psz_namecodec );
+        return( -1 );
+    }
+
+    p_vdec->p_context = &p_vdec->context;
+    memset( p_vdec->p_context, 0, sizeof( AVCodecContext ) );
+
+    p_vdec->p_context->width  = p_vdec->format.i_width;
+    p_vdec->p_context->height = p_vdec->format.i_height;
+    p_vdec->p_context->pix_fmt = PIX_FMT_YUV420P;
+
+    if (avcodec_open(p_vdec->p_context, p_vdec->p_codec) < 0)
+    {
+        intf_ErrMsg( "vdec error: cannot open codec (%s)",
+                     p_vdec->psz_namecodec );
+        return( -1 );
+    }
+    else
+    {
+        intf_WarnMsg( 1, "vdec info: ffmpeg codec (%s) started",
+                         p_vdec->psz_namecodec );
+    }
+
+    __PACKET_REINIT( p_vdec );
+    return( 0 );
+}
+
+/*****************************************************************************
+ * EndThread: thread destruction
+ *****************************************************************************
+ * This function is called when the thread ends after a sucessful
+ * initialization.
+ *****************************************************************************/
+static void EndThread( videodec_thread_t *p_vdec )
+{
+    if( p_vdec == NULL )
+    {
+        intf_ErrMsg( "vdec error: cannot free structures" );
+        return;
+    }
+
+    if( p_vdec->p_context != NULL)
+    {
+        avcodec_close( p_vdec->p_context );
+        intf_WarnMsg(1, "vdec info: ffmpeg codec (%s) stopped",
+                        p_vdec->psz_namecodec);
+    }
+
+    if( p_vdec->p_vout != NULL )
+    {
+        vout_DestroyThread( p_vdec->p_vout, NULL );
+    }
+
+    free( p_vdec );
+}
+
+static void  DecodeThread( videodec_thread_t *p_vdec )
+{
+    int i_len;
+    int b_gotpicture;
+    int b_convert;
+    int i_aspect;
+   
+    pes_packet_t  *p_pes;
+    AVPicture avpicture;  /* ffmpeg picture */
+    u32 i_chroma;
+    picture_t *p_picture; /* videolan picture */
+    /* we have to get a frame stored in a pes 
+       give it to ffmpeg decoder 
+       and send the image to the output */ 
+    /* when we have the first image we create the video output */
+/* int avcodec_decode_video(AVCodecContext *avctx, AVPicture *picture, 
+                            int *got_picture_ptr,
+                            UINT8 *buf, int buf_size);
+ typedef struct AVPicture 
+ {
+     UINT8 *data[3];
+     int linesize[3];
+ } AVPicture;
+ */
+    p_pes = NULL;
+    do
+    {
+        __PACKET_FILL( p_vdec );
+        if( p_vdec->p_fifo->b_die )
+        {
+            return;
+        }
+        /* save p_pes for pts */
+        if( p_pes == NULL ) {p_pes = __PES_GET( p_vdec->p_fifo );}
+        i_len = avcodec_decode_video( p_vdec->p_context,
+                                      &avpicture,
+                                      &b_gotpicture,
+                                      p_vdec->p_buff,
+                                      p_vdec->i_data_size);
+        if( i_len < 0 )
+        {
+            intf_WarnMsg( 1, "vdec error: cannot decode one frame (%d bytes)",
+                        p_vdec->i_data_size );
+            __PES_NEXT( p_vdec->p_fifo );
+            __PACKET_REINIT( p_vdec );
+            return;
+        }
+        p_vdec->i_data_size -= i_len;
+        p_vdec->p_buff += i_len;
+    } while( !b_gotpicture );
+
+    i_chroma =__FfmpegChromaToFourCC( p_vdec->p_context->pix_fmt );
+    if( i_chroma == 0 )
+    {
+        b_convert = 1;
+        i_chroma = FOURCC_I420;
+    }
+    else
+    {
+        b_convert = 0;
+    }
+    
+    /* Send decoded frame to vout */
+    if( p_vdec->p_vout == NULL )
+    {
+        /* FIXME FIXME faire ca comme il faut avec :
+         * pp_vout_bank
+         * bon aspect, ds avi pas definie mais pour le reste a voir ...
+         */
+
+        /* create vout */
+        /* FIXME */
+/*
+        p_vdec->i_aspect = VOUT_ASPECT_FACTOR * 4 / 3;   AR_3_4_PICTURE 
+*/      
+
+        /* ffmpeg set it for our with some codec */  
+        if( (p_vdec->format.i_width == 0)||(p_vdec->format.i_height == 0) )
+        {
+            p_vdec->format.i_width  = p_vdec->p_context->width;
+            p_vdec->format.i_height = p_vdec->p_context->height; 
+        }
+        /* calculate i_aspect */
+        i_aspect = VOUT_ASPECT_FACTOR * p_vdec->format.i_width /
+                        p_vdec->format.i_height;
+        /* FIXME comment faire ca proprement */ 
+/*
+        if( i_aspect == VOUT_ASPECT_FACTOR * 4 /3 )
+        {
+            i_aspect = 1;
+        }
+        else
+        {
+            if( i_aspect == VOUT_ASPECT_FACTOR * 16 /9 )
+            {
+                i_aspect = 2;
+            }
+        }
+*/ 
+        p_vdec->i_aspect = i_aspect;
+        p_vdec->i_chroma = i_chroma;
+
+        intf_WarnMsg( 1, "vdec info: creating vout %dx%d chroma %4.4s %s %s",
+                         p_vdec->format.i_width,
+                         p_vdec->format.i_height,
+                         (char*)&i_chroma,
+                         b_convert ? "(with convertion)" : "",
+                         /*i_aspect ==1 ? "aspect 4:3" : "aspect 16:9"*/ 
+                         "free aspect" ); 
+
+        p_vdec->p_vout = vout_CreateThread( 
+                                NULL,
+                                p_vdec->format.i_width,
+                                p_vdec->format.i_height,
+                                p_vdec->i_chroma,
+                                p_vdec->i_aspect );
+
+        if( p_vdec->p_vout == NULL )
+        {
+            intf_ErrMsg( "vdec error: can't open vout, aborting" );
+            p_vdec->p_fifo->b_error = 1;
+            return;
+        }
+    }
+
+    while( (p_picture = vout_CreatePicture( p_vdec->p_vout,
+                                    0,  /* ??? */
+                                    0,  /* ??? */
+                                    0) ) /* ??? */
+                    == NULL )
+    {
+        if( p_vdec->p_fifo->b_die || p_vdec->p_fifo->b_error )
+        {
+            return;
+        }
+        msleep( VOUT_OUTMEM_SLEEP );
+    }
+
+    if( b_convert == 1 )
+    {
+        /* we convert in a supported format */
+        int i_status;
+        u8 *p_buff;
+        AVPicture avpicture_tmp;
+        
+        p_buff = malloc( avpicture_get_size( PIX_FMT_YUV420P,
+                                             p_vdec->p_context->width,
+                                             p_vdec->p_context->height) );
+        avpicture_fill(  &avpicture_tmp,
+                         p_buff,
+                         PIX_FMT_YUV420P,
+                         p_vdec->p_context->width,
+                         p_vdec->p_context->height );
+
+        i_status = img_convert( &avpicture_tmp,
+                                PIX_FMT_YUV420P,
+                                &avpicture,
+                                p_vdec->p_context->pix_fmt,
+                                p_vdec->p_context->width,
+                                p_vdec->p_context->height );
+       if( i_status < 0 )
+       {
+            intf_ErrMsg( "vdec error: cannot convert picture in known chroma" );
+            return;
+       }
+        __ConvertAVPictureToPicture( &avpicture_tmp, p_picture );
+        free( p_buff ); /* FIXME try to alloc only one time */
+    }
+    else
+    {
+        __ConvertAVPictureToPicture( &avpicture, p_picture );
+    }
+
+    vout_DatePicture( p_vdec->p_vout, p_picture, p_pes->i_pts );
+    vout_DisplayPicture( p_vdec->p_vout, p_picture );
+    
+    return;
+}   
+
diff --git a/plugins/ffmpeg/ffmpeg.h b/plugins/ffmpeg/ffmpeg.h
new file mode 100644 (file)
index 0000000..51c500b
--- /dev/null
@@ -0,0 +1,57 @@
+/*****************************************************************************
+ * ffmpeg_vdec.h: video decoder using ffmpeg library
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: ffmpeg.h,v 1.1 2002/04/23 23:44:36 fenrir Exp $
+ *
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+/* Pour un flux video */
+typedef struct bitmapinfoheader_s
+{
+    u32 i_size; /* size of header */
+    u32 i_width;
+    u32 i_height;
+    u16 i_planes;
+    u16 i_bitcount;
+    u32 i_compression;
+    u32 i_sizeimage;
+    u32 i_xpelspermeter;
+    u32 i_ypelspermeter;
+    u32 i_clrused;
+    u32 i_clrimportant;
+} bitmapinfoheader_t;
+
+typedef struct videodec_thread_s
+{
+    decoder_config_t    *p_config;
+    decoder_fifo_t      *p_fifo;    
+
+    bitmapinfoheader_t  format;
+
+    AVCodecContext      context, *p_context;
+    AVCodec             *p_codec;
+    vout_thread_t       *p_vout; 
+    int                 i_aspect;
+    u32                 i_chroma;
+    char *psz_namecodec;
+    /* private */
+    data_packet_t       *p_data;
+    byte_t              *p_buff;
+    int                 i_data_size;
+} videodec_thread_t;
index e7f088703223a887c111c9ec66fa909bdcb6a0a1..21e61af1b7a2d4f82b64cb19a2f88e7927ef085d 100644 (file)
@@ -67,7 +67,7 @@ MODULE_CONFIG_STOP
 
 MODULE_INIT_START
     SET_DESCRIPTION( _("libmad MPEG 1/2/3 audio decoder library") )
-    ADD_CAPABILITY( DECODER, 50 )
+    ADD_CAPABILITY( DECODER, 100 )
     ADD_SHORTCUT( "mad" )
 MODULE_INIT_STOP
 
index 05a971eb23509dafb5fe5238cf73b8aa0ad0cee2..2d45d2192c4f12b9228a46abfe1e56fdcb23f82c 100644 (file)
@@ -2,7 +2,7 @@
  * mpeg_adec.c: MPEG audio decoder thread
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: mpeg_adec.c,v 1.22 2002/04/19 13:56:11 sam Exp $
+ * $Id: mpeg_adec.c,v 1.23 2002/04/23 23:44:36 fenrir Exp $
  *
  * Authors: Michel Kaempf <maxx@via.ecp.fr>
  *          Michel Lespinasse <walken@via.ecp.fr>
@@ -67,7 +67,7 @@ MODULE_CONFIG_STOP
 
 MODULE_INIT_START
     SET_DESCRIPTION( _("MPEG I/II layer 1/2 audio decoder") )
-    ADD_CAPABILITY( DECODER, 100 )
+    ADD_CAPABILITY( DECODER, 50 )
     ADD_REQUIREMENT( FPU )
     ADD_SHORTCUT( "builtin" )
 MODULE_INIT_STOP
index 5bb9072f7bc79ec14833be1a6be816f330ff4ac2..6638f513185f663e740c335fe469b35cf100cbbd 100644 (file)
@@ -2,7 +2,7 @@
  * input_programs.c: es_descriptor_t, pgrm_descriptor_t management
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: input_programs.c,v 1.81 2002/04/23 14:16:20 sam Exp $
+ * $Id: input_programs.c,v 1.82 2002/04/23 23:44:36 fenrir Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -617,6 +617,8 @@ int input_SelectES( input_thread_t * p_input, es_descriptor_t * p_es )
     case AC3_AUDIO_ES:
     case MPEG1_AUDIO_ES:
     case MPEG2_AUDIO_ES:
+    case MPEG4_VIDEO_ES:
+    case MSMPEG4_VIDEO_ES:
     case LPCM_AUDIO_ES:
         if( p_main->b_audio )
         {