]> git.sesse.net Git - vlc/blobdiff - modules/demux/avi/avi.c
* modules/demux/*: removed useless probing messages.
[vlc] / modules / demux / avi / avi.c
index 315201777f51f666912311e0d595be6f9756d995..17433a0c60b358d85180591d4f24b81f89607abc 100644 (file)
@@ -50,6 +50,8 @@ static void Close( vlc_object_t * );
 vlc_module_begin();
     set_description( _("AVI demuxer") );
     set_capability( "demux2", 212 );
+    set_category( CAT_INPUT );
+    set_subcategory( SUBCAT_INPUT_DEMUX );
 
     add_bool( "avi-interleaved", 0, NULL,
               INTERLEAVE_TEXT, INTERLEAVE_LONGTEXT, VLC_TRUE );
@@ -200,20 +202,21 @@ static int Open( vlc_object_t * p_this )
     avi_chunk_avih_t    *p_avih;
 
     unsigned int i_track;
-    unsigned int i;
+    unsigned int i, i_peeker;
 
     uint8_t  *p_peek;
 
-
     /* Is it an avi file ? */
-    if( stream_Peek( p_demux->s, &p_peek, 12 ) < 12 )
+    if( stream_Peek( p_demux->s, &p_peek, 200 ) < 200 ) return VLC_EGENERIC;
+
+    for( i_peeker = 0; i_peeker < 188; i_peeker++ )
     {
-        msg_Err( p_demux, "cannot peek()" );
-        return VLC_EGENERIC;
+        if( !strncmp( &p_peek[0], "RIFF", 4 ) &&
+            !strncmp( &p_peek[8], "AVI ", 4 ) ) break;
+        p_peek++;
     }
-    if( strncmp( &p_peek[0], "RIFF", 4 ) || strncmp( &p_peek[8], "AVI ", 4 ) )
+    if( i_peeker == 188 )
     {
-        msg_Warn( p_demux, "avi module discarded (invalid header)" );
         return VLC_EGENERIC;
     }
 
@@ -238,6 +241,11 @@ static int Open( vlc_object_t * p_this )
         p_demux->pf_demux = Demux_UnSeekable;
     }
 
+    if( i_peeker > 0 )
+    {
+       stream_Read( p_demux->s, NULL, i_peeker );
+    }
+
     if( AVI_ChunkReadRoot( p_demux->s, &p_sys->ck_root ) )
     {
         msg_Err( p_demux, "avi module discarded (invalid file)" );
@@ -292,7 +300,7 @@ static int Open( vlc_object_t * p_this )
         goto error;
     }
 
-    /* print informations on streams */
+    /* print information on streams */
     msg_Dbg( p_demux, "AVIH: %d stream, flags %s%s%s%s ",
              i_track,
              p_avih->i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
@@ -316,6 +324,7 @@ static int Open( vlc_object_t * p_this )
         avi_track_t      *tk = malloc( sizeof( avi_track_t ) );
         avi_chunk_list_t *p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i );
         avi_chunk_strh_t *p_strh = AVI_ChunkFind( p_strl, AVIFOURCC_strh, 0 );
+        avi_chunk_STRING_t *p_strn = AVI_ChunkFind( p_strl, AVIFOURCC_strn, 0 );
         avi_chunk_strf_auds_t *p_auds;
         avi_chunk_strf_vids_t *p_vids;
         es_format_t fmt;
@@ -402,11 +411,20 @@ static int Open( vlc_object_t * p_this )
                             break;
                     }
                     es_format_Init( &fmt, VIDEO_ES, tk->i_codec );
+
+                    if( p_vids->p_bih->biBitCount == 24 )
+                    {
+                        /* This is in BGR format */
+                        fmt.video.i_bmask = 0x00ff0000;
+                        fmt.video.i_gmask = 0x0000ff00;
+                        fmt.video.i_rmask = 0x000000ff;
+                    }
                 }
                 else
                 {
                     es_format_Init( &fmt, VIDEO_ES, p_vids->p_bih->biCompression );
-                    if( tk->i_codec == FOURCC_mp4v && !strncasecmp( (char*)&p_strh->i_handler, "XVID", 4 ) )
+                    if( tk->i_codec == FOURCC_mp4v &&
+                        !strncasecmp( (char*)&p_strh->i_handler, "XVID", 4 ) )
                     {
                         fmt.i_codec = VLC_FOURCC( 'X', 'V', 'I', 'D' );
                     }
@@ -426,12 +444,33 @@ static int Open( vlc_object_t * p_this )
                          p_vids->p_bih->biHeight,
                          p_vids->p_bih->biBitCount,
                          (float)tk->i_rate/(float)tk->i_scale );
