Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

audio.c

00001 /*****************************************************************************
00002  * audio.c: audio decoder using ffmpeg library
00003  *****************************************************************************
00004  * Copyright (C) 1999-2003 the VideoLAN team
00005  * $Id: audio.c 12093 2005-08-09 19:15:32Z jpsaman $
00006  *
00007  * Authors: Laurent Aimar <[email protected]>
00008  *          Gildas Bazin <[email protected]>
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00023  *****************************************************************************/
00024 
00025 /*****************************************************************************
00026  * Preamble
00027  *****************************************************************************/
00028 #include <vlc/vlc.h>
00029 #include <vlc/decoder.h>
00030 
00031 /* ffmpeg header */
00032 #ifdef HAVE_FFMPEG_AVCODEC_H
00033 #   include <ffmpeg/avcodec.h>
00034 #else
00035 #   include <avcodec.h>
00036 #endif
00037 
00038 #include "ffmpeg.h"
00039 
00040 static unsigned int pi_channels_maps[7] =
00041 {
00042     0,
00043     AOUT_CHAN_CENTER,   AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
00044     AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
00045     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
00046      | AOUT_CHAN_REARRIGHT,
00047     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
00048      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
00049     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
00050      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE
00051 };
00052 
00053 /*****************************************************************************
00054  * decoder_sys_t : decoder descriptor
00055  *****************************************************************************/
00056 struct decoder_sys_t
00057 {
00058     /* Common part between video and audio decoder */
00059     int i_cat;
00060     int i_codec_id;
00061     char *psz_namecodec;
00062     AVCodecContext      *p_context;
00063     AVCodec             *p_codec;
00064 
00065     /* Temporary buffer for libavcodec */
00066     uint8_t *p_output;
00067 
00068     /*
00069      * Output properties
00070      */
00071     audio_sample_format_t aout_format;
00072     audio_date_t          end_date;
00073 
00074     /*
00075      *
00076      */
00077     uint8_t *p_samples;
00078     int     i_samples;
00079 };
00080 
00081 /*****************************************************************************
00082  * InitAudioDec: initialize audio decoder
00083  *****************************************************************************
00084  * The ffmpeg codec will be opened, some memory allocated.
00085  *****************************************************************************/
00086 int E_(InitAudioDec)( decoder_t *p_dec, AVCodecContext *p_context,
00087                       AVCodec *p_codec, int i_codec_id, char *psz_namecodec )
00088 {
00089     decoder_sys_t *p_sys;
00090     vlc_value_t lockval;
00091 
00092     var_Get( p_dec->p_libvlc, "avcodec", &lockval );
00093 
00094     /* Allocate the memory needed to store the decoder's structure */
00095     if( ( p_dec->p_sys = p_sys =
00096           (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
00097     {
00098         msg_Err( p_dec, "out of memory" );
00099         return VLC_EGENERIC;
00100     }
00101 
00102     p_sys->p_context = p_context;
00103     p_sys->p_codec = p_codec;
00104     p_sys->i_codec_id = i_codec_id;
00105     p_sys->psz_namecodec = psz_namecodec;
00106 
00107     /* ***** Fill p_context with init values ***** */
00108     p_sys->p_context->sample_rate = p_dec->fmt_in.audio.i_rate;
00109     p_sys->p_context->channels = p_dec->fmt_in.audio.i_channels;
00110     p_sys->p_context->block_align = p_dec->fmt_in.audio.i_blockalign;
00111     p_sys->p_context->bit_rate = p_dec->fmt_in.i_bitrate;
00112     p_sys->p_context->bits_per_sample = p_dec->fmt_in.audio.i_bitspersample;
00113 
00114     if( ( p_sys->p_context->extradata_size = p_dec->fmt_in.i_extra ) > 0 )
00115     {
00116         int i_offset = 0;
00117 
00118         if( p_dec->fmt_in.i_codec == VLC_FOURCC( 'f', 'l', 'a', 'c' ) )
00119             i_offset = 8;
00120 
00121         p_sys->p_context->extradata_size -= i_offset;
00122         p_sys->p_context->extradata =
00123             malloc( p_sys->p_context->extradata_size +
00124                     FF_INPUT_BUFFER_PADDING_SIZE );
00125         memcpy( p_sys->p_context->extradata,
00126                 (char*)p_dec->fmt_in.p_extra + i_offset,
00127                 p_sys->p_context->extradata_size );
00128         memset( (char*)p_sys->p_context->extradata +
00129                 p_sys->p_context->extradata_size, 0,
00130                 FF_INPUT_BUFFER_PADDING_SIZE );
00131     }
00132 
00133     /* ***** Open the codec ***** */
00134     vlc_mutex_lock( lockval.p_address );
00135     if (avcodec_open( p_sys->p_context, p_sys->p_codec ) < 0)
00136     {
00137         vlc_mutex_unlock( lockval.p_address );
00138         msg_Err( p_dec, "cannot open codec (%s)", p_sys->psz_namecodec );
00139         free( p_sys );
00140         return VLC_EGENERIC;
00141     }
00142     vlc_mutex_unlock( lockval.p_address );
00143 
00144     msg_Dbg( p_dec, "ffmpeg codec (%s) started", p_sys->psz_namecodec );
00145 
00146     p_sys->p_output = malloc( 3 * AVCODEC_MAX_AUDIO_FRAME_SIZE );
00147     p_sys->p_samples = NULL;
00148     p_sys->i_samples = 0;
00149 
00150     if( p_dec->fmt_in.audio.i_rate )
00151     {
00152         aout_DateInit( &p_sys->end_date, p_dec->fmt_in.audio.i_rate );
00153         aout_DateSet( &p_sys->end_date, 0 );
00154     }
00155 
00156     /* Set output properties */
00157     p_dec->fmt_out.i_cat = AUDIO_ES;
00158     p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE;
00159     p_dec->fmt_out.audio.i_bitspersample = 16;
00160 
00161     return VLC_SUCCESS;
00162 }
00163 
00164 /*****************************************************************************
00165  * SplitBuffer: Needed because aout really doesn't like big audio chunk and
00166  * wma produces easily > 30000 samples...
00167  *****************************************************************************/
00168 aout_buffer_t *SplitBuffer( decoder_t *p_dec )
00169 {
00170     decoder_sys_t *p_sys = p_dec->p_sys;
00171     int i_samples = __MIN( p_sys->i_samples, 4096 );
00172     aout_buffer_t *p_buffer;
00173 
00174     if( i_samples == 0 ) return NULL;
00175 
00176     if( ( p_buffer = p_dec->pf_aout_buffer_new( p_dec, i_samples ) ) == NULL )
00177     {
00178         msg_Err( p_dec, "cannot get aout buffer" );
00179         return NULL;
00180     }
00181 
00182     p_buffer->start_date = aout_DateGet( &p_sys->end_date );
00183     p_buffer->end_date = aout_DateIncrement( &p_sys->end_date, i_samples );
00184 
00185     memcpy( p_buffer->p_buffer, p_sys->p_samples, p_buffer->i_nb_bytes );
00186 
00187     p_sys->p_samples += p_buffer->i_nb_bytes;
00188     p_sys->i_samples -= i_samples;
00189 
00190     return p_buffer;
00191 }
00192 
00193 /*****************************************************************************
00194  * DecodeAudio: Called to decode one frame
00195  *****************************************************************************/
00196 aout_buffer_t *E_( DecodeAudio )( decoder_t *p_dec, block_t **pp_block )
00197 {
00198     decoder_sys_t *p_sys = p_dec->p_sys;
00199     int i_used, i_output;
00200     aout_buffer_t *p_buffer;
00201     block_t *p_block;
00202 
00203     if( !pp_block || !*pp_block ) return NULL;
00204 
00205     p_block = *pp_block;
00206 
00207     if( p_block->i_buffer <= 0 && p_sys->i_samples > 0 )
00208     {
00209         /* More data */
00210         p_buffer = SplitBuffer( p_dec );
00211         if( !p_buffer ) block_Release( p_block );
00212         return p_buffer;
00213     }
00214 
00215     if( !aout_DateGet( &p_sys->end_date ) && !p_block->i_pts )
00216     {
00217         /* We've just started the stream, wait for the first PTS. */
00218         block_Release( p_block );
00219         return NULL;
00220     }
00221 
00222     if( p_block->i_buffer <= 0 || ( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) ) )
00223     {
00224         block_Release( p_block );
00225         return NULL;
00226     }
00227 
00228     i_used = avcodec_decode_audio( p_sys->p_context,
00229                                    (int16_t*)p_sys->p_output, &i_output,
00230                                    p_block->p_buffer, p_block->i_buffer );
00231 
00232     if( i_used < 0 || i_output < 0 )
00233     {
00234         if( i_used < 0 )
00235             msg_Warn( p_dec, "cannot decode one frame (%d bytes)",
00236                       p_block->i_buffer );
00237 
00238         block_Release( p_block );
00239         return NULL;
00240     }
00241     else if( i_used > p_block->i_buffer )
00242     {
00243         i_used = p_block->i_buffer;
00244     }
00245 
00246     p_block->i_buffer -= i_used;
00247     p_block->p_buffer += i_used;
00248 
00249     if( p_sys->p_context->channels <= 0 || p_sys->p_context->channels > 6 )
00250     {
00251         msg_Warn( p_dec, "invalid channels count %d",
00252                   p_sys->p_context->channels );
00253         block_Release( p_block );
00254         return NULL;
00255     }
00256 
00257     if( p_dec->fmt_out.audio.i_rate != (unsigned int)p_sys->p_context->sample_rate )
00258     {
00259         aout_DateInit( &p_sys->end_date, p_sys->p_context->sample_rate );
00260         aout_DateSet( &p_sys->end_date, p_block->i_pts );
00261     }
00262 
00263     /* **** Set audio output parameters **** */
00264     p_dec->fmt_out.audio.i_rate     = p_sys->p_context->sample_rate;
00265     p_dec->fmt_out.audio.i_channels = p_sys->p_context->channels;
00266     p_dec->fmt_out.audio.i_original_channels =
00267         p_dec->fmt_out.audio.i_physical_channels =
00268             pi_channels_maps[p_sys->p_context->channels];
00269 
00270     if( p_block->i_pts != 0 &&
00271         p_block->i_pts != aout_DateGet( &p_sys->end_date ) )
00272     {
00273         aout_DateSet( &p_sys->end_date, p_block->i_pts );
00274     }
00275     p_block->i_pts = 0;
00276 
00277     /* **** Now we can output these samples **** */
00278     p_sys->i_samples = i_output / 2 / p_sys->p_context->channels;
00279     p_sys->p_samples = p_sys->p_output;
00280 
00281     p_buffer = SplitBuffer( p_dec );
00282     if( !p_buffer ) block_Release( p_block );
00283     return p_buffer;
00284 }
00285 
00286 /*****************************************************************************
00287  * EndAudioDec: audio decoder destruction
00288  *****************************************************************************/
00289 void E_(EndAudioDec)( decoder_t *p_dec )
00290 {
00291     decoder_sys_t *p_sys = p_dec->p_sys;
00292 
00293     if( p_sys->p_output ) free( p_sys->p_output );
00294 }

Generated on Tue Dec 20 10:14:29 2005 for vlc-0.8.4a by  doxygen 1.4.2