From e4ef10de4c8599a99dd1fdb479f3040c27cfc6ac Mon Sep 17 00:00:00 2001 From: Laurent Aimar Date: Sun, 27 Apr 2003 11:55:03 +0000 Subject: [PATCH] * avi: Support for OpenDML file. Not tested with file size > 2Go, so report status. --- modules/demux/avi/avi.c | 260 +++++++++++++++++++++++++++++++++---- modules/demux/avi/avi.h | 6 +- modules/demux/avi/libavi.c | 169 ++++++++++++++++++++---- modules/demux/avi/libavi.h | 50 ++++++- 4 files changed, 430 insertions(+), 55 deletions(-) diff --git a/modules/demux/avi/avi.c b/modules/demux/avi/avi.c index d2dee7a17b..99ce734ae7 100644 --- a/modules/demux/avi/avi.c +++ b/modules/demux/avi/avi.c @@ -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 * * 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, diff --git a/modules/demux/avi/avi.h b/modules/demux/avi/avi.h index e60aaf9bec..39e7e57fe2 100644 --- a/modules/demux/avi/avi.h +++ b/modules/demux/avi/avi.h @@ -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 * * 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 */ diff --git a/modules/demux/avi/libavi.c b/modules/demux/avi/libavi.c index fa2e5762f7..c1a8541f35 100644 --- a/modules/demux/avi/libavi.c +++ b/modules/demux/avi/libavi.c @@ -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 * * This program is free software; you can redistribute it and/or modify @@ -31,11 +31,6 @@ #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, "", AVIFOURCC_PRINT( p_container->list.i_type ) ); + msg_Dbg( p_input, "", (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, "", AVIFOURCC_PRINT( p_container->list.i_type ) ); + msg_Dbg( p_input, "", (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 ); } diff --git a/modules/demux/avi/libavi.h b/modules/demux/avi/libavi.h index c45bfb4d06..e77819bdab 100644 --- a/modules/demux/avi/libavi.h +++ b/modules/demux/avi/libavi.h @@ -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 * * 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; -- 2.39.5