+
+                if( p_vids->p_bih->biCompression == 0x00 )
+                {
+                    /* RGB DIB are coded from bottom to top */
+                    fmt.video.i_height =
+                        (unsigned int)(-(int)p_vids->p_bih->biHeight);
+                }
+                break;
+
+            case( AVIFOURCC_txts):
+                tk->i_cat   = SPU_ES;
+                tk->i_codec = VLC_FOURCC( 's', 'u', 'b', 't' );
+                msg_Dbg( p_demux, "stream[%d] subtitles", i );
+                es_format_Init( &fmt, SPU_ES, tk->i_codec );
                 break;
+                
+            case( AVIFOURCC_mids):
+                msg_Dbg( p_demux, "stream[%d] midi is UNSUPPORTED", i );
             default:
                 msg_Warn( p_demux, "stream[%d] unknown type", i );
                 free( tk );
                 continue;
         }
+        if( p_strn )
+        {
+            fmt.psz_description = strdup( p_strn->p_str );
+        }
         tk->p_es = es_out_Add( p_demux->out, &fmt );
         TAB_APPEND( p_sys->i_track, p_sys->track, tk );
     }
@@ -610,12 +649,21 @@ static int Demux_Seekable( demux_t *p_demux )
 
     if( i_track_count <= 0 )
     {
+        int64_t i_length = p_sys->i_length * (mtime_t)1000000;
+
+        p_sys->i_time += 25*1000;  /* read 25ms */
+        if( i_length > 0 )
+        {
+            if( p_sys->i_time >= i_length )
+                return 0;
+            return 1;
+        }
         msg_Warn( p_demux, "no track selected, exiting..." );
-        return( 0 );
+        return 0;
     }
 
     /* wait for the good time */
-    es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_time );
+    es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_time + 1 );
     p_sys->i_time += 25*1000;  /* read 25ms */
 
     /* init toread */
@@ -802,7 +850,8 @@ static int Demux_Seekable( demux_t *p_demux )
                 }
                 else
                 {
-                    i_toread = __MAX( AVI_PTSToByte( tk, 20 * 1000 ), 100 );
+                    i_toread = AVI_PTSToByte( tk, 20 * 1000 );
+                    i_toread = __MAX( i_toread, 100 );
                 }
             }
             i_size = __MIN( tk->p_index[tk->i_idxposc].i_length -
@@ -836,7 +885,7 @@ static int Demux_Seekable( demux_t *p_demux )
             p_frame->p_buffer += 8;
             p_frame->i_buffer -= 8;
         }
-        p_frame->i_pts = AVI_GetPTS( tk );
+        p_frame->i_pts = AVI_GetPTS( tk ) + 1;
         if( tk->p_index[tk->i_idxposc].i_flags&AVIIF_KEYFRAME )
         {
             p_frame->i_flags = BLOCK_FLAG_TYPE_I;
@@ -917,7 +966,7 @@ static int Demux_UnSeekable( demux_t *p_demux )
     unsigned int i_stream;
     unsigned int i_packet;
 
-    es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_time );
+    es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_time + 1 );
 
     /* *** find master stream for data packet skipping algo *** */
     /* *** -> first video, if any, or first audio ES *** */
@@ -998,7 +1047,7 @@ static int Demux_UnSeekable( demux_t *p_demux )
                 {
                     return( -1 );
                 }
-                p_frame->i_pts = AVI_GetPTS( p_stream );
+                p_frame->i_pts = AVI_GetPTS( p_stream ) + 1;
 
                 if( avi_pk.i_cat != VIDEO_ES )
                     p_frame->i_dts = p_frame->i_pts;
@@ -1042,8 +1091,6 @@ static int Demux_UnSeekable( demux_t *p_demux )
 
 /*****************************************************************************
  * Seek: goto to i_date or i_percent
- *****************************************************************************
- * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
  *****************************************************************************/
 static int Seek( demux_t *p_demux, mtime_t i_date, int i_percent )
 {
@@ -1066,7 +1113,7 @@ static int Seek( demux_t *p_demux, mtime_t i_date, int i_percent )
             if( i_percent >= 100 )
             {
                 msg_Warn( p_demux, "cannot seek so far !" );
-                return( -1 );
+                return VLC_EGENERIC;
             }
             i_percent = __MAX( i_percent, 0 );
 
@@ -1086,14 +1133,14 @@ static int Seek( demux_t *p_demux, mtime_t i_date, int i_percent )
             if( !p_stream || !p_stream->b_activated )
             {
                 msg_Warn( p_demux, "cannot find any selected stream" );
-                return( -1 );
+                return VLC_EGENERIC;
             }
 
             /* be sure that the index exist */
             if( AVI_StreamChunkSet( p_demux, i_stream, 0 ) )
             {
                 msg_Warn( p_demux, "cannot seek" );
-                return( -1 );
+                return VLC_EGENERIC;
             }
 
             while( i_pos >= p_stream->p_index[p_stream->i_idxposc].i_pos +
@@ -1104,7 +1151,7 @@ static int Seek( demux_t *p_demux, mtime_t i_date, int i_percent )
                                         i_stream, p_stream->i_idxposc + 1 ) )
                 {
                     msg_Warn( p_demux, "cannot seek" );
-                    return( -1 );
+                    return VLC_EGENERIC;
                 }
             }
 
