* avi: Support for OpenDML file.
authorLaurent Aimar <fenrir@videolan.org>
Sun, 27 Apr 2003 11:55:03 +0000 (11:55 +0000)
committerLaurent Aimar <fenrir@videolan.org>
Sun, 27 Apr 2003 11:55:03 +0000 (11:55 +0000)
 Not tested with file size > 2Go, so report status.

modules/demux/avi/avi.c
modules/demux/avi/avi.h
modules/demux/avi/libavi.c
modules/demux/avi/libavi.h

index d2dee7a..99ce734 100644 (file)
@@ -2,7 +2,7 @@
  * avi.c : AVI file Stream input module for vlc
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: avi.c,v 1.42 2003/03/30 18:14:37 gbazin Exp $
+ * $Id: avi.c,v 1.43 2003/04/27 11:55:03 fenrir Exp $
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -334,7 +334,7 @@ static int AVI_PacketGetHeader( input_thread_t *p_input, avi_packet_t *p_pk )
     p_pk->i_fourcc  = GetFOURCC( p_peek );
     p_pk->i_size    = GetDWLE( p_peek + 4 );
     p_pk->i_pos     = AVI_TellAbsolute( p_input );
-    if( p_pk->i_fourcc == AVIFOURCC_LIST )
+    if( p_pk->i_fourcc == AVIFOURCC_LIST || p_pk->i_fourcc == AVIFOURCC_RIFF )
     {
         p_pk->i_type = GetFOURCC( p_peek + 8 );
     }
@@ -357,10 +357,15 @@ static int AVI_PacketNext( input_thread_t *p_input )
     {
         return VLC_EGENERIC;
     }
+
     if( avi_ck.i_fourcc == AVIFOURCC_LIST && avi_ck.i_type == AVIFOURCC_rec )
     {
         return AVI_SkipBytes( p_input, 12 );
     }
+    else if( avi_ck.i_fourcc == AVIFOURCC_RIFF && avi_ck.i_type == AVIFOURCC_AVIX )
+    {
+        return AVI_SkipBytes( p_input, 24 );
+    }
     else
     {
         return AVI_SkipBytes( p_input, __EVEN( avi_ck.i_size ) + 8 );
@@ -413,6 +418,7 @@ static int AVI_PacketSearch( input_thread_t *p_input )
         {
             case AVIFOURCC_JUNK:
             case AVIFOURCC_LIST:
+            case AVIFOURCC_RIFF:
             case AVIFOURCC_idx1:
                 return VLC_SUCCESS;
         }
@@ -472,7 +478,7 @@ static void AVI_IndexAddEntry( demux_sys_t *p_avi,
     }
 }
 
-static void AVI_IndexLoad( input_thread_t *p_input )
+static void AVI_IndexLoad_idx1( input_thread_t *p_input )
 {
     demux_sys_t *p_avi = p_input->p_demux_data;
 
@@ -495,12 +501,7 @@ static void AVI_IndexLoad( input_thread_t *p_input )
         msg_Warn( p_input, "cannot find idx1 chunk, no index defined" );
         return;
     }
-    for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
-    {
-        p_avi->pp_info[i_stream]->i_idxnb  = 0;
-        p_avi->pp_info[i_stream]->i_idxmax = 0;
-        p_avi->pp_info[i_stream]->p_index  = NULL;
-    }
+
     /* *** calculate offset *** */
     if( p_idx1->i_entry_count > 0 &&
         p_idx1->entry[0].i_pos < p_movi->i_chunk_pos )
@@ -531,16 +532,129 @@ static void AVI_IndexLoad( input_thread_t *p_input )
             AVI_IndexAddEntry( p_avi, i_stream, &index );
         }
     }
