diff options
-rw-r--r-- | contrib/ffmpeg/module.defs | 1 | ||||
-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 |
9 files changed, 119 insertions, 35 deletions
diff --git a/contrib/ffmpeg/module.defs b/contrib/ffmpeg/module.defs index 243b314ef..8572bae2f 100644 --- a/contrib/ffmpeg/module.defs +++ b/contrib/ffmpeg/module.defs @@ -19,6 +19,7 @@ FFMPEG.CONFIGURE.extra = \ --disable-dxva2 \ --enable-bzlib \ --enable-encoder=ac3 \ + --enable-encoder=aac \ --enable-encoder=mpeg4 \ --enable-encoder=mpeg2video \ --enable-encoder=snow \ 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 ); } } |