summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--contrib/ffmpeg/A06-mix-normalization.patch39
-rw-r--r--libhb/audio_resample.c21
-rw-r--r--libhb/audio_resample.h4
-rw-r--r--libhb/common.c3
-rw-r--r--libhb/common.h1
-rw-r--r--libhb/decavcodec.c3
-rw-r--r--libhb/declpcm.c3
-rw-r--r--libhb/encavcodecaudio.c2
-rw-r--r--test/test.c48
9 files changed, 112 insertions, 12 deletions
diff --git a/contrib/ffmpeg/A06-mix-normalization.patch b/contrib/ffmpeg/A06-mix-normalization.patch
new file mode 100644
index 000000000..06fb2754c
--- /dev/null
+++ b/contrib/ffmpeg/A06-mix-normalization.patch
@@ -0,0 +1,39 @@
+diff --git a/libavresample/audio_mix.c b/libavresample/audio_mix.c
+index 2c2a356..25f9f98 100644
+--- a/libavresample/audio_mix.c
++++ b/libavresample/audio_mix.c
+@@ -327,7 +327,9 @@ int ff_audio_mix_init(AVAudioResampleContext *avr)
+ avr->out_channel_layout,
+ avr->center_mix_level,
+ avr->surround_mix_level,
+- avr->lfe_mix_level, 1, matrix_dbl,
++ avr->lfe_mix_level,
++ avr->normalize_mix_level,
++ matrix_dbl,
+ avr->in_channels,
+ avr->matrix_encoding);
+ if (ret < 0) {
+diff --git a/libavresample/internal.h b/libavresample/internal.h
+index 7b7648f..006b6fd 100644
+--- a/libavresample/internal.h
++++ b/libavresample/internal.h
+@@ -45,6 +45,7 @@ struct AVAudioResampleContext {
+ double center_mix_level; /**< center mix level */
+ double surround_mix_level; /**< surround mix level */
+ double lfe_mix_level; /**< lfe mix level */
++ int normalize_mix_level; /**< enable mix level normalization */
+ int force_resampling; /**< force resampling */
+ int filter_size; /**< length of each FIR filter in the resampling filterbank relative to the cutoff frequency */
+ int phase_shift; /**< log2 of the number of entries in the resampling polyphase filterbank */
+diff --git a/libavresample/options.c b/libavresample/options.c
+index 02e1f86..e7e0c27 100644
+--- a/libavresample/options.c
++++ b/libavresample/options.c
+@@ -47,6 +47,7 @@ static const AVOption options[] = {
+ { "center_mix_level", "Center Mix Level", OFFSET(center_mix_level), AV_OPT_TYPE_DOUBLE, { M_SQRT1_2 }, -32.0, 32.0, PARAM },
+ { "surround_mix_level", "Surround Mix Level", OFFSET(surround_mix_level), AV_OPT_TYPE_DOUBLE, { M_SQRT1_2 }, -32.0, 32.0, PARAM },
+ { "lfe_mix_level", "LFE Mix Level", OFFSET(lfe_mix_level), AV_OPT_TYPE_DOUBLE, { 0.0 }, -32.0, 32.0, PARAM },
++ { "normalize_mix_level", "Normalize Mix Level", OFFSET(normalize_mix_level), AV_OPT_TYPE_INT, { 1 }, 0, 1, PARAM },
+ { "force_resampling", "Force Resampling", OFFSET(force_resampling), AV_OPT_TYPE_INT, { 0 }, 0, 1, PARAM },
+ { "filter_size", "Resampling Filter Size", OFFSET(filter_size), AV_OPT_TYPE_INT, { 16 }, 0, 32, /* ??? */ PARAM },
+ { "phase_shift", "Resampling Phase Shift", OFFSET(phase_shift), AV_OPT_TYPE_INT, { 10 }, 0, 30, /* ??? */ PARAM },
diff --git a/libhb/audio_resample.c b/libhb/audio_resample.c
index 3f67da87c..ea09b38a2 100644
--- a/libhb/audio_resample.c
+++ b/libhb/audio_resample.c
@@ -13,20 +13,23 @@
hb_audio_resample_t* hb_audio_resample_init(enum AVSampleFormat output_sample_fmt,
uint64_t output_channel_layout,
- enum AVMatrixEncoding matrix_encoding)
+ enum AVMatrixEncoding matrix_encoding,
+ int normalize_mix_level)
{
hb_audio_resample_t *resample = malloc(sizeof(hb_audio_resample_t));
if (resample == NULL)
return NULL;
- resample->out.sample_fmt = output_sample_fmt;
- resample->out.sample_size = av_get_bytes_per_sample(output_sample_fmt);
- resample->out.channel_layout = output_channel_layout;
- resample->out.channels =
+ resample->out.sample_fmt = output_sample_fmt;
+ resample->out.sample_size =
+ av_get_bytes_per_sample(output_sample_fmt);
+ resample->out.channel_layout = output_channel_layout;
+ resample->out.channels =
av_get_channel_layout_nb_channels(output_channel_layout);
- resample->out.matrix_encoding = matrix_encoding;
- resample->resample_needed = 0;
- resample->avresample = NULL;
+ resample->out.matrix_encoding = matrix_encoding;
+ resample->out.normalize_mix_level = normalize_mix_level;
+ resample->resample_needed = 0;
+ resample->avresample = NULL;
return resample;
}
@@ -72,6 +75,8 @@ int hb_audio_resample_update(hb_audio_resample_t *resample,
resample->out.channel_layout, 0);
av_opt_set_int(resample->avresample, "matrix_encoding",
resample->out.matrix_encoding, 0);
+ av_opt_set_int(resample->avresample, "normalize_mix_level",
+ resample->out.normalize_mix_level, 0);
}
else if (resample_changed)
{
diff --git a/libhb/audio_resample.h b/libhb/audio_resample.h
index 5982905e6..4b1586e73 100644
--- a/libhb/audio_resample.h
+++ b/libhb/audio_resample.h
@@ -39,6 +39,7 @@ typedef struct
int channels;
int linesize;
int sample_size;
+ int normalize_mix_level;
uint64_t channel_layout;
enum AVSampleFormat sample_fmt;
enum AVMatrixEncoding matrix_encoding;
@@ -52,7 +53,8 @@ typedef struct
*/
hb_audio_resample_t* hb_audio_resample_init(enum AVSampleFormat output_sample_fmt,
uint64_t output_channel_layout,
- enum AVMatrixEncoding matrix_encoding);
+ enum AVMatrixEncoding matrix_encoding,
+ int normalize_mix_level);
/* Update an hb_audio_resample_t, setting the input sample characteristics.
*
diff --git a/libhb/common.c b/libhb/common.c
index 13a2e1d95..9ff9f44a3 100644
--- a/libhb/common.c
+++ b/libhb/common.c
@@ -1637,6 +1637,7 @@ void hb_audio_config_init(hb_audio_config_t * audiocfg)
audiocfg->out.mixdown = HB_INVALID_AMIXDOWN;
audiocfg->out.dynamic_range_compression = 0;
audiocfg->out.gain = 0;
+ audiocfg->out.normalize_mix_level = 0;
audiocfg->out.name = NULL;
}
@@ -1684,6 +1685,7 @@ int hb_audio_add(const hb_job_t * job, const hb_audio_config_t * audiocfg)
audio->config.out.mixdown = HB_AMIXDOWN_NONE;
audio->config.out.dynamic_range_compression = 0;
audio->config.out.gain = 0;
+ audio->config.out.normalize_mix_level = 0;
audio->config.out.compression_level = -1;
audio->config.out.quality = HB_INVALID_AUDIO_QUALITY;
}
@@ -1698,6 +1700,7 @@ int hb_audio_add(const hb_job_t * job, const hb_audio_config_t * audiocfg)
audio->config.out.dynamic_range_compression = audiocfg->out.dynamic_range_compression;
audio->config.out.mixdown = audiocfg->out.mixdown;
audio->config.out.gain = audiocfg->out.gain;
+ audio->config.out.normalize_mix_level = audiocfg->out.normalize_mix_level;
}
if (audiocfg->out.name && *audiocfg->out.name)
{
diff --git a/libhb/common.h b/libhb/common.h
index 5b2fc08fa..1650f8002 100644
--- a/libhb/common.h
+++ b/libhb/common.h
@@ -452,6 +452,7 @@ struct hb_audio_config_s
float compression_level; /* Output compression level (encoder-specific) */
double dynamic_range_compression; /* Amount of DRC applied to this track */
double gain; /* Gain (in dB), negative is quieter */
+ int normalize_mix_level; /* mix level normalization (boolean) */
char * name; /* Output track name */
} out;
diff --git a/libhb/decavcodec.c b/libhb/decavcodec.c
index 17f814d61..934f7611e 100644
--- a/libhb/decavcodec.c
+++ b/libhb/decavcodec.c
@@ -192,7 +192,8 @@ static int decavcodecaInit( hb_work_object_t * w, hb_job_t * job )
int mode;
uint64_t layout = hb_ff_mixdown_xlat(w->audio->config.out.mixdown,
&mode);
- pv->resample = hb_audio_resample_init(AV_SAMPLE_FMT_FLT, layout, mode);
+ pv->resample = hb_audio_resample_init(AV_SAMPLE_FMT_FLT, layout, mode,
+ w->audio->config.out.normalize_mix_level);
if (pv->resample == NULL)
{
hb_error("decavcodecaInit: hb_audio_resample_init() failed");
diff --git a/libhb/declpcm.c b/libhb/declpcm.c
index e48bf5db7..0d4e449d1 100644
--- a/libhb/declpcm.c
+++ b/libhb/declpcm.c
@@ -164,7 +164,8 @@ static int declpcmInit( hb_work_object_t * w, hb_job_t * job )
int mode;
uint64_t layout = hb_ff_mixdown_xlat(w->audio->config.out.mixdown, &mode);
- pv->resample = hb_audio_resample_init(AV_SAMPLE_FMT_FLT, layout, mode);
+ pv->resample = hb_audio_resample_init(AV_SAMPLE_FMT_FLT, layout, mode,
+ w->audio->config.out.normalize_mix_level);
if (pv->resample == NULL)
{
hb_error("declpcmInit: hb_audio_resample_init() failed");
diff --git a/libhb/encavcodecaudio.c b/libhb/encavcodecaudio.c
index 28eb0d9ae..ef5297cca 100644
--- a/libhb/encavcodecaudio.c
+++ b/libhb/encavcodecaudio.c
@@ -119,7 +119,7 @@ static int encavcodecaInit(hb_work_object_t *w, hb_job_t *job)
// sample_fmt conversion
pv->resample = hb_audio_resample_init(context->sample_fmt,
context->channel_layout,
- AV_MATRIX_ENCODING_NONE);
+ AV_MATRIX_ENCODING_NONE, 0);
if (hb_audio_resample_update(pv->resample, AV_SAMPLE_FMT_FLT,
context->channel_layout, context->channels))
{
diff --git a/test/test.c b/test/test.c
index 5d61b579c..b59534d44 100644
--- a/test/test.c
+++ b/test/test.c
@@ -71,6 +71,7 @@ static int allowed_audio_copy = -1;
static char * mixdowns = NULL;
static char * dynamic_range_compression = NULL;
static char * audio_gain = NULL;
+static char ** normalize_mix_level = NULL;
static char * atracks = NULL;
static char * arates = NULL;
static char ** abitrates = NULL;
@@ -2096,6 +2097,41 @@ static int HandleEvents( hb_handle_t * h )
}
/* Audio Gain */
+ /* Audio Mix Normalization */
+ i = 0;
+ int norm = 0;
+ if( normalize_mix_level )
+ {
+ for ( i = 0; normalize_mix_level[i] != NULL && i < num_audio_tracks; i++ )
+ {
+ char * token = normalize_mix_level[i];
+ norm = atoi(token);
+ audio = hb_list_audio_config_item(job->list_audio, i);
+
+ if( audio != NULL )
+ {
+ audio->out.normalize_mix_level = norm;
+ }
+ else
+ {
+ fprintf(stderr, "Ignoring normalization %d, no audio tracks\n", norm);
+ }
+ }
+ }
+ if (i < num_audio_tracks && i == 1)
+ {
+ /* We have fewer inputs than audio tracks,
+ * and we only have one input, use
+ * that for all tracks.
+ */
+ for (; i < num_audio_tracks; i++)
+ {
+ audio = hb_list_audio_config_item(job->list_audio, i);
+ audio->out.normalize_mix_level = norm;
+ }
+ }
+ /* Audio Mix Normalization */
+
/* Audio Track Names */
if ( anames )
{
@@ -2883,6 +2919,10 @@ static void ShowHelp()
" Separated by commas for more than one audio track.\n"
" (mono/stereo/dpl1/dpl2/6ch, default: up to 6ch for ac3,\n"
" up to dpl2 for other encoders)\n"
+ " --normalize-mix Normalize audio mix levels to prevent clipping.\n"
+ " <string> Separated by commas for more than one audio track.\n"
+ " 0 = Disable Normalization (default)\n"
+ " 1 = Enable Normalization\n"
" -R, --arate Set audio samplerate(s) (" );
for( i = 0; i < hb_audio_rates_count; i++ )
{
@@ -3186,6 +3226,7 @@ static int ParseOptions( int argc, char ** argv )
#define X264_PRESET 284
#define X264_TUNE 285
#define H264_LEVEL 286
+ #define NORMALIZE_MIX 287
for( ;; )
{
@@ -3212,6 +3253,7 @@ static int ParseOptions( int argc, char ** argv )
{ "markers", optional_argument, NULL, 'm' },
{ "audio", required_argument, NULL, 'a' },
{ "mixdown", required_argument, NULL, '6' },
+ { "normalize-mix", required_argument, NULL, NORMALIZE_MIX },
{ "drc", required_argument, NULL, 'D' },
{ "gain", required_argument, NULL, AUDIO_GAIN },
{ "subtitle", required_argument, NULL, 's' },
@@ -3430,6 +3472,12 @@ static int ParseOptions( int argc, char ** argv )
audio_gain = strdup( optarg );
}
break;
+ case NORMALIZE_MIX:
+ if( optarg != NULL )
+ {
+ normalize_mix_level = str_split( optarg, ',' );
+ }
+ break;
case 's':
subtracks = str_split( optarg, ',' );
break;