+}
+
+static void __Parse_indx( input_thread_t    *p_input,
+                          int               i_stream,
+                          avi_chunk_indx_t  *p_indx )
+{
+    demux_sys_t         *p_avi    = p_input->p_demux_data;
+    AVIIndexEntry_t     index;
+    int32_t             i;
+
+    msg_Dbg( p_input, "loading subindex(0x%x) %d entries", p_indx->i_indextype, p_indx->i_entriesinuse );
+    if( p_indx->i_indexsubtype == 0 )
+    {
+        for( i = 0; i < p_indx->i_entriesinuse; i++ )
+        {
+            index.i_id      = p_indx->i_id;
+            index.i_flags   = p_indx->idx.std[i].i_size & 0x80000000 ? 0 : AVIIF_KEYFRAME;
+            index.i_pos     = p_indx->i_baseoffset + p_indx->idx.std[i].i_offset - 8;
+            index.i_length  = p_indx->idx.std[i].i_size&0x7fffffff;
+
+            AVI_IndexAddEntry( p_avi, i_stream, &index );
+        }
+    }
+    else if( p_indx->i_indexsubtype == AVI_INDEX_2FIELD )
+    {
+        for( i = 0; i < p_indx->i_entriesinuse; i++ )
+        {
+            index.i_id      = p_indx->i_id;
+            index.i_flags   = p_indx->idx.field[i].i_size & 0x80000000 ? 0 : AVIIF_KEYFRAME;
+            index.i_pos     = p_indx->i_baseoffset + p_indx->idx.field[i].i_offset - 8;
+            index.i_length  = p_indx->idx.field[i].i_size;
+
+            AVI_IndexAddEntry( p_avi, i_stream, &index );
+        }
+    }
+    else
+    {
+        msg_Warn( p_input, "unknow subtype index(0x%x)", p_indx->i_indexsubtype );
+    }
+}
+
+static void AVI_IndexLoad_indx( input_thread_t *p_input )
+{
+    demux_sys_t         *p_avi = p_input->p_demux_data;
+    unsigned int        i_stream;
+    int32_t             i;
+
+    avi_chunk_list_t    *p_riff;
+    avi_chunk_list_t    *p_hdrl;
+
+    p_riff = (void*)AVI_ChunkFind( &p_avi->ck_root,
+                                   AVIFOURCC_RIFF, 0);
+    p_hdrl = (void*)AVI_ChunkFind( p_riff, AVIFOURCC_hdrl, 0 );
+
+    for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
+    {
+        avi_chunk_list_t    *p_strl;
+        avi_chunk_indx_t    *p_indx;
+
+#define p_stream  p_avi->pp_info[i_stream]
+        p_strl = (void*)AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i_stream );
+        p_indx = (void*)AVI_ChunkFind( p_strl, AVIFOURCC_indx, 0 );
+
+        if( !p_indx )
+        {
+            msg_Warn( p_input, "cannot find indx (misdetect/broken OpenDML file?)" );
+            continue;
+        }
+
+        if( p_indx->i_indextype == AVI_INDEX_OF_CHUNKS )
+        {
+            __Parse_indx( p_input, i_stream, p_indx );
+        }
+        else if( p_indx->i_indextype == AVI_INDEX_OF_INDEXES )
+        {
+            avi_chunk_indx_t    ck_sub;
+            for( i = 0; i < p_indx->i_entriesinuse; i++ )
+            {
+                AVI_SeekAbsolute( p_input, p_indx->idx.super[i].i_offset );
+
+                if( !AVI_ChunkRead( p_input, &ck_sub, NULL, p_avi->b_seekable ) )
+                {
+                    __Parse_indx( p_input, i_stream, &ck_sub );
+                }
+            }
+        }
+        else
+        {
+            msg_Warn( p_input, "unknow type index(0x%x)", p_indx->i_indextype );
+        }
+#undef p_stream
+    }
+}
+static void AVI_IndexLoad( input_thread_t *p_input )
+{
+    demux_sys_t *p_avi = p_input->p_demux_data;
+    unsigned int i_stream;
+
+    for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
+    {
+        p_avi->pp_info[i_stream]->i_idxnb  = 0;
+        p_avi->pp_info[i_stream]->i_idxmax = 0;
+        p_avi->pp_info[i_stream]->p_index  = NULL;
+    }
+
+    if( p_avi->b_odml )
+    {
+        AVI_IndexLoad_indx( p_input );
+    }
+    else
+    {
+        AVI_IndexLoad_idx1( p_input );
+    }
+
+
     for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
     {
         msg_Dbg( p_input,
-                "stream[%d] creating %d index entries",
+                "stream[%d] created %d index entries",
                 i_stream,
                 p_avi->pp_info[i_stream]->i_idxnb );
     }
-
 }
