mirror of
https://github.com/electron/electron.git
synced 2026-04-10 03:01:51 -04:00
chore: cherry-pick 3910c9f5cde6 from chromium (#28094)
* chore: cherry-pick 3910c9f5cde6 from chromium * update patches Co-authored-by: Electron Bot <electron@github.com>
This commit is contained in:
@@ -152,3 +152,4 @@ cherry-pick-7e0e52df283c.patch
|
||||
cherry-pick-dea071d8b30f.patch
|
||||
cherry-pick-a4faa754a9ef.patch
|
||||
mediarecorder_tolerate_non-gmb_nv12_frames_for_h264.patch
|
||||
cherry-pick-3910c9f5cde6.patch
|
||||
|
||||
224
patches/chromium/cherry-pick-3910c9f5cde6.patch
Normal file
224
patches/chromium/cherry-pick-3910c9f5cde6.patch
Normal file
@@ -0,0 +1,224 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Raymond Toy <rtoy@chromium.org>
|
||||
Date: Tue, 2 Mar 2021 15:15:29 +0000
|
||||
Subject: Convert AudioParam NaN values to the default value
|
||||
|
||||
If any output value of an AudioParam (including the intrinsic values
|
||||
and any inputs to the AudioParam), should be NaN, replace the NaN
|
||||
value with the associated defaultValue.
|
||||
|
||||
This causes some slowdowns so SIMD/NEON code was added to mitigate the
|
||||
degradation. There is still some slowdown, but the worst case is now
|
||||
about 7% slower on x86 and 10% on arm. Generally, the slowdown is less
|
||||
than 2% and 5%, respectively. (Perversely, some results got faster,
|
||||
and the differences are statistically significant.)
|
||||
|
||||
Full details can be found at
|
||||
https://docs.google.com/spreadsheets/d/1EhbLHm-9cUoEO5aj1vYemVBLQ3Dh4dCJPPLTfZPrZt4/edit?usp=sharing
|
||||
|
||||
Manually tested the test case from the bug and the issue no longer
|
||||
occurs.
|
||||
|
||||
(cherry picked from commit ab1862017b5717271a28376659944dddc602195c)
|
||||
|
||||
(cherry picked from commit eb0c0353bf245885797d8ce0d1b864d88a381fbb)
|
||||
|
||||
Bug: 1170531
|
||||
Change-Id: I00d902b40a9ef9da990c6d68b664b1dcfc31b091
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2658724
|
||||
Commit-Queue: Raymond Toy <rtoy@chromium.org>
|
||||
Reviewed-by: Hongchan Choi <hongchan@chromium.org>
|
||||
Cr-Original-Original-Commit-Position: refs/heads/master@{#851733}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2686369
|
||||
Reviewed-by: Raymond Toy <rtoy@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/branch-heads/4389@{#880}
|
||||
Cr-Original-Branched-From: 9251c5db2b6d5a59fe4eac7aafa5fed37c139bb7-refs/heads/master@{#843830}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2727697
|
||||
Reviewed-by: Victor-Gabriel Savu <vsavu@google.com>
|
||||
Commit-Queue: Artem Sumaneev <asumaneev@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4240@{#1551}
|
||||
Cr-Branched-From: f297677702651916bbf65e59c0d4bbd4ce57d1ee-refs/heads/master@{#800218}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/webaudio/audio_param.cc b/third_party/blink/renderer/modules/webaudio/audio_param.cc
|
||||
index c5d329479a412d52ee39167ff841b1cea417a217..135588f56ebceabd3e0a12f9f506955bb58b20ca 100644
|
||||
--- a/third_party/blink/renderer/modules/webaudio/audio_param.cc
|
||||
+++ b/third_party/blink/renderer/modules/webaudio/audio_param.cc
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "third_party/blink/renderer/modules/webaudio/audio_param.h"
|
||||
|
||||
+#include "build/build_config.h"
|
||||
#include "third_party/blink/renderer/core/inspector/console_message.h"
|
||||
#include "third_party/blink/renderer/modules/webaudio/audio_graph_tracer.h"
|
||||
#include "third_party/blink/renderer/modules/webaudio/audio_node.h"
|
||||
@@ -235,6 +236,49 @@ void AudioParamHandler::CalculateSampleAccurateValues(
|
||||
CalculateFinalValues(values, number_of_values, IsAudioRate());
|
||||
}
|
||||
|
||||
+// Replace NaN values in |values| with |default_value|.
|
||||
+static void HandleNaNValues(float* values,
|
||||
+ unsigned number_of_values,
|
||||
+ float default_value) {
|
||||
+ unsigned k = 0;
|
||||
+#if defined(ARCH_CPU_X86_FAMILY)
|
||||
+ if (number_of_values >= 4) {
|
||||
+ __m128 defaults = _mm_set1_ps(default_value);
|
||||
+ for (k = 0; k < number_of_values; k += 4) {
|
||||
+ __m128 v = _mm_loadu_ps(values + k);
|
||||
+ // cmpuord returns all 1's if v is NaN for each elmeent of v.
|
||||
+ __m128 isnan = _mm_cmpunord_ps(v, v);
|
||||
+ // Replace NaN parts with default.
|
||||
+ __m128 result = _mm_and_ps(isnan, defaults);
|
||||
+ // Merge in the parts that aren't NaN
|
||||
+ result = _mm_or_ps(_mm_andnot_ps(isnan, v), result);
|
||||
+ _mm_storeu_ps(values + k, result);
|
||||
+ }
|
||||
+ }
|
||||
+#elif defined(CPU_ARM_NEON)
|
||||
+ if (number_of_values >= 4) {
|
||||
+ uint32x4_t defaults = static_cast<uint32x4_t>(vdupq_n_f32(default_value));
|
||||
+ for (k = 0; k < number_of_values; k += 4) {
|
||||
+ float32x4_t v = vld1q_f32(values + k);
|
||||
+ // Returns true (all ones) if v is not NaN
|
||||
+ uint32x4_t is_not_nan = vceqq_f32(v, v);
|
||||
+ // Get the parts that are not NaN
|
||||
+ uint32x4_t result = vandq_u32(is_not_nan, v);
|
||||
+ // Replace the parts that are NaN with the default and merge with previous
|
||||
+ // result. (Note: vbic_u32(x, y) = x and not y)
|
||||
+ result = vorrq_u32(result, vbicq_u32(defaults, is_not_nan));
|
||||
+ vst1q_f32(values + k, static_cast<float32x4_t>(result));
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
+ for (; k < number_of_values; ++k) {
|
||||
+ if (std::isnan(values[k])) {
|
||||
+ values[k] = default_value;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void AudioParamHandler::CalculateFinalValues(float* values,
|
||||
unsigned number_of_values,
|
||||
bool sample_accurate) {
|
||||
@@ -297,10 +341,21 @@ void AudioParamHandler::CalculateFinalValues(float* values,
|
||||
}
|
||||
}
|
||||
|
||||
- // Clamp the values now to the nominal range
|
||||
float min_value = MinValue();
|
||||
float max_value = MaxValue();
|
||||
|
||||
+ if (NumberOfRenderingConnections() > 0) {
|
||||
+ // AudioParams by themselves don't produce NaN because of the finite min
|
||||
+ // and max values. But an input to an AudioParam could have NaNs.
|
||||
+ //
|
||||
+ // NaN values in AudioParams must be replaced by the AudioParam's
|
||||
+ // defaultValue. Then these values must be clamped to lie in the nominal
|
||||
+ // range between the AudioParam's minValue and maxValue.
|
||||
+ //
|
||||
+ // See https://webaudio.github.io/web-audio-api/#computation-of-value.
|
||||
+ HandleNaNValues(values, number_of_values, DefaultValue());
|
||||
+ }
|
||||
+
|
||||
vector_math::Vclip(values, 1, &min_value, &max_value, values, 1,
|
||||
number_of_values);
|
||||
}
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audioparam-interface/nan-param.html b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audioparam-interface/nan-param.html
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..e9b8f0accbd1b0359275615f3ef12bd7e9317c4f
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audioparam-interface/nan-param.html
|
||||
@@ -0,0 +1,92 @@
|
||||
+<!doctype html>
|
||||
+<html>
|
||||
+ <head>
|
||||
+ <title>Test Flushing of NaN to Zero in AudioParams</title>
|
||||
+ <script src="/resources/testharness.js"></script>
|
||||
+ <script src="/resources/testharnessreport.js"></script>
|
||||
+ <script src="/webaudio/resources/audit-util.js"></script>
|
||||
+ <script src="/webaudio/resources/audit.js"></script>
|
||||
+ </head>
|
||||
+
|
||||
+ <body>
|
||||
+ <script>
|
||||
+ let audit = Audit.createTaskRunner();
|
||||
+
|
||||
+ // See
|
||||
+ // https://webaudio.github.io/web-audio-api/#computation-of-value.
|
||||
+ //
|
||||
+ // The computed value must replace NaN values in the output with
|
||||
+ // the default value of the param.
|
||||
+ audit.define('AudioParam NaN', async (task, should) => {
|
||||
+ // For testing, we only need a small number of frames; and
|
||||
+ // a low sample rate is perfectly fine. Use two channels.
|
||||
+ // The first channel is for the AudioParam output. The
|
||||
+ // second channel is for the AudioParam input.
|
||||
+ let context = new OfflineAudioContext(
|
||||
+ {numberOfChannels: 2, length: 256, sampleRate: 8192});
|
||||
+ let merger = new ChannelMergerNode(
|
||||
+ context, {numberOfInputs: context.destination.channelCount});
|
||||
+ merger.connect(context.destination);
|
||||
+
|
||||
+ // A constant source with a huge value.
|
||||
+ let mod = new ConstantSourceNode(context, {offset: 1e30});
|
||||
+
|
||||
+ // Gain nodes with a huge positive gain and huge negative
|
||||
+ // gain. Combined with the huge offset in |mod|, the
|
||||
+ // output of the gain nodes are +Infinity and -Infinity.
|
||||
+ let gainPos = new GainNode(context, {gain: 1e30});
|
||||
+ let gainNeg = new GainNode(context, {gain: -1e30});
|
||||
+
|
||||
+ mod.connect(gainPos);
|
||||
+ mod.connect(gainNeg);
|
||||
+
|
||||
+ // Connect these to the second merger channel. This is a
|
||||
+ // sanity check that the AudioParam input really is NaN.
|
||||
+ gainPos.connect(merger, 0, 1);
|
||||
+ gainNeg.connect(merger, 0, 1);
|
||||
+
|
||||
+ // Source whose AudioParam is connected to the graph
|
||||
+ // that produces NaN values. Use a non-default value offset
|
||||
+ // just in case something is wrong we get default for some
|
||||
+ // other reason.
|
||||
+ let src = new ConstantSourceNode(context, {offset: 100});
|
||||
+
|
||||
+ gainPos.connect(src.offset);
|
||||
+ gainNeg.connect(src.offset);
|
||||
+
|
||||
+ // AudioParam output goes to channel 1 of the destination.
|
||||
+ src.connect(merger, 0, 0);
|
||||
+
|
||||
+ // Let's go!
|
||||
+ mod.start();
|
||||
+ src.start();
|
||||
+
|
||||
+ let buffer = await context.startRendering();
|
||||
+
|
||||
+ let input = buffer.getChannelData(1);
|
||||
+ let output = buffer.getChannelData(0);
|
||||
+
|
||||
+ // Have to test manually for NaN values in the input because
|
||||
+ // NaN fails all comparisons.
|
||||
+ let isNaN = true;
|
||||
+ for (let k = 0; k < input.length; ++k) {
|
||||
+ if (!Number.isNaN(input[k])) {
|
||||
+ isNaN = false;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ should(isNaN, 'AudioParam input contains only NaN').beTrue();
|
||||
+
|
||||
+ // Output of the AudioParam should have all NaN values
|
||||
+ // replaced by the default.
|
||||
+ should(output, 'AudioParam output')
|
||||
+ .beConstantValueOf(src.offset.defaultValue);
|
||||
+
|
||||
+ task.done();
|
||||
+ });
|
||||
+
|
||||
+ audit.run();
|
||||
+ </script>
|
||||
+ </body>
|
||||
+</html>
|
||||
Reference in New Issue
Block a user