audio.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:9k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * audio.c: audio decoder using ffmpeg library
  3.  *****************************************************************************
  4.  * Copyright (C) 1999-2003 VideoLAN
  5.  * $Id: audio.c 8994 2004-10-15 08:58:16Z gbazin $
  6.  *
  7.  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  8.  *          Gildas Bazin <gbazin@videolan.org>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  23.  *****************************************************************************/
  24. /*****************************************************************************
  25.  * Preamble
  26.  *****************************************************************************/
  27. #include <vlc/vlc.h>
  28. #include <vlc/decoder.h>
  29. /* ffmpeg header */
  30. #ifdef HAVE_FFMPEG_AVCODEC_H
  31. #   include <ffmpeg/avcodec.h>
  32. #else
  33. #   include <avcodec.h>
  34. #endif
  35. #include "ffmpeg.h"
  36. static unsigned int pi_channels_maps[7] =
  37. {
  38.     0,
  39.     AOUT_CHAN_CENTER,   AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
  40.     AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
  41.     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
  42.      | AOUT_CHAN_REARRIGHT,
  43.     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
  44.      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
  45.     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
  46.      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE
  47. };
  48. /*****************************************************************************
  49.  * decoder_sys_t : decoder descriptor
  50.  *****************************************************************************/
  51. struct decoder_sys_t
  52. {
  53.     /* Common part between video and audio decoder */
  54.     int i_cat;
  55.     int i_codec_id;
  56.     char *psz_namecodec;
  57.     AVCodecContext      *p_context;
  58.     AVCodec             *p_codec;
  59.     /* Temporary buffer for libavcodec */
  60.     uint8_t *p_output;
  61.     /*
  62.      * Output properties
  63.      */
  64.     audio_sample_format_t aout_format;
  65.     audio_date_t          end_date;
  66.     /*
  67.      *
  68.      */
  69.     uint8_t *p_samples;
  70.     int     i_samples;
  71. };
  72. /*****************************************************************************
  73.  * InitAudioDec: initialize audio decoder
  74.  *****************************************************************************
  75.  * The ffmpeg codec will be opened, some memory allocated.
  76.  *****************************************************************************/
  77. int E_(InitAudioDec)( decoder_t *p_dec, AVCodecContext *p_context,
  78.                       AVCodec *p_codec, int i_codec_id, char *psz_namecodec )
  79. {
  80.     decoder_sys_t *p_sys;
  81.     vlc_value_t lockval;
  82.     var_Get( p_dec->p_libvlc, "avcodec", &lockval );
  83.     /* Allocate the memory needed to store the decoder's structure */
  84.     if( ( p_dec->p_sys = p_sys =
  85.           (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
  86.     {
  87.         msg_Err( p_dec, "out of memory" );
  88.         return VLC_EGENERIC;
  89.     }
  90.     p_sys->p_context = p_context;
  91.     p_sys->p_codec = p_codec;
  92.     p_sys->i_codec_id = i_codec_id;
  93.     p_sys->psz_namecodec = psz_namecodec;
  94.     /* ***** Fill p_context with init values ***** */
  95.     p_sys->p_context->sample_rate = p_dec->fmt_in.audio.i_rate;
  96.     p_sys->p_context->channels = p_dec->fmt_in.audio.i_channels;
  97.     p_sys->p_context->block_align = p_dec->fmt_in.audio.i_blockalign;
  98.     p_sys->p_context->bit_rate = p_dec->fmt_in.i_bitrate;
  99.     if( ( p_sys->p_context->extradata_size = p_dec->fmt_in.i_extra ) > 0 )
  100.     {
  101.         p_sys->p_context->extradata =
  102.             malloc( p_dec->fmt_in.i_extra + FF_INPUT_BUFFER_PADDING_SIZE );
  103.         memcpy( p_sys->p_context->extradata,
  104.                 p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra );
  105.         memset( p_sys->p_context->extradata + p_dec->fmt_in.i_extra, 0,
  106.                 FF_INPUT_BUFFER_PADDING_SIZE );
  107.     }
  108.     /* ***** Open the codec ***** */
  109.     vlc_mutex_lock( lockval.p_address );
  110.     if (avcodec_open( p_sys->p_context, p_sys->p_codec ) < 0)
  111.     {
  112.         vlc_mutex_unlock( lockval.p_address );
  113.         msg_Err( p_dec, "cannot open codec (%s)", p_sys->psz_namecodec );
  114.         free( p_sys );
  115.         return VLC_EGENERIC;
  116.     }
  117.     vlc_mutex_unlock( lockval.p_address );
  118.     msg_Dbg( p_dec, "ffmpeg codec (%s) started", p_sys->psz_namecodec );
  119.     p_sys->p_output = malloc( 3 * AVCODEC_MAX_AUDIO_FRAME_SIZE );
  120.     p_sys->p_samples = NULL;
  121.     p_sys->i_samples = 0;
  122.     if( p_dec->fmt_in.audio.i_rate )
  123.     {
  124.         aout_DateInit( &p_sys->end_date, p_dec->fmt_in.audio.i_rate );
  125.         aout_DateSet( &p_sys->end_date, 0 );
  126.     }
  127.     /* Set output properties */
  128.     p_dec->fmt_out.i_cat = AUDIO_ES;
  129.     p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE;
  130.     p_dec->fmt_out.audio.i_bitspersample = 16;
  131.     return VLC_SUCCESS;
  132. }
  133. /*****************************************************************************
  134.  * SplitBuffer: Needed because aout really doesn't like big audio chunk and
  135.  * wma produces easily > 30000 samples...
  136.  *****************************************************************************/
  137. aout_buffer_t *SplitBuffer( decoder_t *p_dec )
  138. {
  139.     decoder_sys_t *p_sys = p_dec->p_sys;
  140.     int i_samples = __MIN( p_sys->i_samples, 4096 );
  141.     aout_buffer_t *p_buffer;
  142.     if( i_samples == 0 ) return NULL;
  143.     if( ( p_buffer = p_dec->pf_aout_buffer_new( p_dec, i_samples ) ) == NULL )
  144.     {
  145.         msg_Err( p_dec, "cannot get aout buffer" );
  146.         return NULL;
  147.     }
  148.     p_buffer->start_date = aout_DateGet( &p_sys->end_date );
  149.     p_buffer->end_date = aout_DateIncrement( &p_sys->end_date, i_samples );
  150.     memcpy( p_buffer->p_buffer, p_sys->p_samples, p_buffer->i_nb_bytes );
  151.     p_sys->p_samples += p_buffer->i_nb_bytes;
  152.     p_sys->i_samples -= i_samples;
  153.     return p_buffer;
  154. }
  155. /*****************************************************************************
  156.  * DecodeAudio: Called to decode one frame
  157.  *****************************************************************************/
  158. aout_buffer_t *E_( DecodeAudio )( decoder_t *p_dec, block_t **pp_block )
  159. {
  160.     decoder_sys_t *p_sys = p_dec->p_sys;
  161.     int i_used, i_output;
  162.     aout_buffer_t *p_buffer;
  163.     block_t *p_block;
  164.     if( !pp_block || !*pp_block ) return NULL;
  165.     p_block = *pp_block;
  166.     if( p_block->i_buffer <= 0 && p_sys->i_samples > 0 )
  167.     {
  168.         /* More data */
  169.         p_buffer = SplitBuffer( p_dec );
  170.         if( !p_buffer ) block_Release( p_block );
  171.         return p_buffer;
  172.     }
  173.     if( !aout_DateGet( &p_sys->end_date ) && !p_block->i_pts )
  174.     {
  175.         /* We've just started the stream, wait for the first PTS. */
  176.         block_Release( p_block );
  177.         return NULL;
  178.     }
  179.     if( p_block->i_buffer <= 0 || p_block->i_flags & BLOCK_FLAG_DISCONTINUITY )
  180.     {
  181.         block_Release( p_block );
  182.         return NULL;
  183.     }
  184.     i_used = avcodec_decode_audio( p_sys->p_context,
  185.                                    (int16_t*)p_sys->p_output, &i_output,
  186.                                    p_block->p_buffer, p_block->i_buffer );
  187.     if( i_used < 0 || i_output < 0 )
  188.     {
  189.         if( i_used < 0 )
  190.             msg_Warn( p_dec, "cannot decode one frame (%d bytes)",
  191.                       p_block->i_buffer );
  192.         block_Release( p_block );
  193.         return NULL;
  194.     }
  195.     else if( i_used > p_block->i_buffer )
  196.     {
  197.         i_used = p_block->i_buffer;
  198.     }
  199.     p_block->i_buffer -= i_used;
  200.     p_block->p_buffer += i_used;
  201.     if( p_sys->p_context->channels <= 0 || p_sys->p_context->channels > 6 )
  202.     {
  203.         msg_Warn( p_dec, "invalid channels count %d",
  204.                   p_sys->p_context->channels );
  205.         block_Release( p_block );
  206.         return NULL;
  207.     }
  208.     if( p_dec->fmt_out.audio.i_rate != p_sys->p_context->sample_rate )
  209.     {
  210.         aout_DateInit( &p_sys->end_date, p_sys->p_context->sample_rate );
  211.         aout_DateSet( &p_sys->end_date, p_block->i_pts );
  212.     }
  213.     /* **** Set audio output parameters **** */
  214.     p_dec->fmt_out.audio.i_rate     = p_sys->p_context->sample_rate;
  215.     p_dec->fmt_out.audio.i_channels = p_sys->p_context->channels;
  216.     p_dec->fmt_out.audio.i_original_channels =
  217.         p_dec->fmt_out.audio.i_physical_channels =
  218.             pi_channels_maps[p_sys->p_context->channels];
  219.     if( p_block->i_pts != 0 &&
  220.         p_block->i_pts != aout_DateGet( &p_sys->end_date ) )
  221.     {
  222.         aout_DateSet( &p_sys->end_date, p_block->i_pts );
  223.     }
  224.     p_block->i_pts = 0;
  225.     /* **** Now we can output these samples **** */
  226.     p_sys->i_samples = i_output / 2 / p_sys->p_context->channels;
  227.     p_sys->p_samples = p_sys->p_output;
  228.     p_buffer = SplitBuffer( p_dec );
  229.     if( !p_buffer ) block_Release( p_block );
  230.     return p_buffer;
  231. }
  232. /*****************************************************************************
  233.  * EndAudioDec: audio decoder destruction
  234.  *****************************************************************************/
  235. void E_(EndAudioDec)( decoder_t *p_dec )
  236. {
  237.     decoder_sys_t *p_sys = p_dec->p_sys;
  238.     if( p_sys->p_output ) free( p_sys->p_output );
  239. }