diff options
author | jstebbins <[email protected]> | 2011-06-07 21:27:02 +0000 |
---|---|---|
committer | jstebbins <[email protected]> | 2011-06-07 21:27:02 +0000 |
commit | d40287132815adc74a0d1444a1e7b76e89879f69 (patch) | |
tree | 00c95f36cbe47104a7ad40233c93bc588702251f /libhb | |
parent | e07dec1ec259a52a893642da14856e16085f3c36 (diff) |
libhb: add support for libav aac encoder (libhb only)
This generalizes the ac3 encoder to make it easy to add support
for any audio encoder that libav supports. Since ffaac is not quite
ready, the cli and gui does not expose ffaac yet.
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@4029 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'libhb')
-rw-r--r-- | libhb/common.c | 16 | ||||
-rw-r--r-- | libhb/common.h | 3 | ||||
-rw-r--r-- | libhb/encavcodecaudio.c (renamed from libhb/encac3.c) | 106 | ||||
-rw-r--r-- | libhb/hb.c | 7 | ||||
-rw-r--r-- | libhb/internal.h | 2 | ||||
-rw-r--r-- | libhb/muxmkv.c | 1 | ||||
-rw-r--r-- | libhb/muxmp4.c | 1 | ||||
-rw-r--r-- | libhb/work.c | 17 |
8 files changed, 118 insertions, 35 deletions
diff --git a/libhb/common.c b/libhb/common.c index 868cafbcb..cc4f5ec0c 100644 --- a/libhb/common.c +++ b/libhb/common.c @@ -222,6 +222,22 @@ void hb_get_audio_bitrate_limits(uint32_t codec, int samplerate, int mixdown, in } break; + case HB_ACODEC_FFAAC: + *low = 32 * channels; + if (samplerate > 24000) + { + *high = 160 * channels; + if (*high > 768) + *high = 768; + } + else + { + *high = 96 * channels; + if (*high > 480) + *high = 480; + } + break; + case HB_ACODEC_VORBIS: *high = channels * 80; if (samplerate > 24000) diff --git a/libhb/common.h b/libhb/common.h index 14af50d8a..ee3bc3b98 100644 --- a/libhb/common.h +++ b/libhb/common.h @@ -321,6 +321,7 @@ struct hb_job_s #define HB_ACODEC_FFMPEG 0x00008000 #define HB_ACODEC_CA_AAC 0x00010000 #define HB_ACODEC_CA_HAAC 0x00020000 +#define HB_ACODEC_FFAAC 0x00040000 #define HB_ACODEC_PASS_FLAG 0x40000000 #define HB_ACODEC_PASS_MASK (HB_ACODEC_AC3 | HB_ACODEC_DCA) #define HB_ACODEC_AC3_PASS (HB_ACODEC_AC3 | HB_ACODEC_PASS_FLAG) @@ -791,7 +792,7 @@ extern hb_work_object_t hb_encvorbis; extern hb_work_object_t hb_muxer; extern hb_work_object_t hb_encca_aac; extern hb_work_object_t hb_encca_haac; -extern hb_work_object_t hb_encac3; +extern hb_work_object_t hb_encavcodeca; #define FILTER_OK 0 #define FILTER_DELAY 1 diff --git a/libhb/encac3.c b/libhb/encavcodecaudio.c index d0c27f419..a295dc368 100644 --- a/libhb/encac3.c +++ b/libhb/encavcodecaudio.c @@ -1,4 +1,4 @@ -/* $Id: encac3.c,v 1.23 2005/10/13 23:47:06 titer Exp $ +/* $Id: encavcodeca.c,v 1.23 2005/10/13 23:47:06 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://handbrake.fr/>. @@ -7,6 +7,7 @@ #include "hb.h" #include "hbffmpeg.h" #include "downmix.h" +#include "libavcodec/audioconvert.h" struct hb_work_private_s { @@ -14,29 +15,27 @@ struct hb_work_private_s AVCodecContext * context; int out_discrete_channels; + int samples_per_frame; unsigned long input_samples; unsigned long output_bytes; hb_list_t * list; uint8_t * buf; }; -int encac3Init( hb_work_object_t *, hb_job_t * ); -int encac3Work( hb_work_object_t *, hb_buffer_t **, hb_buffer_t ** ); -void encac3Close( hb_work_object_t * ); +static int encavcodecaInit( hb_work_object_t *, hb_job_t * ); +static int encavcodecaWork( hb_work_object_t *, hb_buffer_t **, hb_buffer_t ** ); +static void encavcodecaClose( hb_work_object_t * ); -#define AC3_SAMPLES_PER_FRAME 1536 -#define AC3_MAX_CODED_FRAME_SIZE 3840 - -hb_work_object_t hb_encac3 = +hb_work_object_t hb_encavcodeca = { - WORK_ENCAC3, - "AC-3 encoder (libavcodec)", - encac3Init, - encac3Work, - encac3Close + WORK_ENCAVCODEC_AUDIO, + "AVCodec Audio encoder (libavcodec)", + encavcodecaInit, + encavcodecaWork, + encavcodecaClose }; -int encac3Init( hb_work_object_t * w, hb_job_t * job ) +static int encavcodecaInit( hb_work_object_t * w, hb_job_t * job ) { AVCodec * codec; AVCodecContext * context; @@ -48,20 +47,24 @@ int encac3Init( hb_work_object_t * w, hb_job_t * job ) pv->job = job; pv->out_discrete_channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown); - pv->input_samples = AC3_SAMPLES_PER_FRAME * pv->out_discrete_channels; - pv->output_bytes = AC3_MAX_CODED_FRAME_SIZE; - - pv->buf = malloc( pv->input_samples * sizeof( float ) ); - codec = avcodec_find_encoder( CODEC_ID_AC3 ); + codec = avcodec_find_encoder( w->codec_param ); if( !codec ) { - hb_log( "encac3Init: avcodec_find_encoder " + hb_log( "encavcodecaInit: avcodec_find_encoder " "failed" ); + return 1; } context = avcodec_alloc_context(); avcodec_get_context_defaults3(context, codec); + int ret = av_set_string3( context, "stereo_mode", "ms_off", 1, NULL ); + /* Let avutil sanity check the options for us*/ + if( ret == AVERROR(ENOENT) ) + hb_log( "avcodec options: Unknown option %s", "stereo_mode" ); + if( ret == AVERROR(EINVAL) ) + hb_log( "avcodec options: Bad argument %s=%s", "stereo_mode", "ms_off" ? "ms_off" : "(null)" ); + context->channel_layout = AV_CH_LAYOUT_STEREO; switch( audio->config.out.mixdown ) { @@ -80,23 +83,41 @@ int encac3Init( hb_work_object_t * w, hb_job_t * job ) break; default: - hb_log(" encac3Init: bad mixdown" ); + hb_log(" encavcodecaInit: bad mixdown" ); break; } context->bit_rate = audio->config.out.bitrate * 1000; context->sample_rate = audio->config.out.samplerate; context->channels = pv->out_discrete_channels; - context->sample_fmt = AV_SAMPLE_FMT_FLT; + // Try to set format to float. Fallback to whatever is supported. + hb_ff_set_sample_fmt( context, codec ); if( hb_avcodec_open( context, codec ) ) { - hb_log( "encac3Init: avcodec_open failed" ); + hb_log( "encavcodecaInit: avcodec_open failed" ); + return 1; } pv->context = context; + pv->samples_per_frame = context->frame_size; + pv->input_samples = pv->samples_per_frame * pv->out_discrete_channels; + + // Set a reasonable maximum output size + pv->output_bytes = context->frame_size * + (av_get_bits_per_sample_fmt(context->sample_fmt) / 8) * + context->channels; + + pv->buf = malloc( pv->input_samples * sizeof( float ) ); + pv->list = hb_list_init(); + if ( w->codec_param == CODEC_ID_AAC && context->extradata ) + { + memcpy( w->config->aac.bytes, context->extradata, context->extradata_size ); + w->config->aac.length = context->extradata_size; + } + return 0; } @@ -105,7 +126,7 @@ int encac3Init( hb_work_object_t * w, hb_job_t * job ) *********************************************************************** * **********************************************************************/ -void encac3Close( hb_work_object_t * w ) +static void encavcodecaClose( hb_work_object_t * w ) { hb_work_private_t * pv = w->private_data; @@ -113,7 +134,7 @@ void encac3Close( hb_work_object_t * w ) { if( pv->context ) { - hb_deep_log( 2, "encac3: closing libavcodec" ); + hb_deep_log( 2, "encavcodeca: closing libavcodec" ); if ( pv->context->codec ) avcodec_flush_buffers( pv->context ); hb_avcodec_close( pv->context ); @@ -176,7 +197,34 @@ static hb_buffer_t * Encode( hb_work_object_t * w ) break; } hb_layout_remap( map, &hb_smpte_chan_map, layout, - (float*)pv->buf, AC3_SAMPLES_PER_FRAME); + (float*)pv->buf, pv->samples_per_frame); + } + + // Do we need to convert our internal float format? + if ( pv->context->sample_fmt != AV_SAMPLE_FMT_FLT ) + { + int isamp, osamp; + AVAudioConvert *ctx; + + isamp = av_get_bits_per_sample_fmt( AV_SAMPLE_FMT_FLT ) / 8; + osamp = av_get_bits_per_sample_fmt( pv->context->sample_fmt ) / 8; + ctx = av_audio_convert_alloc( pv->context->sample_fmt, 1, + AV_SAMPLE_FMT_FLT, 1, + NULL, 0 ); + + // get output buffer size then malloc a buffer + //nsamples = out_size / isamp; + //buffer = av_malloc( nsamples * sizeof(hb_sample_t) ); + + // we're doing straight sample format conversion which + // behaves as if there were only one channel. + const void * const ibuf[6] = { pv->buf }; + void * const obuf[6] = { pv->buf }; + const int istride[6] = { isamp }; + const int ostride[6] = { osamp }; + + av_audio_convert( ctx, obuf, ostride, ibuf, istride, pv->input_samples ); + av_audio_convert_free( ctx ); } buf = hb_buffer_init( pv->output_bytes ); @@ -184,7 +232,7 @@ static hb_buffer_t * Encode( hb_work_object_t * w ) (short*)pv->buf ); buf->start = pts + 90000 * pos / pv->out_discrete_channels / sizeof( float ) / audio->config.out.samplerate; - buf->stop = buf->start + 90000 * AC3_SAMPLES_PER_FRAME / audio->config.out.samplerate; + buf->stop = buf->start + 90000 * pv->samples_per_frame / audio->config.out.samplerate; buf->frametype = HB_FRAME_AUDIO; @@ -195,7 +243,7 @@ static hb_buffer_t * Encode( hb_work_object_t * w ) } else if (buf->size < 0) { - hb_log( "encac3: avcodec_encode_audio failed" ); + hb_log( "encavcodeca: avcodec_encode_audio failed" ); hb_buffer_close( &buf ); return NULL; } @@ -208,7 +256,7 @@ static hb_buffer_t * Encode( hb_work_object_t * w ) *********************************************************************** * **********************************************************************/ -int encac3Work( hb_work_object_t * w, hb_buffer_t ** buf_in, +static int encavcodecaWork( hb_work_object_t * w, hb_buffer_t ** buf_in, hb_buffer_t ** buf_out ) { hb_work_private_t * pv = w->private_data; diff --git a/libhb/hb.c b/libhb/hb.c index a4761a867..1e3686cf2 100644 --- a/libhb/hb.c +++ b/libhb/hb.c @@ -262,6 +262,9 @@ void hb_ff_set_sample_fmt(AVCodecContext *context, AVCodec *codec) break; } } + if ( *fmt == -1 ) + context->sample_fmt = codec->sample_fmts[0]; + } } @@ -415,7 +418,7 @@ hb_handle_t * hb_init( int verbose, int update_check ) hb_register( &hb_encca_aac ); hb_register( &hb_encca_haac ); #endif - hb_register( &hb_encac3 ); + hb_register( &hb_encavcodeca ); return h; } @@ -517,7 +520,7 @@ hb_handle_t * hb_init_dl( int verbose, int update_check ) hb_register( &hb_encca_aac ); hb_register( &hb_encca_haac ); #endif - hb_register( &hb_encac3 ); + hb_register( &hb_encavcodeca ); return h; } diff --git a/libhb/internal.h b/libhb/internal.h index 700084e78..f92ce263a 100644 --- a/libhb/internal.h +++ b/libhb/internal.h @@ -360,7 +360,7 @@ enum WORK_ENCVORBIS, WORK_ENC_CA_AAC, WORK_ENC_CA_HAAC, - WORK_ENCAC3, + WORK_ENCAVCODEC_AUDIO, WORK_MUX }; diff --git a/libhb/muxmkv.c b/libhb/muxmkv.c index 7256843ff..654c51bc0 100644 --- a/libhb/muxmkv.c +++ b/libhb/muxmkv.c @@ -229,6 +229,7 @@ static int MKVInit( hb_mux_object_t * m ) } break; case HB_ACODEC_FAAC: + case HB_ACODEC_FFAAC: case HB_ACODEC_CA_AAC: case HB_ACODEC_CA_HAAC: track->codecPrivate = audio->priv.config.aac.bytes; diff --git a/libhb/muxmp4.c b/libhb/muxmp4.c index 3df70dc17..b9c7637e8 100644 --- a/libhb/muxmp4.c +++ b/libhb/muxmp4.c @@ -420,6 +420,7 @@ rate_found2: } } else if( audio->config.out.codec == HB_ACODEC_FAAC || + audio->config.out.codec == HB_ACODEC_FFAAC || audio->config.out.codec == HB_ACODEC_CA_AAC || audio->config.out.codec == HB_ACODEC_CA_HAAC ) { diff --git a/libhb/work.c b/libhb/work.c index f1db58b81..f0a81fa75 100644 --- a/libhb/work.c +++ b/libhb/work.c @@ -121,6 +121,7 @@ hb_work_object_t * hb_codec_decoder( int codec ) hb_work_object_t * hb_codec_encoder( int codec ) { + hb_work_object_t * w; switch( codec ) { case HB_ACODEC_FAAC: return hb_get_work( WORK_ENCFAAC ); @@ -128,7 +129,18 @@ hb_work_object_t * hb_codec_encoder( int codec ) case HB_ACODEC_VORBIS: return hb_get_work( WORK_ENCVORBIS ); case HB_ACODEC_CA_AAC: return hb_get_work( WORK_ENC_CA_AAC ); case HB_ACODEC_CA_HAAC:return hb_get_work( WORK_ENC_CA_HAAC ); - case HB_ACODEC_AC3: return hb_get_work( WORK_ENCAC3 ); + case HB_ACODEC_FFAAC: + { + w = hb_get_work( WORK_ENCAVCODEC_AUDIO ); + w->codec_param = CODEC_ID_AAC; + return w; + } + case HB_ACODEC_AC3: + { + w = hb_get_work( WORK_ENCAVCODEC_AUDIO ); + w->codec_param = CODEC_ID_AC3; + return w; + } } return NULL; } @@ -371,8 +383,9 @@ void hb_display_job_info( hb_job_t * job ) ( ( audio->config.out.codec == HB_ACODEC_LAME ) ? "lame" : ( ( audio->config.out.codec == HB_ACODEC_CA_AAC ) ? "ca_aac" : ( ( audio->config.out.codec == HB_ACODEC_CA_HAAC ) ? "ca_haac" : + ( ( audio->config.out.codec == HB_ACODEC_FFAAC ) ? "ffaac" : ( ( audio->config.out.codec == HB_ACODEC_AC3 ) ? "ffac3" : - "vorbis" ) ) ) ) ); + "vorbis" ) ) ) ) ) ); hb_log( " + bitrate: %d kbps, samplerate: %d Hz", audio->config.out.bitrate, audio->config.out.samplerate ); } } |