Commit 5a7ae53c authored by Sergey Silkin's avatar Sergey Silkin Committed by Commit Bot

Wait for HW codecs support status is known.

In RTC video en-/decoder factories, wait until codec support status in
GPU factory is known before querying supported formats and creating
codecs.

This feature is controlled by kRTCGpuCodecSupportWaiter field trial and
is enabled by default with 3 seconds timeout.

Bug: 1047994
Change-Id: Ia822b399b3007815e2f5a15270bbc7cec1801aca
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2453251
Commit-Queue: Sergey Silkin <ssilkin@chromium.org>
Reviewed-by: default avatarHarald Alvestrand <hta@chromium.org>
Reviewed-by: default avatarGuido Urdaneta <guidou@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Reviewed-by: default avatarDan Sanders <sandersd@chromium.org>
Cr-Commit-Position: refs/heads/master@{#818078}
parent 699b7ee2
...@@ -264,10 +264,8 @@ IN_PROC_BROWSER_TEST_F( ...@@ -264,10 +264,8 @@ IN_PROC_BROWSER_TEST_F(
#if defined(OS_ANDROID) && BUILDFLAG(USE_PROPRIETARY_CODECS) #if defined(OS_ANDROID) && BUILDFLAG(USE_PROPRIETARY_CODECS)
// This test is to make sure HW H264 work normally on supported devices, since // This test is to make sure HW H264 work normally on supported devices, since
// there is no SW H264 fallback available on Android. // there is no SW H264 fallback available on Android.
// TODO(crbug.com/1047994): Disabled due to flakiness caused by timing issue
// in blink HW codec factories.
IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest, IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
DISABLED_CanSetupH264VideoCallOnSupportedDevice) { CanSetupH264VideoCallOnSupportedDevice) {
MakeTypicalPeerConnectionCall("CanSetupH264VideoCallOnSupportedDevice();"); MakeTypicalPeerConnectionCall("CanSetupH264VideoCallOnSupportedDevice();");
} }
#endif #endif
......
...@@ -761,13 +761,13 @@ ...@@ -761,13 +761,13 @@
} }
async function CanSetupH264VideoCallOnSupportedDevice() { async function CanSetupH264VideoCallOnSupportedDevice() {
// Setup one way video call, prioritize H264 and verify that it used.
createConnections(null); createConnections(null);
setOfferSdpTransform(maybePreferH264SendCodec); setOfferSdpTransform(maybePreferH264SendCodec);
navigator.mediaDevices.getUserMedia({audio: false, video: true}) navigator.mediaDevices.getUserMedia({audio: false, video: true})
.then(addStreamToBothConnectionsAndNegotiate) .then(addStreamToTheFirstConnectionAndNegotiate)
.catch(failTest); .catch(failTest);
await detectVideoPlaying('remote-view-1');
await detectVideoPlaying('remote-view-2'); await detectVideoPlaying('remote-view-2');
assertEquals(gLocalStream.getVideoTracks().length, 1); assertEquals(gLocalStream.getVideoTracks().length, 1);
......
...@@ -57,3 +57,6 @@ ...@@ -57,3 +57,6 @@
# crbug.com/1120813 # crbug.com/1120813
-P/CompositorImplBrowserTestRefreshRate.VideoPreference/* -P/CompositorImplBrowserTestRefreshRate.VideoPreference/*
# crbug.com/1047994
-WebRtcBrowserTest.CanSetupH264VideoCallOnSupportedDevice
...@@ -24,3 +24,6 @@ ...@@ -24,3 +24,6 @@
# crbug.com/954217 # crbug.com/954217
-RenderFrameHostImplBrowserTest.VisibilityScrolledOutOfView -RenderFrameHostImplBrowserTest.VisibilityScrolledOutOfView
# crbug.com/1047994
-WebRtcBrowserTest.CanSetupH264VideoCallOnSupportedDevice
...@@ -185,6 +185,14 @@ const base::Feature kRTCUnifiedPlanByDefault{"RTCUnifiedPlanByDefault", ...@@ -185,6 +185,14 @@ const base::Feature kRTCUnifiedPlanByDefault{"RTCUnifiedPlanByDefault",
const base::Feature kRTCOfferExtmapAllowMixed{ const base::Feature kRTCOfferExtmapAllowMixed{
"RTCOfferExtmapAllowMixed", base::FEATURE_DISABLED_BY_DEFAULT}; "RTCOfferExtmapAllowMixed", base::FEATURE_DISABLED_BY_DEFAULT};
// Enables waiting for codec support status notification from GPU factory in RTC
// codec factories.
const base::Feature kRTCGpuCodecSupportWaiter{"kRTCGpuCodecSupportWaiter",
base::FEATURE_ENABLED_BY_DEFAULT};
const base::FeatureParam<int> kRTCGpuCodecSupportWaiterTimeoutParam{
&kRTCGpuCodecSupportWaiter, "timeout_ms", 3000};
// Prevents workers from sending IsolateInBackgroundNotification to V8 // Prevents workers from sending IsolateInBackgroundNotification to V8
// and thus instructs V8 to favor performance over memory on workers. // and thus instructs V8 to favor performance over memory on workers.
const base::Feature kV8OptimizeWorkersForPerformance{ const base::Feature kV8OptimizeWorkersForPerformance{
......
...@@ -50,6 +50,9 @@ BLINK_COMMON_EXPORT extern const base::Feature kRawClipboard; ...@@ -50,6 +50,9 @@ BLINK_COMMON_EXPORT extern const base::Feature kRawClipboard;
BLINK_COMMON_EXPORT extern const base::Feature kRTCGetDisplayMedia; BLINK_COMMON_EXPORT extern const base::Feature kRTCGetDisplayMedia;
BLINK_COMMON_EXPORT extern const base::Feature kRTCUnifiedPlanByDefault; BLINK_COMMON_EXPORT extern const base::Feature kRTCUnifiedPlanByDefault;
BLINK_COMMON_EXPORT extern const base::Feature kRTCOfferExtmapAllowMixed; BLINK_COMMON_EXPORT extern const base::Feature kRTCOfferExtmapAllowMixed;
BLINK_COMMON_EXPORT extern const base::Feature kRTCGpuCodecSupportWaiter;
BLINK_COMMON_EXPORT extern const base::FeatureParam<int>
kRTCGpuCodecSupportWaiterTimeoutParam;
BLINK_COMMON_EXPORT extern const base::Feature kV8OptimizeWorkersForPerformance; BLINK_COMMON_EXPORT extern const base::Feature kV8OptimizeWorkersForPerformance;
BLINK_COMMON_EXPORT extern const base::Feature BLINK_COMMON_EXPORT extern const base::Feature
kWebMeasureMemoryViaPerformanceManager; kWebMeasureMemoryViaPerformanceManager;
......
...@@ -1265,6 +1265,8 @@ component("platform") { ...@@ -1265,6 +1265,8 @@ component("platform") {
"p2p/socket_dispatcher.h", "p2p/socket_dispatcher.h",
"peerconnection/audio_codec_factory.cc", "peerconnection/audio_codec_factory.cc",
"peerconnection/audio_codec_factory.h", "peerconnection/audio_codec_factory.h",
"peerconnection/gpu_codec_support_waiter.cc",
"peerconnection/gpu_codec_support_waiter.h",
"peerconnection/rtc_answer_options_platform.h", "peerconnection/rtc_answer_options_platform.h",
"peerconnection/rtc_api_name.h", "peerconnection/rtc_api_name.h",
"peerconnection/rtc_dtmf_sender_handler.cc", "peerconnection/rtc_dtmf_sender_handler.cc",
......
...@@ -12,6 +12,7 @@ include_rules = [ ...@@ -12,6 +12,7 @@ include_rules = [
# Dependencies. # Dependencies.
"+base/strings/string_number_conversions.h", "+base/strings/string_number_conversions.h",
"+base/strings/string_split.h", "+base/strings/string_split.h",
"+base/task/task_traits.h",
"+base/threading/thread_restrictions.h", "+base/threading/thread_restrictions.h",
"+media/base", "+media/base",
"+media/capture/capture_switches.h", "+media/capture/capture_switches.h",
...@@ -30,7 +31,6 @@ include_rules = [ ...@@ -30,7 +31,6 @@ include_rules = [
specific_include_rules = { specific_include_rules = {
".*_test\.cc": [ ".*_test\.cc": [
"+base/task/task_traits.h",
"+base/threading/thread.h", "+base/threading/thread.h",
"+gpu/command_buffer/common/mailbox.h", "+gpu/command_buffer/common/mailbox.h",
"+media/video/mock_gpu_video_accelerator_factories.h", "+media/video/mock_gpu_video_accelerator_factories.h",
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/platform/peerconnection/gpu_codec_support_waiter.h"
#include "base/sequenced_task_runner.h"
#include "base/synchronization/waitable_event.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h"
namespace blink {
namespace {
// Codec support known callback can potentially be called after the waiter is
// destroyed. RefCountedWaitableEvent is used for the event which callback sets
// to keep it alive in such case.
class RefCountedWaitableEvent
: public base::WaitableEvent,
public WTF::ThreadSafeRefCounted<RefCountedWaitableEvent> {
public:
RefCountedWaitableEvent()
: base::WaitableEvent(base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED) {}
private:
friend class WTF::ThreadSafeRefCounted<RefCountedWaitableEvent>;
~RefCountedWaitableEvent() = default;
};
base::Optional<base::TimeDelta> GetCodecSupportWaitTimeoutMs() {
if (!base::FeatureList::IsEnabled(features::kRTCGpuCodecSupportWaiter)) {
return base::nullopt;
}
int timeout_ms = base::GetFieldTrialParamByFeatureAsInt(
features::kRTCGpuCodecSupportWaiter,
features::kRTCGpuCodecSupportWaiterTimeoutParam.name,
features::kRTCGpuCodecSupportWaiterTimeoutParam.default_value);
return base::TimeDelta::FromMilliseconds(timeout_ms);
}
void OnCodecSupportKnown(
scoped_refptr<RefCountedWaitableEvent> codec_support_known) {
codec_support_known->Signal();
}
} // namespace
GpuCodecSupportWaiter::GpuCodecSupportWaiter(
media::GpuVideoAcceleratorFactories* gpu_factories)
: gpu_factories_(gpu_factories),
wait_timeout_ms_(GetCodecSupportWaitTimeoutMs()) {}
bool GpuCodecSupportWaiter::IsCodecSupportKnown(bool is_encoder) const {
if (is_encoder) {
if (gpu_factories_->IsEncoderSupportKnown()) {
return true;
}
} else if (gpu_factories_->IsDecoderSupportKnown()) {
return true;
}
if (!wait_timeout_ms_) {
return false;
}
// crbug.com/1047994. GPU might not be initialized by the time it is queried
// for supported codecs. Request support status notification and block
// execution with timeout.
// https://github.com/w3c/webrtc-extensions/issues/49 is a request for async
// WebRTC API.
scoped_refptr<RefCountedWaitableEvent> codec_support_known =
base::MakeRefCounted<RefCountedWaitableEvent>();
// Callback passed to Notify{Decoder|Decoder}SupportKnown is called on
// caller's sequence. To not block the callback while waiting for it, request
// notification on a separate sequence.
scoped_refptr<base::SequencedTaskRunner> task_runner =
base::ThreadPool::CreateSequencedTaskRunner({});
bool is_support_notification_requested = task_runner->PostTask(
FROM_HERE,
base::BindOnce(
[](media::GpuVideoAcceleratorFactories* gpu_factories,
scoped_refptr<RefCountedWaitableEvent> codec_support_known,
bool is_encoder) {
if (is_encoder) {
gpu_factories->NotifyEncoderSupportKnown(
base::BindOnce(&OnCodecSupportKnown, codec_support_known));
} else {
gpu_factories->NotifyDecoderSupportKnown(
base::BindOnce(&OnCodecSupportKnown, codec_support_known));
}
},
gpu_factories_, codec_support_known, is_encoder));
if (!is_support_notification_requested) {
DLOG(WARNING) << "Failed to request codec support notification.";
return false;
}
return codec_support_known->TimedWait(*wait_timeout_ms_);
}
bool GpuCodecSupportWaiter::IsDecoderSupportKnown() const {
return IsCodecSupportKnown(/*is_encoder=*/false);
}
bool GpuCodecSupportWaiter::IsEncoderSupportKnown() const {
return IsCodecSupportKnown(/*is_encoder=*/true);
}
} // namespace blink
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_GPU_CODEC_SUPPORT_WAITER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_GPU_CODEC_SUPPORT_WAITER_H_
#include "base/optional.h"
#include "base/time/time.h"
#include "media/video/gpu_video_accelerator_factories.h"
namespace blink {
class GpuCodecSupportWaiter {
public:
explicit GpuCodecSupportWaiter(
media::GpuVideoAcceleratorFactories* gpu_factories);
bool IsDecoderSupportKnown() const;
bool IsEncoderSupportKnown() const;
base::Optional<base::TimeDelta> wait_timeout_ms() const {
return wait_timeout_ms_;
}
private:
bool IsCodecSupportKnown(bool is_encoder) const;
media::GpuVideoAcceleratorFactories* gpu_factories_;
const base::Optional<base::TimeDelta> wait_timeout_ms_;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_GPU_CODEC_SUPPORT_WAITER_H_
...@@ -175,12 +175,24 @@ class ScopedVideoDecoder : public webrtc::VideoDecoder { ...@@ -175,12 +175,24 @@ class ScopedVideoDecoder : public webrtc::VideoDecoder {
RTCVideoDecoderFactory::RTCVideoDecoderFactory( RTCVideoDecoderFactory::RTCVideoDecoderFactory(
media::GpuVideoAcceleratorFactories* gpu_factories) media::GpuVideoAcceleratorFactories* gpu_factories)
: gpu_factories_(gpu_factories) { : gpu_factories_(gpu_factories), gpu_codec_support_waiter_(gpu_factories) {
DVLOG(2) << __func__; DVLOG(2) << __func__;
} }
void RTCVideoDecoderFactory::CheckAndWaitDecoderSupportStatusIfNeeded() const {
if (!gpu_codec_support_waiter_.IsDecoderSupportKnown()) {
DLOG(WARNING) << "Decoder support is unknown. Timeout "
<< gpu_codec_support_waiter_.wait_timeout_ms()
.value_or(base::TimeDelta())
.InMilliseconds()
<< "ms. Decoders might not be available.";
}
}
std::vector<webrtc::SdpVideoFormat> std::vector<webrtc::SdpVideoFormat>
RTCVideoDecoderFactory::GetSupportedFormats() const { RTCVideoDecoderFactory::GetSupportedFormats() const {
CheckAndWaitDecoderSupportStatusIfNeeded();
std::vector<webrtc::SdpVideoFormat> supported_formats; std::vector<webrtc::SdpVideoFormat> supported_formats;
for (auto& codec_config : kCodecConfigs) { for (auto& codec_config : kCodecConfigs) {
media::VideoDecoderConfig config( media::VideoDecoderConfig config(
...@@ -213,6 +225,8 @@ std::unique_ptr<webrtc::VideoDecoder> ...@@ -213,6 +225,8 @@ std::unique_ptr<webrtc::VideoDecoder>
RTCVideoDecoderFactory::CreateVideoDecoder( RTCVideoDecoderFactory::CreateVideoDecoder(
const webrtc::SdpVideoFormat& format) { const webrtc::SdpVideoFormat& format) {
DVLOG(2) << __func__; DVLOG(2) << __func__;
CheckAndWaitDecoderSupportStatusIfNeeded();
std::unique_ptr<webrtc::VideoDecoder> decoder = std::unique_ptr<webrtc::VideoDecoder> decoder =
RTCVideoDecoderAdapter::Create(gpu_factories_, format); RTCVideoDecoderAdapter::Create(gpu_factories_, format);
// ScopedVideoDecoder uses the task runner to make sure the decoder is // ScopedVideoDecoder uses the task runner to make sure the decoder is
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_RTC_VIDEO_DECODER_FACTORY_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_RTC_VIDEO_DECODER_FACTORY_H_
#include "base/macros.h" #include "base/macros.h"
#include "third_party/blink/renderer/platform/peerconnection/gpu_codec_support_waiter.h"
#include "third_party/webrtc/api/video_codecs/video_decoder_factory.h" #include "third_party/webrtc/api/video_codecs/video_decoder_factory.h"
#include "third_party/webrtc/modules/video_coding/include/video_codec_interface.h" #include "third_party/webrtc/modules/video_coding/include/video_codec_interface.h"
...@@ -34,8 +35,12 @@ class RTCVideoDecoderFactory : public webrtc::VideoDecoderFactory { ...@@ -34,8 +35,12 @@ class RTCVideoDecoderFactory : public webrtc::VideoDecoderFactory {
std::vector<webrtc::SdpVideoFormat> GetSupportedFormats() const override; std::vector<webrtc::SdpVideoFormat> GetSupportedFormats() const override;
private: private:
void CheckAndWaitDecoderSupportStatusIfNeeded() const;
media::GpuVideoAcceleratorFactories* gpu_factories_; media::GpuVideoAcceleratorFactories* gpu_factories_;
GpuCodecSupportWaiter gpu_codec_support_waiter_;
DISALLOW_COPY_AND_ASSIGN(RTCVideoDecoderFactory); DISALLOW_COPY_AND_ASSIGN(RTCVideoDecoderFactory);
}; };
......
...@@ -193,13 +193,25 @@ bool IsConstrainedH264(const webrtc::SdpVideoFormat& format) { ...@@ -193,13 +193,25 @@ bool IsConstrainedH264(const webrtc::SdpVideoFormat& format) {
RTCVideoEncoderFactory::RTCVideoEncoderFactory( RTCVideoEncoderFactory::RTCVideoEncoderFactory(
media::GpuVideoAcceleratorFactories* gpu_factories) media::GpuVideoAcceleratorFactories* gpu_factories)
: gpu_factories_(gpu_factories) {} : gpu_factories_(gpu_factories), gpu_codec_support_waiter_(gpu_factories) {}
RTCVideoEncoderFactory::~RTCVideoEncoderFactory() {} RTCVideoEncoderFactory::~RTCVideoEncoderFactory() {}
void RTCVideoEncoderFactory::CheckAndWaitEncoderSupportStatusIfNeeded() const {
if (!gpu_codec_support_waiter_.IsEncoderSupportKnown()) {
DLOG(WARNING) << "Encoder support is unknown. Timeout "
<< gpu_codec_support_waiter_.wait_timeout_ms()
.value_or(base::TimeDelta())
.InMilliseconds()
<< "ms. Encoders might not be available.";
}
}
std::unique_ptr<webrtc::VideoEncoder> std::unique_ptr<webrtc::VideoEncoder>
RTCVideoEncoderFactory::CreateVideoEncoder( RTCVideoEncoderFactory::CreateVideoEncoder(
const webrtc::SdpVideoFormat& format) { const webrtc::SdpVideoFormat& format) {
CheckAndWaitEncoderSupportStatusIfNeeded();
std::unique_ptr<webrtc::VideoEncoder> encoder; std::unique_ptr<webrtc::VideoEncoder> encoder;
bool is_constrained_h264 = IsConstrainedH264(format); bool is_constrained_h264 = IsConstrainedH264(format);
auto supported_formats = GetSupportedFormatsInternal(gpu_factories_); auto supported_formats = GetSupportedFormatsInternal(gpu_factories_);
...@@ -218,11 +230,14 @@ RTCVideoEncoderFactory::CreateVideoEncoder( ...@@ -218,11 +230,14 @@ RTCVideoEncoderFactory::CreateVideoEncoder(
gpu_factories_); gpu_factories_);
} }
} }
return encoder; return encoder;
} }
std::vector<webrtc::SdpVideoFormat> std::vector<webrtc::SdpVideoFormat>
RTCVideoEncoderFactory::GetSupportedFormats() const { RTCVideoEncoderFactory::GetSupportedFormats() const {
CheckAndWaitEncoderSupportStatusIfNeeded();
return GetSupportedFormatsInternal(gpu_factories_).sdp_formats; return GetSupportedFormatsInternal(gpu_factories_).sdp_formats;
} }
......
...@@ -8,10 +8,9 @@ ...@@ -8,10 +8,9 @@
#include <vector> #include <vector>
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ref_counted.h" #include "third_party/blink/renderer/platform/peerconnection/gpu_codec_support_waiter.h"
#include "base/optional.h"
#include "media/base/video_codecs.h"
#include "third_party/webrtc/api/video_codecs/video_encoder_factory.h" #include "third_party/webrtc/api/video_codecs/video_encoder_factory.h"
#include "third_party/webrtc/modules/video_coding/include/video_codec_interface.h"
namespace media { namespace media {
class GpuVideoAcceleratorFactories; class GpuVideoAcceleratorFactories;
...@@ -33,8 +32,12 @@ class RTCVideoEncoderFactory : public webrtc::VideoEncoderFactory { ...@@ -33,8 +32,12 @@ class RTCVideoEncoderFactory : public webrtc::VideoEncoderFactory {
std::vector<webrtc::SdpVideoFormat> GetSupportedFormats() const override; std::vector<webrtc::SdpVideoFormat> GetSupportedFormats() const override;
private: private:
void CheckAndWaitEncoderSupportStatusIfNeeded() const;
media::GpuVideoAcceleratorFactories* gpu_factories_; media::GpuVideoAcceleratorFactories* gpu_factories_;
GpuCodecSupportWaiter gpu_codec_support_waiter_;
DISALLOW_COPY_AND_ASSIGN(RTCVideoEncoderFactory); DISALLOW_COPY_AND_ASSIGN(RTCVideoEncoderFactory);
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment