summaryrefslogtreecommitdiffstats
path: root/libhb
diff options
context:
space:
mode:
Diffstat (limited to 'libhb')
-rw-r--r--libhb/common.c22
-rw-r--r--libhb/common.h2
-rw-r--r--libhb/decavcodec.c42
-rw-r--r--libhb/work.c5
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 );
}