Commit e4ef10de authored by Laurent Aimar's avatar Laurent Aimar

* avi: Support for OpenDML file.

 Not tested with file size > 2Go, so report status.
parent 020af3bf
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* avi.c : AVI file Stream input module for vlc * avi.c : AVI file Stream input module for vlc
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * 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> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* *
* This program is free software; you can redistribute it and/or modify * 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 ) ...@@ -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_fourcc = GetFOURCC( p_peek );
p_pk->i_size = GetDWLE( p_peek + 4 ); p_pk->i_size = GetDWLE( p_peek + 4 );
p_pk->i_pos = AVI_TellAbsolute( p_input ); 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 ); p_pk->i_type = GetFOURCC( p_peek + 8 );
} }
...@@ -357,10 +357,15 @@ static int AVI_PacketNext( input_thread_t *p_input ) ...@@ -357,10 +357,15 @@ static int AVI_PacketNext( input_thread_t *p_input )
{ {
return VLC_EGENERIC; return VLC_EGENERIC;
} }
if( avi_ck.i_fourcc == AVIFOURCC_LIST && avi_ck.i_type == AVIFOURCC_rec ) if( avi_ck.i_fourcc == AVIFOURCC_LIST && avi_ck.i_type == AVIFOURCC_rec )
{ {
return AVI_SkipBytes( p_input, 12 ); 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 else
{ {
return AVI_SkipBytes( p_input, __EVEN( avi_ck.i_size ) + 8 ); return AVI_SkipBytes( p_input, __EVEN( avi_ck.i_size ) + 8 );
...@@ -413,6 +418,7 @@ static int AVI_PacketSearch( input_thread_t *p_input ) ...@@ -413,6 +418,7 @@ static int AVI_PacketSearch( input_thread_t *p_input )
{ {
case AVIFOURCC_JUNK: case AVIFOURCC_JUNK:
case AVIFOURCC_LIST: case AVIFOURCC_LIST:
case AVIFOURCC_RIFF:
case AVIFOURCC_idx1: case AVIFOURCC_idx1:
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -472,7 +478,7 @@ static void AVI_IndexAddEntry( demux_sys_t *p_avi, ...@@ -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; demux_sys_t *p_avi = p_input->p_demux_data;
...@@ -495,12 +501,7 @@ static void AVI_IndexLoad( input_thread_t *p_input ) ...@@ -495,12 +501,7 @@ static void AVI_IndexLoad( input_thread_t *p_input )
msg_Warn( p_input, "cannot find idx1 chunk, no index defined" ); msg_Warn( p_input, "cannot find idx1 chunk, no index defined" );
return; 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 *** */ /* *** calculate offset *** */
if( p_idx1->i_entry_count > 0 && if( p_idx1->i_entry_count > 0 &&
p_idx1->entry[0].i_pos < p_movi->i_chunk_pos ) p_idx1->entry[0].i_pos < p_movi->i_chunk_pos )
...@@ -531,16 +532,129 @@ static void AVI_IndexLoad( input_thread_t *p_input ) ...@@ -531,16 +532,129 @@ static void AVI_IndexLoad( input_thread_t *p_input )
AVI_IndexAddEntry( p_avi, i_stream, &index ); 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++ ) for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
{ {
msg_Dbg( p_input, msg_Dbg( p_input,
"stream[%d] creating %d index entries", "stream[%d] created %d index entries",
i_stream, i_stream,
p_avi->pp_info[i_stream]->i_idxnb ); p_avi->pp_info[i_stream]->i_idxnb );
} }
} }
static void AVI_IndexCreate( input_thread_t *p_input ) static void AVI_IndexCreate( input_thread_t *p_input )
{ {
demux_sys_t *p_avi = p_input->p_demux_data; demux_sys_t *p_avi = p_input->p_demux_data;
...@@ -596,7 +710,22 @@ static void AVI_IndexCreate( input_thread_t *p_input ) ...@@ -596,7 +710,22 @@ static void AVI_IndexCreate( input_thread_t *p_input )
switch( pk.i_fourcc ) switch( pk.i_fourcc )
{ {
case AVIFOURCC_idx1: 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; goto print_stat;
case AVIFOURCC_RIFF:
msg_Dbg( p_input, "new RIFF chunk found" );
case AVIFOURCC_rec: case AVIFOURCC_rec:
case AVIFOURCC_JUNK: case AVIFOURCC_JUNK:
break; break;
...@@ -609,7 +738,8 @@ static void AVI_IndexCreate( input_thread_t *p_input ) ...@@ -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 ) ) AVI_PacketNext( p_input ) )
{ {
break; break;
...@@ -844,6 +974,7 @@ static int AVIInit( vlc_object_t * p_this ) ...@@ -844,6 +974,7 @@ static int AVIInit( vlc_object_t * p_this )
p_avi->b_seekable = ( ( p_input->stream.b_seekable ) p_avi->b_seekable = ( ( p_input->stream.b_seekable )
&&( p_input->stream.i_method == INPUT_METHOD_FILE ) ); &&( p_input->stream.i_method == INPUT_METHOD_FILE ) );
p_avi->i_movi_lastchunk_pos = 0; p_avi->i_movi_lastchunk_pos = 0;
p_avi->b_odml = VLC_FALSE;
/* *** for unseekable stream, automaticaly use AVIDemux_interleaved *** */ /* *** for unseekable stream, automaticaly use AVIDemux_interleaved *** */
if( !p_avi->b_seekable || config_GetInt( p_input, "avi-interleaved" ) ) if( !p_avi->b_seekable || config_GetInt( p_input, "avi-interleaved" ) )
...@@ -858,6 +989,29 @@ static int AVIInit( vlc_object_t * p_this ) ...@@ -858,6 +989,29 @@ static int AVIInit( vlc_object_t * p_this )
} }
AVI_ChunkDumpDebug( p_input, &p_avi->ck_root ); 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, p_riff = (avi_chunk_list_t*)AVI_ChunkFind( &p_avi->ck_root,
AVIFOURCC_RIFF, 0 ); AVIFOURCC_RIFF, 0 );
...@@ -1331,6 +1485,59 @@ static mtime_t AVI_GetPTS( avi_stream_t *p_info ) ...@@ -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, static int AVI_StreamChunkFind( input_thread_t *p_input,
unsigned int i_stream ) unsigned int i_stream )
{ {
...@@ -1363,17 +1570,9 @@ static int AVI_StreamChunkFind( input_thread_t *p_input, ...@@ -1363,17 +1570,9 @@ static int AVI_StreamChunkFind( input_thread_t *p_input,
if( avi_pk.i_stream >= p_avi->i_streams || if( avi_pk.i_stream >= p_avi->i_streams ||
( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) ) ( 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: return VLC_EGENERIC;
AVI_SkipBytes( p_input, 12 );
break;
default:
if( AVI_PacketNext( p_input ) )
{
return VLC_EGENERIC;
}
break;
} }
} }
else else
...@@ -1585,7 +1784,7 @@ static int AVISeek ( input_thread_t *p_input, ...@@ -1585,7 +1784,7 @@ static int AVISeek ( input_thread_t *p_input,
if( !p_avi->i_length ) if( !p_avi->i_length )
{ {
avi_stream_t *p_stream; avi_stream_t *p_stream;
uint64_t i_pos; int64_t i_pos;
/* use i_percent to create a true i_date */ /* use i_percent to create a true i_date */
msg_Warn( p_input, msg_Warn( p_input,
...@@ -2068,6 +2267,14 @@ static int AVIDemux_Seekable( input_thread_t *p_input ) ...@@ -2068,6 +2267,14 @@ static int AVIDemux_Seekable( input_thread_t *p_input )
p_pes->i_pts = AVI_GetPTS( p_stream ); 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 */ /* read data */
if( p_stream->i_samplesize ) if( p_stream->i_samplesize )
{ {
...@@ -2199,8 +2406,13 @@ static int AVIDemux_UnSeekable( input_thread_t *p_input ) ...@@ -2199,8 +2406,13 @@ static int AVIDemux_UnSeekable( input_thread_t *p_input )
{ {
case AVIFOURCC_JUNK: case AVIFOURCC_JUNK:
case AVIFOURCC_LIST: case AVIFOURCC_LIST:
case AVIFOURCC_RIFF:
return( !AVI_PacketNext( p_input ) ? 1 : 0 ); return( !AVI_PacketNext( p_input ) ? 1 : 0 );
case AVIFOURCC_idx1: case AVIFOURCC_idx1:
if( p_avi->b_odml )
{
return( !AVI_PacketNext( p_input ) ? 1 : 0 );
}
return( 0 ); // eof return( 0 ); // eof
default: default:
msg_Warn( p_input, msg_Warn( p_input,
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* avi.h : AVI file Stream input module for vlc * avi.h : AVI file Stream input module for vlc
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * 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> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -38,7 +38,7 @@ typedef struct AVIIndexEntry_s ...@@ -38,7 +38,7 @@ typedef struct AVIIndexEntry_s
{ {
vlc_fourcc_t i_id; vlc_fourcc_t i_id;
uint32_t i_flags; uint32_t i_flags;
uint32_t i_pos; off_t i_pos;
uint32_t i_length; uint32_t i_length;
uint32_t i_lengthtotal; uint32_t i_lengthtotal;
...@@ -76,6 +76,8 @@ struct demux_sys_t ...@@ -76,6 +76,8 @@ struct demux_sys_t
vlc_bool_t b_seekable; vlc_bool_t b_seekable;
avi_chunk_t ck_root; avi_chunk_t ck_root;
vlc_bool_t b_odml;
off_t i_movi_begin; off_t i_movi_begin;
off_t i_movi_lastchunk_pos; /* XXX position of last valid chunk */ off_t i_movi_lastchunk_pos; /* XXX position of last valid chunk */
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* libavi.c : * libavi.c :
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * 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> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -31,11 +31,6 @@ ...@@ -31,11 +31,6 @@
#include "libavi.h" #include "libavi.h"
#define AVI_DEBUG 1 #define AVI_DEBUG 1
#define AVIFOURCC_PRINT( x ) \
(x)&0xff, \
( (x) >> 8 )&0xff, \
( (x) >> 16 )&0xff, \
( (x) >> 24 )&0xff
#define FREE( p ) \ #define FREE( p ) \
if( p ) {free( p ); p = NULL; } if( p ) {free( p ); p = NULL; }
...@@ -53,6 +48,15 @@ static uint32_t GetDWLE( uint8_t *p_buff ) ...@@ -53,6 +48,15 @@ static uint32_t GetDWLE( uint8_t *p_buff )
return (uint32_t)p_buff[0] | ( ((uint32_t)p_buff[1]) << 8 ) | return (uint32_t)p_buff[0] | ( ((uint32_t)p_buff[1]) << 8 ) |
( ((uint32_t)p_buff[2]) << 16 ) | ( ((uint32_t)p_buff[3]) << 24 ); ( ((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 ) static vlc_fourcc_t GetFOURCC( byte_t *p_buff )
{ {
return VLC_FOURCC( p_buff[0], p_buff[1], p_buff[2], p_buff[3] ); 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, ...@@ -261,9 +265,9 @@ static int AVI_ChunkReadCommon( input_thread_t *p_input,
p_chk->common.p_next = NULL; p_chk->common.p_next = NULL;
#ifdef AVI_DEBUG #ifdef AVI_DEBUG
msg_Dbg( p_input, 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, 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_size,
p_chk->common.i_chunk_pos ); p_chk->common.i_chunk_pos );
#endif #endif
...@@ -355,10 +359,10 @@ static int AVI_ChunkRead_list( input_thread_t *p_input, ...@@ -355,10 +359,10 @@ static int AVI_ChunkRead_list( input_thread_t *p_input,
} }
#ifdef AVI_DEBUG #ifdef AVI_DEBUG
msg_Dbg( p_input, msg_Dbg( p_input,
"found LIST chunk: \'%c%c%c%c\'", "found LIST chunk: \'%4.4s\'",
AVIFOURCC_PRINT( p_container->list.i_type ) ); (char*)&p_container->list.i_type );
#endif #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( ; ; ) for( ; ; )
{ {
p_chk = malloc( sizeof( avi_chunk_t ) ); p_chk = malloc( sizeof( avi_chunk_t ) );
...@@ -388,7 +392,7 @@ static int AVI_ChunkRead_list( input_thread_t *p_input, ...@@ -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; return VLC_SUCCESS;
} }
...@@ -411,6 +415,12 @@ static int AVI_ChunkRead_list( input_thread_t *p_input, ...@@ -411,6 +415,12 @@ static int AVI_ChunkRead_list( input_thread_t *p_input,
msg_Warn( p_input, "not enough data" ); \ msg_Warn( p_input, "not enough data" ); \
} \ } \
return code return code
#define AVI_READ1BYTE( i_byte ) \
i_byte = *p_read; \
p_read++; \
i_read--
#define AVI_READ2BYTES( i_word ) \ #define AVI_READ2BYTES( i_word ) \
i_word = GetWLE( p_read ); \ i_word = GetWLE( p_read ); \
p_read += 2; \ p_read += 2; \
...@@ -421,6 +431,11 @@ static int AVI_ChunkRead_list( input_thread_t *p_input, ...@@ -421,6 +431,11 @@ static int AVI_ChunkRead_list( input_thread_t *p_input,
p_read += 4; \ p_read += 4; \
i_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 ) \ #define AVI_READFOURCC( i_dword ) \
i_dword = GetFOURCC( p_read ); \ i_dword = GetFOURCC( p_read ); \
p_read += 4; \ p_read += 4; \
...@@ -479,8 +494,8 @@ static int AVI_ChunkRead_strh( input_thread_t *p_input, ...@@ -479,8 +494,8 @@ static int AVI_ChunkRead_strh( input_thread_t *p_input,
AVI_READ4BYTES( p_chk->strh.i_samplesize ); AVI_READ4BYTES( p_chk->strh.i_samplesize );
#ifdef AVI_DEBUG #ifdef AVI_DEBUG
msg_Dbg( p_input, msg_Dbg( p_input,
"strh: type:%c%c%c%c handler:0x%8.8x samplesize:%d %.2ffps", "strh: type:%4.4s handler:0x%8.8x samplesize:%d %.2ffps",
AVIFOURCC_PRINT( p_chk->strh.i_type ), (char*)&p_chk->strh.i_type,
p_chk->strh.i_handler, p_chk->strh.i_handler,
p_chk->strh.i_samplesize, p_chk->strh.i_samplesize,
( p_chk->strh.i_scale ? ( p_chk->strh.i_scale ?
...@@ -580,8 +595,8 @@ static int AVI_ChunkRead_strf( input_thread_t *p_input, ...@@ -580,8 +595,8 @@ static int AVI_ChunkRead_strf( input_thread_t *p_input,
} }
#ifdef AVI_DEBUG #ifdef AVI_DEBUG
msg_Dbg( p_input, msg_Dbg( p_input,
"strf: video:%c%c%c%c %dx%d planes:%d %dbpp", "strf: video:%4.4s %dx%d planes:%d %dbpp",
AVIFOURCC_PRINT( p_chk->strf.vids.p_bih->biCompression ), (char*)&p_chk->strf.vids.p_bih->biCompression,
p_chk->strf.vids.p_bih->biWidth, p_chk->strf.vids.p_bih->biWidth,
p_chk->strf.vids.p_bih->biHeight, p_chk->strf.vids.p_bih->biHeight,
p_chk->strf.vids.p_bih->biPlanes, p_chk->strf.vids.p_bih->biPlanes,
...@@ -632,7 +647,7 @@ static int AVI_ChunkRead_idx1( input_thread_t *p_input, ...@@ -632,7 +647,7 @@ static int AVI_ChunkRead_idx1( input_thread_t *p_input,
AVI_READCHUNK_ENTER; 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_count = i_count;
p_chk->idx1.i_entry_max = i_count; p_chk->idx1.i_entry_max = i_count;
...@@ -666,7 +681,99 @@ static void AVI_ChunkFree_idx1( input_thread_t *p_input, ...@@ -666,7 +681,99 @@ static void AVI_ChunkFree_idx1( input_thread_t *p_input,
FREE( p_chk->idx1.entry ) 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; vlc_fourcc_t i_fourcc;
char *psz_type; char *psz_type;
...@@ -725,8 +832,8 @@ static int AVI_ChunkRead_strz( input_thread_t *p_input, ...@@ -725,8 +832,8 @@ static int AVI_ChunkRead_strz( input_thread_t *p_input,
p_strz->p_str[i_read] = 0; p_strz->p_str[i_read] = 0;
#ifdef AVI_DEBUG #ifdef AVI_DEBUG
msg_Dbg( p_input, "%c%c%c%c: %s : %s", msg_Dbg( p_input, "%4.4s: %s : %s",
AVIFOURCC_PRINT( p_strz->i_chunk_fourcc), p_strz->p_type, p_strz->p_str); (char*)&p_strz->i_chunk_fourcc, p_strz->p_type, p_strz->p_str);
#endif #endif
AVI_READCHUNK_EXIT( VLC_SUCCESS ); AVI_READCHUNK_EXIT( VLC_SUCCESS );
} }
...@@ -767,6 +874,7 @@ static struct ...@@ -767,6 +874,7 @@ static struct
{ AVIFOURCC_strf, AVI_ChunkRead_strf, AVI_ChunkFree_strf }, { AVIFOURCC_strf, AVI_ChunkRead_strf, AVI_ChunkFree_strf },
{ AVIFOURCC_strd, AVI_ChunkRead_strd, AVI_ChunkFree_nothing }, { AVIFOURCC_strd, AVI_ChunkRead_strd, AVI_ChunkFree_nothing },
{ AVIFOURCC_idx1, AVI_ChunkRead_idx1, AVI_ChunkFree_idx1 }, { 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_JUNK, AVI_ChunkRead_nothing, AVI_ChunkFree_nothing },
{ AVIFOURCC_IARL, AVI_ChunkRead_strz, AVI_ChunkFree_strz }, { AVIFOURCC_IARL, AVI_ChunkRead_strz, AVI_ChunkFree_strz },
...@@ -841,7 +949,12 @@ int _AVI_ChunkRead( input_thread_t *p_input, ...@@ -841,7 +949,12 @@ int _AVI_ChunkRead( input_thread_t *p_input,
return AVI_Chunk_Function[i_index]. return AVI_Chunk_Function[i_index].
AVI_ChunkRead_function( p_input, p_chk, b_seekable ); 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)" ); msg_Warn( p_input, "unknown chunk (not loaded)" );
return AVI_NextChunk( p_input, p_chk ); return AVI_NextChunk( p_input, p_chk );
} }
...@@ -871,8 +984,8 @@ void _AVI_ChunkFree( input_thread_t *p_input, ...@@ -871,8 +984,8 @@ void _AVI_ChunkFree( input_thread_t *p_input,
if( AVI_Chunk_Function[i_index].AVI_ChunkFree_function ) if( AVI_Chunk_Function[i_index].AVI_ChunkFree_function )
{ {
#ifdef AVI_DEBUG #ifdef AVI_DEBUG
msg_Dbg( p_input, "free chunk %c%c%c%c", msg_Dbg( p_input, "free chunk %4.4s",
AVIFOURCC_PRINT( p_chk->common.i_chunk_fourcc ) ); (char*)&p_chk->common.i_chunk_fourcc );
#endif #endif
AVI_Chunk_Function[i_index].AVI_ChunkFree_function( p_input, p_chk); 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, ...@@ -1012,18 +1125,18 @@ static void AVI_ChunkDumpDebug_level( input_thread_t *p_input,
p_chk->common.i_chunk_fourcc == AVIFOURCC_LIST ) p_chk->common.i_chunk_fourcc == AVIFOURCC_LIST )
{ {
sprintf( str + i_level * 5, 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 ? '+' : '*', i_level ? '+' : '*',
AVIFOURCC_PRINT( p_chk->common.i_chunk_fourcc ), (char*)&p_chk->common.i_chunk_fourcc,
AVIFOURCC_PRINT( p_chk->list.i_type ), (char*)&p_chk->list.i_type,
p_chk->common.i_chunk_size, p_chk->common.i_chunk_size,
p_chk->common.i_chunk_pos ); p_chk->common.i_chunk_pos );
} }
else else
{ {
sprintf( str + i_level * 5, sprintf( str + i_level * 5,
"+ %c%c%c%c size:"I64Fu" pos:"I64Fu, "+ %4.4s size:"I64Fu" pos:"I64Fu,
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_size,
p_chk->common.i_chunk_pos ); p_chk->common.i_chunk_pos );
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* libavi.h : LibAVI library * libavi.h : LibAVI library
****************************************************************************** ******************************************************************************
* Copyright (C) 2001 VideoLAN * 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> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
#define AVIFOURCC_LIST VLC_FOURCC('L','I','S','T') #define AVIFOURCC_LIST VLC_FOURCC('L','I','S','T')
#define AVIFOURCC_JUNK VLC_FOURCC('J','U','N','K') #define AVIFOURCC_JUNK VLC_FOURCC('J','U','N','K')
#define AVIFOURCC_AVI VLC_FOURCC('A','V','I',' ') #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_WAVE VLC_FOURCC('W','A','V','E')
#define AVIFOURCC_INFO VLC_FOURCC('I','N','F','O') #define AVIFOURCC_INFO VLC_FOURCC('I','N','F','O')
...@@ -58,6 +59,7 @@ ...@@ -58,6 +59,7 @@
#define AVIFOURCC_strh VLC_FOURCC('s','t','r','h') #define AVIFOURCC_strh VLC_FOURCC('s','t','r','h')
#define AVIFOURCC_strf VLC_FOURCC('s','t','r','f') #define AVIFOURCC_strf VLC_FOURCC('s','t','r','f')
#define AVIFOURCC_strd VLC_FOURCC('s','t','r','d') #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_rec VLC_FOURCC('r','e','c',' ')
#define AVIFOURCC_auds VLC_FOURCC('a','u','d','s') #define AVIFOURCC_auds VLC_FOURCC('a','u','d','s')
...@@ -273,6 +275,51 @@ typedef struct avi_chunk_strd_s ...@@ -273,6 +275,51 @@ typedef struct avi_chunk_strd_s
uint8_t *p_data; uint8_t *p_data;
} avi_chunk_strd_t; } 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 typedef struct avi_chunk_STRING_s
{ {
AVI_CHUNK_COMMON AVI_CHUNK_COMMON
...@@ -289,6 +336,7 @@ typedef union avi_chunk_u ...@@ -289,6 +336,7 @@ typedef union avi_chunk_u
avi_chunk_strh_t strh; avi_chunk_strh_t strh;
avi_chunk_strf_t strf; avi_chunk_strf_t strf;
avi_chunk_strd_t strd; avi_chunk_strd_t strd;
avi_chunk_indx_t indx;
avi_chunk_STRING_t strz; avi_chunk_STRING_t strz;
} avi_chunk_t; } avi_chunk_t;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment