2006-09-10 14:02:42 +00:00
/*
* copyright (c) 2002 Mark Hills <mark@pogo.org.uk>
*
2011-03-18 17:35:10 +00:00
* This file is part of Libav.
2006-10-07 15:30:46 +00:00
*
2011-03-18 17:35:10 +00:00
* Libav is free software; you can redistribute it and/or
2006-09-10 14:02:42 +00:00
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
2006-10-07 15:30:46 +00:00
* version 2.1 of the License, or (at your option) any later version.
2006-09-10 14:02:42 +00:00
*
2011-03-18 17:35:10 +00:00
* Libav is distributed in the hope that it will be useful,
2006-09-10 14:02:42 +00: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 17:35:10 +00:00
* License along with Libav; if not, write to the Free Software
2007-07-05 10:40:25 +00:00
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2006-09-10 14:02:42 +00:00
*/
2003-03-06 11:32:04 +00:00
/**
2010-04-20 14:45:34 +00:00
* @file
2012-02-28 18:51:04 -05:00
* Vorbis encoding support via libvorbisenc.
2003-03-06 11:32:04 +00:00
* @author Mark Hills <mark@pogo.org.uk>
2002-09-01 18:07:56 +00:00
*/
#include <vorbis/vorbisenc.h>
2012-02-28 22:39:07 -05:00
#include "libavutil/fifo.h"
2010-09-29 15:09:38 +00:00
#include "libavutil/opt.h"
2002-09-01 18:07:56 +00:00
#include "avcodec.h"
2012-02-29 01:02:54 -05:00
#include "audio_frame_queue.h"
2007-06-02 01:41:07 +00:00
#include "bytestream.h"
2012-02-07 15:37:45 -05:00
#include "internal.h"
2010-06-27 09:25:05 +00:00
#include "vorbis.h"
2012-02-29 01:02:54 -05:00
#include "vorbis_parser.h"
2002-09-01 18:07:56 +00:00
2004-04-04 17:06:30 +00:00
#undef NDEBUG
#include <assert.h>
2012-02-28 18:51:04 -05: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 14:39:20 +00:00
#define OGGVORBIS_FRAME_SIZE 64
2002-09-01 18:07:56 +00:00
2011-12-29 21:37:05 +01:00
#define BUFFER_SIZE (1024 * 64)
2002-09-01 18:07:56 +00:00
typedef struct OggVorbisContext {
2012-02-28 18:51:04 -05: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 */
2012-02-28 22:39:07 -05:00
AVFifoBuffer * pkt_fifo ; /**< output packet buffer */
2012-02-28 18:51:04 -05:00
int eof ; /**< end-of-file flag */
2012-02-28 19:51:25 -05:00
int dsp_initialized ; /**< vd has been initialized */
2012-02-28 18:51:04 -05:00
vorbis_comment vc ; /**< VorbisComment info */
ogg_packet op ; /**< ogg packet */
double iblock ; /**< impulse block bias option */
2012-02-29 01:02:54 -05:00
VorbisParseContext vp ; /**< parse context to get durations */
AudioFrameQueue afq ; /**< frame queue for timestamps */
2011-12-29 21:37:05 +01:00
} OggVorbisContext ;
2002-09-01 18:07:56 +00: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 15:09:38 +00:00
};
2012-02-28 19:33:07 -05:00
static const AVCodecDefault defaults [] = {
{ "b" , "0" },
{ NULL },
};
2010-10-14 07:47:49 +00:00
static const AVClass class = { "libvorbis" , av_default_item_name , options , LIBAVUTIL_VERSION_INT };
2002-09-01 18:07:56 +00:00
2012-02-28 18:51:04 -05:00
2012-02-21 18:40:22 -05: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-28 18:51:04 -05:00
static av_cold int oggvorbis_init_encoder ( vorbis_info * vi ,
AVCodecContext * avctx )
2011-12-29 21:37:05 +01:00
{
2012-02-28 18:51:04 -05:00
OggVorbisContext * s = avctx -> priv_data ;
2006-01-21 17:09:23 +00:00
double cfreq ;
2012-02-21 18:40:22 -05:00
int ret ;
2002-12-21 15:54:21 +00:00
2012-02-28 19:33:07 -05:00
if ( avctx -> flags & CODEC_FLAG_QSCALE || ! avctx -> bit_rate ) {
2012-02-28 18:51:04 -05:00
/* variable bitrate
* NOTE: we use the oggenc range of -1 to 10 for global_quality for
2012-02-28 19:33:07 -05:00
* user convenience, but libvorbis uses -0.1 to 1.0.
2012-02-28 18:51:04 -05:00
*/
float q = avctx -> global_quality / ( float ) FF_QP2LAMBDA ;
2012-02-28 19:33:07 -05:00
/* default to 3 if the user did not set quality or bitrate */
if ( ! ( avctx -> flags & CODEC_FLAG_QSCALE ))
q = 3.0 ;
2012-02-28 18:51:04 -05:00
if (( ret = vorbis_encode_setup_vbr ( vi , avctx -> channels ,
avctx -> sample_rate ,
2012-02-21 18:40:22 -05:00
q / 10.0 )))
goto error ;
2006-01-21 17:09:23 +00:00
} else {
2012-02-28 18:51:04 -05:00
int minrate = avctx -> rc_min_rate > 0 ? avctx -> rc_min_rate : - 1 ;
2012-02-28 18:52:30 -05:00
int maxrate = avctx -> rc_max_rate > 0 ? avctx -> rc_max_rate : - 1 ;
2010-06-04 22:40:31 +00:00
2012-02-28 18:51:04 -05:00
/* average bitrate */
if (( ret = vorbis_encode_setup_managed ( vi , avctx -> channels ,
2012-02-28 18:52:30 -05:00
avctx -> sample_rate , maxrate ,
avctx -> bit_rate , minrate )))
2012-02-21 18:40:22 -05:00
goto error ;
2006-01-21 17:09:23 +00:00
2010-06-04 22:40:40 +00:00
/* variable bitrate by estimate, disable slow rate management */
2011-12-29 21:37:05 +01:00
if ( minrate == - 1 && maxrate == - 1 )
2012-02-21 18:40:22 -05:00
if (( ret = vorbis_encode_ctl ( vi , OV_ECTL_RATEMANAGE2_SET , NULL )))
goto error ;
2006-01-21 17:09:23 +00:00
}
/* cutoff frequency */
2012-02-28 18:51:04 -05:00
if ( avctx -> cutoff > 0 ) {
cfreq = avctx -> cutoff / 1000.0 ;
2012-02-21 18:40:22 -05:00
if (( ret = vorbis_encode_ctl ( vi , OV_ECTL_LOWPASS_SET , & cfreq )))
goto error ;
2006-01-21 17:09:23 +00:00
}
2012-02-28 18:51:04 -05:00
/* impulse block bias */
if ( s -> iblock ) {
if (( ret = vorbis_encode_ctl ( vi , OV_ECTL_IBLOCK_SET , & s -> iblock )))
2012-02-21 18:40:22 -05:00
goto error ;
2010-09-29 15:09:38 +00:00
}
2012-02-21 18:40:22 -05:00
if (( ret = vorbis_encode_setup_init ( vi )))
goto error ;
return 0 ;
error :
return vorbis_error_to_averror ( ret );
2002-09-01 18:07:56 +00:00
}
2010-07-20 21:54:46 +00: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 21:54:46 +00:00
2012-02-28 18:51:04 -05:00
static av_cold int oggvorbis_encode_close ( AVCodecContext * avctx )
2012-02-21 18:40:22 -05:00
{
2012-02-28 18:51:04 -05:00
OggVorbisContext * s = avctx -> priv_data ;
2012-02-21 18:40:22 -05:00
2012-02-28 18:51:04 -05:00
/* notify vorbisenc this is EOF */
2012-02-28 19:51:25 -05:00
if ( s -> dsp_initialized )
vorbis_analysis_wrote ( & s -> vd , 0 );
2012-02-21 18:40:22 -05:00
2012-02-28 18:51:04 -05:00
vorbis_block_clear ( & s -> vb );
vorbis_dsp_clear ( & s -> vd );
vorbis_info_clear ( & s -> vi );
2012-02-21 18:40:22 -05:00
2012-02-28 22:39:07 -05:00
av_fifo_free ( s -> pkt_fifo );
2012-02-29 01:02:54 -05:00
ff_af_queue_close ( & s -> afq );
#if FF_API_OLD_ENCODE_AUDIO
2012-02-28 18:51:04 -05:00
av_freep ( & avctx -> coded_frame );
2012-02-29 01:02:54 -05:00
#endif
2012-02-28 18:51:04 -05:00
av_freep ( & avctx -> extradata );
2012-02-21 18:40:22 -05:00
return 0 ;
}
2012-02-28 18:51:04 -05:00
static av_cold int oggvorbis_encode_init ( AVCodecContext * avctx )
2011-12-29 21:37:05 +01:00
{
2012-02-28 18:51:04 -05:00
OggVorbisContext * s = avctx -> priv_data ;
2004-04-04 15:19:20 +00:00
ogg_packet header , header_comm , header_code ;
uint8_t * p ;
2010-07-20 21:54:46 +00:00
unsigned int offset ;
2012-02-21 18:40:22 -05:00
int ret ;
2002-09-01 18:07:56 +00:00
2012-02-28 18:51:04 -05:00
vorbis_info_init ( & s -> vi );
if (( ret = oggvorbis_init_encoder ( & s -> vi , avctx ))) {
2012-02-29 00:02:55 -05:00
av_log ( avctx , AV_LOG_ERROR , "encoder setup failed \n " );
2012-02-21 18:40:22 -05:00
goto error ;
}
2012-02-28 18:51:04 -05:00
if (( ret = vorbis_analysis_init ( & s -> vd , & s -> vi ))) {
2012-02-29 00:02:55 -05:00
av_log ( avctx , AV_LOG_ERROR , "analysis init failed \n " );
2012-02-21 18:40:22 -05:00
ret = vorbis_error_to_averror ( ret );
goto error ;
}
2012-02-28 19:51:25 -05:00
s -> dsp_initialized = 1 ;
2012-02-28 18:51:04 -05:00
if (( ret = vorbis_block_init ( & s -> vd , & s -> vb ))) {
2012-02-29 00:02:55 -05:00
av_log ( avctx , AV_LOG_ERROR , "dsp init failed \n " );
2012-02-21 18:40:22 -05:00
ret = vorbis_error_to_averror ( ret );
goto error ;
2002-09-01 18:07:56 +00:00
}
2012-02-28 18:51:04 -05:00
vorbis_comment_init ( & s -> vc );
vorbis_comment_add_tag ( & s -> vc , "encoder" , LIBAVCODEC_IDENT );
2004-04-04 15:19:20 +00:00
2012-02-28 18:51:04 -05:00
if (( ret = vorbis_analysis_headerout ( & s -> vd , & s -> vc , & header , & header_comm ,
& header_code ))) {
2012-02-21 18:40:22 -05:00
ret = vorbis_error_to_averror ( ret );
goto error ;
}
2005-12-17 18:14:38 +00:00
2012-02-28 18:51:04 -05: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-21 18:40:22 -05:00
if ( ! p ) {
ret = AVERROR ( ENOMEM );
goto error ;
}
2011-12-29 21:37:05 +01:00
p [ 0 ] = 2 ;
offset = 1 ;
2005-05-13 18:10:23 +00: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-28 18:51:04 -05:00
assert ( offset == avctx -> extradata_size );
2005-12-17 18:14:38 +00:00
2012-02-29 01:02:54 -05:00
if (( ret = avpriv_vorbis_parse_extradata ( avctx , & s -> vp )) < 0 ) {
av_log ( avctx , AV_LOG_ERROR , "invalid extradata \n " );
return ret ;
}
2012-02-28 18:51:04 -05:00
vorbis_comment_clear ( & s -> vc );
2005-12-17 18:14:38 +00:00
2012-02-28 18:51:04 -05:00
avctx -> frame_size = OGGVORBIS_FRAME_SIZE ;
2012-02-29 01:02:54 -05:00
ff_af_queue_init ( avctx , & s -> afq );
2005-12-17 18:14:38 +00:00
2012-02-28 22:39:07 -05:00
s -> pkt_fifo = av_fifo_alloc ( BUFFER_SIZE );
if ( ! s -> pkt_fifo ) {
ret = AVERROR ( ENOMEM );
goto error ;
}
2012-02-29 01:02:54 -05:00
#if FF_API_OLD_ENCODE_AUDIO
2012-02-28 18:51:04 -05:00
avctx -> coded_frame = avcodec_alloc_frame ();
if ( ! avctx -> coded_frame ) {
2012-02-21 18:40:22 -05:00
ret = AVERROR ( ENOMEM );
goto error ;
}
2012-02-29 01:02:54 -05:00
#endif
2005-12-17 18:14:38 +00:00
2011-12-29 21:37:05 +01:00
return 0 ;
2012-02-21 18:40:22 -05:00
error :
2012-02-28 18:51:04 -05:00
oggvorbis_encode_close ( avctx );
2012-02-21 18:40:22 -05:00
return ret ;
2002-09-01 18:07:56 +00:00
}
2012-02-29 01:02:54 -05:00
static int oggvorbis_encode_frame ( AVCodecContext * avctx , AVPacket * avpkt ,
const AVFrame * frame , int * got_packet_ptr )
2002-09-01 18:07:56 +00:00
{
2012-02-28 18:51:04 -05:00
OggVorbisContext * s = avctx -> priv_data ;
2011-12-29 21:37:05 +01:00
ogg_packet op ;
2012-02-29 01:02:54 -05:00
int ret , duration ;
2008-10-15 07:29:37 +00:00
2012-02-28 18:51:04 -05:00
/* send samples to libvorbis */
2012-02-29 01:02:54 -05:00
if ( frame ) {
const int samples = frame -> nb_samples ;
2011-12-29 21:37:05 +01:00
float ** buffer ;
2012-02-28 18:51:04 -05:00
int c , channels = s -> vi . channels ;
2002-09-01 18:07:56 +00:00
2012-02-28 18:51:04 -05:00
buffer = vorbis_analysis_buffer ( & s -> vd , samples );
2010-06-27 09:25:05 +00:00
for ( c = 0 ; c < channels ; c ++ ) {
int co = ( channels > 8 ) ? c :
2011-12-29 21:37:05 +01:00
ff_vorbis_encoding_channel_layout_offsets [ channels - 1 ][ c ];
2012-08-23 13:47:09 -04:00
memcpy ( buffer [ c ], frame -> extended_data [ co ],
samples * sizeof ( * buffer [ c ]));
2005-12-22 01:10:11 +00:00
}
2012-02-29 00:02:55 -05:00
if (( ret = vorbis_analysis_wrote ( & s -> vd , samples )) < 0 ) {
av_log ( avctx , AV_LOG_ERROR , "error in vorbis_analysis_wrote() \n " );
2012-02-28 21:00:33 -05:00
return vorbis_error_to_averror ( ret );
2012-02-29 00:02:55 -05:00
}
2012-02-29 01:02:54 -05:00
if (( ret = ff_af_queue_add ( & s -> afq , frame ) < 0 ))
return ret ;
2008-10-15 07:29:37 +00:00
} else {
2012-02-28 18:51:04 -05:00
if ( ! s -> eof )
2012-02-29 00:02:55 -05:00
if (( ret = vorbis_analysis_wrote ( & s -> vd , 0 )) < 0 ) {
av_log ( avctx , AV_LOG_ERROR , "error in vorbis_analysis_wrote() \n " );
2012-02-28 21:00:33 -05:00
return vorbis_error_to_averror ( ret );
2012-02-29 00:02:55 -05:00
}
2012-02-28 18:51:04 -05:00
s -> eof = 1 ;
2008-10-15 07:29:37 +00:00
}
2002-09-01 18:07:56 +00:00
2012-02-28 18:51:04 -05:00
/* retrieve available packets from libvorbis */
2012-02-28 21:00:33 -05: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 18:07:56 +00:00
2012-02-28 18:51:04 -05:00
/* add any available packets to the output packet buffer */
2012-02-28 21:00:33 -05:00
while (( ret = vorbis_bitrate_flushpacket ( & s -> vd , & op )) == 1 ) {
2012-02-28 22:39:07 -05:00
if ( av_fifo_space ( s -> pkt_fifo ) < sizeof ( ogg_packet ) + op . bytes ) {
2012-02-29 00:02:55 -05:00
av_log ( avctx , AV_LOG_ERROR , "packet buffer is too small" );
return AVERROR_BUG ;
2010-07-11 06:59:21 +00:00
}
2012-02-28 22:39:07 -05: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 01:10:11 +00:00
}
2012-02-29 00:02:55 -05:00
if ( ret < 0 ) {
av_log ( avctx , AV_LOG_ERROR , "error getting available packets \n " );
2012-02-28 21:00:33 -05:00
break ;
2012-02-29 00:02:55 -05:00
}
2002-09-01 18:07:56 +00:00
}
2012-02-29 00:02:55 -05:00
if ( ret < 0 ) {
av_log ( avctx , AV_LOG_ERROR , "error getting available packets \n " );
2012-02-28 21:00:33 -05:00
return vorbis_error_to_averror ( ret );
2012-02-29 00:02:55 -05:00
}
2002-09-01 18:07:56 +00:00
2012-02-29 01:02:54 -05: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 );
if (( ret = ff_alloc_packet ( avpkt , op . bytes ))) {
av_log ( avctx , AV_LOG_ERROR , "Error getting output packet \n " );
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 06:59:21 +00:00
}
2012-02-29 01:02:54 -05:00
ff_af_queue_remove ( & s -> afq , duration , & avpkt -> pts , & avpkt -> duration );
2004-04-04 14:39:20 +00:00
}
2012-02-29 01:02:54 -05:00
* got_packet_ptr = 1 ;
return 0 ;
2002-09-01 18:07:56 +00:00
}
2011-01-25 21:40:11 +00:00
AVCodec ff_libvorbis_encoder = {
2011-09-23 21:11:15 +02:00
. name = "libvorbis" ,
. type = AVMEDIA_TYPE_AUDIO ,
2012-08-05 11:11:04 +02:00
. id = AV_CODEC_ID_VORBIS ,
2011-09-23 21:11:15 +02:00
. priv_data_size = sizeof ( OggVorbisContext ),
. init = oggvorbis_encode_init ,
2012-02-29 01:02:54 -05:00
. encode2 = oggvorbis_encode_frame ,
2011-09-23 21:11:15 +02:00
. close = oggvorbis_encode_close ,
. capabilities = CODEC_CAP_DELAY ,
2012-08-23 13:47:09 -04:00
. sample_fmts = ( const enum AVSampleFormat []) { AV_SAMPLE_FMT_FLTP ,
2012-02-28 18:51:04 -05:00
AV_SAMPLE_FMT_NONE },
2011-09-23 21:11:15 +02:00
. long_name = NULL_IF_CONFIG_SMALL ( "libvorbis Vorbis" ),
. priv_class = & class ,
2012-02-28 19:33:07 -05:00
. defaults = defaults ,
2011-09-23 21:11:15 +02:00
};