diff options
Diffstat (limited to 'libhb')
-rw-r--r-- | libhb/common.c | 22 | ||||
-rw-r--r-- | libhb/common.h | 2 | ||||
-rw-r--r-- | libhb/decavcodec.c | 42 | ||||
-rw-r--r-- | libhb/work.c | 5 |
4 files changed, 70 insertions, 1 deletions
diff --git a/libhb/common.c b/libhb/common.c index a0e6b7a58..813ece48e 100644 --- a/libhb/common.c +++ b/libhb/common.c @@ -3709,6 +3709,28 @@ int hb_subtitle_can_pass( int source, int mux ) } } +int hb_audio_can_apply_drc(uint32_t codec, uint32_t codec_param, int encoder) +{ + if (encoder & HB_ACODEC_PASS_FLAG) + { + // can't apply DRC to passthrough audio + return 0; + } + else if (codec & HB_ACODEC_FF_MASK) + { + return (codec_param == AV_CODEC_ID_AC3 || + codec_param == AV_CODEC_ID_EAC3); + } + else if (codec == HB_ACODEC_AC3) + { + return 1; + } + else + { + return 0; + } +} + /********************************************************************** * hb_metadata_init ********************************************************************** diff --git a/libhb/common.h b/libhb/common.h index 613338b35..cf037e579 100644 --- a/libhb/common.h +++ b/libhb/common.h @@ -161,6 +161,8 @@ int hb_subtitle_can_force( int source ); int hb_subtitle_can_burn( int source ); int hb_subtitle_can_pass( int source, int mux ); +int hb_audio_can_apply_drc(uint32_t codec, uint32_t codec_param, int encoder); + hb_attachment_t *hb_attachment_copy(const hb_attachment_t *src); hb_list_t *hb_attachment_list_copy(const hb_list_t *src); diff --git a/libhb/decavcodec.c b/libhb/decavcodec.c index 5a4b0513c..1e760583b 100644 --- a/libhb/decavcodec.c +++ b/libhb/decavcodec.c @@ -360,12 +360,54 @@ static int decavcodecaInit( hb_work_object_t * w, hb_job_t * job ) AVDictionary * av_opts = NULL; av_dict_set( &av_opts, "refcounted_frames", "1", 0 ); + // Dynamic Range Compression + if (w->audio->config.out.dynamic_range_compression >= 0.0f && + hb_audio_can_apply_drc(w->audio->config.in.codec, + w->audio->config.in.codec_param, 0)) + { + float drc_scale_max = 1.0f; + /* + * avcodec_open will fail if the value for any of the options is out of + * range, so assume a conservative maximum of 1 and try to determine the + * option's actual upper limit. + */ + if (codec != NULL && codec->priv_class != NULL) + { + const AVOption *opt; + opt = av_opt_find2((void*)&codec->priv_class, "drc_scale", NULL, + AV_OPT_FLAG_DECODING_PARAM|AV_OPT_FLAG_AUDIO_PARAM, + AV_OPT_SEARCH_FAKE_OBJ, NULL); + if (opt != NULL) + { + drc_scale_max = opt->max; + } + } + if (w->audio->config.out.dynamic_range_compression > drc_scale_max) + { + hb_log("decavcodecaInit: track %d, sanitizing out-of-range DRC %.2f to %.2f", + w->audio->config.out.track, + w->audio->config.out.dynamic_range_compression, drc_scale_max); + w->audio->config.out.dynamic_range_compression = drc_scale_max; + } + + char drc_scale[5]; // "?.??\n" + snprintf(drc_scale, sizeof(drc_scale), "%.2f", + w->audio->config.out.dynamic_range_compression); + av_dict_set(&av_opts, "drc_scale", drc_scale, 0); + } + if (hb_avcodec_open(pv->context, codec, &av_opts, 0)) { av_dict_free( &av_opts ); hb_log("decavcodecaInit: avcodec_open failed"); return 1; } + // avcodec_open populates av_opts with the things it didn't recognize. + AVDictionaryEntry *t = NULL; + while ((t = av_dict_get(av_opts, "", t, AV_DICT_IGNORE_SUFFIX)) != NULL) + { + hb_log("decavcodecaInit: unknown option '%s'", t->key); + } av_dict_free( &av_opts ); pv->frame = av_frame_alloc(); diff --git a/libhb/work.c b/libhb/work.c index 05f76d46e..abdf19f4f 100644 --- a/libhb/work.c +++ b/libhb/work.c @@ -452,7 +452,10 @@ void hb_display_job_info(hb_job_t *job) { hb_log( " + gain: %.fdB", audio->config.out.gain ); } - if( ( audio->config.out.dynamic_range_compression != 0.0 ) && ( audio->config.in.codec == HB_ACODEC_AC3 ) ) + if (audio->config.out.dynamic_range_compression > 0.0f && + hb_audio_can_apply_drc(audio->config.in.codec, + audio->config.in.codec_param, + audio->config.out.codec)) { hb_log( " + dynamic range compression: %f", audio->config.out.dynamic_range_compression ); } |