Commit 9295116d authored by Laurent Aimar's avatar Laurent Aimar

* all : begin to rewrite some parts of avi demux, mainly to clean ugly code

and to prepare for OpenDML support.
Add new options :
  --avi-index force index creation.
  --avi-interleaved force method used for unseekable stream but need
interleaved stream and could lead to loss of audio/video synchro.
parent 28b43ac2
SOURCES_avi = \ SOURCES_avi = \
modules/demux/avi/avi.c \ modules/demux/avi/avi.c \
modules/demux/avi/libioRIFF.c modules/demux/avi/libioRIFF.c \
modules/demux/avi/libavi.c
noinst_HEADERS += \ noinst_HEADERS += \
modules/demux/avi/avi.h \ modules/demux/avi/avi.h \
modules/demux/avi/libioRIFF.h modules/demux/avi/libioRIFF.h \
modules/demux/avi/libavi.h
This diff is collapsed.
...@@ -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.3 2002/09/18 23:34:28 fenrir Exp $ * $Id: avi.h,v 1.4 2002/10/15 00:55:07 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
...@@ -22,178 +22,6 @@ ...@@ -22,178 +22,6 @@
#define MAX_PACKETS_IN_FIFO 2 #define MAX_PACKETS_IN_FIFO 2
/* flags for use in <dwFlags> in AVIFileHdr */
#define AVIF_HASINDEX 0x00000010 /* Index at end of file? */
#define AVIF_MUSTUSEINDEX 0x00000020
#define AVIF_ISINTERLEAVED 0x00000100
#define AVIF_TRUSTCKTYPE 0x00000800 /* Use CKType to find key frames? */
#define AVIF_WASCAPTUREFILE 0x00010000
#define AVIF_COPYRIGHTED 0x00020000
/* Flags for index */
#define AVIIF_LIST 0x00000001L /* chunk is a 'LIST' */
#define AVIIF_KEYFRAME 0x00000010L /* this frame is a key frame.*/
#define AVIIF_NOTIME 0x00000100L /* this frame doesn't take any time */
#define AVIIF_COMPUSE 0x0FFF0000L /* these bits are for compressor use */
#define AVIIF_FIXKEYFRAME 0x00001000L /* invented; used to say that
the keyframe flag isn't a true flag
but have to be verified */
#define MKTWOCC( a, b ) \
( (u16)(a) | ( (u16)(b) << 8 ) )
/* *** avi stuff *** */
#define AVIFOURCC_RIFF MKFOURCC('R','I','F','F')
#define AVIFOURCC_LIST MKFOURCC('L','I','S','T')
#define AVIFOURCC_JUNK MKFOURCC('J','U','N','K')
#define AVIFOURCC_AVI MKFOURCC('A','V','I',' ')
#define AVIFOURCC_WAVE MKFOURCC('W','A','V','E')
#define AVIFOURCC_avih MKFOURCC('a','v','i','h')
#define AVIFOURCC_hdrl MKFOURCC('h','d','r','l')
#define AVIFOURCC_movi MKFOURCC('m','o','v','i')
#define AVIFOURCC_idx1 MKFOURCC('i','d','x','1')
#define AVIFOURCC_strl MKFOURCC('s','t','r','l')
#define AVIFOURCC_strh MKFOURCC('s','t','r','h')
#define AVIFOURCC_strf MKFOURCC('s','t','r','f')
#define AVIFOURCC_strd MKFOURCC('s','t','r','d')
#define AVIFOURCC_rec MKFOURCC('r','e','c',' ')
#define AVIFOURCC_auds MKFOURCC('a','u','d','s')
#define AVIFOURCC_vids MKFOURCC('v','i','d','s')
#define AVITWOCC_wb MKTWOCC('w','b')
#define AVITWOCC_db MKTWOCC('d','b')
#define AVITWOCC_dc MKTWOCC('d','c')
#define AVITWOCC_pc MKTWOCC('p','c')
/* *** codex stuff *** */
/* MPEG4 video */
#define FOURCC_DIVX VLC_FOURCC('D','I','V','X')
#define FOURCC_divx VLC_FOURCC('d','i','v','x')
#define FOURCC_DIV1 VLC_FOURCC('D','I','V','1')
#define FOURCC_div1 VLC_FOURCC('d','i','v','1')
#define FOURCC_MP4S VLC_FOURCC('M','P','4','S')
#define FOURCC_mp4s VLC_FOURCC('m','p','4','s')
#define FOURCC_M4S2 VLC_FOURCC('M','4','S','2')
#define FOURCC_m4s2 VLC_FOURCC('m','4','s','2')
#define FOURCC_xvid VLC_FOURCC('x','v','i','d')
#define FOURCC_XVID VLC_FOURCC('X','V','I','D')
#define FOURCC_XviD VLC_FOURCC('X','v','i','D')
#define FOURCC_DX50 VLC_FOURCC('D','X','5','0')
#define FOURCC_mp4v VLC_FOURCC('m','p','4','v')
#define FOURCC_4 VLC_FOURCC( 4, 0, 0, 0 )
/* MSMPEG4 v2 */
#define FOURCC_MPG4 VLC_FOURCC('M','P','G','4')
#define FOURCC_mpg4 VLC_FOURCC('m','p','g','4')
#define FOURCC_DIV2 VLC_FOURCC('D','I','V','2')
#define FOURCC_div2 VLC_FOURCC('d','i','v','2')
#define FOURCC_MP42 VLC_FOURCC('M','P','4','2')
#define FOURCC_mp42 VLC_FOURCC('m','p','4','2')
/* MSMPEG4 v3 / M$ mpeg4 v3 */
#define FOURCC_MPG3 VLC_FOURCC('M','P','G','3')
#define FOURCC_mpg3 VLC_FOURCC('m','p','g','3')
#define FOURCC_div3 VLC_FOURCC('d','i','v','3')
#define FOURCC_MP43 VLC_FOURCC('M','P','4','3')
#define FOURCC_mp43 VLC_FOURCC('m','p','4','3')
/* DivX 3.20 */
#define FOURCC_DIV3 VLC_FOURCC('D','I','V','3')
#define FOURCC_DIV4 VLC_FOURCC('D','I','V','4')
#define FOURCC_div4 VLC_FOURCC('d','i','v','4')
#define FOURCC_DIV5 VLC_FOURCC('D','I','V','5')
#define FOURCC_div5 VLC_FOURCC('d','i','v','5')
#define FOURCC_DIV6 VLC_FOURCC('D','I','V','6')
#define FOURCC_div6 VLC_FOURCC('d','i','v','6')
/* AngelPotion stuff */
#define FOURCC_AP41 VLC_FOURCC('A','P','4','1')
/* ?? */
#define FOURCC_3IV1 VLC_FOURCC('3','I','V','1')
/* H263 and H263i */
#define FOURCC_H263 VLC_FOURCC('H','2','6','3')
#define FOURCC_h263 VLC_FOURCC('h','2','6','3')
#define FOURCC_U263 VLC_FOURCC('U','2','6','3')
#define FOURCC_I263 VLC_FOURCC('I','2','6','3')
#define FOURCC_i263 VLC_FOURCC('i','2','6','3')
/* Sound formats */
#define WAVE_FORMAT_UNKNOWN 0x0000
#define WAVE_FORMAT_PCM 0x0001
#define WAVE_FORMAT_MPEG 0x0050
#define WAVE_FORMAT_MPEGLAYER3 0x0055
#define WAVE_FORMAT_A52 0x2000
typedef struct bitmapinfoheader_s
{
u32 i_size; /* size of header */
u32 i_width;
u32 i_height;
u16 i_planes;
u16 i_bitcount;
u32 i_compression;
u32 i_sizeimage;
u32 i_xpelspermeter;
u32 i_ypelspermeter;
u32 i_clrused;
u32 i_clrimportant;
} bitmapinfoheader_t;
typedef struct waveformatex_s
{
u16 i_formattag; // + 0x00
u16 i_channels; // + 0x02
u32 i_samplespersec; // + 0x04
u32 i_avgbytespersec; // + 0x08
u16 i_blockalign; // + 0x0c
u16 i_bitspersample; // + 0x0e
u16 i_size; /* the extra size in bytes */
} waveformatex_t;
typedef struct MainAVIHeader_s
{
u32 i_microsecperframe;
u32 i_maxbytespersec;
u32 i_reserved1; /* dwPaddingGranularity; pad to multiples of this
size; normally 2K */
u32 i_flags;
u32 i_totalframes;
u32 i_initialframes;
u32 i_streams;
u32 i_suggestedbuffersize;
u32 i_width;
u32 i_height;
u32 i_scale;
u32 i_rate;
u32 i_start;
u32 i_length;
} MainAVIHeader_t;
typedef struct AVIStreamHeader_s
{
u32 i_type;
u32 i_handler;
u32 i_flags;
u32 i_reserved1; /* wPriority wLanguage */
u32 i_initialframes;
u32 i_scale;
u32 i_rate;
u32 i_start;
u32 i_length; /* In units above... */
u32 i_suggestedbuffersize;
u32 i_quality;
u32 i_samplesize;
} AVIStreamHeader_t;
typedef struct AVIIndexEntry_s typedef struct AVIIndexEntry_s
{ {
u32 i_id; u32 i_id;
...@@ -216,13 +44,14 @@ typedef struct AVIESBuffer_s ...@@ -216,13 +44,14 @@ typedef struct AVIESBuffer_s
typedef struct AVIStreamInfo_s typedef struct AVIStreamInfo_s
{ {
int i_cat; /* AUDIO_ES, VIDEO_ES */ int i_cat; /* AUDIO_ES, VIDEO_ES */
int i_activated;
vlc_fourcc_t i_fourcc; vlc_fourcc_t i_fourcc;
vlc_fourcc_t i_codec; vlc_fourcc_t i_codec;
AVIStreamHeader_t header; int i_rate;
int i_scale;
int i_samplesize;
bitmapinfoheader_t video_format;
waveformatex_t audio_format;
es_descriptor_t *p_es; es_descriptor_t *p_es;
int b_selected; /* newly selected */ int b_selected; /* newly selected */
AVIIndexEntry_t *p_index; AVIIndexEntry_t *p_index;
...@@ -241,17 +70,16 @@ typedef struct AVIStreamInfo_s ...@@ -241,17 +70,16 @@ typedef struct AVIStreamInfo_s
struct demux_sys_t struct demux_sys_t
{ {
mtime_t i_time;
mtime_t i_length;
mtime_t i_pcr; mtime_t i_pcr;
int i_rate; int i_rate;
riffchunk_t *p_riff;
riffchunk_t *p_hdrl;
riffchunk_t *p_movi; riffchunk_t *p_movi;
riffchunk_t *p_idx1;
int b_seekable; int b_seekable;
avi_chunk_t ck_root;
/* Info extrated from avih */ /* Info extrated from avih */
MainAVIHeader_t avih;
/* number of stream and informations*/ /* number of stream and informations*/
int i_streams; int i_streams;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* libioRIFF.c : AVI file Stream input module for vlc * libioRIFF.c : AVI file Stream input module for vlc
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * Copyright (C) 2001 VideoLAN
* $Id: libioRIFF.c,v 1.2 2002/09/18 23:34:28 fenrir Exp $ * $Id: libioRIFF.c,v 1.3 2002/10/15 00:55:07 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
...@@ -135,7 +135,7 @@ riffchunk_t * RIFF_ReadChunk(input_thread_t * p_input) ...@@ -135,7 +135,7 @@ riffchunk_t * RIFF_ReadChunk(input_thread_t * p_input)
{ {
memcpy( &p_riff->i_8bytes, p_peek + 8, count - 8 ); memcpy( &p_riff->i_8bytes, p_peek + 8, count - 8 );
} }
__RIFF_TellPos(p_input, &(p_riff->i_pos) ); __RIFF_TellPos(p_input, &p_riff->i_pos );
return( p_riff ); return( p_riff );
} }
...@@ -177,265 +177,3 @@ int RIFF_NextChunk( input_thread_t * p_input,riffchunk_t *p_rifffather) ...@@ -177,265 +177,3 @@ int RIFF_NextChunk( input_thread_t * p_input,riffchunk_t *p_rifffather)
return( 0 ); return( 0 );
} }
/****************************************************************
* Permet de rentrer dans un ck RIFF ou LIST *
****************************************************************/
int RIFF_DescendChunk(input_thread_t * p_input)
{
return( __RIFF_SkipBytes(p_input,12) != 0 ? -1 : 0 );
}
/***************************************************************
* Permet de sortir d'un sous chunk et d'aller sur le suivant *
* chunk *
***************************************************************/
int RIFF_AscendChunk(input_thread_t * p_input ,riffchunk_t *p_riff)
{
int i_skip;
u32 i_posactu;
__RIFF_TellPos(p_input, &i_posactu);
i_skip = __EVEN( p_riff->i_pos + p_riff->i_size + 8 ) - i_posactu;
return( (( __RIFF_SkipBytes(p_input,i_skip)) != 0) ? -1 : 0 );
}
/***************************************************************
* Permet de se deplacer jusqu'au premier chunk avec le bon id *
* *************************************************************/
int RIFF_FindChunk(input_thread_t * p_input ,u32 i_id,riffchunk_t *p_rifffather)
{
riffchunk_t *p_riff = NULL;
do
{
if ( p_riff )
{
free(p_riff);
if ( RIFF_NextChunk(p_input ,p_rifffather) != 0 )
{
return( -1 );
}
}
p_riff=RIFF_ReadChunk(p_input);
} while ( ( p_riff )&&( p_riff->i_id != i_id ) );
if ( ( !p_riff )||( p_riff->i_id != i_id ) )
{
return( -1 );
}
free( p_riff );
return( 0 );
}
/*****************************************************************
* Permet de pointer sur la zone de donn du chunk courant *
*****************************************************************/
int RIFF_GoToChunkData(input_thread_t * p_input)
{
return( ( __RIFF_SkipBytes(p_input,8) != 0 ) ? -1 : 0 );
}
int RIFF_LoadChunkData(input_thread_t * p_input,riffchunk_t *p_riff )
{
off_t i_read = __EVEN( p_riff->i_size );
RIFF_GoToChunkData(p_input);
if ( input_SplitBuffer( p_input,
&p_riff->p_data,
i_read ) != i_read )
{
msg_Err( p_input, "cannot read enough data " );
return ( -1 );
}
if( p_riff->i_size&1 )
{
p_riff->p_data->p_payload_end--;
}
return( 0 );
}
int RIFF_LoadChunkDataInPES(input_thread_t * p_input,
pes_packet_t **pp_pes,
int i_size_index)
{
u32 i_read;
data_packet_t *p_data;
riffchunk_t *p_riff;
int i_size;
int b_pad = 0;
if( (p_riff = RIFF_ReadChunk( p_input )) == NULL )
{
*pp_pes = NULL;
return( -1 );
}
RIFF_GoToChunkData(p_input);
*pp_pes = input_NewPES( p_input->p_method_data );
if( *pp_pes == NULL )
{
return( -1 );
}
if( (!p_riff->i_size) || (!i_size_index ) )
{
i_size = __MAX( i_size_index, p_riff->i_size );
}
else
{
i_size = __MIN( p_riff->i_size, i_size_index );
}
if( !p_riff->i_size )
{
p_data = input_NewPacket( p_input->p_method_data, 0 );
(*pp_pes)->p_first = p_data;
(*pp_pes)->p_last = p_data;
(*pp_pes)->i_nb_data = 1;
(*pp_pes)->i_pes_size = 0;
return( 0 );
}
if( i_size&1 )
{
i_size++;
b_pad = 1;
}
do
{
i_read = input_SplitBuffer(p_input, &p_data, i_size -
(*pp_pes)->i_pes_size );
if( i_read < 0 )
{
/* FIXME free on all packets */
return( -1 );
}
if( (*pp_pes)->p_first == NULL )
{
(*pp_pes)->p_first = p_data;
(*pp_pes)->p_last = p_data;
(*pp_pes)->i_nb_data = 1;
(*pp_pes)->i_pes_size = ( p_data->p_payload_end -
p_data->p_payload_start );
}
else
{
(*pp_pes)->p_last->p_next = p_data;
(*pp_pes)->p_last = p_data;
(*pp_pes)->i_nb_data++;
(*pp_pes)->i_pes_size += ( p_data->p_payload_end -
p_data->p_payload_start );
}
} while( ((*pp_pes)->i_pes_size < i_size)&&(i_read != 0) );
if( b_pad )
{
(*pp_pes)->i_pes_size--;
(*pp_pes)->p_last->p_payload_end--;
}
return( 0 );
}
int RIFF_GoToChunk(input_thread_t * p_input, riffchunk_t *p_riff)
{
if( p_input->stream.b_seekable )
{
p_input->pf_seek( p_input, (off_t)p_riff->i_pos );
input_AccessReinit( p_input );
return( 0 );
}
return( -1 );
}
int RIFF_TestFileHeader( input_thread_t * p_input, riffchunk_t ** pp_riff, u32 i_type )
{
if( !( *pp_riff = RIFF_ReadChunk( p_input ) ) )
{
return( -1 );
}
if( (*pp_riff)->i_id != MKFOURCC('R','I','F','F')
|| (*pp_riff)->i_type != i_type )
{
free( *pp_riff );
return( -1 );
}
return( 0 );
}
int RIFF_FindAndLoadChunk( input_thread_t * p_input, riffchunk_t *p_riff, riffchunk_t **pp_fmt, u32 i_type )
{
*pp_fmt = NULL;
if ( RIFF_FindChunk( p_input, i_type, p_riff ) != 0)
{
return( -1 );
}
if ( ( (*pp_fmt = RIFF_ReadChunk( p_input )) == NULL)
|| ( RIFF_LoadChunkData( p_input, *pp_fmt ) != 0 ) )
{
if( *pp_fmt != NULL )
{
RIFF_DeleteChunk( p_input, *pp_fmt );
}
return( -1 );
}
return( 0 );
}
int RIFF_FindAndGotoDataChunk( input_thread_t * p_input, riffchunk_t *p_riff, riffchunk_t **pp_data, u32 i_type )
{
*pp_data = NULL;
if ( RIFF_FindChunk( p_input, i_type, p_riff ) != 0)
{
return( -1 );
}
if ( ( *pp_data = RIFF_ReadChunk( p_input ) ) == NULL )
{
return( -1 );
}
if ( RIFF_GoToChunkData( p_input ) != 0 )
{
RIFF_DeleteChunk( p_input, *pp_data );
return( -1 );
}
return( 0 );
}
int RIFF_FindListChunk( input_thread_t *p_input, riffchunk_t **pp_riff, riffchunk_t *p_rifffather, u32 i_type )
{
int i_ok;
*pp_riff = NULL;
i_ok = 0;
while( i_ok == 0 )
{
if( *pp_riff != NULL )
{
free( *pp_riff );
}
if( RIFF_FindChunk( p_input,
MKFOURCC('L','I','S','T'), p_rifffather ) != 0 )
{
return( -1 );
}
*pp_riff = RIFF_ReadChunk( p_input );
if( *pp_riff == NULL )
{
return( -1 );
}
if( (*pp_riff)->i_type != i_type )
{
if( RIFF_NextChunk( p_input, p_rifffather ) != 0 )
{
return( -1 );
}
}
else
{
i_ok = 1;
}
}
return( 0 );
}
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* libioRIFF.h : AVI file Stream input module for vlc * libioRIFF.h : AVI file Stream input module for vlc
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * Copyright (C) 2001 VideoLAN
* $Id: libioRIFF.h,v 1.2 2002/09/18 23:34:28 fenrir Exp $ * $Id: libioRIFF.h,v 1.3 2002/10/15 00:55:07 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
...@@ -37,32 +37,4 @@ int __RIFF_SkipBytes(input_thread_t * p_input,int nb); ...@@ -37,32 +37,4 @@ int __RIFF_SkipBytes(input_thread_t * p_input,int nb);
void RIFF_DeleteChunk( input_thread_t *p_input, riffchunk_t *p_chunk ); void RIFF_DeleteChunk( input_thread_t *p_input, riffchunk_t *p_chunk );
riffchunk_t *RIFF_ReadChunk(input_thread_t * p_input); riffchunk_t *RIFF_ReadChunk(input_thread_t * p_input);
int RIFF_NextChunk( input_thread_t * p_input,riffchunk_t *p_rifffather); int RIFF_NextChunk( input_thread_t * p_input,riffchunk_t *p_rifffather);
int RIFF_DescendChunk(input_thread_t * p_input);
int RIFF_AscendChunk(input_thread_t * p_input ,riffchunk_t *p_riff);
int RIFF_FindChunk(input_thread_t * p_input,
u32 i_id,riffchunk_t *p_rifffather);
int RIFF_GoToChunkData(input_thread_t * p_input);
int RIFF_LoadChunkData(input_thread_t * p_input,
riffchunk_t *p_riff );
int RIFF_LoadChunkDataInPES(input_thread_t * p_input,
pes_packet_t **pp_pes,
int i_size_index);
int RIFF_GoToChunk(input_thread_t * p_input,
riffchunk_t *p_riff);
int RIFF_TestFileHeader( input_thread_t * p_input,
riffchunk_t ** pp_riff,
u32 i_type );
int RIFF_FindAndLoadChunk( input_thread_t * p_input,
riffchunk_t *p_riff,
riffchunk_t **pp_fmt,
u32 i_type );
int RIFF_FindAndGotoDataChunk( input_thread_t * p_input,
riffchunk_t *p_riff,
riffchunk_t **pp_data,
u32 i_type );
int RIFF_FindListChunk( input_thread_t *p_input,
riffchunk_t **pp_riff,
riffchunk_t *p_rifffather,
u32 i_type );
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