| // 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 |