2006-09-10 17:02:42 +03:00
/*
* copyright ( c ) 2002 Mark Hills < mark @ pogo . org . uk >
*
2006-10-07 18:30:46 +03:00
* This file is part of FFmpeg .
*
* FFmpeg is free software ; you can redistribute it and / or
2006-09-10 17:02:42 +03:00
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
2006-10-07 18:30:46 +03:00
* version 2.1 of the License , or ( at your option ) any later version .
2006-09-10 17:02:42 +03:00
*
2006-10-07 18:30:46 +03:00
* FFmpeg is distributed in the hope that it will be useful ,
2006-09-10 17:02:42 +03:00
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
2006-10-07 18:30:46 +03:00
* License along with FFmpeg ; if not , write to the Free Software
2007-07-05 13:40:25 +03:00
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA
2006-09-10 17:02:42 +03:00
*/
2003-03-06 13:32:04 +02:00
/**
2010-04-20 17:45:34 +03:00
* @ file
2012-02-29 02:51:04 +03:00
* Vorbis encoding support via libvorbisenc .
2003-03-06 13:32:04 +02:00
* @ author Mark Hills < mark @ pogo . org . uk >
2002-09-01 21:07:56 +03:00
*/
# include <vorbis/vorbisenc.h>
2012-02-29 06:39:07 +03:00
# include "libavutil/fifo.h"
2010-09-29 18:09:38 +03:00
# include "libavutil/opt.h"
2002-09-01 21:07:56 +03:00
# include "avcodec.h"
2012-02-29 09:02:54 +03:00
# include "audio_frame_queue.h"
2007-06-02 04:41:07 +03:00
# include "bytestream.h"
2012-02-07 23:37:45 +03:00
# include "internal.h"
2010-06-27 12:25:05 +03:00
# include "vorbis.h"
2012-02-29 09:02:54 +03:00
# include "vorbis_parser.h"
2002-09-01 21:07:56 +03:00
2004-04-04 20:06:30 +03:00
# undef NDEBUG
# include <assert.h>
2012-02-29 02:51:04 +03:00
/* Number of samples the user should send in each call.
* This value is used because it is the LCD of all possible frame sizes , so
* an output packet will always start at the same point as one of the input
* packets .
*/
2004-04-04 17:39:20 +03:00
# define OGGVORBIS_FRAME_SIZE 64
2002-09-01 21:07:56 +03:00
2011-12-29 23:37:05 +03:00
# define BUFFER_SIZE (1024 * 64)
2002-09-01 21:07:56 +03:00
typedef struct OggVorbisContext {
2012-02-29 02:51:04 +03:00
AVClass * av_class ; /**< class for AVOptions */
2012-05-05 11:45:30 +03:00
AVFrame frame ;
2012-02-29 02:51:04 +03:00
vorbis_info vi ; /**< vorbis_info used during init */
vorbis_dsp_state vd ; /**< DSP state used for analysis */
vorbis_block vb ; /**< vorbis_block used for analysis */
2012-02-29 06:39:07 +03:00
AVFifoBuffer * pkt_fifo ; /**< output packet buffer */
2012-02-29 02:51:04 +03:00
int eof ; /**< end-of-file flag */
2012-02-29 03:51:25 +03:00
int dsp_initialized ; /**< vd has been initialized */
2012-02-29 02:51:04 +03:00
vorbis_comment vc ; /**< VorbisComment info */
ogg_packet op ; /**< ogg packet */
double iblock ; /**< impulse block bias option */
2012-02-29 09:02:54 +03:00
VorbisParseContext vp ; /**< parse context to get durations */
AudioFrameQueue afq ; /**< frame queue for timestamps */
2011-12-29 23:37:05 +03:00
} OggVorbisContext ;
2002-09-01 21:07:56 +03:00
2011-12-29 23:37:05 +03:00
static const AVOption options [ ] = {
{ " iblock " , " Sets the impulse block bias " , offsetof ( OggVorbisContext , iblock ) , AV_OPT_TYPE_DOUBLE , { . dbl = 0 } , - 15 , 0 , AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM } ,
{ NULL }
2010-09-29 18:09:38 +03:00
} ;
2012-02-29 03:33:07 +03:00
static const AVCodecDefault defaults [ ] = {
{ " b " , " 0 " } ,
{ NULL } ,
} ;
2010-10-14 10:47:49 +03:00
static const AVClass class = { " libvorbis " , av_default_item_name , options , LIBAVUTIL_VERSION_INT } ;
2002-09-01 21:07:56 +03:00
2012-02-29 02:51:04 +03:00
2012-02-22 02:40:22 +03:00
static int vorbis_error_to_averror ( int ov_err )
2011-12-31 01:10:41 +03:00
{
2012-02-22 02:40:22 +03:00
switch ( ov_err ) {
case OV_EFAULT : return AVERROR_BUG ;
case OV_EINVAL : return AVERROR ( EINVAL ) ;
case OV_EIMPL : return AVERROR ( EINVAL ) ;
default : return AVERROR_UNKNOWN ;
2011-12-31 01:10:41 +03:00
}
}
2012-02-29 02:51:04 +03:00
static av_cold int oggvorbis_init_encoder ( vorbis_info * vi ,
AVCodecContext * avctx )
2011-12-29 23:37:05 +03:00
{
2012-02-29 02:51:04 +03:00
OggVorbisContext * s = avctx - > priv_data ;
2006-01-21 19:09:23 +02:00
double cfreq ;
2012-02-22 02:40:22 +03:00
int ret ;
2002-12-21 17:54:21 +02:00
2012-02-29 03:33:07 +03:00
if ( avctx - > flags & CODEC_FLAG_QSCALE | | ! avctx - > bit_rate ) {
2012-02-29 02:51:04 +03:00
/* variable bitrate
* NOTE : we use the oggenc range of - 1 to 10 for global_quality for
2012-02-29 03:33:07 +03:00
* user convenience , but libvorbis uses - 0.1 to 1.0 .
2012-02-29 02:51:04 +03:00
*/
float q = avctx - > global_quality / ( float ) FF_QP2LAMBDA ;
2012-02-29 03:33:07 +03:00
/* default to 3 if the user did not set quality or bitrate */
if ( ! ( avctx - > flags & CODEC_FLAG_QSCALE ) )
q = 3.0 ;
2012-02-29 02:51:04 +03:00
if ( ( ret = vorbis_encode_setup_vbr ( vi , avctx - > channels ,
avctx - > sample_rate ,
2012-02-22 02:40:22 +03:00
q / 10.0 ) ) )
goto error ;
2006-01-21 19:09:23 +02:00
} else {
2012-02-29 02:51:04 +03:00
int minrate = avctx - > rc_min_rate > 0 ? avctx - > rc_min_rate : - 1 ;
2012-02-29 02:52:30 +03:00
int maxrate = avctx - > rc_max_rate > 0 ? avctx - > rc_max_rate : - 1 ;
2010-06-05 01:40:31 +03:00
2012-02-29 02:51:04 +03:00
/* average bitrate */
if ( ( ret = vorbis_encode_setup_managed ( vi , avctx - > channels ,
2012-02-29 02:52:30 +03:00
avctx - > sample_rate , maxrate ,
avctx - > bit_rate , minrate ) ) )
2012-02-22 02:40:22 +03:00
goto error ;
2006-01-21 19:09:23 +02:00
2010-06-05 01:40:40 +03:00
/* variable bitrate by estimate, disable slow rate management */
2011-12-29 23:37:05 +03:00
if ( minrate = = - 1 & & maxrate = = - 1 )
2012-02-22 02:40:22 +03:00
if ( ( ret = vorbis_encode_ctl ( vi , OV_ECTL_RATEMANAGE2_SET , NULL ) ) )
2012-02-26 06:47:56 +03:00
goto error ; /* should not happen */
2006-01-21 19:09:23 +02:00
}
2002-12-21 17:54:21 +02:00
2006-01-21 19:09:23 +02:00
/* cutoff frequency */
2012-02-29 02:51:04 +03:00
if ( avctx - > cutoff > 0 ) {
cfreq = avctx - > cutoff / 1000.0 ;
2012-02-22 02:40:22 +03:00
if ( ( ret = vorbis_encode_ctl ( vi , OV_ECTL_LOWPASS_SET , & cfreq ) ) )
2012-02-26 06:47:56 +03:00
goto error ; /* should not happen */
2006-01-21 19:09:23 +02:00
}
2002-09-01 21:07:56 +03:00
2012-02-29 02:51:04 +03:00
/* impulse block bias */
if ( s - > iblock ) {
if ( ( ret = vorbis_encode_ctl ( vi , OV_ECTL_IBLOCK_SET , & s - > iblock ) ) )
2012-02-22 02:40:22 +03:00
goto error ;
2010-09-29 18:09:38 +03:00
}
2012-03-01 03:13:16 +03:00
if ( avctx - > channels = = 3 & &
avctx - > channel_layout ! = ( AV_CH_LAYOUT_STEREO | AV_CH_FRONT_CENTER ) | |
avctx - > channels = = 4 & &
avctx - > channel_layout ! = AV_CH_LAYOUT_2_2 & &
avctx - > channel_layout ! = AV_CH_LAYOUT_QUAD | |
avctx - > channels = = 5 & &
avctx - > channel_layout ! = AV_CH_LAYOUT_5POINT0 & &
avctx - > channel_layout ! = AV_CH_LAYOUT_5POINT0_BACK | |
avctx - > channels = = 6 & &
avctx - > channel_layout ! = AV_CH_LAYOUT_5POINT1 & &
avctx - > channel_layout ! = AV_CH_LAYOUT_5POINT1_BACK | |
avctx - > channels = = 7 & &
avctx - > channel_layout ! = ( AV_CH_LAYOUT_5POINT1 | AV_CH_BACK_CENTER ) | |
avctx - > channels = = 8 & &
avctx - > channel_layout ! = AV_CH_LAYOUT_7POINT1 ) {
if ( avctx - > channel_layout ) {
2011-04-15 12:48:03 +03:00
char name [ 32 ] ;
2012-03-01 03:13:16 +03:00
av_get_channel_layout_string ( name , sizeof ( name ) , avctx - > channels ,
avctx - > channel_layout ) ;
av_log ( avctx , AV_LOG_ERROR , " %s not supported by Vorbis: "
2011-04-15 12:48:03 +03:00
" output stream will have incorrect "
" channel layout. \n " , name ) ;
} else {
2012-03-01 03:13:16 +03:00
av_log ( avctx , AV_LOG_WARNING , " No channel layout specified. The encoder "
2011-04-15 12:48:03 +03:00
" will use Vorbis channel layout for "
2012-03-01 03:13:16 +03:00
" %d channels. \n " , avctx - > channels ) ;
2011-04-15 12:48:03 +03:00
}
}
2012-02-22 02:40:22 +03:00
if ( ( ret = vorbis_encode_setup_init ( vi ) ) )
goto error ;
return 0 ;
error :
return vorbis_error_to_averror ( ret ) ;
2002-09-01 21:07:56 +03:00
}
2010-07-21 00:54:46 +03:00
/* How many bytes are needed for a buffer of length 'l' */
2011-12-29 23:37:05 +03:00
static int xiph_len ( int l )
{
2011-12-30 00:23:16 +03:00
return 1 + l / 255 + l ;
2011-12-29 23:37:05 +03:00
}
2010-07-21 00:54:46 +03:00
2012-02-29 02:51:04 +03:00
static av_cold int oggvorbis_encode_close ( AVCodecContext * avctx )
2012-02-22 02:40:22 +03:00
{
2012-02-29 02:51:04 +03:00
OggVorbisContext * s = avctx - > priv_data ;
2012-02-22 02:40:22 +03:00
2012-02-29 02:51:04 +03:00
/* notify vorbisenc this is EOF */
2012-02-29 03:51:25 +03:00
if ( s - > dsp_initialized )
vorbis_analysis_wrote ( & s - > vd , 0 ) ;
2012-02-22 02:40:22 +03:00
2012-02-29 02:51:04 +03:00
vorbis_block_clear ( & s - > vb ) ;
vorbis_dsp_clear ( & s - > vd ) ;
vorbis_info_clear ( & s - > vi ) ;
2012-02-22 02:40:22 +03:00
2012-02-29 06:39:07 +03:00
av_fifo_free ( s - > pkt_fifo ) ;
2012-02-29 09:02:54 +03:00
ff_af_queue_close ( & s - > afq ) ;
# if FF_API_OLD_ENCODE_AUDIO
2012-02-29 02:51:04 +03:00
av_freep ( & avctx - > coded_frame ) ;
2012-02-29 09:02:54 +03:00
# endif
2012-02-29 02:51:04 +03:00
av_freep ( & avctx - > extradata ) ;
2012-02-22 02:40:22 +03:00
return 0 ;
}
2012-02-29 02:51:04 +03:00
static av_cold int oggvorbis_encode_init ( AVCodecContext * avctx )
2011-12-29 23:37:05 +03:00
{
2012-02-29 02:51:04 +03:00
OggVorbisContext * s = avctx - > priv_data ;
2004-04-04 18:19:20 +03:00
ogg_packet header , header_comm , header_code ;
uint8_t * p ;
2010-07-21 00:54:46 +03:00
unsigned int offset ;
2012-02-22 02:40:22 +03:00
int ret ;
2002-09-01 21:07:56 +03:00
2012-02-29 02:51:04 +03:00
vorbis_info_init ( & s - > vi ) ;
if ( ( ret = oggvorbis_init_encoder ( & s - > vi , avctx ) ) ) {
2012-02-29 08:02:55 +03:00
av_log ( avctx , AV_LOG_ERROR , " encoder setup failed \n " ) ;
2012-02-22 02:40:22 +03:00
goto error ;
}
2012-02-29 02:51:04 +03:00
if ( ( ret = vorbis_analysis_init ( & s - > vd , & s - > vi ) ) ) {
2012-02-29 08:02:55 +03:00
av_log ( avctx , AV_LOG_ERROR , " analysis init failed \n " ) ;
2012-02-22 02:40:22 +03:00
ret = vorbis_error_to_averror ( ret ) ;
goto error ;
}
2012-02-29 03:51:25 +03:00
s - > dsp_initialized = 1 ;
2012-02-29 02:51:04 +03:00
if ( ( ret = vorbis_block_init ( & s - > vd , & s - > vb ) ) ) {
2012-02-29 08:02:55 +03:00
av_log ( avctx , AV_LOG_ERROR , " dsp init failed \n " ) ;
2012-02-22 02:40:22 +03:00
ret = vorbis_error_to_averror ( ret ) ;
goto error ;
2002-09-01 21:07:56 +03:00
}
2012-02-29 02:51:04 +03:00
vorbis_comment_init ( & s - > vc ) ;
2012-05-22 18:18:39 +03:00
if ( ! ( avctx - > flags & CODEC_FLAG_BITEXACT ) )
vorbis_comment_add_tag ( & s - > vc , " encoder " , LIBAVCODEC_IDENT ) ;
2004-04-04 18:19:20 +03:00
2012-02-29 02:51:04 +03:00
if ( ( ret = vorbis_analysis_headerout ( & s - > vd , & s - > vc , & header , & header_comm ,
& header_code ) ) ) {
2012-02-22 02:40:22 +03:00
ret = vorbis_error_to_averror ( ret ) ;
goto error ;
}
2005-12-17 20:14:38 +02:00
2012-02-29 02:51:04 +03:00
avctx - > extradata_size = 1 + xiph_len ( header . bytes ) +
xiph_len ( header_comm . bytes ) +
header_code . bytes ;
p = avctx - > extradata = av_malloc ( avctx - > extradata_size +
FF_INPUT_BUFFER_PADDING_SIZE ) ;
2012-02-22 02:40:22 +03:00
if ( ! p ) {
ret = AVERROR ( ENOMEM ) ;
goto error ;
}
2011-12-29 23:37:05 +03:00
p [ 0 ] = 2 ;
offset = 1 ;
2005-05-13 21:10:23 +03:00
offset + = av_xiphlacing ( & p [ offset ] , header . bytes ) ;
offset + = av_xiphlacing ( & p [ offset ] , header_comm . bytes ) ;
memcpy ( & p [ offset ] , header . packet , header . bytes ) ;
offset + = header . bytes ;
memcpy ( & p [ offset ] , header_comm . packet , header_comm . bytes ) ;
offset + = header_comm . bytes ;
memcpy ( & p [ offset ] , header_code . packet , header_code . bytes ) ;
offset + = header_code . bytes ;
2012-02-29 02:51:04 +03:00
assert ( offset = = avctx - > extradata_size ) ;
2005-12-17 20:14:38 +02:00
2012-02-29 09:02:54 +03:00
if ( ( ret = avpriv_vorbis_parse_extradata ( avctx , & s - > vp ) ) < 0 ) {
av_log ( avctx , AV_LOG_ERROR , " invalid extradata \n " ) ;
return ret ;
}
2012-02-29 02:51:04 +03:00
vorbis_comment_clear ( & s - > vc ) ;
2005-12-17 20:14:38 +02:00
2012-02-29 02:51:04 +03:00
avctx - > frame_size = OGGVORBIS_FRAME_SIZE ;
2012-02-29 09:02:54 +03:00
ff_af_queue_init ( avctx , & s - > afq ) ;
2005-12-17 20:14:38 +02:00
2012-02-29 06:39:07 +03:00
s - > pkt_fifo = av_fifo_alloc ( BUFFER_SIZE ) ;
if ( ! s - > pkt_fifo ) {
ret = AVERROR ( ENOMEM ) ;
goto error ;
}
2005-12-17 20:14:38 +02:00
2012-02-29 09:02:54 +03:00
# if FF_API_OLD_ENCODE_AUDIO
2012-02-29 02:51:04 +03:00
avctx - > coded_frame = avcodec_alloc_frame ( ) ;
if ( ! avctx - > coded_frame ) {
2012-02-22 02:40:22 +03:00
ret = AVERROR ( ENOMEM ) ;
goto error ;
}
2012-02-29 09:02:54 +03:00
# endif
2005-12-17 20:14:38 +02:00
2011-12-29 23:37:05 +03:00
return 0 ;
2012-02-22 02:40:22 +03:00
error :
2012-02-29 02:51:04 +03:00
oggvorbis_encode_close ( avctx ) ;
2012-02-22 02:40:22 +03:00
return ret ;
2002-09-01 21:07:56 +03:00
}
2012-02-29 09:02:54 +03:00
static int oggvorbis_encode_frame ( AVCodecContext * avctx , AVPacket * avpkt ,
const AVFrame * frame , int * got_packet_ptr )
2002-09-01 21:07:56 +03:00
{
2012-02-29 02:51:04 +03:00
OggVorbisContext * s = avctx - > priv_data ;
2011-12-29 23:37:05 +03:00
ogg_packet op ;
2012-02-29 09:02:54 +03:00
int ret , duration ;
2008-10-15 10:29:37 +03:00
2012-02-29 02:51:04 +03:00
/* send samples to libvorbis */
2012-02-29 09:02:54 +03:00
if ( frame ) {
const float * audio = ( const float * ) frame - > data [ 0 ] ;
const int samples = frame - > nb_samples ;
2011-12-29 23:37:05 +03:00
float * * buffer ;
2012-02-29 02:51:04 +03:00
int c , channels = s - > vi . channels ;
2002-09-01 21:07:56 +03:00
2012-02-29 02:51:04 +03:00
buffer = vorbis_analysis_buffer ( & s - > vd , samples ) ;
2010-06-27 12:25:05 +03:00
for ( c = 0 ; c < channels ; c + + ) {
2012-02-29 02:51:04 +03:00
int i ;
2010-06-27 12:25:05 +03:00
int co = ( channels > 8 ) ? c :
2011-12-29 23:37:05 +03:00
ff_vorbis_encoding_channel_layout_offsets [ channels - 1 ] [ c ] ;
2012-02-29 02:51:04 +03:00
for ( i = 0 ; i < samples ; i + + )
2012-02-29 03:55:10 +03:00
buffer [ c ] [ i ] = audio [ i * channels + co ] ;
2005-12-22 03:10:11 +02:00
}
2012-02-29 08:02:55 +03:00
if ( ( ret = vorbis_analysis_wrote ( & s - > vd , samples ) ) < 0 ) {
av_log ( avctx , AV_LOG_ERROR , " error in vorbis_analysis_wrote() \n " ) ;
2012-02-29 05:00:33 +03:00
return vorbis_error_to_averror ( ret ) ;
2005-12-22 03:10:11 +02:00
}
2012-02-29 09:02:54 +03:00
if ( ( ret = ff_af_queue_add ( & s - > afq , frame ) < 0 ) )
return ret ;
2008-10-15 10:29:37 +03:00
} else {
2012-02-29 02:51:04 +03:00
if ( ! s - > eof )
2012-02-29 08:02:55 +03:00
if ( ( ret = vorbis_analysis_wrote ( & s - > vd , 0 ) ) < 0 ) {
av_log ( avctx , AV_LOG_ERROR , " error in vorbis_analysis_wrote() \n " ) ;
2012-02-29 05:00:33 +03:00
return vorbis_error_to_averror ( ret ) ;
2012-02-29 08:02:55 +03:00
}
2012-02-29 02:51:04 +03:00
s - > eof = 1 ;
2008-10-15 10:29:37 +03:00
}
2002-09-01 21:07:56 +03:00
2012-02-29 02:51:04 +03:00
/* retrieve available packets from libvorbis */
2012-02-29 05:00:33 +03:00
while ( ( ret = vorbis_analysis_blockout ( & s - > vd , & s - > vb ) ) = = 1 ) {
if ( ( ret = vorbis_analysis ( & s - > vb , NULL ) ) < 0 )
break ;
if ( ( ret = vorbis_bitrate_addblock ( & s - > vb ) ) < 0 )
break ;
2002-09-01 21:07:56 +03:00
2012-02-29 02:51:04 +03:00
/* add any available packets to the output packet buffer */
2012-02-29 05:00:33 +03:00
while ( ( ret = vorbis_bitrate_flushpacket ( & s - > vd , & op ) ) = = 1 ) {
2012-02-29 06:39:07 +03:00
if ( av_fifo_space ( s - > pkt_fifo ) < sizeof ( ogg_packet ) + op . bytes ) {
2012-03-01 03:13:16 +03:00
av_log ( avctx , AV_LOG_ERROR , " packet buffer is too small \n " ) ;
2012-02-29 08:02:55 +03:00
return AVERROR_BUG ;
2010-07-11 09:59:21 +03:00
}
2012-02-29 06:39:07 +03:00
av_fifo_generic_write ( s - > pkt_fifo , & op , sizeof ( ogg_packet ) , NULL ) ;
av_fifo_generic_write ( s - > pkt_fifo , op . packet , op . bytes , NULL ) ;
2005-12-22 03:10:11 +02:00
}
2012-02-29 08:02:55 +03:00
if ( ret < 0 ) {
av_log ( avctx , AV_LOG_ERROR , " error getting available packets \n " ) ;
2012-02-29 05:00:33 +03:00
break ;
2005-12-22 03:10:11 +02:00
}
2002-09-01 21:07:56 +03:00
}
2012-02-29 08:02:55 +03:00
if ( ret < 0 ) {
av_log ( avctx , AV_LOG_ERROR , " error getting available packets \n " ) ;
2012-02-29 05:00:33 +03:00
return vorbis_error_to_averror ( ret ) ;
2012-02-29 08:02:55 +03:00
}
2002-09-01 21:07:56 +03:00
2012-02-29 09:02:54 +03:00
/* check for available packets */
if ( av_fifo_size ( s - > pkt_fifo ) < sizeof ( ogg_packet ) )
return 0 ;
av_fifo_generic_read ( s - > pkt_fifo , & op , sizeof ( ogg_packet ) , NULL ) ;
2012-03-22 23:22:39 +03:00
if ( ( ret = ff_alloc_packet2 ( avctx , avpkt , op . bytes ) ) )
2012-02-29 09:02:54 +03:00
return ret ;
av_fifo_generic_read ( s - > pkt_fifo , avpkt - > data , op . bytes , NULL ) ;
avpkt - > pts = ff_samples_to_time_base ( avctx , op . granulepos ) ;
duration = avpriv_vorbis_parse_frame ( & s - > vp , avpkt - > data , avpkt - > size ) ;
if ( duration > 0 ) {
/* we do not know encoder delay until we get the first packet from
* libvorbis , so we have to update the AudioFrameQueue counts */
if ( ! avctx - > delay ) {
avctx - > delay = duration ;
s - > afq . remaining_delay + = duration ;
s - > afq . remaining_samples + = duration ;
2010-07-11 09:59:21 +03:00
}
2012-02-29 09:02:54 +03:00
ff_af_queue_remove ( & s - > afq , duration , & avpkt - > pts , & avpkt - > duration ) ;
2004-04-04 17:39:20 +03:00
}
2012-02-29 09:02:54 +03:00
* got_packet_ptr = 1 ;
return 0 ;
2002-09-01 21:07:56 +03:00
}
2011-01-25 23:40:11 +02:00
AVCodec ff_libvorbis_encoder = {
2011-09-23 22:11:15 +03:00
. name = " libvorbis " ,
. type = AVMEDIA_TYPE_AUDIO ,
. id = CODEC_ID_VORBIS ,
. priv_data_size = sizeof ( OggVorbisContext ) ,
. init = oggvorbis_encode_init ,
2012-02-29 09:02:54 +03:00
. encode2 = oggvorbis_encode_frame ,
2011-09-23 22:11:15 +03:00
. close = oggvorbis_encode_close ,
. capabilities = CODEC_CAP_DELAY ,
2012-02-29 03:55:10 +03:00
. sample_fmts = ( const enum AVSampleFormat [ ] ) { AV_SAMPLE_FMT_FLT ,
2012-02-29 02:51:04 +03:00
AV_SAMPLE_FMT_NONE } ,
2011-09-23 22:11:15 +03:00
. long_name = NULL_IF_CONFIG_SMALL ( " libvorbis Vorbis " ) ,
. priv_class = & class ,
2012-02-29 03:33:07 +03:00
. defaults = defaults ,
2011-09-23 22:11:15 +03:00
} ;
2012-05-05 11:45:30 +03:00
static int oggvorbis_decode_init ( AVCodecContext * avccontext ) {
OggVorbisContext * context = avccontext - > priv_data ;
uint8_t * p = avccontext - > extradata ;
int i , hsizes [ 3 ] ;
unsigned char * headers [ 3 ] , * extradata = avccontext - > extradata ;
vorbis_info_init ( & context - > vi ) ;
vorbis_comment_init ( & context - > vc ) ;
if ( ! avccontext - > extradata_size | | ! p ) {
av_log ( avccontext , AV_LOG_ERROR , " vorbis extradata absent \n " ) ;
return - 1 ;
}
if ( p [ 0 ] = = 0 & & p [ 1 ] = = 30 ) {
for ( i = 0 ; i < 3 ; i + + ) {
hsizes [ i ] = bytestream_get_be16 ( & p ) ;
headers [ i ] = p ;
p + = hsizes [ i ] ;
}
} else if ( * p = = 2 ) {
unsigned int offset = 1 ;
p + + ;
for ( i = 0 ; i < 2 ; i + + ) {
hsizes [ i ] = 0 ;
while ( ( * p = = 0xFF ) & & ( offset < avccontext - > extradata_size ) ) {
hsizes [ i ] + = 0xFF ;
offset + + ;
p + + ;
}
if ( offset > = avccontext - > extradata_size - 1 ) {
av_log ( avccontext , AV_LOG_ERROR ,
" vorbis header sizes damaged \n " ) ;
return - 1 ;
}
hsizes [ i ] + = * p ;
offset + + ;
p + + ;
}
hsizes [ 2 ] = avccontext - > extradata_size - hsizes [ 0 ] - hsizes [ 1 ] - offset ;
#if 0
av_log ( avccontext , AV_LOG_DEBUG ,
" vorbis header sizes: %d, %d, %d, / extradata_len is %d \n " ,
hsizes [ 0 ] , hsizes [ 1 ] , hsizes [ 2 ] , avccontext - > extradata_size ) ;
# endif
headers [ 0 ] = extradata + offset ;
headers [ 1 ] = extradata + offset + hsizes [ 0 ] ;
headers [ 2 ] = extradata + offset + hsizes [ 0 ] + hsizes [ 1 ] ;
} else {
av_log ( avccontext , AV_LOG_ERROR ,
" vorbis initial header len is wrong: %d \n " , * p ) ;
return - 1 ;
}
for ( i = 0 ; i < 3 ; i + + ) {
context - > op . b_o_s = i = = 0 ;
context - > op . bytes = hsizes [ i ] ;
context - > op . packet = headers [ i ] ;
if ( vorbis_synthesis_headerin ( & context - > vi , & context - > vc , & context - > op ) < 0 ) {
av_log ( avccontext , AV_LOG_ERROR , " %d. vorbis header damaged \n " , i + 1 ) ;
return - 1 ;
}
}
avccontext - > channels = context - > vi . channels ;
avccontext - > sample_rate = context - > vi . rate ;
avccontext - > time_base = ( AVRational ) { 1 , avccontext - > sample_rate } ;
vorbis_synthesis_init ( & context - > vd , & context - > vi ) ;
vorbis_block_init ( & context - > vd , & context - > vb ) ;
return 0 ;
}
static inline int conv ( int samples , float * * pcm , char * buf , int channels ) {
int i , j ;
ogg_int16_t * ptr , * data = ( ogg_int16_t * ) buf ;
float * mono ;
for ( i = 0 ; i < channels ; i + + ) {
ptr = & data [ i ] ;
mono = pcm [ i ] ;
for ( j = 0 ; j < samples ; j + + ) {
* ptr = av_clip_int16 ( mono [ j ] * 32767.f ) ;
ptr + = channels ;
}
}
return 0 ;
}
static int oggvorbis_decode_frame ( AVCodecContext * avccontext , void * data ,
int * got_frame_ptr , AVPacket * avpkt )
{
OggVorbisContext * context = avccontext - > priv_data ;
float * * pcm ;
ogg_packet * op = & context - > op ;
int samples , total_samples , total_bytes ;
int ret ;
int16_t * output ;
if ( ! avpkt - > size ) {
//FIXME flush
return 0 ;
}
context - > frame . nb_samples = 8192 * 4 ;
if ( ( ret = avccontext - > get_buffer ( avccontext , & context - > frame ) ) < 0 ) {
av_log ( avccontext , AV_LOG_ERROR , " get_buffer() failed \n " ) ;
return ret ;
}
output = ( int16_t * ) context - > frame . data [ 0 ] ;
op - > packet = avpkt - > data ;
op - > bytes = avpkt - > size ;
// av_log(avccontext, AV_LOG_DEBUG, "%d %d %d %"PRId64" %"PRId64" %d %d\n", op->bytes, op->b_o_s, op->e_o_s, op->granulepos, op->packetno, buf_size, context->vi.rate);
/* for(i=0; i<op->bytes; i++)
av_log ( avccontext , AV_LOG_DEBUG , " %02X " , op - > packet [ i ] ) ;
av_log ( avccontext , AV_LOG_DEBUG , " \n " ) ; */
if ( vorbis_synthesis ( & context - > vb , op ) = = 0 )
vorbis_synthesis_blockin ( & context - > vd , & context - > vb ) ;
total_samples = 0 ;
total_bytes = 0 ;
while ( ( samples = vorbis_synthesis_pcmout ( & context - > vd , & pcm ) ) > 0 ) {
conv ( samples , pcm , ( char * ) output + total_bytes , context - > vi . channels ) ;
total_bytes + = samples * 2 * context - > vi . channels ;
total_samples + = samples ;
vorbis_synthesis_read ( & context - > vd , samples ) ;
}
context - > frame . nb_samples = total_samples ;
* got_frame_ptr = 1 ;
* ( AVFrame * ) data = context - > frame ;
return avpkt - > size ;
}
static int oggvorbis_decode_close ( AVCodecContext * avccontext ) {
OggVorbisContext * context = avccontext - > priv_data ;
vorbis_info_clear ( & context - > vi ) ;
vorbis_comment_clear ( & context - > vc ) ;
return 0 ;
}
AVCodec ff_libvorbis_decoder = {
. name = " libvorbis " ,
. type = AVMEDIA_TYPE_AUDIO ,
. id = CODEC_ID_VORBIS ,
. priv_data_size = sizeof ( OggVorbisContext ) ,
. init = oggvorbis_decode_init ,
. decode = oggvorbis_decode_frame ,
. close = oggvorbis_decode_close ,
. capabilities = CODEC_CAP_DELAY ,
} ;