]> git.sesse.net Git - vlc/blobdiff - modules/demux/avi/avi.c
* ALL: i18n updates and fixes.
[vlc] / modules / demux / avi / avi.c
index 0ec58060299ed6cc7fdd2c57373288d860b2d8d9..5b5c931d7a502f0595e64e9bb687e8078e63b517 100644 (file)
@@ -2,7 +2,7 @@
  * avi.c : AVI file Stream input module for vlc
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: avi.c,v 1.22 2003/01/11 18:10:49 fenrir Exp $
+ * $Id: avi.c,v 1.36 2003/02/27 13:19:43 gbazin Exp $
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -52,20 +52,20 @@ static int    AVIDemux_Seekable  ( input_thread_t * );
 static int    AVIDemux_UnSeekable( input_thread_t *p_input );
 
 #define AVIEnd(a) __AVIEnd(VLC_OBJECT(a))
-
+#define FREE( p ) if( p ) { free( p ); (p) = NULL; }
 /*****************************************************************************
  * Module descriptor
  *****************************************************************************/
 vlc_module_begin();
-    add_category_hint( "demuxer", NULL );
+    add_category_hint( N_("avi-demuxer"), NULL, VLC_TRUE );
         add_bool( "avi-interleaved", 0, NULL,
-                  "force interleaved method",
-                  "force interleaved method" );
+                  _("force interleaved method"),
+                  _("force interleaved method"), VLC_TRUE );
         add_bool( "avi-index", 0, NULL,
-                  "force index creation",
-                  "force index creation" );
+                  _("force index creation"),
+                  _("force index creation"), VLC_TRUE );
 
-    set_description( "avi demuxer" );
+    set_description( _("avi demuxer") );
     set_capability( "demux", 212 );
     set_callbacks( AVIInit, __AVIEnd );
 vlc_module_end();
@@ -142,7 +142,11 @@ static int input_ReadInPES( input_thread_t *p_input,
                                           p_pes->i_pes_size, 2048 ) );
         if( i_read <= 0 )
         {
-            return p_pes->i_pes_size;
+            /* should occur only with EOF and max allocation reached 
+             * it safer to  return an error */
+            /* free pes */
+            input_DeletePES( p_input->p_method_data, p_pes );
+            return -1;
         }
 
         if( !p_pes->p_first )
@@ -622,6 +626,7 @@ print_stat:
 static vlc_bool_t AVI_StreamStart ( input_thread_t *, demux_sys_t *, int );
 static int  AVI_StreamSeek   ( input_thread_t *, demux_sys_t *, int, mtime_t );
 static void AVI_StreamStop   ( input_thread_t *, demux_sys_t *, int );
+static int  AVI_StreamStopFinishedStreams( input_thread_t *, demux_sys_t * );
 
 static vlc_bool_t AVI_StreamStart( input_thread_t *p_input,
                                    demux_sys_t *p_avi, int i_stream )
@@ -679,6 +684,28 @@ static void    AVI_StreamStop( input_thread_t *p_input,
 #undef  p_stream
 }
 
+static int AVI_StreamStopFinishedStreams( input_thread_t *p_input,
+                                           demux_sys_t *p_avi )
+{
+    unsigned int i_stream;
+    int b_end;
+
+    for( i_stream = 0,b_end = VLC_TRUE;
+            i_stream < p_avi->i_streams; i_stream++ )
+    {
+#define p_stream    p_avi->pp_info[i_stream]
+        if( p_stream->i_idxposc >= p_stream->i_idxnb )
+        {
+            AVI_StreamStop( p_input, p_avi, i_stream );
+        }
+        else
+        {
+            b_end = VLC_FALSE;
+        }
+#undef  p_stream
+    }
+    return( b_end );
+}
 /****************************************************************************
  * AVI_MovieGetLength give max streams length in second
  ****************************************************************************/
