2006-09-10 16:02:42 +02:00
/*
* copyright ( c ) 2002 Mark Hills < mark @ pogo . org . uk >
*
2011-03-18 18:35:10 +01:00
* This file is part of Libav .
2006-10-07 17:30:46 +02:00
*
2011-03-18 18:35:10 +01:00
* Libav is free software ; you can redistribute it and / or
2006-09-10 16:02:42 +02:00
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
2006-10-07 17:30:46 +02:00
* version 2.1 of the License , or ( at your option ) any later version .
2006-09-10 16:02:42 +02:00
*
2011-03-18 18:35:10 +01:00
* Libav is distributed in the hope that it will be useful ,
2006-09-10 16:02:42 +02: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
2011-03-18 18:35:10 +01:00
* License along with Libav ; if not , write to the Free Software
2007-07-05 12:40:25 +02:00
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA
2006-09-10 16:02:42 +02:00
*/
2003-03-06 12:32:04 +01:00
/**
2010-04-20 16:45:34 +02:00
* @ file
2012-02-29 00:51:04 +01:00
* Vorbis encoding support via libvorbisenc .
2003-03-06 12:32:04 +01:00
* @ author Mark Hills < mark @ pogo . org . uk >
2002-09-01 20:07:56 +02:00
*/
# include <vorbis/vorbisenc.h>
2010-09-29 17:09:38 +02:00
# include "libavutil/opt.h"
2002-09-01 20:07:56 +02:00
# include "avcodec.h"
2007-06-02 03:41:07 +02:00
# include "bytestream.h"
2012-02-07 21:37:45 +01:00
# include "internal.h"
2010-06-27 11:25:05 +02:00
# include "vorbis.h"
2002-09-01 20:07:56 +02:00
2004-04-04 19:06:30 +02:00
# undef NDEBUG
# include <assert.h>
2012-02-29 00:51:04 +01: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 16:39:20 +02:00
# define OGGVORBIS_FRAME_SIZE 64
2002-09-01 20:07:56 +02:00
2011-12-29 21:37:05 +01:00
# define BUFFER_SIZE (1024 * 64)
2002-09-01 20:07:56 +02:00
typedef struct OggVorbisContext {
2012-02-29 00:51:04 +01:00
AVClass * av_class ; /**< class for AVOptions */
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 */
uint8_t buffer [ BUFFER_SIZE ] ; /**< output packet buffer */
int buffer_index ; /**< current buffer position */
int eof ; /**< end-of-file flag */
vorbis_comment vc ; /**< VorbisComment info */
ogg_packet op ; /**< ogg packet */
double iblock ; /**< impulse block bias option */
2011-12-29 21:37:05 +01:00
} OggVorbisContext ;
2002-09-01 20:07:56 +02:00
2011-12-29 21:37:05 +01: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 17:09:38 +02:00
} ;
2010-10-14 09:47:49 +02:00
static const AVClass class = { " libvorbis " , av_default_item_name , options , LIBAVUTIL_VERSION_INT } ;
2002-09-01 20:07:56 +02:00
2012-02-29 00:51:04 +01:00
2012-02-22 00:40:22 +01:00
static int vorbis_error_to_averror ( int ov_err )
{
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 ;
}
}
2012-02-29 00:51:04 +01:00
static av_cold int oggvorbis_init_encoder ( vorbis_info * vi ,
AVCodecContext * avctx )
2011-12-29 21:37:05 +01:00
{
2012-02-29 00:51:04 +01:00
OggVorbisContext * s = avctx - > priv_data ;
2006-01-21 18:09:23 +01:00
double cfreq ;
2012-02-22 00:40:22 +01:00
int ret ;
2002-12-21 16:54:21 +01:00
2012-02-29 00:51:04 +01:00
if ( avctx - > flags & CODEC_FLAG_QSCALE ) {
/* variable bitrate
* NOTE : we use the oggenc range of - 1 to 10 for global_quality for
* user convenience , but libvorbis uses - 0.1 to 1.0
*/
float q = avctx - > global_quality / ( float ) FF_QP2LAMBDA ;
if ( ( ret = vorbis_encode_setup_vbr ( vi , avctx - > channels ,
avctx - > sample_rate ,
2012-02-22 00:40:22 +01:00
q / 10.0 ) ) )
goto error ;
2006-01-21 18:09:23 +01:00
} else {
2012-02-29 00:51:04 +01:00
int minrate = avctx - > rc_min_rate > 0 ? avctx - > rc_min_rate : - 1 ;
int maxrate = avctx - > rc_min_rate > 0 ? avctx - > rc_max_rate : - 1 ;
2010-06-05 00:40:31 +02:00
2012-02-29 00:51:04 +01:00
/* average bitrate */
if ( ( ret = vorbis_encode_setup_managed ( vi , avctx - > channels ,
avctx - > sample_rate , minrate ,
avctx - > bit_rate , maxrate ) ) )
2012-02-22 00:40:22 +01:00
goto error ;
2006-01-21 18:09:23 +01:00
2010-06-05 00:40:40 +02:00
/* variable bitrate by estimate, disable slow rate management */
2011-12-29 21:37:05 +01:00
if ( minrate = = - 1 & & maxrate = = - 1 )
2012-02-22 00:40:22 +01:00
if ( ( ret = vorbis_encode_ctl ( vi , OV_ECTL_RATEMANAGE2_SET , NULL ) ) )
goto error ;
2006-01-21 18:09:23 +01:00
}
2002-12-21 16:54:21 +01:00
2006-01-21 18:09:23 +01:00
/* cutoff frequency */
2012-02-29 00:51:04 +01:00
if ( avctx - > cutoff > 0 ) {
cfreq = avctx - > cutoff / 1000.0 ;
2012-02-22 00:40:22 +01:00
if ( ( ret = vorbis_encode_ctl ( vi , OV_ECTL_LOWPASS_SET , & cfreq ) ) )
goto error ;
2006-01-21 18:09:23 +01:00
}
2002-09-01 20:07:56 +02:00
2012-02-29 00:51:04 +01:00
/* impulse block bias */
if ( s - > iblock ) {
if ( ( ret = vorbis_encode_ctl ( vi , OV_ECTL_IBLOCK_SET , & s - > iblock ) ) )
2012-02-22 00:40:22 +01:00
goto error ;
2010-09-29 17:09:38 +02:00
}
2012-02-22 00:40:22 +01:00
if ( ( ret = vorbis_encode_setup_init ( vi ) ) )
goto error ;
return 0 ;
error :
return vorbis_error_to_averror ( ret ) ;
2002-09-01 20:07:56 +02:00
}
2010-07-20 23:54:46 +02:00
/* How many bytes are needed for a buffer of length 'l' */
2011-12-29 21:37:05 +01:00
static int xiph_len ( int l )
{
2011-12-29 22:23:16 +01:00
return 1 + l / 255 + l ;
2011-12-29 21:37:05 +01:00
}
2010-07-20 23:54:46 +02:00
2012-02-29 00:51:04 +01:00
static av_cold int oggvorbis_encode_close ( AVCodecContext * avctx )
2012-02-22 00:40:22 +01:00
{
2012-02-29 00:51:04 +01:00
OggVorbisContext * s = avctx - > priv_data ;
2012-02-22 00:40:22 +01:00
2012-02-29 00:51:04 +01:00
/* notify vorbisenc this is EOF */
vorbis_analysis_wrote ( & s - > vd , 0 ) ;
2012-02-22 00:40:22 +01:00
2012-02-29 00:51:04 +01:00
vorbis_block_clear ( & s - > vb ) ;
vorbis_dsp_clear ( & s - > vd ) ;
vorbis_info_clear ( & s - > vi ) ;
2012-02-22 00:40:22 +01:00
2012-02-29 00:51:04 +01:00
av_freep ( & avctx - > coded_frame ) ;
av_freep ( & avctx - > extradata ) ;
2012-02-22 00:40:22 +01:00
return 0 ;
}
2012-02-29 00:51:04 +01:00
static av_cold int oggvorbis_encode_init ( AVCodecContext * avctx )
2011-12-29 21:37:05 +01:00
{
2012-02-29 00:51:04 +01:00
OggVorbisContext * s = avctx - > priv_data ;
2004-04-04 17:19:20 +02:00
ogg_packet header , header_comm , header_code ;
uint8_t * p ;
2010-07-20 23:54:46 +02:00
unsigned int offset ;
2012-02-22 00:40:22 +01:00
int ret ;
2002-09-01 20:07:56 +02:00
2012-02-29 00:51:04 +01:00
vorbis_info_init ( & s - > vi ) ;
if ( ( ret = oggvorbis_init_encoder ( & s - > vi , avctx ) ) ) {
av_log ( avctx , AV_LOG_ERROR , " oggvorbis_encode_init: init_encoder failed \n " ) ;
2012-02-22 00:40:22 +01:00
goto error ;
}
2012-02-29 00:51:04 +01:00
if ( ( ret = vorbis_analysis_init ( & s - > vd , & s - > vi ) ) ) {
2012-02-22 00:40:22 +01:00
ret = vorbis_error_to_averror ( ret ) ;
goto error ;
}
2012-02-29 00:51:04 +01:00
if ( ( ret = vorbis_block_init ( & s - > vd , & s - > vb ) ) ) {
2012-02-22 00:40:22 +01:00
ret = vorbis_error_to_averror ( ret ) ;
goto error ;
2002-09-01 20:07:56 +02:00
}
2012-02-29 00:51:04 +01:00
vorbis_comment_init ( & s - > vc ) ;
vorbis_comment_add_tag ( & s - > vc , " encoder " , LIBAVCODEC_IDENT ) ;
2004-04-04 17:19:20 +02:00
2012-02-29 00:51:04 +01:00
if ( ( ret = vorbis_analysis_headerout ( & s - > vd , & s - > vc , & header , & header_comm ,
& header_code ) ) ) {
2012-02-22 00:40:22 +01:00
ret = vorbis_error_to_averror ( ret ) ;
goto error ;
}
2005-12-17 19:14:38 +01:00
2012-02-29 00:51:04 +01: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 00:40:22 +01:00
if ( ! p ) {
ret = AVERROR ( ENOMEM ) ;
goto error ;
}
2011-12-29 21:37:05 +01:00
p [ 0 ] = 2 ;
offset = 1 ;
2005-05-13 20:10:23 +02: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 00:51:04 +01:00
assert ( offset = = avctx - > extradata_size ) ;
2005-12-17 19:14:38 +01:00
2012-02-29 00:51:04 +01:00
vorbis_comment_clear ( & s - > vc ) ;
2005-12-17 19:14:38 +01:00
2012-02-29 00:51:04 +01:00
avctx - > frame_size = OGGVORBIS_FRAME_SIZE ;
2005-12-17 19:14:38 +01:00
2012-02-29 00:51:04 +01:00
avctx - > coded_frame = avcodec_alloc_frame ( ) ;
if ( ! avctx - > coded_frame ) {
2012-02-22 00:40:22 +01:00
ret = AVERROR ( ENOMEM ) ;
goto error ;
}
2005-12-17 19:14:38 +01:00
2011-12-29 21:37:05 +01:00
return 0 ;
2012-02-22 00:40:22 +01:00
error :
2012-02-29 00:51:04 +01:00
oggvorbis_encode_close ( avctx ) ;
2012-02-22 00:40:22 +01:00
return ret ;
2002-09-01 20:07:56 +02:00
}
2012-02-29 00:51:04 +01:00
static int oggvorbis_encode_frame ( AVCodecContext * avctx , unsigned char * packets ,
2011-12-29 21:37:05 +01:00
int buf_size , void * data )
2002-09-01 20:07:56 +02:00
{
2012-02-29 00:51:04 +01:00
OggVorbisContext * s = avctx - > priv_data ;
2011-12-29 21:37:05 +01:00
ogg_packet op ;
signed short * audio = data ;
2012-02-29 00:51:04 +01:00
int pkt_size ;
2008-10-15 09:29:37 +02:00
2012-02-29 00:51:04 +01:00
/* send samples to libvorbis */
2011-12-29 21:37:05 +01:00
if ( data ) {
2012-02-29 00:51:04 +01:00
const int samples = avctx - > frame_size ;
2011-12-29 21:37:05 +01:00
float * * buffer ;
2012-02-29 00:51:04 +01:00
int c , channels = s - > vi . channels ;
2002-09-01 20:07:56 +02:00
2012-02-29 00:51:04 +01:00
buffer = vorbis_analysis_buffer ( & s - > vd , samples ) ;
2010-06-27 11:25:05 +02:00
for ( c = 0 ; c < channels ; c + + ) {
2012-02-29 00:51:04 +01:00
int i ;
2010-06-27 11:25:05 +02:00
int co = ( channels > 8 ) ? c :
2011-12-29 21:37:05 +01:00
ff_vorbis_encoding_channel_layout_offsets [ channels - 1 ] [ c ] ;
2012-02-29 00:51:04 +01:00
for ( i = 0 ; i < samples ; i + + )
buffer [ c ] [ i ] = audio [ i * channels + co ] / 32768.f ;
2005-12-22 02:10:11 +01:00
}
2012-02-29 00:51:04 +01:00
vorbis_analysis_wrote ( & s - > vd , samples ) ;
2008-10-15 09:29:37 +02:00
} else {
2012-02-29 00:51:04 +01:00
if ( ! s - > eof )
vorbis_analysis_wrote ( & s - > vd , 0 ) ;
s - > eof = 1 ;
2008-10-15 09:29:37 +02:00
}
2002-09-01 20:07:56 +02:00
2012-02-29 00:51:04 +01:00
/* retrieve available packets from libvorbis */
while ( vorbis_analysis_blockout ( & s - > vd , & s - > vb ) = = 1 ) {
vorbis_analysis ( & s - > vb , NULL ) ;
vorbis_bitrate_addblock ( & s - > vb ) ;
2002-09-01 20:07:56 +02:00
2012-02-29 00:51:04 +01:00
/* add any available packets to the output packet buffer */
while ( vorbis_bitrate_flushpacket ( & s - > vd , & op ) ) {
2007-02-21 11:15:08 +01:00
/* i'd love to say the following line is a hack, but sadly it's
* not , apparently the end of stream decision is in libogg . */
2011-12-29 21:37:05 +01:00
if ( op . bytes = = 1 & & op . e_o_s )
2004-06-22 23:14:01 +02:00
continue ;
2012-02-29 00:51:04 +01:00
if ( s - > buffer_index + sizeof ( ogg_packet ) + op . bytes > BUFFER_SIZE ) {
av_log ( avctx , AV_LOG_ERROR , " libvorbis: buffer overflow. " ) ;
2010-07-11 08:59:21 +02:00
return - 1 ;
}
2012-02-29 00:51:04 +01:00
memcpy ( s - > buffer + s - > buffer_index , & op , sizeof ( ogg_packet ) ) ;
s - > buffer_index + = sizeof ( ogg_packet ) ;
memcpy ( s - > buffer + s - > buffer_index , op . packet , op . bytes ) ;
s - > buffer_index + = op . bytes ;
2005-12-22 02:10:11 +01:00
}
2002-09-01 20:07:56 +02:00
}
2012-02-29 00:51:04 +01:00
/* output then next packet from the output buffer, if available */
pkt_size = 0 ;
if ( s - > buffer_index ) {
ogg_packet * op2 = ( ogg_packet * ) s - > buffer ;
op2 - > packet = s - > buffer + sizeof ( ogg_packet ) ;
pkt_size = op2 - > bytes ;
// FIXME: we should use the user-supplied pts and duration
avctx - > coded_frame - > pts = ff_samples_to_time_base ( avctx ,
op2 - > granulepos ) ;
if ( pkt_size > buf_size ) {
av_log ( avctx , AV_LOG_ERROR , " libvorbis: buffer overflow. " ) ;
2010-07-11 08:59:21 +02:00
return - 1 ;
}
2012-02-29 00:51:04 +01:00
memcpy ( packets , op2 - > packet , pkt_size ) ;
s - > buffer_index - = pkt_size + sizeof ( ogg_packet ) ;
memmove ( s - > buffer , s - > buffer + pkt_size + sizeof ( ogg_packet ) ,
s - > buffer_index ) ;
2004-04-04 16:39:20 +02:00
}
2012-02-29 00:51:04 +01:00
return pkt_size ;
2002-09-01 20:07:56 +02:00
}
2011-01-25 22:40:11 +01:00
AVCodec ff_libvorbis_encoder = {
2011-09-23 21:11:15 +02:00
. name = " libvorbis " ,
. type = AVMEDIA_TYPE_AUDIO ,
. id = CODEC_ID_VORBIS ,
. priv_data_size = sizeof ( OggVorbisContext ) ,
. init = oggvorbis_encode_init ,
. encode = oggvorbis_encode_frame ,
. close = oggvorbis_encode_close ,
. capabilities = CODEC_CAP_DELAY ,
2012-02-29 00:51:04 +01:00
. sample_fmts = ( const enum AVSampleFormat [ ] ) { AV_SAMPLE_FMT_S16 ,
AV_SAMPLE_FMT_NONE } ,
2011-09-23 21:11:15 +02:00
. long_name = NULL_IF_CONFIG_SMALL ( " libvorbis Vorbis " ) ,
. priv_class = & class ,
} ;