From 1e9f16e284a4bb84ac446bf18e6b5581754fc6d3 Mon Sep 17 00:00:00 2001 From: Gildas Bazin Date: Sun, 16 Nov 2003 21:07:31 +0000 Subject: [PATCH] * ALL: final improvements to the decoders/packetizers api. (There are still a few decoders/packetizers left to be converted but this shouldn't take too long). * ALL: small improvements to the encoders api. --- include/aout_internal.h | 24 +- include/audio_output.h | 15 +- include/input_ext-intf.h | 5 +- include/ninput.h | 53 ++- include/vlc_block_helper.h | 104 +++++- include/vlc_codec.h | 56 ++-- include/vlc_common.h | 9 +- include/vlc_video.h | 6 +- modules/codec/a52.c | 428 ++++++++---------------- modules/codec/adpcm.c | 310 +++++++++-------- modules/codec/araw.c | 410 ++++++++++------------- modules/codec/cinepak.c | 105 +++--- modules/codec/dts.c | 571 ++++++++++++-------------------- modules/codec/dv.c | 4 +- modules/codec/dvbsub.c | 4 +- modules/codec/faad.c | 283 ++++++++-------- modules/codec/ffmpeg/audio.c | 223 +++++-------- modules/codec/ffmpeg/encoder.c | 275 +++++++-------- modules/codec/ffmpeg/ffmpeg.c | 109 +++--- modules/codec/ffmpeg/ffmpeg.h | 10 +- modules/codec/ffmpeg/video.c | 255 +++++++------- modules/codec/flacdec.c | 4 +- modules/codec/libmpeg2.c | 299 +++++++---------- modules/codec/lpcm.c | 6 +- modules/codec/mpeg_audio.c | 469 ++++++++++---------------- modules/codec/rawvideo.c | 234 +++++-------- modules/codec/speex.c | 331 +++++++----------- modules/codec/spudec/spudec.c | 6 +- modules/codec/subsdec.c | 50 +-- modules/codec/tarkin.c | 4 +- modules/codec/theora.c | 385 ++++++++------------- modules/codec/vorbis.c | 367 ++++++++------------ modules/codec/xvid.c | 8 +- modules/demux/a52sys.c | 6 +- modules/demux/aac.c | 4 +- modules/demux/asf/asf.c | 4 +- modules/demux/au.c | 10 +- modules/demux/avi/avi.c | 4 +- modules/demux/livedotcom.cpp | 8 +- modules/demux/mkv.cpp | 14 +- modules/demux/mpeg/mpga.c | 4 +- modules/demux/wav.c | 14 +- modules/misc/dummy/Modules.am | 1 + modules/misc/dummy/decoder.c | 132 ++++---- modules/misc/dummy/dummy.c | 8 +- modules/misc/dummy/dummy.h | 8 +- modules/packetizer/copy.c | 31 +- modules/packetizer/mpeg4audio.c | 340 ++++++++----------- modules/stream_out/transcode.c | 160 +++++---- src/audio_output/common.c | 4 +- src/audio_output/dec.c | 3 +- src/input/input.c | 56 +++- src/input/input_dec.c | 334 +++++++++++++++++-- src/input/input_programs.c | 5 +- src/libvlc.h | 27 +- 55 files changed, 2926 insertions(+), 3673 deletions(-) diff --git a/include/aout_internal.h b/include/aout_internal.h index 9f38dcb16e..81e53885e0 100644 --- a/include/aout_internal.h +++ b/include/aout_internal.h @@ -2,7 +2,7 @@ * aout_internal.h : internal defines for audio output ***************************************************************************** * Copyright (C) 2002 VideoLAN - * $Id: aout_internal.h,v 1.41 2003/10/27 21:54:10 gbazin Exp $ + * $Id: aout_internal.h,v 1.42 2003/11/16 21:07:30 gbazin Exp $ * * Authors: Christophe Massiot * @@ -97,7 +97,7 @@ struct aout_fifo_t /***************************************************************************** * aout_filter_t : audio output filter *****************************************************************************/ -typedef struct aout_filter_t +struct aout_filter_t { VLC_COMMON_MEMBERS @@ -113,7 +113,7 @@ typedef struct aout_filter_t struct aout_buffer_t * ); vlc_bool_t b_in_place; vlc_bool_t b_continuity; -} aout_filter_t; +}; /***************************************************************************** * aout_mixer_t : audio output mixer @@ -255,20 +255,10 @@ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input, aout_buffer_t * p_buffer ); /* From filters.c : */ -int aout_FiltersCreatePipeline( aout_instance_t * p_aout, - aout_filter_t ** pp_filters, - int * pi_nb_filters, - const audio_sample_format_t * p_input_format, - const audio_sample_format_t * p_output_format ); -void aout_FiltersDestroyPipeline( aout_instance_t * p_aout, - aout_filter_t ** pp_filters, - int i_nb_filters ); -void aout_FiltersHintBuffers( aout_instance_t * p_aout, - aout_filter_t ** pp_filters, - int i_nb_filters, aout_alloc_t * p_first_alloc ); -void aout_FiltersPlay( aout_instance_t * p_aout, - aout_filter_t ** pp_filters, - int i_nb_filters, aout_buffer_t ** pp_input_buffer ); +VLC_EXPORT( int, aout_FiltersCreatePipeline, ( aout_instance_t * p_aout, aout_filter_t ** pp_filters, int * pi_nb_filters, const audio_sample_format_t * p_input_format, const audio_sample_format_t * p_output_format ) ); +VLC_EXPORT( void, aout_FiltersDestroyPipeline, ( aout_instance_t * p_aout, aout_filter_t ** pp_filters, int i_nb_filters ) ); +VLC_EXPORT( void, aout_FiltersPlay, ( aout_instance_t * p_aout, aout_filter_t ** pp_filters, int i_nb_filters, aout_buffer_t ** pp_input_buffer ) ); +void aout_FiltersHintBuffers( aout_instance_t * p_aout, aout_filter_t ** pp_filters, int i_nb_filters, aout_alloc_t * p_first_alloc ); /* From mixer.c : */ int aout_MixerNew( aout_instance_t * p_aout ); diff --git a/include/audio_output.h b/include/audio_output.h index 2971b76cb2..98820eadac 100644 --- a/include/audio_output.h +++ b/include/audio_output.h @@ -2,7 +2,7 @@ * audio_output.h : audio output interface ***************************************************************************** * Copyright (C) 2002 VideoLAN - * $Id: audio_output.h,v 1.83 2003/10/08 21:01:07 gbazin Exp $ + * $Id: audio_output.h,v 1.84 2003/11/16 21:07:30 gbazin Exp $ * * Authors: Christophe Massiot * @@ -28,19 +28,24 @@ ***************************************************************************** * This structure defines a format for audio samples. *****************************************************************************/ -struct audio_sample_format_t +struct audio_format_t { vlc_fourcc_t i_format; + unsigned int i_rate; + /* Describes the channels configuration of the samples (ie. number of * channels which are available in the buffer, and positions). */ uint32_t i_physical_channels; + /* Describes from which original channels, before downmixing, the * buffer is derived. */ uint32_t i_original_channels; + /* Optional - for A/52, SPDIF and DTS types : */ /* Bytes used by one compressed frame, depends on bitrate. */ unsigned int i_bytes_per_frame; + /* Number of sampleframes contained in one compressed frame. */ unsigned int i_frame_length; /* Please note that it may be completely arbitrary - buffers are not @@ -48,6 +53,12 @@ struct audio_sample_format_t * just here for the division : * buffer_size = i_nb_samples * i_bytes_per_frame / i_frame_length */ + + /* FIXME ? (used by the codecs) */ + int i_bitrate; + int i_channels; + int i_blockalign; + int i_bitspersample; }; #define AOUT_FMTS_IDENTICAL( p_first, p_second ) ( \ diff --git a/include/input_ext-intf.h b/include/input_ext-intf.h index 20e39fddf3..d07de40c59 100644 --- a/include/input_ext-intf.h +++ b/include/input_ext-intf.h @@ -4,7 +4,7 @@ * control the pace of reading. ***************************************************************************** * Copyright (C) 1999, 2000 VideoLAN - * $Id: input_ext-intf.h,v 1.97 2003/11/06 16:36:41 nitrox Exp $ + * $Id: input_ext-intf.h,v 1.98 2003/11/16 21:07:30 gbazin Exp $ * * Authors: Christophe Massiot * @@ -26,6 +26,8 @@ #ifndef _VLC_INPUT_EXT_INTF_H #define _VLC_INPUT_EXT_INTF_H 1 +#include "ninput.h" + /* * Communication input -> interface */ @@ -65,6 +67,7 @@ struct es_descriptor_t unsigned int i_pes_real_size; /* as indicated by the header */ /* Decoder information */ + es_format_t fmt; decoder_fifo_t * p_decoder_fifo; void * p_waveformatex; void * p_bitmapinfoheader; diff --git a/include/ninput.h b/include/ninput.h index c9a13caf84..e2b5b827e0 100644 --- a/include/ninput.h +++ b/include/ninput.h @@ -2,7 +2,7 @@ * ninput.h ***************************************************************************** * Copyright (C) 1999-2001 VideoLAN - * $Id: ninput.h,v 1.14 2003/11/13 17:59:34 gbazin Exp $ + * $Id: ninput.h,v 1.15 2003/11/16 21:07:30 gbazin Exp $ * * Authors: Laurent Aimar * @@ -24,6 +24,9 @@ #ifndef _NINPUT_H #define _NINPUT_H 1 +#include "audio_output.h" +#include "vlc_video.h" + enum es_extra_type_e { ES_EXTRA_TYPE_UNKNOWN, @@ -32,6 +35,12 @@ enum es_extra_type_e ES_EXTRA_TYPE_SUBHEADER }; +typedef struct subs_format_t +{ + char *psz_encoding; + +} subs_format_t; + typedef struct { int i_cat; @@ -47,31 +56,16 @@ typedef struct char *psz_language; char *psz_description; - struct - { - int i_samplerate; - int i_channels; - int i_bitrate; - int i_blockalign; - int i_bitspersample; - } audio; - - struct - { - int i_width; - int i_height; - int i_display_width; - int i_display_height; - } video; - - struct - { - char *psz_encoding; - } subs; + audio_format_t audio; + video_format_t video; + subs_format_t subs; + + int i_bitrate; int i_extra_type; int i_extra; void *p_extra; + } es_format_t; static inline void es_format_Init( es_format_t *fmt, @@ -84,18 +78,9 @@ static inline void es_format_Init( es_format_t *fmt, fmt->psz_language = NULL; fmt->psz_description = NULL; - fmt->audio.i_samplerate = 0; - fmt->audio.i_channels = 0; - fmt->audio.i_bitrate = 0; - fmt->audio.i_blockalign = 0; - fmt->audio.i_bitspersample = 0; - - fmt->video.i_width = 0; - fmt->video.i_height = 0; - fmt->video.i_display_width = 0; - fmt->video.i_display_height = 0; - - fmt->subs.psz_encoding = NULL; + memset( &fmt->audio, 0, sizeof(audio_format_t) ); + memset( &fmt->video, 0, sizeof(video_format_t) ); + memset( &fmt->subs, 0, sizeof(subs_format_t) ); fmt->i_extra_type = ES_EXTRA_TYPE_UNKNOWN; fmt->i_extra = 0; diff --git a/include/vlc_block_helper.h b/include/vlc_block_helper.h index 1e8676b536..bb155023be 100644 --- a/include/vlc_block_helper.h +++ b/include/vlc_block_helper.h @@ -2,7 +2,7 @@ * vlc_block_helper.h: Helper functions for data blocks management. ***************************************************************************** * Copyright (C) 2003 VideoLAN - * $Id: vlc_block_helper.h,v 1.4 2003/10/23 20:51:20 gbazin Exp $ + * $Id: vlc_block_helper.h,v 1.5 2003/11/16 21:07:30 gbazin Exp $ * * Authors: Gildas Bazin * @@ -29,26 +29,38 @@ typedef struct block_bytestream_t block_t *p_chain; block_t *p_block; int i_offset; + } block_bytestream_t; -#define block_BytestreamInit( a, b, c ) __block_BytestreamInit( VLC_OBJECT(a), b, c ) +#define block_BytestreamInit( a ) __block_BytestreamInit( VLC_OBJECT(a) ) /***************************************************************************** * block_bytestream_t management *****************************************************************************/ -static inline block_bytestream_t __block_BytestreamInit( vlc_object_t *p_obj, - block_t *p_block, int i_offset ) +static inline block_bytestream_t __block_BytestreamInit( vlc_object_t *p_obj ) { block_bytestream_t bytestream; - bytestream.i_offset = i_offset; - bytestream.p_block = p_block; - bytestream.p_chain = p_block; + bytestream.i_offset = 0; + bytestream.p_chain = bytestream.p_block = NULL; return bytestream; } -static inline block_t *block_BytestreamFlush( block_bytestream_t *p_bytestream) +static inline void block_BytestreamRelease( block_bytestream_t *p_bytestream ) +{ + while( p_bytestream->p_chain ) + { + block_t *p_next; + p_next = p_bytestream->p_chain->p_next; + p_bytestream->p_chain->pf_release( p_bytestream->p_chain ); + p_bytestream->p_chain = p_next; + } + p_bytestream->i_offset = 0; + p_bytestream->p_chain = p_bytestream->p_block = NULL; +} + +static inline void block_BytestreamFlush( block_bytestream_t *p_bytestream ) { while( p_bytestream->p_chain != p_bytestream->p_block ) { @@ -57,8 +69,54 @@ static inline block_t *block_BytestreamFlush( block_bytestream_t *p_bytestream) p_bytestream->p_chain->pf_release( p_bytestream->p_chain ); p_bytestream->p_chain = p_next; } + while( p_bytestream->p_block && + (p_bytestream->p_block->i_buffer - p_bytestream->i_offset) == 0 ) + { + block_t *p_next; + p_next = p_bytestream->p_chain->p_next; + p_bytestream->p_chain->pf_release( p_bytestream->p_chain ); + p_bytestream->p_chain = p_bytestream->p_block = p_next; + p_bytestream->i_offset = 0; + } +} - return p_bytestream->p_chain; +static inline void block_BytestreamPush( block_bytestream_t *p_bytestream, + block_t *p_block ) +{ + block_ChainAppend( &p_bytestream->p_chain, p_block ); + if( !p_bytestream->p_block ) p_bytestream->p_block = p_block; +} + +static inline block_t *block_BytestreamPop( block_bytestream_t *p_bytestream ) +{ + block_t *p_block; + + block_BytestreamFlush( p_bytestream ); + + p_block = p_bytestream->p_block; + if( p_block == NULL ) + { + return NULL; + } + else if( !p_block->p_next ) + { + p_block->p_buffer += p_bytestream->i_offset; + p_block->i_buffer -= p_bytestream->i_offset; + p_bytestream->i_offset = 0; + p_bytestream->p_chain = p_bytestream->p_block = NULL; + return p_block; + } + + while( p_block->p_next && p_block->p_next->p_next ) + p_block = p_block->p_next; + + { + block_t *p_block_old = p_block; + p_block = p_block->p_next; + p_block_old->p_next = NULL; + } + + return p_block; } static inline int block_SkipByte( block_bytestream_t *p_bytestream ) @@ -151,6 +209,34 @@ static inline int block_GetByte( block_bytestream_t *p_bytestream, return VLC_EGENERIC; } +static inline int block_WaitBytes( block_bytestream_t *p_bytestream, + int i_data ) +{ + block_t *p_block; + int i_offset, i_copy, i_size; + + /* Check we have that much data */ + i_offset = p_bytestream->i_offset; + i_size = i_data; + i_copy = 0; + for( p_block = p_bytestream->p_block; + p_block != NULL; p_block = p_block->p_next ) + { + i_copy = __MIN( i_size, p_block->i_buffer - i_offset ); + i_size -= i_copy; + i_offset = 0; + + if( !i_size ) break; + } + + if( i_size ) + { + /* Not enough data, bail out */ + return VLC_EGENERIC; + } + return VLC_SUCCESS; +} + static inline int block_SkipBytes( block_bytestream_t *p_bytestream, int i_data ) { diff --git a/include/vlc_codec.h b/include/vlc_codec.h index 5acb0746ee..180538a09b 100644 --- a/include/vlc_codec.h +++ b/include/vlc_codec.h @@ -2,7 +2,7 @@ * vlc_codec.h: codec related structures ***************************************************************************** * Copyright (C) 1999-2003 VideoLAN - * $Id: vlc_codec.h,v 1.3 2003/11/05 18:59:01 gbazin Exp $ + * $Id: vlc_codec.h,v 1.4 2003/11/16 21:07:30 gbazin Exp $ * * Authors: Gildas Bazin * @@ -23,11 +23,15 @@ #ifndef _VLC_CODEC_H #define _VLC_CODEC_H 1 +#include "ninput.h" + /** * \file * This file defines the structure and types used by decoders and encoders */ +typedef struct decoder_owner_sys_t decoder_owner_sys_t; + /** * \defgroup decoder Decoder * @@ -43,15 +47,39 @@ struct decoder_t /* Module properties */ module_t * p_module; decoder_sys_t * p_sys; - int ( * pf_init ) ( decoder_t * ); + + /* Deprecated */ int ( * pf_decode )( decoder_t *, block_t * ); - int ( * pf_end ) ( decoder_t * ); + decoder_fifo_t * p_fifo; + int ( * pf_run ) ( decoder_fifo_t * ); + /* End deprecated */ - /* Input properties */ - decoder_fifo_t * p_fifo; /* stores the PES stream data */ + picture_t * ( * pf_decode_video )( decoder_t *, block_t ** ); + aout_buffer_t * ( * pf_decode_audio )( decoder_t *, block_t ** ); + void ( * pf_decode_sub) ( decoder_t *, block_t ** ); + block_t * ( * pf_packetize ) ( decoder_t *, block_t ** ); - /* Tmp field for old decoder api */ - int ( * pf_run ) ( decoder_fifo_t * ); + /* Input format ie from demuxer (XXX: a lot of field could be invalid) */ + es_format_t fmt_in; + + /* Output format of decoder/packetizer */ + es_format_t fmt_out; + + /* + * Buffers allocation + */ + + /* Audio output callbacks */ + aout_buffer_t * ( * pf_aout_buffer_new) ( decoder_t *, int ); + void ( * pf_aout_buffer_del) ( decoder_t *, aout_buffer_t * ); + + /* Video output callbacks */ + picture_t * ( * pf_vout_buffer_new) ( decoder_t * ); + void ( * pf_vout_buffer_del) ( decoder_t *, picture_t * ); + + + /* Private structure for the owner of the decoder */ + decoder_owner_sys_t *p_owner; }; /** @@ -79,22 +107,12 @@ struct encoder_t block_t * ( * pf_encode_audio )( encoder_t *, aout_buffer_t * ); /* Properties of the input data fed to the encoder */ - union { - audio_sample_format_t audio; - video_frame_format_t video; - } format; + es_format_t fmt_in; /* Properties of the output of the encoder */ - vlc_fourcc_t i_fourcc; - int i_bitrate; - - int i_extra_data; - uint8_t *p_extra_data; + es_format_t fmt_out; /* FIXME: move these to the ffmpeg encoder */ - int i_frame_rate; - int i_frame_rate_base; - int i_aspect; int i_key_int; int i_b_frames; int i_vtolerance; diff --git a/include/vlc_common.h b/include/vlc_common.h index 20398d00a7..1aed266348 100644 --- a/include/vlc_common.h +++ b/include/vlc_common.h @@ -3,7 +3,7 @@ * Collection of useful common types and macros definitions ***************************************************************************** * Copyright (C) 1998, 1999, 2000 VideoLAN - * $Id: vlc_common.h,v 1.85 2003/10/29 17:32:54 zorglub Exp $ + * $Id: vlc_common.h,v 1.86 2003/11/16 21:07:30 gbazin Exp $ * * Authors: Samuel Hocevar * Vincent Seguin @@ -229,14 +229,17 @@ typedef struct aout_sys_t aout_sys_t; typedef struct aout_fifo_t aout_fifo_t; typedef struct aout_input_t aout_input_t; typedef struct aout_buffer_t aout_buffer_t; -typedef struct audio_sample_format_t audio_sample_format_t; +typedef struct audio_format_t audio_format_t; +typedef audio_format_t audio_sample_format_t; typedef struct audio_date_t audio_date_t; +typedef struct aout_filter_t aout_filter_t; /* Video */ typedef struct vout_thread_t vout_thread_t; typedef struct vout_sys_t vout_sys_t; typedef struct chroma_sys_t chroma_sys_t; -typedef struct video_frame_format_t video_frame_format_t; +typedef struct video_format_t video_format_t; +typedef video_format_t video_frame_format_t; typedef struct picture_t picture_t; typedef struct picture_sys_t picture_sys_t; typedef struct picture_heap_t picture_heap_t; diff --git a/include/vlc_video.h b/include/vlc_video.h index 66b3564f1c..70aedd27e5 100644 --- a/include/vlc_video.h +++ b/include/vlc_video.h @@ -4,7 +4,7 @@ * includes all common video types and constants. ***************************************************************************** * Copyright (C) 1999, 2000 VideoLAN - * $Id: vlc_video.h,v 1.5 2003/10/24 21:27:06 gbazin Exp $ + * $Id: vlc_video.h,v 1.6 2003/11/16 21:07:30 gbazin Exp $ * * Authors: Vincent Seguin * @@ -28,7 +28,7 @@ /** * Description of a video frame */ -struct video_frame_format_t +struct video_format_t { vlc_fourcc_t i_chroma; /**< picture chroma */ unsigned int i_aspect; /**< aspect ratio */ @@ -42,6 +42,8 @@ struct video_frame_format_t unsigned int i_bits_per_pixel; /**< number of bits per pixel */ + unsigned int i_frame_rate; /**< frame rate numerator */ + unsigned int i_frame_rate_base; /**< frame rate denominator */ }; /** diff --git a/modules/codec/a52.c b/modules/codec/a52.c index 8ea4310939..7f6b1f1446 100644 --- a/modules/codec/a52.c +++ b/modules/codec/a52.c @@ -1,8 +1,8 @@ /***************************************************************************** - * a52.c: A/52 basic parser + * a52.c: parse A/52 audio sync info and packetize the stream ***************************************************************************** * Copyright (C) 2001-2002 VideoLAN - * $Id: a52.c,v 1.28 2003/10/23 20:51:20 gbazin Exp $ + * $Id: a52.c,v 1.29 2003/11/16 21:07:30 gbazin Exp $ * * Authors: Stéphane Borel * Christophe Massiot @@ -29,13 +29,10 @@ #include #include #include /* memcpy() */ -#include #include #include #include -#include -#include #include "vlc_block_helper.h" @@ -52,33 +49,16 @@ struct decoder_sys_t /* * Input properties */ - int i_state; + int i_state; - block_t *p_chain; block_bytestream_t bytestream; - /* - * Decoder output properties - */ - aout_instance_t * p_aout; /* opaque */ - aout_input_t * p_aout_input; /* opaque */ - audio_sample_format_t aout_format; - aout_buffer_t * p_aout_buffer; /* current aout buffer being filled */ - - /* - * Packetizer output properties - */ - sout_packetizer_input_t *p_sout_input; - sout_format_t sout_format; - sout_buffer_t * p_sout_buffer; /* current sout buffer */ - /* * Common properties */ - uint8_t *p_out_buffer; /* output buffer */ - audio_date_t end_date; + audio_date_t end_date; - mtime_t pts; + mtime_t i_pts; int i_frame_size, i_bit_rate; unsigned int i_rate, i_channels, i_channels_conf; @@ -89,7 +69,9 @@ enum { STATE_NOSYNC, STATE_SYNC, STATE_HEADER, - STATE_DATA + STATE_NEXT_SYNC, + STATE_GET_DATA, + STATE_SEND_DATA }; /**************************************************************************** @@ -97,17 +79,14 @@ enum { ****************************************************************************/ static int OpenDecoder ( vlc_object_t * ); static int OpenPacketizer( vlc_object_t * ); - -static int InitDecoder ( decoder_t * ); -static int RunDecoder ( decoder_t *, block_t * ); -static int EndDecoder ( decoder_t * ); +static void CloseDecoder ( vlc_object_t * ); +static void *DecodeBlock ( decoder_t *, block_t ** ); static int SyncInfo ( const byte_t *, int *, int *, int *,int * ); -static int GetOutBuffer ( decoder_t *, uint8_t ** ); -static int GetAoutBuffer( decoder_t *, aout_buffer_t ** ); -static int GetSoutBuffer( decoder_t *, sout_buffer_t ** ); -static int SendOutBuffer( decoder_t * ); +static uint8_t *GetOutBuffer ( decoder_t *, void ** ); +static aout_buffer_t *GetAoutBuffer( decoder_t * ); +static block_t *GetSoutBuffer( decoder_t * ); /***************************************************************************** * Module descriptor @@ -115,12 +94,12 @@ static int SendOutBuffer( decoder_t * ); vlc_module_begin(); set_description( _("A/52 parser") ); set_capability( "decoder", 100 ); - set_callbacks( OpenDecoder, NULL ); + set_callbacks( OpenDecoder, CloseDecoder ); add_submodule(); set_description( _("A/52 audio packetizer") ); set_capability( "packetizer", 10 ); - set_callbacks( OpenPacketizer, NULL ); + set_callbacks( OpenPacketizer, CloseDecoder ); vlc_module_end(); /***************************************************************************** @@ -129,25 +108,38 @@ vlc_module_end(); static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; + decoder_sys_t *p_sys; - if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('a','5','2',' ') - && p_dec->p_fifo->i_fourcc != VLC_FOURCC('a','5','2','b') ) + if( p_dec->fmt_in.i_codec != VLC_FOURCC('a','5','2',' ') + && p_dec->fmt_in.i_codec != VLC_FOURCC('a','5','2','b') ) { return VLC_EGENERIC; } - p_dec->pf_init = InitDecoder; - p_dec->pf_decode = RunDecoder; - p_dec->pf_end = EndDecoder; - /* Allocate the memory needed to store the decoder's structure */ - if( ( p_dec->p_sys = + if( ( p_dec->p_sys = p_sys = (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL ) { msg_Err( p_dec, "out of memory" ); return VLC_EGENERIC; } - p_dec->p_sys->b_packetizer = VLC_FALSE; + + /* Misc init */ + p_sys->b_packetizer = VLC_FALSE; + p_sys->i_state = STATE_NOSYNC; + aout_DateSet( &p_sys->end_date, 0 ); + + p_sys->bytestream = block_BytestreamInit( p_dec ); + + /* Set output properties */ + p_dec->fmt_out.i_cat = AUDIO_ES; + p_dec->fmt_out.i_codec = VLC_FOURCC('a','5','2',' '); + + /* Set callback */ + p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **)) + DecodeBlock; + p_dec->pf_packetize = (block_t *(*)(decoder_t *, block_t **)) + DecodeBlock; return VLC_SUCCESS; } @@ -163,68 +155,38 @@ static int OpenPacketizer( vlc_object_t *p_this ) return i_ret; } -/***************************************************************************** - * InitDecoder: Initalize the decoder - *****************************************************************************/ -static int InitDecoder( decoder_t *p_dec ) -{ - p_dec->p_sys->i_state = STATE_NOSYNC; - - p_dec->p_sys->p_out_buffer = NULL; - aout_DateSet( &p_dec->p_sys->end_date, 0 ); - - p_dec->p_sys->p_aout = NULL; - p_dec->p_sys->p_aout_input = NULL; - p_dec->p_sys->p_aout_buffer = NULL; - p_dec->p_sys->aout_format.i_format = VLC_FOURCC('a','5','2',' '); - - p_dec->p_sys->p_sout_input = NULL; - p_dec->p_sys->p_sout_buffer = NULL; - p_dec->p_sys->sout_format.i_cat = AUDIO_ES; - p_dec->p_sys->sout_format.i_fourcc = VLC_FOURCC( 'a', '5', '2', ' ' ); - - p_dec->p_sys->p_chain = NULL; - - return VLC_SUCCESS; -} - /**************************************************************************** - * RunDecoder: the whole thing + * DecodeBlock: the whole thing **************************************************************************** * This function is called just after the thread is launched. ****************************************************************************/ -static int RunDecoder( decoder_t *p_dec, block_t *p_block ) +static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; uint8_t p_header[A52_HEADER_SIZE]; + uint8_t *p_buf; + void *p_out_buffer; - if( !aout_DateGet( &p_sys->end_date ) && !p_block->i_pts ) + if( !pp_block || !*pp_block ) return NULL; + + if( !aout_DateGet( &p_sys->end_date ) && !(*pp_block)->i_pts ) { /* We've just started the stream, wait for the first PTS. */ - block_Release( p_block ); - return VLC_SUCCESS; + block_Release( *pp_block ); + return NULL; } - if( p_block->b_discontinuity ) + if( (*pp_block)->b_discontinuity ) { - p_sys->i_state = STATE_SYNC; + p_sys->i_state = STATE_NOSYNC; } - if( p_sys->p_chain ) - { - block_ChainAppend( &p_sys->p_chain, p_block ); - } - else - { - block_ChainAppend( &p_sys->p_chain, p_block ); - p_sys->bytestream = block_BytestreamInit( p_dec, p_sys->p_chain, 0 ); - } + block_BytestreamPush( &p_sys->bytestream, *pp_block ); while( 1 ) { switch( p_sys->i_state ) { - case STATE_NOSYNC: while( block_PeekBytes( &p_sys->bytestream, p_header, 2 ) == VLC_SUCCESS ) @@ -238,30 +200,21 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) } if( p_sys->i_state != STATE_SYNC ) { - if( block_PeekByte( &p_sys->bytestream, p_header ) - == VLC_SUCCESS && p_header[0] == 0x0b ) - { - /* Start of a sync word, need more data */ - return VLC_SUCCESS; - } - - block_ChainRelease( p_sys->p_chain ); - p_sys->p_chain = NULL; + block_BytestreamFlush( &p_sys->bytestream ); /* Need more data */ - return VLC_SUCCESS; + return NULL; } case STATE_SYNC: /* New frame, set the Presentation Time Stamp */ - p_sys->pts = p_sys->bytestream.p_block->i_pts; - if( p_sys->pts != 0 && - p_sys->pts != aout_DateGet( &p_sys->end_date ) ) + p_sys->i_pts = p_sys->bytestream.p_block->i_pts; + if( p_sys->i_pts != 0 && + p_sys->i_pts != aout_DateGet( &p_sys->end_date ) ) { - aout_DateSet( &p_sys->end_date, p_sys->pts ); + aout_DateSet( &p_sys->end_date, p_sys->i_pts ); } p_sys->i_state = STATE_HEADER; - break; case STATE_HEADER: /* Get A/52 frame header (A52_HEADER_SIZE bytes) */ @@ -269,7 +222,7 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) A52_HEADER_SIZE ) != VLC_SUCCESS ) { /* Need more data */ - return VLC_SUCCESS; + return NULL; } /* Check if frame is valid and get frame info */ @@ -285,247 +238,160 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) p_sys->i_state = STATE_NOSYNC; break; } - p_sys->i_state = STATE_DATA; + p_sys->i_state = STATE_NEXT_SYNC; - case STATE_DATA: - /* TODO: If p_block == NULL, flush the buffer without checking the + case STATE_NEXT_SYNC: + /* TODO: If pp_block == NULL, flush the buffer without checking the * next sync word */ - /* Check if next expected frame contains the sync word */ - if( block_PeekOffsetBytes( &p_sys->bytestream, - p_sys->i_frame_size, p_header, 2 ) - != VLC_SUCCESS ) - { - /* Need more data */ - return VLC_SUCCESS; - } - - if( p_header[0] != 0x0b || p_header[1] != 0x77 ) - { - msg_Dbg( p_dec, "emulated sync word " - "(no sync on following frame)" ); - p_sys->i_state = STATE_NOSYNC; - block_SkipByte( &p_sys->bytestream ); - break; + /* Check if next expected frame contains the sync word */ + if( block_PeekOffsetBytes( &p_sys->bytestream, + p_sys->i_frame_size, p_header, 2 ) + != VLC_SUCCESS ) + { + /* Need more data */ + return NULL; } - if( !p_sys->p_out_buffer ) - if( GetOutBuffer( p_dec, &p_sys->p_out_buffer ) != VLC_SUCCESS ) + if( p_header[0] != 0x0b || p_header[1] != 0x77 ) { - return VLC_EGENERIC; + msg_Dbg( p_dec, "emulated sync word " + "(no sync on following frame)" ); + p_sys->i_state = STATE_NOSYNC; + block_SkipByte( &p_sys->bytestream ); + break; } + p_sys->i_state = STATE_SEND_DATA; + break; - /* Copy the whole frame into the buffer */ - if( block_GetBytes( &p_sys->bytestream, p_sys->p_out_buffer, - p_sys->i_frame_size ) != VLC_SUCCESS ) + case STATE_GET_DATA: + /* Make sure we have enough data. + * (Not useful if we went through NEXT_SYNC) */ + if( block_WaitBytes( &p_sys->bytestream, + p_sys->i_frame_size ) != VLC_SUCCESS ) { /* Need more data */ - return VLC_SUCCESS; + return NULL; } + p_sys->i_state = STATE_SEND_DATA; - p_sys->p_chain = block_BytestreamFlush( &p_sys->bytestream ); + case STATE_SEND_DATA: + if( !(p_buf = GetOutBuffer( p_dec, &p_out_buffer )) ) + { + //p_dec->b_error = VLC_TRUE; + return NULL; + } - SendOutBuffer( p_dec ); - p_sys->i_state = STATE_NOSYNC; + /* Copy the whole frame into the buffer. When we reach this point + * we already know we have enough data available. */ + block_GetBytes( &p_sys->bytestream, p_buf, p_sys->i_frame_size ); /* Make sure we don't reuse the same pts twice */ - if( p_sys->pts == p_sys->bytestream.p_block->i_pts ) - p_sys->pts = p_sys->bytestream.p_block->i_pts = 0; - } - } + if( p_sys->i_pts == p_sys->bytestream.p_block->i_pts ) + p_sys->i_pts = p_sys->bytestream.p_block->i_pts = 0; - return VLC_SUCCESS; -} - -/***************************************************************************** - * EndDecoder: clean up the decoder - *****************************************************************************/ -static int EndDecoder( decoder_t *p_dec ) -{ - if( p_dec->p_sys->p_aout_input != NULL ) - { - if( p_dec->p_sys->p_aout_buffer ) - { - aout_DecDeleteBuffer( p_dec->p_sys->p_aout, - p_dec->p_sys->p_aout_input, - p_dec->p_sys->p_aout_buffer ); - } + /* So p_block doesn't get re-added several times */ + *pp_block = block_BytestreamPop( &p_sys->bytestream ); - aout_DecDelete( p_dec->p_sys->p_aout, p_dec->p_sys->p_aout_input ); - } + p_sys->i_state = STATE_NOSYNC; - if( p_dec->p_sys->p_sout_input != NULL ) - { - if( p_dec->p_sys->p_sout_buffer ) - { - sout_BufferDelete( p_dec->p_sys->p_sout_input->p_sout, - p_dec->p_sys->p_sout_buffer ); + return p_out_buffer; } - - sout_InputDelete( p_dec->p_sys->p_sout_input ); } - if( p_dec->p_sys->p_chain ) block_ChainRelease( p_dec->p_sys->p_chain ); - - free( p_dec->p_sys ); - - return VLC_SUCCESS; + return NULL; } /***************************************************************************** - * GetOutBuffer: + * CloseDecoder: clean up the decoder *****************************************************************************/ -static int GetOutBuffer( decoder_t *p_dec, uint8_t **pp_out_buffer ) +static void CloseDecoder( vlc_object_t *p_this ) { + decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys = p_dec->p_sys; - int i_ret; - if( p_sys->b_packetizer ) - { - i_ret = GetSoutBuffer( p_dec, &p_sys->p_sout_buffer ); - *pp_out_buffer = - p_sys->p_sout_buffer ? p_sys->p_sout_buffer->p_buffer : NULL; - } - else - { - i_ret = GetAoutBuffer( p_dec, &p_sys->p_aout_buffer ); - *pp_out_buffer = - p_sys->p_aout_buffer ? p_sys->p_aout_buffer->p_buffer : NULL; - } + block_BytestreamRelease( &p_sys->bytestream ); - return i_ret; + free( p_sys ); } /***************************************************************************** - * GetAoutBuffer: + * GetOutBuffer: *****************************************************************************/ -static int GetAoutBuffer( decoder_t *p_dec, aout_buffer_t **pp_buffer ) +static uint8_t *GetOutBuffer( decoder_t *p_dec, void **pp_out_buffer ) { decoder_sys_t *p_sys = p_dec->p_sys; + uint8_t *p_buf; - if( p_sys->p_aout_input != NULL && - ( p_sys->aout_format.i_rate != p_sys->i_rate - || p_sys->aout_format.i_original_channels != p_sys->i_channels_conf - || (int)p_sys->aout_format.i_bytes_per_frame != p_sys->i_frame_size ) ) + if( p_dec->fmt_out.audio.i_rate != p_sys->i_rate ) { - /* Parameters changed - this should not happen. */ - aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input ); - p_sys->p_aout_input = NULL; - } + msg_Info( p_dec, "A/52 channels:%d samplerate:%d bitrate:%d", + p_sys->i_channels, p_sys->i_rate, p_sys->i_bit_rate ); - /* Creating the audio input if not created yet. */ - if( p_sys->p_aout_input == NULL ) - { - p_sys->aout_format.i_rate = p_sys->i_rate; - p_sys->aout_format.i_original_channels = p_sys->i_channels_conf; - p_sys->aout_format.i_physical_channels - = p_sys->i_channels_conf & AOUT_CHAN_PHYSMASK; - p_sys->aout_format.i_bytes_per_frame = p_sys->i_frame_size; - p_sys->aout_format.i_frame_length = A52_FRAME_NB; aout_DateInit( &p_sys->end_date, p_sys->i_rate ); - aout_DateSet( &p_sys->end_date, p_sys->pts ); - p_sys->p_aout_input = aout_DecNew( p_dec, - &p_sys->p_aout, - &p_sys->aout_format ); - if( p_sys->p_aout_input == NULL ) - { - *pp_buffer = NULL; - return VLC_EGENERIC; - } + aout_DateSet( &p_sys->end_date, p_sys->i_pts ); } - *pp_buffer = aout_DecNewBuffer( p_sys->p_aout, p_sys->p_aout_input, - A52_FRAME_NB ); - if( *pp_buffer == NULL ) + p_dec->fmt_out.audio.i_rate = p_sys->i_rate; + p_dec->fmt_out.audio.i_channels = p_sys->i_channels; + p_dec->fmt_out.audio.i_bitrate = p_sys->i_bit_rate; + p_dec->fmt_out.audio.i_bytes_per_frame = p_sys->i_frame_size; + p_dec->fmt_out.audio.i_frame_length = A52_FRAME_NB; + + p_dec->fmt_out.audio.i_original_channels = p_sys->i_channels_conf; + p_dec->fmt_out.audio.i_physical_channels = + p_sys->i_channels_conf & AOUT_CHAN_PHYSMASK; + + if( p_sys->b_packetizer ) { - return VLC_EGENERIC; + block_t *p_sout_buffer = GetSoutBuffer( p_dec ); + p_buf = p_sout_buffer ? p_sout_buffer->p_buffer : NULL; + *pp_out_buffer = p_sout_buffer; + } + else + { + aout_buffer_t *p_aout_buffer = GetAoutBuffer( p_dec ); + p_buf = p_aout_buffer ? p_aout_buffer->p_buffer : NULL; + *pp_out_buffer = p_aout_buffer; } - (*pp_buffer)->start_date = aout_DateGet( &p_sys->end_date ); - (*pp_buffer)->end_date = - aout_DateIncrement( &p_sys->end_date, A52_FRAME_NB ); - - return VLC_SUCCESS; + return p_buf; } /***************************************************************************** - * GetSoutBuffer: + * GetAoutBuffer: *****************************************************************************/ -static int GetSoutBuffer( decoder_t *p_dec, sout_buffer_t **pp_buffer ) +static aout_buffer_t *GetAoutBuffer( decoder_t *p_dec ) { decoder_sys_t *p_sys = p_dec->p_sys; + aout_buffer_t *p_buf; - if( p_sys->p_sout_input != NULL && - ( p_sys->sout_format.i_sample_rate != (int)p_sys->i_rate - || p_sys->sout_format.i_channels != (int)p_sys->i_channels ) ) - { - /* Parameters changed - this should not happen. */ - } - - /* Creating the sout input if not created yet. */ - if( p_sys->p_sout_input == NULL ) - { - p_sys->sout_format.i_sample_rate = p_sys->i_rate; - p_sys->sout_format.i_channels = p_sys->i_channels; - p_sys->sout_format.i_block_align = 0; - p_sys->sout_format.i_bitrate = p_sys->i_bit_rate; - p_sys->sout_format.i_extra_data = 0; - p_sys->sout_format.p_extra_data = NULL; + p_buf = p_dec->pf_aout_buffer_new( p_dec, A52_FRAME_NB ); + if( p_buf == NULL ) return NULL; - aout_DateInit( &p_sys->end_date, p_sys->i_rate ); - aout_DateSet( &p_sys->end_date, p_sys->pts ); + p_buf->start_date = aout_DateGet( &p_sys->end_date ); + p_buf->end_date = aout_DateIncrement( &p_sys->end_date, A52_FRAME_NB ); - p_sys->p_sout_input = sout_InputNew( p_dec, &p_sys->sout_format ); - if( p_sys->p_sout_input == NULL ) - { - msg_Err( p_dec, "cannot add a new stream" ); - *pp_buffer = NULL; - return VLC_EGENERIC; - } - msg_Info( p_dec, "A/52 channels:%d samplerate:%d bitrate:%d", - p_sys->i_channels, p_sys->i_rate, p_sys->i_bit_rate ); - } - - *pp_buffer = sout_BufferNew( p_sys->p_sout_input->p_sout, - p_sys->i_frame_size ); - if( *pp_buffer == NULL ) - { - return VLC_EGENERIC; - } - - (*pp_buffer)->i_pts = - (*pp_buffer)->i_dts = aout_DateGet( &p_sys->end_date ); - - (*pp_buffer)->i_length = - aout_DateIncrement( &p_sys->end_date, A52_FRAME_NB ) - - (*pp_buffer)->i_pts; - - return VLC_SUCCESS; + return p_buf; } /***************************************************************************** - * SendOutBuffer: + * GetSoutBuffer: *****************************************************************************/ -static int SendOutBuffer( decoder_t *p_dec ) +static block_t *GetSoutBuffer( decoder_t *p_dec ) { decoder_sys_t *p_sys = p_dec->p_sys; + block_t *p_block; - if( p_sys->b_packetizer ) - { - sout_InputSendBuffer( p_sys->p_sout_input, p_sys->p_sout_buffer ); - p_sys->p_sout_buffer = NULL; - } - else - { - /* We have all we need, send the buffer to the aout core. */ - aout_DecPlay( p_sys->p_aout, p_sys->p_aout_input, - p_sys->p_aout_buffer ); - p_sys->p_aout_buffer = NULL; - } + p_block = block_New( p_dec, p_sys->i_frame_size ); + if( p_block == NULL ) return NULL; - p_sys->p_out_buffer = NULL; + p_block->i_pts = p_block->i_dts = aout_DateGet( &p_sys->end_date ); - return VLC_SUCCESS; + p_block->i_length = aout_DateIncrement( &p_sys->end_date, A52_FRAME_NB ) - + p_block->i_pts; + + return p_block; } /***************************************************************************** diff --git a/modules/codec/adpcm.c b/modules/codec/adpcm.c index 5afd36255b..555f08ffe1 100644 --- a/modules/codec/adpcm.c +++ b/modules/codec/adpcm.c @@ -2,7 +2,7 @@ * adpcm.c : adpcm variant audio decoder ***************************************************************************** * Copyright (C) 2001, 2002 VideoLAN - * $Id: adpcm.c,v 1.15 2003/11/05 01:47:40 fenrir Exp $ + * $Id: adpcm.c,v 1.16 2003/11/16 21:07:30 gbazin Exp $ * * Authors: Laurent Aimar * @@ -29,7 +29,6 @@ #include /* malloc(), free() */ #include -#include #include #include @@ -38,15 +37,17 @@ /***************************************************************************** * Module descriptor *****************************************************************************/ -static int Open ( vlc_object_t * ); +static int OpenDecoder( vlc_object_t * ); +static void CloseDecoder( vlc_object_t * ); + +static aout_buffer_t *DecodeBlock( decoder_t *, block_t ** ); vlc_module_begin(); set_description( _("ADPCM audio decoder") ); set_capability( "decoder", 50 ); - set_callbacks( Open, NULL ); + set_callbacks( OpenDecoder, CloseDecoder ); vlc_module_end(); - /***************************************************************************** * Local prototypes *****************************************************************************/ @@ -61,31 +62,19 @@ enum adpcm_codec_e struct decoder_sys_t { - WAVEFORMATEX *p_wf; enum adpcm_codec_e codec; int i_block; int i_samplesperblock; - /* audio output */ - aout_instance_t * p_aout; /* opaque */ - aout_input_t * p_aout_input; /* opaque */ - audio_sample_format_t output_format; - - audio_date_t date; + audio_date_t end_date; }; -static int Init ( decoder_t * ); -static int Decode( decoder_t *, block_t * ); -static int End ( decoder_t * ); - - - -static void DecodeAdpcmMs ( decoder_sys_t *, int16_t *, uint8_t * ); -static void DecodeAdpcmImaWav ( decoder_sys_t *, int16_t *, uint8_t * ); -static void DecodeAdpcmImaQT ( decoder_sys_t *, int16_t *, uint8_t * ); -static void DecodeAdpcmDk4 ( decoder_sys_t *, int16_t *, uint8_t * ); -static void DecodeAdpcmDk3 ( decoder_sys_t *, int16_t *, uint8_t * ); +static void DecodeAdpcmMs ( decoder_t *, int16_t *, uint8_t * ); +static void DecodeAdpcmImaWav( decoder_t *, int16_t *, uint8_t * ); +static void DecodeAdpcmImaQT ( decoder_t *, int16_t *, uint8_t * ); +static void DecodeAdpcmDk4 ( decoder_t *, int16_t *, uint8_t * ); +static void DecodeAdpcmDk3 ( decoder_t *, int16_t *, uint8_t * ); static int pi_channels_maps[6] = { @@ -134,64 +123,48 @@ static int i_adaptation_coeff2[7] = 0, -256, 0, 64, 0, -208, -232 }; - /***************************************************************************** * OpenDecoder: probe the decoder and return score - ***************************************************************************** - * Tries to launch a decoder and return score so that the interface is able - * to choose. *****************************************************************************/ -static int Open( vlc_object_t *p_this ) +static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; + decoder_sys_t *p_sys; - switch( p_dec->p_fifo->i_fourcc ) + switch( p_dec->fmt_in.i_codec ) { case VLC_FOURCC('i','m','a', '4'): /* IMA ADPCM */ case VLC_FOURCC('m','s',0x00,0x02): /* MS ADPCM */ case VLC_FOURCC('m','s',0x00,0x11): /* IMA ADPCM */ case VLC_FOURCC('m','s',0x00,0x61): /* Duck DK4 ADPCM */ case VLC_FOURCC('m','s',0x00,0x62): /* Duck DK3 ADPCM */ - - p_dec->pf_init = Init; - p_dec->pf_decode = Decode; - p_dec->pf_end = End; - - p_dec->p_sys = malloc( sizeof( decoder_sys_t ) ); - return VLC_SUCCESS; - + break; default: return VLC_EGENERIC; } -} - -/***************************************************************************** - * Init: - *****************************************************************************/ -static int Init ( decoder_t *p_dec ) -{ - decoder_sys_t *p_sys = p_dec->p_sys; - WAVEFORMATEX *p_wf; - if( ( p_wf = (WAVEFORMATEX*)p_dec->p_fifo->p_waveformatex ) == NULL ) + /* Allocate the memory needed to store the decoder's structure */ + if( ( p_dec->p_sys = p_sys = + (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL ) { - msg_Err( p_dec, "unknown raw format" ); + msg_Err( p_dec, "out of memory" ); return VLC_EGENERIC; } - if( p_wf->nChannels < 1 || p_wf->nChannels > 2 ) + if( p_dec->fmt_in.audio.i_channels <= 0 || + p_dec->fmt_in.audio.i_channels > 5 ) { - msg_Err( p_dec, "bad channels count(1-2)" ); + msg_Err( p_dec, "bad channels count(1-5)" ); return VLC_EGENERIC; } - if( p_wf->nSamplesPerSec <= 0 ) + + if( p_dec->fmt_in.audio.i_rate <= 0 ) { msg_Err( p_dec, "bad samplerate" ); return VLC_EGENERIC; } - p_sys->p_wf = p_wf; - switch( p_dec->p_fifo->i_fourcc ) + switch( p_dec->fmt_in.i_codec ) { case VLC_FOURCC('i','m','a', '4'): /* IMA ADPCM */ p_sys->codec = ADPCM_IMA_QT; @@ -210,146 +183,152 @@ static int Init ( decoder_t *p_dec ) break; } - if( ( p_sys->i_block = p_wf->nBlockAlign ) <= 0 ) + if( 1 )//( p_sys->i_block = p_wf->nBlockAlign ) <= 0 ) { - p_sys->i_block = p_sys->codec==ADPCM_IMA_QT ? 34*p_wf->nChannels:1024; + p_sys->i_block = (p_sys->codec == ADPCM_IMA_QT) ? + 34 * p_dec->fmt_in.audio.i_channels : 1024; msg_Warn( p_dec, "block size undefined, -> using %d", p_sys->i_block ); } /* calculate samples per block */ switch( p_sys->codec ) { - case ADPCM_IMA_QT: - p_sys->i_samplesperblock = 64; - break; - case ADPCM_IMA_WAV: - p_sys->i_samplesperblock = - 2 * ( p_sys->i_block - 4 * p_wf->nChannels )/ p_wf->nChannels; - break; - case ADPCM_MS: - p_sys->i_samplesperblock = - 2 * (p_sys->i_block - 7 * p_wf->nChannels)/p_wf->nChannels + 2; - break; - case ADPCM_DK4: - p_sys->i_samplesperblock = - 2 * (p_sys->i_block - 4 * p_wf->nChannels)/p_wf->nChannels + 1; - break; - case ADPCM_DK3: - p_wf->nChannels = 2; - p_sys->i_samplesperblock = ( 4 * ( p_sys->i_block - 16 ) + 2 )/ 3; - break; + case ADPCM_IMA_QT: + p_sys->i_samplesperblock = 64; + break; + case ADPCM_IMA_WAV: + p_sys->i_samplesperblock = + 2 * ( p_sys->i_block - 4 * p_dec->fmt_in.audio.i_channels ) / + p_dec->fmt_in.audio.i_channels; + break; + case ADPCM_MS: + p_sys->i_samplesperblock = + 2 * (p_sys->i_block - 7 * p_dec->fmt_in.audio.i_channels) / + p_dec->fmt_in.audio.i_channels + 2; + break; + case ADPCM_DK4: + p_sys->i_samplesperblock = + 2 * (p_sys->i_block - 4 * p_dec->fmt_in.audio.i_channels) / + p_dec->fmt_in.audio.i_channels + 1; + break; + case ADPCM_DK3: + p_dec->fmt_in.audio.i_channels = 2; + p_sys->i_samplesperblock = ( 4 * ( p_sys->i_block - 16 ) + 2 )/ 3; + break; } - msg_Dbg( p_dec, - "format: samplerate:%dHz channels:%d bits/sample:%d blockalign:%d samplesperblock %d", - p_wf->nSamplesPerSec, p_wf->nChannels, - p_wf->wBitsPerSample, p_wf->nBlockAlign, + + msg_Dbg( p_dec, "format: samplerate:%dHz channels:%d bits/sample:%d " + "blockalign:%d samplesperblock %d", + p_dec->fmt_in.audio.i_rate, p_dec->fmt_in.audio.i_channels, + p_dec->fmt_in.audio.i_bitspersample, p_sys->i_block, p_sys->i_samplesperblock ); - p_sys->output_format.i_format = AOUT_FMT_S16_NE; - p_sys->output_format.i_rate = p_wf->nSamplesPerSec; - p_sys->output_format.i_physical_channels = - p_sys->output_format.i_original_channels = - pi_channels_maps[p_wf->nChannels]; + p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE; + p_dec->fmt_out.audio.i_rate = p_dec->fmt_in.audio.i_rate; + p_dec->fmt_out.audio.i_channels = p_dec->fmt_in.audio.i_channels; + p_dec->fmt_out.audio.i_physical_channels = + p_dec->fmt_out.audio.i_original_channels = + pi_channels_maps[p_dec->fmt_in.audio.i_channels]; - p_sys->p_aout = NULL; - p_sys->p_aout_input = aout_DecNew( p_dec, - &p_sys->p_aout, &p_sys->output_format); - if( p_sys->p_aout_input == NULL ) - { - msg_Err( p_dec, "cannot create aout" ); - return VLC_EGENERIC; - } + aout_DateInit( &p_sys->end_date, p_dec->fmt_out.audio.i_rate ); + aout_DateSet( &p_sys->end_date, 0 ); - aout_DateInit( &p_sys->date, p_sys->output_format.i_rate ); - aout_DateSet( &p_sys->date, 0 ); + p_dec->pf_decode_audio = DecodeBlock; return VLC_SUCCESS; } /***************************************************************************** - * Decode: + * DecodeBlock: *****************************************************************************/ -static int Decode( decoder_t *p_dec, block_t *p_block ) +static aout_buffer_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; - mtime_t i_pts = p_block->i_pts; - uint8_t *p_data = p_block->p_buffer; - int i_data = p_block->i_buffer; + block_t *p_block; - while( i_data >= p_sys->i_block ) + if( !pp_block || !*pp_block ) return NULL; + + p_block = *pp_block; + + if( p_block->i_pts != 0 && + p_block->i_pts != aout_DateGet( &p_sys->end_date ) ) + { + aout_DateSet( &p_sys->end_date, p_block->i_pts ); + } + else if( !aout_DateGet( &p_sys->end_date ) ) { - aout_buffer_t *out; + /* We've just started the stream, wait for the first PTS. */ + block_Release( p_block ); + return NULL; + } - if( i_pts != 0 && i_pts != aout_DateGet( &p_sys->date ) ) - { - aout_DateSet( &p_sys->date, i_pts ); - } - else if( !aout_DateGet( &p_sys->date ) ) - { - block_Release( p_block ); - return VLC_SUCCESS; - } - i_pts = 0; + /* Don't re-use the same pts twice */ + p_block->i_pts = 0; + + if( p_block->i_buffer >= p_sys->i_block ) + { + aout_buffer_t *p_out; - out = aout_DecNewBuffer( p_sys->p_aout, - p_sys->p_aout_input, - p_sys->i_samplesperblock ); - if( out == NULL ) + p_out = p_dec->pf_aout_buffer_new( p_dec, p_sys->i_samplesperblock ); + if( p_out == NULL ) { - msg_Err( p_dec, "cannot get aout buffer" ); block_Release( p_block ); - return VLC_EGENERIC; + return NULL; } - out->start_date = aout_DateGet( &p_sys->date ); - out->end_date = aout_DateIncrement( &p_sys->date, - p_sys->i_samplesperblock ); + + p_out->start_date = aout_DateGet( &p_sys->end_date ); + p_out->end_date = + aout_DateIncrement( &p_sys->end_date, p_sys->i_samplesperblock ); switch( p_sys->codec ) { - case ADPCM_IMA_QT: - DecodeAdpcmImaQT( p_sys, (int16_t*)out->p_buffer, p_data ); - break; - case ADPCM_IMA_WAV: - DecodeAdpcmImaWav( p_sys, (int16_t*)out->p_buffer, p_data ); - break; - case ADPCM_MS: - DecodeAdpcmMs( p_sys, (int16_t*)out->p_buffer, p_data ); - break; - case ADPCM_DK4: - DecodeAdpcmDk4( p_sys, (int16_t*)out->p_buffer, p_data ); - break; - case ADPCM_DK3: - DecodeAdpcmDk3( p_sys, (int16_t*)out->p_buffer, p_data ); - break; - default: - break; + case ADPCM_IMA_QT: + DecodeAdpcmImaQT( p_dec, (int16_t*)p_out->p_buffer, + p_block->p_buffer ); + break; + case ADPCM_IMA_WAV: + DecodeAdpcmImaWav( p_dec, (int16_t*)p_out->p_buffer, + p_block->p_buffer ); + break; + case ADPCM_MS: + DecodeAdpcmMs( p_dec, (int16_t*)p_out->p_buffer, + p_block->p_buffer ); + break; + case ADPCM_DK4: + DecodeAdpcmDk4( p_dec, (int16_t*)p_out->p_buffer, + p_block->p_buffer ); + break; + case ADPCM_DK3: + DecodeAdpcmDk3( p_dec, (int16_t*)p_out->p_buffer, + p_block->p_buffer ); + break; + default: + break; } - aout_DecPlay( p_sys->p_aout, p_sys->p_aout_input, out ); - p_data += p_sys->i_block; - i_data -= p_sys->i_block; + p_block->p_buffer += p_out->i_nb_bytes; + p_block->i_buffer -= p_out->i_nb_bytes; + return p_out; } block_Release( p_block ); - return VLC_SUCCESS; + return NULL; } /***************************************************************************** - * End: + * CloseDecoder: *****************************************************************************/ -static int End ( decoder_t *p_dec ) +static void CloseDecoder( vlc_object_t *p_this ) { + decoder_t *p_dec = (decoder_t *)p_this; decoder_sys_t *p_sys = p_dec->p_sys; - if( p_sys->p_aout_input ) - { - aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input ); - } free( p_sys ); - - return VLC_SUCCESS; } +/***************************************************************************** + * Local functions + *****************************************************************************/ #define CLAMP( v, min, max ) \ if( (v) < (min) ) (v) = (min); \ if( (v) > (max) ) (v) = (max) @@ -401,14 +380,16 @@ static int AdpcmMsExpandNibble(adpcm_ms_channel_t *p_channel, return( i_predictor ); } -static void DecodeAdpcmMs( decoder_sys_t *p_sys, int16_t *p_sample, uint8_t *p_buffer ) +static void DecodeAdpcmMs( decoder_t *p_dec, int16_t *p_sample, + uint8_t *p_buffer ) { + decoder_sys_t *p_sys = p_dec->p_sys; adpcm_ms_channel_t channel[2]; int i_nibbles; int b_stereo; int i_block_predictor; - b_stereo = p_sys->p_wf->nChannels == 2 ? 1 : 0; + b_stereo = p_dec->fmt_in.audio.i_channels == 2 ? 1 : 0; GetByte( i_block_predictor ); CLAMP( i_block_predictor, 0, 6 ); @@ -453,8 +434,8 @@ static void DecodeAdpcmMs( decoder_sys_t *p_sys, int16_t *p_sample, uint8_t *p_b *p_sample++ = channel[0].i_sample1; } - for( i_nibbles = 2 *( p_sys->i_block - 7 * p_sys->p_wf->nChannels ); - i_nibbles > 0; i_nibbles -= 2,p_buffer++ ) + for( i_nibbles = 2 * (p_sys->i_block - 7 * p_dec->fmt_in.audio.i_channels); + i_nibbles > 0; i_nibbles -= 2, p_buffer++ ) { *p_sample++ = AdpcmMsExpandNibble( &channel[0], (*p_buffer) >> 4); *p_sample++ = AdpcmMsExpandNibble( &channel[b_stereo ? 1 : 0], @@ -495,13 +476,15 @@ static int AdpcmImaWavExpandNibble(adpcm_ima_wav_channel_t *p_channel, return( p_channel->i_predictor ); } -static void DecodeAdpcmImaWav( decoder_sys_t *p_sys, int16_t *p_sample, uint8_t *p_buffer ) +static void DecodeAdpcmImaWav( decoder_t *p_dec, int16_t *p_sample, + uint8_t *p_buffer ) { + decoder_sys_t *p_sys = p_dec->p_sys; adpcm_ima_wav_channel_t channel[2]; int i_nibbles; int b_stereo; - b_stereo = p_sys->p_wf->nChannels == 2 ? 1 : 0; + b_stereo = p_dec->fmt_in.audio.i_channels == 2 ? 1 : 0; GetWord( channel[0].i_predictor ); GetByte( channel[0].i_step_index ); @@ -562,16 +545,17 @@ static void DecodeAdpcmImaWav( decoder_sys_t *p_sys, int16_t *p_sample, uint8_t /* * Ima4 in QT file */ -static void DecodeAdpcmImaQT( decoder_sys_t *p_sys, int16_t *p_sample, uint8_t *p_buffer ) +static void DecodeAdpcmImaQT( decoder_t *p_dec, int16_t *p_sample, + uint8_t *p_buffer ) { adpcm_ima_wav_channel_t channel[2]; int i_nibbles; int i_ch; int i_step; - i_step = p_sys->p_wf->nChannels; + i_step = p_dec->fmt_in.audio.i_channels; - for( i_ch = 0; i_ch < p_sys->p_wf->nChannels; i_ch++ ) + for( i_ch = 0; i_ch < p_dec->fmt_in.audio.i_channels; i_ch++ ) { /* load preambule */ channel[i_ch].i_predictor = (int16_t)((( ( p_buffer[0] << 1 )|( p_buffer[1] >> 7 ) ))<<7); @@ -599,14 +583,15 @@ static void DecodeAdpcmImaQT( decoder_sys_t *p_sys, int16_t *p_sample, uint8_t * /* * Dk4 */ - -static void DecodeAdpcmDk4( decoder_sys_t *p_sys, int16_t *p_sample, uint8_t *p_buffer ) +static void DecodeAdpcmDk4( decoder_t *p_dec, int16_t *p_sample, + uint8_t *p_buffer ) { + decoder_sys_t *p_sys = p_dec->p_sys; adpcm_ima_wav_channel_t channel[2]; int i_nibbles; int b_stereo; - b_stereo = p_sys->p_wf->nChannels == 2 ? 1 : 0; + b_stereo = p_dec->fmt_in.audio.i_channels == 2 ? 1 : 0; GetWord( channel[0].i_predictor ); GetByte( channel[0].i_step_index ); @@ -644,8 +629,10 @@ static void DecodeAdpcmDk4( decoder_sys_t *p_sys, int16_t *p_sample, uint8_t *p_ /* * Dk3 */ -static void DecodeAdpcmDk3( decoder_sys_t *p_sys, int16_t *p_sample, uint8_t *p_buffer ) +static void DecodeAdpcmDk3( decoder_t *p_dec, int16_t *p_sample, + uint8_t *p_buffer ) { + decoder_sys_t *p_sys = p_dec->p_sys; uint8_t *p_end = &p_buffer[p_sys->i_block]; adpcm_ima_wav_channel_t sum; adpcm_ima_wav_channel_t diff; @@ -705,4 +692,3 @@ static void DecodeAdpcmDk3( decoder_sys_t *p_sys, int16_t *p_sample, uint8_t *p_ } } } - diff --git a/modules/codec/araw.c b/modules/codec/araw.c index 7e0b85e7e4..ae7dd17d75 100644 --- a/modules/codec/araw.c +++ b/modules/codec/araw.c @@ -2,7 +2,7 @@ * araw.c: Pseudo audio decoder; for raw pcm data ***************************************************************************** * Copyright (C) 2001, 2003 VideoLAN - * $Id: araw.c,v 1.23 2003/11/08 04:57:56 fenrir Exp $ + * $Id: araw.c,v 1.24 2003/11/16 21:07:30 gbazin Exp $ * * Authors: Laurent Aimar * @@ -25,92 +25,48 @@ * Preamble *****************************************************************************/ #include /* malloc(), free() */ -#include -#include +#include #include #include -#include - #include "codecs.h" /***************************************************************************** * Module descriptor *****************************************************************************/ -static int DecoderOpen ( vlc_object_t * ); +static int DecoderOpen ( vlc_object_t * ); +static void DecoderClose( vlc_object_t * ); -static int EncoderOpen ( vlc_object_t *p_this ); -static void EncoderClose ( vlc_object_t *p_this ); +static int EncoderOpen ( vlc_object_t * ); +static void EncoderClose( vlc_object_t * ); vlc_module_begin(); /* audio decoder module */ set_description( _("Raw/Log Audio decoder") ); set_capability( "decoder", 50 ); - set_callbacks( DecoderOpen, NULL ); + set_callbacks( DecoderOpen, DecoderClose ); /* audio encoder submodule */ add_submodule(); set_description( _("Raw audio encoder") ); - set_capability( "audio encoder", 10 ); + set_capability( "encoder", 10 ); set_callbacks( EncoderOpen, EncoderClose ); vlc_module_end(); - /***************************************************************************** * Local prototypes *****************************************************************************/ -static int DecoderInit ( decoder_t * ); -static int DecoderDecode( decoder_t *, block_t * ); -static int DecoderEnd ( decoder_t * ); +static aout_buffer_t *DecodeBlock( decoder_t *, block_t ** ); +static block_t *EncoderEncode( encoder_t *, aout_buffer_t * ); struct decoder_sys_t { - WAVEFORMATEX *p_wf; - - int16_t *p_logtos16; // used with m/alaw to int16_t - - /* Output properties */ - aout_instance_t * p_aout; /* opaque */ - aout_input_t * p_aout_input; /* opaque */ - audio_sample_format_t output_format; + int16_t *p_logtos16; /* used with m/alaw to int16_t */ - audio_date_t date; + audio_date_t end_date; }; - -static block_t *EncoderEncode( encoder_t *, aout_buffer_t *p_aout_buf ); - -/***************************************************************************** - * DecoderOpen: probe the decoder and return score - ***************************************************************************** - * Tries to launch a decoder and return score so that the interface is able - * to choose. - *****************************************************************************/ -static int DecoderOpen( vlc_object_t *p_this ) -{ - decoder_t *p_dec = (decoder_t*)p_this; - - switch( p_dec->p_fifo->i_fourcc ) - { - case VLC_FOURCC('a','r','a','w'): /* from wav/avi/asf file */ - case VLC_FOURCC('t','w','o','s'): /* _signed_ big endian samples (mov)*/ - case VLC_FOURCC('s','o','w','t'): /* _signed_ little endian samples (mov)*/ - - case VLC_FOURCC('a','l','a','w'): - case VLC_FOURCC('u','l','a','w'): - p_dec->pf_init = DecoderInit; - p_dec->pf_decode = DecoderDecode; - p_dec->pf_end = DecoderEnd; - - p_dec->p_sys = malloc( sizeof( decoder_sys_t ) ); - return VLC_SUCCESS; - - default: - return VLC_EGENERIC; - } -} - static int pi_channels_maps[6] = { 0, @@ -195,264 +151,267 @@ static int16_t alawtos16[256] = }; /***************************************************************************** - * DecoderInit: initialize data before entering main loop + * DecoderOpen: probe the decoder and return score *****************************************************************************/ -static int DecoderInit( decoder_t *p_dec ) +static int DecoderOpen( vlc_object_t *p_this ) { - decoder_sys_t *p_sys = p_dec->p_sys; + decoder_t *p_dec = (decoder_t*)p_this; + decoder_sys_t *p_sys; + + switch( p_dec->fmt_in.i_codec ) + { + /* from wav/avi/asf file */ + case VLC_FOURCC('a','r','a','w'): + /* _signed_ big endian samples (mov)*/ + case VLC_FOURCC('t','w','o','s'): + /* _signed_ little endian samples (mov)*/ + case VLC_FOURCC('s','o','w','t'): + + case VLC_FOURCC('a','l','a','w'): + case VLC_FOURCC('u','l','a','w'): + break; + + default: + return VLC_EGENERIC; + } - WAVEFORMATEX *p_wf; - if( ( p_wf = (WAVEFORMATEX*)p_dec->p_fifo->p_waveformatex ) == NULL ) + /* Allocate the memory needed to store the decoder's structure */ + if( ( p_dec->p_sys = p_sys = + (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL ) { - msg_Err( p_dec, "unknown raw format" ); + msg_Err( p_dec, "out of memory" ); return VLC_EGENERIC; } - if( p_wf->nChannels <= 0 || p_wf->nChannels > 5 ) + if( p_dec->fmt_in.audio.i_channels <= 0 || + p_dec->fmt_in.audio.i_channels > 5 ) { msg_Err( p_dec, "bad channels count(1-5)" ); return VLC_EGENERIC; } - if( p_wf->nSamplesPerSec <= 0 ) + + if( p_dec->fmt_in.audio.i_rate <= 0 ) { msg_Err( p_dec, "bad samplerate" ); return VLC_EGENERIC; } - p_sys->p_wf = p_wf; p_sys->p_logtos16 = NULL; - /* fixing some values */ - if( p_wf->nBlockAlign == 0 && - ( p_wf->wFormatTag == WAVE_FORMAT_PCM || - p_wf->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ) ) - { - p_wf->nBlockAlign = ( p_wf->wBitsPerSample + 7 ) / 8 * p_wf->nChannels; - } + msg_Dbg( p_dec, "samplerate:%dHz channels:%d bits/sample:%d", + p_dec->fmt_in.audio.i_rate, p_dec->fmt_in.audio.i_channels, + p_dec->fmt_in.audio.i_bitspersample ); - msg_Dbg( p_dec, - "samplerate:%dHz channels:%d bits/sample:%d blockalign:%d", - p_wf->nSamplesPerSec, p_wf->nChannels, - p_wf->wBitsPerSample, p_wf->nBlockAlign ); - - if( p_wf->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ) + if( 0 /* p_wf->wFormatTag == WAVE_FORMAT_IEEE_FLOAT */ ) { - switch( ( p_wf->wBitsPerSample + 7 ) / 8 ) + switch( ( p_dec->fmt_in.audio.i_bitspersample + 7 ) / 8 ) { - case( 4 ): - p_sys->output_format.i_format = VLC_FOURCC('f','l','3','2'); - break; - case( 8 ): - p_sys->output_format.i_format = VLC_FOURCC('f','l','6','4'); - break; - default: - msg_Err( p_dec, "bad parameters(bits/sample)" ); - return VLC_EGENERIC; + case 4: + p_dec->fmt_out.i_codec = VLC_FOURCC('f','l','3','2'); + break; + case 8: + p_dec->fmt_out.i_codec = VLC_FOURCC('f','l','6','4'); + break; + default: + msg_Err( p_dec, "bad parameters(bits/sample)" ); + return VLC_EGENERIC; } } else { - if( p_dec->p_fifo->i_fourcc == VLC_FOURCC( 't', 'w', 'o', 's' ) ) + if( p_dec->fmt_in.i_codec == VLC_FOURCC( 't', 'w', 'o', 's' ) ) { - switch( ( p_wf->wBitsPerSample + 7 ) / 8 ) + switch( ( p_dec->fmt_in.audio.i_bitspersample + 7 ) / 8 ) { - case( 1 ): - p_sys->output_format.i_format = VLC_FOURCC('s','8',' ',' '); - break; - case( 2 ): - p_sys->output_format.i_format = VLC_FOURCC('s','1','6','b'); - break; - case( 3 ): - p_sys->output_format.i_format = VLC_FOURCC('s','2','4','b'); - break; - case( 4 ): - p_sys->output_format.i_format = VLC_FOURCC('s','3','2','b'); - break; - default: - msg_Err( p_dec, "bad parameters(bits/sample)" ); - return VLC_EGENERIC; + case 1: + p_dec->fmt_out.i_codec = VLC_FOURCC('s','8',' ',' '); + break; + case 2: + p_dec->fmt_out.i_codec = VLC_FOURCC('s','1','6','b'); + break; + case 3: + p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','b'); + break; + case 4: + p_dec->fmt_out.i_codec = VLC_FOURCC('s','3','2','b'); + break; + default: + msg_Err( p_dec, "bad parameters(bits/sample)" ); + return VLC_EGENERIC; } } - else if( p_dec->p_fifo->i_fourcc == VLC_FOURCC( 's', 'o', 'w', 't' ) ) + else if( p_dec->fmt_in.i_codec == VLC_FOURCC( 's', 'o', 'w', 't' ) ) { - switch( ( p_wf->wBitsPerSample + 7 ) / 8 ) + switch( ( p_dec->fmt_in.audio.i_bitspersample + 7 ) / 8 ) { - case( 1 ): - p_sys->output_format.i_format = VLC_FOURCC('s','8',' ',' '); - break; - case( 2 ): - p_sys->output_format.i_format = VLC_FOURCC('s','1','6','l'); - break; - case( 3 ): - p_sys->output_format.i_format = VLC_FOURCC('s','2','4','l'); - break; - case( 4 ): - p_sys->output_format.i_format = VLC_FOURCC('s','3','2','l'); - break; - default: - msg_Err( p_dec, "bad parameters(bits/sample)" ); - return VLC_EGENERIC; + case 1: + p_dec->fmt_out.i_codec = VLC_FOURCC('s','8',' ',' '); + break; + case 2: + p_dec->fmt_out.i_codec = VLC_FOURCC('s','1','6','l'); + break; + case 3: + p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','l'); + break; + case 4: + p_dec->fmt_out.i_codec = VLC_FOURCC('s','3','2','l'); + break; + default: + msg_Err( p_dec, "bad parameters(bits/sample)" ); + return VLC_EGENERIC; } } - else if( p_dec->p_fifo->i_fourcc == VLC_FOURCC( 'a', 'r', 'a', 'w' ) ) + else if( p_dec->fmt_in.i_codec == VLC_FOURCC( 'a', 'r', 'a', 'w' ) ) { - switch( ( p_wf->wBitsPerSample + 7 ) / 8 ) + switch( ( p_dec->fmt_in.audio.i_bitspersample + 7 ) / 8 ) { - case( 1 ): - p_sys->output_format.i_format = VLC_FOURCC('u','8',' ',' '); - break; - case( 2 ): - p_sys->output_format.i_format = VLC_FOURCC('s','1','6','l'); - break; - case( 3 ): - p_sys->output_format.i_format = VLC_FOURCC('s','2','4','l'); - break; - case( 4 ): - p_sys->output_format.i_format = VLC_FOURCC('s','3','2','l'); - break; - default: - msg_Err( p_dec, "bad parameters(bits/sample)" ); - return VLC_EGENERIC; + case 1: + p_dec->fmt_out.i_codec = VLC_FOURCC('u','8',' ',' '); + break; + case 2: + p_dec->fmt_out.i_codec = VLC_FOURCC('s','1','6','l'); + break; + case 3: + p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','l'); + break; + case 4: + p_dec->fmt_out.i_codec = VLC_FOURCC('s','3','2','l'); + break; + default: + msg_Err( p_dec, "bad parameters(bits/sample)" ); + return VLC_EGENERIC; } } - else if( p_dec->p_fifo->i_fourcc == VLC_FOURCC( 'a', 'l', 'a', 'w' ) ) + else if( p_dec->fmt_in.i_codec == VLC_FOURCC( 'a', 'l', 'a', 'w' ) ) { - p_sys->output_format.i_format = AOUT_FMT_S16_NE; + p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE; p_sys->p_logtos16 = alawtos16; - p_wf->wBitsPerSample = 8; + p_dec->fmt_in.audio.i_bitspersample = 8; } - else if( p_dec->p_fifo->i_fourcc == VLC_FOURCC( 'u', 'l', 'a', 'w' ) ) + else if( p_dec->fmt_in.i_codec == VLC_FOURCC( 'u', 'l', 'a', 'w' ) ) { - p_sys->output_format.i_format = AOUT_FMT_S16_NE; + p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE; p_sys->p_logtos16 = ulawtos16; - p_wf->wBitsPerSample = 8; + p_dec->fmt_in.audio.i_bitspersample = 8; } } - p_sys->output_format.i_rate = p_wf->nSamplesPerSec; - p_sys->output_format.i_physical_channels = - p_sys->output_format.i_original_channels = pi_channels_maps[p_wf->nChannels]; + /* Set output properties */ + p_dec->fmt_out.i_cat = AUDIO_ES; + p_dec->fmt_out.audio.i_rate = p_dec->fmt_in.audio.i_rate; + p_dec->fmt_out.audio.i_channels = p_dec->fmt_in.audio.i_channels; + p_dec->fmt_out.audio.i_physical_channels = + p_dec->fmt_out.audio.i_original_channels = + pi_channels_maps[p_dec->fmt_in.audio.i_channels]; - p_sys->p_aout = NULL; - p_sys->p_aout_input = aout_DecNew( p_dec, &p_sys->p_aout, - &p_sys->output_format ); - if( p_sys->p_aout_input == NULL ) - { - msg_Err( p_dec, "cannot create aout" ); - return VLC_EGENERIC; - } + aout_DateInit( &p_sys->end_date, p_dec->fmt_out.audio.i_rate ); + aout_DateSet( &p_sys->end_date, 0 ); - aout_DateInit( &p_sys->date, p_sys->output_format.i_rate ); - aout_DateSet( &p_sys->date, 0 ); + p_dec->pf_decode_audio = DecodeBlock; return VLC_SUCCESS; } -/***************************************************************************** - * DecoderDecode: decodes a frame - *****************************************************************************/ -static int DecoderDecode( decoder_t *p_dec, block_t *p_block ) +/**************************************************************************** + * DecodeBlock: the whole thing + **************************************************************************** + * This function must be fed with whole samples (see nBlockAlign). + ****************************************************************************/ +static aout_buffer_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; - int i_size = p_block->i_buffer; - uint8_t *p = p_block->p_buffer; - int i_samples; // per channels + block_t *p_block; + int i_samples; - if( p_sys->p_wf->nBlockAlign > 0 ) - { - /* Align it (it should already be aligned by demuxer) */ - i_size -= i_size % p_sys->p_wf->nBlockAlign; - } - if( i_size < p_sys->p_wf->nBlockAlign ) - { - block_Release( p_block ); - return VLC_SUCCESS; - } - i_samples = i_size / ( ( p_sys->p_wf->wBitsPerSample + 7 ) / 8 ) / - p_sys->p_wf->nChannels; + if( !pp_block || !*pp_block ) return NULL; + + p_block = *pp_block; - if( p_block->i_pts != 0 && p_block->i_pts != aout_DateGet( &p_sys->date ) ) + if( p_block->i_pts != 0 && + p_block->i_pts != aout_DateGet( &p_sys->end_date ) ) { - aout_DateSet( &p_sys->date, p_block->i_pts ); + aout_DateSet( &p_sys->end_date, p_block->i_pts ); } - else if( !aout_DateGet( &p_sys->date ) ) + else if( !aout_DateGet( &p_sys->end_date ) ) { + /* We've just started the stream, wait for the first PTS. */ block_Release( p_block ); - return VLC_SUCCESS; + return NULL; } - while( i_samples > 0 ) + /* Don't re-use the same pts twice */ + p_block->i_pts = 0; + + i_samples = p_block->i_buffer * 8 / p_dec->fmt_in.audio.i_bitspersample / + p_dec->fmt_in.audio.i_channels; + + + /* Create chunks of max 1024 samples */ + if( i_samples > 0 ) { - int i_copy = __MIN( i_samples, 1024 ); - aout_buffer_t *out; + aout_buffer_t *p_out; + i_samples = __MIN( i_samples, 1024 ); - out = aout_DecNewBuffer( p_sys->p_aout, p_sys->p_aout_input, i_copy ); - if( out == NULL ) + p_out = p_dec->pf_aout_buffer_new( p_dec, i_samples ); + if( p_out == NULL ) { - msg_Err( p_dec, "cannot get aout buffer" ); block_Release( p_block ); - return VLC_EGENERIC; + return NULL; } - out->start_date = aout_DateGet( &p_sys->date ); - out->end_date = aout_DateIncrement( &p_sys->date, i_copy ); + p_out->start_date = aout_DateGet( &p_sys->end_date ); + p_out->end_date = aout_DateIncrement( &p_sys->end_date, i_samples ); if( p_sys->p_logtos16 ) { - int16_t *s = (int16_t*)out->p_buffer; + int16_t *s = (int16_t*)p_out->p_buffer; unsigned int i; - for( i = 0; i < out->i_nb_bytes / 2; i++ ) + for( i = 0; i < p_out->i_nb_bytes / 2; i++ ) { - *s++ = p_sys->p_logtos16[*p++]; + *s++ = p_sys->p_logtos16[*p_block->p_buffer++]; + p_block->i_buffer++; } } else { - memcpy( out->p_buffer, p, out->i_nb_bytes ); - - p += out->i_nb_bytes; + memcpy( p_out->p_buffer, p_block->p_buffer, p_out->i_nb_bytes ); + p_block->p_buffer += p_out->i_nb_bytes; + p_block->i_buffer -= p_out->i_nb_bytes; } - aout_DecPlay( p_sys->p_aout, p_sys->p_aout_input, out ); - - i_samples -= i_copy; + return p_out; } + block_Release( p_block ); - return VLC_SUCCESS; + return NULL; } /***************************************************************************** - * DecoderEnd : faad decoder thread destruction + * DecoderClose: decoder destruction *****************************************************************************/ -static int DecoderEnd( decoder_t *p_dec ) +static void DecoderClose( vlc_object_t *p_this ) { - decoder_sys_t *p_sys = p_dec->p_sys; + decoder_t *p_dec = (decoder_t *)p_this; - if( p_sys->p_aout_input ) - { - aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input ); - } - free( p_sys ); - - return VLC_SUCCESS; + free( p_dec->p_sys ); } /***************************************************************************** * EncoderOpen: *****************************************************************************/ -static int EncoderOpen ( vlc_object_t *p_this ) +static int EncoderOpen( vlc_object_t *p_this ) { encoder_t *p_enc = (encoder_t *)p_this; - if( p_enc->format.audio.i_format != VLC_FOURCC( 's', '1', '6', 'b' ) && - p_enc->format.audio.i_format != VLC_FOURCC( 's', '1', '6', 'l' ) ) + if( p_enc->fmt_in.i_codec != VLC_FOURCC( 's', '1', '6', 'b' ) && + p_enc->fmt_in.i_codec != VLC_FOURCC( 's', '1', '6', 'l' ) ) { msg_Warn( p_enc, "unhandled input format" ); return VLC_EGENERIC; } - switch( p_enc->i_fourcc ) + switch( p_enc->fmt_out.i_codec ) { case VLC_FOURCC( 's', '1', '6', 'b' ): case VLC_FOURCC( 's', '1', '6', 'l' ): @@ -469,11 +428,7 @@ static int EncoderOpen ( vlc_object_t *p_this ) } p_enc->p_sys = NULL; - p_enc->pf_header = NULL; p_enc->pf_encode_audio = EncoderEncode; - p_enc->pf_encode_video = NULL; - p_enc->i_extra_data = 0; - p_enc->p_extra_data = NULL; return VLC_SUCCESS; } @@ -494,21 +449,22 @@ static block_t *EncoderEncode( encoder_t *p_enc, aout_buffer_t *p_aout_buf ) block_t *p_block = NULL; unsigned int i; - if( p_enc->i_fourcc == p_enc->format.audio.i_format ) + if( p_enc->fmt_in.i_codec == p_enc->fmt_out.i_codec ) { if( ( p_block = block_New( p_enc, p_aout_buf->i_nb_bytes ) ) ) { - memcpy( p_block->p_buffer, p_aout_buf->p_buffer, p_aout_buf->i_nb_bytes ); + memcpy( p_block->p_buffer, p_aout_buf->p_buffer, + p_aout_buf->i_nb_bytes ); } } - else if( p_enc->i_fourcc == VLC_FOURCC( 'u', '8', ' ', ' ' ) ) + else if( p_enc->fmt_out.i_codec == VLC_FOURCC( 'u', '8', ' ', ' ' ) ) { if( ( p_block = block_New( p_enc, p_aout_buf->i_nb_bytes / 2 ) ) ) { uint8_t *p_dst = (uint8_t*)p_block->p_buffer; int8_t *p_src = (int8_t*) p_aout_buf->p_buffer; - if( p_enc->format.audio.i_format == VLC_FOURCC( 's', '1', '6', 'l' ) ) + if( p_enc->fmt_in.i_codec == VLC_FOURCC( 's', '1', '6', 'l' ) ) { p_src++; } @@ -519,14 +475,14 @@ static block_t *EncoderEncode( encoder_t *p_enc, aout_buffer_t *p_aout_buf ) } } } - else if( p_enc->i_fourcc == VLC_FOURCC( 's', '8', ' ', ' ' ) ) + else if( p_enc->fmt_out.i_codec == VLC_FOURCC( 's', '8', ' ', ' ' ) ) { if( ( p_block = block_New( p_enc, p_aout_buf->i_nb_bytes / 2 ) ) ) { int8_t *p_dst = (int8_t*)p_block->p_buffer; int8_t *p_src = (int8_t*)p_aout_buf->p_buffer; - if( p_enc->format.audio.i_format == VLC_FOURCC( 's', '1', '6', 'l' ) ) + if( p_enc->fmt_in.i_codec == VLC_FOURCC( 's', '1', '6', 'l' ) ) { p_src++; } @@ -559,11 +515,9 @@ static block_t *EncoderEncode( encoder_t *p_enc, aout_buffer_t *p_aout_buf ) if( p_block ) { p_block->i_dts = p_block->i_pts = p_aout_buf->start_date; - p_block->i_length = (int64_t)p_aout_buf->i_nb_samples * (int64_t)1000000 / - p_enc->format.audio.i_rate; + p_block->i_length = (int64_t)p_aout_buf->i_nb_samples * + (int64_t)1000000 / p_enc->fmt_in.audio.i_rate; } return p_block; } - - diff --git a/modules/codec/cinepak.c b/modules/codec/cinepak.c index a9ef93bcf1..4a3b8eed1c 100644 --- a/modules/codec/cinepak.c +++ b/modules/codec/cinepak.c @@ -2,7 +2,7 @@ * cinepak.c: cinepak video decoder ***************************************************************************** * Copyright (C) 1999-2001 VideoLAN - * $Id: cinepak.c,v 1.2 2003/10/25 00:49:13 sam Exp $ + * $Id: cinepak.c,v 1.3 2003/11/16 21:07:30 gbazin Exp $ * * Authors: Laurent Aimar * @@ -71,20 +71,14 @@ struct decoder_sys_t * Cinepak properties */ cinepak_context_t *p_context; - - /* - * Output properties - */ - vout_thread_t *p_vout; }; /***************************************************************************** * Local prototypes *****************************************************************************/ -static int OpenDecoder( vlc_object_t * ); -static int InitDecoder( decoder_t * ); -static int RunDecoder ( decoder_t *, block_t * ); -static int EndDecoder ( decoder_t * ); +static int OpenDecoder( vlc_object_t * ); +static void CloseDecoder( vlc_object_t * ); +static picture_t *DecodeBlock ( decoder_t *, block_t ** ); static int cinepak_decode_frame( cinepak_context_t *, int, uint8_t * ); @@ -94,7 +88,7 @@ static int cinepak_decode_frame( cinepak_context_t *, int, uint8_t * ); vlc_module_begin(); set_description( _("Cinepak video decoder") ); set_capability( "decoder", 70 ); - set_callbacks( OpenDecoder, NULL ); + set_callbacks( OpenDecoder, CloseDecoder ); vlc_module_end(); /***************************************************************************** @@ -106,8 +100,10 @@ vlc_module_end(); static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; + decoder_sys_t *p_sys; + vlc_value_t val; - switch( p_dec->p_fifo->i_fourcc ) + switch( p_dec->fmt_in.i_codec ) { case VLC_FOURCC('c','v','i','d'): case VLC_FOURCC('C','V','I','D'): @@ -118,30 +114,13 @@ static int OpenDecoder( vlc_object_t *p_this ) } /* Allocate the memory needed to store the decoder's structure */ - if( ( p_dec->p_sys = + if( ( p_dec->p_sys = p_sys = (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL ) { msg_Err( p_dec, "out of memory" ); return VLC_EGENERIC; } - p_dec->pf_init = InitDecoder; - p_dec->pf_decode = RunDecoder; - p_dec->pf_end = EndDecoder; - - return VLC_SUCCESS; -} - -/***************************************************************************** - * InitDecoder: Initalize the decoder - *****************************************************************************/ -static int InitDecoder( decoder_t *p_dec ) -{ - decoder_sys_t *p_sys = p_dec->p_sys; - vlc_value_t val; - - p_sys->p_vout = NULL; - if( !(p_sys->p_context = malloc( sizeof( cinepak_context_t ) ) ) ) { msg_Err( p_dec, "out of memory" ); @@ -152,57 +131,53 @@ static int InitDecoder( decoder_t *p_dec ) var_Get( p_dec, "grayscale", &val ); p_sys->p_context->b_grayscale = val.b_bool; + p_dec->pf_decode_video = DecodeBlock; + msg_Dbg( p_dec, "cinepak decoder started" ); return VLC_SUCCESS; } /**************************************************************************** - * RunDecoder: the whole thing + * DecodeBlock: the whole thing **************************************************************************** * This function must be fed with whole frames. ****************************************************************************/ -static int RunDecoder( decoder_t *p_dec, block_t *p_block ) +static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; int i_status, i_plane; uint8_t *p_dst, *p_src; picture_t *p_pic; + block_t *p_block; + + if( !pp_block || !*pp_block ) return NULL; - i_status = cinepak_decode_frame( p_sys->p_context, - p_block->i_buffer, p_block->p_buffer ); + p_block = *pp_block; + + i_status = cinepak_decode_frame( p_sys->p_context, p_block->i_buffer, + p_block->p_buffer ); if( i_status < 0 ) { msg_Warn( p_dec, "cannot decode one frame (%d bytes)", p_block->i_buffer ); block_Release( p_block ); - return VLC_SUCCESS; + return NULL; } - /* Check our vout */ - p_sys->p_vout = vout_Request( p_dec, p_sys->p_vout, - p_sys->p_context->i_width, - p_sys->p_context->i_height, - VLC_FOURCC('I','4','2','0'), - p_sys->p_context->i_width - * VOUT_ASPECT_FACTOR - / p_sys->p_context->i_height ); - if( !p_sys->p_vout ) - { - msg_Err( p_dec, "cannot create vout" ); - block_Release( p_block ); - return VLC_EGENERIC; - } + p_dec->fmt_out.video.i_width = p_sys->p_context->i_width; + p_dec->fmt_out.video.i_height = p_sys->p_context->i_height; + p_dec->fmt_out.video.i_aspect = p_sys->p_context->i_width + * VOUT_ASPECT_FACTOR / p_sys->p_context->i_height; + p_dec->fmt_out.i_codec = VLC_FOURCC('I','4','2','0'); + + /* Get a new picture */ + p_pic = p_dec->pf_vout_buffer_new( p_dec ); - /* Send decoded frame to vout */ - while( !(p_pic = vout_CreatePicture( p_sys->p_vout, 0, 0, 0 ) ) ) + if( p_pic == NULL ) { - if( p_dec->p_fifo->b_die || p_dec->p_fifo->b_error ) - { - block_Release( p_block ); - return VLC_EGENERIC; - } - msleep( VOUT_OUTMEM_SLEEP ); + block_Release( p_block ); + return NULL; } for( i_plane = 0; i_plane < 3; i_plane++ ) @@ -224,25 +199,23 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) } } - vout_DatePicture( p_sys->p_vout, p_pic, p_block->i_pts); - vout_DisplayPicture( p_sys->p_vout, p_pic ); - + p_pic->date = p_block->i_pts; block_Release( p_block ); - return VLC_SUCCESS; + + return p_pic; } /***************************************************************************** - * EndDecoder: theora decoder destruction + * CloseDecoder: decoder destruction *****************************************************************************/ -static int EndDecoder( decoder_t *p_dec ) +static void CloseDecoder( vlc_object_t *p_this ) { + decoder_t *p_dec = (decoder_t *)p_this; decoder_sys_t *p_sys = p_dec->p_sys; int i; msg_Dbg( p_dec, "cinepak decoder stopped" ); - vout_Request( p_dec, p_sys->p_vout, 0, 0, 0, 0 ); - for( i = 0; i < 3; i++ ) { if( p_sys->p_context->p_pix[i] ) free( p_sys->p_context->p_pix[i] ); @@ -251,8 +224,6 @@ static int EndDecoder( decoder_t *p_dec ) free( p_sys->p_context ); free( p_sys ); - - return VLC_SUCCESS; } /***************************************************************************** diff --git a/modules/codec/dts.c b/modules/codec/dts.c index 84e41ed2e2..45e72f606e 100644 --- a/modules/codec/dts.c +++ b/modules/codec/dts.c @@ -1,8 +1,8 @@ /***************************************************************************** - * dts.c: DTS basic parser + * dts.c: parse DTS audio sync info and packetize the stream ***************************************************************************** * Copyright (C) 2003 VideoLAN - * $Id: dts.c,v 1.4 2003/09/02 20:19:25 gbazin Exp $ + * $Id: dts.c,v 1.5 2003/11/16 21:07:30 gbazin Exp $ * * Authors: Jon Lech Johansen * Gildas Bazin @@ -28,17 +28,12 @@ #include #include #include /* memcpy() */ -#include #include #include #include -#include -#include -#ifdef HAVE_UNISTD_H -# include -#endif +#include "vlc_block_helper.h" #define DTS_HEADER_SIZE 10 @@ -53,48 +48,35 @@ struct decoder_sys_t /* * Input properties */ - int i_state; + int i_state; - uint8_t p_header[DTS_HEADER_SIZE]; - int i_header; - - mtime_t pts; - - int i_frame_size; + block_bytestream_t bytestream; /* - * Decoder output properties + * Common properties */ - aout_instance_t * p_aout; /* opaque */ - aout_input_t * p_aout_input; /* opaque */ - audio_sample_format_t aout_format; - aout_buffer_t * p_aout_buffer; /* current aout buffer being filled */ + audio_date_t end_date; + + mtime_t i_pts; + + int i_frame_size, i_bit_rate; + unsigned int i_frame_length, i_rate, i_channels, i_channels_conf; + /* This is very hacky. For DTS over S/PDIF we apparently need to send * 3 frames at a time. This should likely be moved to the output stage. */ - int i_frames_in_buf; - - /* - * Packetizer output properties - */ - sout_packetizer_input_t *p_sout_input; - sout_format_t sout_format; - sout_buffer_t * p_sout_buffer; /* current sout buffer */ + int i_frames_in_buf; + aout_buffer_t *p_aout_buffer; /* current aout buffer being filled */ - /* - * Common properties - */ - uint8_t *p_out_buffer; /* output buffer */ - int i_out_buffer; /* position in output buffer */ - audio_date_t end_date; }; enum { STATE_NOSYNC, - STATE_PARTIAL_SYNC, STATE_SYNC, STATE_HEADER, - STATE_DATA + STATE_NEXT_SYNC, + STATE_GET_DATA, + STATE_SEND_DATA }; /**************************************************************************** @@ -102,18 +84,15 @@ enum { ****************************************************************************/ static int OpenDecoder ( vlc_object_t * ); static int OpenPacketizer( vlc_object_t * ); - -static int InitDecoder ( decoder_t * ); -static int RunDecoder ( decoder_t *, block_t * ); -static int EndDecoder ( decoder_t * ); +static void CloseDecoder ( vlc_object_t * ); +static void *DecodeBlock ( decoder_t *, block_t ** ); static int SyncInfo ( const byte_t *, unsigned int *, unsigned int *, unsigned int *, unsigned int *, unsigned int * ); -static int GetOutBuffer ( decoder_t *, uint8_t ** ); -static int GetAoutBuffer( decoder_t *, aout_buffer_t ** ); -static int GetSoutBuffer( decoder_t *, sout_buffer_t ** ); -static int SendOutBuffer( decoder_t * ); +static uint8_t *GetOutBuffer ( decoder_t *, void ** ); +static aout_buffer_t *GetAoutBuffer( decoder_t * ); +static block_t *GetSoutBuffer( decoder_t * ); /***************************************************************************** * Module descriptor @@ -121,7 +100,7 @@ static int SendOutBuffer( decoder_t * ); vlc_module_begin(); set_description( _("DTS parser") ); set_capability( "decoder", 100 ); - set_callbacks( OpenDecoder, NULL ); + set_callbacks( OpenDecoder, CloseDecoder ); add_submodule(); set_description( _("DTS audio packetizer") ); @@ -135,25 +114,39 @@ vlc_module_end(); static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; + decoder_sys_t *p_sys; - if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('d','t','s',' ') - && p_dec->p_fifo->i_fourcc != VLC_FOURCC('d','t','s','b') ) + if( p_dec->fmt_in.i_codec != VLC_FOURCC('d','t','s',' ') + && p_dec->fmt_in.i_codec != VLC_FOURCC('d','t','s','b') ) { return VLC_EGENERIC; } - p_dec->pf_init = InitDecoder; - p_dec->pf_decode = RunDecoder; - p_dec->pf_end = EndDecoder; - /* Allocate the memory needed to store the decoder's structure */ - if( ( p_dec->p_sys = + if( ( p_dec->p_sys = p_sys = (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL ) { msg_Err( p_dec, "out of memory" ); return VLC_EGENERIC; } - p_dec->p_sys->b_packetizer = VLC_FALSE; + + /* Misc init */ + p_sys->b_packetizer = VLC_FALSE; + p_sys->i_state = STATE_NOSYNC; + aout_DateSet( &p_sys->end_date, 0 ); + p_sys->i_frames_in_buf = 0; + + p_sys->bytestream = block_BytestreamInit( p_dec ); + + /* Set output properties */ + p_dec->fmt_out.i_cat = AUDIO_ES; + p_dec->fmt_out.i_codec = VLC_FOURCC('d','t','s',' '); + + /* Set callback */ + p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **)) + DecodeBlock; + p_dec->pf_packetize = (block_t *(*)(decoder_t *, block_t **)) + DecodeBlock; return VLC_SUCCESS; } @@ -169,420 +162,264 @@ static int OpenPacketizer( vlc_object_t *p_this ) return i_ret; } -/***************************************************************************** - * InitDecoder: Initalize the decoder - *****************************************************************************/ -static int InitDecoder( decoder_t *p_dec ) -{ - p_dec->p_sys->i_state = STATE_NOSYNC; - - p_dec->p_sys->p_out_buffer = NULL; - p_dec->p_sys->i_out_buffer = 0; - aout_DateSet( &p_dec->p_sys->end_date, 0 ); - - p_dec->p_sys->p_aout = NULL; - p_dec->p_sys->p_aout_input = NULL; - p_dec->p_sys->p_aout_buffer = NULL; - p_dec->p_sys->aout_format.i_format = VLC_FOURCC('d','t','s',' '); - - p_dec->p_sys->p_sout_input = NULL; - p_dec->p_sys->p_sout_buffer = NULL; - p_dec->p_sys->sout_format.i_cat = AUDIO_ES; - p_dec->p_sys->sout_format.i_fourcc = VLC_FOURCC('d','t','s',' '); - - return VLC_SUCCESS; -} - /**************************************************************************** - * RunDecoder: the whole thing + * DecodeBlock: the whole thing **************************************************************************** * This function is called just after the thread is launched. ****************************************************************************/ -static int RunDecoder( decoder_t *p_dec, block_t *p_block ) +static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; - int i, i_block_pos = 0; - mtime_t i_pts = p_block->i_pts; + uint8_t p_header[DTS_HEADER_SIZE]; + uint8_t *p_buf; + void *p_out_buffer; - while( i_block_pos < p_block->i_buffer ) + if( !pp_block || !*pp_block ) return NULL; + + if( !aout_DateGet( &p_sys->end_date ) && !(*pp_block)->i_pts ) + { + /* We've just started the stream, wait for the first PTS. */ + block_Release( *pp_block ); + return NULL; + } + + if( (*pp_block)->b_discontinuity ) + { + p_sys->i_state = STATE_NOSYNC; + } + + block_BytestreamPush( &p_sys->bytestream, *pp_block ); + + while( 1 ) { switch( p_sys->i_state ) { case STATE_NOSYNC: /* Look for sync dword - should be 0x7ffe8001 */ - while( i_block_pos < p_block->i_buffer && - p_block->p_buffer[i_block_pos] != 0x7f ) + while( block_PeekBytes( &p_sys->bytestream, p_header, 4 ) + == VLC_SUCCESS ) { - i_block_pos++; - } - - if( i_block_pos < p_block->i_buffer ) - { - p_sys->i_state = STATE_PARTIAL_SYNC; - i_block_pos++; - p_sys->p_header[0] = 0x7f; - p_sys->i_header = 1; - break; - } - break; - - case STATE_PARTIAL_SYNC: - /* Get the full 4 sync bytes */ - if( p_sys->i_header < 4 ) - { - int i_size = __MIN( 4 - p_sys->i_header, - p_block->i_buffer - i_block_pos ); - - memcpy( p_sys->p_header + p_sys->i_header, - p_block->p_buffer + i_block_pos, i_size ); - i_block_pos += i_size; - p_sys->i_header += i_size; - } - - if( p_sys->i_header < 4 ) - break; - - if( p_sys->p_header[0] == 0x7f && p_sys->p_header[1] == 0xfe && - p_sys->p_header[2] == 0x80 && p_sys->p_header[3] == 0x01 ) - { - p_sys->i_state = STATE_SYNC; - } - else - { - for( i = 1; i < 4; i++ ) + if( p_header[0] == 0x7f && p_header[1] == 0xfe && + p_header[2] == 0x80 && p_header[3] == 0x01 ) { - if( p_sys->p_header[i] == 0x7f ) break; - } - - if( p_sys->p_header[i] == 0x7f ) - { - /* Potential new sync */ - p_sys->i_header -= i; - memmove( p_sys->p_header, &p_sys->p_header[i], - p_sys->i_header ); + p_sys->i_state = STATE_SYNC; break; } + block_SkipByte( &p_sys->bytestream ); + } + if( p_sys->i_state != STATE_SYNC ) + { + block_BytestreamFlush( &p_sys->bytestream ); - /* retry to sync*/ - p_sys->i_state = STATE_NOSYNC; + /* Need more data */ + return NULL; } - break; case STATE_SYNC: /* New frame, set the Presentation Time Stamp */ - p_sys->pts = i_pts; i_pts = 0; - if( p_sys->pts != 0 && - p_sys->pts != aout_DateGet( &p_sys->end_date ) ) + p_sys->i_pts = p_sys->bytestream.p_block->i_pts; + if( p_sys->i_pts != 0 && + p_sys->i_pts != aout_DateGet( &p_sys->end_date ) ) { - aout_DateSet( &p_sys->end_date, p_sys->pts ); + aout_DateSet( &p_sys->end_date, p_sys->i_pts ); } p_sys->i_state = STATE_HEADER; - break; case STATE_HEADER: /* Get DTS frame header (DTS_HEADER_SIZE bytes) */ - if( p_sys->i_header < DTS_HEADER_SIZE ) + if( block_PeekBytes( &p_sys->bytestream, p_header, + DTS_HEADER_SIZE ) != VLC_SUCCESS ) { - int i_size = __MIN( DTS_HEADER_SIZE - p_sys->i_header, - p_block->i_buffer - i_block_pos ); - - memcpy( p_sys->p_header + p_sys->i_header, - p_block->p_buffer + i_block_pos, i_size ); - i_block_pos += i_size; - p_sys->i_header += i_size; + /* Need more data */ + return NULL; } - if( p_sys->i_header < DTS_HEADER_SIZE ) + /* Check if frame is valid and get frame info */ + p_sys->i_frame_size = SyncInfo( p_header, + &p_sys->i_channels, + &p_sys->i_channels_conf, + &p_sys->i_rate, + &p_sys->i_bit_rate, + &p_sys->i_frame_length ); + if( !p_sys->i_frame_size ) + { + msg_Dbg( p_dec, "emulated sync word" ); + block_SkipByte( &p_sys->bytestream ); + p_sys->i_state = STATE_NOSYNC; break; + } + p_sys->i_state = STATE_NEXT_SYNC; - if( GetOutBuffer( p_dec, &p_sys->p_out_buffer ) + case STATE_NEXT_SYNC: + /* TODO: If pp_block == NULL, flush the buffer without checking the + * next sync word */ + + /* Check if next expected frame contains the sync word */ + if( block_PeekOffsetBytes( &p_sys->bytestream, + p_sys->i_frame_size, p_header, 4 ) != VLC_SUCCESS ) { - block_Release( p_block ); - return VLC_EGENERIC; + /* Need more data */ + return NULL; } - if( !p_sys->p_out_buffer ) + if( p_header[0] == 0x7f && p_header[1] == 0xfe && + p_header[2] == 0x80 && p_header[3] == 0x01 ) { + msg_Dbg( p_dec, "emulated sync word " + "(no sync on following frame)" ); p_sys->i_state = STATE_NOSYNC; + block_SkipByte( &p_sys->bytestream ); break; } - - memcpy( p_sys->p_out_buffer, p_sys->p_header, DTS_HEADER_SIZE ); - p_sys->i_out_buffer = DTS_HEADER_SIZE; - p_sys->i_state = STATE_DATA; + p_sys->i_state = STATE_SEND_DATA; break; - case STATE_DATA: - /* Copy the whole DTS frame into the aout buffer */ - if( p_sys->i_out_buffer < p_sys->i_frame_size ) + case STATE_GET_DATA: + /* Make sure we have enough data. + * (Not useful if we went through NEXT_SYNC) */ + if( block_WaitBytes( &p_sys->bytestream, + p_sys->i_frame_size ) != VLC_SUCCESS ) { - int i_size = __MIN( p_sys->i_frame_size - p_sys->i_out_buffer, - p_block->i_buffer - i_block_pos ); - - memcpy( p_sys->p_out_buffer + p_sys->i_out_buffer, - p_block->p_buffer + i_block_pos, i_size ); - i_block_pos += i_size; - p_sys->i_out_buffer += i_size; + /* Need more data */ + return NULL; } + p_sys->i_state = STATE_SEND_DATA; - if( p_sys->i_out_buffer < p_sys->i_frame_size ) - break; /* Need more data */ + case STATE_SEND_DATA: + if( !(p_buf = GetOutBuffer( p_dec, &p_out_buffer )) ) + { + //p_dec->b_error = VLC_TRUE; + return NULL; + } - SendOutBuffer( p_dec ); + /* Copy the whole frame into the buffer. When we reach this point + * we already know we have enough data available. */ + block_GetBytes( &p_sys->bytestream, p_buf, p_sys->i_frame_size ); - p_sys->i_state = STATE_NOSYNC; - break; - } - } + /* Make sure we don't reuse the same pts twice */ + if( p_sys->i_pts == p_sys->bytestream.p_block->i_pts ) + p_sys->i_pts = p_sys->bytestream.p_block->i_pts = 0; - block_Release( p_block ); - return VLC_SUCCESS; -} + /* So p_block doesn't get re-added several times */ + *pp_block = block_BytestreamPop( &p_sys->bytestream ); -/***************************************************************************** - * EndDecoder: clean up the decoder - *****************************************************************************/ -static int EndDecoder( decoder_t *p_dec ) -{ - if( p_dec->p_sys->p_aout_input != NULL ) - { - if( p_dec->p_sys->p_aout_buffer ) - { - aout_DecDeleteBuffer( p_dec->p_sys->p_aout, - p_dec->p_sys->p_aout_input, - p_dec->p_sys->p_aout_buffer ); - } + p_sys->i_state = STATE_NOSYNC; - aout_DecDelete( p_dec->p_sys->p_aout, p_dec->p_sys->p_aout_input ); - } + if( !p_sys->b_packetizer ) + { + if( p_sys->i_frames_in_buf != 3 ) return NULL; + else + { + p_sys->i_frames_in_buf = 0; + p_sys->p_aout_buffer = 0; + } + } - if( p_dec->p_sys->p_sout_input != NULL ) - { - if( p_dec->p_sys->p_sout_buffer ) - { - sout_BufferDelete( p_dec->p_sys->p_sout_input->p_sout, - p_dec->p_sys->p_sout_buffer ); + return p_out_buffer; } - - sout_InputDelete( p_dec->p_sys->p_sout_input ); } - free( p_dec->p_sys ); - - return VLC_SUCCESS; + return NULL; } /***************************************************************************** - * GetOutBuffer: + * CloseDecoder: clean up the decoder *****************************************************************************/ -static int GetOutBuffer ( decoder_t *p_dec, uint8_t **pp_out_buffer ) +static void CloseDecoder( vlc_object_t *p_this ) { + decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys = p_dec->p_sys; - int i_ret; - if( p_sys->b_packetizer ) - { - i_ret= GetSoutBuffer( p_dec, &p_sys->p_sout_buffer ); - *pp_out_buffer = - p_sys->p_sout_buffer ? p_sys->p_sout_buffer->p_buffer : NULL; - } - else - { - i_ret = GetAoutBuffer( p_dec, &p_sys->p_aout_buffer ); - if( p_sys->i_frames_in_buf == 1 ) - *pp_out_buffer = p_sys->p_aout_buffer ? - p_sys->p_aout_buffer->p_buffer : NULL; - else - *pp_out_buffer = p_sys->p_aout_buffer ? - p_sys->p_aout_buffer->p_buffer + p_sys->i_frame_size * - (p_sys->i_frames_in_buf - 1) : NULL; - } + block_BytestreamRelease( &p_sys->bytestream ); - return i_ret; + free( p_sys ); } /***************************************************************************** - * GetAoutBuffer: + * GetOutBuffer: *****************************************************************************/ -static int GetAoutBuffer( decoder_t *p_dec, aout_buffer_t **pp_buffer ) +static uint8_t *GetOutBuffer( decoder_t *p_dec, void **pp_out_buffer ) { - int i_bit_rate; - unsigned int i_frame_length, i_rate, i_channels, i_channels_conf; - decoder_sys_t *p_sys = p_dec->p_sys; + uint8_t *p_buf; - /* Check if frame is valid and get frame info */ - p_sys->i_frame_size = SyncInfo( p_sys->p_header, - &i_channels, &i_channels_conf, - &i_rate, &i_bit_rate, &i_frame_length ); - - if( !p_sys->i_frame_size ) + if( p_dec->fmt_out.audio.i_rate != p_sys->i_rate ) { - msg_Warn( p_dec, "dts syncinfo failed" ); - *pp_buffer = NULL; - return VLC_SUCCESS; - } + msg_Info( p_dec, "DTS channels:%d samplerate:%d bitrate:%d", + p_sys->i_channels, p_sys->i_rate, p_sys->i_bit_rate ); - if( p_sys->p_aout_input != NULL && ( p_sys->aout_format.i_rate != i_rate - || p_sys->aout_format.i_original_channels != i_channels_conf - || (int)p_sys->aout_format.i_bytes_per_frame != p_sys->i_frame_size ) ) - { - /* Parameters changed - this should not happen. */ - aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input ); - p_sys->p_aout_input = NULL; + aout_DateInit( &p_sys->end_date, p_sys->i_rate ); + aout_DateSet( &p_sys->end_date, p_sys->i_pts ); } - /* Creating the audio input if not created yet. */ - if( p_sys->p_aout_input == NULL ) - { - p_sys->aout_format.i_rate = i_rate; - p_sys->aout_format.i_original_channels = i_channels_conf; - p_sys->aout_format.i_physical_channels - = i_channels_conf & AOUT_CHAN_PHYSMASK; - p_sys->aout_format.i_bytes_per_frame = p_sys->i_frame_size; - p_sys->aout_format.i_frame_length = i_frame_length; - aout_DateInit( &p_sys->end_date, i_rate ); - aout_DateSet( &p_sys->end_date, p_sys->pts ); - p_sys->i_frames_in_buf = 3; - p_sys->p_aout_input = aout_DecNew( p_dec, - &p_sys->p_aout, - &p_sys->aout_format ); - - if ( p_sys->p_aout_input == NULL ) - { - *pp_buffer = NULL; - return VLC_SUCCESS; - } - } + p_dec->fmt_out.audio.i_rate = p_sys->i_rate; + p_dec->fmt_out.audio.i_channels = p_sys->i_channels; + p_dec->fmt_out.audio.i_bitrate = p_sys->i_bit_rate; + p_dec->fmt_out.audio.i_bytes_per_frame = p_sys->i_frame_size; + p_dec->fmt_out.audio.i_frame_length = p_sys->i_frame_length; + + p_dec->fmt_out.audio.i_original_channels = p_sys->i_channels_conf; + p_dec->fmt_out.audio.i_physical_channels = + p_sys->i_channels_conf & AOUT_CHAN_PHYSMASK; - if( !aout_DateGet( &p_sys->end_date ) ) + if( p_sys->b_packetizer ) { - /* We've just started the stream, wait for the first PTS. */ - *pp_buffer = NULL; - return VLC_SUCCESS; + block_t *p_sout_buffer = GetSoutBuffer( p_dec ); + p_buf = p_sout_buffer ? p_sout_buffer->p_buffer : NULL; + *pp_out_buffer = p_sout_buffer; } - - if( p_sys->i_frames_in_buf == 3 ) + else { - p_sys->i_frames_in_buf = 0; - *pp_buffer = aout_DecNewBuffer( p_sys->p_aout, p_sys->p_aout_input, - i_frame_length * 3 ); - if( *pp_buffer == NULL ) + if( !p_sys->i_frames_in_buf ) { - return VLC_SUCCESS; + p_sys->p_aout_buffer = GetAoutBuffer( p_dec ); } - - (*pp_buffer)->start_date = aout_DateGet( &p_sys->end_date ); - (*pp_buffer)->end_date = - aout_DateIncrement( &p_sys->end_date, i_frame_length * 3 ); + p_buf = p_sys->p_aout_buffer ? p_sys->p_aout_buffer->p_buffer + + p_sys->i_frames_in_buf * p_sys->i_frame_size : NULL; + *pp_out_buffer = p_sys->p_aout_buffer; } p_sys->i_frames_in_buf++; - return VLC_SUCCESS; + return p_buf; } /***************************************************************************** - * GetSoutBuffer: + * GetAoutBuffer: *****************************************************************************/ -static int GetSoutBuffer( decoder_t *p_dec, sout_buffer_t **pp_buffer ) +static aout_buffer_t *GetAoutBuffer( decoder_t *p_dec ) { - int i_bit_rate; - unsigned int i_frame_length, i_rate, i_channels, i_channels_conf; - decoder_sys_t *p_sys = p_dec->p_sys; + aout_buffer_t *p_buf; - /* Check if frame is valid and get frame info */ - p_sys->i_frame_size = SyncInfo( p_sys->p_header, - &i_channels, &i_channels_conf, - &i_rate, &i_bit_rate, &i_frame_length ); - - if( !p_sys->i_frame_size ) - { - msg_Warn( p_dec, "dts syncinfo failed" ); - *pp_buffer = NULL; - return VLC_SUCCESS; - } - - if( p_sys->p_sout_input != NULL && - ( p_sys->sout_format.i_sample_rate != (int)i_rate - || p_sys->sout_format.i_channels != (int)i_channels ) ) - { - /* Parameters changed - this should not happen. */ - } - - /* Creating the sout input if not created yet. */ - if( p_sys->p_sout_input == NULL ) - { - p_sys->sout_format.i_sample_rate = i_rate; - p_sys->sout_format.i_channels = i_channels; - p_sys->sout_format.i_block_align = 0; - p_sys->sout_format.i_bitrate = i_bit_rate; - p_sys->sout_format.i_extra_data = 0; - p_sys->sout_format.p_extra_data = NULL; - - aout_DateInit( &p_sys->end_date, i_rate ); - aout_DateSet( &p_sys->end_date, p_sys->pts ); - - p_sys->p_sout_input = sout_InputNew( p_dec, - &p_sys->sout_format ); - - if( p_sys->p_sout_input == NULL ) - { - msg_Err( p_dec, "cannot add a new stream" ); - *pp_buffer = NULL; - return VLC_EGENERIC; - } - msg_Info( p_dec, "DTS channels:%d samplerate:%d bitrate:%d", - i_channels, i_rate, i_bit_rate ); - } - - if( !aout_DateGet( &p_sys->end_date ) ) - { - /* We've just started the stream, wait for the first PTS. */ - *pp_buffer = NULL; - return VLC_SUCCESS; - } - - *pp_buffer = sout_BufferNew( p_sys->p_sout_input->p_sout, - p_sys->i_frame_size ); - if( *pp_buffer == NULL ) - { - return VLC_SUCCESS; - } - - (*pp_buffer)->i_pts = - (*pp_buffer)->i_dts = aout_DateGet( &p_sys->end_date ); + p_buf = p_dec->pf_aout_buffer_new( p_dec, p_sys->i_frame_length * 3 ); + if( p_buf == NULL ) return NULL; - (*pp_buffer)->i_length = - aout_DateIncrement( &p_sys->end_date, i_frame_length ) - - (*pp_buffer)->i_pts; + p_buf->start_date = aout_DateGet( &p_sys->end_date ); + p_buf->end_date = + aout_DateIncrement( &p_sys->end_date, p_sys->i_frame_length * 3 ); - return VLC_SUCCESS; + return p_buf; } /***************************************************************************** - * SendOutBuffer: + * GetSoutBuffer: *****************************************************************************/ -static int SendOutBuffer( decoder_t *p_dec ) +static block_t *GetSoutBuffer( decoder_t *p_dec ) { decoder_sys_t *p_sys = p_dec->p_sys; + block_t *p_block; - if( p_sys->b_packetizer ) - { - sout_InputSendBuffer( p_sys->p_sout_input, p_sys->p_sout_buffer ); - p_sys->p_sout_buffer = NULL; - } - else if( p_sys->i_frames_in_buf == 3 ) - { - /* We have all we need, send the buffer to the aout core. */ - aout_DecPlay( p_sys->p_aout, p_sys->p_aout_input, - p_sys->p_aout_buffer ); - p_sys->p_aout_buffer = NULL; - } + p_block = block_New( p_dec, p_sys->i_frame_size ); + if( p_block == NULL ) return NULL; - return VLC_SUCCESS; + p_block->i_pts = p_block->i_dts = aout_DateGet( &p_sys->end_date ); + + p_block->i_length = aout_DateIncrement( &p_sys->end_date, + p_sys->i_frame_length ) - p_block->i_pts; + + return p_block; } /***************************************************************************** diff --git a/modules/codec/dv.c b/modules/codec/dv.c index d84b1a7bb9..5f9acf9f30 100644 --- a/modules/codec/dv.c +++ b/modules/codec/dv.c @@ -2,7 +2,7 @@ * dv.c: a decoder for DV video ***************************************************************************** * Copyright (C) 2002 VideoLAN - * $Id: dv.c,v 1.5 2003/09/02 20:19:25 gbazin Exp $ + * $Id: dv.c,v 1.6 2003/11/16 21:07:30 gbazin Exp $ * * Authors: Samuel Hocevar * @@ -59,7 +59,7 @@ static int OpenDecoder ( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; - if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('d','v','s','d') ) + if( p_dec->fmt_in.i_codec != VLC_FOURCC('d','v','s','d') ) { return VLC_EGENERIC; } diff --git a/modules/codec/dvbsub.c b/modules/codec/dvbsub.c index f561f96b0e..2a3f2d252b 100644 --- a/modules/codec/dvbsub.c +++ b/modules/codec/dvbsub.c @@ -2,7 +2,7 @@ * dvbsub.c : DVB subtitles decoder thread ***************************************************************************** * Copyright (C) 2003 ANEVIA - * $Id: dvbsub.c,v 1.2 2003/11/06 19:35:05 nitrox Exp $ + * $Id: dvbsub.c,v 1.3 2003/11/16 21:07:30 gbazin Exp $ * * Authors: Damien LUCAS * @@ -275,7 +275,7 @@ vlc_module_end(); static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*) p_this; - if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('d','v','b','s') ) + if( p_dec->fmt_in.i_codec != VLC_FOURCC('d','v','b','s') ) { return VLC_EGENERIC; } diff --git a/modules/codec/faad.c b/modules/codec/faad.c index ae96b4b1d5..a6000b406f 100644 --- a/modules/codec/faad.c +++ b/modules/codec/faad.c @@ -2,7 +2,7 @@ * decoder.c: AAC decoder using libfaad2 ***************************************************************************** * Copyright (C) 2001, 2003 VideoLAN - * $Id: faad.c,v 1.3 2003/11/05 01:47:40 fenrir Exp $ + * $Id: faad.c,v 1.4 2003/11/16 21:07:30 gbazin Exp $ * * Authors: Laurent Aimar * @@ -34,86 +34,69 @@ * Module descriptor *****************************************************************************/ static int Open( vlc_object_t * ); +static void CloseDecoder( vlc_object_t * ); vlc_module_begin(); set_description( _("AAC audio decoder (using libfaad2)") ); set_capability( "decoder", 60 ); - set_callbacks( Open, NULL ); + set_callbacks( Open, CloseDecoder ); vlc_module_end(); /**************************************************************************** * Local prototypes ****************************************************************************/ -static int InitDecoder ( decoder_t * ); -static int RunDecoder ( decoder_t *, block_t * ); -static int EndDecoder ( decoder_t * ); +static aout_buffer_t *DecodeBlock( decoder_t *, block_t ** ); struct decoder_sys_t { /* faad handler */ faacDecHandle *hfaad; - /* audio output */ - audio_sample_format_t output_format; - aout_instance_t * p_aout; /* opaque */ - aout_input_t * p_aout_input; /* opaque */ - /* samples */ - audio_date_t date; + audio_date_t date; /* temporary buffer */ - uint8_t *p_buffer; - int i_buffer; - int i_buffer_size; + uint8_t *p_buffer; + int i_buffer; + int i_buffer_size; }; -/***************************************************************************** - * OpenDecoder: probe the decoder and return score - *****************************************************************************/ -static int Open( vlc_object_t *p_this ) -{ - decoder_t *p_dec = (decoder_t*)p_this; - - if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('m','p','4','a') ) - { - return VLC_EGENERIC; - } - - p_dec->pf_init = InitDecoder; - p_dec->pf_decode = RunDecoder; - p_dec->pf_end = EndDecoder; - - p_dec->p_sys = malloc( sizeof( decoder_sys_t ) ); - - return VLC_SUCCESS; -} - static unsigned int pi_channels_maps[7] = { 0, AOUT_CHAN_CENTER, AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT, - AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT, - AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT, + AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT | + AOUT_CHAN_REARRIGHT, + AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT | + AOUT_CHAN_REARRIGHT, /* FIXME */ - AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_REARCENTER + AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT | + AOUT_CHAN_REARRIGHT | AOUT_CHAN_REARCENTER }; /***************************************************************************** - * InitDecoder: + * OpenDecoder: probe the decoder and return score *****************************************************************************/ -static int InitDecoder ( decoder_t *p_dec ) +static int Open( vlc_object_t *p_this ) { + decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys = p_dec->p_sys; - WAVEFORMATEX wf, *p_wf; faacDecConfiguration *cfg; - if( ( p_wf = (WAVEFORMATEX*)p_dec->p_fifo->p_waveformatex ) == NULL ) + if( p_dec->fmt_in.i_codec != VLC_FOURCC('m','p','4','a') ) { - p_wf = &wf; - memset( p_wf, 0, sizeof( WAVEFORMATEX ) ); + return VLC_EGENERIC; + } + + /* Allocate the memory needed to store the decoder's structure */ + if( ( p_dec->p_sys = p_sys = + (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL ) + { + msg_Err( p_dec, "out of memory" ); + return VLC_EGENERIC; } /* Open a faad context */ @@ -123,37 +106,43 @@ static int InitDecoder ( decoder_t *p_dec ) return VLC_EGENERIC; } - if( p_wf->cbSize > 0 ) + /* Misc init */ + aout_DateSet( &p_sys->date, 0 ); + p_dec->fmt_out.i_cat = AUDIO_ES; + p_dec->fmt_out.i_codec = VLC_FOURCC('f','l','3','2'); + p_dec->pf_decode_audio = DecodeBlock; + + if( p_dec->fmt_in.i_extra > 0 ) { /* We have a decoder config so init the handle */ - unsigned long i_rate; - unsigned char i_channels; + unsigned long i_rate; + unsigned char i_channels; - if( faacDecInit2( p_sys->hfaad, - (uint8_t*)&p_wf[1], p_wf->cbSize, + if( faacDecInit2( p_sys->hfaad, p_dec->fmt_in.p_extra, + p_dec->fmt_in.i_extra, &i_rate, &i_channels ) < 0 ) { return VLC_EGENERIC; } - p_sys->output_format.i_rate = i_rate; - p_sys->output_format.i_physical_channels = - p_sys->output_format.i_original_channels = - pi_channels_maps[i_channels]; + p_dec->fmt_out.audio.i_rate = i_rate; + p_dec->fmt_out.audio.i_channels = i_channels; + p_dec->fmt_out.audio.i_physical_channels = + p_dec->fmt_out.audio.i_original_channels = + pi_channels_maps[i_channels]; + + aout_DateInit( &p_sys->date, i_rate ); } else { /* Will be initalised from first frame */ - p_sys->output_format.i_rate = 0; - p_sys->output_format.i_physical_channels = - p_sys->output_format.i_original_channels = 0; + p_dec->fmt_out.audio.i_rate = 0; + p_dec->fmt_out.audio.i_channels = 0; + p_dec->fmt_out.audio.i_physical_channels = + p_dec->fmt_out.audio.i_original_channels = 0; } - p_sys->output_format.i_format = VLC_FOURCC('f','l','3','2'); - - p_sys->p_aout = NULL; - p_sys->p_aout_input = NULL; - /* set the faad config */ + /* Set the faad config */ cfg = faacDecGetCurrentConfiguration( p_sys->hfaad ); cfg->outputFormat = FAAD_FMT_FLOAT; faacDecSetConfiguration( p_sys->hfaad, cfg ); @@ -167,28 +156,36 @@ static int InitDecoder ( decoder_t *p_dec ) } /***************************************************************************** - * InitDecoder: + * DecodeBlock: *****************************************************************************/ -static int RunDecoder ( decoder_t *p_dec, block_t *p_block ) +static aout_buffer_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; + block_t *p_block; - int i_used = 0; - mtime_t i_pts = p_block->i_pts; + if( !pp_block || !*pp_block ) return NULL; + + p_block = *pp_block; /* Append the block to the temporary buffer */ if( p_sys->i_buffer_size < p_sys->i_buffer + p_block->i_buffer ) { - p_sys->i_buffer_size += p_block->i_buffer; + p_sys->i_buffer_size = p_sys->i_buffer + p_block->i_buffer; p_sys->p_buffer = realloc( p_sys->p_buffer, p_sys->i_buffer_size ); } - memcpy( &p_sys->p_buffer[p_sys->i_buffer], p_block->p_buffer, p_block->i_buffer ); - p_sys->i_buffer += p_block->i_buffer; - if( p_sys->output_format.i_rate == 0 ) + if( p_block->i_buffer ) + { + memcpy( &p_sys->p_buffer[p_sys->i_buffer], + p_block->p_buffer, p_block->i_buffer ); + p_sys->i_buffer += p_block->i_buffer; + p_block->i_buffer = 0; + } + + if( p_dec->fmt_out.audio.i_rate == 0 && p_sys->i_buffer ) { - unsigned long i_rate; - unsigned char i_channels; + unsigned long i_rate; + unsigned char i_channels; /* Init faad with the first frame */ if( faacDecInit( p_sys->hfaad, @@ -196,137 +193,121 @@ static int RunDecoder ( decoder_t *p_dec, block_t *p_block ) &i_rate, &i_channels ) < 0 ) { block_Release( p_block ); - return VLC_EGENERIC; + return NULL; } - p_sys->output_format.i_rate = i_rate; - p_sys->output_format.i_physical_channels = - p_sys->output_format.i_original_channels = - pi_channels_maps[i_channels]; + + p_dec->fmt_out.audio.i_rate = i_rate; + p_dec->fmt_out.audio.i_channels = i_channels; + p_dec->fmt_out.audio.i_physical_channels = + p_dec->fmt_out.audio.i_original_channels = + pi_channels_maps[i_channels]; + + aout_DateInit( &p_sys->date, i_rate ); + } + + if( p_block->i_pts != 0 && p_block->i_pts != aout_DateGet( &p_sys->date ) ) + { + aout_DateSet( &p_sys->date, p_block->i_pts ); + } + else if( !aout_DateGet( &p_sys->date ) ) + { + /* We've just started the stream, wait for the first PTS. */ + block_Release( p_block ); + p_sys->i_buffer = 0; + return NULL; } /* Decode all data */ - while( i_used < p_sys->i_buffer ) + if( p_sys->i_buffer ) { void *samples; faacDecFrameInfo frame; - aout_buffer_t *out; + aout_buffer_t *p_out; samples = faacDecDecode( p_sys->hfaad, &frame, - &p_sys->p_buffer[i_used], p_sys->i_buffer - i_used ); + p_sys->p_buffer, p_sys->i_buffer ); if( frame.error > 0 ) { msg_Warn( p_dec, "%s", faacDecGetErrorMessage( frame.error ) ); - /* flush the buffer */ + + /* Flush the buffer */ p_sys->i_buffer = 0; block_Release( p_block ); - return VLC_SUCCESS; + return NULL; } + if( frame.channels <= 0 || frame.channels > 6 ) { msg_Warn( p_dec, "invalid channels count" ); - /* flush the buffer */ + + /* Flush the buffer */ p_sys->i_buffer = 0; block_Release( p_block ); - return VLC_SUCCESS; + return NULL; } + if( frame.samples <= 0 ) { msg_Warn( p_dec, "decoded zero samples" ); - /* flush the buffer */ + + /* Flush the buffer */ p_sys->i_buffer = 0; block_Release( p_block ); - return VLC_SUCCESS; + return NULL; } - /* we have decoded a valid frame */ - /* msg_Dbg( p_dec, "consumed %d for %dHz %dc %lld", frame.bytesconsumed, frame.samplerate, frame.channels, i_pts ); */ - i_used += frame.bytesconsumed; - - - /* create/recreate the output */ - if( p_sys->p_aout_input && - ( p_sys->output_format.i_original_channels != pi_channels_maps[frame.channels] || - p_sys->output_format.i_rate != frame.samplerate ) ) + /* We decoded a valid frame */ + if( p_dec->fmt_out.audio.i_rate != frame.samplerate ) { - aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input ); - p_sys->p_aout_input = NULL; + aout_DateInit( &p_sys->date, frame.samplerate ); + aout_DateSet( &p_sys->date, p_block->i_pts ); } + p_block->i_pts = 0; /* PTS is valid only once */ - if( p_sys->p_aout_input == NULL ) - { - p_sys->output_format.i_physical_channels = - p_sys->output_format.i_original_channels = pi_channels_maps[frame.channels]; - p_sys->output_format.i_rate = frame.samplerate; - - aout_DateInit( &p_sys->date, p_sys->output_format.i_rate ); - aout_DateSet( &p_sys->date, 0 ); - - p_sys->p_aout_input = aout_DecNew( p_dec, &p_sys->p_aout, &p_sys->output_format ); - } + p_dec->fmt_out.audio.i_rate = frame.samplerate; + p_dec->fmt_out.audio.i_channels = frame.channels; + p_dec->fmt_out.audio.i_physical_channels = + p_dec->fmt_out.audio.i_original_channels = + pi_channels_maps[frame.channels]; - if( p_sys->p_aout_input == NULL ) + p_out = p_dec->pf_aout_buffer_new( p_dec, + frame.samples / frame.channels ); + if( p_out == NULL ) { - msg_Err( p_dec, "cannot create aout" ); + p_sys->i_buffer = 0; block_Release( p_block ); - return VLC_EGENERIC; + return NULL; } - if( i_pts != 0 && i_pts != aout_DateGet( &p_sys->date ) ) - { - aout_DateSet( &p_sys->date, i_pts ); - } - else if( !aout_DateGet( &p_sys->date ) ) - { - /* Wait for a dated packet */ - msg_Dbg( p_dec, "no date" ); - p_sys->i_buffer = 0; - return VLC_SUCCESS; - } - i_pts = 0; /* PTS is valid only once */ + p_out->start_date = aout_DateGet( &p_sys->date ); + p_out->end_date = aout_DateIncrement( &p_sys->date, + frame.samples / frame.channels ); + + memcpy( p_out->p_buffer, samples, p_out->i_nb_bytes ); - if( ( out = aout_DecNewBuffer( p_sys->p_aout, p_sys->p_aout_input, - frame.samples / frame.channels ) ) == NULL ) + p_sys->i_buffer -= frame.bytesconsumed; + if( p_sys->i_buffer > 0 ) { - msg_Err( p_dec, "cannot get a new buffer" ); - block_Release( p_block ); - return VLC_EGENERIC; + memmove( p_sys->p_buffer, &p_sys->p_buffer[frame.bytesconsumed], + p_sys->i_buffer ); } - out->start_date = aout_DateGet( &p_sys->date ); - out->end_date = aout_DateIncrement( &p_sys->date, - frame.samples / frame.channels ); - memcpy( out->p_buffer, samples, out->i_nb_bytes ); - - aout_DecPlay( p_sys->p_aout, p_sys->p_aout_input, out ); - } - p_sys->i_buffer -= i_used; - if( p_sys->i_buffer > 0 ) - { - memmove( &p_sys->p_buffer[0], &p_sys->p_buffer[i_used], p_sys->i_buffer ); + return p_out; } block_Release( p_block ); - return VLC_SUCCESS; + return NULL; } /***************************************************************************** - * InitDecoder: + * CloseDecoder: *****************************************************************************/ -static int EndDecoder ( decoder_t *p_dec ) +static void CloseDecoder( vlc_object_t *p_this ) { + decoder_t *p_dec = (decoder_t *)p_this; decoder_sys_t *p_sys = p_dec->p_sys; - if( p_sys->p_aout_input ) - { - aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input ); - } - faacDecClose( p_sys->hfaad ); free( p_sys ); - - return VLC_SUCCESS; } - - - diff --git a/modules/codec/ffmpeg/audio.c b/modules/codec/ffmpeg/audio.c index df9191fb24..b50f0c13f1 100644 --- a/modules/codec/ffmpeg/audio.c +++ b/modules/codec/ffmpeg/audio.c @@ -2,7 +2,7 @@ * audio.c: audio decoder using ffmpeg library ***************************************************************************** * Copyright (C) 1999-2003 VideoLAN - * $Id: audio.c,v 1.21 2003/10/27 10:00:40 gbazin Exp $ + * $Id: audio.c,v 1.22 2003/11/16 21:07:30 gbazin Exp $ * * Authors: Laurent Aimar * Gildas Bazin @@ -29,19 +29,9 @@ #include #include -#include -#include #include #include -#ifdef HAVE_UNISTD_H -#include /* getpid() */ -#endif - -#ifdef HAVE_SYS_TIMES_H -# include -#endif - #include "codecs.h" #include "aout_internal.h" @@ -83,8 +73,6 @@ struct decoder_sys_t /* * Output properties */ - aout_instance_t *p_aout; - aout_input_t *p_aout_input; audio_sample_format_t aout_format; audio_date_t end_date; }; @@ -98,7 +86,6 @@ int E_(InitAudioDec)( decoder_t *p_dec, AVCodecContext *p_context, AVCodec *p_codec, int i_codec_id, char *psz_namecodec ) { decoder_sys_t *p_sys; - WAVEFORMATEX wf, *p_wf; /* Allocate the memory needed to store the decoder's structure */ if( ( p_dec->p_sys = p_sys = @@ -113,25 +100,19 @@ int E_(InitAudioDec)( decoder_t *p_dec, AVCodecContext *p_context, p_dec->p_sys->i_codec_id = i_codec_id; p_dec->p_sys->psz_namecodec = psz_namecodec; - if( ( p_wf = p_dec->p_fifo->p_waveformatex ) == NULL ) - { - msg_Warn( p_dec, "audio informations missing" ); - p_wf = &wf; - memset( p_wf, 0, sizeof( WAVEFORMATEX ) ); - } - /* ***** Fill p_context with init values ***** */ - p_sys->p_context->sample_rate = p_wf->nSamplesPerSec; - p_sys->p_context->channels = p_wf->nChannels; - p_sys->p_context->block_align = p_wf->nBlockAlign; - p_sys->p_context->bit_rate = p_wf->nAvgBytesPerSec * 8; + p_sys->p_context->sample_rate = p_dec->fmt_in.audio.i_rate; + p_sys->p_context->channels = p_dec->fmt_in.audio.i_channels; + p_sys->p_context->block_align = p_dec->fmt_in.audio.i_blockalign; + p_sys->p_context->bit_rate = p_dec->fmt_in.i_bitrate; - if( ( p_sys->p_context->extradata_size = p_wf->cbSize ) > 0 ) + if( ( p_sys->p_context->extradata_size = p_dec->fmt_in.i_extra ) > 0 ) { p_sys->p_context->extradata = - malloc( p_wf->cbSize + FF_INPUT_BUFFER_PADDING_SIZE ); - memcpy( p_sys->p_context->extradata, &p_wf[1], p_wf->cbSize); - memset( &((uint8_t*)p_sys->p_context->extradata)[p_wf->cbSize], 0, + malloc( p_dec->fmt_in.i_extra + FF_INPUT_BUFFER_PADDING_SIZE ); + memcpy( p_sys->p_context->extradata, + p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra ); + memset( p_sys->p_context->extradata + p_dec->fmt_in.i_extra, 0, FF_INPUT_BUFFER_PADDING_SIZE ); } @@ -148,131 +129,106 @@ int E_(InitAudioDec)( decoder_t *p_dec, AVCodecContext *p_context, p_sys->p_output = malloc( 3 * AVCODEC_MAX_AUDIO_FRAME_SIZE ); - p_sys->p_aout = NULL; - p_sys->p_aout_input = NULL; - aout_DateSet( &p_sys->end_date, 0 ); + /* Set output properties */ + p_dec->fmt_out.i_cat = AUDIO_ES; + p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE; + return VLC_SUCCESS; } /***************************************************************************** * DecodeAudio: Called to decode one frame *****************************************************************************/ -int E_( DecodeAudio )( decoder_t *p_dec, block_t *p_block ) +aout_buffer_t *E_( DecodeAudio )( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; - aout_buffer_t *p_aout_buffer; - mtime_t i_pts; + int i_used, i_output, i_samples; + uint8_t *p_samples; + aout_buffer_t *p_buffer; + block_t *p_block; + + if( !pp_block || !*pp_block ) return NULL; - uint8_t *p_buffer, *p_samples; - int i_buffer, i_samples; + p_block = *pp_block; if( !aout_DateGet( &p_sys->end_date ) && !p_block->i_pts ) { /* We've just started the stream, wait for the first PTS. */ block_Release( p_block ); - return VLC_SUCCESS; + return NULL; } - i_pts = p_block->i_pts; - i_buffer = p_block->i_buffer; - p_buffer = p_block->p_buffer; - - while( i_buffer ) + if( !p_block->i_buffer ) { - int i_used, i_output; + block_Release( p_block ); + return NULL; + } - i_used = avcodec_decode_audio( p_sys->p_context, - (int16_t*)p_sys->p_output, &i_output, - p_buffer, i_buffer ); + i_used = avcodec_decode_audio( p_sys->p_context, + (int16_t*)p_sys->p_output, &i_output, + p_block->p_buffer, p_block->i_buffer ); + + if( i_used < 0 )//|| i_output == 0 ) + { if( i_used < 0 ) - { - msg_Warn( p_dec, "cannot decode one frame (%d bytes)", i_buffer ); - break; - } - - i_buffer -= i_used; - p_buffer += i_used; - - if( p_sys->p_context->channels <= 0 || p_sys->p_context->channels > 6 ) - { - msg_Warn( p_dec, "invalid channels count %d", - p_sys->p_context->channels ); - break; - } - - /* **** First check if we have a valid output **** */ - if( p_sys->p_aout_input == NULL || - p_sys->aout_format.i_original_channels != - pi_channels_maps[p_sys->p_context->channels] ) - { - if( p_sys->p_aout_input != NULL ) - { - /* **** Delete the old **** */ - aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input ); - } - - /* **** Create a new audio output **** */ - p_sys->aout_format.i_format = AOUT_FMT_S16_NE; - p_sys->aout_format.i_rate = p_sys->p_context->sample_rate; - p_sys->aout_format.i_physical_channels = - p_sys->aout_format.i_original_channels = - pi_channels_maps[p_sys->p_context->channels]; - - aout_DateInit( &p_sys->end_date, p_sys->aout_format.i_rate ); - p_sys->p_aout_input = aout_DecNew( p_dec, &p_sys->p_aout, - &p_sys->aout_format ); - } - - if( !p_sys->p_aout_input ) - { - msg_Err( p_dec, "cannot create audio output" ); - block_Release( p_block ); - return VLC_EGENERIC; - } - - if( i_pts != 0 && i_pts != aout_DateGet( &p_sys->end_date ) ) - { - aout_DateSet( &p_sys->end_date, i_pts ); - i_pts = 0; - } - - /* **** Now we can output these samples **** */ - i_samples = i_output / 2 / p_sys->p_context->channels; - - p_samples = p_sys->p_output; - while( i_samples > 0 ) - { - int i_smaller_samples; - - i_smaller_samples = __MIN( 8000, i_samples ); - - p_aout_buffer = aout_DecNewBuffer( p_sys->p_aout, - p_sys->p_aout_input, - i_smaller_samples ); - if( !p_aout_buffer ) - { - msg_Err( p_dec, "cannot get aout buffer" ); - block_Release( p_block ); - return VLC_EGENERIC; - } - - p_aout_buffer->start_date = aout_DateGet( &p_sys->end_date ); - p_aout_buffer->end_date = aout_DateIncrement( &p_sys->end_date, - i_smaller_samples ); - memcpy( p_aout_buffer->p_buffer, p_samples, - p_aout_buffer->i_nb_bytes ); - - aout_DecPlay( p_sys->p_aout, p_sys->p_aout_input, p_aout_buffer ); - - p_samples += i_smaller_samples * 2 * p_sys->p_context->channels; - i_samples -= i_smaller_samples; - } + msg_Warn( p_dec, "cannot decode one frame (%d bytes)", + p_block->i_buffer ); + + block_Release( p_block ); + return NULL; } - block_Release( p_block ); - return VLC_SUCCESS; + p_block->i_buffer -= i_used; + p_block->p_buffer += i_used; + + if( p_sys->p_context->channels <= 0 || p_sys->p_context->channels > 6 ) + { + msg_Warn( p_dec, "invalid channels count %d", + p_sys->p_context->channels ); + block_Release( p_block ); + return NULL; + } + + if( p_dec->fmt_out.audio.i_rate != p_sys->p_context->sample_rate ) + { + aout_DateInit( &p_sys->end_date, p_sys->p_context->sample_rate ); + aout_DateSet( &p_sys->end_date, p_block->i_pts ); + } + + /* **** Set audio output parameters **** */ + p_dec->fmt_out.audio.i_rate = p_sys->p_context->sample_rate; + p_dec->fmt_out.audio.i_channels = p_sys->p_context->channels; + p_dec->fmt_out.audio.i_original_channels = + p_dec->fmt_out.audio.i_physical_channels = + pi_channels_maps[p_sys->p_context->channels]; + + if( p_block->i_pts != 0 && + p_block->i_pts != aout_DateGet( &p_sys->end_date ) ) + { + aout_DateSet( &p_sys->end_date, p_block->i_pts ); + p_block->i_pts = 0; + } + + /* **** Now we can output these samples **** */ + i_samples = i_output / 2 / p_sys->p_context->channels; + p_samples = p_sys->p_output; + + p_buffer = p_dec->pf_aout_buffer_new( p_dec, i_samples ); + if( !p_buffer ) + { + msg_Err( p_dec, "cannot get aout buffer" ); + block_Release( p_block ); + return NULL; + } + + p_buffer->start_date = aout_DateGet( &p_sys->end_date ); + p_buffer->end_date = aout_DateIncrement( &p_sys->end_date, i_samples ); + + memcpy( p_buffer->p_buffer, p_samples, p_buffer->i_nb_bytes ); + + return p_buffer; } /***************************************************************************** @@ -283,9 +239,4 @@ void E_(EndAudioDec)( decoder_t *p_dec ) decoder_sys_t *p_sys = p_dec->p_sys; if( p_sys->p_output ) free( p_sys->p_output ); - - if( p_sys->p_aout_input ) - { - aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input ); - } } diff --git a/modules/codec/ffmpeg/encoder.c b/modules/codec/ffmpeg/encoder.c index 72da933077..fa3c307849 100644 --- a/modules/codec/ffmpeg/encoder.c +++ b/modules/codec/ffmpeg/encoder.c @@ -2,7 +2,7 @@ * encoder.c: video and audio encoder using the ffmpeg library ***************************************************************************** * Copyright (C) 1999-2001 VideoLAN - * $Id: encoder.c,v 1.6 2003/11/05 23:32:31 hartman Exp $ + * $Id: encoder.c,v 1.7 2003/11/16 21:07:31 gbazin Exp $ * * Authors: Laurent Aimar * Gildas Bazin @@ -51,11 +51,8 @@ /***************************************************************************** * Local prototypes *****************************************************************************/ -int E_(OpenVideoEncoder) ( vlc_object_t * ); -void E_(CloseVideoEncoder)( vlc_object_t * ); - -int E_(OpenAudioEncoder) ( vlc_object_t * ); -void E_(CloseAudioEncoder)( vlc_object_t * ); +int E_(OpenEncoder) ( vlc_object_t * ); +void E_(CloseEncoder)( vlc_object_t * ); static block_t *EncodeVideo( encoder_t *, picture_t * ); static block_t *EncodeAudio( encoder_t *, aout_buffer_t * ); @@ -92,29 +89,35 @@ struct encoder_sys_t }; /***************************************************************************** - * OpenVideoEncoder: probe the encoder + * OpenEncoder: probe the encoder *****************************************************************************/ -int E_(OpenVideoEncoder)( vlc_object_t *p_this ) +int E_(OpenEncoder)( vlc_object_t *p_this ) { encoder_t *p_enc = (encoder_t *)p_this; encoder_sys_t *p_sys = p_enc->p_sys; - AVCodecContext *p_context; + AVCodecContext *p_context; AVCodec *p_codec; int i_codec_id, i_cat; char *psz_namecodec; - if( !E_(GetFfmpegCodec)( p_enc->i_fourcc, &i_cat, &i_codec_id, + if( !E_(GetFfmpegCodec)( p_enc->fmt_out.i_codec, &i_cat, &i_codec_id, &psz_namecodec ) ) { return VLC_EGENERIC; } - if( i_cat != VIDEO_ES ) + if( p_enc->fmt_out.i_cat == VIDEO_ES && i_cat != VIDEO_ES ) { msg_Err( p_enc, "\"%s\" is not a video encoder", psz_namecodec ); return VLC_EGENERIC; } + if( p_enc->fmt_out.i_cat == AUDIO_ES && i_cat != AUDIO_ES ) + { + msg_Err( p_enc, "\"%s\" is not an audio encoder", psz_namecodec ); + return VLC_EGENERIC; + } + /* Initialization must be done before avcodec_find_decoder() */ E_(InitLibavcodec)(p_this); @@ -134,41 +137,86 @@ int E_(OpenVideoEncoder)( vlc_object_t *p_this ) p_enc->p_sys = p_sys; p_sys->p_codec = p_codec; - p_enc->pf_header = NULL; p_enc->pf_encode_video = EncodeVideo; - p_enc->format.video.i_chroma = VLC_FOURCC('I','4','2','0'); + p_enc->pf_encode_audio = EncodeAudio; - if( p_enc->i_fourcc == VLC_FOURCC( 'm','p','1','v' ) || - p_enc->i_fourcc == VLC_FOURCC( 'm','p','2','v' ) ) + p_sys->p_buffer_out = NULL; + p_sys->p_buffer = NULL; + + p_sys->p_context = p_context = avcodec_alloc_context(); + + /* Set CPU capabilities */ +#ifdef HAVE_MMX + p_context->dsp_mask = 0; + if( p_enc->p_libvlc->i_cpu & CPU_CAPABILITY_MMX ) + { + p_context->dsp_mask &= FF_MM_MMX; + } + if( p_enc->p_libvlc->i_cpu & CPU_CAPABILITY_MMXEXT ) + { + p_context->dsp_mask &= FF_MM_MMXEXT; + } + if( p_enc->p_libvlc->i_cpu & CPU_CAPABILITY_3DNOW ) + { + p_context->dsp_mask &= FF_MM_3DNOW; + } + if( p_enc->p_libvlc->i_cpu & CPU_CAPABILITY_SSE ) { - p_enc->i_fourcc = VLC_FOURCC( 'm','p','g','v' ); + p_context->dsp_mask &= FF_MM_SSE; + p_context->dsp_mask &= FF_MM_SSE2; /* FIXME */ } + /* Hack to make sure everything can be disabled **/ + p_context->dsp_mask &= (FF_MM_FORCE >> 1); +#endif - p_sys->p_context = p_context = avcodec_alloc_context(); - p_context->width = p_enc->format.video.i_width; - p_context->height = p_enc->format.video.i_height; - p_context->bit_rate = p_enc->i_bitrate; + /* Make sure we get extradata filled by the encoder */ + p_context->extradata_size = 0; + p_context->extradata = NULL; + p_context->flags |= CODEC_FLAG_GLOBAL_HEADER; + + if( p_enc->fmt_in.i_cat == VIDEO_ES ) + { + p_context->width = p_enc->fmt_in.video.i_width; + p_context->height = p_enc->fmt_in.video.i_height; - p_context->frame_rate = p_enc->i_frame_rate; + p_context->frame_rate = p_enc->fmt_in.video.i_frame_rate; #if LIBAVCODEC_BUILD >= 4662 - p_context->frame_rate_base= p_enc->i_frame_rate_base; + p_context->frame_rate_base= p_enc->fmt_in.video.i_frame_rate_base; #endif #if LIBAVCODEC_BUILD >= 4687 - p_context->sample_aspect_ratio = - av_d2q( p_enc->i_aspect * p_context->height / p_context->width / - VOUT_ASPECT_FACTOR, 255 ); + p_context->sample_aspect_ratio = + av_d2q( p_enc->fmt_in.video.i_aspect * p_context->height / + p_context->width / VOUT_ASPECT_FACTOR, 255 ); #else - p_context->aspect_ratio = ((float)p_enc->i_aspect) / VOUT_ASPECT_FACTOR; + p_context->aspect_ratio = ((float)p_enc->fmt_in.video.i_aspect) / + VOUT_ASPECT_FACTOR; #endif - p_context->gop_size = p_enc->i_key_int >= 0 ? p_enc->i_key_int : 50; + p_sys->p_buffer_out = malloc( AVCODEC_MAX_VIDEO_FRAME_SIZE ); + + /* Ffmpeg does handle the conversion itself */ + //p_enc->fmt_in.i_codec = VLC_FOURCC('I','4','2','0'); + } + else if( p_enc->fmt_in.i_cat == AUDIO_ES ) + { + p_enc->fmt_in.i_codec = AOUT_FMT_S16_NE; + p_context->bit_rate = p_enc->fmt_out.i_bitrate; + p_context->sample_rate = p_enc->fmt_in.audio.i_rate; + p_context->channels = p_enc->fmt_in.audio.i_channels; + p_sys->i_frame_size = p_context->frame_size * 2 * p_context->channels; + p_sys->p_buffer = malloc( p_sys->i_frame_size ); + p_sys->p_buffer_out = malloc( 2 * AVCODEC_MAX_AUDIO_FRAME_SIZE ); + } + + /* Misc parameters */ + p_context->gop_size = p_enc->i_key_int > 0 ? p_enc->i_key_int : 50; p_context->max_b_frames = __MIN( p_enc->i_b_frames, FF_MAX_B_FRAMES ); p_context->b_frame_strategy = 0; p_context->b_quant_factor = 2.0; - if( p_enc->i_vtolerance >= 0 ) + if( p_enc->i_vtolerance > 0 ) { p_context->bit_rate_tolerance = p_enc->i_vtolerance; } @@ -186,7 +234,7 @@ int E_(OpenVideoEncoder)( vlc_object_t *p_this ) if( i_codec_id == CODEC_ID_RAWVIDEO ) { - p_context->pix_fmt = E_(GetFfmpegChroma)( p_enc->i_fourcc ); + p_context->pix_fmt = E_(GetFfmpegChroma)( p_enc->fmt_in.i_codec ); } /* Make sure we get extradata filled by the encoder */ @@ -194,19 +242,40 @@ int E_(OpenVideoEncoder)( vlc_object_t *p_this ) p_context->extradata = NULL; p_context->flags |= CODEC_FLAG_GLOBAL_HEADER; - if( avcodec_open( p_context, p_sys->p_codec ) ) + if( avcodec_open( p_context, p_codec ) ) { - msg_Err( p_enc, "cannot open encoder" ); - return VLC_EGENERIC; + if( p_enc->fmt_in.i_cat == AUDIO_ES && p_context->channels > 2 ) + { + p_context->channels = 2; + p_enc->fmt_in.audio.i_channels = 2; // FIXME + if( avcodec_open( p_context, p_codec ) ) + { + msg_Err( p_enc, "cannot open encoder" ); + return VLC_EGENERIC; + } + msg_Warn( p_enc, "stereo mode selected (codec limitation)" ); + } + else + { + msg_Err( p_enc, "cannot open encoder" ); + return VLC_EGENERIC; + } } - p_enc->i_extra_data = p_context->extradata_size; - p_enc->p_extra_data = p_context->extradata; + p_enc->fmt_out.i_extra = p_context->extradata_size; + p_enc->fmt_out.p_extra = p_context->extradata; p_context->flags &= ~CODEC_FLAG_GLOBAL_HEADER; - p_sys->p_buffer_out = malloc( AVCODEC_MAX_VIDEO_FRAME_SIZE ); + if( p_enc->fmt_in.i_cat == AUDIO_ES ) + { + p_sys->i_frame_size = p_context->frame_size * 2 * p_context->channels; + p_sys->p_buffer = malloc( p_sys->i_frame_size ); + } + p_sys->i_last_ref_pts = 0; p_sys->i_buggy_pts_detect = 0; + p_sys->i_samples_delay = 0; + p_sys->i_pts = 0; msg_Dbg( p_enc, "found encoder %s", psz_namecodec ); @@ -229,7 +298,7 @@ static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pict ) } /* Set the pts of the frame being encoded (segfaults with mpeg4!)*/ - if( p_enc->i_fourcc == VLC_FOURCC( 'm', 'p', 'g', 'v' ) ) + if( p_enc->fmt_out.i_codec == VLC_FOURCC( 'm', 'p', 'g', 'v' ) ) frame.pts = p_pict->date; else frame.pts = 0; @@ -250,8 +319,9 @@ static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pict ) p_sys->i_buggy_pts_detect = p_sys->p_context->coded_frame->pts; /* FIXME, 3-2 pulldown is not handled correctly */ - p_block->i_length = I64C(1000000) * p_enc->i_frame_rate_base / - p_enc->i_frame_rate; + p_block->i_length = I64C(1000000) * + p_enc->fmt_in.video.i_frame_rate_base / + p_enc->fmt_in.video.i_frame_rate; p_block->i_pts = p_sys->p_context->coded_frame->pts; if( !p_sys->p_context->delay || @@ -279,8 +349,9 @@ static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pict ) { /* Buggy libavcodec which doesn't update coded_frame->pts * correctly */ - p_block->i_length = I64C(1000000) * p_enc->i_frame_rate_base / - p_enc->i_frame_rate; + p_block->i_length = I64C(1000000) * + p_enc->fmt_in.video.i_frame_rate_base / + p_enc->fmt_in.video.i_frame_rate; p_block->i_dts = p_block->i_pts = p_pict->date; } @@ -290,118 +361,6 @@ static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pict ) return NULL; } -/***************************************************************************** - * CloseVideoEncoder: ffmpeg video encoder destruction - *****************************************************************************/ -void E_(CloseVideoEncoder)( vlc_object_t *p_this ) -{ - encoder_t *p_enc = (encoder_t *)p_this; - encoder_sys_t *p_sys = p_enc->p_sys; - - avcodec_close( p_sys->p_context ); - free( p_sys->p_context ); - free( p_sys->p_buffer_out ); - free( p_sys ); -} - -/***************************************************************************** - * OpenAudioEncoder: probe the encoder - *****************************************************************************/ -int E_(OpenAudioEncoder)( vlc_object_t *p_this ) -{ - encoder_t *p_enc = (encoder_t *)p_this; - encoder_sys_t *p_sys; - AVCodecContext *p_context; - AVCodec *p_codec; - int i_codec_id, i_cat; - char *psz_namecodec; - - if( !E_(GetFfmpegCodec)( p_enc->i_fourcc, &i_cat, &i_codec_id, - &psz_namecodec ) ) - { - return VLC_EGENERIC; - } - - if( i_cat != AUDIO_ES ) - { - msg_Err( p_enc, "\"%s\" is not an audio encoder", psz_namecodec ); - return VLC_EGENERIC; - } - - /* Initialization must be done before avcodec_find_decoder() */ - E_(InitLibavcodec)(p_this); - - p_codec = avcodec_find_encoder( i_codec_id ); - if( !p_codec ) - { - msg_Err( p_enc, "cannot find encoder %s", psz_namecodec ); - return VLC_EGENERIC; - } - - /* Allocate the memory needed to store the decoder's structure */ - if( ( p_sys = (encoder_sys_t *)malloc(sizeof(encoder_sys_t)) ) == NULL ) - { - msg_Err( p_enc, "out of memory" ); - return VLC_EGENERIC; - } - p_enc->p_sys = p_sys; - p_sys->p_codec = p_codec; - - p_enc->pf_header = NULL; - p_enc->pf_encode_audio = EncodeAudio; - p_enc->format.audio.i_format = VLC_FOURCC('s','1','6','n'); - - p_sys->p_context = p_context = avcodec_alloc_context(); - p_context->bit_rate = p_enc->i_bitrate; - p_context->sample_rate = p_enc->format.audio.i_rate; - p_context->channels = - aout_FormatNbChannels( &p_enc->format.audio ); - - /* Make sure we get extradata filled by the encoder */ - p_context->extradata_size = 0; - p_context->extradata = NULL; - p_context->flags |= CODEC_FLAG_GLOBAL_HEADER; - - if( avcodec_open( p_context, p_codec ) < 0 ) - { - if( p_context->channels > 2 ) - { - p_context->channels = 2; - //id->f_dst.i_channels = 2; - if( avcodec_open( p_context, p_codec ) < 0 ) - { - msg_Err( p_enc, "cannot open encoder" ); - return VLC_EGENERIC; - } - msg_Warn( p_enc, "stereo mode selected (codec limitation)" ); - } - else - { - msg_Err( p_enc, "cannot open encoder" ); - return VLC_EGENERIC; - } - } - - p_enc->i_extra_data = p_context->extradata_size; - p_enc->p_extra_data = p_context->extradata; - p_context->flags &= ~CODEC_FLAG_GLOBAL_HEADER; - - p_sys->i_frame_size = p_context->frame_size * 2 * p_context->channels; - p_sys->p_buffer = malloc( p_sys->i_frame_size ); - p_sys->p_buffer_out = malloc( 2 * AVCODEC_MAX_AUDIO_FRAME_SIZE ); - - msg_Warn( p_enc, "avcodec_setup_audio: %d %d %d %d", - p_context->frame_size, p_context->bit_rate, p_context->channels, - p_context->sample_rate ); - - p_sys->i_samples_delay = 0; - p_sys->i_pts = 0; - - msg_Dbg( p_enc, "found encoder %s", psz_namecodec ); - - return VLC_SUCCESS; -} - /**************************************************************************** * EncodeAudio: the whole thing ****************************************************************************/ @@ -416,7 +375,7 @@ static block_t *EncodeAudio( encoder_t *p_enc, aout_buffer_t *p_aout_buf ) p_sys->i_pts = p_aout_buf->start_date - (mtime_t)1000000 * (mtime_t)p_sys->i_samples_delay / - (mtime_t)p_enc->format.audio.i_rate; + (mtime_t)p_enc->fmt_in.audio.i_rate; p_sys->i_samples_delay += i_samples; @@ -484,16 +443,18 @@ static block_t *EncodeAudio( encoder_t *p_enc, aout_buffer_t *p_aout_buf ) } /***************************************************************************** - * CloseAudioEncoder: ffmpeg audio encoder destruction + * CloseEncoder: ffmpeg encoder destruction *****************************************************************************/ -void E_(CloseAudioEncoder)( vlc_object_t *p_this ) +void E_(CloseEncoder)( vlc_object_t *p_this ) { encoder_t *p_enc = (encoder_t *)p_this; encoder_sys_t *p_sys = p_enc->p_sys; avcodec_close( p_sys->p_context ); free( p_sys->p_context ); - free( p_sys->p_buffer ); - free( p_sys->p_buffer_out ); + + if( p_sys->p_buffer ) free( p_sys->p_buffer ); + if( p_sys->p_buffer_out ) free( p_sys->p_buffer_out ); + free( p_sys ); } diff --git a/modules/codec/ffmpeg/ffmpeg.c b/modules/codec/ffmpeg/ffmpeg.c index c6a9268488..b90f2d8e31 100644 --- a/modules/codec/ffmpeg/ffmpeg.c +++ b/modules/codec/ffmpeg/ffmpeg.c @@ -2,7 +2,7 @@ * ffmpeg.c: video decoder using ffmpeg library ***************************************************************************** * Copyright (C) 1999-2001 VideoLAN - * $Id: ffmpeg.c,v 1.58 2003/10/29 20:53:41 gbazin Exp $ + * $Id: ffmpeg.c,v 1.59 2003/11/16 21:07:31 gbazin Exp $ * * Authors: Laurent Aimar * Gildas Bazin @@ -29,15 +29,9 @@ #include #include -#include -#include #include #include -#ifdef HAVE_SYS_TIMES_H -# include -#endif - /* ffmpeg header */ #ifdef HAVE_FFMPEG_AVCODEC_H # include @@ -77,10 +71,7 @@ struct decoder_sys_t * Local prototypes ****************************************************************************/ static int OpenDecoder( vlc_object_t * ); -static int InitDecoder( decoder_t * ); -static int EndDecoder( decoder_t * ); - -static int b_ffmpeginit = 0; +static void CloseDecoder( vlc_object_t * ); /***************************************************************************** * Module descriptor @@ -90,7 +81,7 @@ vlc_module_begin(); /* decoder main module */ add_category_hint( N_("ffmpeg"), NULL, VLC_FALSE ); set_capability( "decoder", 70 ); - set_callbacks( OpenDecoder, NULL ); + set_callbacks( OpenDecoder, CloseDecoder ); set_description( _("ffmpeg audio/video decoder((MS)MPEG4,SVQ1,H263,WMV,WMA)") ); add_bool( "ffmpeg-dr", 1, NULL, DR_TEXT, DR_TEXT, VLC_TRUE ); @@ -115,18 +106,12 @@ vlc_module_begin(); set_callbacks( E_(OpenChroma), NULL ); set_description( _("ffmpeg chroma conversion") ); - /* video encoder submodule */ - add_submodule(); - set_description( _("ffmpeg video encoder") ); - set_capability( "video encoder", 100 ); - set_callbacks( E_(OpenVideoEncoder), E_(CloseVideoEncoder) ); - - /* audio encoder submodule */ - add_submodule(); - set_description( _("ffmpeg audio encoder") ); - set_capability( "audio encoder", 10 ); - set_callbacks( E_(OpenAudioEncoder), E_(CloseAudioEncoder) ); - + /* encoder submodule */ + add_submodule(); + set_description( _("ffmpeg audio/video encoder") ); + set_capability( "encoder", 100 ); + set_callbacks( E_(OpenEncoder), E_(CloseEncoder) ); + var_Create( p_module->p_libvlc, "avcodec", VLC_VAR_MUTEX ); vlc_module_end(); @@ -136,10 +121,14 @@ vlc_module_end(); static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*) p_this; - int i_cat, i_codec_id; + int i_cat, i_codec_id, i_result; char *psz_namecodec; - if( !E_(GetFfmpegCodec)( p_dec->p_fifo->i_fourcc, &i_cat, &i_codec_id, + AVCodecContext *p_context; + AVCodec *p_codec; + + /* *** determine codec type *** */ + if( !E_(GetFfmpegCodec)( p_dec->fmt_in.i_codec, &i_cat, &i_codec_id, &psz_namecodec ) ) { return VLC_EGENERIC; @@ -148,54 +137,51 @@ static int OpenDecoder( vlc_object_t *p_this ) /* Initialization must be done before avcodec_find_decoder() */ E_(InitLibavcodec)(p_this); - if( !avcodec_find_decoder( i_codec_id ) ) - { - msg_Dbg( p_dec, "codec not found (%s)", psz_namecodec ); - return VLC_EGENERIC; - } - - p_dec->pf_init = InitDecoder; - p_dec->pf_decode = (i_cat == VIDEO_ES) ? E_(DecodeVideo) : E_(DecodeAudio); - p_dec->pf_end = EndDecoder; - - return VLC_SUCCESS; -} - -/***************************************************************************** - * InitDecoder: Initalize the decoder - *****************************************************************************/ -static int InitDecoder( decoder_t *p_dec ) -{ - int i_cat, i_codec_id, i_result; - char *psz_namecodec; - AVCodecContext *p_context; - AVCodec *p_codec; - - /* *** determine codec type *** */ - E_(GetFfmpegCodec)( p_dec->p_fifo->i_fourcc, - &i_cat, &i_codec_id, &psz_namecodec ); - /* *** ask ffmpeg for a decoder *** */ if( !( p_codec = avcodec_find_decoder( i_codec_id ) ) ) { - msg_Err( p_dec, "codec not found (%s)", psz_namecodec ); + msg_Dbg( p_dec, "codec not found (%s)", psz_namecodec ); return VLC_EGENERIC; } /* *** get a p_context *** */ p_context = avcodec_alloc_context(); + /* Set CPU capabilities */ +#ifdef HAVE_MMX + p_context->dsp_mask = 0; + if( p_dec->p_libvlc->i_cpu & CPU_CAPABILITY_MMX ) + { + p_context->dsp_mask &= FF_MM_MMX; + } + if( p_dec->p_libvlc->i_cpu & CPU_CAPABILITY_MMXEXT ) + { + p_context->dsp_mask &= FF_MM_MMXEXT; + } + if( p_dec->p_libvlc->i_cpu & CPU_CAPABILITY_3DNOW ) + { + p_context->dsp_mask &= FF_MM_3DNOW; + } + if( p_enc->p_libvlc->i_cpu & CPU_CAPABILITY_SSE ) + { + p_context->dsp_mask &= FF_MM_SSE; + p_context->dsp_mask &= FF_MM_SSE2; /* FIXME */ + } + /* Hack to make sure everything can be disabled **/ + p_context->dsp_mask &= (FF_MM_FORCE >> 1); +#endif + switch( i_cat ) { case VIDEO_ES: + p_dec->pf_decode_video = E_(DecodeVideo); i_result = E_( InitVideoDec )( p_dec, p_context, p_codec, i_codec_id, psz_namecodec ); - p_dec->pf_decode = E_(DecodeVideo); break; case AUDIO_ES: + p_dec->pf_decode_audio = E_(DecodeAudio); i_result = E_( InitAudioDec )( p_dec, p_context, p_codec, i_codec_id, psz_namecodec ); - p_dec->pf_decode = E_(DecodeAudio); break; default: i_result = VLC_EGENERIC; @@ -205,12 +191,13 @@ static int InitDecoder( decoder_t *p_dec ) return i_result; } - + /***************************************************************************** - * EndDecoder: decoder destruction + * CloseDecoder: decoder destruction *****************************************************************************/ -static int EndDecoder( decoder_t *p_dec ) +static void CloseDecoder( vlc_object_t *p_this ) { + decoder_t *p_dec = (decoder_t *)p_this; decoder_sys_t *p_sys = p_dec->p_sys; if( !p_sys->p_context ) @@ -234,7 +221,6 @@ static int EndDecoder( decoder_t *p_dec ) } free( p_sys ); - return VLC_SUCCESS; } /***************************************************************************** @@ -692,12 +678,13 @@ int E_(GetFfmpegChroma)( vlc_fourcc_t i_chroma ) void E_(InitLibavcodec)( vlc_object_t *p_object ) { + static int b_ffmpeginit = 0; vlc_value_t lockval; var_Get( p_object->p_libvlc, "avcodec", &lockval ); vlc_mutex_lock( lockval.p_address ); - /* *** init ffmpeg library (libavcodec) *** */ + /* *** init ffmpeg library (libavcodec) *** */ if( !b_ffmpeginit ) { avcodec_init(); diff --git a/modules/codec/ffmpeg/ffmpeg.h b/modules/codec/ffmpeg/ffmpeg.h index 2393c21948..d4a57941b6 100644 --- a/modules/codec/ffmpeg/ffmpeg.h +++ b/modules/codec/ffmpeg/ffmpeg.h @@ -2,7 +2,7 @@ * ffmpeg.h: decoder using the ffmpeg library ***************************************************************************** * Copyright (C) 2001 VideoLAN - * $Id: ffmpeg.h,v 1.27 2003/10/27 01:04:38 gbazin Exp $ + * $Id: ffmpeg.h,v 1.28 2003/11/16 21:07:31 gbazin Exp $ * * Authors: Laurent Aimar * @@ -42,20 +42,20 @@ int E_(GetFfmpegChroma)( vlc_fourcc_t ); int E_( InitVideoDec )( decoder_t *, AVCodecContext *, AVCodec *, int, char * ); void E_( EndVideoDec ) ( decoder_t * ); -int E_( DecodeVideo ) ( decoder_t *, block_t * ); +picture_t *E_( DecodeVideo ) ( decoder_t *, block_t ** ); /* Audio decoder module */ int E_( InitAudioDec )( decoder_t *, AVCodecContext *, AVCodec *, int, char * ); void E_( EndAudioDec ) ( decoder_t * ); -int E_( DecodeAudio ) ( decoder_t *, block_t * ); +aout_buffer_t *E_( DecodeAudio ) ( decoder_t *, block_t ** ); /* Chroma conversion module */ int E_(OpenChroma)( vlc_object_t * ); /* Video encoder module */ -int E_(OpenVideoEncoder) ( vlc_object_t * ); -void E_(CloseVideoEncoder)( vlc_object_t * ); +int E_(OpenEncoder) ( vlc_object_t * ); +void E_(CloseEncoder)( vlc_object_t * ); /* Audio encoder module */ int E_(OpenAudioEncoder) ( vlc_object_t * ); diff --git a/modules/codec/ffmpeg/video.c b/modules/codec/ffmpeg/video.c index 1349a26c4c..74ed35ab2a 100644 --- a/modules/codec/ffmpeg/video.c +++ b/modules/codec/ffmpeg/video.c @@ -2,7 +2,7 @@ * video.c: video decoder using the ffmpeg library ***************************************************************************** * Copyright (C) 1999-2001 VideoLAN - * $Id: video.c,v 1.43 2003/10/28 14:17:52 gbazin Exp $ + * $Id: video.c,v 1.44 2003/11/16 21:07:31 gbazin Exp $ * * Authors: Laurent Aimar * Gildas Bazin @@ -29,14 +29,9 @@ #include #include -#include #include #include -#ifdef HAVE_SYS_TIMES_H -# include -#endif - /* ffmpeg header */ #ifdef HAVE_FFMPEG_AVCODEC_H # include @@ -66,11 +61,8 @@ struct decoder_sys_t AVFrame *p_ff_pic; BITMAPINFOHEADER *p_format; - vout_thread_t *p_vout; - /* for frame skipping algo */ int b_hurry_up; - int i_frame_error; int i_frame_skip; /* how many decoded frames are late */ @@ -82,11 +74,12 @@ struct decoder_sys_t vlc_bool_t b_has_b_frames; - int i_buffer; - char *p_buffer; + int i_buffer_orig, i_buffer; + char *p_buffer_orig, *p_buffer; /* Postprocessing handle */ void *p_pp; + vlc_bool_t b_pp_init; }; /***************************************************************************** @@ -99,20 +92,31 @@ static void ffmpeg_ReleaseFrameBuf( struct AVCodecContext *, AVFrame * ); /***************************************************************************** * Local Functions *****************************************************************************/ -static inline uint32_t ffmpeg_PixFmtToChroma( int i_ff_chroma ) +static uint32_t ffmpeg_PixFmtToChroma( int i_ff_chroma ) { - /* FIXME FIXME some of them are wrong */ switch( i_ff_chroma ) { case PIX_FMT_YUV420P: - case PIX_FMT_YUV422: - return( VLC_FOURCC('I','4','2','0') ); - case PIX_FMT_RGB24: - return( VLC_FOURCC('R','V','2','4') ); + return VLC_FOURCC('I','4','2','0'); case PIX_FMT_YUV422P: - return( VLC_FOURCC('I','4','2','2') ); + return VLC_FOURCC('I','4','2','2'); case PIX_FMT_YUV444P: - return( VLC_FOURCC('I','4','4','4') ); + return VLC_FOURCC('I','4','4','4'); + + case PIX_FMT_YUV422: + return VLC_FOURCC('Y','U','Y','2'); + + case PIX_FMT_RGB555: + return VLC_FOURCC('R','V','1','5'); + case PIX_FMT_RGB565: + return VLC_FOURCC('R','V','1','6'); + case PIX_FMT_RGB24: + return VLC_FOURCC('R','V','2','4'); + case PIX_FMT_RGBA32: + return VLC_FOURCC('R','V','3','2'); + case PIX_FMT_GRAY8: + return VLC_FOURCC('G','R','E','Y'); + case PIX_FMT_YUV410P: case PIX_FMT_YUV411P: case PIX_FMT_BGR24: @@ -121,50 +125,54 @@ static inline uint32_t ffmpeg_PixFmtToChroma( int i_ff_chroma ) } } -/* Return a Vout */ -static vout_thread_t *ffmpeg_CreateVout( decoder_t *p_dec, - AVCodecContext *p_context ) +/* Returns a new picture buffer */ +static inline picture_t *ffmpeg_NewPictBuf( decoder_t *p_dec, + AVCodecContext *p_context ) { - vout_thread_t *p_vout; - unsigned int i_width = p_context->width; - unsigned int i_height = p_context->height; - uint32_t i_chroma = ffmpeg_PixFmtToChroma( p_context->pix_fmt ); - unsigned int i_aspect; + decoder_sys_t *p_sys = p_dec->p_sys; + picture_t *p_pic; - if( !i_width || !i_height ) + p_dec->fmt_out.video.i_width = p_context->width; + p_dec->fmt_out.video.i_height = p_context->height; + p_dec->fmt_out.i_codec = ffmpeg_PixFmtToChroma( p_context->pix_fmt ); + + if( !p_context->width || !p_context->height ) { - return( NULL ); /* Can't create a new vout without display size */ + return NULL; /* invalid display size */ } - if( !i_chroma ) + if( !p_dec->fmt_out.i_codec ) { /* we make conversion if possible*/ - i_chroma = VLC_FOURCC('I','4','2','0'); + p_dec->fmt_out.i_codec = VLC_FOURCC('I','4','2','0'); } #if LIBAVCODEC_BUILD >= 4687 - i_aspect = VOUT_ASPECT_FACTOR * ( av_q2d(p_context->sample_aspect_ratio) * - p_context->width / p_context->height ); + p_dec->fmt_out.video.i_aspect = + VOUT_ASPECT_FACTOR * ( av_q2d(p_context->sample_aspect_ratio) * + p_context->width / p_context->height ); #else - i_aspect = VOUT_ASPECT_FACTOR * p_context->aspect_ratio; + p_dec->fmt_out.video.i_aspect = + VOUT_ASPECT_FACTOR * p_context->aspect_ratio; #endif - if( i_aspect == 0 ) + if( p_dec->fmt_out.video.i_aspect == 0 ) { - i_aspect = VOUT_ASPECT_FACTOR * i_width / i_height; + p_dec->fmt_out.video.i_aspect = + VOUT_ASPECT_FACTOR * p_context->width / p_context->height; } - /* Spawn a video output if there is none. First we look for our children, - * then we look for any other vout that might be available. */ - p_vout = vout_Request( p_dec, p_dec->p_sys->p_vout, - i_width, i_height, i_chroma, i_aspect ); + p_pic = p_dec->pf_vout_buffer_new( p_dec ); #ifdef LIBAVCODEC_PP - if( p_dec->p_sys->p_pp ) - E_(InitPostproc)( p_dec, p_dec->p_sys->p_pp, i_width, i_height, - p_context->pix_fmt ); + if( p_sys->p_pp && !p_sys->b_pp_init ) + { + E_(InitPostproc)( p_dec, p_sys->p_pp, p_context->width, + p_context->height, p_context->pix_fmt ); + p_sys->b_pp_init = VLC_TRUE; + } #endif - return p_vout; + return p_pic; } /***************************************************************************** @@ -194,18 +202,9 @@ int E_(InitVideoDec)( decoder_t *p_dec, AVCodecContext *p_context, p_dec->p_sys->psz_namecodec = psz_namecodec; p_sys->p_ff_pic = avcodec_alloc_frame(); - if( ( p_sys->p_format = - (BITMAPINFOHEADER *)p_dec->p_fifo->p_bitmapinfoheader ) != NULL ) - { - /* ***** Fill p_context with init values ***** */ - p_sys->p_context->width = p_sys->p_format->biWidth; - p_sys->p_context->height = p_sys->p_format->biHeight; - } - else - { - msg_Warn( p_dec, "display informations missing" ); - p_sys->p_format = NULL; - } + /* ***** Fill p_context with init values ***** */ + p_sys->p_context->width = p_dec->fmt_in.video.i_width; + p_sys->p_context->height = p_dec->fmt_in.video.i_height; /* ***** Get configuration of ffmpeg plugin ***** */ i_tmp = config_GetInt( p_dec, "ffmpeg-workaround-bugs" ); @@ -258,6 +257,7 @@ int E_(InitVideoDec)( decoder_t *p_dec, AVCodecContext *p_context, #ifdef LIBAVCODEC_PP p_sys->p_pp = NULL; + p_dec->p_sys->b_pp_init = VLC_FALSE; if( E_(OpenPostproc)( p_dec, &p_sys->p_pp ) == VLC_SUCCESS ) { /* for now we cannot do postproc and dr */ @@ -280,16 +280,15 @@ int E_(InitVideoDec)( decoder_t *p_dec, AVCodecContext *p_context, p_sys->p_context->opaque = p_dec; /* ***** init this codec with special data ***** */ - if( p_sys->p_format && p_sys->p_format->biSize > sizeof(BITMAPINFOHEADER) ) + if( p_dec->fmt_in.i_extra ) { int b_gotpicture; - int i_size = p_sys->p_format->biSize - sizeof(BITMAPINFOHEADER); + int i_size = p_dec->fmt_in.i_extra; if( p_sys->i_codec_id == CODEC_ID_MPEG4 ) { uint8_t *p_vol = malloc( i_size + FF_INPUT_BUFFER_PADDING_SIZE ); - - memcpy( p_vol, &p_sys->p_format[1], i_size ); + memcpy( p_vol, p_dec->fmt_in.p_extra, i_size ); memset( &p_vol[i_size], 0, FF_INPUT_BUFFER_PADDING_SIZE ); avcodec_decode_video( p_sys->p_context, p_sys->p_ff_pic, @@ -307,7 +306,7 @@ int E_(InitVideoDec)( decoder_t *p_dec, AVCodecContext *p_context, memcpy( &p[0], "SVQ3", 4 ); memset( &p[4], 0, 8 ); - memcpy( &p[12], &p_sys->p_format[1], i_size ); + memcpy( &p[12], p_dec->fmt_in.p_extra, i_size ); } #endif else @@ -316,20 +315,24 @@ int E_(InitVideoDec)( decoder_t *p_dec, AVCodecContext *p_context, p_sys->p_context->extradata = malloc( i_size + FF_INPUT_BUFFER_PADDING_SIZE ); memcpy( p_sys->p_context->extradata, - &p_sys->p_format[1], i_size ); + p_dec->fmt_in.p_extra, i_size ); memset( &((uint8_t*)p_sys->p_context->extradata)[i_size], 0, FF_INPUT_BUFFER_PADDING_SIZE ); } } /* ***** misc init ***** */ - p_sys->p_vout = NULL; p_sys->input_pts = 0; p_sys->i_pts = 0; p_sys->b_has_b_frames = VLC_FALSE; p_sys->i_late_frames = 0; - p_sys->i_buffer = 1; - p_sys->p_buffer = malloc( p_sys->i_buffer ); + p_sys->i_buffer = 0; + p_sys->i_buffer_orig = 1; + p_sys->p_buffer_orig = p_sys->p_buffer = malloc( p_sys->i_buffer ); + + /* Set output properties */ + p_dec->fmt_out.i_cat = VIDEO_ES; + p_dec->fmt_out.i_codec = ffmpeg_PixFmtToChroma( p_context->pix_fmt ); return VLC_SUCCESS; } @@ -337,17 +340,22 @@ int E_(InitVideoDec)( decoder_t *p_dec, AVCodecContext *p_context, /***************************************************************************** * DecodeVideo: Called to decode one or more frames *****************************************************************************/ -int E_(DecodeVideo)( decoder_t *p_dec, block_t *p_block ) +picture_t *E_(DecodeVideo)( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; - int i_buffer, b_drawpicture; - char *p_buffer; + int b_drawpicture; + block_t *p_block; + + if( !pp_block || !*pp_block ) return NULL; + + p_block = *pp_block; if( p_block->i_pts > 0 ) { p_sys->input_pts = p_block->i_pts; } +#if 0 /* TODO implement it in a better way */ /* A good idea could be to decode all I pictures and see for the other */ if( p_sys->b_hurry_up && p_sys->i_late_frames > 4 ) @@ -364,7 +372,8 @@ int E_(DecodeVideo)( decoder_t *p_dec, block_t *p_block ) p_sys->i_late_frames--; /* needed else it will never be decrease */ block_Release( p_block ); - return VLC_SUCCESS; + p_sys->i_buffer = 0; + return NULL; } } else @@ -383,6 +392,7 @@ int E_(DecodeVideo)( decoder_t *p_dec, block_t *p_block ) p_sys->i_late_frames--; return VLC_SUCCESS; } +#endif if( !p_sys->p_context->width || !p_sys->p_context->height ) { @@ -395,36 +405,46 @@ int E_(DecodeVideo)( decoder_t *p_dec, block_t *p_block ) /* Don't forget that ffmpeg requires a little more bytes * that the real frame size */ - i_buffer = p_block->i_buffer; - if( i_buffer + FF_INPUT_BUFFER_PADDING_SIZE > p_sys->i_buffer ) + if( p_block->i_buffer ) { - free( p_sys->p_buffer ); - p_sys->i_buffer = i_buffer + FF_INPUT_BUFFER_PADDING_SIZE; - p_sys->p_buffer = malloc( p_sys->i_buffer ); + p_sys->i_buffer = p_block->i_buffer; + if( p_sys->i_buffer + FF_INPUT_BUFFER_PADDING_SIZE > + p_sys->i_buffer_orig ) + { + free( p_sys->p_buffer_orig ); + p_sys->i_buffer_orig = + p_block->i_buffer + FF_INPUT_BUFFER_PADDING_SIZE; + p_sys->p_buffer_orig = malloc( p_sys->i_buffer_orig ); + } + p_sys->p_buffer = p_sys->p_buffer_orig; + p_sys->i_buffer = p_block->i_buffer; + p_dec->p_vlc->pf_memcpy( p_sys->p_buffer, p_block->p_buffer, + p_block->i_buffer ); + memset( p_sys->p_buffer + p_block->i_buffer, 0, + FF_INPUT_BUFFER_PADDING_SIZE ); + + p_block->i_buffer = 0; } - p_buffer = p_sys->p_buffer; - p_dec->p_vlc->pf_memcpy( p_buffer, p_block->p_buffer, p_block->i_buffer ); - memset( p_buffer + i_buffer, 0, FF_INPUT_BUFFER_PADDING_SIZE ); - while( i_buffer ) + while( p_sys->i_buffer ) { int i_used, b_gotpicture; picture_t *p_pic; i_used = avcodec_decode_video( p_sys->p_context, p_sys->p_ff_pic, &b_gotpicture, - p_buffer, i_buffer ); + p_sys->p_buffer, p_sys->i_buffer ); if( i_used < 0 ) { - msg_Warn( p_dec, "cannot decode one frame (%d bytes)", i_buffer ); - p_sys->i_frame_error++; + msg_Warn( p_dec, "cannot decode one frame (%d bytes)", + p_sys->i_buffer ); block_Release( p_block ); - return VLC_SUCCESS; + return NULL; } /* Consumed bytes */ - i_buffer -= i_used; - p_buffer += i_used; + p_sys->i_buffer -= i_used; + p_sys->p_buffer += i_used; /* Nothing to display */ if( !b_gotpicture ) continue; @@ -449,23 +469,12 @@ int E_(DecodeVideo)( decoder_t *p_dec, block_t *p_block ) if( !p_sys->b_direct_rendering ) { - p_sys->p_vout = ffmpeg_CreateVout( p_dec, p_sys->p_context ); - if( !p_sys->p_vout ) - { - msg_Err( p_dec, "cannot create vout" ); - block_Release( p_block ); - return VLC_EGENERIC; - } - /* Get a new picture */ - while( !(p_pic = vout_CreatePicture( p_sys->p_vout, 0, 0, 0 ) ) ) + p_pic = ffmpeg_NewPictBuf( p_dec, p_sys->p_context ); + if( !p_pic ) { - if( p_dec->p_fifo->b_die || p_dec->p_fifo->b_error ) - { - block_Release( p_block ); - return VLC_EGENERIC; - } - msleep( VOUT_OUTMEM_SLEEP ); + block_Release( p_block ); + return NULL; } /* Fill p_picture_t from AVVideoFrame and do chroma conversion @@ -493,8 +502,7 @@ int E_(DecodeVideo)( decoder_t *p_dec, block_t *p_block ) /* Send decoded frame to vout */ if( p_sys->i_pts ) { - vout_DatePicture( p_sys->p_vout, p_pic, p_sys->i_pts ); - vout_DisplayPicture( p_sys->p_vout, p_pic ); + p_pic->date = p_sys->i_pts; /* interpolate the next PTS */ if( p_sys->p_context->frame_rate > 0 ) @@ -504,11 +512,16 @@ int E_(DecodeVideo)( decoder_t *p_dec, block_t *p_block ) p_sys->p_context->frame_rate_base / (2 * p_sys->p_context->frame_rate); } + return p_pic; + } + else + { + p_dec->pf_vout_buffer_del( p_dec, p_pic ); } } block_Release( p_block ); - return VLC_SUCCESS; + return NULL; } /***************************************************************************** @@ -527,10 +540,7 @@ void E_(EndVideoDec)( decoder_t *p_dec ) E_(ClosePostproc)( p_dec, p_sys->p_pp ); #endif - free( p_sys->p_buffer ); - - /* We are about to die. Reattach video output to p_vlc. */ - vout_Request( p_dec, p_sys->p_vout, 0, 0, 0, 0 ); + free( p_sys->p_buffer_orig ); } /***************************************************************************** @@ -632,28 +642,14 @@ static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context, return avcodec_default_get_buffer( p_context, p_ff_pic ); } - /* Check and (re)create our vout if needed */ - p_sys->p_vout = ffmpeg_CreateVout( p_dec, p_sys->p_context ); - if( !p_sys->p_vout ) + /* Get a new picture */ + //p_sys->p_vout->render.b_allow_modify_pics = 0; + p_pic = ffmpeg_NewPictBuf( p_dec, p_sys->p_context ); + if( !p_pic ) { - msg_Err( p_dec, "cannot create vout" ); - p_dec->p_fifo->b_error = 1; /* abort */ p_sys->b_direct_rendering = 0; return avcodec_default_get_buffer( p_context, p_ff_pic ); } - - p_sys->p_vout->render.b_allow_modify_pics = 0; - - /* Get a new picture */ - while( !(p_pic = vout_CreatePicture( p_sys->p_vout, 0, 0, 0 ) ) ) - { - if( p_dec->p_fifo->b_die || p_dec->p_fifo->b_error ) - { - p_sys->b_direct_rendering = 0; - return avcodec_default_get_buffer( p_context, p_ff_pic ); - } - msleep( VOUT_OUTMEM_SLEEP ); - } p_sys->p_context->draw_horiz_band = NULL; p_ff_pic->opaque = (void*)p_pic; @@ -670,20 +666,19 @@ static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context, if( p_ff_pic->reference != 0 ) { - vout_LinkPicture( p_sys->p_vout, p_pic ); + //vout_LinkPicture( p_sys->p_vout, p_pic ); } /* FIXME what is that, should give good value */ p_ff_pic->age = 256*256*256*64; // FIXME FIXME from ffmpeg - return( 0 ); + return 0; } -static void ffmpeg_ReleaseFrameBuf( struct AVCodecContext *p_context, - AVFrame *p_ff_pic ) +static void ffmpeg_ReleaseFrameBuf( struct AVCodecContext *p_context, + AVFrame *p_ff_pic ) { decoder_t *p_dec = (decoder_t *)p_context->opaque; - decoder_sys_t *p_sys = p_dec->p_sys; picture_t *p_pic; if( p_ff_pic->type != FF_BUFFER_TYPE_USER ) @@ -701,6 +696,6 @@ static void ffmpeg_ReleaseFrameBuf( struct AVCodecContext *p_context, if( p_ff_pic->reference != 0 ) { - vout_UnlinkPicture( p_sys->p_vout, p_pic ); + //vout_UnlinkPicture( p_sys->p_vout, p_pic ); } } diff --git a/modules/codec/flacdec.c b/modules/codec/flacdec.c index 4f3c886280..3b0cd72da7 100644 --- a/modules/codec/flacdec.c +++ b/modules/codec/flacdec.c @@ -2,7 +2,7 @@ * flac.c: flac decoder module making use of libflac ***************************************************************************** * Copyright (C) 1999-2001 VideoLAN - * $Id: flacdec.c,v 1.4 2003/09/02 20:19:25 gbazin Exp $ + * $Id: flacdec.c,v 1.5 2003/11/16 21:07:30 gbazin Exp $ * * Authors: Sigmund Augdal * @@ -116,7 +116,7 @@ static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; - if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('f','l','a','c') ) + if( p_dec->fmt_in.i_codec != VLC_FOURCC('f','l','a','c') ) { return VLC_EGENERIC; } diff --git a/modules/codec/libmpeg2.c b/modules/codec/libmpeg2.c index bef10b689b..d80b1829ad 100755 --- a/modules/codec/libmpeg2.c +++ b/modules/codec/libmpeg2.c @@ -2,7 +2,7 @@ * libmpeg2.c: mpeg2 video decoder module making use of libmpeg2. ***************************************************************************** * Copyright (C) 1999-2001 VideoLAN - * $Id: libmpeg2.c,v 1.32 2003/11/04 17:46:17 gbazin Exp $ + * $Id: libmpeg2.c,v 1.33 2003/11/16 21:07:30 gbazin Exp $ * * Authors: Gildas Bazin * Christophe Massiot @@ -72,18 +72,18 @@ struct decoder_sys_t /* * Output properties */ - vout_thread_t *p_vout; vout_synchro_t *p_synchro; + int i_aspect; }; /***************************************************************************** * Local prototypes *****************************************************************************/ -static int OpenDecoder( vlc_object_t * ); -static int InitDecoder( decoder_t * ); -static int RunDecoder ( decoder_t *, block_t * ); -static int EndDecoder ( decoder_t * ); +static int OpenDecoder( vlc_object_t * ); +static void CloseDecoder( vlc_object_t * ); + +static picture_t *DecodeBlock( decoder_t *, block_t ** ); static picture_t *GetNewPicture( decoder_t *, uint8_t ** ); @@ -93,7 +93,7 @@ static picture_t *GetNewPicture( decoder_t *, uint8_t ** ); vlc_module_begin(); set_description( _("MPEG I/II video decoder (using libmpeg2)") ); set_capability( "decoder", 150 ); - set_callbacks( OpenDecoder, NULL ); + set_callbacks( OpenDecoder, CloseDecoder ); add_shortcut( "libmpeg2" ); vlc_module_end(); @@ -103,32 +103,21 @@ vlc_module_end(); static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; + decoder_sys_t *p_sys; - if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('m','p','g','v') && - p_dec->p_fifo->i_fourcc != VLC_FOURCC('m','p','g','1') && + if( p_dec->fmt_in.i_codec != VLC_FOURCC('m','p','g','v') && + p_dec->fmt_in.i_codec != VLC_FOURCC('m','p','g','1') && /* Pinnacle hardware-mpeg1 */ - p_dec->p_fifo->i_fourcc != VLC_FOURCC('P','I','M','1') && + p_dec->fmt_in.i_codec != VLC_FOURCC('P','I','M','1') && /* ATI Video */ - p_dec->p_fifo->i_fourcc != VLC_FOURCC('V','C','R','2') && - p_dec->p_fifo->i_fourcc != VLC_FOURCC('m','p','g','2') ) + p_dec->fmt_in.i_codec != VLC_FOURCC('V','C','R','2') && + p_dec->fmt_in.i_codec != VLC_FOURCC('m','p','g','2') ) { return VLC_EGENERIC; } - p_dec->pf_init = InitDecoder; - p_dec->pf_decode = RunDecoder; - p_dec->pf_end = EndDecoder; - - return VLC_SUCCESS; -} - -/***************************************************************************** - * InitDecoder: Initalize the decoder - *****************************************************************************/ -static int InitDecoder( decoder_t *p_dec ) -{ /* Allocate the memory needed to store the decoder's structure */ - if( ( p_dec->p_sys = + if( ( p_dec->p_sys = p_sys = (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL ) { msg_Err( p_dec, "out of memory" ); @@ -136,30 +125,31 @@ static int InitDecoder( decoder_t *p_dec ) } /* Initialize the thread properties */ - memset( p_dec->p_sys, 0, sizeof(decoder_sys_t) ); - p_dec->p_sys->p_pes = NULL; - p_dec->p_sys->p_vout = NULL; - p_dec->p_sys->p_mpeg2dec = NULL; - p_dec->p_sys->p_synchro = NULL; - p_dec->p_sys->p_info = NULL; - p_dec->p_sys->i_pts = mdate() + DEFAULT_PTS_DELAY; - p_dec->p_sys->i_current_pts = 0; - p_dec->p_sys->i_previous_pts = 0; - p_dec->p_sys->p_picture_to_destroy = NULL; - p_dec->p_sys->b_garbage_pic = 0; - p_dec->p_sys->b_slice_i = 0; - p_dec->p_sys->b_skip = 0; + memset( p_sys, 0, sizeof(decoder_sys_t) ); + p_sys->p_pes = NULL; + p_sys->p_mpeg2dec = NULL; + p_sys->p_synchro = NULL; + p_sys->p_info = NULL; + p_sys->i_pts = mdate() + DEFAULT_PTS_DELAY; + p_sys->i_current_pts = 0; + p_sys->i_previous_pts = 0; + p_sys->p_picture_to_destroy = NULL; + p_sys->b_garbage_pic = 0; + p_sys->b_slice_i = 0; + p_sys->b_skip = 0; /* Initialize decoder */ - p_dec->p_sys->p_mpeg2dec = mpeg2_init(); - if( p_dec->p_sys->p_mpeg2dec == NULL) + p_sys->p_mpeg2dec = mpeg2_init(); + if( p_sys->p_mpeg2dec == NULL) { msg_Err( p_dec, "mpeg2_init() failed" ); - free( p_dec->p_sys ); + free( p_sys ); return VLC_EGENERIC; } - p_dec->p_sys->p_info = mpeg2_info( p_dec->p_sys->p_mpeg2dec ); + p_sys->p_info = mpeg2_info( p_sys->p_mpeg2dec ); + + p_dec->pf_decode_video = DecodeBlock; return VLC_SUCCESS; } @@ -167,32 +157,29 @@ static int InitDecoder( decoder_t *p_dec ) /***************************************************************************** * RunDecoder: the libmpeg2 decoder *****************************************************************************/ -static int RunDecoder( decoder_t *p_dec, block_t *p_block ) +static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; mpeg2_state_t state; picture_t *p_pic; - int i_aspect; - vlc_bool_t b_need_more_data = VLC_FALSE; + block_t *p_block; + + if( !pp_block || !*pp_block ) return NULL; + + p_block = *pp_block; while( 1 ) { - if( p_dec->p_fifo->b_die || p_dec->p_fifo->b_error ) - { - block_Release( p_block ); - return VLC_EGENERIC; - } - state = mpeg2_parse( p_sys->p_mpeg2dec ); switch( state ) { case STATE_BUFFER: - if( !p_block->i_buffer || b_need_more_data ) + if( !p_block->i_buffer ) { block_Release( p_block ); - return VLC_SUCCESS; + return NULL; } if( p_block->b_discontinuity && p_sys->p_synchro @@ -215,16 +202,6 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) } p_sys->p_picture_to_destroy = p_pic; - memset( p_pic->p[0].p_pixels, 0, - p_sys->p_info->sequence->width - * p_sys->p_info->sequence->height ); - memset( p_pic->p[1].p_pixels, 0x80, - p_sys->p_info->sequence->width - * p_sys->p_info->sequence->height / 4 ); - memset( p_pic->p[2].p_pixels, 0x80, - p_sys->p_info->sequence->width - * p_sys->p_info->sequence->height / 4 ); - if ( p_sys->b_slice_i ) { vout_SynchroNewPicture( p_sys->p_synchro, @@ -246,7 +223,7 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) mpeg2_buffer( p_sys->p_mpeg2dec, p_block->p_buffer, p_block->p_buffer + p_block->i_buffer ); - b_need_more_data = VLC_TRUE; + p_block->i_buffer = 0; break; case STATE_SEQUENCE: @@ -255,25 +232,24 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) uint8_t *buf[3]; buf[0] = buf[1] = buf[2] = NULL; - /* Check whether the input gives a particular aspect ratio */ - if( p_dec->p_fifo->p_demux_data - && ( *(int*)(p_dec->p_fifo->p_demux_data) & 0x7 ) ) + /* Check whether the input gave a particular aspect ratio */ + if( p_dec->fmt_in.video.i_aspect ) { - i_aspect = *(int*)(p_dec->p_fifo->p_demux_data); - switch( i_aspect ) + p_sys->i_aspect = p_dec->fmt_in.video.i_aspect; + switch( p_sys->i_aspect ) { case AR_3_4_PICTURE: - i_aspect = VOUT_ASPECT_FACTOR * 4 / 3; + p_sys->i_aspect = VOUT_ASPECT_FACTOR * 4 / 3; break; case AR_16_9_PICTURE: - i_aspect = VOUT_ASPECT_FACTOR * 16 / 9; + p_sys->i_aspect = VOUT_ASPECT_FACTOR * 16 / 9; break; case AR_221_1_PICTURE: - i_aspect = VOUT_ASPECT_FACTOR * 221 / 100; + p_sys->i_aspect = VOUT_ASPECT_FACTOR * 221 / 100; break; case AR_SQUARE_PICTURE: default: - i_aspect = VOUT_ASPECT_FACTOR * + p_sys->i_aspect = VOUT_ASPECT_FACTOR * p_sys->p_info->sequence->width / p_sys->p_info->sequence->height; break; @@ -282,73 +258,42 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) else { /* Use the value provided in the MPEG sequence header */ - i_aspect = ((uint64_t)p_sys->p_info->sequence->display_width) * + p_sys->i_aspect = + ((uint64_t)p_sys->p_info->sequence->display_width) * p_sys->p_info->sequence->pixel_width * VOUT_ASPECT_FACTOR / p_sys->p_info->sequence->display_height / p_sys->p_info->sequence->pixel_height; } - if ( p_dec->p_sys->p_vout != NULL ) - { - int i_pic; - /* Temporary hack to free the pictures in use by libmpeg2 */ - for ( i_pic = 0; i_pic < p_dec->p_sys->p_vout->render.i_pictures; i_pic++ ) - { - if( p_dec->p_sys->p_vout->render.pp_picture[i_pic]->i_status == - RESERVED_PICTURE ) - vout_DestroyPicture( p_dec->p_sys->p_vout, - p_dec->p_sys->p_vout->render.pp_picture[i_pic] ); - if( p_dec->p_sys->p_vout->render.pp_picture[i_pic]->i_refcount > 0 ) - vout_UnlinkPicture( p_dec->p_sys->p_vout, - p_dec->p_sys->p_vout->render.pp_picture[i_pic] ); - } - } - - p_sys->p_vout = vout_Request( p_dec, p_sys->p_vout, - p_sys->p_info->sequence->width, - p_sys->p_info->sequence->height, - VLC_FOURCC('Y','V','1','2'), - i_aspect ); - - if(p_sys->p_vout == NULL ) - { - msg_Err( p_dec, "cannot create vout" ); - block_Release( p_block ); - return -1; - } - msg_Dbg( p_dec, "%dx%d, aspect %d, %u.%03u fps", p_sys->p_info->sequence->width, - p_sys->p_info->sequence->height, i_aspect, + p_sys->p_info->sequence->height, p_sys->i_aspect, (uint32_t)((uint64_t)1001000000 * 27 / - p_sys->p_info->sequence->frame_period / 1001), + p_sys->p_info->sequence->frame_period / 1001), (uint32_t)((uint64_t)1001000000 * 27 / - p_sys->p_info->sequence->frame_period % 1001) ); + p_sys->p_info->sequence->frame_period % 1001) ); mpeg2_custom_fbuf( p_sys->p_mpeg2dec, 1 ); /* Set the first 2 reference frames */ mpeg2_set_buf( p_sys->p_mpeg2dec, buf, NULL ); - if( (p_pic = GetNewPicture( p_dec, buf )) == NULL ) break; - memset( p_pic->p[0].p_pixels, 0, - p_sys->p_info->sequence->width - * p_sys->p_info->sequence->height ); - memset( p_pic->p[1].p_pixels, 0x80, - p_sys->p_info->sequence->width - * p_sys->p_info->sequence->height / 4 ); - memset( p_pic->p[2].p_pixels, 0x80, - p_sys->p_info->sequence->width - * p_sys->p_info->sequence->height / 4 ); + if( (p_pic = GetNewPicture( p_dec, buf )) == NULL ) + { + block_Release( p_block ); + return NULL; + } + mpeg2_set_buf( p_sys->p_mpeg2dec, buf, p_pic ); + /* This picture will never go through display_picture. */ - vout_DatePicture( p_sys->p_vout, p_pic, 0 ); - vout_DisplayPicture( p_sys->p_vout, p_pic ); + p_pic->date = 0; + /* For some reason, libmpeg2 will put this pic twice in * discard_picture. This can be considered a bug in libmpeg2. */ - vout_LinkPicture( p_sys->p_vout, p_pic ); + //vout_LinkPicture( p_sys->p_vout, p_pic ); - if ( p_sys->p_synchro ) + if( p_sys->p_synchro ) { vout_SynchroRelease( p_sys->p_synchro ); } @@ -363,10 +308,9 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) vout_SynchroNewPicture( p_sys->p_synchro, p_sys->p_info->current_picture->flags & PIC_MASK_CODING_TYPE, p_sys->p_info->current_picture->nb_fields, - 0, 0, - p_sys->i_current_rate ); + 0, 0, p_sys->i_current_rate ); - if ( p_sys->b_skip ) + if( p_sys->b_skip ) { vout_SynchroTrash( p_sys->p_synchro ); } @@ -381,10 +325,9 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) uint8_t *buf[3]; buf[0] = buf[1] = buf[2] = NULL; - if ( p_sys->b_after_sequence_header - && ((p_sys->p_info->current_picture->flags - & PIC_MASK_CODING_TYPE) - == PIC_FLAG_CODING_TYPE_P) ) + if ( p_sys->b_after_sequence_header && + ((p_sys->p_info->current_picture->flags & + PIC_MASK_CODING_TYPE) == PIC_FLAG_CODING_TYPE_P) ) { /* Intra-slice refresh. Simulate a blank I picture. */ msg_Dbg( p_dec, "intra-slice refresh stream" ); @@ -411,7 +354,7 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) && !vout_SynchroChoose( p_sys->p_synchro, p_sys->p_info->current_picture->flags & PIC_MASK_CODING_TYPE, - p_sys->p_vout->render_time ) ) + /*p_sys->p_vout->render_time*/ 0 /*FIXME*/ ) ) { mpeg2_skip( p_sys->p_mpeg2dec, 1 ); p_sys->b_skip = 1; @@ -423,7 +366,13 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) mpeg2_skip( p_sys->p_mpeg2dec, 0 ); p_sys->b_skip = 0; vout_SynchroDecode( p_sys->p_synchro ); - if( (p_pic = GetNewPicture( p_dec, buf )) == NULL ) break; + + if( (p_pic = GetNewPicture( p_dec, buf )) == NULL ) + { + block_Release( p_block ); + return NULL; + } + mpeg2_set_buf( p_sys->p_mpeg2dec, buf, p_pic ); } } @@ -441,26 +390,28 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) & PIC_MASK_CODING_TYPE, p_sys->b_garbage_pic ); p_sys->b_garbage_pic = 0; - vout_DisplayPicture( p_sys->p_vout, p_pic ); if ( p_sys->p_picture_to_destroy != p_pic ) { - vout_DatePicture( p_sys->p_vout, p_pic, - vout_SynchroDate( p_sys->p_synchro ) ); + p_pic->date = vout_SynchroDate( p_sys->p_synchro ); } else { p_sys->p_picture_to_destroy = NULL; - vout_DatePicture( p_sys->p_vout, p_pic, 0 ); + p_pic->date = 0; } + return p_pic; /* FIXME */ } if( p_sys->p_info->discard_fbuf && p_sys->p_info->discard_fbuf->id ) { - p_pic = (picture_t *)p_sys->p_info->discard_fbuf->id; - vout_UnlinkPicture( p_sys->p_vout, p_pic ); + //p_pic = (picture_t *)p_sys->p_info->discard_fbuf->id; + //vout_UnlinkPicture( p_sys->p_vout, p_pic ); } + + //return p_pic; /* FIXME */ + break; case STATE_INVALID: @@ -470,8 +421,8 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) msg_Warn( p_dec, "invalid picture encountered" ); if ( ( p_sys->p_info->current_picture == NULL ) || - ( ( p_sys->p_info->current_picture->flags & PIC_MASK_CODING_TYPE) - != B_CODING_TYPE ) ) + ( ( p_sys->p_info->current_picture->flags & + PIC_MASK_CODING_TYPE) != B_CODING_TYPE ) ) { vout_SynchroReset( p_sys->p_synchro ); } @@ -502,7 +453,7 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) p_sys->p_info->sequence->width * p_sys->p_info->sequence->height / 4 ); - if ( p_sys->b_slice_i ) + if( p_sys->b_slice_i ) { vout_SynchroNewPicture( p_sys->p_synchro, I_CODING_TYPE, 2, 0, 0, p_sys->i_current_rate ); @@ -517,47 +468,23 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) } } - block_Release( p_block ); - return VLC_EGENERIC; + /* Never reached */ + return NULL; } /***************************************************************************** - * EndDecoder: libmpeg2 decoder destruction + * CloseDecoder: libmpeg2 decoder destruction *****************************************************************************/ -static int EndDecoder( decoder_t * p_dec ) +static void CloseDecoder( vlc_object_t *p_this ) { + decoder_t *p_dec = (decoder_t *)p_this; decoder_sys_t *p_sys = p_dec->p_sys; - if( p_sys ) - { - int i_pic; - - if( p_sys->p_synchro ) - vout_SynchroRelease( p_sys->p_synchro ); - - if( p_sys->p_vout ) - { - /* Temporary hack to free the pictures in use by libmpeg2 */ - for( i_pic = 0; i_pic < p_sys->p_vout->render.i_pictures; i_pic++ ) - { - if( p_sys->p_vout->render.pp_picture[i_pic]->i_status == - RESERVED_PICTURE ) - vout_DestroyPicture( p_sys->p_vout, - p_sys->p_vout->render.pp_picture[i_pic] ); - if( p_sys->p_vout->render.pp_picture[i_pic]->i_refcount > 0 ) - vout_UnlinkPicture( p_sys->p_vout, - p_sys->p_vout->render.pp_picture[i_pic] ); - } - - vout_Request( p_dec, p_sys->p_vout, 0, 0, 0, 0 ); - } + if( p_sys->p_synchro ) vout_SynchroRelease( p_sys->p_synchro ); - if( p_sys->p_mpeg2dec ) mpeg2_close( p_sys->p_mpeg2dec ); + if( p_sys->p_mpeg2dec ) mpeg2_close( p_sys->p_mpeg2dec ); - free( p_sys ); - } - - return VLC_SUCCESS; + free( p_sys ); } /***************************************************************************** @@ -568,26 +495,28 @@ static picture_t *GetNewPicture( decoder_t *p_dec, uint8_t **pp_buf ) decoder_sys_t *p_sys = p_dec->p_sys; picture_t *p_pic; - vlc_bool_t b_progressive = p_sys->p_info->current_picture != NULL ? - p_sys->p_info->current_picture->flags & PIC_FLAG_PROGRESSIVE_FRAME : 1; - vlc_bool_t b_top_field_first = p_sys->p_info->current_picture != NULL ? - p_sys->p_info->current_picture->flags & PIC_FLAG_TOP_FIELD_FIRST : 1; - unsigned int i_nb_fields = p_sys->p_info->current_picture != NULL ? - p_sys->p_info->current_picture->nb_fields : 2; + p_dec->fmt_out.video.i_width = p_sys->p_info->sequence->width; + p_dec->fmt_out.video.i_height = p_sys->p_info->sequence->height; + p_dec->fmt_out.video.i_aspect = p_sys->i_aspect; - /* Get a new picture */ - while( !( p_pic = vout_CreatePicture( p_sys->p_vout, - b_progressive, b_top_field_first, i_nb_fields ) ) ) - { - if( p_dec->p_fifo->b_die || p_dec->p_fifo->b_error ) - break; + p_dec->fmt_out.i_codec = + ( p_sys->p_info->sequence->chroma_height < + p_sys->p_info->sequence->height ) ? + VLC_FOURCC('I','4','2','0') : VLC_FOURCC('I','4','2','2'); - msleep( VOUT_OUTMEM_SLEEP ); - } + /* Get a new picture */ + p_pic = p_dec->pf_vout_buffer_new( p_dec ); if( p_pic == NULL ) return NULL; - vout_LinkPicture( p_sys->p_vout, p_pic ); + p_pic->b_progressive = p_sys->p_info->current_picture != NULL ? + p_sys->p_info->current_picture->flags & PIC_FLAG_PROGRESSIVE_FRAME : 1; + p_pic->b_top_field_first = p_sys->p_info->current_picture != NULL ? + p_sys->p_info->current_picture->flags & PIC_FLAG_TOP_FIELD_FIRST : 1; + p_pic->i_nb_fields = p_sys->p_info->current_picture != NULL ? + p_sys->p_info->current_picture->nb_fields : 2; + + //vout_LinkPicture( p_sys->p_vout, p_pic ); pp_buf[0] = p_pic->p[0].p_pixels; pp_buf[1] = p_pic->p[1].p_pixels; diff --git a/modules/codec/lpcm.c b/modules/codec/lpcm.c index fc73cc36be..ccfc99b631 100644 --- a/modules/codec/lpcm.c +++ b/modules/codec/lpcm.c @@ -2,7 +2,7 @@ * lpcm.c: lpcm decoder module ***************************************************************************** * Copyright (C) 1999-2001 VideoLAN - * $Id: lpcm.c,v 1.17 2003/09/02 20:19:25 gbazin Exp $ + * $Id: lpcm.c,v 1.18 2003/11/16 21:07:30 gbazin Exp $ * * Authors: Samuel Hocevar * Henri Fallon @@ -104,8 +104,8 @@ static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; - if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('l','p','c','m') - && p_dec->p_fifo->i_fourcc != VLC_FOURCC('l','p','c','b') ) + if( p_dec->fmt_in.i_codec != VLC_FOURCC('l','p','c','m') + && p_dec->fmt_in.i_codec != VLC_FOURCC('l','p','c','b') ) { return VLC_EGENERIC; } diff --git a/modules/codec/mpeg_audio.c b/modules/codec/mpeg_audio.c index dccabe7ec9..8918ff68a1 100644 --- a/modules/codec/mpeg_audio.c +++ b/modules/codec/mpeg_audio.c @@ -2,7 +2,7 @@ * mpeg_audio.c: parse MPEG audio sync info and packetize the stream ***************************************************************************** * Copyright (C) 2001-2003 VideoLAN - * $Id: mpeg_audio.c,v 1.21 2003/10/23 21:28:11 gbazin Exp $ + * $Id: mpeg_audio.c,v 1.22 2003/11/16 21:07:30 gbazin Exp $ * * Authors: Laurent Aimar * Eric Petit @@ -51,32 +51,15 @@ struct decoder_sys_t */ int i_state; - block_t *p_chain; block_bytestream_t bytestream; - /* - * Decoder output properties - */ - aout_instance_t * p_aout; /* opaque */ - aout_input_t * p_aout_input; /* opaque */ - audio_sample_format_t aout_format; - aout_buffer_t * p_aout_buffer; /* current aout buffer being filled */ - - /* - * Packetizer output properties - */ - sout_packetizer_input_t *p_sout_input; - sout_format_t sout_format; - sout_buffer_t * p_sout_buffer; /* current sout buffer */ - /* * Common properties */ - uint8_t *p_out_buffer; /* output buffer */ audio_date_t end_date; unsigned int i_current_layer; - mtime_t pts; + mtime_t i_pts; int i_frame_size, i_free_frame_size; unsigned int i_channels_conf, i_channels; @@ -90,7 +73,8 @@ enum { STATE_SYNC, STATE_HEADER, STATE_NEXT_SYNC, - STATE_DATA + STATE_GET_DATA, + STATE_SEND_DATA }; /* This isn't the place to put mad-specific stuff. However, it makes the @@ -104,17 +88,14 @@ enum { /**************************************************************************** * Local prototypes ****************************************************************************/ -static int OpenDecoder ( vlc_object_t * ); -static int OpenPacketizer( vlc_object_t * ); +static int OpenDecoder ( vlc_object_t * ); +static int OpenPacketizer( vlc_object_t * ); +static void CloseDecoder ( vlc_object_t * ); +static void *DecodeBlock ( decoder_t *, block_t ** ); -static int InitDecoder ( decoder_t * ); -static int RunDecoder ( decoder_t *, block_t * ); -static int EndDecoder ( decoder_t * ); - -static int GetOutBuffer ( decoder_t *, uint8_t ** ); -static int GetAoutBuffer( decoder_t *, aout_buffer_t ** ); -static int GetSoutBuffer( decoder_t *, sout_buffer_t ** ); -static int SendOutBuffer( decoder_t * ); +static uint8_t *GetOutBuffer ( decoder_t *, void ** ); +static aout_buffer_t *GetAoutBuffer( decoder_t * ); +static block_t *GetSoutBuffer( decoder_t * ); static int SyncInfo( uint32_t i_header, unsigned int * pi_channels, unsigned int * pi_channels_conf, @@ -129,12 +110,12 @@ static int SyncInfo( uint32_t i_header, unsigned int * pi_channels, vlc_module_begin(); set_description( _("MPEG audio layer I/II/III parser") ); set_capability( "decoder", 100 ); - set_callbacks( OpenDecoder, NULL ); + set_callbacks( OpenDecoder, CloseDecoder ); add_submodule(); set_description( _("MPEG audio layer I/II/III packetizer") ); set_capability( "packetizer", 10 ); - set_callbacks( OpenPacketizer, NULL ); + set_callbacks( OpenPacketizer, CloseDecoder ); vlc_module_end(); /***************************************************************************** @@ -143,24 +124,39 @@ vlc_module_end(); static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; + decoder_sys_t *p_sys; - if( p_dec->p_fifo->i_fourcc != VLC_FOURCC( 'm', 'p', 'g', 'a') ) + if( p_dec->fmt_in.i_codec != VLC_FOURCC('m','p','g','a') ) { return VLC_EGENERIC; } - p_dec->pf_init = InitDecoder; - p_dec->pf_decode = RunDecoder; - p_dec->pf_end = EndDecoder; - /* Allocate the memory needed to store the decoder's structure */ - if( ( p_dec->p_sys = + if( ( p_dec->p_sys = p_sys = (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL ) { msg_Err( p_dec, "out of memory" ); return VLC_EGENERIC; } - p_dec->p_sys->b_packetizer = VLC_FALSE; + + /* Misc init */ + p_sys->b_packetizer = VLC_FALSE; + p_sys->i_state = STATE_NOSYNC; + aout_DateSet( &p_sys->end_date, 0 ); + p_sys->bytestream = block_BytestreamInit( p_dec ); + + /* Set output properties */ + p_dec->fmt_out.i_cat = AUDIO_ES; + p_dec->fmt_out.i_codec = VLC_FOURCC('m','p','g','a'); + + /* Set callback */ + p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **)) + DecodeBlock; + p_dec->pf_packetize = (block_t *(*)(decoder_t *, block_t **)) + DecodeBlock; + + /* Start with the minimum size for a free bitrate frame */ + p_sys->i_free_frame_size = MPGA_HEADER_SIZE; return VLC_SUCCESS; } @@ -176,66 +172,34 @@ static int OpenPacketizer( vlc_object_t *p_this ) return i_ret; } -/***************************************************************************** - * InitDecoder: Initalize the decoder - *****************************************************************************/ -static int InitDecoder( decoder_t *p_dec ) -{ - p_dec->p_sys->i_state = STATE_NOSYNC; - - p_dec->p_sys->p_out_buffer = NULL; - aout_DateSet( &p_dec->p_sys->end_date, 0 ); - - p_dec->p_sys->p_aout = NULL; - p_dec->p_sys->p_aout_input = NULL; - p_dec->p_sys->p_aout_buffer = NULL; - p_dec->p_sys->aout_format.i_format = VLC_FOURCC('m','p','g','a'); - - p_dec->p_sys->p_sout_input = NULL; - p_dec->p_sys->p_sout_buffer = NULL; - p_dec->p_sys->sout_format.i_cat = AUDIO_ES; - p_dec->p_sys->sout_format.i_fourcc = VLC_FOURCC('m','p','g','a'); - - /* Start with the minimum size for a free bitrate frame */ - p_dec->p_sys->i_free_frame_size = MPGA_HEADER_SIZE; - - p_dec->p_sys->p_chain = NULL; - - return VLC_SUCCESS; -} - /**************************************************************************** - * RunDecoder: the whole thing + * DecodeBlock: the whole thing **************************************************************************** * This function is called just after the thread is launched. ****************************************************************************/ -static int RunDecoder( decoder_t *p_dec, block_t *p_block ) +static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; uint8_t p_header[MAD_BUFFER_GUARD]; uint32_t i_header; + uint8_t *p_buf; + void *p_out_buffer; + + if( !pp_block || !*pp_block ) return NULL; - if( !aout_DateGet( &p_sys->end_date ) && !p_block->i_pts ) + if( !aout_DateGet( &p_sys->end_date ) && !(*pp_block)->i_pts ) { /* We've just started the stream, wait for the first PTS. */ - block_Release( p_block ); - return VLC_SUCCESS; + block_Release( *pp_block ); + return NULL; } - if( p_block->b_discontinuity ) + if( (*pp_block)->b_discontinuity ) { - p_sys->i_state = STATE_SYNC; + p_sys->i_state = STATE_NOSYNC; } - if( p_sys->p_chain ) - { - block_ChainAppend( &p_sys->p_chain, p_block ); - } - else - { - block_ChainAppend( &p_sys->p_chain, p_block ); - p_sys->bytestream = block_BytestreamInit( p_dec, p_sys->p_chain, 0 ); - } + block_BytestreamPush( &p_sys->bytestream, *pp_block ); while( 1 ) { @@ -256,30 +220,21 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) } if( p_sys->i_state != STATE_SYNC ) { - if( block_PeekByte( &p_sys->bytestream, p_header ) - == VLC_SUCCESS && p_header[0] == 0xff ) - { - /* Start of a sync word, need more data */ - return VLC_SUCCESS; - } - - block_ChainRelease( p_sys->p_chain ); - p_sys->p_chain = NULL; + block_BytestreamFlush( &p_sys->bytestream ); /* Need more data */ - return VLC_SUCCESS; + return NULL; } case STATE_SYNC: /* New frame, set the Presentation Time Stamp */ - p_sys->pts = p_sys->bytestream.p_block->i_pts; - if( p_sys->pts != 0 && - p_sys->pts != aout_DateGet( &p_sys->end_date ) ) + p_sys->i_pts = p_sys->bytestream.p_block->i_pts; + if( p_sys->i_pts != 0 && + p_sys->i_pts != aout_DateGet( &p_sys->end_date ) ) { - aout_DateSet( &p_sys->end_date, p_sys->pts ); + aout_DateSet( &p_sys->end_date, p_sys->i_pts ); } p_sys->i_state = STATE_HEADER; - break; case STATE_HEADER: /* Get MPGA frame header (MPGA_HEADER_SIZE bytes) */ @@ -287,7 +242,7 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) MPGA_HEADER_SIZE ) != VLC_SUCCESS ) { /* Need more data */ - return VLC_SUCCESS; + return NULL; } /* Build frame header */ @@ -334,7 +289,7 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) MAD_BUFFER_GUARD ) != VLC_SUCCESS ) { /* Need more data */ - return VLC_SUCCESS; + return NULL; } if( p_header[0] == 0xff && (p_header[1] & 0xe0) == 0xe0 ) @@ -359,23 +314,9 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) &i_next_max_frame_size, &i_next_layer ); - if( i_next_frame_size == -1 ) - { - msg_Dbg( p_dec, "emulated start code on next frame" ); - block_SkipByte( &p_sys->bytestream ); - p_sys->i_state = STATE_NOSYNC; - break; - } - /* Free bitrate only */ - if( p_sys->i_bit_rate == 0 ) + if( p_sys->i_bit_rate == 0 && i_next_frame_size == -1 ) { - if( i_next_bit_rate != 0 ) - { - p_sys->i_frame_size++; - break; - } - if( (unsigned int)p_sys->i_frame_size > p_sys->i_max_frame_size ) { @@ -387,6 +328,17 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) p_sys->i_free_frame_size = MPGA_HEADER_SIZE; break; } + + p_sys->i_frame_size++; + break; + } + + if( i_next_frame_size == -1 ) + { + msg_Dbg( p_dec, "emulated start code on next frame" ); + block_SkipByte( &p_sys->bytestream ); + p_sys->i_state = STATE_NOSYNC; + break; } /* Check info is in sync with previous one */ @@ -408,12 +360,35 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) p_sys->i_state = STATE_NOSYNC; break; } + + /* Free bitrate only */ + if( p_sys->i_bit_rate == 0 ) + { + if( i_next_bit_rate != 0 ) + { + p_sys->i_frame_size++; + break; + } + } + } else { /* Free bitrate only */ if( p_sys->i_bit_rate == 0 ) { + if( (unsigned int)p_sys->i_frame_size > + p_sys->i_max_frame_size ) + { + msg_Dbg( p_dec, "frame too big %d > %d " + "(emulated startcode ?)", p_sys->i_frame_size, + p_sys->i_max_frame_size ); + block_SkipByte( &p_sys->bytestream ); + p_sys->i_state = STATE_NOSYNC; + p_sys->i_free_frame_size = MPGA_HEADER_SIZE; + break; + } + p_sys->i_frame_size++; break; } @@ -425,254 +400,156 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) break; } - if( GetOutBuffer( p_dec, &p_sys->p_out_buffer ) != VLC_SUCCESS ) + p_sys->i_state = STATE_SEND_DATA; + break; + + case STATE_GET_DATA: + /* Make sure we have enough data. + * (Not useful if we went through NEXT_SYNC) */ + if( block_WaitBytes( &p_sys->bytestream, + p_sys->i_frame_size ) != VLC_SUCCESS ) { - return VLC_EGENERIC; + /* Need more data */ + return NULL; } + p_sys->i_state = STATE_SEND_DATA; - /* Free bitrate only */ - if( p_sys->i_bit_rate == 0 ) + case STATE_SEND_DATA: + if( !(p_buf = GetOutBuffer( p_dec, &p_out_buffer )) ) { - p_sys->i_free_frame_size = p_sys->i_frame_size; + //p_dec->b_error = VLC_TRUE; + return NULL; } - p_sys->i_state = STATE_DATA; - - case STATE_DATA: - /* Copy the whole frame into the buffer */ - if( block_GetBytes( &p_sys->bytestream, p_sys->p_out_buffer, - p_sys->i_frame_size ) != VLC_SUCCESS ) + /* Free bitrate only */ + if( p_sys->i_bit_rate == 0 ) { - /* Need more data */ - return VLC_SUCCESS; + p_sys->i_free_frame_size = p_sys->i_frame_size; } - p_sys->p_chain = block_BytestreamFlush( &p_sys->bytestream ); + /* Copy the whole frame into the buffer. When we reach this point + * we already know we have enough data available. */ + block_GetBytes( &p_sys->bytestream, p_buf, p_sys->i_frame_size ); /* Get beginning of next frame for libmad */ if( !p_sys->b_packetizer ) { - memcpy( p_sys->p_out_buffer + p_sys->i_frame_size, + memcpy( p_buf + p_sys->i_frame_size, p_header, MAD_BUFFER_GUARD ); } - SendOutBuffer( p_dec ); p_sys->i_state = STATE_NOSYNC; /* Make sure we don't reuse the same pts twice */ - if( p_sys->pts == p_sys->bytestream.p_block->i_pts ) - p_sys->pts = p_sys->bytestream.p_block->i_pts = 0; + if( p_sys->i_pts == p_sys->bytestream.p_block->i_pts ) + p_sys->i_pts = p_sys->bytestream.p_block->i_pts = 0; + + /* So p_block doesn't get re-added several times */ + *pp_block = block_BytestreamPop( &p_sys->bytestream ); + + return p_out_buffer; } } - return VLC_SUCCESS; + return NULL; } /***************************************************************************** * GetOutBuffer: *****************************************************************************/ -static int GetOutBuffer( decoder_t *p_dec, uint8_t **pp_out_buffer ) +static uint8_t *GetOutBuffer( decoder_t *p_dec, void **pp_out_buffer ) { decoder_sys_t *p_sys = p_dec->p_sys; - int i_ret; + uint8_t *p_buf; + + if( p_dec->fmt_out.audio.i_rate != p_sys->i_rate ) + { + msg_Info( p_dec, "MPGA channels:%d samplerate:%d bitrate:%d", + p_sys->i_channels, p_sys->i_rate, p_sys->i_bit_rate ); + + aout_DateInit( &p_sys->end_date, p_sys->i_rate ); + aout_DateSet( &p_sys->end_date, p_sys->i_pts ); + } + + p_dec->fmt_out.audio.i_rate = p_sys->i_rate; + p_dec->fmt_out.audio.i_channels = p_sys->i_channels; + p_dec->fmt_out.audio.i_bitrate = p_sys->i_bit_rate; + p_dec->fmt_out.audio.i_frame_length = p_sys->i_frame_length; + p_dec->fmt_out.audio.i_bytes_per_frame = + p_sys->i_max_frame_size + MAD_BUFFER_GUARD; + + p_dec->fmt_out.audio.i_original_channels = p_sys->i_channels_conf; + p_dec->fmt_out.audio.i_physical_channels = + p_sys->i_channels_conf & AOUT_CHAN_PHYSMASK; if( p_sys->b_packetizer ) { - i_ret = GetSoutBuffer( p_dec, &p_sys->p_sout_buffer ); - *pp_out_buffer = - p_sys->p_sout_buffer ? p_sys->p_sout_buffer->p_buffer : NULL; + block_t *p_sout_buffer = GetSoutBuffer( p_dec ); + p_buf = p_sout_buffer ? p_sout_buffer->p_buffer : NULL; + *pp_out_buffer = p_sout_buffer; } else { - i_ret = GetAoutBuffer( p_dec, &p_sys->p_aout_buffer ); - *pp_out_buffer = - p_sys->p_aout_buffer ? p_sys->p_aout_buffer->p_buffer : NULL; + aout_buffer_t *p_aout_buffer = GetAoutBuffer( p_dec ); + p_buf = p_aout_buffer ? p_aout_buffer->p_buffer : NULL; + *pp_out_buffer = p_aout_buffer; } - return i_ret; + return p_buf; } /***************************************************************************** * GetAoutBuffer: *****************************************************************************/ -static int GetAoutBuffer( decoder_t *p_dec, aout_buffer_t **pp_buffer ) +static aout_buffer_t *GetAoutBuffer( decoder_t *p_dec ) { decoder_sys_t *p_sys = p_dec->p_sys; + aout_buffer_t *p_buf; - if( p_sys->p_aout_input != NULL && - ( p_sys->aout_format.i_rate != p_sys->i_rate - || p_sys->aout_format.i_original_channels != p_sys->i_channels_conf - || p_sys->aout_format.i_bytes_per_frame != - p_sys->i_max_frame_size + MAD_BUFFER_GUARD - || p_sys->aout_format.i_frame_length != p_sys->i_frame_length - || p_sys->i_current_layer != p_sys->i_layer ) ) - { - /* Parameters changed - this should not happen. */ - aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input ); - p_sys->p_aout_input = NULL; - } + p_buf = p_dec->pf_aout_buffer_new( p_dec, p_sys->i_frame_length ); + if( p_buf == NULL ) return NULL; - /* Creating the audio input if not created yet. */ - if( p_sys->p_aout_input == NULL ) - { - p_sys->i_current_layer = p_sys->i_layer; - if( p_sys->i_layer == 3 ) - { - p_sys->aout_format.i_format = VLC_FOURCC('m','p','g','3'); - } - else - { - p_sys->aout_format.i_format = VLC_FOURCC('m','p','g','a'); - } + p_buf->start_date = aout_DateGet( &p_sys->end_date ); + p_buf->end_date = + aout_DateIncrement( &p_sys->end_date, p_sys->i_frame_length ); - p_sys->aout_format.i_rate = p_sys->i_rate; - p_sys->aout_format.i_original_channels = p_sys->i_channels_conf; - p_sys->aout_format.i_physical_channels - = p_sys->i_channels_conf & AOUT_CHAN_PHYSMASK; - p_sys->aout_format.i_bytes_per_frame = p_sys->i_max_frame_size - + MAD_BUFFER_GUARD; - p_sys->aout_format.i_frame_length = p_sys->i_frame_length; - aout_DateInit( &p_sys->end_date, p_sys->i_rate ); - aout_DateSet( &p_sys->end_date, p_sys->pts ); - p_sys->p_aout_input = aout_DecNew( p_dec, - &p_sys->p_aout, - &p_sys->aout_format ); - if( p_sys->p_aout_input == NULL ) - { - *pp_buffer = NULL; - return VLC_EGENERIC; - } - } - - *pp_buffer = aout_DecNewBuffer( p_sys->p_aout, p_sys->p_aout_input, - p_sys->i_frame_length ); - if( *pp_buffer == NULL ) - { - return VLC_EGENERIC; - } + /* Hack for libmad filter */ + p_buf->i_nb_bytes = p_sys->i_frame_size + MAD_BUFFER_GUARD; - (*pp_buffer)->start_date = aout_DateGet( &p_sys->end_date ); - (*pp_buffer)->end_date = - aout_DateIncrement( &p_sys->end_date, p_sys->i_frame_length ); - - return VLC_SUCCESS; + return p_buf; } /***************************************************************************** * GetSoutBuffer: *****************************************************************************/ -static int GetSoutBuffer( decoder_t *p_dec, sout_buffer_t **pp_buffer ) +static block_t *GetSoutBuffer( decoder_t *p_dec ) { decoder_sys_t *p_sys = p_dec->p_sys; + block_t *p_block; - if( p_sys->p_sout_input != NULL && - ( p_sys->sout_format.i_sample_rate != (int)p_sys->i_rate - || p_sys->sout_format.i_channels != (int)p_sys->i_channels ) ) - { - /* Parameters changed - this should not happen. */ - } + p_block = block_New( p_dec, p_sys->i_frame_size ); + if( p_block == NULL ) return NULL; - /* Creating the sout input if not created yet. */ - if( p_sys->p_sout_input == NULL ) - { - p_sys->sout_format.i_sample_rate = p_sys->i_rate; - p_sys->sout_format.i_channels = p_sys->i_channels; - p_sys->sout_format.i_block_align = 0; - p_sys->sout_format.i_bitrate = p_sys->i_bit_rate; - p_sys->sout_format.i_extra_data = 0; - p_sys->sout_format.p_extra_data = NULL; + p_block->i_pts = p_block->i_dts = aout_DateGet( &p_sys->end_date ); - aout_DateInit( &p_sys->end_date, p_sys->i_rate ); - aout_DateSet( &p_sys->end_date, p_sys->pts ); - - p_sys->p_sout_input = sout_InputNew( p_dec, &p_sys->sout_format ); - if( p_sys->p_sout_input == NULL ) - { - msg_Err( p_dec, "cannot add a new stream" ); - *pp_buffer = NULL; - return VLC_EGENERIC; - } - msg_Info( p_dec, "MPGA channels:%d samplerate:%d bitrate:%d", - p_sys->i_channels, p_sys->i_rate, p_sys->i_bit_rate ); - } - - *pp_buffer = sout_BufferNew( p_sys->p_sout_input->p_sout, - p_sys->i_frame_size ); - if( *pp_buffer == NULL ) - { - return VLC_EGENERIC; - } + p_block->i_length = + aout_DateIncrement( &p_sys->end_date, p_sys->i_frame_length ) - + p_block->i_pts; - (*pp_buffer)->i_pts = - (*pp_buffer)->i_dts = aout_DateGet( &p_sys->end_date ); - - (*pp_buffer)->i_length = - aout_DateIncrement( &p_sys->end_date, p_sys->i_frame_length ) - - (*pp_buffer)->i_pts; - - return VLC_SUCCESS; + return p_block; } /***************************************************************************** - * SendOutBuffer: + * CloseDecoder: clean up the decoder *****************************************************************************/ -static int SendOutBuffer( decoder_t *p_dec ) +static void CloseDecoder( vlc_object_t *p_this ) { + decoder_t *p_dec = (decoder_t *)p_this; decoder_sys_t *p_sys = p_dec->p_sys; - if( p_sys->b_packetizer ) - { - sout_InputSendBuffer( p_sys->p_sout_input, p_sys->p_sout_buffer ); - p_sys->p_sout_buffer = NULL; - } - else - { - /* We have all we need, send the buffer to the aout core. */ - p_sys->p_aout_buffer->i_nb_bytes = - p_sys->i_frame_size + MAD_BUFFER_GUARD; - aout_DecPlay( p_sys->p_aout, p_sys->p_aout_input, - p_sys->p_aout_buffer ); - p_sys->p_aout_buffer = NULL; - } - - p_sys->p_out_buffer = NULL; + block_BytestreamRelease( &p_sys->bytestream ); - return VLC_SUCCESS; -} - -/***************************************************************************** - * EndDecoder: clean up the decoder - *****************************************************************************/ -static int EndDecoder( decoder_t *p_dec ) -{ - if( p_dec->p_sys->p_aout_input != NULL ) - { - if( p_dec->p_sys->p_aout_buffer ) - { - aout_DecDeleteBuffer( p_dec->p_sys->p_aout, - p_dec->p_sys->p_aout_input, - p_dec->p_sys->p_aout_buffer ); - } - - aout_DecDelete( p_dec->p_sys->p_aout, p_dec->p_sys->p_aout_input ); - } - - if( p_dec->p_sys->p_sout_input != NULL ) - { - if( p_dec->p_sys->p_sout_buffer ) - { - sout_BufferDelete( p_dec->p_sys->p_sout_input->p_sout, - p_dec->p_sys->p_sout_buffer ); - } - - sout_InputDelete( p_dec->p_sys->p_sout_input ); - } - - if( p_dec->p_sys->p_chain ) block_ChainRelease( p_dec->p_sys->p_chain ); - - free( p_dec->p_sys ); - - return VLC_SUCCESS; + free( p_sys ); } /***************************************************************************** diff --git a/modules/codec/rawvideo.c b/modules/codec/rawvideo.c index 83fc9bf69a..390d22dd8b 100644 --- a/modules/codec/rawvideo.c +++ b/modules/codec/rawvideo.c @@ -2,7 +2,7 @@ * rawvideo.c: Pseudo video decoder/packetizer for raw video data ***************************************************************************** * Copyright (C) 2001, 2002 VideoLAN - * $Id: rawvideo.c,v 1.7 2003/10/24 21:27:06 gbazin Exp $ + * $Id: rawvideo.c,v 1.8 2003/11/16 21:07:30 gbazin Exp $ * * Authors: Laurent Aimar * @@ -28,10 +28,8 @@ #include /* strdup() */ #include -#include #include #include -#include #include "codecs.h" @@ -48,17 +46,6 @@ struct decoder_sys_t */ int i_raw_size; - /* - * Output properties - */ - vout_thread_t *p_vout; - - /* - * Packetizer output properties - */ - sout_packetizer_input_t *p_sout_input; - sout_format_t sout_format; - /* * Common properties */ @@ -69,15 +56,14 @@ struct decoder_sys_t /**************************************************************************** * Local prototypes ****************************************************************************/ -static int OpenDecoder ( vlc_object_t * ); -static int OpenPacketizer( vlc_object_t * ); +static int OpenDecoder ( vlc_object_t * ); +static int OpenPacketizer( vlc_object_t * ); +static void CloseDecoder ( vlc_object_t * ); -static int InitDecoder ( decoder_t * ); -static int RunDecoder ( decoder_t *, block_t * ); -static int EndDecoder ( decoder_t * ); +static void *DecodeBlock ( decoder_t *, block_t ** ); -static int DecodeFrame ( decoder_t *, block_t * ); -static int SendFrame ( decoder_t *, block_t * ); +static picture_t *DecodeFrame( decoder_t *, block_t * ); +static block_t *SendFrame ( decoder_t *, block_t * ); /***************************************************************************** * Module descriptor @@ -85,25 +71,23 @@ static int SendFrame ( decoder_t *, block_t * ); vlc_module_begin(); set_description( _("Pseudo Raw Video decoder") ); set_capability( "decoder", 50 ); - set_callbacks( OpenDecoder, NULL ); + set_callbacks( OpenDecoder, CloseDecoder ); add_submodule(); set_description( _("Pseudo Raw Video packetizer") ); set_capability( "packetizer", 100 ); - set_callbacks( OpenPacketizer, NULL ); + set_callbacks( OpenPacketizer, CloseDecoder ); vlc_module_end(); /***************************************************************************** * OpenDecoder: probe the decoder and return score - ***************************************************************************** - * Tries to launch a decoder and return score so that the interface is able - * to choose. *****************************************************************************/ static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; + decoder_sys_t *p_sys; - switch( p_dec->p_fifo->i_fourcc ) + switch( p_dec->fmt_in.i_codec ) { /* Planar YUV */ case VLC_FOURCC('I','4','4','4'): @@ -129,18 +113,47 @@ static int OpenDecoder( vlc_object_t *p_this ) return VLC_EGENERIC; } - p_dec->pf_init = InitDecoder; - p_dec->pf_decode = RunDecoder; - p_dec->pf_end = EndDecoder; - /* Allocate the memory needed to store the decoder's structure */ - if( ( p_dec->p_sys = + if( ( p_dec->p_sys = p_sys = (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL ) { msg_Err( p_dec, "out of memory" ); return VLC_EGENERIC; } + /* Misc init */ p_dec->p_sys->b_packetizer = VLC_FALSE; + p_sys->i_pts = 0; + + if( p_dec->fmt_in.video.i_width <= 0 || + p_dec->fmt_in.video.i_height <= 0 ) + { + msg_Err( p_dec, "invalid display size %dx%d", + p_dec->fmt_in.video.i_width, p_dec->fmt_in.video.i_height ); + return VLC_EGENERIC; + } + + /* Find out p_vdec->i_raw_size */ + vout_InitFormat( &p_dec->fmt_out.video, p_dec->fmt_in.i_codec, + p_dec->fmt_in.video.i_width, + p_dec->fmt_in.video.i_height, + p_dec->fmt_in.video.i_aspect ); + p_sys->i_raw_size = p_dec->fmt_out.video.i_bits_per_pixel * + p_dec->fmt_out.video.i_width * p_dec->fmt_out.video.i_height / 8; + + /* Set output properties */ + p_dec->fmt_out.i_cat = VIDEO_ES; + p_dec->fmt_out.i_codec = p_dec->fmt_in.i_codec; + //if( !p_dec->fmt_in.video.i_aspect ) + { + p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR * + p_dec->fmt_out.video.i_width / p_dec->fmt_out.video.i_height; + } + + /* Set callbacks */ + p_dec->pf_decode_video = (picture_t *(*)(decoder_t *, block_t **)) + DecodeBlock; + p_dec->pf_packetize = (block_t *(*)(decoder_t *, block_t **)) + DecodeBlock; return VLC_SUCCESS; } @@ -156,96 +169,27 @@ static int OpenPacketizer( vlc_object_t *p_this ) return i_ret; } -/***************************************************************************** - * InitDecoder: Initalize the decoder - *****************************************************************************/ -static int InitDecoder( decoder_t *p_dec ) -{ - decoder_sys_t *p_sys = p_dec->p_sys; - video_frame_format_t format; - - p_sys->i_pts = 0; - - p_sys->p_sout_input = NULL; - p_sys->sout_format.i_cat = VIDEO_ES; - p_sys->sout_format.i_block_align = 0; - p_sys->sout_format.i_bitrate = 0; - p_sys->sout_format.i_extra_data = 0; - p_sys->sout_format.p_extra_data = NULL; - -#define bih ((BITMAPINFOHEADER*)p_dec->p_fifo->p_bitmapinfoheader) - if( bih == NULL ) - { - msg_Err( p_dec, "info missing, fatal" ); - return VLC_EGENERIC; - } - if( bih->biWidth <= 0 || bih->biHeight <= 0 ) - { - msg_Err( p_dec, "invalid display size %dx%d", - bih->biWidth, bih->biHeight ); - return VLC_EGENERIC; - } - - if( p_sys->b_packetizer ) - { - /* add an input for the stream ouput */ - p_sys->sout_format.i_width = bih->biWidth; - p_sys->sout_format.i_height = bih->biHeight; - p_sys->sout_format.i_fourcc = p_dec->p_fifo->i_fourcc; - - p_sys->p_sout_input = - sout_InputNew( p_dec, &p_sys->sout_format ); - - if( !p_sys->p_sout_input ) - { - msg_Err( p_dec, "cannot add a new stream" ); - return VLC_EGENERIC; - } - } - else - { - /* Initialize video output */ - p_sys->p_vout = vout_Request( p_dec, NULL, - bih->biWidth, bih->biHeight, - p_dec->p_fifo->i_fourcc, - VOUT_ASPECT_FACTOR * bih->biWidth / - bih->biHeight ); - if( p_sys->p_vout == NULL ) - { - msg_Err( p_dec, "failed to create vout" ); - return VLC_EGENERIC; - } - } - - /* Find out p_vdec->i_raw_size */ - vout_InitFormat( &format, p_dec->p_fifo->i_fourcc, - bih->biWidth, bih->biHeight, - bih->biWidth * VOUT_ASPECT_FACTOR / bih->biHeight ); - p_sys->i_raw_size = format.i_bits_per_pixel * - format.i_width * format.i_height / 8; -#undef bih - - return VLC_SUCCESS; -} - /**************************************************************************** - * RunDecoder: the whole thing + * DecodeBlock: the whole thing **************************************************************************** - * This function must be fed with ogg packets. + * This function must be fed with complete frames. ****************************************************************************/ -static int RunDecoder( decoder_t *p_dec, block_t *p_block ) +static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; - int i_ret; + block_t *p_block; + void *p_buf; + + if( !pp_block || !*pp_block ) return NULL; + + p_block = *pp_block; -#if 0 - if( !aout_DateGet( &p_sys->end_date ) && !p_block->i_pts ) + if( !p_sys->i_pts && !p_block->i_pts ) { /* We've just started the stream, wait for the first PTS. */ block_Release( p_block ); - return VLC_SUCCESS; + return NULL; } -#endif /* Date management */ if( p_block->i_pts > 0 && p_block->i_pts != p_sys->i_pts ) @@ -259,23 +203,23 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) p_block->i_buffer, p_sys->i_raw_size ); block_Release( p_block ); - return VLC_EGENERIC; + return NULL; } if( p_sys->b_packetizer ) { - i_ret = SendFrame( p_dec, p_block ); + p_buf = SendFrame( p_dec, p_block ); } else { - i_ret = DecodeFrame( p_dec, p_block ); + p_buf = DecodeFrame( p_dec, p_block ); } /* Date management: 1 frame per packet */ p_sys->i_pts += ( I64C(1000000) * 1.0 / 25 /*FIXME*/ ); + *pp_block = NULL; - block_Release( p_block ); - return i_ret; + return p_buf; } /***************************************************************************** @@ -306,70 +250,44 @@ static void FillPicture( decoder_t *p_dec, block_t *p_block, picture_t *p_pic ) /***************************************************************************** * DecodeFrame: decodes a video frame. *****************************************************************************/ -static int DecodeFrame( decoder_t *p_dec, block_t *p_block ) +static picture_t *DecodeFrame( decoder_t *p_dec, block_t *p_block ) { decoder_sys_t *p_sys = p_dec->p_sys; picture_t *p_pic; /* Get a new picture */ - while( !(p_pic = vout_CreatePicture( p_sys->p_vout, 0, 0, 0 ) ) ) + p_pic = p_dec->pf_vout_buffer_new( p_dec ); + if( !p_pic ) { - if( p_dec->p_fifo->b_die || p_dec->p_fifo->b_error ) - { - return VLC_EGENERIC; - } - msleep( VOUT_OUTMEM_SLEEP ); + block_Release( p_block ); + return NULL; } - if( !p_pic ) return VLC_EGENERIC; FillPicture( p_dec, p_block, p_pic ); - vout_DatePicture( p_sys->p_vout, p_pic, p_sys->i_pts ); - vout_DisplayPicture( p_sys->p_vout, p_pic ); + p_pic->date = p_sys->i_pts; - return VLC_SUCCESS; + block_Release( p_block ); + return p_pic; } /***************************************************************************** * SendFrame: send a video frame to the stream output. *****************************************************************************/ -static int SendFrame( decoder_t *p_dec, block_t *p_block ) +static block_t *SendFrame( decoder_t *p_dec, block_t *p_block ) { decoder_sys_t *p_sys = p_dec->p_sys; - sout_buffer_t *p_sout_buffer = - sout_BufferNew( p_sys->p_sout_input->p_sout, p_block->i_buffer ); - - if( !p_sout_buffer ) return VLC_EGENERIC; + p_block->i_dts = p_block->i_pts = p_sys->i_pts; - p_dec->p_vlc->pf_memcpy( p_sout_buffer->p_buffer, - p_block->p_buffer, p_block->i_buffer ); - - p_sout_buffer->i_dts = p_sout_buffer->i_pts = p_sys->i_pts; - - sout_InputSendBuffer( p_sys->p_sout_input, p_sout_buffer ); - - return VLC_SUCCESS; + return p_block; } /***************************************************************************** - * EndDecoder: decoder destruction + * CloseDecoder: decoder destruction *****************************************************************************/ -static int EndDecoder( decoder_t *p_dec ) +static void CloseDecoder( vlc_object_t *p_this ) { - decoder_sys_t *p_sys = p_dec->p_sys; - - if( !p_sys->b_packetizer ) - { - vout_Request( p_dec, p_sys->p_vout, 0, 0, 0, 0 ); - } - - if( p_sys->p_sout_input != NULL ) - { - sout_InputDelete( p_sys->p_sout_input ); - } - - free( p_sys ); - - return VLC_SUCCESS; + decoder_t *p_dec = (decoder_t*)p_this; + free( p_dec->p_sys ); } diff --git a/modules/codec/speex.c b/modules/codec/speex.c index ec1c733076..e3578302d5 100755 --- a/modules/codec/speex.c +++ b/modules/codec/speex.c @@ -2,7 +2,7 @@ * speex.c: speex decoder/packetizer module making use of libspeex. ***************************************************************************** * Copyright (C) 1999-2001 VideoLAN - * $Id: speex.c,v 1.2 2003/10/22 18:24:08 gbazin Exp $ + * $Id: speex.c,v 1.3 2003/11/16 21:07:30 gbazin Exp $ * * Authors: Gildas Bazin * @@ -28,12 +28,7 @@ #include /* memcpy(), memset() */ #include -#include #include -#include -#include -#include - #include #include @@ -54,6 +49,7 @@ struct decoder_sys_t * Input properties */ int i_headers; + int i_frame_in_packet; /* * Speex properties @@ -63,23 +59,10 @@ struct decoder_sys_t SpeexStereoState stereo; void *p_state; - /* - * Output properties - */ - aout_instance_t *p_aout; - aout_input_t *p_aout_input; - audio_sample_format_t aout_format; - - /* - * Packetizer output properties - */ - sout_packetizer_input_t *p_sout_input; - sout_format_t sout_format; - /* * Common properties */ - audio_date_t end_date; + audio_date_t end_date; }; @@ -97,17 +80,16 @@ static int pi_channels_maps[6] = /**************************************************************************** * Local prototypes ****************************************************************************/ -static int OpenDecoder ( vlc_object_t * ); -static int OpenPacketizer( vlc_object_t * ); +static int OpenDecoder ( vlc_object_t * ); +static int OpenPacketizer( vlc_object_t * ); +static void CloseDecoder ( vlc_object_t * ); -static int InitDecoder ( decoder_t * ); -static int RunDecoder ( decoder_t *, block_t * ); -static int EndDecoder ( decoder_t * ); +static void *DecodeBlock ( decoder_t *, block_t ** ); +static int ProcessHeader ( decoder_t *, ogg_packet * ); +static void *ProcessPacket( decoder_t *, ogg_packet *, block_t ** ); -static int ProcessHeader ( decoder_t *, ogg_packet * ); -static int ProcessPacket ( decoder_t *, ogg_packet *, mtime_t ); -static int DecodePacket ( decoder_t *, ogg_packet * ); -static int SendPacket ( decoder_t *, ogg_packet * ); +static aout_buffer_t *DecodePacket( decoder_t *, ogg_packet * ); +static block_t *SendPacket( decoder_t *, ogg_packet *, block_t * ); static void ParseSpeexComments( decoder_t *, ogg_packet * ); @@ -117,12 +99,12 @@ static void ParseSpeexComments( decoder_t *, ogg_packet * ); vlc_module_begin(); set_description( _("Speex audio decoder") ); set_capability( "decoder", 100 ); - set_callbacks( OpenDecoder, NULL ); + set_callbacks( OpenDecoder, CloseDecoder ); add_submodule(); set_description( _("Speex audio packetizer") ); set_capability( "packetizer", 100 ); - set_callbacks( OpenPacketizer, NULL ); + set_callbacks( OpenPacketizer, CloseDecoder ); vlc_module_end(); /***************************************************************************** @@ -131,18 +113,15 @@ vlc_module_end(); static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; + decoder_sys_t *p_sys = p_dec->p_sys; - if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('s','p','x',' ') ) + if( p_dec->fmt_in.i_codec != VLC_FOURCC('s','p','x',' ') ) { return VLC_EGENERIC; } - p_dec->pf_init = InitDecoder; - p_dec->pf_decode = RunDecoder; - p_dec->pf_end = EndDecoder; - /* Allocate the memory needed to store the decoder's structure */ - if( ( p_dec->p_sys = + if( ( p_dec->p_sys = p_sys = (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL ) { msg_Err( p_dec, "out of memory" ); @@ -150,6 +129,23 @@ static int OpenDecoder( vlc_object_t *p_this ) } p_dec->p_sys->b_packetizer = VLC_FALSE; + aout_DateSet( &p_sys->end_date, 0 ); + + /* Set output properties */ + p_dec->fmt_out.i_cat = AUDIO_ES; + p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE; + + /* Set callbacks */ + p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **)) + DecodeBlock; + p_dec->pf_packetize = (block_t *(*)(decoder_t *, block_t **)) + DecodeBlock; + + p_sys->i_headers = 0; + p_sys->p_state = NULL; + p_sys->p_header = NULL; + p_sys->i_frame_in_packet = 0; + return VLC_SUCCESS; } @@ -159,53 +155,42 @@ static int OpenPacketizer( vlc_object_t *p_this ) int i_ret = OpenDecoder( p_this ); - if( i_ret == VLC_SUCCESS ) p_dec->p_sys->b_packetizer = VLC_TRUE; + if( i_ret == VLC_SUCCESS ) + { + p_dec->p_sys->b_packetizer = VLC_TRUE; + p_dec->fmt_out.i_codec = VLC_FOURCC('s','p','x',' '); + } return i_ret; } -/***************************************************************************** - * InitDecoder: Initalize the decoder - *****************************************************************************/ -static int InitDecoder( decoder_t *p_dec ) -{ - decoder_sys_t *p_sys = p_dec->p_sys; - - aout_DateSet( &p_sys->end_date, 0 ); - - p_sys->p_aout = NULL; - p_sys->p_aout_input = NULL; - p_sys->aout_format.i_format = VLC_FOURCC('s','p','x',' '); - - p_sys->p_sout_input = NULL; - p_sys->sout_format.i_cat = AUDIO_ES; - p_sys->sout_format.i_fourcc = VLC_FOURCC( 's', 'p', 'x', ' ' ); - p_sys->sout_format.i_block_align = 0; - p_sys->sout_format.i_bitrate = 0; - p_sys->sout_format.i_extra_data = 0; - p_sys->sout_format.p_extra_data = NULL; - - p_sys->i_headers = 0; - p_sys->p_state = NULL; - p_sys->p_header = NULL; - - return VLC_SUCCESS; -} - /**************************************************************************** - * RunDecoder: the whole thing + * DecodeBlock: the whole thing **************************************************************************** * This function must be fed with ogg packets. ****************************************************************************/ -static int RunDecoder( decoder_t *p_dec, block_t *p_block ) +static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; ogg_packet oggpacket; - int i_ret; - /* Block to Ogg packet */ - oggpacket.packet = p_block->p_buffer; - oggpacket.bytes = p_block->i_buffer; + if( !pp_block ) return NULL; + + if( *pp_block ) + { + /* Block to Ogg packet */ + oggpacket.packet = (*pp_block)->p_buffer; + oggpacket.bytes = (*pp_block)->i_buffer; + } + else + { + if( p_sys->b_packetizer ) return NULL; + + /* Block to Ogg packet */ + oggpacket.packet = NULL; + oggpacket.bytes = 0; + } + oggpacket.granulepos = -1; oggpacket.b_o_s = 0; oggpacket.e_o_s = 0; @@ -217,23 +202,13 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) if( ProcessHeader( p_dec, &oggpacket ) != VLC_SUCCESS ) { msg_Err( p_dec, "Initial Speex header is corrupted" ); - block_Release( p_block ); - return VLC_EGENERIC; + block_Release( *pp_block ); + return NULL; } p_sys->i_headers++; - if( p_sys->b_packetizer ) - { - i_ret = ProcessPacket( p_dec, &oggpacket, p_block->i_pts ); - block_Release( p_block ); - return i_ret; - } - else - { - block_Release( p_block ); - return VLC_SUCCESS; - } + return ProcessPacket( p_dec, &oggpacket, pp_block ); } if( p_sys->i_headers == 1 ) @@ -242,40 +217,10 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) ParseSpeexComments( p_dec, &oggpacket ); p_sys->i_headers++; - if( p_sys->b_packetizer ) - { - i_ret = ProcessPacket( p_dec, &oggpacket, p_block->i_pts ); - block_Release( p_block ); - return i_ret; - } - else - { - block_Release( p_block ); - return VLC_SUCCESS; - } - } - - if( p_sys->i_headers < p_sys->p_header->extra_headers + 2 ) - { - /* Skip them for now */ - p_sys->i_headers++; - - if( p_sys->b_packetizer ) - { - i_ret = ProcessPacket( p_dec, &oggpacket, p_block->i_pts ); - block_Release( p_block ); - return i_ret; - } - else - { - block_Release( p_block ); - return VLC_SUCCESS; - } + return ProcessPacket( p_dec, &oggpacket, pp_block ); } - i_ret = ProcessPacket( p_dec, &oggpacket, p_block->i_pts ); - block_Release( p_block ); - return i_ret; + return ProcessPacket( p_dec, &oggpacket, pp_block ); } /***************************************************************************** @@ -330,27 +275,6 @@ static int ProcessHeader( decoder_t *p_dec, ogg_packet *p_oggpacket ) ( p_header->nb_channels == 1 ) ? " (mono" : " (stereo", p_header->vbr ? ", VBR)" : ")" ); - aout_DateInit( &p_sys->end_date, p_header->rate ); - - if( p_sys->b_packetizer ) - { - /* add an input for the stream ouput */ - p_sys->sout_format.i_sample_rate = p_header->rate; - p_sys->sout_format.i_channels = p_header->nb_channels; - p_sys->sout_format.i_block_align = 1; - p_sys->sout_format.i_bitrate = 0; - - p_sys->p_sout_input = sout_InputNew( p_dec, &p_sys->sout_format ); - if( !p_sys->p_sout_input ) - { - msg_Err( p_dec, "cannot add a new stream" ); - return VLC_EGENERIC; - } - - /* We're done */ - return VLC_SUCCESS; - } - /* Take care of speex decoder init */ speex_bits_init( &p_sys->bits ); p_sys->p_state = p_state = speex_decoder_init( p_mode ); @@ -370,20 +294,14 @@ static int ProcessHeader( decoder_t *p_dec, ogg_packet *p_oggpacket ) speex_decoder_ctl( p_state, SPEEX_SET_HANDLER, &callback ); } - p_sys->aout_format.i_format = AOUT_FMT_S16_NE; - p_sys->aout_format.i_physical_channels = - p_sys->aout_format.i_original_channels = + /* Setup the format */ + p_dec->fmt_out.audio.i_physical_channels = + p_dec->fmt_out.audio.i_original_channels = pi_channels_maps[p_header->nb_channels]; - p_sys->aout_format.i_rate = p_header->rate; + p_dec->fmt_out.audio.i_channels = p_header->nb_channels; + p_dec->fmt_out.audio.i_rate = p_header->rate; - p_sys->p_aout = NULL; - p_sys->p_aout_input = aout_DecNew( p_dec, &p_sys->p_aout, - &p_sys->aout_format ); - if( p_sys->p_aout_input == NULL ) - { - msg_Err( p_dec, "failed to create aout fifo" ); - return VLC_EGENERIC; - } + aout_DateInit( &p_sys->end_date, p_header->rate ); return VLC_SUCCESS; } @@ -391,72 +309,89 @@ static int ProcessHeader( decoder_t *p_dec, ogg_packet *p_oggpacket ) /***************************************************************************** * ProcessPacket: processes a Speex packet. *****************************************************************************/ -static int ProcessPacket( decoder_t *p_dec, ogg_packet *p_oggpacket, - mtime_t i_pts ) +static void *ProcessPacket( decoder_t *p_dec, ogg_packet *p_oggpacket, + block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; + block_t *p_block = *pp_block; /* Date management */ - if( i_pts > 0 && i_pts != aout_DateGet( &p_sys->end_date ) ) + if( p_block && p_block->i_pts > 0 && + p_block->i_pts != aout_DateGet( &p_sys->end_date ) ) { - aout_DateSet( &p_sys->end_date, i_pts ); + aout_DateSet( &p_sys->end_date, p_block->i_pts ); } if( !aout_DateGet( &p_sys->end_date ) ) { /* We've just started the stream, wait for the first PTS. */ - return VLC_SUCCESS; + if( p_block ) block_Release( p_block ); + return NULL; } + *pp_block = NULL; /* To avoid being fed the same packet again */ + if( p_sys->b_packetizer ) { - return SendPacket( p_dec, p_oggpacket ); + return SendPacket( p_dec, p_oggpacket, p_block ); } else { - return DecodePacket( p_dec, p_oggpacket ); + aout_buffer_t *p_aout_buffer; + + if( p_sys->i_headers >= p_sys->p_header->extra_headers + 2 ) + p_aout_buffer = DecodePacket( p_dec, p_oggpacket ); + else + p_aout_buffer = NULL; /* Skip headers */ + + if( p_block ) + { + block_Release( p_block ); + } + return p_aout_buffer; } } /***************************************************************************** * DecodePacket: decodes a Speex packet. *****************************************************************************/ -static int DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket ) +static aout_buffer_t *DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket ) { decoder_sys_t *p_sys = p_dec->p_sys; - int j; - /* Copy Ogg packet to Speex bitstream */ - speex_bits_read_from( &p_sys->bits, p_oggpacket->packet, - p_oggpacket->bytes ); + if( p_oggpacket->bytes ) + { + /* Copy Ogg packet to Speex bitstream */ + speex_bits_read_from( &p_sys->bits, p_oggpacket->packet, + p_oggpacket->bytes ); + p_sys->i_frame_in_packet = 0; + } - /* Decode each frame of the packet */ - for( j = 0; j != p_sys->p_header->frames_per_packet; j++ ) + /* Decode one frame at a time */ + if( p_sys->i_frame_in_packet < p_sys->p_header->frames_per_packet ) { aout_buffer_t *p_aout_buffer; int i_ret; - p_aout_buffer = aout_DecNewBuffer( p_sys->p_aout, p_sys->p_aout_input, - p_sys->p_header->frame_size ); + p_aout_buffer = + p_dec->pf_aout_buffer_new( p_dec, p_sys->p_header->frame_size ); if( !p_aout_buffer ) { - msg_Err( p_dec, "cannot get aout buffer" ); - return VLC_SUCCESS; + return NULL; } i_ret = speex_decode( p_sys->p_state, &p_sys->bits, (int16_t *)p_aout_buffer->p_buffer ); - if( i_ret == -1 ) break; /* End of stream */ + if( i_ret == -1 ) return NULL; /* End of stream */ if( i_ret== -2 ) { msg_Warn( p_dec, "Decoding error: corrupted stream?" ); - break; + return NULL; } if( speex_bits_remaining( &p_sys->bits ) < 0 ) { msg_Warn( p_dec, "Decoding overflow: corrupted stream?" ); - break; } if( p_sys->p_header->nb_channels == 2 ) @@ -468,45 +403,36 @@ static int DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket ) p_aout_buffer->end_date = aout_DateIncrement( &p_sys->end_date, p_sys->p_header->frame_size); - aout_DecPlay( p_sys->p_aout, p_sys->p_aout_input, p_aout_buffer ); - } + p_sys->i_frame_in_packet++; - return VLC_SUCCESS; + return p_aout_buffer; + } + else + { + return NULL; + } } /***************************************************************************** * SendPacket: send an ogg packet to the stream output. *****************************************************************************/ -static int SendPacket( decoder_t *p_dec, ogg_packet *p_oggpacket ) +static block_t *SendPacket( decoder_t *p_dec, ogg_packet *p_oggpacket, + block_t *p_block ) { decoder_sys_t *p_sys = p_dec->p_sys; - sout_buffer_t *p_sout_buffer = - sout_BufferNew( p_sys->p_sout_input->p_sout, p_oggpacket->bytes ); - - if( !p_sout_buffer ) return VLC_EGENERIC; - - p_dec->p_vlc->pf_memcpy( p_sout_buffer->p_buffer, - p_oggpacket->packet, - p_oggpacket->bytes ); - - p_sout_buffer->i_bitrate = 0; - /* Date management */ - p_sout_buffer->i_dts = p_sout_buffer->i_pts = - aout_DateGet( &p_sys->end_date ); + p_block->i_dts = p_block->i_pts = aout_DateGet( &p_sys->end_date ); if( p_sys->i_headers >= p_sys->p_header->extra_headers + 2 ) - p_sout_buffer->i_length = + p_block->i_length = aout_DateIncrement( &p_sys->end_date, p_sys->p_header->frame_size ) - - p_sout_buffer->i_pts; + p_block->i_pts; else - p_sout_buffer->i_length = 0; + p_block->i_length = 0; - sout_InputSendBuffer( p_sys->p_sout_input, p_sout_buffer ); - - return VLC_SUCCESS; + return p_block; } /***************************************************************************** @@ -552,22 +478,13 @@ static void ParseSpeexComments( decoder_t *p_dec, ogg_packet *p_oggpacket ) } /***************************************************************************** - * EndDecoder: speex decoder destruction + * CloseDecoder: speex decoder destruction *****************************************************************************/ -static int EndDecoder( decoder_t * p_dec ) +static void CloseDecoder( vlc_object_t *p_this ) { + decoder_t * p_dec = (decoder_t *)p_this; decoder_sys_t *p_sys = p_dec->p_sys; - if( p_sys->p_aout_input != NULL ) - { - aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input ); - } - - if( p_sys->p_sout_input != NULL ) - { - sout_InputDelete( p_sys->p_sout_input ); - } - if( p_sys->p_state ) { speex_decoder_destroy( p_sys->p_state ); @@ -576,6 +493,4 @@ static int EndDecoder( decoder_t * p_dec ) if( p_sys->p_header ) free( p_sys->p_header ); free( p_sys ); - - return VLC_SUCCESS; } diff --git a/modules/codec/spudec/spudec.c b/modules/codec/spudec/spudec.c index 162c3c8898..ee91f93c50 100644 --- a/modules/codec/spudec/spudec.c +++ b/modules/codec/spudec/spudec.c @@ -2,7 +2,7 @@ * spudec.c : SPU decoder thread ***************************************************************************** * Copyright (C) 2000-2001 VideoLAN - * $Id: spudec.c,v 1.26 2003/11/06 16:36:41 nitrox Exp $ + * $Id: spudec.c,v 1.27 2003/11/16 21:07:31 gbazin Exp $ * * Authors: Samuel Hocevar * @@ -61,8 +61,8 @@ static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; - if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('s','p','u',' ') - && p_dec->p_fifo->i_fourcc != VLC_FOURCC('s','p','u','b') ) + if( p_dec->fmt_in.i_codec != VLC_FOURCC('s','p','u',' ') + && p_dec->fmt_in.i_codec != VLC_FOURCC('s','p','u','b') ) { return VLC_EGENERIC; } diff --git a/modules/codec/subsdec.c b/modules/codec/subsdec.c index bc56ea22bc..566a31d7ae 100644 --- a/modules/codec/subsdec.c +++ b/modules/codec/subsdec.c @@ -2,7 +2,7 @@ * subsdec.c : text subtitles decoder ***************************************************************************** * Copyright (C) 2000-2001 VideoLAN - * $Id: subsdec.c,v 1.6 2003/11/15 15:40:19 hartman Exp $ + * $Id: subsdec.c,v 1.7 2003/11/16 21:07:30 gbazin Exp $ * * Authors: Gildas Bazin * Samuel Hocevar @@ -56,10 +56,9 @@ struct decoder_sys_t * Local prototypes *****************************************************************************/ static int OpenDecoder ( vlc_object_t * ); +static void CloseDecoder ( vlc_object_t * ); -static int InitDecoder ( decoder_t * ); -static int RunDecoder ( decoder_t *, block_t * ); -static int EndDecoder ( decoder_t * ); +static void DecodeBlock ( decoder_t *, block_t ** ); static void ParseText ( decoder_t *, block_t *, vout_thread_t * ); @@ -103,7 +102,7 @@ static char *ppsz_justification_text[] = {N_("Center"),N_("Left"),N_("Right")}; vlc_module_begin(); set_description( _("text subtitles decoder") ); set_capability( "decoder", 50 ); - set_callbacks( OpenDecoder, NULL ); + set_callbacks( OpenDecoder, CloseDecoder ); add_category_hint( N_("Subtitles"), NULL, VLC_FALSE ); add_integer( "subsdec-align", 0, NULL, ALIGN_TEXT, ALIGN_LONGTEXT, @@ -125,37 +124,25 @@ vlc_module_end(); static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; + decoder_sys_t *p_sys; + vlc_value_t val; - if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('s','u','b','t') && - p_dec->p_fifo->i_fourcc != VLC_FOURCC('s','s','a',' ') ) + if( p_dec->fmt_in.i_codec != VLC_FOURCC('s','u','b','t') && + p_dec->fmt_in.i_codec != VLC_FOURCC('s','s','a',' ') ) { return VLC_EGENERIC; } - p_dec->pf_init = InitDecoder; - p_dec->pf_decode = RunDecoder; - p_dec->pf_end = EndDecoder; + p_dec->pf_decode_sub = DecodeBlock; /* Allocate the memory needed to store the decoder's structure */ - if( ( p_dec->p_sys = + if( ( p_dec->p_sys = p_sys = (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL ) { msg_Err( p_dec, "out of memory" ); return VLC_EGENERIC; } - return VLC_SUCCESS; -} - -/***************************************************************************** - * InitDecoder: Initalize the decoder - *****************************************************************************/ -static int InitDecoder( decoder_t *p_dec ) -{ - decoder_sys_t *p_sys = p_dec->p_sys; - subtitle_data_t *p_demux_data = (subtitle_data_t *)p_dec->p_fifo->p_demux_data; - vlc_value_t val; - var_Create( p_dec, "subsdec-align", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Get( p_dec, "subsdec-align", &val ); p_sys->i_align = val.i_int; @@ -183,6 +170,7 @@ static int InitDecoder( decoder_t *p_dec ) if( val.psz_string ) free( val.psz_string ); #else + msg_Dbg( p_dec, "No iconv support available" ); #endif @@ -195,11 +183,11 @@ static int InitDecoder( decoder_t *p_dec ) } /**************************************************************************** - * RunDecoder: the whole thing + * DecodeBlock: the whole thing **************************************************************************** * This function must be fed with complete subtitles units. ****************************************************************************/ -static int RunDecoder( decoder_t *p_dec, block_t *p_block ) +static void DecodeBlock( decoder_t *p_dec, block_t **pp_block ) { vout_thread_t *p_vout; @@ -208,20 +196,18 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) if( !p_vout ) { msg_Warn( p_dec, "couldn't find a video output, trashing subtitle" ); - return VLC_SUCCESS; } - ParseText( p_dec, p_block, p_vout ); + ParseText( p_dec, *pp_block, p_vout ); vlc_object_release( p_vout ); - - return VLC_SUCCESS; } /***************************************************************************** - * EndDecoder: clean up the decoder + * CloseDecoder: clean up the decoder *****************************************************************************/ -static int EndDecoder( decoder_t *p_dec ) +static void CloseDecoder( vlc_object_t *p_this ) { + decoder_t *p_dec = (decoder_t *)p_this; decoder_sys_t *p_sys = p_dec->p_sys; vout_thread_t *p_vout; @@ -253,8 +239,6 @@ static int EndDecoder( decoder_t *p_dec ) #endif free( p_sys ); - - return VLC_SUCCESS; } /***************************************************************************** diff --git a/modules/codec/tarkin.c b/modules/codec/tarkin.c index 1c6b82c1e6..9ed2a34f87 100644 --- a/modules/codec/tarkin.c +++ b/modules/codec/tarkin.c @@ -2,7 +2,7 @@ * tarkin.c: tarkin decoder module making use of libtarkin. ***************************************************************************** * Copyright (C) 1999-2001 VideoLAN - * $Id: tarkin.c,v 1.6 2003/10/25 00:49:13 sam Exp $ + * $Id: tarkin.c,v 1.7 2003/11/16 21:07:30 gbazin Exp $ * * Authors: Gildas Bazin * @@ -105,7 +105,7 @@ static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; - if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('t','a','r','k') ) + if( p_dec->fmt_in.i_codec != VLC_FOURCC('t','a','r','k') ) { return VLC_EGENERIC; } diff --git a/modules/codec/theora.c b/modules/codec/theora.c index 2f81c7140d..48ffd2cccd 100644 --- a/modules/codec/theora.c +++ b/modules/codec/theora.c @@ -2,7 +2,7 @@ * theora.c: theora decoder module making use of libtheora. ***************************************************************************** * Copyright (C) 1999-2001 VideoLAN - * $Id: theora.c,v 1.13 2003/10/25 00:49:13 sam Exp $ + * $Id: theora.c,v 1.14 2003/11/16 21:07:30 gbazin Exp $ * * Authors: Gildas Bazin * @@ -28,11 +28,8 @@ #include /* memcpy(), memset() */ #include -#include #include #include -#include -#include #include @@ -58,17 +55,6 @@ struct decoder_sys_t theora_comment tc; /* theora comment header */ theora_state td; /* theora bitstream user comments */ - /* - * Output properties - */ - vout_thread_t *p_vout; - - /* - * Packetizer output properties - */ - sout_packetizer_input_t *p_sout_input; - sout_format_t sout_format; - /* * Common properties */ @@ -78,16 +64,14 @@ struct decoder_sys_t /***************************************************************************** * Local prototypes *****************************************************************************/ -static int OpenDecoder ( vlc_object_t * ); -static int OpenPacketizer( vlc_object_t * ); +static int OpenDecoder ( vlc_object_t * ); +static int OpenPacketizer( vlc_object_t * ); +static void CloseDecoder ( vlc_object_t * ); -static int InitDecoder ( decoder_t * ); -static int RunDecoder ( decoder_t *, block_t * ); -static int EndDecoder ( decoder_t * ); +static void *DecodeBlock ( decoder_t *, block_t ** ); +static void *ProcessPacket ( decoder_t *, ogg_packet *, block_t ** ); -static int ProcessPacket ( decoder_t *, ogg_packet *, mtime_t ); -static int DecodePacket ( decoder_t *, ogg_packet * ); -static int SendPacket ( decoder_t *, ogg_packet * ); +static picture_t *DecodePacket( decoder_t *, ogg_packet * ); static void ParseTheoraComments( decoder_t * ); static void theora_CopyPicture( decoder_t *, picture_t *, yuv_buffer * ); @@ -103,18 +87,18 @@ static block_t *Encode( encoder_t *p_enc, picture_t *p_pict ); vlc_module_begin(); set_description( _("Theora video decoder") ); set_capability( "decoder", 100 ); - set_callbacks( OpenDecoder, NULL ); + set_callbacks( OpenDecoder, CloseDecoder ); add_shortcut( "theora" ); add_submodule(); set_description( _("Theora video packetizer") ); set_capability( "packetizer", 100 ); - set_callbacks( OpenPacketizer, NULL ); + set_callbacks( OpenPacketizer, CloseDecoder ); add_shortcut( "theora" ); add_submodule(); set_description( _("Theora video encoder") ); - set_capability( "video encoder", 100 ); + set_capability( "encoder", 100 ); set_callbacks( OpenEncoder, CloseEncoder ); add_shortcut( "theora" ); vlc_module_end(); @@ -125,18 +109,15 @@ vlc_module_end(); static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; + decoder_sys_t *p_sys; - if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('t','h','e','o') ) + if( p_dec->fmt_in.i_codec != VLC_FOURCC('t','h','e','o') ) { return VLC_EGENERIC; } - p_dec->pf_init = InitDecoder; - p_dec->pf_decode = RunDecoder; - p_dec->pf_end = EndDecoder; - /* Allocate the memory needed to store the decoder's structure */ - if( ( p_dec->p_sys = + if( ( p_dec->p_sys = p_sys = (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL ) { msg_Err( p_dec, "out of memory" ); @@ -144,6 +125,24 @@ static int OpenDecoder( vlc_object_t *p_this ) } p_dec->p_sys->b_packetizer = VLC_FALSE; + p_sys->i_pts = 0; + + /* Set output properties */ + p_dec->fmt_out.i_cat = VIDEO_ES; + p_dec->fmt_out.i_codec = VLC_FOURCC('I','4','2','0'); + + /* Set callbacks */ + p_dec->pf_decode_video = (picture_t *(*)(decoder_t *, block_t **)) + DecodeBlock; + p_dec->pf_packetize = (block_t *(*)(decoder_t *, block_t **)) + DecodeBlock; + + /* Init supporting Theora structures needed in header parsing */ + theora_comment_init( &p_sys->tc ); + theora_info_init( &p_sys->ti ); + + p_sys->i_headers = 0; + return VLC_SUCCESS; } @@ -153,48 +152,29 @@ static int OpenPacketizer( vlc_object_t *p_this ) int i_ret = OpenDecoder( p_this ); - if( i_ret == VLC_SUCCESS ) p_dec->p_sys->b_packetizer = VLC_TRUE; + if( i_ret == VLC_SUCCESS ) + { + p_dec->p_sys->b_packetizer = VLC_TRUE; + p_dec->fmt_out.i_codec = VLC_FOURCC( 't', 'h', 'e', 'o' ); + } return i_ret; } -/***************************************************************************** - * InitDecoder: Initalize the decoder - *****************************************************************************/ -static int InitDecoder( decoder_t *p_dec ) -{ - decoder_sys_t *p_sys = p_dec->p_sys; - - p_sys->i_pts = 0; - - p_sys->p_sout_input = NULL; - p_sys->sout_format.i_cat = VIDEO_ES; - p_sys->sout_format.i_fourcc = VLC_FOURCC( 't', 'h', 'e', 'o' ); - p_sys->sout_format.i_width = 0; - p_sys->sout_format.i_height = 0; - p_sys->sout_format.i_bitrate = 0; - p_sys->sout_format.i_extra_data = 0; - p_sys->sout_format.p_extra_data = NULL; - - /* Init supporting Theora structures needed in header parsing */ - theora_comment_init( &p_sys->tc ); - theora_info_init( &p_sys->ti ); - - p_sys->i_headers = 0; - - return VLC_SUCCESS; -} - /**************************************************************************** - * RunDecoder: the whole thing + * DecodeBlock: the whole thing **************************************************************************** * This function must be fed with ogg packets. ****************************************************************************/ -static int RunDecoder( decoder_t *p_dec, block_t *p_block ) +static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; + block_t *p_block; ogg_packet oggpacket; - int i_ret; + + if( !pp_block || !*pp_block ) return NULL; + + p_block = *pp_block; /* Block to Ogg packet */ oggpacket.packet = p_block->p_buffer; @@ -211,55 +191,23 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) oggpacket.b_o_s = 1; /* yes this actually is a b_o_s packet :) */ if( theora_decode_header( &p_sys->ti, &p_sys->tc, &oggpacket ) < 0 ) { - msg_Err( p_dec->p_fifo, "This bitstream does not contain Theora " + msg_Err( p_dec, "This bitstream does not contain Theora " "video data" ); block_Release( p_block ); - return VLC_EGENERIC; + return NULL; } p_sys->i_headers++; + /* Set output properties */ + p_dec->fmt_out.video.i_width = p_sys->ti.width; + p_dec->fmt_out.video.i_height = p_sys->ti.height; - if( p_sys->b_packetizer ) - { - /* add a input for the stream ouput */ - p_sys->sout_format.i_width = p_sys->ti.width; - p_sys->sout_format.i_height = p_sys->ti.height; - - p_sys->p_sout_input = - sout_InputNew( p_dec, &p_sys->sout_format ); - - if( !p_sys->p_sout_input ) - { - msg_Err( p_dec, "cannot add a new stream" ); - block_Release( p_block ); - return VLC_EGENERIC; - } - } + if( p_sys->ti.aspect_denominator ) + p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR * + p_sys->ti.aspect_numerator / p_sys->ti.aspect_denominator; else - { - /* Initialize video output */ - int i_chroma, i_aspect; - - if( p_sys->ti.aspect_denominator ) - i_aspect = VOUT_ASPECT_FACTOR * p_sys->ti.aspect_numerator / - p_sys->ti.aspect_denominator; - else - i_aspect = VOUT_ASPECT_FACTOR * - p_sys->ti.frame_width / p_sys->ti.frame_height; - - i_chroma = VLC_FOURCC('Y','V','1','2'); - - p_sys->p_vout = - vout_Request( p_dec, NULL, - p_sys->ti.frame_width, p_sys->ti.frame_height, - i_chroma, i_aspect ); - if( p_sys->p_vout == NULL ) - { - msg_Err( p_dec, "failed to create video output" ); - block_Release( p_block ); - return VLC_EGENERIC; - } - } + p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR * + p_sys->ti.frame_width / p_sys->ti.frame_height; msg_Dbg( p_dec, "%dx%d %.02f fps video, frame content " "is %dx%d with offset (%d,%d)", @@ -268,17 +216,7 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) p_sys->ti.frame_width, p_sys->ti.frame_height, p_sys->ti.offset_x, p_sys->ti.offset_y ); - if( p_sys->b_packetizer ) - { - i_ret = SendPacket( p_dec, &oggpacket ); - block_Release( p_block ); - return i_ret; - } - else - { - block_Release( p_block ); - return VLC_SUCCESS; - } + return ProcessPacket( p_dec, &oggpacket, pp_block ); } if( p_sys->i_headers == 1 ) @@ -287,23 +225,13 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) if( theora_decode_header( &p_sys->ti, &p_sys->tc, &oggpacket ) < 0 ) { msg_Err( p_dec, "2nd Theora header is corrupted" ); - return VLC_EGENERIC; + return NULL; } p_sys->i_headers++; ParseTheoraComments( p_dec ); - if( p_sys->b_packetizer ) - { - i_ret = SendPacket( p_dec, &oggpacket ); - block_Release( p_block ); - return i_ret; - } - else - { - block_Release( p_block ); - return VLC_SUCCESS; - } + return ProcessPacket( p_dec, &oggpacket, pp_block ); } if( p_sys->i_headers == 2 ) @@ -314,7 +242,7 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) if( theora_decode_header( &p_sys->ti, &p_sys->tc, &oggpacket ) < 0 ) { msg_Err( p_dec, "3rd Theora header is corrupted" ); - return VLC_EGENERIC; + return NULL; } p_sys->i_headers++; @@ -324,115 +252,84 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) theora_decode_init( &p_sys->td, &p_sys->ti ); } - if( p_sys->b_packetizer ) - { - i_ret = SendPacket( p_dec, &oggpacket ); - block_Release( p_block ); - return i_ret; - } - else - { - block_Release( p_block ); - return VLC_SUCCESS; - } + return ProcessPacket( p_dec, &oggpacket, pp_block ); } - i_ret = ProcessPacket( p_dec, &oggpacket, p_block->i_pts ); - block_Release( p_block ); - return i_ret; + return ProcessPacket( p_dec, &oggpacket, pp_block ); } /***************************************************************************** - * ProcessPacket: processes a Vorbis packet. + * ProcessPacket: processes a theora packet. *****************************************************************************/ -static int ProcessPacket( decoder_t *p_dec, ogg_packet *p_oggpacket, - mtime_t i_pts ) +static void *ProcessPacket( decoder_t *p_dec, ogg_packet *p_oggpacket, + block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; + block_t *p_block = *pp_block; + void *p_buf; /* Date management */ - if( i_pts > 0 && i_pts != p_sys->i_pts ) + if( p_block->i_pts > 0 && p_block->i_pts != p_sys->i_pts ) { - p_sys->i_pts = i_pts; + p_sys->i_pts = p_block->i_pts; } if( p_sys->b_packetizer ) { - return SendPacket( p_dec, p_oggpacket ); + /* Date management */ + p_block->i_dts = p_block->i_pts = p_sys->i_pts; + + if( p_sys->i_headers >= 3 ) + p_block->i_length = p_sys->i_pts - p_block->i_pts; + else + p_block->i_length = 0; + + p_buf = p_block; } else { - return DecodePacket( p_dec, p_oggpacket ); - } -} - -/***************************************************************************** - * DecodePacket: decodes a Theora packet. - *****************************************************************************/ -static int DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket ) -{ - picture_t *p_pic; - yuv_buffer yuv; - - decoder_sys_t *p_sys = p_dec->p_sys; - - theora_decode_packetin( &p_sys->td, p_oggpacket ); - - /* Decode */ - theora_decode_YUVout( &p_sys->td, &yuv ); + if( p_sys->i_headers >= 3 ) + p_buf = DecodePacket( p_dec, p_oggpacket ); + else + p_buf = NULL; - /* Get a new picture */ - while( !(p_pic = vout_CreatePicture( p_sys->p_vout, 0, 0, 0 ) ) ) - { - if( p_dec->p_fifo->b_die || p_dec->p_fifo->b_error ) + if( p_block ) { - return VLC_EGENERIC; + block_Release( p_block ); + *pp_block = NULL; } - msleep( VOUT_OUTMEM_SLEEP ); } - if( !p_pic ) return VLC_EGENERIC; - - theora_CopyPicture( p_dec, p_pic, &yuv ); - - vout_DatePicture( p_sys->p_vout, p_pic, p_sys->i_pts ); - vout_DisplayPicture( p_sys->p_vout, p_pic ); /* Date management */ p_sys->i_pts += ( I64C(1000000) * p_sys->ti.fps_denominator / p_sys->ti.fps_numerator ); /* 1 frame per packet */ - return VLC_SUCCESS; + return p_buf; } /***************************************************************************** - * SendPacket: send an ogg packet to the stream output. + * DecodePacket: decodes a Theora packet. *****************************************************************************/ -static int SendPacket( decoder_t *p_dec, ogg_packet *p_oggpacket ) +static picture_t *DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket ) { decoder_sys_t *p_sys = p_dec->p_sys; + picture_t *p_pic; + yuv_buffer yuv; - sout_buffer_t *p_sout_buffer = - sout_BufferNew( p_sys->p_sout_input->p_sout, p_oggpacket->bytes ); - - if( !p_sout_buffer ) return VLC_EGENERIC; + theora_decode_packetin( &p_sys->td, p_oggpacket ); - p_dec->p_vlc->pf_memcpy( p_sout_buffer->p_buffer, - p_oggpacket->packet, - p_oggpacket->bytes ); + /* Decode */ + theora_decode_YUVout( &p_sys->td, &yuv ); - /* Date management */ - p_sout_buffer->i_dts = p_sout_buffer->i_pts = p_sys->i_pts; - p_sys->i_pts += ( I64C(1000000) * p_sys->ti.fps_denominator / - p_sys->ti.fps_numerator ); /* 1 frame per packet */ + /* Get a new picture */ + p_pic = p_dec->pf_vout_buffer_new( p_dec ); + if( !p_pic ) return NULL; - if( p_sys->i_headers >= 3 ) - p_sout_buffer->i_length = p_sys->i_pts - p_sout_buffer->i_pts; - else - p_sout_buffer->i_length = 0; + theora_CopyPicture( p_dec, p_pic, &yuv ); - sout_InputSendBuffer( p_sys->p_sout_input, p_sout_buffer ); + p_pic->date = p_sys->i_pts; - return VLC_SUCCESS; + return p_pic; } /***************************************************************************** @@ -467,26 +364,17 @@ static void ParseTheoraComments( decoder_t *p_dec ) } /***************************************************************************** - * EndDecoder: theora decoder destruction + * CloseDecoder: theora decoder destruction *****************************************************************************/ -static int EndDecoder( decoder_t *p_dec ) +static void CloseDecoder( vlc_object_t *p_this ) { + decoder_t *p_dec = (decoder_t *)p_this; decoder_sys_t *p_sys = p_dec->p_sys; - if( !p_sys->b_packetizer ) - vout_Request( p_dec, p_sys->p_vout, 0, 0, 0, 0 ); - - if( p_sys->p_sout_input != NULL ) - { - sout_InputDelete( p_sys->p_sout_input ); - } - theora_info_clear( &p_sys->ti ); theora_comment_clear( &p_sys->tc ); free( p_sys ); - - return VLC_SUCCESS; } /***************************************************************************** @@ -534,7 +422,7 @@ struct encoder_sys_t /* * Input properties */ - int i_headers; + vlc_bool_t b_headers; /* * Theora properties @@ -543,12 +431,6 @@ struct encoder_sys_t theora_comment tc; /* theora comment header */ theora_state td; /* theora bitstream user comments */ - /* - * Packetizer output properties - */ - sout_packetizer_input_t *p_sout_input; - sout_format_t sout_format; - /* * Common properties */ @@ -563,7 +445,7 @@ static int OpenEncoder( vlc_object_t *p_this ) encoder_t *p_enc = (encoder_t *)p_this; encoder_sys_t *p_sys = p_enc->p_sys; - if( p_enc->i_fourcc != VLC_FOURCC('t','h','e','o') ) + if( p_enc->fmt_out.i_codec != VLC_FOURCC('t','h','e','o') ) { return VLC_EGENERIC; } @@ -578,7 +460,7 @@ static int OpenEncoder( vlc_object_t *p_this ) p_enc->pf_header = Headers; p_enc->pf_encode_video = Encode; - p_enc->format.video.i_chroma = VLC_FOURCC('I','4','2','0'); + p_enc->fmt_in.i_codec = VLC_FOURCC('I','4','2','0'); #define frame_x_offset 0 #define frame_y_offset 0 @@ -590,10 +472,10 @@ static int OpenEncoder( vlc_object_t *p_this ) theora_info_init( &p_sys->ti ); - p_sys->ti.width = p_enc->format.video.i_width; - p_sys->ti.height = p_enc->format.video.i_height; - p_sys->ti.frame_width = p_enc->format.video.i_width; - p_sys->ti.frame_height = p_enc->format.video.i_height; + p_sys->ti.width = p_enc->fmt_in.video.i_width; + p_sys->ti.height = p_enc->fmt_in.video.i_height; + p_sys->ti.frame_width = p_enc->fmt_in.video.i_width; + p_sys->ti.frame_height = p_enc->fmt_in.video.i_height; p_sys->ti.offset_x = frame_x_offset; p_sys->ti.offset_y = frame_y_offset; p_sys->ti.fps_numerator = video_hzn; @@ -601,7 +483,7 @@ static int OpenEncoder( vlc_object_t *p_this ) p_sys->ti.aspect_numerator = video_an; p_sys->ti.aspect_denominator = video_ad; p_sys->ti.colorspace = not_specified; - p_sys->ti.target_bitrate = p_enc->i_bitrate; + p_sys->ti.target_bitrate = p_enc->fmt_out.i_bitrate; p_sys->ti.quality = video_q; p_sys->ti.dropframes_p = 0; @@ -609,7 +491,7 @@ static int OpenEncoder( vlc_object_t *p_this ) p_sys->ti.keyframe_auto_p = 1; p_sys->ti.keyframe_frequency = 64; p_sys->ti.keyframe_frequency_force = 64; - p_sys->ti.keyframe_data_target_bitrate = p_enc->i_bitrate * 1.5; + p_sys->ti.keyframe_data_target_bitrate = p_enc->fmt_out.i_bitrate * 1.5; p_sys->ti.keyframe_auto_threshold = 80; p_sys->ti.keyframe_mindistance = 8; p_sys->ti.noise_sensitivity = 1; @@ -618,7 +500,7 @@ static int OpenEncoder( vlc_object_t *p_this ) theora_info_clear( &p_sys->ti ); theora_comment_init( &p_sys->tc ); - p_sys->i_headers = 0; + p_sys->b_headers = VLC_FALSE; return VLC_SUCCESS; } @@ -631,35 +513,32 @@ static int OpenEncoder( vlc_object_t *p_this ) static block_t *Headers( encoder_t *p_enc ) { encoder_sys_t *p_sys = p_enc->p_sys; - ogg_packet oggpacket; - block_t *p_block; + block_t *p_chain = NULL; /* Create theora headers */ - switch( p_sys->i_headers ) + if( !p_sys->b_headers ) { - case 0: - theora_encode_header( &p_sys->td, &oggpacket ); - break; - case 1: - theora_encode_comment( &p_sys->tc, &oggpacket ); - break; - case 2: - theora_encode_tables( &p_sys->td, &oggpacket ); - break; - default: - break; - } + ogg_packet oggpackets[3]; + int i; - p_sys->i_headers++; - if( p_sys->i_headers > 3 ) return NULL; + theora_encode_header( &p_sys->td, &oggpackets[0] ); + theora_encode_comment( &p_sys->tc, &oggpackets[1] ); + theora_encode_tables( &p_sys->td, &oggpackets[2] ); - /* Ogg packet to block */ - p_block = block_New( p_enc, oggpacket.bytes ); - p_block->p_buffer = oggpacket.packet; - p_block->i_buffer = oggpacket.bytes; - p_block->i_dts = oggpacket.granulepos; + /* Ogg packet to block */ + for( i = 0; i < 3; i++ ) + { + block_t *p_block = block_New( p_enc, oggpackets[i].bytes ); + memcpy( p_block->p_buffer, oggpackets[i].packet, + oggpackets[i].bytes ); + p_block->i_dts = p_block->i_pts = p_block->i_length = 0; + block_ChainAppend( &p_chain, p_block ); + } - return p_block; + p_sys->b_headers = VLC_TRUE; + } + + return p_chain; } /**************************************************************************** @@ -689,7 +568,11 @@ static block_t *Encode( encoder_t *p_enc, picture_t *p_pict ) yuv.u = p_pict->p[1].p_pixels; yuv.v = p_pict->p[2].p_pixels; - theora_encode_YUVin( &p_sys->td, &yuv ); + if( theora_encode_YUVin( &p_sys->td, &yuv ) < 0 ) + { + msg_Warn( p_enc, "failed encoding a frame" ); + return NULL; + } theora_encode_packetout( &p_sys->td, 0, &oggpacket ); diff --git a/modules/codec/vorbis.c b/modules/codec/vorbis.c index 417694817b..a998aba594 100644 --- a/modules/codec/vorbis.c +++ b/modules/codec/vorbis.c @@ -2,7 +2,7 @@ * vorbis.c: vorbis decoder/encoder/packetizer module making use of libvorbis. ***************************************************************************** * Copyright (C) 1999-2001 VideoLAN - * $Id: vorbis.c,v 1.21 2003/10/27 17:50:54 gbazin Exp $ + * $Id: vorbis.c,v 1.22 2003/11/16 21:07:30 gbazin Exp $ * * Authors: Gildas Bazin * @@ -28,12 +28,7 @@ #include /* memcpy(), memset() */ #include -#include #include -#include -#include -#include - #include #include @@ -78,24 +73,11 @@ struct decoder_sys_t * decoder */ vorbis_block vb; /* local working space for packet->PCM decode */ - /* - * Output properties - */ - aout_instance_t *p_aout; - aout_input_t *p_aout_input; - audio_sample_format_t aout_format; - - /* - * Packetizer output properties - */ - sout_packetizer_input_t *p_sout_input; - sout_format_t sout_format; - /* * Common properties */ - audio_date_t end_date; - int i_last_block_size; + audio_date_t end_date; + int i_last_block_size; }; @@ -113,16 +95,15 @@ static int pi_channels_maps[6] = /**************************************************************************** * Local prototypes ****************************************************************************/ -static int OpenDecoder ( vlc_object_t * ); -static int OpenPacketizer( vlc_object_t * ); +static int OpenDecoder ( vlc_object_t * ); +static int OpenPacketizer( vlc_object_t * ); +static void CloseDecoder ( vlc_object_t * ); +static void *DecodeBlock ( decoder_t *, block_t ** ); -static int InitDecoder ( decoder_t * ); -static int RunDecoder ( decoder_t *, block_t * ); -static int EndDecoder ( decoder_t * ); +static void *ProcessPacket ( decoder_t *, ogg_packet *, block_t ** ); -static int ProcessPacket ( decoder_t *, ogg_packet *, mtime_t ); -static int DecodePacket ( decoder_t *, ogg_packet * ); -static int SendPacket ( decoder_t *, ogg_packet * ); +static aout_buffer_t *DecodePacket ( decoder_t *, ogg_packet * ); +static block_t *SendPacket( decoder_t *, ogg_packet *, block_t * ); static void ParseVorbisComments( decoder_t * ); @@ -150,17 +131,17 @@ vlc_module_begin(); #else set_capability( "decoder", 100 ); #endif - set_callbacks( OpenDecoder, NULL ); + set_callbacks( OpenDecoder, CloseDecoder ); add_submodule(); set_description( _("Vorbis audio packetizer") ); set_capability( "packetizer", 100 ); - set_callbacks( OpenPacketizer, NULL ); + set_callbacks( OpenPacketizer, CloseDecoder ); #ifndef MODULE_NAME_IS_tremor add_submodule(); set_description( _("Vorbis audio encoder") ); - set_capability( "audio encoder", 100 ); + set_capability( "encoder", 100 ); set_callbacks( OpenEncoder, CloseEncoder ); #endif @@ -172,24 +153,43 @@ vlc_module_end(); static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; + decoder_sys_t *p_sys; - if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('v','o','r','b') ) + if( p_dec->fmt_in.i_codec != VLC_FOURCC('v','o','r','b') ) { return VLC_EGENERIC; } - p_dec->pf_init = InitDecoder; - p_dec->pf_decode = RunDecoder; - p_dec->pf_end = EndDecoder; - /* Allocate the memory needed to store the decoder's structure */ - if( ( p_dec->p_sys = + if( ( p_dec->p_sys = p_sys = (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL ) { msg_Err( p_dec, "out of memory" ); return VLC_EGENERIC; } - p_dec->p_sys->b_packetizer = VLC_FALSE; + + /* Misc init */ + aout_DateSet( &p_sys->end_date, 0 ); + p_sys->b_packetizer = VLC_FALSE; + p_sys->i_headers = 0; + + /* Take care of vorbis init */ + vorbis_info_init( &p_sys->vi ); + vorbis_comment_init( &p_sys->vc ); + + /* Set output properties */ + p_dec->fmt_out.i_cat = AUDIO_ES; +#ifdef MODULE_NAME_IS_tremor + p_dec->fmt_out.i_codec = VLC_FOURCC('f','i','3','2'); +#else + p_dec->fmt_out.i_codec = VLC_FOURCC('f','l','3','2'); +#endif + + /* Set callbacks */ + p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **)) + DecodeBlock; + p_dec->pf_packetize = (block_t *(*)(decoder_t *, block_t **)) + DecodeBlock; return VLC_SUCCESS; } @@ -200,55 +200,42 @@ static int OpenPacketizer( vlc_object_t *p_this ) int i_ret = OpenDecoder( p_this ); - if( i_ret == VLC_SUCCESS ) p_dec->p_sys->b_packetizer = VLC_TRUE; + if( i_ret == VLC_SUCCESS ) + { + p_dec->p_sys->b_packetizer = VLC_TRUE; + p_dec->fmt_out.i_codec = VLC_FOURCC('v','o','r','b'); + } return i_ret; } -/***************************************************************************** - * InitDecoder: Initalize the decoder - *****************************************************************************/ -static int InitDecoder( decoder_t *p_dec ) -{ - decoder_sys_t *p_sys = p_dec->p_sys; - - aout_DateSet( &p_sys->end_date, 0 ); - - p_sys->p_aout = NULL; - p_sys->p_aout_input = NULL; - p_sys->aout_format.i_format = VLC_FOURCC('v','o','r','b'); - - p_sys->p_sout_input = NULL; - p_sys->sout_format.i_cat = AUDIO_ES; - p_sys->sout_format.i_fourcc = VLC_FOURCC( 'v', 'o', 'r', 'b' ); - p_sys->sout_format.i_block_align = 0; - p_sys->sout_format.i_bitrate = 0; - p_sys->sout_format.i_extra_data = 0; - p_sys->sout_format.p_extra_data = NULL; - - /* Take care of vorbis init */ - vorbis_info_init( &p_sys->vi ); - vorbis_comment_init( &p_sys->vc ); - - p_sys->i_headers = 0; - - return VLC_SUCCESS; -} - /**************************************************************************** - * RunDecoder: the whole thing + * DecodeBlock: the whole thing **************************************************************************** * This function must be fed with ogg packets. ****************************************************************************/ -static int RunDecoder( decoder_t *p_dec, block_t *p_block ) +static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; ogg_packet oggpacket; - int i_ret; - /* Block to Ogg packet */ - oggpacket.packet = p_block->p_buffer; - oggpacket.bytes = p_block->i_buffer; + if( !pp_block ) return NULL; + + if( *pp_block ) + { + /* Block to Ogg packet */ + oggpacket.packet = (*pp_block)->p_buffer; + oggpacket.bytes = (*pp_block)->i_buffer; + } + else + { + if( p_sys->b_packetizer ) return NULL; + + /* Block to Ogg packet */ + oggpacket.packet = NULL; + oggpacket.bytes = 0; + } + oggpacket.granulepos = -1; oggpacket.b_o_s = 0; oggpacket.e_o_s = 0; @@ -262,55 +249,20 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) if( vorbis_synthesis_headerin( &p_sys->vi, &p_sys->vc, &oggpacket ) < 0 ) { - msg_Err( p_dec->p_fifo, "This bitstream does not contain Vorbis " + msg_Err( p_dec, "This bitstream does not contain Vorbis " "audio data"); - block_Release( p_block ); - return VLC_EGENERIC; + block_Release( *pp_block ); + return NULL; } p_sys->i_headers++; - - if( p_sys->b_packetizer ) - { - /* add a input for the stream ouput */ - p_sys->sout_format.i_sample_rate = p_sys->vi.rate; - p_sys->sout_format.i_channels = p_sys->vi.channels; - p_sys->sout_format.i_block_align = 1; - p_sys->sout_format.i_bitrate = p_sys->vi.bitrate_nominal; - - p_sys->p_sout_input = - sout_InputNew( p_dec, &p_sys->sout_format ); - - if( !p_sys->p_sout_input ) - { - msg_Err( p_dec, "cannot add a new stream" ); - block_Release( p_block ); - return VLC_EGENERIC; - } - } - else - { -#ifdef MODULE_NAME_IS_tremor - p_sys->aout_format.i_format = VLC_FOURCC('f','i','3','2'); -#else - p_sys->aout_format.i_format = VLC_FOURCC('f','l','3','2'); -#endif - p_sys->aout_format.i_physical_channels = - p_sys->aout_format.i_original_channels = - pi_channels_maps[p_sys->vi.channels]; - p_sys->aout_format.i_rate = p_sys->vi.rate; - - p_sys->p_aout = NULL; - p_sys->p_aout_input = aout_DecNew( p_dec, &p_sys->p_aout, - &p_sys->aout_format ); - - if( p_sys->p_aout_input == NULL ) - { - msg_Err( p_dec, "failed to create aout fifo" ); - block_Release( p_block ); - return VLC_EGENERIC; - } - } + /* Setup the format */ + p_dec->fmt_out.audio.i_rate = p_sys->vi.rate; + p_dec->fmt_out.audio.i_channels = p_sys->vi.channels; + p_dec->fmt_out.audio.i_bitrate = p_sys->vi.bitrate_nominal; + p_dec->fmt_out.audio.i_physical_channels = + p_dec->fmt_out.audio.i_original_channels = + pi_channels_maps[p_sys->vi.channels]; aout_DateInit( &p_sys->end_date, p_sys->vi.rate ); @@ -318,17 +270,7 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) p_sys->vi.channels, p_sys->vi.rate, p_sys->vi.bitrate_nominal ); - if( p_sys->b_packetizer ) - { - i_ret = ProcessPacket( p_dec, &oggpacket, p_block->i_pts ); - block_Release( p_block ); - return i_ret; - } - else - { - block_Release( p_block ); - return VLC_SUCCESS; - } + return ProcessPacket( p_dec, &oggpacket, pp_block ); } if( p_sys->i_headers == 1 ) @@ -338,23 +280,14 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) < 0 ) { msg_Err( p_dec, "2nd Vorbis header is corrupted" ); - return VLC_EGENERIC; + block_Release( *pp_block ); + return NULL; } p_sys->i_headers++; ParseVorbisComments( p_dec ); - if( p_sys->b_packetizer ) - { - i_ret = ProcessPacket( p_dec, &oggpacket, p_block->i_pts ); - block_Release( p_block ); - return i_ret; - } - else - { - block_Release( p_block ); - return VLC_SUCCESS; - } + return ProcessPacket( p_dec, &oggpacket, pp_block ); } if( p_sys->i_headers == 2 ) @@ -366,7 +299,8 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) < 0 ) { msg_Err( p_dec, "3rd Vorbis header is corrupted" ); - return VLC_EGENERIC; + block_Release( *pp_block ); + return NULL; } p_sys->i_headers++; @@ -377,58 +311,62 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) vorbis_block_init( &p_sys->vd, &p_sys->vb ); } - if( p_sys->b_packetizer ) - { - i_ret = ProcessPacket( p_dec, &oggpacket, p_block->i_pts ); - block_Release( p_block ); - return i_ret; - } - else - { - block_Release( p_block ); - return VLC_SUCCESS; - } + return ProcessPacket( p_dec, &oggpacket, pp_block ); } - i_ret = ProcessPacket( p_dec, &oggpacket, p_block->i_pts ); - block_Release( p_block ); - return i_ret; + return ProcessPacket( p_dec, &oggpacket, pp_block ); } /***************************************************************************** * ProcessPacket: processes a Vorbis packet. *****************************************************************************/ -static int ProcessPacket( decoder_t *p_dec, ogg_packet *p_oggpacket, - mtime_t i_pts ) +static void *ProcessPacket( decoder_t *p_dec, ogg_packet *p_oggpacket, + block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; + block_t *p_block = *pp_block; /* Date management */ - if( i_pts > 0 && i_pts != aout_DateGet( &p_sys->end_date ) ) + if( p_block && p_block->i_pts > 0 && + p_block->i_pts != aout_DateGet( &p_sys->end_date ) ) { - aout_DateSet( &p_sys->end_date, i_pts ); + aout_DateSet( &p_sys->end_date, p_block->i_pts ); } if( !aout_DateGet( &p_sys->end_date ) ) { /* We've just started the stream, wait for the first PTS. */ - return VLC_SUCCESS; + if( p_block ) block_Release( p_block ); + return NULL; } + *pp_block = NULL; /* To avoid being fed the same packet again */ + if( p_sys->b_packetizer ) { - return SendPacket( p_dec, p_oggpacket ); + return SendPacket( p_dec, p_oggpacket, p_block ); } else { - return DecodePacket( p_dec, p_oggpacket ); + aout_buffer_t *p_aout_buffer; + + if( p_sys->i_headers >= 3 ) + p_aout_buffer = DecodePacket( p_dec, p_oggpacket ); + else + p_aout_buffer = NULL; + + if( p_block ) + { + block_Release( p_block ); + } + return p_aout_buffer; } } /***************************************************************************** * DecodePacket: decodes a Vorbis packet. *****************************************************************************/ -static int DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket ) +static aout_buffer_t *DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket ) { decoder_sys_t *p_sys = p_dec->p_sys; int i_samples; @@ -439,7 +377,8 @@ static int DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket ) float **pp_pcm; #endif - if( vorbis_synthesis( &p_sys->vb, p_oggpacket ) == 0 ) + if( p_oggpacket->bytes && + vorbis_synthesis( &p_sys->vb, p_oggpacket ) == 0 ) vorbis_synthesis_blockin( &p_sys->vd, &p_sys->vb ); /* **pp_pcm is a multichannel float vector. In stereo, for @@ -447,17 +386,15 @@ static int DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket ) * the size of each channel. Convert the float values * (-1.<=range<=1.) to whatever PCM format and write it out */ - while( ( i_samples = vorbis_synthesis_pcmout( &p_sys->vd, &pp_pcm ) ) > 0 ) + if( ( i_samples = vorbis_synthesis_pcmout( &p_sys->vd, &pp_pcm ) ) > 0 ) { aout_buffer_t *p_aout_buffer; - p_aout_buffer = aout_DecNewBuffer( p_sys->p_aout, p_sys->p_aout_input, - i_samples ); - if( !p_aout_buffer ) - { - msg_Err( p_dec, "cannot get aout buffer" ); - return VLC_SUCCESS; - } + + p_aout_buffer = + p_dec->pf_aout_buffer_new( p_dec, i_samples ); + + if( p_aout_buffer == NULL ) return NULL; /* Interleave the samples */ #ifdef MODULE_NAME_IS_tremor @@ -475,50 +412,38 @@ static int DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket ) p_aout_buffer->start_date = aout_DateGet( &p_sys->end_date ); p_aout_buffer->end_date = aout_DateIncrement( &p_sys->end_date, i_samples ); - - aout_DecPlay( p_sys->p_aout, p_sys->p_aout_input, p_aout_buffer ); + return p_aout_buffer; + } + else + { + return NULL; } - } /***************************************************************************** - * SendPacket: send an ogg packet to the stream output. + * SendPacket: send an ogg dated packet to the stream output. *****************************************************************************/ -static int SendPacket( decoder_t *p_dec, ogg_packet *p_oggpacket ) +static block_t *SendPacket( decoder_t *p_dec, ogg_packet *p_oggpacket, + block_t *p_block ) { decoder_sys_t *p_sys = p_dec->p_sys; - int i_block_size, i_samples; - - sout_buffer_t *p_sout_buffer = - sout_BufferNew( p_sys->p_sout_input->p_sout, p_oggpacket->bytes ); - - if( !p_sout_buffer ) return VLC_EGENERIC; + int i_block_size, i_samples; i_block_size = vorbis_packet_blocksize( &p_sys->vi, p_oggpacket ); if( i_block_size < 0 ) i_block_size = 0; /* non audio packet */ i_samples = ( p_sys->i_last_block_size + i_block_size ) >> 2; p_sys->i_last_block_size = i_block_size; - p_dec->p_vlc->pf_memcpy( p_sout_buffer->p_buffer, - p_oggpacket->packet, - p_oggpacket->bytes ); - - p_sout_buffer->i_bitrate = p_sys->vi.bitrate_nominal; - /* Date management */ - p_sout_buffer->i_dts = p_sout_buffer->i_pts = - aout_DateGet( &p_sys->end_date ); + p_block->i_dts = p_block->i_pts = aout_DateGet( &p_sys->end_date ); if( p_sys->i_headers >= 3 ) - p_sout_buffer->i_length = - aout_DateIncrement( &p_sys->end_date, i_samples ) - - p_sout_buffer->i_pts; + p_block->i_length = aout_DateIncrement( &p_sys->end_date, i_samples ) - + p_block->i_pts; else - p_sout_buffer->i_length = 0; - - sout_InputSendBuffer( p_sys->p_sout_input, p_sout_buffer ); + p_block->i_length = 0; - return VLC_SUCCESS; + return p_block; } /***************************************************************************** @@ -574,22 +499,13 @@ static void Interleave( float *p_out, const float **pp_in, } /***************************************************************************** - * EndDecoder: vorbis decoder destruction + * CloseDecoder: vorbis decoder destruction *****************************************************************************/ -static int EndDecoder( decoder_t * p_dec ) +static void CloseDecoder( vlc_object_t *p_this ) { + decoder_t *p_dec = (decoder_t *)p_this; decoder_sys_t *p_sys = p_dec->p_sys; - if( p_sys->p_aout_input != NULL ) - { - aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input ); - } - - if( p_sys->p_sout_input != NULL ) - { - sout_InputDelete( p_sys->p_sout_input ); - } - if( !p_sys->b_packetizer && p_sys->i_headers >= 3 ) { vorbis_block_clear( &p_sys->vb ); @@ -600,11 +516,8 @@ static int EndDecoder( decoder_t * p_dec ) vorbis_info_clear( &p_sys->vi ); /* must be called last */ free( p_sys ); - - return VLC_SUCCESS; } - #if defined(HAVE_VORBIS_VORBISENC_H) && !defined(MODULE_NAME_IS_tremor) /***************************************************************************** @@ -632,12 +545,6 @@ struct encoder_sys_t int i_samples_delay; int i_channels; - /* - * Packetizer output properties - */ - sout_packetizer_input_t *p_sout_input; - sout_format_t sout_format; - /* * Common properties */ @@ -652,7 +559,7 @@ static int OpenEncoder( vlc_object_t *p_this ) encoder_t *p_enc = (encoder_t *)p_this; encoder_sys_t *p_sys; - if( p_enc->i_fourcc != VLC_FOURCC('v','o','r','b') ) + if( p_enc->fmt_out.i_codec != VLC_FOURCC('v','o','r','b') ) { return VLC_EGENERIC; } @@ -667,14 +574,14 @@ static int OpenEncoder( vlc_object_t *p_this ) p_enc->pf_header = Headers; p_enc->pf_encode_audio = Encode; - p_enc->format.audio.i_format = VLC_FOURCC('f','l','3','2'); + p_enc->fmt_in.i_codec = VLC_FOURCC('f','l','3','2'); /* Initialize vorbis encoder */ vorbis_info_init( &p_sys->vi ); if( vorbis_encode_setup_managed( &p_sys->vi, - aout_FormatNbChannels( &p_enc->format.audio ), - p_enc->format.audio.i_rate, -1, p_enc->i_bitrate, -1 ) || + p_enc->fmt_in.audio.i_channels, p_enc->fmt_in.audio.i_rate, + -1, p_enc->fmt_out.i_bitrate, -1 ) || vorbis_encode_ctl( &p_sys->vi, OV_ECTL_RATEMANAGE_AVG, NULL ) || vorbis_encode_setup_init( &p_sys->vi ) ){} @@ -686,7 +593,7 @@ static int OpenEncoder( vlc_object_t *p_this ) vorbis_analysis_init( &p_sys->vd, &p_sys->vi ); vorbis_block_init( &p_sys->vd, &p_sys->vb ); - p_sys->i_channels = aout_FormatNbChannels( &p_enc->format.audio ); + p_sys->i_channels = p_enc->fmt_in.audio.i_channels; p_sys->i_last_block_size = 0; p_sys->i_samples_delay = 0; p_sys->i_headers = 0; @@ -743,7 +650,7 @@ static block_t *Encode( encoder_t *p_enc, aout_buffer_t *p_aout_buf ) p_sys->i_pts = p_aout_buf->start_date - (mtime_t)1000000 * (mtime_t)p_sys->i_samples_delay / - (mtime_t)p_enc->format.audio.i_rate; + (mtime_t)p_enc->fmt_in.audio.i_rate; p_sys->i_samples_delay += p_aout_buf->i_nb_samples; @@ -798,7 +705,7 @@ static block_t *Encode( encoder_t *p_enc, aout_buffer_t *p_aout_buf ) p_sys->i_last_block_size = i_block_size; p_block->i_length = (mtime_t)1000000 * - (mtime_t)i_samples / (mtime_t)p_enc->format.audio.i_rate; + (mtime_t)i_samples / (mtime_t)p_enc->fmt_in.audio.i_rate; p_block->i_dts = p_block->i_pts = p_sys->i_pts; diff --git a/modules/codec/xvid.c b/modules/codec/xvid.c index acf8a98f79..666b225e5e 100644 --- a/modules/codec/xvid.c +++ b/modules/codec/xvid.c @@ -2,7 +2,7 @@ * xvid.c: a decoder for libxvidcore, the Xvid video codec ***************************************************************************** * Copyright (C) 2002 VideoLAN - * $Id: xvid.c,v 1.6 2003/09/02 20:19:25 gbazin Exp $ + * $Id: xvid.c,v 1.7 2003/11/16 21:07:30 gbazin Exp $ * * Authors: Samuel Hocevar * @@ -61,9 +61,9 @@ static int OpenDecoder ( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; - if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('x','v','i','d') - && p_dec->p_fifo->i_fourcc != VLC_FOURCC('X','V','I','D') - && p_dec->p_fifo->i_fourcc != VLC_FOURCC('D','I','V','X') ) + if( p_dec->fmt_in.i_codec != VLC_FOURCC('x','v','i','d') + && p_dec->fmt_in.i_codec != VLC_FOURCC('X','V','I','D') + && p_dec->fmt_in.i_codec != VLC_FOURCC('D','I','V','X') ) { return VLC_EGENERIC; } diff --git a/modules/demux/a52sys.c b/modules/demux/a52sys.c index 3a26238d8b..fb15b537b9 100644 --- a/modules/demux/a52sys.c +++ b/modules/demux/a52sys.c @@ -2,7 +2,7 @@ * a52.c : Raw a52 Stream input module for vlc ***************************************************************************** * Copyright (C) 2001 VideoLAN - * $Id: a52sys.c,v 1.8 2003/11/13 12:28:34 fenrir Exp $ + * $Id: a52sys.c,v 1.9 2003/11/16 21:07:31 gbazin Exp $ * * Authors: Laurent Aimar * @@ -144,10 +144,10 @@ static int Open( vlc_object_t * p_this ) { int i_frame_size; - HeaderInfo( p_peek, &fmt.audio.i_channels, &fmt.audio.i_samplerate, &i_frame_size ); + HeaderInfo( p_peek, &fmt.audio.i_channels, &fmt.audio.i_rate, &i_frame_size ); msg_Dbg( p_input, "a52 channels=%d sample_rate=%d", - fmt.audio.i_channels, fmt.audio.i_samplerate ); + fmt.audio.i_channels, fmt.audio.i_rate ); } vlc_mutex_lock( &p_input->stream.stream_lock ); diff --git a/modules/demux/aac.c b/modules/demux/aac.c index 916632f209..69d5b852a3 100644 --- a/modules/demux/aac.c +++ b/modules/demux/aac.c @@ -2,7 +2,7 @@ * aac.c : Raw aac Stream input module for vlc ***************************************************************************** * Copyright (C) 2001 VideoLAN - * $Id: aac.c,v 1.6 2003/11/13 12:28:34 fenrir Exp $ + * $Id: aac.c,v 1.7 2003/11/16 21:07:31 gbazin Exp $ * * Authors: Laurent Aimar * @@ -157,7 +157,7 @@ static int Open( vlc_object_t * p_this ) if( HeaderCheck( p_peek ) ) { fmt.audio.i_channels = AAC_CHANNELS( p_peek ); - fmt.audio.i_samplerate = AAC_SAMPLE_RATE( p_peek ); + fmt.audio.i_rate = AAC_SAMPLE_RATE( p_peek ); msg_Dbg( p_input, "adts header: id=%d channels=%d sample_rate=%d", diff --git a/modules/demux/asf/asf.c b/modules/demux/asf/asf.c index 1873b11bdc..3cdd6a458e 100644 --- a/modules/demux/asf/asf.c +++ b/modules/demux/asf/asf.c @@ -2,7 +2,7 @@ * asf.c : ASFv01 file input module for vlc ***************************************************************************** * Copyright (C) 2002-2003 VideoLAN - * $Id: asf.c,v 1.40 2003/11/13 12:28:34 fenrir Exp $ + * $Id: asf.c,v 1.41 2003/11/16 21:07:31 gbazin Exp $ * * Authors: Laurent Aimar * @@ -186,7 +186,7 @@ static int Open( vlc_object_t * p_this ) es_format_Init( &fmt, AUDIO_ES, 0 ); wf_tag_to_fourcc( GetWLE( &p_data[0] ), &fmt.i_codec, NULL ); fmt.audio.i_channels = GetWLE( &p_data[2] ); - fmt.audio.i_samplerate = GetDWLE( &p_data[4] ); + fmt.audio.i_rate = GetDWLE( &p_data[4] ); fmt.audio.i_bitrate = GetDWLE( &p_data[8] ) * 8; fmt.audio.i_blockalign = GetWLE( &p_data[12] ); fmt.audio.i_bitspersample = GetWLE( &p_data[14] ); diff --git a/modules/demux/au.c b/modules/demux/au.c index fb28051569..ee1a7182c0 100644 --- a/modules/demux/au.c +++ b/modules/demux/au.c @@ -2,7 +2,7 @@ * au.c : au file input module for vlc ***************************************************************************** * Copyright (C) 2001-2003 VideoLAN - * $Id: au.c,v 1.8 2003/11/11 00:37:59 fenrir Exp $ + * $Id: au.c,v 1.9 2003/11/16 21:07:31 gbazin Exp $ * * Authors: Laurent Aimar * @@ -170,7 +170,7 @@ static int Open( vlc_object_t * p_this ) /* Create WAVEFORMATEX structure */ es_format_Init( &p_sys->fmt, AUDIO_ES, 0 ); p_sys->fmt.audio.i_channels = p_sys->au.i_channels; - p_sys->fmt.audio.i_samplerate = p_sys->au.i_sample_rate; + p_sys->fmt.audio.i_rate = p_sys->au.i_sample_rate; switch( p_sys->au.i_encoding ) { case AU_ALAW_8: /* 8-bit ISDN A-law */ @@ -262,7 +262,7 @@ static int Open( vlc_object_t * p_this ) i_cat = AU_CAT_UNKNOWN; goto error; } - p_sys->fmt.audio.i_bitrate = p_sys->fmt.audio.i_samplerate * + p_sys->fmt.audio.i_bitrate = p_sys->fmt.audio.i_rate * p_sys->fmt.audio.i_channels * p_sys->fmt.audio.i_bitspersample; @@ -279,7 +279,7 @@ static int Open( vlc_object_t * p_this ) int i_samples, i_modulo; /* read samples for 50ms of */ - i_samples = __MAX( p_sys->fmt.audio.i_samplerate / 20, 1 ); + i_samples = __MAX( p_sys->fmt.audio.i_rate / 20, 1 ); p_sys->i_frame_size = i_samples * p_sys->fmt.audio.i_channels * ( (p_sys->fmt.audio.i_bitspersample + 7) / 8 ); @@ -293,7 +293,7 @@ static int Open( vlc_object_t * p_this ) p_sys->i_frame_length = (mtime_t)1000000 * (mtime_t)i_samples / - (mtime_t)p_sys->fmt.audio.i_samplerate; + (mtime_t)p_sys->fmt.audio.i_rate; p_input->pf_demux = DemuxPCM; p_input->pf_demux_control = demux_vaControlDefault; diff --git a/modules/demux/avi/avi.c b/modules/demux/avi/avi.c index 81ca721f18..2d686c6405 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.68 2003/11/16 15:51:59 titer Exp $ + * $Id: avi.c,v 1.69 2003/11/16 21:07:31 gbazin Exp $ * Authors: Laurent Aimar * * This program is free software; you can redistribute it and/or modify @@ -274,7 +274,7 @@ static int Open( vlc_object_t * p_this ) es_format_Init( &fmt, AUDIO_ES, tk->i_codec ); fmt.audio.i_channels = p_auds->p_wf->nChannels; - fmt.audio.i_samplerate = p_auds->p_wf->nSamplesPerSec; + fmt.audio.i_rate = p_auds->p_wf->nSamplesPerSec; fmt.audio.i_bitrate = p_auds->p_wf->nAvgBytesPerSec * 8; fmt.audio.i_blockalign = p_auds->p_wf->nBlockAlign; fmt.audio.i_bitspersample = p_auds->p_wf->wBitsPerSample; diff --git a/modules/demux/livedotcom.cpp b/modules/demux/livedotcom.cpp index ab0e75df23..c9ddbab42f 100644 --- a/modules/demux/livedotcom.cpp +++ b/modules/demux/livedotcom.cpp @@ -2,7 +2,7 @@ * live.cpp : live.com support. ***************************************************************************** * Copyright (C) 2003 VideoLAN - * $Id: livedotcom.cpp,v 1.6 2003/11/08 06:47:34 fenrir Exp $ + * $Id: livedotcom.cpp,v 1.7 2003/11/16 21:07:31 gbazin Exp $ * * Authors: Laurent Aimar * @@ -453,19 +453,19 @@ static int DemuxOpen ( vlc_object_t *p_this ) { es_format_Init( &tk->fmt, AUDIO_ES, VLC_FOURCC( 'u', 'n', 'd', 'f' ) ); tk->fmt.audio.i_channels = sub->numChannels(); - tk->fmt.audio.i_samplerate = sub->rtpSource()->timestampFrequency(); + tk->fmt.audio.i_rate = sub->rtpSource()->timestampFrequency(); if( !strcmp( sub->codecName(), "MPA" ) || !strcmp( sub->codecName(), "MPA-ROBUST" ) || !strcmp( sub->codecName(), "X-MP3-DRAFT-00" ) ) { tk->fmt.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'a' ); - tk->fmt.audio.i_samplerate = 0; + tk->fmt.audio.i_rate = 0; } else if( !strcmp( sub->codecName(), "AC3" ) ) { tk->fmt.i_codec = VLC_FOURCC( 'a', '5', '2', ' ' ); - tk->fmt.audio.i_samplerate = 0; + tk->fmt.audio.i_rate = 0; } else if( !strcmp( sub->codecName(), "L16" ) ) { diff --git a/modules/demux/mkv.cpp b/modules/demux/mkv.cpp index f59a0012cf..a11c5b9268 100644 --- a/modules/demux/mkv.cpp +++ b/modules/demux/mkv.cpp @@ -2,7 +2,7 @@ * mkv.cpp : matroska demuxer ***************************************************************************** * Copyright (C) 2001 VideoLAN - * $Id: mkv.cpp,v 1.39 2003/11/13 12:28:34 fenrir Exp $ + * $Id: mkv.cpp,v 1.40 2003/11/16 21:07:31 gbazin Exp $ * * Authors: Laurent Aimar * @@ -734,7 +734,7 @@ static int Open( vlc_object_t * p_this ) KaxVideoDisplayWidth &vwidth = *(KaxVideoDisplayWidth*)el4; vwidth.ReadData( p_sys->es->I_O() ); - tk.fmt.video.i_display_width = uint16( vwidth ); + tk.fmt.video.i_visible_width = uint16( vwidth ); msg_Dbg( p_input, "| | | | + display width=%d", uint16( vwidth ) ); } else if( EbmlId( *el4 ) == KaxVideoDisplayHeight::ClassInfos.GlobalId ) @@ -742,7 +742,7 @@ static int Open( vlc_object_t * p_this ) KaxVideoDisplayWidth &vheight = *(KaxVideoDisplayWidth*)el4; vheight.ReadData( p_sys->es->I_O() ); - tk.fmt.video.i_display_height = uint16( vheight ); + tk.fmt.video.i_visible_height = uint16( vheight ); msg_Dbg( p_input, "| | | | + display height=%d", uint16( vheight ) ); } else if( EbmlId( *el4 ) == KaxVideoFrameRate::ClassInfos.GlobalId ) @@ -795,8 +795,8 @@ static int Open( vlc_object_t * p_this ) KaxAudioSamplingFreq &afreq = *(KaxAudioSamplingFreq*)el4; afreq.ReadData( p_sys->es->I_O() ); - tk.fmt.audio.i_samplerate = (int)float( afreq ); - msg_Dbg( p_input, "| | | | + afreq=%d", tk.fmt.audio.i_samplerate ); + tk.fmt.audio.i_rate = (int)float( afreq ); + msg_Dbg( p_input, "| | | | + afreq=%d", tk.fmt.audio.i_rate ); } else if( EbmlId( *el4 ) == KaxAudioChannels::ClassInfos.GlobalId ) { @@ -1068,7 +1068,7 @@ static int Open( vlc_object_t * p_this ) wf_tag_to_fourcc( GetWLE( &p_wf->wFormatTag ), &tk.fmt.i_codec, NULL ); tk.fmt.audio.i_channels = GetWLE( &p_wf->nChannels ); - tk.fmt.audio.i_samplerate = GetDWLE( &p_wf->nSamplesPerSec ); + tk.fmt.audio.i_rate = GetDWLE( &p_wf->nSamplesPerSec ); tk.fmt.audio.i_bitrate = GetDWLE( &p_wf->nAvgBytesPerSec ) * 8; tk.fmt.audio.i_blockalign = GetWLE( &p_wf->nBlockAlign );; tk.fmt.audio.i_bitspersample = GetWLE( &p_wf->wBitsPerSample ); @@ -1133,7 +1133,7 @@ static int Open( vlc_object_t * p_this ) for( i_srate = 0; i_srate < 13; i_srate++ ) { - if( i_sample_rates[i_srate] == tk.fmt.audio.i_samplerate ) + if( i_sample_rates[i_srate] == tk.fmt.audio.i_rate ) { break; } diff --git a/modules/demux/mpeg/mpga.c b/modules/demux/mpeg/mpga.c index ba84043b1d..3b603bd90d 100644 --- a/modules/demux/mpeg/mpga.c +++ b/modules/demux/mpeg/mpga.c @@ -2,7 +2,7 @@ * mpga.c : MPEG-I/II Audio input module for vlc ***************************************************************************** * Copyright (C) 2001 VideoLAN - * $Id: mpga.c,v 1.7 2003/11/13 12:28:34 fenrir Exp $ + * $Id: mpga.c,v 1.8 2003/11/16 21:07:31 gbazin Exp $ * * Authors: Laurent Aimar * @@ -311,7 +311,7 @@ static int Open( vlc_object_t * p_this ) MPGA_SAMPLE_RATE( header ) ); fmt.audio.i_channels = MPGA_CHANNELS( header ); - fmt.audio.i_samplerate = MPGA_SAMPLE_RATE( header ); + fmt.audio.i_rate = MPGA_SAMPLE_RATE( header ); fmt.audio.i_bitrate = p_sys->i_bitrate_avg; } diff --git a/modules/demux/wav.c b/modules/demux/wav.c index c585f6efe2..c9a65d5ca4 100644 --- a/modules/demux/wav.c +++ b/modules/demux/wav.c @@ -2,7 +2,7 @@ * wav.c : wav file input module for vlc ***************************************************************************** * Copyright (C) 2001-2003 VideoLAN - * $Id: wav.c,v 1.8 2003/11/11 02:49:26 fenrir Exp $ + * $Id: wav.c,v 1.9 2003/11/16 21:07:31 gbazin Exp $ * * Authors: Laurent Aimar * @@ -135,7 +135,7 @@ static int Open( vlc_object_t * p_this ) es_format_Init( &p_sys->fmt, AUDIO_ES, 0 ); wf_tag_to_fourcc( GetWLE( &p_wf->wFormatTag ), &p_sys->fmt.i_codec, &psz_name ); p_sys->fmt.audio.i_channels = GetWLE ( &p_wf->nChannels ); - p_sys->fmt.audio.i_samplerate = GetDWLE( &p_wf->nSamplesPerSec ); + p_sys->fmt.audio.i_rate = GetDWLE( &p_wf->nSamplesPerSec ); p_sys->fmt.audio.i_blockalign = GetWLE ( &p_wf->nBlockAlign ); p_sys->fmt.audio.i_bitrate = GetDWLE( &p_wf->nAvgBytesPerSec ) * 8; p_sys->fmt.audio.i_bitspersample = GetWLE ( &p_wf->wBitsPerSample );; @@ -150,7 +150,7 @@ static int Open( vlc_object_t * p_this ) msg_Dbg( p_input, "format:0x%4.4x channels:%d %dHz %dKo/s blockalign:%d bits/samples:%d extra size:%d", GetWLE( &p_wf->wFormatTag ), p_sys->fmt.audio.i_channels, - p_sys->fmt.audio.i_samplerate, + p_sys->fmt.audio.i_rate, p_sys->fmt.audio.i_bitrate / 8 / 1024, p_sys->fmt.audio.i_blockalign, p_sys->fmt.audio.i_bitspersample, @@ -338,12 +338,12 @@ static void FrameInfo_PCM( input_thread_t *p_input, int i_modulo; /* read samples for 50ms of */ - i_samples = __MAX( p_sys->fmt.audio.i_samplerate / 20, 1 ); + i_samples = __MAX( p_sys->fmt.audio.i_rate / 20, 1 ); *pi_length = (mtime_t)1000000 * (mtime_t)i_samples / - (mtime_t)p_sys->fmt.audio.i_samplerate; + (mtime_t)p_sys->fmt.audio.i_rate; i_bytes = i_samples * p_sys->fmt.audio.i_channels * ( (p_sys->fmt.audio.i_bitspersample + 7) / 8 ); @@ -370,7 +370,7 @@ static void FrameInfo_MS_ADPCM( input_thread_t *p_input, *pi_length = (mtime_t)1000000 * (mtime_t)i_samples / - (mtime_t)p_sys->fmt.audio.i_samplerate; + (mtime_t)p_sys->fmt.audio.i_rate; *pi_size = p_sys->fmt.audio.i_blockalign; } @@ -388,7 +388,7 @@ static void FrameInfo_IMA_ADPCM( input_thread_t *p_input, *pi_length = (mtime_t)1000000 * (mtime_t)i_samples / - (mtime_t)p_sys->fmt.audio.i_samplerate; + (mtime_t)p_sys->fmt.audio.i_rate; *pi_size = p_sys->fmt.audio.i_blockalign; } diff --git a/modules/misc/dummy/Modules.am b/modules/misc/dummy/Modules.am index b9f3531fcb..21773febf6 100644 --- a/modules/misc/dummy/Modules.am +++ b/modules/misc/dummy/Modules.am @@ -6,6 +6,7 @@ SOURCES_dummy = \ interface.c \ input.c \ decoder.c \ + encoder.c \ renderer.c \ $(NULL) diff --git a/modules/misc/dummy/decoder.c b/modules/misc/dummy/decoder.c index cbd400a890..317e4acf25 100644 --- a/modules/misc/dummy/decoder.c +++ b/modules/misc/dummy/decoder.c @@ -1,8 +1,8 @@ /***************************************************************************** - * dec_dummy.c: dummy decoder plugin for vlc. + * decoder.c: dummy decoder plugin for vlc. ***************************************************************************** * Copyright (C) 2002 VideoLAN - * $Id: decoder.c,v 1.7 2003/10/25 00:49:14 sam Exp $ + * $Id: decoder.c,v 1.8 2003/11/16 21:07:31 gbazin Exp $ * * Authors: Samuel Hocevar * @@ -45,99 +45,95 @@ #include /* sprintf() */ /***************************************************************************** - * Local prototypes + * decoder_sys_t : theora decoder descriptor *****************************************************************************/ -static int Run ( decoder_fifo_t * ); +struct decoder_sys_t +{ + int i_fd; +}; /***************************************************************************** - * OpenDecoder: probe the decoder and return score - ***************************************************************************** - * Always returns 0 because we are the dummy decoder! + * Local prototypes *****************************************************************************/ -int E_(OpenDecoder) ( vlc_object_t *p_this ) -{ - ((decoder_t*)p_this)->pf_run = Run; - - return VLC_SUCCESS; -} +static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block ); /***************************************************************************** - * Run: this function is called just after the thread is created + * OpenDecoder: Open the decoder *****************************************************************************/ -static int Run ( decoder_fifo_t *p_fifo ) +int E_(OpenDecoder) ( vlc_object_t *p_this ) { - uint8_t p_buffer[1024]; + decoder_t *p_dec = (decoder_t*)p_this; + decoder_sys_t *p_sys; + char psz_file[ PATH_MAX ]; - bit_stream_t bit_stream; - mtime_t last_date = mdate(); - size_t i_bytes = 0; + /* Allocate the memory needed to store the decoder's structure */ + if( ( p_dec->p_sys = p_sys = + (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL ) + { + msg_Err( p_dec, "out of memory" ); + return VLC_EGENERIC; + } - char psz_file[100]; -#ifndef UNDER_CE - int i_fd; -#endif + sprintf( psz_file, "stream.%i", p_dec->i_object_id ); - sprintf( psz_file, "stream.%i", p_fifo->i_object_id ); #ifndef UNDER_CE - i_fd = open( psz_file, O_WRONLY | O_CREAT | O_TRUNC, 00644 ); + p_sys->i_fd = open( psz_file, O_WRONLY | O_CREAT | O_TRUNC, 00644 ); - if( i_fd == -1 ) + if( p_sys->i_fd == -1 ) { - msg_Err( p_fifo, "cannot create `%s'", psz_file ); - p_fifo->b_error = 1; - DecoderError( p_fifo ); - return -1; + msg_Err( p_dec, "cannot create `%s'", psz_file ); + return VLC_EGENERIC; } #endif - msg_Dbg( p_fifo, "dumping stream to file `%s'", psz_file ); + msg_Dbg( p_dec, "dumping stream to file `%s'", psz_file ); - if( InitBitstream( &bit_stream, p_fifo, NULL, NULL ) != VLC_SUCCESS ) - { - msg_Err( p_fifo, "cannot initialize bitstream" ); - p_fifo->b_error = 1; - DecoderError( p_fifo ); -#ifndef UNDER_CE - close( i_fd ); -#endif - return -1; - } + /* Set callbacks */ + p_dec->pf_decode_video = (picture_t *(*)(decoder_t *, block_t **)) + DecodeBlock; + p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **)) + DecodeBlock; - while( !p_fifo->b_die && !p_fifo->b_error ) - { - GetChunk( &bit_stream, p_buffer, 1024 ); -#ifndef UNDER_CE - write( i_fd, p_buffer, 1024 ); + return VLC_SUCCESS; +} - i_bytes += 1024; -#endif +/**************************************************************************** + * RunDecoder: the whole thing + **************************************************************************** + * This function must be fed with ogg packets. + ****************************************************************************/ +static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) +{ + decoder_sys_t *p_sys = p_dec->p_sys; + block_t *p_block; - if( mdate() < last_date + 2000000 ) - { - continue; - } + if( !pp_block || !*pp_block ) return NULL; + p_block = *pp_block; - msg_Dbg( p_fifo, "dumped %i bytes", i_bytes ); + if( p_block->i_buffer ) + { +#ifndef UNDER_CE + write( p_sys->i_fd, p_block->p_buffer, p_block->i_buffer ); +#endif - i_bytes = 0; - last_date = mdate(); + msg_Dbg( p_dec, "dumped %i bytes", p_block->i_buffer ); } - if( i_bytes ) - { - msg_Dbg( p_fifo, "dumped %i bytes", i_bytes ); - } + block_Release( p_block ); + return NULL; +} + +/***************************************************************************** + * CloseDecoder: decoder destruction + *****************************************************************************/ +void E_(CloseDecoder) ( vlc_object_t *p_this ) +{ + decoder_t *p_dec = (decoder_t *)p_this; + decoder_sys_t *p_sys = p_dec->p_sys; #ifndef UNDER_CE - close( i_fd ); + close( p_sys->i_fd ); #endif - CloseBitstream( &bit_stream ); - - if( p_fifo->b_error ) - { - DecoderError( p_fifo ); - return -1; - } - return 0; + free( p_sys ); } diff --git a/modules/misc/dummy/dummy.c b/modules/misc/dummy/dummy.c index a568c80ffc..3fcca12808 100644 --- a/modules/misc/dummy/dummy.c +++ b/modules/misc/dummy/dummy.c @@ -2,7 +2,7 @@ * dummy.c : dummy plugin for vlc ***************************************************************************** * Copyright (C) 2000, 2001 VideoLAN - * $Id: dummy.c,v 1.9 2003/07/14 21:32:59 sigmunau Exp $ + * $Id: dummy.c,v 1.10 2003/11/16 21:07:31 gbazin Exp $ * * Authors: Samuel Hocevar * @@ -69,7 +69,11 @@ vlc_module_begin(); add_submodule(); set_description( _("dummy decoder function") ); set_capability( "decoder", 0 ); - set_callbacks( E_(OpenDecoder), NULL ); + set_callbacks( E_(OpenDecoder), E_(CloseDecoder) ); + add_submodule(); + set_description( _("dummy encoder function") ); + set_capability( "encoder", 0 ); + set_callbacks( E_(OpenEncoder), E_(CloseEncoder) ); add_submodule(); set_description( _("dummy audio output function") ); set_capability( "audio output", 1 ); diff --git a/modules/misc/dummy/dummy.h b/modules/misc/dummy/dummy.h index bd90954cdc..82224ebc52 100644 --- a/modules/misc/dummy/dummy.h +++ b/modules/misc/dummy/dummy.h @@ -2,7 +2,7 @@ * dummy.h : dummy plugin for vlc ***************************************************************************** * Copyright (C) 2000, 2001, 2002 VideoLAN - * $Id: dummy.h,v 1.2 2003/07/14 21:32:59 sigmunau Exp $ + * $Id: dummy.h,v 1.3 2003/11/16 21:07:31 gbazin Exp $ * * Authors: Samuel Hocevar * @@ -32,9 +32,13 @@ int E_(OpenDemux) ( vlc_object_t * ); void E_(CloseDemux) ( vlc_object_t * ); int E_(OpenDecoder) ( vlc_object_t * ); +void E_(CloseDecoder) ( vlc_object_t * ); + +int E_(OpenEncoder) ( vlc_object_t * ); +void E_(CloseEncoder) ( vlc_object_t * ); int E_(OpenAudio) ( vlc_object_t * ); int E_(OpenVideo) ( vlc_object_t * ); -int E_(OpenRenderer) ( vlc_object_t * ); +int E_(OpenRenderer) ( vlc_object_t * ); diff --git a/modules/packetizer/copy.c b/modules/packetizer/copy.c index 9b74eebd40..f5ee5bb1cd 100644 --- a/modules/packetizer/copy.c +++ b/modules/packetizer/copy.c @@ -2,7 +2,7 @@ * copy.c ***************************************************************************** * Copyright (C) 2001, 2002 VideoLAN - * $Id: copy.c,v 1.17 2003/09/29 22:37:36 gbazin Exp $ + * $Id: copy.c,v 1.18 2003/11/16 21:07:31 gbazin Exp $ * * Authors: Laurent Aimar * Eric Petit @@ -240,35 +240,6 @@ static int Init( packetizer_thread_t *p_pack ) p_pack->output_format.i_cat = VIDEO_ES; break; - case VLC_FOURCC( 'I', '4', '2', '0' ): - p_pack->output_format.i_fourcc = VLC_FOURCC( 'I', '4', '2', '0' ); - p_pack->output_format.i_cat = VIDEO_ES; - break; - case VLC_FOURCC( 'I', '4', '2', '2' ): - p_pack->output_format.i_fourcc = VLC_FOURCC( 'I', '4', '2', '2' ); - p_pack->output_format.i_cat = VIDEO_ES; - break; - case VLC_FOURCC( 'R', 'V', '1', '5' ): - p_pack->output_format.i_fourcc = VLC_FOURCC( 'R', 'V', '1', '5' ); - p_pack->output_format.i_cat = VIDEO_ES; - break; - case VLC_FOURCC( 'R', 'V', '1', '6' ): - p_pack->output_format.i_fourcc = VLC_FOURCC( 'R', 'V', '1', '6' ); - p_pack->output_format.i_cat = VIDEO_ES; - break; - case VLC_FOURCC( 'R', 'V', '2', '4' ): - p_pack->output_format.i_fourcc = VLC_FOURCC( 'R', 'V', '2', '4' ); - p_pack->output_format.i_cat = VIDEO_ES; - break; - case VLC_FOURCC( 'R', 'V', '3', '2' ): - p_pack->output_format.i_fourcc = VLC_FOURCC( 'R', 'V', '3', '2' ); - p_pack->output_format.i_cat = VIDEO_ES; - break; - case VLC_FOURCC( 'G', 'R', 'E', 'Y' ): - p_pack->output_format.i_fourcc = VLC_FOURCC( 'G', 'R', 'E', 'Y' ); - p_pack->output_format.i_cat = VIDEO_ES; - break; - /* audio */ case VLC_FOURCC( 'm', 'p', 'g', 'a' ): p_pack->output_format.i_fourcc = VLC_FOURCC( 'm', 'p', 'g', 'a' ); diff --git a/modules/packetizer/mpeg4audio.c b/modules/packetizer/mpeg4audio.c index dfc319c8ee..6a1b5e694d 100644 --- a/modules/packetizer/mpeg4audio.c +++ b/modules/packetizer/mpeg4audio.c @@ -2,7 +2,7 @@ * mpeg4audio.c: parse and packetize an MPEG 4 audio stream ***************************************************************************** * Copyright (C) 2001, 2002 VideoLAN - * $Id: mpeg4audio.c,v 1.11 2003/10/24 17:55:14 gbazin Exp $ + * $Id: mpeg4audio.c,v 1.12 2003/11/16 21:07:31 gbazin Exp $ * * Authors: Laurent Aimar * Gildas Bazin @@ -58,23 +58,15 @@ struct decoder_sys_t /* * Input properties */ - int i_state; + int i_state; - block_t *p_chain; block_bytestream_t bytestream; - /* - * Packetizer output properties - */ - sout_packetizer_input_t *p_sout_input; - sout_format_t sout_format; - sout_buffer_t * p_sout_buffer; /* current sout buffer */ - /* * Common properties */ - audio_date_t end_date; - mtime_t pts; + audio_date_t end_date; + mtime_t i_pts; int i_frame_size, i_raw_blocks; unsigned int i_channels; @@ -87,7 +79,8 @@ enum { STATE_SYNC, STATE_HEADER, STATE_NEXT_SYNC, - STATE_DATA + STATE_GET_DATA, + STATE_SEND_DATA }; static int i_sample_rates[] = @@ -101,12 +94,13 @@ static int i_sample_rates[] = /**************************************************************************** * Local prototypes ****************************************************************************/ -static int OpenPacketizer( vlc_object_t * ); -static int InitPacketizer( decoder_t * ); -static int RunFramePacketizer ( decoder_t *, block_t * ); -static int RunADTSPacketizer ( decoder_t *, block_t * ); -static int EndPacketizer ( decoder_t * ); -static int GetSoutBuffer( decoder_t *, sout_buffer_t ** ); +static int OpenPacketizer( vlc_object_t * ); +static void ClosePacketizer( vlc_object_t * ); + +static block_t *PacketizeBlock ( decoder_t *, block_t ** ); +static block_t *ADTSPacketizeBlock( decoder_t *, block_t ** ); + +static uint8_t *GetOutBuffer ( decoder_t *, void ** ); static int ADTSSyncInfo( decoder_t *, const byte_t * p_buf, unsigned int * pi_channels, @@ -121,7 +115,7 @@ static int ADTSSyncInfo( decoder_t *, const byte_t * p_buf, vlc_module_begin(); set_description( _("MPEG4 Audio packetizer") ); set_capability( "packetizer", 50 ); - set_callbacks( OpenPacketizer, NULL ); + set_callbacks( OpenPacketizer, ClosePacketizer ); vlc_module_end(); /***************************************************************************** @@ -130,151 +124,140 @@ vlc_module_end(); static int OpenPacketizer( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; + decoder_sys_t *p_sys; - if( p_dec->p_fifo->i_fourcc != VLC_FOURCC( 'm', 'p', '4', 'a' ) ) + if( p_dec->fmt_in.i_codec != VLC_FOURCC( 'm', 'p', '4', 'a' ) ) { return VLC_EGENERIC; } /* Allocate the memory needed to store the decoder's structure */ - if( ( p_dec->p_sys = + if( ( p_dec->p_sys = p_sys = (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL ) { msg_Err( p_dec, "out of memory" ); return VLC_EGENERIC; } - p_dec->pf_init = InitPacketizer; - p_dec->pf_decode = RunFramePacketizer; - p_dec->pf_end = EndPacketizer; - - return VLC_SUCCESS; -} - -/***************************************************************************** - * InitPacketizer: Initalize the packetizer - *****************************************************************************/ -static int InitPacketizer( decoder_t *p_dec ) -{ - decoder_sys_t *p_sys = p_dec->p_sys; - WAVEFORMATEX *p_wf; - + /* Misc init */ p_sys->i_state = STATE_NOSYNC; - aout_DateSet( &p_sys->end_date, 0 ); + p_sys->bytestream = block_BytestreamInit( p_dec ); - p_sys->p_sout_input = NULL; - p_sys->p_sout_buffer = NULL; - p_sys->p_chain = NULL; + /* Set output properties */ + p_dec->fmt_out.i_cat = AUDIO_ES; + p_dec->fmt_out.i_codec = VLC_FOURCC('m','p','4','a'); - msg_Info( p_dec, "Running MPEG4 audio packetizer" ); + /* Set callback */ + p_dec->pf_packetize = PacketizeBlock; - p_wf = (WAVEFORMATEX*)p_dec->p_fifo->p_waveformatex; + msg_Info( p_dec, "Running MPEG4 audio packetizer" ); - if( p_wf && p_wf->cbSize > 0) + if( p_dec->fmt_in.i_extra > 0 ) { - uint8_t *p_config = (uint8_t*)&p_wf[1]; + uint8_t *p_config = (uint8_t*)p_dec->fmt_in.p_extra; int i_index; i_index = ( ( p_config[0] << 1 ) | ( p_config[1] >> 7 ) ) & 0x0f; if( i_index != 0x0f ) { - p_sys->i_rate = i_sample_rates[i_index]; - p_sys->i_frame_length = (( p_config[1] >> 2 ) & 0x01) ? 960 : 1024; + p_dec->fmt_out.audio.i_rate = i_sample_rates[i_index]; + p_dec->fmt_out.audio.i_frame_length = + (( p_config[1] >> 2 ) & 0x01) ? 960 : 1024; } else { - p_sys->i_rate = ( ( p_config[1] & 0x7f ) << 17 ) | + p_dec->fmt_out.audio.i_rate = ( ( p_config[1] & 0x7f ) << 17 ) | ( p_config[2] << 9 ) | ( p_config[3] << 1 ) | ( p_config[4] >> 7 ); - p_sys->i_frame_length = (( p_config[4] >> 2 ) & 0x01) ? 960 : 1024; + p_dec->fmt_out.audio.i_frame_length = + (( p_config[4] >> 2 ) & 0x01) ? 960 : 1024; } msg_Dbg( p_dec, "AAC %dHz %d samples/frame", - p_sys->i_rate, p_sys->i_frame_length ); + p_dec->fmt_out.audio.i_rate, + p_dec->fmt_out.audio.i_frame_length ); - p_sys->i_channels = p_wf->nChannels; - p_sys->sout_format.i_extra_data = p_wf->cbSize; - p_sys->sout_format.p_extra_data = malloc( p_wf->cbSize ); - memcpy( p_sys->sout_format.p_extra_data, &p_wf[1], p_wf->cbSize ); + aout_DateInit( &p_sys->end_date, p_dec->fmt_out.audio.i_rate ); + + p_dec->fmt_out.audio.i_channels = p_dec->fmt_in.audio.i_channels; + p_dec->fmt_out.i_extra = p_dec->fmt_in.i_extra; + p_dec->fmt_out.p_extra = malloc( p_dec->fmt_in.i_extra ); + memcpy( p_dec->fmt_out.p_extra, p_dec->fmt_in.p_extra, + p_dec->fmt_in.i_extra ); } else { msg_Dbg( p_dec, "No decoder specific info, must be an ADTS stream" ); /* We will try to create a AAC Config from adts */ - p_sys->sout_format.i_extra_data = 0; - p_sys->sout_format.p_extra_data = NULL; - p_dec->pf_decode = RunADTSPacketizer; + p_dec->fmt_out.i_extra = 0; + p_dec->fmt_out.p_extra = NULL; + p_dec->pf_packetize = ADTSPacketizeBlock; } return VLC_SUCCESS; } /**************************************************************************** - * RunFramePacketizer: the whole thing + * PacketizeBlock: the whole thing **************************************************************************** * This function must be fed with complete frames. ****************************************************************************/ -static int RunFramePacketizer( decoder_t *p_dec, block_t *p_block ) +static block_t *PacketizeBlock( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; + block_t *p_block; + + if( !pp_block || !*pp_block ) return NULL; + + p_block = *pp_block; if( !aout_DateGet( &p_sys->end_date ) && !p_block->i_pts ) { /* We've just started the stream, wait for the first PTS. */ block_Release( p_block ); - return VLC_SUCCESS; + return NULL; } - - p_sys->pts = p_block->i_pts; - p_sys->i_frame_size = p_block->i_buffer; - - if( GetSoutBuffer( p_dec, &p_sys->p_sout_buffer ) != VLC_SUCCESS ) + else if( p_block->i_pts != 0 && + p_block->i_pts != aout_DateGet( &p_sys->end_date ) ) { - return VLC_EGENERIC; + aout_DateSet( &p_sys->end_date, p_block->i_pts ); } - /* Copy the whole frame into the buffer */ - p_dec->p_vlc->pf_memcpy( p_sys->p_sout_buffer->p_buffer, - p_block->p_buffer, p_block->i_buffer ); + p_block->i_pts = p_block->i_dts = aout_DateGet( &p_sys->end_date ); - sout_InputSendBuffer( p_sys->p_sout_input, p_sys->p_sout_buffer ); - p_sys->p_sout_buffer = NULL; + p_block->i_length = aout_DateIncrement( &p_sys->end_date, + p_dec->fmt_out.audio.i_frame_length ) - p_block->i_pts; - block_Release( p_block ); - return VLC_SUCCESS; + return *pp_block; } /**************************************************************************** - * RunADTSPacketizer: the whole thing + * DTSPacketizeBlock: the whole thing ****************************************************************************/ -static int RunADTSPacketizer( decoder_t *p_dec, block_t *p_block ) +static block_t *ADTSPacketizeBlock( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; uint8_t p_header[ADTS_HEADER_SIZE]; + void *p_out_buffer; + uint8_t *p_buf; - if( !aout_DateGet( &p_sys->end_date ) && !p_block->i_pts ) + if( !pp_block || !*pp_block ) return NULL; + + if( !aout_DateGet( &p_sys->end_date ) && !(*pp_block)->i_pts ) { /* We've just started the stream, wait for the first PTS. */ - block_Release( p_block ); - return VLC_SUCCESS; + block_Release( *pp_block ); + return NULL; } - if( p_block->b_discontinuity ) + if( (*pp_block)->b_discontinuity ) { - p_sys->i_state = STATE_SYNC; + p_sys->i_state = STATE_NOSYNC; } - if( p_sys->p_chain ) - { - block_ChainAppend( &p_sys->p_chain, p_block ); - } - else - { - block_ChainAppend( &p_sys->p_chain, p_block ); - p_sys->bytestream = block_BytestreamInit( p_dec, p_sys->p_chain, 0 ); - } + block_BytestreamPush( &p_sys->bytestream, *pp_block ); while( 1 ) { @@ -295,27 +278,19 @@ static int RunADTSPacketizer( decoder_t *p_dec, block_t *p_block ) } if( p_sys->i_state != STATE_SYNC ) { - if( block_PeekByte( &p_sys->bytestream, p_header ) - == VLC_SUCCESS && p_header[0] == 0xff ) - { - /* Start of a sync word, need more data */ - return VLC_SUCCESS; - } - - block_ChainRelease( p_sys->p_chain ); - p_sys->p_chain = NULL; + block_BytestreamFlush( &p_sys->bytestream ); /* Need more data */ - return VLC_SUCCESS; + return NULL; } case STATE_SYNC: /* New frame, set the Presentation Time Stamp */ - p_sys->pts = p_sys->bytestream.p_block->i_pts; - if( p_sys->pts != 0 && - p_sys->pts != aout_DateGet( &p_sys->end_date ) ) + p_sys->i_pts = p_sys->bytestream.p_block->i_pts; + if( p_sys->i_pts != 0 && + p_sys->i_pts != aout_DateGet( &p_sys->end_date ) ) { - aout_DateSet( &p_sys->end_date, p_sys->pts ); + aout_DateSet( &p_sys->end_date, p_sys->i_pts ); } p_sys->i_state = STATE_HEADER; break; @@ -326,7 +301,7 @@ static int RunADTSPacketizer( decoder_t *p_dec, block_t *p_block ) ADTS_HEADER_SIZE ) != VLC_SUCCESS ) { /* Need more data */ - return VLC_SUCCESS; + return NULL; } /* Check if frame is valid and get frame info */ @@ -344,9 +319,9 @@ static int RunADTSPacketizer( decoder_t *p_dec, block_t *p_block ) break; } - p_sys->i_state = STATE_DATA; + p_sys->i_state = STATE_NEXT_SYNC; - case STATE_DATA: + case STATE_NEXT_SYNC: /* TODO: If p_block == NULL, flush the buffer without checking the * next sync word */ @@ -356,7 +331,7 @@ static int RunADTSPacketizer( decoder_t *p_dec, block_t *p_block ) != VLC_SUCCESS ) { /* Need more data */ - return VLC_SUCCESS; + return NULL; } if( p_header[0] != 0xff || (p_header[1] & 0xf6) != 0xf0 ) @@ -368,125 +343,103 @@ static int RunADTSPacketizer( decoder_t *p_dec, block_t *p_block ) break; } - if( !p_sys->p_sout_buffer ) - if( GetSoutBuffer( p_dec, &p_sys->p_sout_buffer ) != VLC_SUCCESS ) + p_sys->i_state = STATE_SEND_DATA; + break; + + case STATE_GET_DATA: + /* Make sure we have enough data. + * (Not useful if we went through NEXT_SYNC) */ + if( block_WaitBytes( &p_sys->bytestream, p_sys->i_frame_size + + p_sys->i_header_size) != VLC_SUCCESS ) { - return VLC_EGENERIC; + /* Need more data */ + return NULL; } + p_sys->i_state = STATE_SEND_DATA; - /* Skip the ADTS header */ - if( p_sys->i_header_size ) + case STATE_SEND_DATA: + if( !(p_buf = GetOutBuffer( p_dec, &p_out_buffer )) ) { - if( block_SkipBytes( &p_sys->bytestream, - p_sys->i_header_size ) != VLC_SUCCESS ) - { - /* Need more data */ - return VLC_SUCCESS; - } - p_sys->i_header_size = 0; + //p_dec->b_error = VLC_TRUE; + return NULL; } + /* When we reach this point we already know we have enough + * data available. */ + + /* Skip the ADTS header */ + block_SkipBytes( &p_sys->bytestream, p_sys->i_header_size ); + /* Copy the whole frame into the buffer */ - if( block_GetBytes( &p_sys->bytestream, - p_sys->p_sout_buffer->p_buffer, - p_sys->i_frame_size ) != VLC_SUCCESS ) - { - /* Need more data */ - return VLC_SUCCESS; - } + block_GetBytes( &p_sys->bytestream, p_buf, p_sys->i_frame_size ); - p_sys->p_chain = block_BytestreamFlush( &p_sys->bytestream ); + /* Make sure we don't reuse the same pts twice */ + if( p_sys->i_pts == p_sys->bytestream.p_block->i_pts ) + p_sys->i_pts = p_sys->bytestream.p_block->i_pts = 0; - sout_InputSendBuffer( p_sys->p_sout_input, p_sys->p_sout_buffer ); + /* So p_block doesn't get re-added several times */ + *pp_block = block_BytestreamPop( &p_sys->bytestream ); p_sys->i_state = STATE_NOSYNC; - p_sys->p_sout_buffer = NULL; - /* Make sure we don't reuse the same pts twice */ - if( p_sys->pts == p_sys->bytestream.p_block->i_pts ) - p_sys->pts = p_sys->bytestream.p_block->i_pts = 0; + return p_out_buffer; } } - return VLC_SUCCESS; + return NULL; } /***************************************************************************** - * GetSoutBuffer: + * GetOutBuffer: *****************************************************************************/ -static int GetSoutBuffer( decoder_t *p_dec, sout_buffer_t **pp_buffer ) +static uint8_t *GetOutBuffer( decoder_t *p_dec, void **pp_out_buffer ) { decoder_sys_t *p_sys = p_dec->p_sys; + block_t *p_block; - if( p_sys->p_sout_input != NULL && - ( p_sys->sout_format.i_sample_rate != (int)p_sys->i_rate - || p_sys->sout_format.i_channels != (int)p_sys->i_channels ) ) - { - /* Parameters changed - this should not happen. */ - } - - /* Creating the sout input if not created yet. */ - if( p_sys->p_sout_input == NULL ) + if( p_dec->fmt_out.audio.i_rate != p_sys->i_rate ) { - p_sys->sout_format.i_cat = AUDIO_ES; - p_sys->sout_format.i_fourcc = VLC_FOURCC( 'm', 'p', '4', 'a' ); - p_sys->sout_format.i_sample_rate = p_sys->i_rate; - p_sys->sout_format.i_channels = p_sys->i_channels; - p_sys->sout_format.i_block_align = 0; - p_sys->sout_format.i_bitrate = 0; - - aout_DateInit( &p_sys->end_date, p_sys->i_rate ); - aout_DateSet( &p_sys->end_date, p_sys->pts ); - - p_sys->p_sout_input = sout_InputNew( p_dec, &p_sys->sout_format ); - if( p_sys->p_sout_input == NULL ) - { - msg_Err( p_dec, "cannot add a new stream" ); - *pp_buffer = NULL; - return VLC_EGENERIC; - } msg_Info( p_dec, "AAC channels: %d samplerate: %d", p_sys->i_channels, p_sys->i_rate ); - } - *pp_buffer = sout_BufferNew( p_sys->p_sout_input->p_sout, - p_sys->i_frame_size ); - if( *pp_buffer == NULL ) - { - return VLC_EGENERIC; + aout_DateInit( &p_sys->end_date, p_sys->i_rate ); + aout_DateSet( &p_sys->end_date, p_sys->i_pts ); } - (*pp_buffer)->i_pts = - (*pp_buffer)->i_dts = aout_DateGet( &p_sys->end_date ); + p_dec->fmt_out.audio.i_rate = p_sys->i_rate; + p_dec->fmt_out.audio.i_channels = p_sys->i_channels; + p_dec->fmt_out.audio.i_bytes_per_frame = p_sys->i_frame_size; + p_dec->fmt_out.audio.i_frame_length = p_sys->i_frame_length; - (*pp_buffer)->i_length = - aout_DateIncrement( &p_sys->end_date, p_sys->i_frame_length ) - - (*pp_buffer)->i_pts; +#if 0 + p_dec->fmt_out.audio.i_original_channels = p_sys->i_channels_conf; + p_dec->fmt_out.audio.i_physical_channels = + p_sys->i_channels_conf & AOUT_CHAN_PHYSMASK; +#endif - return VLC_SUCCESS; + p_block = block_New( p_dec, p_sys->i_frame_size ); + if( p_block == NULL ) return NULL; + + p_block->i_pts = p_block->i_dts = aout_DateGet( &p_sys->end_date ); + + p_block->i_length = aout_DateIncrement( &p_sys->end_date, + p_sys->i_frame_length ) - p_block->i_pts; + + *pp_out_buffer = p_block; + return p_block->p_buffer; } /***************************************************************************** - * EndPacketizer: clean up the packetizer + * ClosePacketizer: clean up the packetizer *****************************************************************************/ -static int EndPacketizer( decoder_t *p_dec ) +static void ClosePacketizer( vlc_object_t *p_this ) { - if( p_dec->p_sys->p_sout_input != NULL ) - { - if( p_dec->p_sys->p_sout_buffer ) - { - sout_BufferDelete( p_dec->p_sys->p_sout_input->p_sout, - p_dec->p_sys->p_sout_buffer ); - } - - sout_InputDelete( p_dec->p_sys->p_sout_input ); - } + decoder_t *p_dec = (decoder_t *)p_this; + decoder_sys_t *p_sys = p_dec->p_sys; - if( p_dec->p_sys->p_chain ) block_ChainRelease( p_dec->p_sys->p_chain ); + block_BytestreamRelease( &p_sys->bytestream ); free( p_dec->p_sys ); - - return VLC_SUCCESS; } /***************************************************************************** @@ -499,7 +452,6 @@ static int ADTSSyncInfo( decoder_t * p_dec, const byte_t * p_buf, unsigned int * pi_header_size, unsigned int * pi_raw_blocks_in_frame ) { - decoder_sys_t *p_sys = p_dec->p_sys; int i_id, i_profile, i_sample_rate_idx, i_frame_size; vlc_bool_t b_crc; @@ -525,13 +477,13 @@ static int ADTSSyncInfo( decoder_t * p_dec, const byte_t * p_buf, *pi_frame_length = 1024; /* Build the decoder specific info header */ - if( !p_dec->p_sys->sout_format.i_extra_data ) + if( !p_dec->fmt_out.i_extra ) { - p_sys->sout_format.i_extra_data = 2; - p_sys->sout_format.p_extra_data = malloc( 2 ); - p_sys->sout_format.p_extra_data[0] = + p_dec->fmt_out.i_extra = 2; + p_dec->fmt_out.p_extra = malloc( 2 ); + ((uint8_t *)p_dec->fmt_out.p_extra)[0] = (i_profile + 1) << 3 | (i_sample_rate_idx >> 1); - p_sys->sout_format.p_extra_data[1] = + ((uint8_t *)p_dec->fmt_out.p_extra)[1] = ((i_sample_rate_idx & 0x01) << 7) | (*pi_channels <<3); } diff --git a/modules/stream_out/transcode.c b/modules/stream_out/transcode.c index a693e40347..745433a0e9 100644 --- a/modules/stream_out/transcode.c +++ b/modules/stream_out/transcode.c @@ -2,7 +2,7 @@ * transcode.c ***************************************************************************** * Copyright (C) 2001, 2002 VideoLAN - * $Id: transcode.c,v 1.49 2003/11/05 18:59:01 gbazin Exp $ + * $Id: transcode.c,v 1.50 2003/11/16 21:07:31 gbazin Exp $ * * Authors: Laurent Aimar * Gildas Bazin @@ -598,6 +598,39 @@ static inline int get_ff_chroma( vlc_fourcc_t i_chroma ) } } +static inline vlc_fourcc_t get_vlc_chroma( int i_pix_fmt ) +{ + switch( i_pix_fmt ) + { + case PIX_FMT_YUV420P: + return VLC_FOURCC('I','4','2','0'); + case PIX_FMT_YUV422P: + return VLC_FOURCC('I','4','2','2'); + case PIX_FMT_YUV444P: + return VLC_FOURCC('I','4','4','4'); + + case PIX_FMT_YUV422: + return VLC_FOURCC('Y','U','Y','2'); + + case PIX_FMT_RGB555: + return VLC_FOURCC('R','V','1','5'); + case PIX_FMT_RGB565: + return VLC_FOURCC('R','V','1','6'); + case PIX_FMT_RGB24: + return VLC_FOURCC('R','V','2','4'); + case PIX_FMT_RGBA32: + return VLC_FOURCC('R','V','3','2'); + case PIX_FMT_GRAY8: + return VLC_FOURCC('G','R','E','Y'); + + case PIX_FMT_YUV410P: + case PIX_FMT_YUV411P: + case PIX_FMT_BGR24: + default: + return 0; + } +} + static int transcode_audio_ffmpeg_new( sout_stream_t *p_stream, sout_stream_id_t *id ) { @@ -657,18 +690,22 @@ static int transcode_audio_ffmpeg_new( sout_stream_t *p_stream, /* find encoder */ id->p_encoder = vlc_object_create( p_stream, VLC_OBJECT_ENCODER ); - id->p_encoder->i_fourcc = id->f_dst.i_fourcc; - id->p_encoder->format.audio.i_format = AOUT_FMT_S16_NE; - id->p_encoder->format.audio.i_rate = id->f_dst.i_sample_rate; - id->p_encoder->format.audio.i_physical_channels = - id->p_encoder->format.audio.i_original_channels = + + /* Initialization of encoder format structures */ + es_format_Init( &id->p_encoder->fmt_in, AUDIO_ES, AOUT_FMT_S16_NE ); + id->p_encoder->fmt_in.audio.i_format = AOUT_FMT_S16_NE; + id->p_encoder->fmt_in.audio.i_rate = id->f_dst.i_sample_rate; + id->p_encoder->fmt_in.audio.i_physical_channels = + id->p_encoder->fmt_in.audio.i_original_channels = pi_channels_maps[id->f_dst.i_channels]; - id->p_encoder->i_bitrate = id->f_dst.i_bitrate; - id->p_encoder->i_extra_data = 0; - id->p_encoder->p_extra_data = NULL; + id->p_encoder->fmt_in.audio.i_channels = id->f_dst.i_channels; + + id->p_encoder->fmt_out = id->p_encoder->fmt_in; + id->p_encoder->fmt_out.i_codec = id->f_dst.i_fourcc; + id->p_encoder->fmt_out.i_bitrate = id->f_dst.i_bitrate; id->p_encoder->p_module = - module_Need( id->p_encoder, "audio encoder", NULL ); + module_Need( id->p_encoder, "encoder", NULL ); if( !id->p_encoder->p_module ) { vlc_object_destroy( id->p_encoder ); @@ -678,8 +715,8 @@ static int transcode_audio_ffmpeg_new( sout_stream_t *p_stream, id->b_enc_inited = VLC_FALSE; - id->f_dst.i_extra_data = id->p_encoder->i_extra_data; - id->f_dst.p_extra_data = id->p_encoder->p_extra_data; + id->f_dst.i_extra_data = id->p_encoder->fmt_out.i_extra; + id->f_dst.p_extra_data = id->p_encoder->fmt_out.p_extra; /* Hack for mp3 transcoding support */ if( id->f_dst.i_fourcc == VLC_FOURCC( 'm','p','3',' ' ) ) @@ -953,64 +990,65 @@ static int transcode_video_ffmpeg_new( sout_stream_t *p_stream, /* Open encoder */ id->p_encoder = vlc_object_create( p_stream, VLC_OBJECT_ENCODER ); - id->p_encoder->i_fourcc = id->f_dst.i_fourcc; - id->p_encoder->format.video.i_width = p_sys->i_width; - id->p_encoder->format.video.i_height = p_sys->i_height; - id->p_encoder->i_bitrate = p_sys->i_vbitrate; - id->p_encoder->i_vtolerance = p_sys->i_vtolerance; - id->p_encoder->i_key_int = p_sys->i_key_int; - id->p_encoder->i_b_frames = p_sys->i_b_frames; - id->p_encoder->i_qmin = p_sys->i_qmin; - id->p_encoder->i_qmax = p_sys->i_qmax; - id->p_encoder->i_hq = p_sys->i_hq; + /* Initialization of encoder format structures */ + es_format_Init( &id->p_encoder->fmt_in, + id->f_src.i_cat, get_vlc_chroma(id->ff_dec_c->pix_fmt) ); + + id->p_encoder->fmt_in.video.i_width = id->f_dst.i_width; + id->p_encoder->fmt_in.video.i_height = id->f_dst.i_height; - if( id->p_encoder->format.video.i_width <= 0 ) + if( id->p_encoder->fmt_in.video.i_width <= 0 ) { - id->p_encoder->format.video.i_width = id->f_dst.i_width = + id->p_encoder->fmt_in.video.i_width = id->f_dst.i_width = id->ff_dec_c->width - p_sys->i_crop_left - p_sys->i_crop_right; } - if( id->p_encoder->format.video.i_height <= 0 ) + if( id->p_encoder->fmt_in.video.i_height <= 0 ) { - id->p_encoder->format.video.i_height = id->f_dst.i_height = + id->p_encoder->fmt_in.video.i_height = id->f_dst.i_height = id->ff_dec_c->height - p_sys->i_crop_top - p_sys->i_crop_bottom; } - id->p_ff_pic = avcodec_alloc_frame(); - id->p_ff_pic_tmp0 = NULL; - id->p_ff_pic_tmp1 = NULL; - id->p_ff_pic_tmp2 = NULL; - id->p_vresample = NULL; - + id->p_encoder->fmt_in.video.i_frame_rate = 25; /* FIXME as it break mpeg */ + id->p_encoder->fmt_in.video.i_frame_rate_base= 1; if( id->ff_dec ) { - id->p_encoder->i_frame_rate = id->ff_dec_c->frame_rate; + id->p_encoder->fmt_in.video.i_frame_rate = id->ff_dec_c->frame_rate; #if LIBAVCODEC_BUILD >= 4662 - id->p_encoder->i_frame_rate_base= id->ff_dec_c->frame_rate_base; + id->p_encoder->fmt_in.video.i_frame_rate_base = + id->ff_dec_c->frame_rate_base; #endif #if LIBAVCODEC_BUILD >= 4687 - id->p_encoder->i_aspect = VOUT_ASPECT_FACTOR * + id->p_encoder->fmt_in.video.i_aspect = VOUT_ASPECT_FACTOR * ( av_q2d(id->ff_dec_c->sample_aspect_ratio) * id->ff_dec_c->width / id->ff_dec_c->height ); #else - id->p_encoder->i_aspect = VOUT_ASPECT_FACTOR * + id->p_encoder->video.fmt_in.i_aspect = VOUT_ASPECT_FACTOR * id->ff_dec_c->aspect_ratio; #endif } - else - { -#if LIBAVCODEC_BUILD >= 4662 - id->p_encoder->i_frame_rate = 25 ; /* FIXME as it break mpeg */ - id->p_encoder->i_frame_rate_base= 1; -#else - id->p_encoder->i_frame_rate = 25 * FRAME_RATE_BASE; -#endif - } + + id->p_encoder->fmt_out = id->p_encoder->fmt_in; + id->p_encoder->fmt_out.i_codec = id->f_dst.i_fourcc; + id->p_encoder->fmt_out.i_bitrate = id->f_dst.i_bitrate; + + id->p_encoder->i_vtolerance = p_sys->i_vtolerance; + id->p_encoder->i_key_int = p_sys->i_key_int; + id->p_encoder->i_b_frames = p_sys->i_b_frames; + id->p_encoder->i_qmin = p_sys->i_qmin; + id->p_encoder->i_qmax = p_sys->i_qmax; + id->p_encoder->i_hq = p_sys->i_hq; + + id->p_ff_pic = avcodec_alloc_frame(); + id->p_ff_pic_tmp0 = NULL; + id->p_ff_pic_tmp1 = NULL; + id->p_ff_pic_tmp2 = NULL; + id->p_vresample = NULL; id->p_encoder->p_module = - module_Need( id->p_encoder, "video encoder", NULL ); + module_Need( id->p_encoder, "encoder", NULL ); if( !id->p_encoder->p_module ) { @@ -1138,26 +1176,26 @@ static int transcode_video_ffmpeg_process( sout_stream_t *p_stream, { /* XXX hack because of copy packetizer and mpeg4video that can fail * detecting size */ - if( id->p_encoder->format.video.i_width <= 0 ) + if( id->p_encoder->fmt_in.video.i_width <= 0 ) { - id->p_encoder->format.video.i_width = id->f_dst.i_width = + id->p_encoder->fmt_in.video.i_width = + id->p_encoder->fmt_out.video.i_width = id->f_dst.i_width = id->ff_dec_c->width - p_sys->i_crop_left - - p_sys->i_crop_right; + p_sys->i_crop_right; } - if( id->p_encoder->format.video.i_height <= 0 ) + if( id->p_encoder->fmt_in.video.i_height <= 0 ) { - id->p_encoder->format.video.i_height = id->f_dst.i_height = + id->p_encoder->fmt_in.video.i_height = + id->p_encoder->fmt_out.video.i_height = id->f_dst.i_height = id->ff_dec_c->height - p_sys->i_crop_top - - p_sys->i_crop_bottom; + p_sys->i_crop_bottom; } - id->p_encoder->i_bitrate = p_sys->i_vbitrate; - - id->p_encoder->i_extra_data = 0; - id->p_encoder->p_extra_data = NULL; + id->p_encoder->fmt_out.i_extra = 0; + id->p_encoder->fmt_out.p_extra = NULL; id->p_encoder->p_module = - module_Need( id->p_encoder, "video encoder", NULL ); + module_Need( id->p_encoder, "encoder", NULL ); if( !id->p_encoder->p_module ) { vlc_object_destroy( id->p_encoder ); @@ -1165,8 +1203,8 @@ static int transcode_video_ffmpeg_process( sout_stream_t *p_stream, return VLC_EGENERIC; } - id->f_dst.i_extra_data = id->p_encoder->i_extra_data; - id->f_dst.p_extra_data = id->p_encoder->p_extra_data; + id->f_dst.i_extra_data = id->p_encoder->fmt_out.i_extra; + id->f_dst.p_extra_data = id->p_encoder->fmt_out.p_extra; /* Hack for mp2v/mp1v transcoding support */ if( id->f_dst.i_fourcc == VLC_FOURCC( 'm','p','1','v' ) || @@ -1198,7 +1236,7 @@ static int transcode_video_ffmpeg_process( sout_stream_t *p_stream, } id->i_inter_pixfmt = - get_ff_chroma( id->p_encoder->format.video.i_chroma ); + get_ff_chroma( id->p_encoder->fmt_in.i_codec ); id->b_enc_inited = VLC_TRUE; } @@ -1293,7 +1331,7 @@ static int transcode_video_ffmpeg_process( sout_stream_t *p_stream, /* Encoding */ vout_InitPicture( VLC_OBJECT(p_stream), &pic, - id->p_encoder->format.video.i_chroma, + id->p_encoder->fmt_in.i_codec, id->f_dst.i_width, id->f_dst.i_height, id->f_dst.i_width * VOUT_ASPECT_FACTOR / id->f_dst.i_height ); diff --git a/src/audio_output/common.c b/src/audio_output/common.c index c86b8158d7..edae9e99d9 100644 --- a/src/audio_output/common.c +++ b/src/audio_output/common.c @@ -2,7 +2,7 @@ * common.c : audio output management of common data structures ***************************************************************************** * Copyright (C) 2002 VideoLAN - * $Id: common.c,v 1.17 2003/02/11 11:16:04 massiot Exp $ + * $Id: common.c,v 1.18 2003/11/16 21:07:31 gbazin Exp $ * * Authors: Christophe Massiot * @@ -66,8 +66,6 @@ aout_instance_t * __aout_New( vlc_object_t * p_parent ) val.b_bool = VLC_TRUE; var_Set( p_aout, "intf-change", val ); - vlc_object_attach( p_aout, p_parent->p_vlc ); - return p_aout; } diff --git a/src/audio_output/dec.c b/src/audio_output/dec.c index 0480c6b69a..377d2b9fd3 100644 --- a/src/audio_output/dec.c +++ b/src/audio_output/dec.c @@ -2,7 +2,7 @@ * dec.c : audio output API towards decoders ***************************************************************************** * Copyright (C) 2002 VideoLAN - * $Id: dec.c,v 1.12 2003/10/27 21:54:10 gbazin Exp $ + * $Id: dec.c,v 1.13 2003/11/16 21:07:31 gbazin Exp $ * * Authors: Christophe Massiot * @@ -164,6 +164,7 @@ aout_input_t * __aout_DecNew( vlc_object_t * p_this, { return NULL; } + vlc_object_attach( *pp_aout, p_this->p_vlc ); } else { diff --git a/src/input/input.c b/src/input/input.c index 2690647b16..7fa827c8a6 100644 --- a/src/input/input.c +++ b/src/input/input.c @@ -4,7 +4,7 @@ * decoders. ***************************************************************************** * Copyright (C) 1998-2002 VideoLAN - * $Id: input.c,v 1.254 2003/11/13 13:31:12 fenrir Exp $ + * $Id: input.c,v 1.255 2003/11/16 21:07:31 gbazin Exp $ * * Authors: Christophe Massiot * @@ -981,6 +981,7 @@ struct es_out_sys_t vlc_bool_t i_audio; vlc_bool_t i_video; }; + struct es_out_id_t { es_descriptor_t *p_es; @@ -1008,6 +1009,7 @@ static es_out_t *EsOutCreate( input_thread_t *p_input ) out->p_sys->i_video = -1; return out; } + static void EsOutRelease( es_out_t *out ) { es_out_sys_t *p_sys = out->p_sys; @@ -1065,11 +1067,12 @@ static es_out_id_t *EsOutAdd( es_out_t *out, es_format_t *fmt ) { case AUDIO_ES: { - WAVEFORMATEX *p_wf = malloc( sizeof( WAVEFORMATEX ) + fmt->i_extra); + WAVEFORMATEX *p_wf = + malloc( sizeof( WAVEFORMATEX ) + fmt->i_extra); p_wf->wFormatTag = WAVE_FORMAT_UNKNOWN; p_wf->nChannels = fmt->audio.i_channels; - p_wf->nSamplesPerSec = fmt->audio.i_samplerate; + p_wf->nSamplesPerSec = fmt->audio.i_rate; p_wf->nAvgBytesPerSec = fmt->audio.i_bitrate / 8; p_wf->nBlockAlign = fmt->audio.i_blockalign; p_wf->wBitsPerSample = fmt->audio.i_bitspersample; @@ -1078,7 +1081,7 @@ static es_out_id_t *EsOutAdd( es_out_t *out, es_format_t *fmt ) { if( fmt->i_extra_type != ES_EXTRA_TYPE_WAVEFORMATEX ) { - msg_Warn( p_input, "extra type != WAVEFORMATEX for audio" ); + msg_Warn( p_input, "extra type != WAVEFORMATEX for audio"); } memcpy( &p_wf[1], fmt->p_extra, fmt->i_extra ); } @@ -1095,7 +1098,8 @@ static es_out_id_t *EsOutAdd( es_out_t *out, es_format_t *fmt ) p_bih->biPlanes = 1; p_bih->biBitCount = 24; p_bih->biCompression = fmt->i_codec; - p_bih->biSizeImage = fmt->video.i_width * fmt->video.i_height; + p_bih->biSizeImage = fmt->video.i_width * + fmt->video.i_height; p_bih->biXPelsPerMeter = 0; p_bih->biYPelsPerMeter = 0; p_bih->biClrUsed = 0; @@ -1166,39 +1170,50 @@ static es_out_id_t *EsOutAdd( es_out_t *out, es_format_t *fmt ) { case AUDIO_ES: input_AddInfo( p_cat, _("Type"), _("Audio") ); - input_AddInfo( p_cat, _("Codec"), "%.4s", (char*)&fmt->i_codec ); + input_AddInfo( p_cat, _("Codec"), "%.4s", + (char*)&fmt->i_codec ); if( fmt->audio.i_channels > 0 ) { - input_AddInfo( p_cat, _("Channels"), "%d", fmt->audio.i_channels ); + input_AddInfo( p_cat, _("Channels"), "%d", + fmt->audio.i_channels ); } - if( fmt->audio.i_samplerate > 0 ) + if( fmt->audio.i_rate > 0 ) { - input_AddInfo( p_cat, _("Sample Rate"), "%d", fmt->audio.i_samplerate ); + input_AddInfo( p_cat, _("Sample Rate"), "%d", + fmt->audio.i_rate ); } if( fmt->audio.i_bitrate > 0 ) { - input_AddInfo( p_cat, _("Bitrate"), "%d", fmt->audio.i_bitrate ); + input_AddInfo( p_cat, _("Bitrate"), "%d", + fmt->audio.i_bitrate ); } if( fmt->audio.i_bitspersample ) { - input_AddInfo( p_cat, _("Bits Per Sample"), "%d", fmt->audio.i_bitspersample ); + input_AddInfo( p_cat, _("Bits Per Sample"), "%d", + fmt->audio.i_bitspersample ); } break; case VIDEO_ES: input_AddInfo( p_cat, _("Type"), _("Video") ); - input_AddInfo( p_cat, _("Codec"), "%.4s", (char*)&fmt->i_codec ); + input_AddInfo( p_cat, _("Codec"), "%.4s", + (char*)&fmt->i_codec ); if( fmt->video.i_width > 0 && fmt->video.i_height > 0 ) { - input_AddInfo( p_cat, _("Resolution"), "%dx%d", fmt->video.i_width, fmt->video.i_height ); + input_AddInfo( p_cat, _("Resolution"), "%dx%d", + fmt->video.i_width, fmt->video.i_height ); } - if( fmt->video.i_display_width > 0 && fmt->video.i_display_height > 0 ) + if( fmt->video.i_visible_width > 0 && + fmt->video.i_visible_height > 0 ) { - input_AddInfo( p_cat, _("Display Resolution"), "%dx%d", fmt->video.i_display_width, fmt->video.i_display_height); + input_AddInfo( p_cat, _("Display Resolution"), "%dx%d", + fmt->video.i_visible_width, + fmt->video.i_visible_height); } break; case SPU_ES: input_AddInfo( p_cat, _("Type"), _("Subtitle") ); - input_AddInfo( p_cat, _("Codec"), "%.4s", (char*)&fmt->i_codec ); + input_AddInfo( p_cat, _("Codec"), "%.4s", + (char*)&fmt->i_codec ); break; default: @@ -1207,9 +1222,12 @@ static es_out_id_t *EsOutAdd( es_out_t *out, es_format_t *fmt ) } vlc_mutex_unlock( &p_input->stream.stream_lock ); + id->p_es->fmt = *fmt; + TAB_APPEND( out->p_sys->i_id, out->p_sys->id, id ); return id; } + static int EsOutSend( es_out_t *out, es_out_id_t *id, pes_packet_t *p_pes ) { if( id->p_es->p_decoder_fifo ) @@ -1222,6 +1240,7 @@ static int EsOutSend( es_out_t *out, es_out_id_t *id, pes_packet_t *p_pes ) } return VLC_SUCCESS; } + static void EsOutDel( es_out_t *out, es_out_id_t *id ) { es_out_sys_t *p_sys = out->p_sys; @@ -1248,6 +1267,7 @@ static void EsOutDel( es_out_t *out, es_out_id_t *id ) free( id ); } + static int EsOutControl( es_out_t *out, int i_query, va_list args ) { es_out_sys_t *p_sys = out->p_sys; @@ -1306,8 +1326,8 @@ static int PositionCallback( vlc_object_t *p_this, char const *psz_cmd, vlc_mutex_lock( &p_input->stream.stream_lock ); p_input->stream.p_selected_area->i_seek = - (int64_t)( newval.f_float * - (double)p_input->stream.p_selected_area->i_size ); + (int64_t)( newval.f_float * + (double)p_input->stream.p_selected_area->i_size ); if( p_input->stream.p_selected_area->i_seek < 0 ) { diff --git a/src/input/input_dec.c b/src/input/input_dec.c index 83000f429d..1cc012c2e6 100644 --- a/src/input/input_dec.c +++ b/src/input/input_dec.c @@ -2,9 +2,10 @@ * input_dec.c: Functions for the management of decoders ***************************************************************************** * Copyright (C) 1999-2001 VideoLAN - * $Id: input_dec.c,v 1.66 2003/11/06 16:36:41 nitrox Exp $ + * $Id: input_dec.c,v 1.67 2003/11/16 21:07:31 gbazin Exp $ * * Authors: Christophe Massiot + * Gildas Bazin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,14 +30,28 @@ #include #include +#include + +#include "stream_output.h" #include "input_ext-intf.h" #include "input_ext-plugins.h" +#include "codecs.h" + static decoder_t * CreateDecoder( input_thread_t *, es_descriptor_t *, int ); static int DecoderThread( decoder_t * ); static void DeleteDecoder( decoder_t * ); +/* Buffers allocation callbacks for the decoders */ +static aout_buffer_t *aout_new_buffer( decoder_t *, int ); +static void aout_del_buffer( decoder_t *, aout_buffer_t * ); + +static picture_t *vout_new_buffer( decoder_t * ); +static void vout_del_buffer( decoder_t *, picture_t * ); + +static es_format_t null_es_format = {0}; + /***************************************************************************** * input_RunDecoder: spawns a new decoder thread *****************************************************************************/ @@ -280,13 +295,27 @@ void input_EscapeAudioDiscontinuity( input_thread_t * p_input ) } } +struct decoder_owner_sys_t +{ + aout_instance_t *p_aout; + aout_input_t *p_aout_input; + + vout_thread_t *p_vout; + + sout_packetizer_input_t *p_sout; + + /* Current format in use by the output */ + video_format_t video; + audio_format_t audio; +}; + /***************************************************************************** - * CreateDecoderFifo: create a decoder_fifo_t + * CreateDecoder: create a decoder object *****************************************************************************/ static decoder_t * CreateDecoder( input_thread_t * p_input, es_descriptor_t * p_es, int i_object_type ) { - decoder_t * p_dec; + decoder_t *p_dec; p_dec = vlc_object_create( p_input, i_object_type ); if( p_dec == NULL ) @@ -295,9 +324,11 @@ static decoder_t * CreateDecoder( input_thread_t * p_input, return NULL; } - p_dec->pf_init = 0; p_dec->pf_decode = 0; - p_dec->pf_end = 0; + p_dec->pf_decode_audio = 0; + p_dec->pf_decode_video = 0; + p_dec->pf_decode_sub = 0; + p_dec->pf_packetize = 0; p_dec->pf_run = 0; /* Select a new ES */ @@ -307,7 +338,6 @@ static decoder_t * CreateDecoder( input_thread_t * p_input, p_es ); /* Allocate the memory needed to store the decoder's fifo */ - //p_dec->p_fifo = (decoder_fifo_t *)malloc(sizeof(decoder_fifo_t)); p_dec->p_fifo = vlc_object_create( p_input, VLC_OBJECT_DECODER_FIFO ); if( p_dec->p_fifo == NULL ) { @@ -316,14 +346,69 @@ static decoder_t * CreateDecoder( input_thread_t * p_input, } /* Initialize the decoder fifo */ - //memset( p_dec->p_fifo, 0, sizeof(decoder_fifo_t) ); p_dec->p_module = NULL; - /* Initialize the p_fifo structure */ + p_dec->fmt_in = p_es->fmt; + + if( p_es->p_waveformatex ) + { +#define p_wf ((WAVEFORMATEX *)p_es->p_waveformatex) + p_dec->fmt_in.audio.i_channels = p_wf->nChannels; + p_dec->fmt_in.audio.i_rate = p_wf->nSamplesPerSec; + p_dec->fmt_in.i_bitrate = p_wf->nAvgBytesPerSec * 8; + p_dec->fmt_in.audio.i_blockalign = p_wf->nBlockAlign; + p_dec->fmt_in.audio.i_bitspersample = p_wf->wBitsPerSample; + p_dec->fmt_in.i_extra = p_wf->cbSize; + p_dec->fmt_in.p_extra = NULL; + if( p_wf->cbSize ) + { + p_dec->fmt_in.p_extra = malloc( p_wf->cbSize ); + memcpy( p_dec->fmt_in.p_extra, &p_wf[1], p_wf->cbSize ); + } + } + + if( p_es->p_bitmapinfoheader ) + { +#define p_bih ((BITMAPINFOHEADER *) p_es->p_bitmapinfoheader) + p_dec->fmt_in.i_extra = p_bih->biSize - sizeof(BITMAPINFOHEADER); + p_dec->fmt_in.p_extra = NULL; + if( p_dec->fmt_in.i_extra ) + { + p_dec->fmt_in.p_extra = malloc( p_dec->fmt_in.i_extra ); + memcpy( p_dec->fmt_in.p_extra, &p_bih[1], p_dec->fmt_in.i_extra ); + } + + p_dec->fmt_in.video.i_width = p_bih->biWidth; + p_dec->fmt_in.video.i_height = p_bih->biHeight; + } + + p_dec->fmt_in.i_cat = p_es->i_cat; + p_dec->fmt_in.i_codec = p_es->i_fourcc; + + p_dec->fmt_out = null_es_format; + + /* Allocate our private structure for the decoder */ + p_dec->p_owner = (decoder_owner_sys_t*)malloc(sizeof(decoder_owner_sys_t)); + if( p_dec->p_owner == NULL ) + { + msg_Err( p_dec, "out of memory" ); + return NULL; + } + p_dec->p_owner->p_aout = NULL; + p_dec->p_owner->p_aout_input = NULL; + p_dec->p_owner->p_vout = NULL; + p_dec->p_owner->p_sout = NULL; + + /* Set buffers allocation callbacks for the decoders */ + p_dec->pf_aout_buffer_new = aout_new_buffer; + p_dec->pf_aout_buffer_del = aout_del_buffer; + p_dec->pf_vout_buffer_new = vout_new_buffer; + p_dec->pf_vout_buffer_del = vout_del_buffer; + + /* For old decoders only */ vlc_mutex_init( p_input, &p_dec->p_fifo->data_lock ); vlc_cond_init( p_input, &p_dec->p_fifo->data_wait ); p_es->p_decoder_fifo = p_dec->p_fifo; - p_dec->p_fifo->i_id = p_es->i_id; p_dec->p_fifo->i_fourcc = p_es->i_fourcc; p_dec->p_fifo->p_demux_data = p_es->p_demux_data; @@ -332,16 +417,14 @@ static decoder_t * CreateDecoder( input_thread_t * p_input, p_dec->p_fifo->p_spuinfo = p_es->p_spuinfo; p_dec->p_fifo->p_stream_ctrl = &p_input->stream.control; p_dec->p_fifo->p_sout = p_input->stream.p_sout; - p_dec->p_fifo->p_first = NULL; p_dec->p_fifo->pp_last = &p_dec->p_fifo->p_first; p_dec->p_fifo->i_depth = 0; p_dec->p_fifo->b_die = p_dec->p_fifo->b_error = 0; p_dec->p_fifo->p_packets_mgt = p_input->p_method_data; - p_dec->p_fifo->p_dec = p_dec; - vlc_object_attach( p_dec->p_fifo, p_input ); + vlc_object_attach( p_dec, p_input ); return p_dec; @@ -363,10 +446,6 @@ static int DecoderThread( decoder_t * p_dec ) return 0; } - - /* Initialize the decoder */ - p_dec->p_fifo->b_error = p_dec->pf_init( p_dec ); - /* The decoder's main loop */ while( !p_dec->p_fifo->b_die && !p_dec->p_fifo->b_error ) { @@ -398,30 +477,93 @@ static int DecoderThread( decoder_t * p_dec ) p_block->i_pts = p_pes->i_pts; p_block->i_dts = p_pes->i_dts; p_block->b_discontinuity = p_pes->b_discontinuity; - p_dec->p_fifo->b_error = p_dec->pf_decode( p_dec, p_block ); - input_DeletePES( p_dec->p_fifo->p_packets_mgt, p_pes ); - } + if( p_dec->i_object_type == VLC_OBJECT_PACKETIZER ) + { + sout_buffer_t *p_sout_buffer; + block_t *p_sout_block; - /* If b_error is set, the decoder thread enters the error loop */ - if( p_dec->p_fifo->b_error ) - { - /* Wait until a `die' order is sent */ - while( !p_dec->p_fifo->b_die ) + while( (p_sout_block = p_dec->pf_packetize( p_dec, &p_block )) ) + { + if( !p_dec->p_owner->p_sout ) + { + sout_format_t sout_format; + + sout_format.i_cat = p_dec->fmt_out.i_cat; + sout_format.i_fourcc = p_dec->fmt_out.i_codec; + sout_format.i_sample_rate = + p_dec->fmt_out.audio.i_rate; + sout_format.i_channels = + p_dec->fmt_out.audio.i_channels; + sout_format.i_width = + p_dec->fmt_out.video.i_width; + sout_format.i_height = + p_dec->fmt_out.video.i_height; + sout_format.i_block_align = 0; + //sout_format.i_bitrate = p_dec->fmt_out.i_bit_rate; + sout_format.i_extra_data = p_dec->fmt_out.i_extra; + sout_format.p_extra_data = p_dec->fmt_out.p_extra; + + p_dec->p_owner->p_sout = + sout_InputNew( p_dec, &sout_format ); + + if( p_dec->p_owner->p_sout == NULL ) + { + msg_Err( p_dec, "cannot create packetizer output" ); + break; + } + } + + p_sout_buffer = + sout_BufferNew( p_dec->p_owner->p_sout->p_sout, + p_sout_block->i_buffer ); + if( p_sout_buffer == NULL ) + { + msg_Err( p_dec, "cannot get sout buffer" ); + break; + } + + memcpy( p_sout_buffer->p_buffer, p_sout_block->p_buffer, + p_sout_block->i_buffer ); + + p_sout_buffer->i_pts = p_sout_block->i_pts; + p_sout_buffer->i_dts = p_sout_block->i_dts; + p_sout_buffer->i_length = p_sout_block->i_length; + + block_Release( p_sout_block ); + + sout_InputSendBuffer( p_dec->p_owner->p_sout, p_sout_buffer ); + } + } + else if( p_dec->fmt_in.i_cat == AUDIO_ES ) { - /* Trash all received PES packets */ - input_ExtractPES( p_dec->p_fifo, NULL ); + aout_buffer_t *p_aout_buf; + + while( (p_aout_buf = p_dec->pf_decode_audio( p_dec, &p_block )) ) + { + aout_DecPlay( p_dec->p_owner->p_aout, + p_dec->p_owner->p_aout_input, p_aout_buf ); + } } - } + else + { + picture_t *p_pic; - /* End of the decoder */ - p_dec->pf_end( p_dec ); + while( (p_pic = p_dec->pf_decode_video( p_dec, &p_block )) ) + { + vout_DatePicture( p_dec->p_owner->p_vout, p_pic, p_pic->date ); + vout_DisplayPicture( p_dec->p_owner->p_vout, p_pic ); + } + } + + input_DeletePES( p_dec->p_fifo->p_packets_mgt, p_pes ); + } return 0; } /***************************************************************************** - * DeleteDecoderFifo: destroy a decoder_fifo_t + * DeleteDecoder: destroys a decoder object *****************************************************************************/ static void DeleteDecoder( decoder_t * p_dec ) { @@ -443,5 +585,135 @@ static void DeleteDecoder( decoder_t * p_dec ) /* Free fifo */ vlc_object_destroy( p_dec->p_fifo ); - //free( p_dec->p_fifo ); + + /* Cleanup */ + if( p_dec->p_owner->p_aout_input ) + aout_DecDelete( p_dec->p_owner->p_aout, p_dec->p_owner->p_aout_input ); + + if( p_dec->p_owner->p_vout ) + { + int i_pic; + + /* Hack to make sure all the the pictures are freed by the decoder */ + for( i_pic = 0; i_pic < p_dec->p_owner->p_vout->render.i_pictures; + i_pic++ ) + { + if( p_dec->p_owner->p_vout->render.pp_picture[i_pic]->i_status == + RESERVED_PICTURE ) + vout_DestroyPicture( p_dec->p_owner->p_vout, + p_dec->p_owner->p_vout->render.pp_picture[i_pic] ); + if( p_dec->p_owner->p_vout->render.pp_picture[i_pic]->i_refcount + > 0 ) + vout_UnlinkPicture( p_dec->p_owner->p_vout, + p_dec->p_owner->p_vout->render.pp_picture[i_pic] ); + } + + /* We are about to die. Reattach video output to p_vlc. */ + vout_Request( p_dec, p_dec->p_owner->p_vout, 0, 0, 0, 0 ); + } + + if( p_dec->p_owner->p_sout ) + sout_InputDelete( p_dec->p_owner->p_sout ); + + free( p_dec->p_owner ); + +} + +/***************************************************************************** + * Buffers allocation callbacks for the decoders + *****************************************************************************/ +static aout_buffer_t *aout_new_buffer( decoder_t *p_dec, int i_samples ) +{ + decoder_owner_sys_t *p_sys = (decoder_owner_sys_t *)p_dec->p_owner; + aout_buffer_t *p_buffer; + + if( p_sys->p_aout_input != NULL && + ( p_dec->fmt_out.audio.i_rate != p_sys->audio.i_rate || + p_dec->fmt_out.audio.i_original_channels != + p_sys->audio.i_original_channels || + p_dec->fmt_out.audio.i_bytes_per_frame != + p_sys->audio.i_bytes_per_frame ) ) + { + /* Parameters changed, restart the aout */ + aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input ); + p_sys->p_aout_input = NULL; + } + + if( p_sys->p_aout_input == NULL ) + { + p_dec->fmt_out.audio.i_format = p_dec->fmt_out.i_codec; + p_sys->audio = p_dec->fmt_out.audio; + p_sys->p_aout_input = + aout_DecNew( p_dec, &p_sys->p_aout, &p_sys->audio ); + if( p_sys->p_aout_input == NULL ) + { + msg_Err( p_dec, "failed to create audio output" ); + return NULL; + } + p_dec->fmt_out.audio.i_bytes_per_frame = + p_sys->audio.i_bytes_per_frame; + } + + p_buffer = aout_DecNewBuffer( p_sys->p_aout, p_sys->p_aout_input, + i_samples ); + + return p_buffer; +} + +static void aout_del_buffer( decoder_t *p_dec, aout_buffer_t *p_buffer ) +{ + aout_DecDeleteBuffer( p_dec->p_owner->p_aout, + p_dec->p_owner->p_aout_input, p_buffer ); +} + +static picture_t *vout_new_buffer( decoder_t *p_dec ) +{ + decoder_owner_sys_t *p_sys = (decoder_owner_sys_t *)p_dec->p_owner; + picture_t *p_pic; + + if( p_sys->p_vout == NULL || + p_dec->fmt_out.video.i_width != p_sys->video.i_width || + p_dec->fmt_out.video.i_height != p_sys->video.i_height || + p_dec->fmt_out.video.i_chroma != p_sys->video.i_chroma || + p_dec->fmt_out.video.i_aspect != p_sys->video.i_aspect ) + { + if( !p_dec->fmt_out.video.i_width || + !p_dec->fmt_out.video.i_height ) + { + /* Can't create a new vout without display size */ + return NULL; + } + + p_dec->fmt_out.video.i_chroma = p_dec->fmt_out.i_codec; + p_sys->video = p_dec->fmt_out.video; + + p_sys->p_vout = vout_Request( p_dec, p_sys->p_vout, + p_sys->video.i_width, + p_sys->video.i_height, + p_sys->video.i_chroma, + p_sys->video.i_aspect ); + + if( p_sys->p_vout == NULL ) + { + msg_Err( p_dec, "failed to create video output" ); + return NULL; + } + } + + /* Get a new picture */ + while( !(p_pic = vout_CreatePicture( p_sys->p_vout, 0, 0, 0 ) ) ) + { + if( p_dec->b_die || p_dec->b_error ) + { + return NULL; + } + msleep( VOUT_OUTMEM_SLEEP ); + } + + return p_pic; +} + +static void vout_del_buffer( decoder_t *p_dec, picture_t *p_pic ) +{ + vout_DestroyPicture( p_dec->p_owner->p_vout, p_pic ); } diff --git a/src/input/input_programs.c b/src/input/input_programs.c index c6e4a579a6..bb260f4546 100644 --- a/src/input/input_programs.c +++ b/src/input/input_programs.c @@ -2,7 +2,7 @@ * input_programs.c: es_descriptor_t, pgrm_descriptor_t management ***************************************************************************** * Copyright (C) 1999-2002 VideoLAN - * $Id: input_programs.c,v 1.120 2003/11/06 16:36:41 nitrox Exp $ + * $Id: input_programs.c,v 1.121 2003/11/16 21:07:31 gbazin Exp $ * * Authors: Christophe Massiot * @@ -51,6 +51,8 @@ static int NavigationCallback( vlc_object_t *, char const *, static int ESCallback( vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void * ); +static es_format_t null_es_format = {0}; + /***************************************************************************** * input_InitStream: init the stream descriptor of the given input *****************************************************************************/ @@ -618,6 +620,7 @@ es_descriptor_t * input_AddES( input_thread_t * p_input, p_es->c_packets = 0; p_es->c_invalid_packets = 0; p_es->b_force_decoder = VLC_FALSE; + p_es->fmt = null_es_format; if( i_data_len ) { diff --git a/src/libvlc.h b/src/libvlc.h index d450110ad1..ab6d64eed9 100644 --- a/src/libvlc.h +++ b/src/libvlc.h @@ -2,7 +2,7 @@ * libvlc.h: main libvlc header ***************************************************************************** * Copyright (C) 1998-2002 VideoLAN - * $Id: libvlc.h,v 1.106 2003/11/15 00:26:15 hartman Exp $ + * $Id: libvlc.h,v 1.107 2003/11/16 21:07:31 gbazin Exp $ * * Authors: Vincent Seguin * Samuel Hocevar @@ -345,24 +345,16 @@ static char *ppsz_language_text[] = "its codecs (decompression methods). Only advanced users should " \ "alter this option as it can break playback of all your streams." ) -#define CODEC_TEXT N_("Choose preferred codec list") +#define CODEC_TEXT N_("Choose preferred codecs list") #define CODEC_LONGTEXT N_( \ - "This allows you to select the order in which VLC will choose its " \ - "codecs. For instance, 'a52old,a52,any' will try the old a52 codec " \ - "before the new one. Please be aware that VLC does not make any " \ - "difference between audio or video codecs, so you should always specify " \ - "'any' at the end of the list to make sure there is a fallback for the " \ - "types you didn't specify.") - + "This allows you to select a list of codecs that VLC will use in " \ + "priority. For instance, 'dummy,a52' will try the dummy and a52 codecs " \ + "before trying the other ones.") -#define ENCODER_VIDEO_TEXT N_("Choose preferred video encoder list") -#define ENCODER_VIDEO_LONGTEXT N_( \ - "This allows you to select the order in which VLC will choose its " \ - "codecs. " ) -#define ENCODER_AUDIO_TEXT N_("Choose preferred audio encoder list") -#define ENCODER_AUDIO_LONGTEXT N_( \ - "This allows you to select the order in which VLC will choose its " \ - "codecs. " ) +#define ENCODER_TEXT N_("Choose preferred encoders list") +#define ENCODER_LONGTEXT N_( \ + "This allows you to select a list of encoders that VLC will use in " \ + "priority") #define SOUT_CAT_LONGTEXT N_( \ "These options allow you to set default global options for the " \ @@ -705,6 +697,7 @@ vlc_module_begin(); /* Decoder options */ add_category_hint( N_("Decoders"), CODEC_CAT_LONGTEXT , VLC_TRUE ); add_module( "codec", "decoder", NULL, NULL, CODEC_TEXT, CODEC_LONGTEXT, VLC_TRUE ); + add_module( "encoder", "encoder", NULL, NULL, ENCODER_TEXT, ENCODER_LONGTEXT, VLC_TRUE ); /* Stream output options */ -- 2.39.2