@@ -1148,12 +1195,12 @@ static int Seek( demux_t *p_demux, mtime_t i_date, int i_percent )
             p_sys->i_time = i_date;
         }
 #undef p_stream
-        return( 1 );
+        return VLC_SUCCESS;
     }
     else
     {
         msg_Err( p_demux, "shouldn't yet be executed" );
-        return( -1 );
+        return VLC_EGENERIC;
     }
 }
 
@@ -1214,7 +1261,7 @@ static int    Control( demux_t *p_demux, int i_query, va_list args )
             if( p_sys->b_seekable )
             {
                 i64 = (mtime_t)(1000000.0 * p_sys->i_length * f );
-                return Seek( p_demux, i64, (int)(f * 100) ) < 0 ? VLC_EGENERIC : VLC_SUCCESS;
+                return Seek( p_demux, i64, (int)(f * 100) );
             }
             else
             {
@@ -1628,7 +1675,7 @@ static int AVI_GetKeyFlag( vlc_fourcc_t i_fourcc, uint8_t *p_byte )
              */
             return p_byte[0] & 0xC0 ? 0 : AVIIF_KEYFRAME;
         case FOURCC_mp4v:
-            /* we should find first occurence of 0x000001b6 (32bits)
+            /* we should find first occurrence of 0x000001b6 (32bits)
              *  startcode:      0x000001b6   32bits
              *  piture type     0(I),1(P)     2bits
              */
@@ -1928,6 +1975,8 @@ static int AVI_IndexLoad_idx1( demux_t *p_demux )
     off_t        i_offset;
     unsigned int i;
 
+    vlc_bool_t b_keyset[100];
+
     p_riff = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0);
     p_idx1 = AVI_ChunkFind( p_riff, AVIFOURCC_idx1, 0);
     p_movi = AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0);
@@ -1951,6 +2000,10 @@ static int AVI_IndexLoad_idx1( demux_t *p_demux )
         }
     }
 
+    /* Reset b_keyset */
+    for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
+        b_keyset[i_stream] = VLC_FALSE;
+
     for( i_index = 0; i_index < p_idx1->i_entry_count; i_index++ )
     {
         unsigned int i_cat;
@@ -1968,6 +2021,21 @@ static int AVI_IndexLoad_idx1( demux_t *p_demux )
             index.i_pos     = p_idx1->entry[i_index].i_pos + i_offset;
             index.i_length  = p_idx1->entry[i_index].i_length;
             AVI_IndexAddEntry( p_sys, i_stream, &index );
+
+            if( index.i_flags&AVIIF_KEYFRAME )
+                b_keyset[i_stream] = VLC_TRUE;
+        }
+    }
+
+    for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
+    {
+        if( !b_keyset[i_stream] )
+        {
+            avi_track_t *tk = p_sys->track[i_stream];
+
+            msg_Dbg( p_demux, "no key frame set for track %d", i_stream );
+            for( i_index = 0; i_index < tk->i_idxnb; i_index++ )
+                tk->p_index[i_index].i_flags |= AVIIF_KEYFRAME;
         }
     }
     return VLC_SUCCESS;
@@ -2008,7 +2076,7 @@ static void __Parse_indx( demux_t    *p_demux,
     }
     else
     {
-        msg_Warn( p_demux, "unknow subtype index(0x%x)", p_indx->i_indexsubtype );
+        msg_Warn( p_demux, "unknown subtype index(0x%x)", p_indx->i_indexsubtype );
     }
 }
 
@@ -2045,7 +2113,7 @@ static void AVI_IndexLoad_indx( demux_t *p_demux )
         }
         else if( p_indx->i_indextype == AVI_INDEX_OF_INDEXES )
         {
-            avi_chunk_indx_t    ck_sub;
+            avi_chunk_t    ck_sub;
             for( i = 0; i < p_indx->i_entriesinuse; i++ )
             {
                 if( stream_Seek( p_demux->s, p_indx->idx.super[i].i_offset )||
@@ -2053,12 +2121,12 @@ static void AVI_IndexLoad_indx( demux_t *p_demux )
                 {
                     break;
                 }
-                __Parse_indx( p_demux, i_stream, &ck_sub );
+                __Parse_indx( p_demux, i_stream, &ck_sub.indx );
             }
         }
         else
         {
-            msg_Warn( p_demux, "unknow type index(0x%x)", p_indx->i_indextype );
+            msg_Warn( p_demux, "unknown type index(0x%x)", p_indx->i_indextype );
         }
 #undef p_stream
     }