From patchwork Sat Feb 1 19:34:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: rcombs X-Patchwork-Id: 17648 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 7FECC44B358 for ; Sat, 1 Feb 2020 21:35:13 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 624AD68AEF8; Sat, 1 Feb 2020 21:35:13 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from so254-54.mailgun.net (so254-54.mailgun.net [198.61.254.54]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 7D2FB688035 for ; Sat, 1 Feb 2020 21:35:06 +0200 (EET) DKIM-Signature: a=rsa-sha256; v=1; c=relaxed/relaxed; d=rcombs.me; q=dns/txt; s=mx; t=1580585707; h=Content-Transfer-Encoding: MIME-Version: Message-Id: Date: Subject: To: From: Sender; bh=5PprHJLGwN3ovVIiHqMNpDXPvRQzD1UJ8BK1AbAe0+M=; b=d2AKlz3VTqRj4itHNYtkhTILvt+/sm9q9WiwkZNB2e5N+tDJLZmi3p/HmAVdI9kblJqGJ3nx 9JJ0wd4dRghofkIMyePjQrtyvK3uhOpRQSjEOUgjEYVUj1/lDwkFVJzXHJnIiobFZQ4YRUby kC4KMLlHywisIU4NfKDSxrCt8II= X-Mailgun-Sending-Ip: 198.61.254.54 X-Mailgun-Sid: WyJiZDU1MSIsICJmZm1wZWctZGV2ZWxAZmZtcGVnLm9yZyIsICJiMGJhIl0= Received: from MacBook-Pro.localdomain (Unknown [24.14.135.13]) by mxa.mailgun.org with ESMTP id 5e35d2e6.7f0ac5e17db0-smtp-out-n01; Sat, 01 Feb 2020 19:35:02 -0000 (UTC) From: rcombs To: ffmpeg-devel@ffmpeg.org Date: Sat, 1 Feb 2020 13:34:43 -0600 Message-Id: <20200201193443.22419-1-rcombs@rcombs.me> X-Mailer: git-send-email 2.24.1 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH] lavc/ac3dec: disable DRC by default X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" This issue has been argued before, with the status quo being preserved under the logic that the spec says this parameter is supposed to default to 1, and that we should follow the spec. The spec was misguided, and thus so was blindly following it. The (E-)AC3 DRC architecture is a clever optimization: the (relatively) heavy lifting of analyzing the audio data and calculating the per-block gain needed is offloaded to the encoder, so that the player only needs to apply the gain coefficients (at the desired scale) to get the DRC effect. In theory, this seems like an efficient way to reduce the computational complexity of playback. In practice, this isn't actually the case. Actual (E-)AC3 is not guaranteed to have useful DRC metadata at all. For instance, ffmpeg's encoder has never supported generating it. This means that a user who wants DRC can't merely use the internal filter for (E-)AC3 and an external one for other codecs; they have to use an external filter at al times! They could also apply the internal filter, but it's hard to see what benefit this would give. I've also seen it argued that (E-)AC3 DRC does a better job of reproducing the intent of the audio mastering engineer than playback-time DRC can. I don't believe this argument is credible either. The official encoder does support passing in custom gain values, but it doesn't appear that this capability is frequently used. I'm not aware of any tooling that actually passes custom data into the encoder's loudness parameters, and Dolby's first-party GUI tools don't appear to support doing so. Dolby's own tools expose the parameters available in the encoder itself, which comprise a set of 5 presets with no customizability: "Film Standard", "Film Light", "Music Standard", "Music Light", and "Speech", along with the null profile. These profiles are documented (minus their time constants) in this PDF on the Dolby website: https://www.dolby.com/us/en/technologies/a-guide-to-dolby-metadata.pdf These are not advanced filters; they don't provide any complex control to the content producer, who can't even tune the details or _know_ the time constants. Even if the mastering engineer did want to customize the DRC with some custom tool, in most cases I don't think they'd have the ability to do so because they don't have access to the point in the pipeline where audio encoding occurs. In TV, audio is often encoded live rather than streaming a pre-compressed bitstream. In web streaming, masters are usually delivered with uncompressed PCM audio and no loudness metadata, and encoded using stock configurations. Film for DVD or Blu-Ray is the only plausible case, but again, I'm not aware of any widely-used tooling for this with any more configurability than Dolby's. Additional context: the AudioToolbox (E-)AC3 decoder (which is Dolby's) seems not to apply DRC; you can see this by comparing the output of ffmpeg's decoder with drc_scale set to 0 and 1 with the output of the (e)ac3_at decoder. So to summarize: - (E-)AC3 DRC is designed as an optimization for the decoder - There's no inherent reason (E-)AC3 _requires_ DRC for playback more than any other codec - Due to inconsistent encoding, it can't be relied upon - There's no reason to believe it's better than decode-side DRC when it works - It's not universally applied by other software I think this makes a compelling case to stop applying (E-)AC3 DRC by default. The user can enable it on their own if they prefer, but I believe having it off by default will improve the apparent quality of (E-)AC3 playback for the vast majority of ffmpeg users, and improve the consistency between (E-)AC3 playback and playback of any other codec. Thus, this patch. --- libavcodec/ac3dec_fixed.c | 2 +- libavcodec/ac3dec_float.c | 2 +- tests/fate/ac3.mak | 32 ++++++++++++++++---------------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/libavcodec/ac3dec_fixed.c b/libavcodec/ac3dec_fixed.c index bd66175d50..312616edfd 100644 --- a/libavcodec/ac3dec_fixed.c +++ b/libavcodec/ac3dec_fixed.c @@ -169,7 +169,7 @@ static void ac3_downmix_c_fixed16(int16_t **samples, int16_t **matrix, static const AVOption options[] = { { "cons_noisegen", "enable consistent noise generation", OFFSET(consistent_noise_generation), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, PAR }, - { "drc_scale", "percentage of dynamic range compression to apply", OFFSET(drc_scale), AV_OPT_TYPE_FLOAT, {.dbl = 1.0}, 0.0, 6.0, PAR }, + { "drc_scale", "percentage of dynamic range compression to apply", OFFSET(drc_scale), AV_OPT_TYPE_FLOAT, {.dbl = 0.0}, 0.0, 6.0, PAR }, { "heavy_compr", "enable heavy dynamic range compression", OFFSET(heavy_compression), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, PAR }, { NULL}, }; diff --git a/libavcodec/ac3dec_float.c b/libavcodec/ac3dec_float.c index b85a4ce336..69bd47aa6a 100644 --- a/libavcodec/ac3dec_float.c +++ b/libavcodec/ac3dec_float.c @@ -33,7 +33,7 @@ static const AVOption options[] = { { "cons_noisegen", "enable consistent noise generation", OFFSET(consistent_noise_generation), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, PAR }, - { "drc_scale", "percentage of dynamic range compression to apply", OFFSET(drc_scale), AV_OPT_TYPE_FLOAT, {.dbl = 1.0}, 0.0, 6.0, PAR }, + { "drc_scale", "percentage of dynamic range compression to apply", OFFSET(drc_scale), AV_OPT_TYPE_FLOAT, {.dbl = 0.0}, 0.0, 6.0, PAR }, { "heavy_compr", "enable heavy dynamic range compression", OFFSET(heavy_compression), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, PAR }, { "target_level", "target level in -dBFS (0 not applied)", OFFSET(target_level), AV_OPT_TYPE_INT, {.i64 = 0 }, -31, 0, PAR }, diff --git a/tests/fate/ac3.mak b/tests/fate/ac3.mak index bb02d3829d..c810b53ad2 100644 --- a/tests/fate/ac3.mak +++ b/tests/fate/ac3.mak @@ -1,67 +1,67 @@ FATE_AC3 += fate-ac3-2.0 -fate-ac3-2.0: CMD = pcm -i $(TARGET_SAMPLES)/ac3/monsters_inc_2.0_192_small.ac3 +fate-ac3-2.0: CMD = pcm -drc_scale 1 -i $(TARGET_SAMPLES)/ac3/monsters_inc_2.0_192_small.ac3 fate-ac3-2.0: REF = $(SAMPLES)/ac3/monsters_inc_2.0_192_small_v2.pcm FATE_AC3 += fate-ac3-4.0 -fate-ac3-4.0: CMD = pcm -i $(TARGET_SAMPLES)/ac3/millers_crossing_4.0.ac3 +fate-ac3-4.0: CMD = pcm -drc_scale 1 -i $(TARGET_SAMPLES)/ac3/millers_crossing_4.0.ac3 fate-ac3-4.0: REF = $(SAMPLES)/ac3/millers_crossing_4.0_v2.pcm #request_channel_layout 4 -> front channel FATE_AC3 += fate-ac3-4.0-downmix-mono -fate-ac3-4.0-downmix-mono: CMD = pcm -request_channel_layout 4 -i $(TARGET_SAMPLES)/ac3/millers_crossing_4.0.ac3 +fate-ac3-4.0-downmix-mono: CMD = pcm -drc_scale 1 -request_channel_layout 4 -i $(TARGET_SAMPLES)/ac3/millers_crossing_4.0.ac3 fate-ac3-4.0-downmix-mono: REF = $(SAMPLES)/ac3/millers_crossing_4.0_mono_v2.pcm #request_channel_layout 3 -> left channel + right channel FATE_AC3 += fate-ac3-4.0-downmix-stereo -fate-ac3-4.0-downmix-stereo: CMD = pcm -request_channel_layout 3 -i $(TARGET_SAMPLES)/ac3/millers_crossing_4.0.ac3 +fate-ac3-4.0-downmix-stereo: CMD = pcm -drc_scale 1 -request_channel_layout 3 -i $(TARGET_SAMPLES)/ac3/millers_crossing_4.0.ac3 fate-ac3-4.0-downmix-stereo: REF = $(SAMPLES)/ac3/millers_crossing_4.0_stereo_v2.pcm FATE_AC3 += fate-ac3-5.1 -fate-ac3-5.1: CMD = pcm -i $(TARGET_SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3 +fate-ac3-5.1: CMD = pcm -drc_scale 1 -i $(TARGET_SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3 fate-ac3-5.1: REF = $(SAMPLES)/ac3/monsters_inc_5.1_448_small_v2.pcm FATE_AC3 += fate-ac3-5.1-downmix-mono -fate-ac3-5.1-downmix-mono: CMD = pcm -request_channel_layout 4 -i $(TARGET_SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3 +fate-ac3-5.1-downmix-mono: CMD = pcm -drc_scale 1 -request_channel_layout 4 -i $(TARGET_SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3 fate-ac3-5.1-downmix-mono: REF = $(SAMPLES)/ac3/monsters_inc_5.1_448_small_mono_v2.pcm FATE_AC3 += fate-ac3-5.1-downmix-stereo -fate-ac3-5.1-downmix-stereo: CMD = pcm -request_channel_layout 3 -i $(TARGET_SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3 +fate-ac3-5.1-downmix-stereo: CMD = pcm -drc_scale 1 -request_channel_layout 3 -i $(TARGET_SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3 fate-ac3-5.1-downmix-stereo: REF = $(SAMPLES)/ac3/monsters_inc_5.1_448_small_stereo_v2.pcm FATE_AC3 += fate-ac3-fixed-2.0 -fate-ac3-fixed-2.0: CMD = pcm -c ac3_fixed -i $(TARGET_SAMPLES)/ac3/monsters_inc_2.0_192_small.ac3 +fate-ac3-fixed-2.0: CMD = pcm -drc_scale 1 -c ac3_fixed -i $(TARGET_SAMPLES)/ac3/monsters_inc_2.0_192_small.ac3 fate-ac3-fixed-2.0: REF = $(SAMPLES)/ac3/monsters_inc_2.0_192_small_v2.pcm FATE_AC3 += fate-ac3-fixed-4.0-downmix-mono -fate-ac3-fixed-4.0-downmix-mono: CMD = pcm -c ac3_fixed -request_channel_layout 4 -i $(TARGET_SAMPLES)/ac3/millers_crossing_4.0.ac3 +fate-ac3-fixed-4.0-downmix-mono: CMD = pcm -drc_scale 1 -c ac3_fixed -request_channel_layout 4 -i $(TARGET_SAMPLES)/ac3/millers_crossing_4.0.ac3 fate-ac3-fixed-4.0-downmix-mono: REF = $(SAMPLES)/ac3/millers_crossing_4.0_mono_v2.pcm FATE_AC3 += fate-ac3-fixed-5.1-downmix-mono -fate-ac3-fixed-5.1-downmix-mono: CMD = pcm -c ac3_fixed -request_channel_layout 4 -i $(TARGET_SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3 +fate-ac3-fixed-5.1-downmix-mono: CMD = pcm -drc_scale 1 -c ac3_fixed -request_channel_layout 4 -i $(TARGET_SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3 fate-ac3-fixed-5.1-downmix-mono: REF = $(SAMPLES)/ac3/monsters_inc_5.1_448_small_mono_v2.pcm FATE_AC3 += fate-ac3-fixed-5.1-downmix-stereo -fate-ac3-fixed-5.1-downmix-stereo: CMD = pcm -c ac3_fixed -request_channel_layout 3 -i $(TARGET_SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3 +fate-ac3-fixed-5.1-downmix-stereo: CMD = pcm -drc_scale 1 -c ac3_fixed -request_channel_layout 3 -i $(TARGET_SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3 fate-ac3-fixed-5.1-downmix-stereo: REF = $(SAMPLES)/ac3/monsters_inc_5.1_448_small_stereo_v2.pcm FATE_EAC3 += fate-eac3-1 -fate-eac3-1: CMD = pcm -i $(TARGET_SAMPLES)/eac3/csi_miami_5.1_256_spx_small.eac3 +fate-eac3-1: CMD = pcm -drc_scale 1 -i $(TARGET_SAMPLES)/eac3/csi_miami_5.1_256_spx_small.eac3 fate-eac3-1: REF = $(SAMPLES)/eac3/csi_miami_5.1_256_spx_small_v2.pcm FATE_EAC3 += fate-eac3-2 -fate-eac3-2: CMD = pcm -i $(TARGET_SAMPLES)/eac3/csi_miami_stereo_128_spx_small.eac3 +fate-eac3-2: CMD = pcm -drc_scale 1 -i $(TARGET_SAMPLES)/eac3/csi_miami_stereo_128_spx_small.eac3 fate-eac3-2: REF = $(SAMPLES)/eac3/csi_miami_stereo_128_spx_small_v2.pcm FATE_EAC3 += fate-eac3-3 -fate-eac3-3: CMD = pcm -i $(TARGET_SAMPLES)/eac3/matrix2_commentary1_stereo_192_small.eac3 +fate-eac3-3: CMD = pcm -drc_scale 1 -i $(TARGET_SAMPLES)/eac3/matrix2_commentary1_stereo_192_small.eac3 fate-eac3-3: REF = $(SAMPLES)/eac3/matrix2_commentary1_stereo_192_small_v2.pcm FATE_EAC3 += fate-eac3-4 -fate-eac3-4: CMD = pcm -i $(TARGET_SAMPLES)/eac3/serenity_english_5.1_1536_small.eac3 +fate-eac3-4: CMD = pcm -drc_scale 1 -i $(TARGET_SAMPLES)/eac3/serenity_english_5.1_1536_small.eac3 fate-eac3-4: REF = $(SAMPLES)/eac3/serenity_english_5.1_1536_small_v2.pcm FATE_EAC3 += fate-eac3-5 -fate-eac3-5: CMD = pcm -i $(TARGET_SAMPLES)/eac3/the_great_wall_7.1.eac3 +fate-eac3-5: CMD = pcm -drc_scale 1 -i $(TARGET_SAMPLES)/eac3/the_great_wall_7.1.eac3 fate-eac3-5: REF = $(SAMPLES)/eac3/the_great_wall_7.1.pcm $(FATE_AC3) $(FATE_EAC3): CMP = oneoff