Commit 6382962d authored by Dan Sanders's avatar Dan Sanders Committed by Commit Bot

[media] Provide async notification for GVAF codec support APIs.

The existing query APIs IsDecoderConfigSupported() and
GetVideoEncodeAcceleratorSupportedProfiles() are fallible because the
list of supported profiles may not have been retrieved from the GPU
process yet.

This CL adds APIs to check if the supported profiles have been fetched
and to register to be notified when they have been.

Bug: 1047994, 1105258
Change-Id: Ib4b9cce8599c00218cb72912186a893a91a65f00
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2249103
Commit-Queue: Dan Sanders <sandersd@chromium.org>
Reviewed-by: default avatarDale Curtis <dalecurtis@chromium.org>
Reviewed-by: default avatarHarald Alvestrand <hta@chromium.org>
Cr-Commit-Position: refs/heads/master@{#788385}
parent 14ddcf7f
......@@ -5,6 +5,7 @@
#include "content/browser/media/android/browser_gpu_video_accelerator_factories.h"
#include "base/bind.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "content/browser/browser_main_loop.h"
#include "content/public/browser/android/gpu_video_accelerator_factories_provider.h"
#include "content/public/common/gpu_stream_constants.h"
......@@ -102,10 +103,21 @@ media::GpuVideoAcceleratorFactories::Supported
BrowserGpuVideoAcceleratorFactories::IsDecoderConfigSupported(
media::VideoDecoderImplementation implementation,
const media::VideoDecoderConfig& config) {
// TODO(sandersd): Add a cache here too?
// Tell the caller to just try it, there are no other decoders to fall back on
// anyway.
return media::GpuVideoAcceleratorFactories::Supported::kTrue;
}
bool BrowserGpuVideoAcceleratorFactories::IsDecoderSupportKnown() {
return true;
}
void BrowserGpuVideoAcceleratorFactories::NotifyDecoderSupportKnown(
base::OnceClosure callback) {
base::SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE,
std::move(callback));
}
std::unique_ptr<media::VideoDecoder>
BrowserGpuVideoAcceleratorFactories::CreateVideoDecoder(
media::MediaLog* media_log,
......@@ -171,6 +183,16 @@ BrowserGpuVideoAcceleratorFactories::
return media::VideoEncodeAccelerator::SupportedProfiles();
}
bool BrowserGpuVideoAcceleratorFactories::IsEncoderSupportKnown() {
return true;
}
void BrowserGpuVideoAcceleratorFactories::NotifyEncoderSupportKnown(
base::OnceClosure callback) {
base::SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE,
std::move(callback));
}
viz::RasterContextProvider*
BrowserGpuVideoAcceleratorFactories::GetMediaContextProvider() {
return context_provider_.get();
......
......@@ -31,10 +31,16 @@ class BrowserGpuVideoAcceleratorFactories
Supported IsDecoderConfigSupported(
media::VideoDecoderImplementation implementation,
const media::VideoDecoderConfig& config) override;
bool IsDecoderSupportKnown() override;
void NotifyDecoderSupportKnown(base::OnceClosure) override;
std::unique_ptr<media::VideoDecoder> CreateVideoDecoder(
media::MediaLog* media_log,
media::VideoDecoderImplementation implementation,
media::RequestOverlayInfoCB request_overlay_info_cb) override;
base::Optional<media::VideoEncodeAccelerator::SupportedProfiles>
GetVideoEncodeAcceleratorSupportedProfiles() override;
bool IsEncoderSupportKnown() override;
void NotifyEncoderSupportKnown(base::OnceClosure) override;
std::unique_ptr<media::VideoEncodeAccelerator> CreateVideoEncodeAccelerator()
override;
std::unique_ptr<gfx::GpuMemoryBuffer> CreateGpuMemoryBuffer(
......@@ -50,8 +56,6 @@ class BrowserGpuVideoAcceleratorFactories
gpu::GpuMemoryBufferManager* GpuMemoryBufferManager() override;
base::UnsafeSharedMemoryRegion CreateSharedMemoryRegion(size_t size) override;
scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() override;
base::Optional<media::VideoEncodeAccelerator::SupportedProfiles>
GetVideoEncodeAcceleratorSupportedProfiles() override;
viz::RasterContextProvider* GetMediaContextProvider() override;
void SetRenderingColorSpace(const gfx::ColorSpace& color_space) override;
......
......@@ -25,6 +25,7 @@
#include "gpu/ipc/client/command_buffer_proxy_impl.h"
#include "gpu/ipc/client/gpu_channel_host.h"
#include "gpu/ipc/common/gpu_memory_buffer_support.h"
#include "media/base/bind_to_current_loop.h"
#include "media/gpu/gpu_video_accelerator_util.h"
#include "media/gpu/ipc/common/media_messages.h"
#include "media/mojo/buildflags.h"
......@@ -52,6 +53,26 @@ void RecordContextProviderPhaseUmaEnum(const ContextProviderPhase phase) {
} // namespace
GpuVideoAcceleratorFactoriesImpl::Notifier::Notifier() = default;
GpuVideoAcceleratorFactoriesImpl::Notifier::~Notifier() = default;
void GpuVideoAcceleratorFactoriesImpl::Notifier::Register(
base::OnceClosure callback) {
if (is_notified_) {
std::move(callback).Run();
return;
}
callbacks_.push_back(std::move(callback));
}
void GpuVideoAcceleratorFactoriesImpl::Notifier::Notify() {
DCHECK(!is_notified_);
is_notified_ = true;
for (auto& callback : callbacks_)
std::move(callback).Run();
callbacks_.clear();
}
// static
std::unique_ptr<GpuVideoAcceleratorFactoriesImpl>
GpuVideoAcceleratorFactoriesImpl::Create(
......@@ -123,6 +144,8 @@ void GpuVideoAcceleratorFactoriesImpl::BindOnTaskRunner(
if (context_provider_->BindToCurrentThread() !=
gpu::ContextResult::kSuccess) {
OnDecoderSupportFailed();
OnEncoderSupportFailed();
OnContextLost();
return;
}
......@@ -139,10 +162,15 @@ void GpuVideoAcceleratorFactoriesImpl::BindOnTaskRunner(
.video_encode_accelerator_supported_profiles);
}
vea_provider_.set_disconnect_handler(base::BindOnce(
&GpuVideoAcceleratorFactoriesImpl::OnEncoderSupportFailed,
base::Unretained(this)));
vea_provider_->GetVideoEncodeAcceleratorSupportedProfiles(
base::BindOnce(&GpuVideoAcceleratorFactoriesImpl::
OnGetVideoEncodeAcceleratorSupportedProfiles,
base::Unretained(this)));
} else {
OnEncoderSupportFailed();
}
#if BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER)
......@@ -153,17 +181,56 @@ void GpuVideoAcceleratorFactoriesImpl::BindOnTaskRunner(
// kAlternate, for example.
interface_factory_->CreateVideoDecoder(
video_decoder_.BindNewPipeAndPassReceiver());
video_decoder_.set_disconnect_handler(
base::BindOnce(&GpuVideoAcceleratorFactoriesImpl::OnDecoderSupportFailed,
base::Unretained(this)));
video_decoder_->GetSupportedConfigs(base::BindOnce(
&GpuVideoAcceleratorFactoriesImpl::OnSupportedDecoderConfigs,
base::Unretained(this)));
#else
OnDecoderSupportFailed();
#endif // BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER)
}
bool GpuVideoAcceleratorFactoriesImpl::IsDecoderSupportKnown() {
base::AutoLock lock(supported_profiles_lock_);
return decoder_support_notifier_.is_notified();
}
void GpuVideoAcceleratorFactoriesImpl::NotifyDecoderSupportKnown(
base::OnceClosure callback) {
base::AutoLock lock(supported_profiles_lock_);
decoder_support_notifier_.Register(
media::BindToCurrentLoop(std::move(callback)));
}
void GpuVideoAcceleratorFactoriesImpl::OnSupportedDecoderConfigs(
const media::SupportedVideoDecoderConfigMap& supported_configs) {
base::AutoLock lock(supported_profiles_lock_);
video_decoder_.reset();
supported_decoder_configs_ = supported_configs;
decoder_support_notifier_.Notify();
}
void GpuVideoAcceleratorFactoriesImpl::OnDecoderSupportFailed() {
base::AutoLock lock(supported_profiles_lock_);
video_decoder_.reset();
if (decoder_support_notifier_.is_notified())
return;
supported_decoder_configs_ = media::SupportedVideoDecoderConfigMap();
decoder_support_notifier_.Notify();
}
bool GpuVideoAcceleratorFactoriesImpl::IsEncoderSupportKnown() {
base::AutoLock lock(supported_profiles_lock_);
return encoder_support_notifier_.is_notified();
}
void GpuVideoAcceleratorFactoriesImpl::NotifyEncoderSupportKnown(
base::OnceClosure callback) {
base::AutoLock lock(supported_profiles_lock_);
encoder_support_notifier_.Register(
media::BindToCurrentLoop(std::move(callback)));
}
void GpuVideoAcceleratorFactoriesImpl::
......@@ -172,6 +239,15 @@ void GpuVideoAcceleratorFactoriesImpl::
supported_profiles) {
base::AutoLock lock(supported_profiles_lock_);
supported_vea_profiles_ = supported_profiles;
encoder_support_notifier_.Notify();
}
void GpuVideoAcceleratorFactoriesImpl::OnEncoderSupportFailed() {
base::AutoLock lock(supported_profiles_lock_);
if (encoder_support_notifier_.is_notified())
return;
supported_vea_profiles_ = media::VideoEncodeAccelerator::SupportedProfiles();
encoder_support_notifier_.Notify();
}
bool GpuVideoAcceleratorFactoriesImpl::CheckContextLost() {
......
......@@ -75,13 +75,19 @@ class CONTENT_EXPORT GpuVideoAcceleratorFactoriesImpl
bool IsGpuVideoAcceleratorEnabled() override;
base::UnguessableToken GetChannelToken() override;
int32_t GetCommandBufferRouteId() override;
Supported IsDecoderConfigSupported(
media::VideoDecoderImplementation implementation,
const media::VideoDecoderConfig& config) override;
bool IsDecoderSupportKnown() override;
void NotifyDecoderSupportKnown(base::OnceClosure callback) override;
std::unique_ptr<media::VideoDecoder> CreateVideoDecoder(
media::MediaLog* media_log,
media::VideoDecoderImplementation implementation,
media::RequestOverlayInfoCB request_overlay_info_cb) override;
Supported IsDecoderConfigSupported(
media::VideoDecoderImplementation implementation,
const media::VideoDecoderConfig& config) override;
base::Optional<media::VideoEncodeAccelerator::SupportedProfiles>
GetVideoEncodeAcceleratorSupportedProfiles() override;
bool IsEncoderSupportKnown() override;
void NotifyEncoderSupportKnown(base::OnceClosure callback) override;
std::unique_ptr<media::VideoEncodeAccelerator> CreateVideoEncodeAccelerator()
override;
......@@ -112,9 +118,6 @@ class CONTENT_EXPORT GpuVideoAcceleratorFactoriesImpl
base::UnsafeSharedMemoryRegion CreateSharedMemoryRegion(size_t size) override;
scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() override;
base::Optional<media::VideoEncodeAccelerator::SupportedProfiles>
GetVideoEncodeAcceleratorSupportedProfiles() override;
viz::RasterContextProvider* GetMediaContextProvider() override;
void SetRenderingColorSpace(const gfx::ColorSpace& color_space) override;
......@@ -127,6 +130,21 @@ class CONTENT_EXPORT GpuVideoAcceleratorFactoriesImpl
~GpuVideoAcceleratorFactoriesImpl() override;
private:
class Notifier {
public:
Notifier();
~Notifier();
void Register(base::OnceClosure callback);
void Notify();
bool is_notified() { return is_notified_; }
private:
bool is_notified_ = false;
std::vector<base::OnceClosure> callbacks_;
};
GpuVideoAcceleratorFactoriesImpl(
scoped_refptr<gpu::GpuChannelHost> gpu_channel_host,
const scoped_refptr<base::SingleThreadTaskRunner>&
......@@ -153,9 +171,12 @@ class CONTENT_EXPORT GpuVideoAcceleratorFactoriesImpl
void OnSupportedDecoderConfigs(
const media::SupportedVideoDecoderConfigMap& supported_configs);
void OnDecoderSupportFailed();
void OnGetVideoEncodeAcceleratorSupportedProfiles(
const media::VideoEncodeAccelerator::SupportedProfiles&
supported_profiles);
void OnEncoderSupportFailed();
const scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
......@@ -196,9 +217,11 @@ class CONTENT_EXPORT GpuVideoAcceleratorFactoriesImpl
// are no supported configs.
base::Optional<media::SupportedVideoDecoderConfigMap>
supported_decoder_configs_ GUARDED_BY(supported_profiles_lock_);
Notifier decoder_support_notifier_ GUARDED_BY(supported_profiles_lock_);
base::Optional<media::VideoEncodeAccelerator::SupportedProfiles>
supported_vea_profiles_ GUARDED_BY(supported_profiles_lock_);
Notifier encoder_support_notifier_ GUARDED_BY(supported_profiles_lock_);
DISALLOW_COPY_AND_ASSIGN(GpuVideoAcceleratorFactoriesImpl);
};
......
......@@ -55,7 +55,7 @@ class MediaLog;
// * The GpuVideoAcceleratorFactories has an associated message loop, which may
// be retrieved as |GetMessageLoop()|.
// * All calls to the Factories after construction must be made on its message
// loop.
// loop, unless otherwise documented below.
class MEDIA_EXPORT GpuVideoAcceleratorFactories {
public:
enum class OutputFormat {
......@@ -90,15 +90,61 @@ class MEDIA_EXPORT GpuVideoAcceleratorFactories {
// Supported::kFalse if |config| is not supported.
//
// May be called on any thread.
//
// TODO(sandersd): Switch to bool if/when all clients check
// IsDecoderSupportKnown().
virtual Supported IsDecoderConfigSupported(
VideoDecoderImplementation implementation,
const VideoDecoderConfig& config) = 0;
// Returns true if IsDecoderConfigSupported() is ready to answer queries.
// Once decoder support is known, it remains known for the lifetime of |this|.
//
// May be called on any thread.
virtual bool IsDecoderSupportKnown() = 0;
// Registers a callback to be notified when IsDecoderConfigSupported() is
// ready to answer queries. The callback will be invoked on the caller's
// sequence.
//
// There is no way to unsubscribe a callback, it is recommended to use a
// WeakPtr if you need this feature.
//
// May be called on any thread.
virtual void NotifyDecoderSupportKnown(base::OnceClosure callback) = 0;
virtual std::unique_ptr<media::VideoDecoder> CreateVideoDecoder(
MediaLog* media_log,
VideoDecoderImplementation implementation,
RequestOverlayInfoCB request_overlay_info_cb) = 0;
// Returns the supported codec profiles of video encode accelerator.
// Returns nullopt if GpuVideoAcceleratorFactories don't know the VEA
// supported profiles.
//
// May be called on any thread.
//
// TODO(sandersd): Remove Optional if/when all clients check
// IsEncoderSupportKnown().
virtual base::Optional<VideoEncodeAccelerator::SupportedProfiles>
GetVideoEncodeAcceleratorSupportedProfiles() = 0;
// Returns true if GetVideoEncodeAcceleratorSupportedProfiles() is populated.
// Once encoder support is known, it remains known for the lifetime of |this|.
//
// May be called on any thread.
virtual bool IsEncoderSupportKnown() = 0;
// Registers a callback to be notified when
// GetVideoEncodeAcceleratorSupportedProfiles() has been populated. The
// callback will be invoked on the caller's sequence.
//
// There is no way to unsubscribe a callback, it is recommended to use a
// WeakPtr if you need this feature.
//
// May be called on any thread.
virtual void NotifyEncoderSupportKnown(base::OnceClosure callback) = 0;
// Caller owns returned pointer, but should call Destroy() on it (instead of
// directly deleting) for proper destruction, as per the
// VideoEncodeAccelerator interface.
......@@ -140,12 +186,6 @@ class MEDIA_EXPORT GpuVideoAcceleratorFactories {
// Returns the task runner the video accelerator runs on.
virtual scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() = 0;
// Returns the supported codec profiles of video encode accelerator.
// Returns nullopt if GpuVideoAcceleratorFactories don't know the VEA
// supported profiles.
virtual base::Optional<VideoEncodeAccelerator::SupportedProfiles>
GetVideoEncodeAcceleratorSupportedProfiles() = 0;
virtual viz::RasterContextProvider* GetMediaContextProvider() = 0;
// Sets the current pipeline rendering color space.
......
......@@ -34,11 +34,15 @@ class MockGpuVideoAcceleratorFactories : public GpuVideoAcceleratorFactories {
MOCK_METHOD2(IsDecoderConfigSupported,
Supported(VideoDecoderImplementation,
const VideoDecoderConfig&));
MOCK_METHOD0(IsDecoderSupportKnown, bool());
MOCK_METHOD1(NotifyDecoderSupportKnown, void(base::OnceClosure));
MOCK_METHOD3(CreateVideoDecoder,
std::unique_ptr<media::VideoDecoder>(MediaLog*,
VideoDecoderImplementation,
RequestOverlayInfoCB));
MOCK_METHOD0(IsEncoderSupportKnown, bool());
MOCK_METHOD1(NotifyEncoderSupportKnown, void(base::OnceClosure));
// CreateVideoEncodeAccelerator returns scoped_ptr, which the mocking
// framework does not want. Trampoline it.
MOCK_METHOD0(DoCreateVideoEncodeAccelerator, VideoEncodeAccelerator*());
......
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