X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fmux%2Favi.c;h=31b13153abf0d89a86d350d5c886caca84aea4e8;hb=19933fe7a674ee6d1253821a656507a6a712f8d0;hp=f3657ee77b960e4d813384c1e14c1d6ff777057b;hpb=42195685323f11ea92176ac02c366444d908f154;p=vlc diff --git a/modules/mux/avi.c b/modules/mux/avi.c index f3657ee77b..31b13153ab 100644 --- a/modules/mux/avi.c +++ b/modules/mux/avi.c @@ -1,8 +1,8 @@ /***************************************************************************** * avi.c ***************************************************************************** - * Copyright (C) 2001, 2002 VideoLAN - * $Id: avi.c,v 1.17 2003/12/22 02:24:53 sam Exp $ + * Copyright (C) 2001, 2002 the VideoLAN team + * $Id$ * * Authors: Laurent Aimar * @@ -18,7 +18,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ /***************************************************************************** @@ -26,13 +26,16 @@ *****************************************************************************/ /* TODO: add OpenDML write support */ -#include -#include -#include -#include +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif -#include "codecs.h" +#include +#include +#include +#include +#include /***************************************************************************** * Module descriptor @@ -41,7 +44,9 @@ static int Open ( vlc_object_t * ); static void Close ( vlc_object_t * ); vlc_module_begin(); - set_description( _("AVI muxer") ); + set_description( N_("AVI muxer") ); + set_category( CAT_SOUT ); + set_subcategory( SUBCAT_SOUT_MUX ); set_capability( "sout mux", 5 ); add_shortcut( "avi" ); set_callbacks( Open, Close ); @@ -51,10 +56,10 @@ vlc_module_end(); /***************************************************************************** * Local prototypes *****************************************************************************/ -static int Capability(sout_mux_t *, int , void *, void * ); -static int AddStream( sout_mux_t *, sout_input_t * ); -static int DelStream( sout_mux_t *, sout_input_t * ); -static int Mux ( sout_mux_t * ); +static int Control( sout_mux_t *, int, va_list ); +static int AddStream( sout_mux_t *, sout_input_t * ); +static int DelStream( sout_mux_t *, sout_input_t * ); +static int Mux ( sout_mux_t * ); typedef struct avi_stream_s { @@ -62,7 +67,7 @@ typedef struct avi_stream_s char fcc[4]; - mtime_t i_duration; // in µs + mtime_t i_duration; // in µs int i_frames; // total frame count int64_t i_totalsize; // total stream size @@ -94,7 +99,7 @@ typedef struct avi_idx1_s struct sout_mux_sys_t { - vlc_bool_t b_write_header; + bool b_write_header; int i_streams; int i_stream_video; @@ -119,23 +124,14 @@ struct sout_mux_sys_t #define AVIIF_KEYFRAME 0x00000010L /* this frame is a key frame.*/ -static sout_buffer_t *avi_HeaderCreateRIFF( sout_mux_t * ); -static sout_buffer_t *avi_HeaderCreateidx1( sout_mux_t * ); +static block_t *avi_HeaderCreateRIFF( sout_mux_t * ); +static block_t *avi_HeaderCreateidx1( sout_mux_t * ); static void SetFCC( uint8_t *p, char *fcc ) { memcpy( p, fcc, 4 ); } -static void SetDWLE( uint8_t *p, uint32_t i_dw ) -{ - p[3] = ( i_dw >> 24 )&0xff; - p[2] = ( i_dw >> 16 )&0xff; - p[1] = ( i_dw >> 8 )&0xff; - p[0] = ( i_dw )&0xff; -} - - /***************************************************************************** * Open: *****************************************************************************/ @@ -155,15 +151,14 @@ static int Open( vlc_object_t *p_this ) p_sys->idx1.i_entry_max = 10000; p_sys->idx1.entry = calloc( p_sys->idx1.i_entry_max, sizeof( avi_idx1_entry_t ) ); - p_sys->b_write_header = VLC_TRUE; + p_sys->b_write_header = true; - p_mux->pf_capacity = Capability; + p_mux->pf_control = Control; p_mux->pf_addstream = AddStream; p_mux->pf_delstream = DelStream; p_mux->pf_mux = Mux; p_mux->p_sys = p_sys; - p_mux->i_preheader = 8; /* (fourcc,length) header */ return VLC_SUCCESS; } @@ -176,14 +171,14 @@ static void Close( vlc_object_t * p_this ) sout_mux_t *p_mux = (sout_mux_t*)p_this; sout_mux_sys_t *p_sys = p_mux->p_sys; - sout_buffer_t *p_hdr, *p_idx1; + block_t *p_hdr, *p_idx1; int i_stream; msg_Dbg( p_mux, "AVI muxer closed" ); /* first create idx1 chunk (write at the end of the stream */ p_idx1 = avi_HeaderCreateidx1( p_mux ); - p_sys->i_idx1_size = p_idx1->i_size; + p_sys->i_idx1_size = p_idx1->i_buffer; sout_AccessOutWrite( p_mux->p_access, p_idx1 ); /* calculate some value for headers creations */ @@ -208,7 +203,7 @@ static void Close( vlc_object_t * p_this ) (uint64_t)p_stream->i_totalsize / (uint64_t)p_stream->i_duration; } - msg_Info( p_mux, "stream[%d] duration:"I64Fd" totalsize:"I64Fd + msg_Info( p_mux, "stream[%d] duration:%"PRId64" totalsize:%"PRId64 " frames:%d fps:%f kb/s:%d", i_stream, (int64_t)p_stream->i_duration / (int64_t)1000000, @@ -222,16 +217,31 @@ static void Close( vlc_object_t * p_this ) sout_AccessOutWrite( p_mux->p_access, p_hdr ); } -static int Capability( sout_mux_t *p_mux, int i_query, - void *p_args, void *p_answer ) +static int Control( sout_mux_t *p_mux, int i_query, va_list args ) { + VLC_UNUSED(p_mux); + bool *pb_bool; + char **ppsz; + switch( i_query ) { - case SOUT_MUX_CAP_GET_ADD_STREAM_ANY_TIME: - *(vlc_bool_t*)p_answer = VLC_FALSE; - return( SOUT_MUX_CAP_ERR_OK ); + case MUX_CAN_ADD_STREAM_WHILE_MUXING: + pb_bool = (bool*)va_arg( args, bool * ); + *pb_bool = false; + return VLC_SUCCESS; + + case MUX_GET_ADD_STREAM_WAIT: + pb_bool = (bool*)va_arg( args, bool * ); + *pb_bool = true; + return VLC_SUCCESS; + + case MUX_GET_MIME: + ppsz = (char**)va_arg( args, char ** ); + *ppsz = strdup( "video/avi" ); + return VLC_SUCCESS; + default: - return( SOUT_MUX_CAP_ERR_UNIMPLEMENTED ); + return VLC_EGENERIC; } } @@ -290,11 +300,15 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input ) case VLC_FOURCC( 'w', 'm', 'a', '1' ): p_wf->wFormatTag = WAVE_FORMAT_WMA1; break; + case VLC_FOURCC( 'w', 'm', 'a', ' ' ): case VLC_FOURCC( 'w', 'm', 'a', '2' ): p_wf->wFormatTag = WAVE_FORMAT_WMA2; break; - case VLC_FOURCC( 'w', 'm', 'a', '3' ): - p_wf->wFormatTag = WAVE_FORMAT_WMA3; + case VLC_FOURCC( 'w', 'm', 'a', 'p' ): + p_wf->wFormatTag = WAVE_FORMAT_WMAP; + break; + case VLC_FOURCC( 'w', 'm', 'a', 'l' ): + p_wf->wFormatTag = WAVE_FORMAT_WMAL; break; /* raw codec */ case VLC_FOURCC( 'u', '8', ' ', ' ' ): @@ -392,55 +406,59 @@ static int Mux ( sout_mux_t *p_mux ) { sout_mux_sys_t *p_sys = p_mux->p_sys; avi_stream_t *p_stream; - int i_stream; - int i; + int i_stream, i; if( p_sys->b_write_header ) { - sout_buffer_t *p_hdr; + block_t *p_hdr; msg_Dbg( p_mux, "writing header" ); p_hdr = avi_HeaderCreateRIFF( p_mux ); sout_AccessOutWrite( p_mux->p_access, p_hdr ); - p_sys->b_write_header = VLC_FALSE; + p_sys->b_write_header = false; } for( i = 0; i < p_mux->i_nb_inputs; i++ ) { int i_count; - sout_fifo_t *p_fifo; + block_fifo_t *p_fifo; i_stream = *((int*)p_mux->pp_inputs[i]->p_sys ); p_stream = &p_sys->stream[i_stream]; p_fifo = p_mux->pp_inputs[i]->p_fifo; - i_count = p_fifo->i_depth; - while( i_count > 0 ) + i_count = block_FifoCount( p_fifo ); + while( i_count > 1 ) { avi_idx1_entry_t *p_idx; - sout_buffer_t *p_data; + block_t *p_data; - p_data = sout_FifoGet( p_fifo ); + p_data = block_FifoGet( p_fifo ); + if( block_FifoCount( p_fifo ) > 0 ) + { + block_t *p_next = block_FifoShow( p_fifo ); + p_data->i_length = p_next->i_dts - p_data->i_dts; + } p_stream->i_frames++; if( p_data->i_length < 0 ) { msg_Warn( p_mux, "argg length < 0 l" ); - sout_BufferDelete( p_mux->p_sout, p_data ); + block_Release( p_data ); i_count--; continue; } p_stream->i_duration += p_data->i_length; - p_stream->i_totalsize += p_data->i_size; + p_stream->i_totalsize += p_data->i_buffer; /* add idx1 entry for this frame */ p_idx = &p_sys->idx1.entry[p_sys->idx1.i_entry_count]; memcpy( p_idx->fcc, p_stream->fcc, 4 ); p_idx->i_flags = AVIIF_KEYFRAME; p_idx->i_pos = p_sys->i_movi_size + 4; - p_idx->i_length= p_data->i_size; + p_idx->i_length= p_data->i_buffer; p_sys->idx1.i_entry_count++; if( p_sys->idx1.i_entry_count >= p_sys->idx1.i_entry_max ) { @@ -449,34 +467,21 @@ static int Mux ( sout_mux_t *p_mux ) p_sys->idx1.i_entry_max * sizeof( avi_idx1_entry_t ) ); } - - if( sout_BufferReallocFromPreHeader( p_mux->p_sout, p_data, 8 ) ) - { - /* there isn't enough data in preheader */ - sout_buffer_t *p_hdr; - - p_hdr = sout_BufferNew( p_mux->p_sout, 8 ); - SetFCC( p_hdr->p_buffer, p_stream->fcc ); - SetDWLE( p_hdr->p_buffer + 4, p_data->i_size ); - - sout_AccessOutWrite( p_mux->p_access, p_hdr ); - p_sys->i_movi_size += p_hdr->i_size; - - } - else + p_data = block_Realloc( p_data, 8, p_data->i_buffer ); + if( p_data ) { SetFCC( p_data->p_buffer, p_stream->fcc ); - SetDWLE( p_data->p_buffer + 4, p_data->i_size - 8 ); - } + SetDWLE( p_data->p_buffer + 4, p_data->i_buffer - 8 ); - if( p_data->i_size & 0x01 ) - { - sout_BufferRealloc( p_mux->p_sout, p_data, p_data->i_size + 1 ); - p_data->i_size += 1; - } + if( p_data->i_buffer & 0x01 ) + { + p_data = block_Realloc( p_data, 0, p_data->i_buffer + 1 ); + p_data->p_buffer[ p_data->i_buffer - 1 ] = '\0'; + } - p_sys->i_movi_size += p_data->i_size; - sout_AccessOutWrite( p_mux->p_access, p_data ); + p_sys->i_movi_size += p_data->i_buffer; + sout_AccessOutWrite( p_mux->p_access, p_data ); + } i_count--; } @@ -545,7 +550,7 @@ static void bo_AddLWordBE( buffer_out_t *p_bo, uint64_t i ) } #endif -static void bo_AddFCC( buffer_out_t *p_bo, char *fcc ) +static void bo_AddFCC( buffer_out_t *p_bo, const char *fcc ) { bo_AddByte( p_bo, fcc[0] ); bo_AddByte( p_bo, fcc[1] ); @@ -624,8 +629,8 @@ static int avi_HeaderAdd_avih( sout_mux_t *p_mux, if( p_sys->stream[i_stream].i_duration > 0 ) { i_maxbytespersec += - p_sys->stream[p_sys->i_stream_video].i_totalsize / - p_sys->stream[p_sys->i_stream_video].i_duration; + p_sys->stream[i_stream].i_totalsize / + p_sys->stream[i_stream].i_duration; } } @@ -656,9 +661,7 @@ static int avi_HeaderAdd_avih( sout_mux_t *p_mux, AVI_BOX_EXIT( 0 ); } -static int avi_HeaderAdd_strh( sout_mux_t *p_mux, - buffer_out_t *p_bo, - avi_stream_t *p_stream ) +static int avi_HeaderAdd_strh( buffer_out_t *p_bo, avi_stream_t *p_stream ) { AVI_BOX_ENTER( "strh" ); @@ -725,9 +728,7 @@ static int avi_HeaderAdd_strh( sout_mux_t *p_mux, AVI_BOX_EXIT( 0 ); } -static int avi_HeaderAdd_strf( sout_mux_t *p_mux, - buffer_out_t *p_bo, - avi_stream_t *p_stream ) +static int avi_HeaderAdd_strf( buffer_out_t *p_bo, avi_stream_t *p_stream ) { AVI_BOX_ENTER( "strf" ); @@ -771,28 +772,26 @@ static int avi_HeaderAdd_strf( sout_mux_t *p_mux, AVI_BOX_EXIT( 0 ); } -static int avi_HeaderAdd_strl( sout_mux_t *p_mux, - buffer_out_t *p_bo, - avi_stream_t *p_stream ) +static int avi_HeaderAdd_strl( buffer_out_t *p_bo, avi_stream_t *p_stream ) { AVI_BOX_ENTER_LIST( "strl" ); - avi_HeaderAdd_strh( p_mux, p_bo, p_stream ); - avi_HeaderAdd_strf( p_mux, p_bo, p_stream ); + avi_HeaderAdd_strh( p_bo, p_stream ); + avi_HeaderAdd_strf( p_bo, p_stream ); AVI_BOX_EXIT( 0 ); } -static sout_buffer_t *avi_HeaderCreateRIFF( sout_mux_t *p_mux ) +static block_t *avi_HeaderCreateRIFF( sout_mux_t *p_mux ) { sout_mux_sys_t *p_sys = p_mux->p_sys; - sout_buffer_t *p_hdr; + block_t *p_hdr; int i_stream; int i_maxbytespersec; int i_junk; buffer_out_t bo; - p_hdr = sout_BufferNew( p_mux->p_sout, HDR_SIZE ); + p_hdr = block_New( p_mux, HDR_SIZE ); memset( p_hdr->p_buffer, 0, HDR_SIZE ); bo_Init( &bo, HDR_SIZE, p_hdr->p_buffer ); @@ -808,7 +807,7 @@ static sout_buffer_t *avi_HeaderCreateRIFF( sout_mux_t *p_mux ) avi_HeaderAdd_avih( p_mux, &bo ); for( i_stream = 0,i_maxbytespersec = 0; i_stream < p_sys->i_streams; i_stream++ ) { - avi_HeaderAdd_strl( p_mux, &bo, &p_sys->stream[i_stream] ); + avi_HeaderAdd_strl( &bo, &p_sys->stream[i_stream] ); } i_junk = HDR_SIZE - bo.i_buffer - 8 - 12; @@ -823,17 +822,17 @@ static sout_buffer_t *avi_HeaderCreateRIFF( sout_mux_t *p_mux ) return( p_hdr ); } -static sout_buffer_t * avi_HeaderCreateidx1( sout_mux_t *p_mux ) +static block_t * avi_HeaderCreateidx1( sout_mux_t *p_mux ) { sout_mux_sys_t *p_sys = p_mux->p_sys; - sout_buffer_t *p_idx1; + block_t *p_idx1; uint32_t i_idx1_size; unsigned int i; buffer_out_t bo; i_idx1_size = 16 * p_sys->idx1.i_entry_count; - p_idx1 = sout_BufferNew( p_mux->p_sout, i_idx1_size + 8 ); + p_idx1 = block_New( p_mux, i_idx1_size + 8 ); memset( p_idx1->p_buffer, 0, i_idx1_size ); bo_Init( &bo, i_idx1_size, p_idx1->p_buffer );