-
 static void AVI_IndexCreate( input_thread_t *p_input )
 {
     demux_sys_t *p_avi = p_input->p_demux_data;
@@ -596,7 +710,22 @@ static void AVI_IndexCreate( input_thread_t *p_input )
             switch( pk.i_fourcc )
             {
                 case AVIFOURCC_idx1:
+                    if( p_avi->b_odml )
+                    {
+                        avi_chunk_list_t *p_avix;
+                        p_avix = (void*)AVI_ChunkFind( &p_avi->ck_root,
+                                                       AVIFOURCC_RIFF, 1 );
+
+                        msg_Dbg( p_input, "looking for new RIFF chunk" );
+                        if( AVI_SeekAbsolute( p_input, p_avix->i_chunk_pos + 24) )
+                        {
+                            goto print_stat;
+                        }
+                        break;
+                    }
                     goto print_stat;
+                case AVIFOURCC_RIFF:
+                        msg_Dbg( p_input, "new RIFF chunk found" );
                 case AVIFOURCC_rec:
                 case AVIFOURCC_JUNK:
                     break;
@@ -609,7 +738,8 @@ static void AVI_IndexCreate( input_thread_t *p_input )
                     }
             }
         }
-        if( pk.i_pos + pk.i_size >= i_movi_end ||
+
+        if( ( !p_avi->b_odml && pk.i_pos + pk.i_size >= i_movi_end ) ||
             AVI_PacketNext( p_input ) )
         {
             break;
@@ -844,6 +974,7 @@ static int AVIInit( vlc_object_t * p_this )
     p_avi->b_seekable = ( ( p_input->stream.b_seekable )
                         &&( p_input->stream.i_method == INPUT_METHOD_FILE ) );
     p_avi->i_movi_lastchunk_pos = 0;
+    p_avi->b_odml = VLC_FALSE;
 
     /* *** for unseekable stream, automaticaly use AVIDemux_interleaved *** */
     if( !p_avi->b_seekable || config_GetInt( p_input, "avi-interleaved" ) )
@@ -858,6 +989,29 @@ static int AVIInit( vlc_object_t * p_this )
     }
     AVI_ChunkDumpDebug( p_input, &p_avi->ck_root );
 
+    if( AVI_ChunkCount( &p_avi->ck_root, AVIFOURCC_RIFF ) > 1 )
+    {
+        int i_count = AVI_ChunkCount( &p_avi->ck_root, AVIFOURCC_RIFF );
+        int i;
+
+        msg_Warn( p_input, "multiple riff -> OpenDML ?" );
+        for( i = 1; i < i_count; i++ )
+        {
+            avi_chunk_list_t *p_avix;
+
+            p_avix = (avi_chunk_list_t*)AVI_ChunkFind( &p_avi->ck_root,
+                                                       AVIFOURCC_RIFF, i );
+            if( p_avix->i_type == AVIFOURCC_AVIX )
+            {
+                msg_Warn( p_input, "detected OpenDML file" );
+
+                p_avi->b_odml = VLC_TRUE;
+                break;
+            }
+        }
+        p_avi->b_odml = VLC_TRUE;
+    }
+
 
     p_riff  = (avi_chunk_list_t*)AVI_ChunkFind( &p_avi->ck_root,
                                                 AVIFOURCC_RIFF, 0 );
@@ -1331,6 +1485,59 @@ static mtime_t AVI_GetPTS( avi_stream_t *p_info )
     }
 }
 