@@ -702,7 +729,7 @@ static mtime_t  AVI_MovieGetLength( input_thread_t *p_input, demux_sys_t *p_avi
         {
             i_length =
                 (mtime_t)( p_stream->p_index[p_stream->i_idxnb-1].i_lengthtotal +
-                           p_stream->p_index[p_stream->i_idxnb-1].i_length ) /
+                           p_stream->p_index[p_stream->i_idxnb-1].i_length ) *
                 (mtime_t)p_stream->i_scale /
                 (mtime_t)p_stream->i_rate /
                 (mtime_t)p_stream->i_samplesize;
@@ -757,6 +784,8 @@ static void __AVIEnd ( vlc_object_t * p_this )
     }
 #endif
     AVI_ChunkFreeRoot( p_input, &p_avi->ck_root );
+
+    FREE( p_input->p_demux_data );
 }
 
 /*****************************************************************************
@@ -902,7 +931,7 @@ static int AVIInit( vlc_object_t * p_this )
                        p_avih->i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
                        p_avih->i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"" );
     }
-        
+
     /* now read info on each stream and create ES */
     p_avi->pp_info = calloc( p_avi->i_streams,
                             sizeof( avi_stream_t* ) );
@@ -941,7 +970,9 @@ static int AVIInit( vlc_object_t * p_this )
         p_info->i_rate  = p_avi_strh->i_rate;
         p_info->i_scale = p_avi_strh->i_scale;
         p_info->i_samplesize = p_avi_strh->i_samplesize;
-
+        msg_Dbg( p_input, "stream[%d] rate:%d scale:%d samplesize:%d",
+                 i,
+                 p_info->i_rate, p_info->i_scale, p_info->i_samplesize );
         switch( p_avi_strh->i_type )
         {
             case( AVIFOURCC_auds ):
@@ -1021,7 +1052,7 @@ static int AVIInit( vlc_object_t * p_this )
 #endif
                 break;
             default:
-                msg_Err( p_input, "stream[%d] unknown type", i );
+                msg_Warn( p_input, "stream[%d] unknown type", i );
                 p_info->i_cat = UNKNOWN_ES;
                 i_init_size = 0;
                 p_init_data = NULL;
@@ -1272,7 +1303,7 @@ static int AVI_StreamChunkFind( input_thread_t *p_input,
 
         if( AVI_PacketGetHeader( p_input, &avi_pk ) )
         {
-            msg_Err( p_input, "cannot get packet header" );
+            msg_Warn( p_input, "cannot get packet header" );
             return VLC_EGENERIC;
         }
         if( avi_pk.i_stream >= p_avi->i_streams ||
@@ -1509,7 +1540,7 @@ static int    AVISeek   ( input_thread_t *p_input,
 
             if( i_percent >= 100 )
             {
-                msg_Err( p_input, "cannot seek so far !" );
+                msg_Warn( p_input, "cannot seek so far !" );
                 return( -1 );
             }
             i_percent = __MAX( i_percent, 0 );
@@ -1530,7 +1561,7 @@ static int    AVISeek   ( input_thread_t *p_input,
             }
             if( !p_stream || !p_stream->b_activated )
             {
-                msg_Err( p_input, "cannot find any selected stream" );
+                msg_Warn( p_input, "cannot find any selected stream" );
                 return( -1 );
             }
 
@@ -1539,7 +1570,7 @@ static int    AVISeek   ( input_thread_t *p_input,
                                     i_stream,
                                     0 ) )
             {
-                msg_Err( p_input, "cannot seek" );
+                msg_Warn( p_input, "cannot seek" );
                 return( -1 );
             }
 
@@ -1550,7 +1581,7 @@ static int    AVISeek   ( input_thread_t *p_input,
                 if( AVI_SetStreamChunk( p_input,
                                         i_stream, p_stream->i_idxposc + 1 ) )
                 {
-                    msg_Err( p_input, "cannot seek" );
+                    msg_Warn( p_input, "cannot seek" );
                     return( -1 );
                 }
             }
@@ -1661,16 +1692,20 @@ typedef struct avi_stream_toread_s
 
 static int AVIDemux_Seekable( input_thread_t *p_input )
 {
+    unsigned int i_stream_count;
     unsigned int i_stream;
     vlc_bool_t b_stream;
-
+    vlc_bool_t b_play_audio;
+    vlc_bool_t b_video; /* is there some video track selected */
     // cannot be more than 100 stream (dcXX or wbXX)
     avi_stream_toread_t toread[100];
 
     demux_sys_t *p_avi = p_input->p_demux_data;
 
+
     /* detect new selected/unselected streams */
-    for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
+    for( i_stream = 0,i_stream_count= 0, b_video = VLC_FALSE;
+            i_stream < p_avi->i_streams; i_stream++ )
     {
 #define p_stream    p_avi->pp_info[i_stream]
         if( p_stream->p_es )
@@ -1687,15 +1722,29 @@ static int AVIDemux_Seekable( input_thread_t *p_input )
                 AVI_StreamStop( p_input, p_avi, i_stream );
             }
         }
+        if( p_stream->b_activated )
+        {
+            i_stream_count++;
+            if( p_stream->i_cat == VIDEO_ES )
+            {
+                b_video = VLC_TRUE;
+            }
+        }
 #undef  p_stream
     }
 
+    if( i_stream_count <= 0 )
+    {
+        msg_Warn( p_input, "no track selected, exiting..." );
+        return( 0 );
+    }
+
     if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
     {
         mtime_t i_date;
         int i_percent;
         /* first wait for empty buffer, arbitrary time FIXME */
-//        msleep( DEFAULT_PTS_DELAY );
+        //msleep( DEFAULT_PTS_DELAY );
 
         i_date = (mtime_t)1000000 *
                  (mtime_t)p_avi->i_length *
@@ -1733,6 +1782,19 @@ static int AVIDemux_Seekable( input_thread_t *p_input )
         subtitle_Demux( p_avi->p_sub, p_avi->i_time );
     }
 #endif
+
+    /* *** send audio data to decoder if rate == DEFAULT_RATE or no video *** */
+    vlc_mutex_lock( &p_input->stream.stream_lock );
+    if( p_input->stream.control.i_rate == DEFAULT_RATE || !b_video )
+    {
+        b_play_audio = VLC_TRUE;
+    }
+    else
+    {
+        b_play_audio = VLC_FALSE;
+    }
+    vlc_mutex_unlock( &p_input->stream.stream_lock );
+
     /* init toread */
     for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
     {
@@ -1740,7 +1802,6 @@ static int AVIDemux_Seekable( input_thread_t *p_input )
         mtime_t i_dpts;
 
         toread[i_stream].b_ok = p_stream->b_activated;
-
         if( p_stream->i_idxposc < p_stream->i_idxnb )
         {
             toread[i_stream].i_posf =
@@ -1819,13 +1880,14 @@ static int AVIDemux_Seekable( input_thread_t *p_input )
 
         if( i_pos == -1 )
         {
-            /* no valid index, we will parse directly the stream */
+            /* no valid index, we will parse directly the stream
+             * in case we fail we will disable all finished stream */
             if( p_avi->i_movi_lastchunk_pos >= p_avi->i_movi_begin )
             {
                 AVI_SeekAbsolute( p_input, p_avi->i_movi_lastchunk_pos );
                 if( AVI_PacketNext( p_input ) )
                 {
-                    return( 0 );
+                    return( AVI_StreamStopFinishedStreams( p_input, p_avi ) ? 0 : 1 );
                 }
             }
             else
@@ -1839,8 +1901,9 @@ static int AVIDemux_Seekable( input_thread_t *p_input )
 
                 if( AVI_PacketGetHeader( p_input, &avi_pk ) )
                 {
-                    msg_Err( p_input, "cannot get packet header" );
-                    return( 0 );
+                    msg_Warn( p_input,
+                             "cannot get packet header, track disabled" );
+                    return( AVI_StreamStopFinishedStreams( p_input, p_avi ) ? 0 : 1 );
                 }
                 if( avi_pk.i_stream >= p_avi->i_streams ||
                     ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
@@ -1853,8 +1916,9 @@ static int AVIDemux_Seekable( input_thread_t *p_input )
                         default:
                             if( AVI_PacketNext( p_input ) )
                             {
-                                msg_Err( p_input, "cannot skip packet" );
-                                return( 0 );
+                                msg_Warn( p_input,
+                                          "cannot skip packet, track disabled" );
+                                return( AVI_StreamStopFinishedStreams( p_input, p_avi ) ? 0 : 1 );
                             }
                             break;
                     }
@@ -1884,8 +1948,9 @@ static int AVIDemux_Seekable( input_thread_t *p_input )
                     {
                         if( AVI_PacketNext( p_input ) )
                         {
-                            msg_Err( p_input, "cannot skip packet" );
-                            return( 0 );
+                            msg_Warn( p_input,
+                                      "cannot skip packet, track disabled" );
+                            return( AVI_StreamStopFinishedStreams( p_input, p_avi ) ? 0 : 1 );
                         }
                     }
                 }
@@ -1900,10 +1965,22 @@ static int AVIDemux_Seekable( input_thread_t *p_input )
         /* read thoses data */
         if( p_stream->i_samplesize )
         {
+            unsigned int i_toread;
+
+            if( ( i_toread = toread[i_stream].i_toread ) <= 0 )
+            {
+                if( p_stream->i_samplesize > 1 )
+                {
+                    i_toread = p_stream->i_samplesize;
+                }
+                else
+                {
+                    i_toread = __MAX( AVI_PTSToByte( p_stream, 20 * 1000 ), 100 );
+                }
+            }
             i_size = __MIN( p_stream->p_index[p_stream->i_idxposc].i_length -
                                 p_stream->i_idxposb,
-                            __MAX( toread[i_stream].i_toread,
-                                   p_stream->i_samplesize ) );
+                            i_toread );
         }
         else
         {
@@ -1917,7 +1994,8 @@ static int AVIDemux_Seekable( input_thread_t *p_input )
 
         if( input_ReadInPES( p_input, &p_pes, __EVEN( i_size ) ) < 0 )
         {
-            msg_Err( p_input, "failled reading data" );
+            msg_Warn( p_input, "failled reading data" );
+            AVI_StreamStop( p_input, p_avi, i_stream );
             toread[i_stream].b_ok = VLC_FALSE;
             continue;
         }
@@ -1975,35 +2053,15 @@ static int AVIDemux_Seekable( input_thread_t *p_input )
 
         b_stream = VLC_TRUE; // at least one read succeed
 
-        if( p_stream->p_es && p_stream->p_es->p_decoder_fifo )
+        if( p_stream->p_es && p_stream->p_es->p_decoder_fifo &&
+            ( b_play_audio || p_stream->i_cat != AUDIO_ES ) )
         {
             p_pes->i_dts =
                 p_pes->i_pts =
                     input_ClockGetTS( p_input,
                                       p_input->stream.p_selected_program,
                                       p_pes->i_pts * 9/100);
-#if 0
-            /* debuuging: split pes in 2 parts */
-            if( p_pes->i_nb_data >= 2 && p_stream->i_cat == AUDIO_ES )
-            {
-                pes_packet_t  *p_pes_;
-                data_packet_t *p_data;
-                int           i_nb_data;
 
-                p_pes_ = PES_split( p_input, p_stream, p_pes );
-                if( p_pes_->i_nb_data >= 2 )
-                {
-                    input_DecodePES( p_stream->p_es->p_decoder_fifo, PES_split( p_input,p_stream,p_pes_ ) );
-                }
-                input_DecodePES( p_stream->p_es->p_decoder_fifo,p_pes_ );
-
-                if( p_pes->i_nb_data >= 2 )
-                {
-                    input_DecodePES( p_stream->p_es->p_decoder_fifo, PES_split( p_input,p_stream,p_pes ) );
-                }
-                //input_DecodePES( p_stream->p_es->p_decoder_fifo,p_pes );
-            }
-#endif
             input_DecodePES( p_stream->p_es->p_decoder_fifo, p_pes );
         }
         else
@@ -2058,7 +2116,7 @@ static int AVIDemux_UnSeekable( input_thread_t *p_input )
     }
     if( !p_stream_master )
     {
-        msg_Err( p_input, "no more stream selected" );
+        msg_Warn( p_input, "no more stream selected" );
         return( 0 );
     }