+#if 0
+static void AVI_FixPTS( avi_stream_t *p_stream, pes_packet_t *p_pes )
+{
+    data_packet_t *p_data;
+    uint8_t       *p;
+    int           i_pos = 0;
+
+    switch( p_stream->i_fourcc )
+    {
+        case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
+            p_data = p_pes->p_first;
+            while( p_data )
+            {
+                p = p_data->p_payload_start;
+                while( p < p_data->p_payload_end - 2 )
+                {
+                    if( p[0] == 0xff && ( p[1]&0xe0) == 0xe0 )
+                    {
+                        mtime_t i_diff = AVI_GetDPTS( p_stream, i_pos );
+                        p_pes->i_dts += i_diff;
+                        p_pes->i_pts += i_diff;
+                        return;
+                    }
+                    p++; i_pos++;
+                }
+                p_data = p_data->p_next;
+            }
+            return;
+        case VLC_FOURCC( 'a', '5', '2', ' ' ):
+            p_data = p_pes->p_first;
+            while( p_data )
+            {
+                p = p_data->p_payload_start;
+                while( p < p_data->p_payload_end - 2 )
+                {
+                    if( p[0] == 0x0b && p[1] == 0x77 )
+                    {
+                        mtime_t i_diff = AVI_GetDPTS( p_stream, i_pos );
+                        p_pes->i_dts += i_diff;
+                        p_pes->i_pts += i_diff;
+                    }
+                    p++; i_pos++;
+                }
+                p_data = p_data->p_next;
+            }
+            return;
+        default:
+            /* we can't fix :( */
+            return;
+    }
+}
+#endif
+
 static int AVI_StreamChunkFind( input_thread_t *p_input,
                                 unsigned int i_stream )
 {
@@ -1363,17 +1570,9 @@ static int AVI_StreamChunkFind( input_thread_t *p_input,
         if( avi_pk.i_stream >= p_avi->i_streams ||
             ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
         {
-            switch( avi_pk.i_fourcc )
+            if( AVI_PacketNext( p_input ) )
             {
-                case AVIFOURCC_LIST:
-                    AVI_SkipBytes( p_input, 12 );
-                    break;
-                default:
-                    if( AVI_PacketNext( p_input ) )
-                    {
-                        return VLC_EGENERIC;
-                    }
-                    break;
+                return VLC_EGENERIC;
             }
         }
         else
@@ -1585,7 +1784,7 @@ static int    AVISeek   ( input_thread_t *p_input,
         if( !p_avi->i_length )
         {
             avi_stream_t *p_stream;
-            uint64_t i_pos;
+            int64_t i_pos;
 
             /* use i_percent to create a true i_date */
             msg_Warn( p_input,
@@ -2068,6 +2267,14 @@ static int AVIDemux_Seekable( input_thread_t *p_input )
 
         p_pes->i_pts = AVI_GetPTS( p_stream );
 
+#if 0
+        /* fix pts for audio: ie pts sould be for the first byte of the first frame */
+        if( p_stream->i_samplesize == 1 )
+        {
+            AVI_FixPTS( p_stream, p_pes );
+        }
+#endif
+
         /* read data */
         if( p_stream->i_samplesize )
         {
@@ -2199,8 +2406,13 @@ static int AVIDemux_UnSeekable( input_thread_t *p_input )
             {
                 case AVIFOURCC_JUNK:
                 case AVIFOURCC_LIST:
+                case AVIFOURCC_RIFF:
                     return( !AVI_PacketNext( p_input ) ? 1 : 0 );
                 case AVIFOURCC_idx1:
+                    if( p_avi->b_odml )
+                    {
+                        return( !AVI_PacketNext( p_input ) ? 1 : 0 );
+                    }
                     return( 0 );    // eof
                 default:
                     msg_Warn( p_input,
index e60aaf9..39e7e57 100644 (file)
@@ -2,7 +2,7 @@
  * avi.h : AVI file Stream input module for vlc
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: avi.h,v 1.8 2002/12/06 16:34:06 sam Exp $
+ * $Id: avi.h,v 1.9 2003/04/27 11:55:03 fenrir Exp $
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -38,7 +38,7 @@ typedef struct AVIIndexEntry_s
 {
     vlc_fourcc_t i_id;
     uint32_t     i_flags;
-    uint32_t     i_pos;
+    off_t        i_pos;
     uint32_t     i_length;
     uint32_t     i_lengthtotal;
 
@@ -76,6 +76,8 @@ struct demux_sys_t
     vlc_bool_t  b_seekable;
     avi_chunk_t ck_root;
 
+    vlc_bool_t  b_odml;
+
     off_t   i_movi_begin;
     off_t   i_movi_lastchunk_pos; /* XXX position of last valid chunk */
 
index fa2e576..c1a8541 100644 (file)
@@ -2,7 +2,7 @@
  * libavi.c :
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: libavi.c,v 1.17 2003/03/10 01:07:09 fenrir Exp $
+ * $Id: libavi.c,v 1.18 2003/04/27 11:55:03 fenrir Exp $
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  *
  * This program is free software; you can redistribute it and/or modify
 #include "libavi.h"
 
 #define AVI_DEBUG 1
-#define AVIFOURCC_PRINT( x ) \
-    (x)&0xff,           \
-    ( (x) >>  8 )&0xff, \
-    ( (x) >> 16 )&0xff, \
-    ( (x) >> 24 )&0xff
 
 #define FREE( p ) \
     if( p ) {free( p ); p = NULL; }
@@ -53,6 +48,15 @@ static uint32_t GetDWLE( uint8_t *p_buff )
     return (uint32_t)p_buff[0] | ( ((uint32_t)p_buff[1]) << 8 ) |
             ( ((uint32_t)p_buff[2]) << 16 ) | ( ((uint32_t)p_buff[3]) << 24 );
 }
+
+static uint64_t GetQWLE( uint8_t *p )
+{
+    return    (uint64_t)p[0]          | ( ((uint64_t)p[1]) << 8  ) |
+           ( ((uint64_t)p[2]) << 16 ) | ( ((uint64_t)p[3]) << 24 ) |
+           ( ((uint64_t)p[4]) << 32 ) | ( ((uint64_t)p[5]) << 40 ) |
+           ( ((uint64_t)p[6]) << 48 ) | ( ((uint64_t)p[7]) << 56 );
+}
+
 static vlc_fourcc_t GetFOURCC( byte_t *p_buff )
 {
     return VLC_FOURCC( p_buff[0], p_buff[1], p_buff[2], p_buff[3] );
@@ -261,9 +265,9 @@ static int AVI_ChunkReadCommon( input_thread_t *p_input,
     p_chk->common.p_next = NULL;
 #ifdef AVI_DEBUG
     msg_Dbg( p_input, 
-             "Found Chunk fourcc:%8.8x (%c%c%c%c) size:"I64Fd" pos:"I64Fd,
+             "Found Chunk fourcc:%8.8x (%4.4s) size:"I64Fd" pos:"I64Fd,
              p_chk->common.i_chunk_fourcc,
-             AVIFOURCC_PRINT( p_chk->common.i_chunk_fourcc ),
+             (char*)&p_chk->common.i_chunk_fourcc,
              p_chk->common.i_chunk_size,
              p_chk->common.i_chunk_pos );
 #endif
@@ -355,10 +359,10 @@ static int AVI_ChunkRead_list( input_thread_t *p_input,
     }
 #ifdef AVI_DEBUG
     msg_Dbg( p_input, 
-             "found LIST chunk: \'%c%c%c%c\'",
-             AVIFOURCC_PRINT( p_container->list.i_type ) );
+             "found LIST chunk: \'%4.4s\'",
+             (char*)&p_container->list.i_type );
 #endif
-    msg_Dbg( p_input, "<list \'%c%c%c%c\'>", AVIFOURCC_PRINT( p_container->list.i_type ) );
+    msg_Dbg( p_input, "<list \'%4.4s\'>", (char*)&p_container->list.i_type );
     for( ; ; )
     {
         p_chk = malloc( sizeof( avi_chunk_t ) );
@@ -388,7 +392,7 @@ static int AVI_ChunkRead_list( input_thread_t *p_input,
         }
 
     }
-    msg_Dbg( p_input, "</list \'%c%c%c%c\'>", AVIFOURCC_PRINT( p_container->list.i_type ) );
+    msg_Dbg( p_input, "</list \'%4.4s\'>", (char*)&p_container->list.i_type );
 
     return VLC_SUCCESS;
 }
@@ -411,6 +415,12 @@ static int AVI_ChunkRead_list( input_thread_t *p_input,
         msg_Warn( p_input, "not enough data" ); \
     } \
     return code
+
+#define AVI_READ1BYTE( i_byte ) \
+    i_byte = *p_read; \
+    p_read++; \
+    i_read--
+
 #define AVI_READ2BYTES( i_word ) \
     i_word = GetWLE( p_read ); \
     p_read += 2; \
@@ -421,6 +431,11 @@ static int AVI_ChunkRead_list( input_thread_t *p_input,
     p_read += 4; \
     i_read -= 4
 
+#define AVI_READ8BYTES( i_dword ) \
+    i_dword = GetQWLE( p_read ); \
+    p_read += 8; \
+    i_read -= 8
+
 #define AVI_READFOURCC( i_dword ) \
     i_dword = GetFOURCC( p_read ); \
     p_read += 4; \
@@ -479,8 +494,8 @@ static int AVI_ChunkRead_strh( input_thread_t *p_input,
     AVI_READ4BYTES( p_chk->strh.i_samplesize );
 #ifdef AVI_DEBUG
     msg_Dbg( p_input, 
-             "strh: type:%c%c%c%c handler:0x%8.8x samplesize:%d %.2ffps",
-             AVIFOURCC_PRINT( p_chk->strh.i_type ),
+             "strh: type:%4.4s handler:0x%8.8x samplesize:%d %.2ffps",
+             (char*)&p_chk->strh.i_type,
              p_chk->strh.i_handler,
              p_chk->strh.i_samplesize,
              ( p_chk->strh.i_scale ? 
@@ -580,8 +595,8 @@ static int AVI_ChunkRead_strf( input_thread_t *p_input,
             }
 #ifdef AVI_DEBUG
             msg_Dbg( p_input,
-                     "strf: video:%c%c%c%c %dx%d planes:%d %dbpp",
-                     AVIFOURCC_PRINT( p_chk->strf.vids.p_bih->biCompression ),
+                     "strf: video:%4.4s %dx%d planes:%d %dbpp",
+                     (char*)&p_chk->strf.vids.p_bih->biCompression,
                      p_chk->strf.vids.p_bih->biWidth,
                      p_chk->strf.vids.p_bih->biHeight,
                      p_chk->strf.vids.p_bih->biPlanes,
@@ -632,7 +647,7 @@ static int AVI_ChunkRead_idx1( input_thread_t *p_input,
 
     AVI_READCHUNK_ENTER;
 
-    i_count = __MIN( p_chk->common.i_chunk_size, i_read ) / 16;
+    i_count = __MIN( (int64_t)p_chk->common.i_chunk_size, i_read ) / 16;
 
     p_chk->idx1.i_entry_count = i_count;
     p_chk->idx1.i_entry_max   = i_count;
@@ -666,7 +681,99 @@ static void AVI_ChunkFree_idx1( input_thread_t *p_input,
     FREE( p_chk->idx1.entry )
 }
 
-static struct 
+
+
+static int AVI_ChunkRead_indx( input_thread_t *p_input,
+                               avi_chunk_t *p_chk,
+                               vlc_bool_t b_seekable )
+{
+    unsigned int i_count, i;
+    int32_t      i_dummy;
+    avi_chunk_indx_t *p_indx = (avi_chunk_indx_t*)p_chk;
+
+    AVI_READCHUNK_ENTER;
+
+    AVI_READ2BYTES( p_indx->i_longsperentry );
+    AVI_READ1BYTE ( p_indx->i_indexsubtype );
+    AVI_READ1BYTE ( p_indx->i_indextype );
+    AVI_READ4BYTES( p_indx->i_entriesinuse );
+
+    AVI_READ4BYTES( p_indx->i_id );
+    p_indx->idx.std     = NULL;
+    p_indx->idx.field   = NULL;
+    p_indx->idx.super   = NULL;
+
+    if( p_indx->i_indextype == AVI_INDEX_OF_CHUNKS && p_indx->i_indexsubtype == 0 )
+    {
+        AVI_READ8BYTES( p_indx->i_baseoffset );
+        AVI_READ4BYTES( i_dummy );
+
+        i_count = __MIN( p_indx->i_entriesinuse, i_read / 8 );
+        p_indx->i_entriesinuse = i_count;
+        p_indx->idx.std = calloc( sizeof( indx_std_entry_t ), i_count );
+
+        for( i = 0; i < i_count; i++ )
+        {
+            AVI_READ4BYTES( p_indx->idx.std[i].i_offset );
+            AVI_READ4BYTES( p_indx->idx.std[i].i_size );
+        }
+    }
+    else if( p_indx->i_indextype == AVI_INDEX_OF_CHUNKS && p_indx->i_indexsubtype == AVI_INDEX_2FIELD )
+    {
+        AVI_READ8BYTES( p_indx->i_baseoffset );
+        AVI_READ4BYTES( i_dummy );
+
+        i_count = __MIN( p_indx->i_entriesinuse, i_read / 12 );
+        p_indx->i_entriesinuse = i_count;
+        p_indx->idx.field = calloc( sizeof( indx_field_entry_t ), i_count );
+        for( i = 0; i < i_count; i++ )
+        {
+            AVI_READ4BYTES( p_indx->idx.field[i].i_offset );
+            AVI_READ4BYTES( p_indx->idx.field[i].i_size );
+            AVI_READ4BYTES( p_indx->idx.field[i].i_offsetfield2 );
+        }
+    }
+    else if( p_indx->i_indextype == AVI_INDEX_OF_INDEXES )
+    {
+        p_indx->i_baseoffset = 0;
+        AVI_READ4BYTES( i_dummy );
+        AVI_READ4BYTES( i_dummy );
+        AVI_READ4BYTES( i_dummy );
+
+        i_count = __MIN( p_indx->i_entriesinuse, i_read / 16 );
+        p_indx->i_entriesinuse = i_count;
+        p_indx->idx.super = calloc( sizeof( indx_super_entry_t ), i_count );
+
+        for( i = 0; i < i_count; i++ )
+        {
+            AVI_READ8BYTES( p_indx->idx.super[i].i_offset );
+            AVI_READ4BYTES( p_indx->idx.super[i].i_size );
+            AVI_READ4BYTES( p_indx->idx.super[i].i_duration );
+        }
+    }
+    else
+    {
+        msg_Warn( p_input, "unknow type/subtype index" );
+    }
+
+#ifdef AVI_DEBUG
+    msg_Dbg( p_input, "indx: type=%d subtype=%d entry=%d", p_indx->i_indextype, p_indx->i_indexsubtype, p_indx->i_entriesinuse );
+#endif
+    AVI_READCHUNK_EXIT( VLC_SUCCESS );
+}
+static void AVI_ChunkFree_indx( input_thread_t *p_input,
+                               avi_chunk_t *p_chk )
+{
+    avi_chunk_indx_t *p_indx = (avi_chunk_indx_t*)p_chk;
+
+    FREE( p_indx->idx.std );
+    FREE( p_indx->idx.field );
+    FREE( p_indx->idx.super );
+}
+
+
+
+static struct
 {
     vlc_fourcc_t i_fourcc;
     char *psz_type;
@@ -725,8 +832,8 @@ static int AVI_ChunkRead_strz( input_thread_t *p_input,
     p_strz->p_str[i_read] = 0;
 
 #ifdef AVI_DEBUG
-    msg_Dbg( p_input, "%c%c%c%c: %s : %s", 
-             AVIFOURCC_PRINT( p_strz->i_chunk_fourcc), p_strz->p_type, p_strz->p_str);
+    msg_Dbg( p_input, "%4.4s: %s : %s", 
+             (char*)&p_strz->i_chunk_fourcc, p_strz->p_type, p_strz->p_str);
 #endif
     AVI_READCHUNK_EXIT( VLC_SUCCESS );
 }
@@ -767,6 +874,7 @@ static struct
     { AVIFOURCC_strf, AVI_ChunkRead_strf, AVI_ChunkFree_strf },
     { AVIFOURCC_strd, AVI_ChunkRead_strd, AVI_ChunkFree_nothing },
     { AVIFOURCC_idx1, AVI_ChunkRead_idx1, AVI_ChunkFree_idx1 },
+    { AVIFOURCC_indx, AVI_ChunkRead_indx, AVI_ChunkFree_indx },
     { AVIFOURCC_JUNK, AVI_ChunkRead_nothing, AVI_ChunkFree_nothing },
 
     { AVIFOURCC_IARL, AVI_ChunkRead_strz, AVI_ChunkFree_strz },
@@ -841,7 +949,12 @@ int  _AVI_ChunkRead( input_thread_t *p_input,
         return AVI_Chunk_Function[i_index].
                         AVI_ChunkRead_function( p_input, p_chk, b_seekable );
     }
-
+    else if( ((char*)&p_chk->common.i_chunk_fourcc)[0] == 'i' &&
+             ((char*)&p_chk->common.i_chunk_fourcc)[1] == 'x' )
+    {
+        p_chk->common.i_chunk_fourcc = AVIFOURCC_indx;
+        return AVI_ChunkRead_indx( p_input, p_chk, b_seekable );
+    }
     msg_Warn( p_input, "unknown chunk (not loaded)" );
     return AVI_NextChunk( p_input, p_chk );
 }
@@ -871,8 +984,8 @@ void _AVI_ChunkFree( input_thread_t *p_input,
     if( AVI_Chunk_Function[i_index].AVI_ChunkFree_function )
     {
 #ifdef AVI_DEBUG
-        msg_Dbg( p_input, "free chunk %c%c%c%c", 
-                 AVIFOURCC_PRINT( p_chk->common.i_chunk_fourcc ) );
+        msg_Dbg( p_input, "free chunk %4.4s", 
+                 (char*)&p_chk->common.i_chunk_fourcc );
 #endif
         AVI_Chunk_Function[i_index].AVI_ChunkFree_function( p_input, p_chk);
     }
@@ -1012,18 +1125,18 @@ static void AVI_ChunkDumpDebug_level( input_thread_t *p_input,
         p_chk->common.i_chunk_fourcc == AVIFOURCC_LIST )
     {
         sprintf( str + i_level * 5, 
-                 "%c %c%c%c%c-%c%c%c%c size:"I64Fu" pos:"I64Fu,
+                 "%c %4.4s-%4.4s size:"I64Fu" pos:"I64Fu,
                  i_level ? '+' : '*',
-                 AVIFOURCC_PRINT( p_chk->common.i_chunk_fourcc ),
-                 AVIFOURCC_PRINT( p_chk->list.i_type ),
+                 (char*)&p_chk->common.i_chunk_fourcc,
+                 (char*)&p_chk->list.i_type,
                  p_chk->common.i_chunk_size,
                  p_chk->common.i_chunk_pos );
     }
     else
     {
         sprintf( str + i_level * 5, 
-                 "+ %c%c%c%c size:"I64Fu" pos:"I64Fu,
-                 AVIFOURCC_PRINT( p_chk->common.i_chunk_fourcc ),
+                 "+ %4.4s size:"I64Fu" pos:"I64Fu,
+                 (char*)&p_chk->common.i_chunk_fourcc,
                  p_chk->common.i_chunk_size,
                  p_chk->common.i_chunk_pos );
     }
index c45bfb4..e77819b 100644 (file)
@@ -2,7 +2,7 @@
  * libavi.h : LibAVI library 
  ******************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: libavi.h,v 1.8 2003/03/13 16:09:20 hartman Exp $
+ * $Id: libavi.h,v 1.9 2003/04/27 11:55:03 fenrir Exp $
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  * 
  * This program is free software; you can redistribute it and/or modify
@@ -46,6 +46,7 @@
 #define AVIFOURCC_LIST         VLC_FOURCC('L','I','S','T')
 #define AVIFOURCC_JUNK         VLC_FOURCC('J','U','N','K')
 #define AVIFOURCC_AVI          VLC_FOURCC('A','V','I',' ')
+#define AVIFOURCC_AVIX         VLC_FOURCC('A','V','I','X')
 #define AVIFOURCC_WAVE         VLC_FOURCC('W','A','V','E')
 #define AVIFOURCC_INFO         VLC_FOURCC('I','N','F','O')
 
@@ -58,6 +59,7 @@
 #define AVIFOURCC_strh         VLC_FOURCC('s','t','r','h')
 #define AVIFOURCC_strf         VLC_FOURCC('s','t','r','f')
 #define AVIFOURCC_strd         VLC_FOURCC('s','t','r','d')
+#define AVIFOURCC_indx         VLC_FOURCC('i','n','d','x')
 
 #define AVIFOURCC_rec          VLC_FOURCC('r','e','c',' ')
 #define AVIFOURCC_auds         VLC_FOURCC('a','u','d','s')
@@ -273,6 +275,51 @@ typedef struct avi_chunk_strd_s
     uint8_t  *p_data;
 } avi_chunk_strd_t;
 
+
+#define AVI_INDEX_OF_INDEXES    0x00
+#define AVI_INDEX_OF_CHUNKS     0x01
+#define AVI_INDEX_IS_DATA       0x80
+
+#define AVI_INDEX_2FIELD        0x01
+typedef struct
+{
+    uint32_t i_offset;
+    uint32_t i_size;
+} indx_std_entry_t;
+
+typedef struct
+{
+    uint32_t i_offset;
+    uint32_t i_size;
+    uint32_t i_offsetfield2;
+} indx_field_entry_t;
+
+typedef struct
+{
+    uint64_t i_offset;
+    uint32_t i_size;
+    uint32_t i_duration;
+} indx_super_entry_t;
+
+typedef struct avi_chunk_indx_s
+{
+    AVI_CHUNK_COMMON
+    int16_t i_longsperentry;
+    int8_t  i_indexsubtype;
+    int8_t  i_indextype;
+    int32_t i_entriesinuse;
+    vlc_fourcc_t i_id;
+
+    int64_t i_baseoffset;
+
+    union
+    {
+        indx_std_entry_t    *std;
+        indx_field_entry_t  *field;
+        indx_super_entry_t  *super;
+    } idx;
+} avi_chunk_indx_t;
+
 typedef struct avi_chunk_STRING_s
 {
     AVI_CHUNK_COMMON
@@ -289,6 +336,7 @@ typedef union avi_chunk_u
     avi_chunk_strh_t    strh;
     avi_chunk_strf_t    strf;
     avi_chunk_strd_t    strd;
+    avi_chunk_indx_t    indx;
     avi_chunk_STRING_t  strz;
 } avi_chunk_t;