Commit c32238c8 authored by Dan Sanders's avatar Dan Sanders Committed by Commit Bot

[media] Mojo replacement for VDA SupportedProfiles.

This API allows mojom::VideoDecoder clients to get a list of rules that
can be used to reject unsupported Initialize() calls without additional
IPC.

On the GPU side, this information is gathered from the existing VDA
SupportedProfiles factory.

On the renderer side, GpuVideoAcceleratorFactories is now responsible
for this query, which it does upon construction. If a MojoVideoDecoder
is initialized before the query has completed, MojoVideoDecoder will
call the remote Intitialize() method as normal.

Bug: 839951, 522298
Change-Id: I62b1e2f6ad79f096d273d7591da1e98094b9cbfe
Reviewed-on: https://chromium-review.googlesource.com/1066620Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarDale Curtis <dalecurtis@chromium.org>
Commit-Queue: Dan Sanders <sandersd@chromium.org>
Cr-Commit-Position: refs/heads/master@{#593327}
parent c985b88c
...@@ -96,6 +96,12 @@ int32_t BrowserGpuVideoAcceleratorFactories::GetCommandBufferRouteId() { ...@@ -96,6 +96,12 @@ int32_t BrowserGpuVideoAcceleratorFactories::GetCommandBufferRouteId() {
return context_provider_->GetCommandBufferProxy()->route_id(); return context_provider_->GetCommandBufferProxy()->route_id();
} }
bool BrowserGpuVideoAcceleratorFactories::IsDecoderConfigSupported(
const media::VideoDecoderConfig& config) {
// TODO(sandersd): Add a cache here too?
return true;
}
std::unique_ptr<media::VideoDecoder> std::unique_ptr<media::VideoDecoder>
BrowserGpuVideoAcceleratorFactories::CreateVideoDecoder( BrowserGpuVideoAcceleratorFactories::CreateVideoDecoder(
media::MediaLog* media_log, media::MediaLog* media_log,
......
...@@ -24,6 +24,8 @@ class BrowserGpuVideoAcceleratorFactories ...@@ -24,6 +24,8 @@ class BrowserGpuVideoAcceleratorFactories
bool IsGpuVideoAcceleratorEnabled() override; bool IsGpuVideoAcceleratorEnabled() override;
base::UnguessableToken GetChannelToken() override; base::UnguessableToken GetChannelToken() override;
int32_t GetCommandBufferRouteId() override; int32_t GetCommandBufferRouteId() override;
bool IsDecoderConfigSupported(
const media::VideoDecoderConfig& config) override;
std::unique_ptr<media::VideoDecoder> CreateVideoDecoder( std::unique_ptr<media::VideoDecoder> CreateVideoDecoder(
media::MediaLog* media_log, media::MediaLog* media_log,
const media::RequestOverlayInfoCB& request_overlay_info_cb, const media::RequestOverlayInfoCB& request_overlay_info_cb,
......
...@@ -32,7 +32,6 @@ ...@@ -32,7 +32,6 @@
#include "media/mojo/buildflags.h" #include "media/mojo/buildflags.h"
#include "media/mojo/clients/mojo_video_decoder.h" #include "media/mojo/clients/mojo_video_decoder.h"
#include "media/mojo/clients/mojo_video_encode_accelerator.h" #include "media/mojo/clients/mojo_video_encode_accelerator.h"
#include "media/mojo/interfaces/video_decoder.mojom.h"
#include "media/video/video_decode_accelerator.h" #include "media/video/video_decode_accelerator.h"
#include "media/video/video_encode_accelerator.h" #include "media/video/video_encode_accelerator.h"
#include "services/service_manager/public/cpp/connector.h" #include "services/service_manager/public/cpp/connector.h"
...@@ -120,8 +119,27 @@ void GpuVideoAcceleratorFactoriesImpl::BindOnTaskRunner( ...@@ -120,8 +119,27 @@ void GpuVideoAcceleratorFactoriesImpl::BindOnTaskRunner(
interface_factory_.Bind(std::move(interface_factory_info)); interface_factory_.Bind(std::move(interface_factory_info));
vea_provider_.Bind(std::move(vea_provider_info)); vea_provider_.Bind(std::move(vea_provider_info));
if (context_provider_->BindToCurrentThread() != gpu::ContextResult::kSuccess) if (context_provider_->BindToCurrentThread() !=
gpu::ContextResult::kSuccess) {
SetContextProviderLost(); SetContextProviderLost();
return;
}
#if BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER)
if (base::FeatureList::IsEnabled(media::kMojoVideoDecoder)) {
interface_factory_->CreateVideoDecoder(mojo::MakeRequest(&video_decoder_));
video_decoder_->GetSupportedConfigs(base::BindOnce(
&GpuVideoAcceleratorFactoriesImpl::OnSupportedDecoderConfigs,
base::Unretained(this)));
}
#endif // BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER)
}
void GpuVideoAcceleratorFactoriesImpl::OnSupportedDecoderConfigs(
std::vector<media::mojom::SupportedVideoDecoderConfigPtr>
supported_configs) {
supported_decoder_configs_ = std::move(supported_configs);
video_decoder_.reset();
} }
bool GpuVideoAcceleratorFactoriesImpl::CheckContextLost() { bool GpuVideoAcceleratorFactoriesImpl::CheckContextLost() {
...@@ -171,6 +189,30 @@ int32_t GpuVideoAcceleratorFactoriesImpl::GetCommandBufferRouteId() { ...@@ -171,6 +189,30 @@ int32_t GpuVideoAcceleratorFactoriesImpl::GetCommandBufferRouteId() {
return context_provider_->GetCommandBufferProxy()->route_id(); return context_provider_->GetCommandBufferProxy()->route_id();
} }
bool GpuVideoAcceleratorFactoriesImpl::IsDecoderConfigSupported(
const media::VideoDecoderConfig& config) {
// If GetSupportedConfigs() has not completed (or was never started), report
// that all configs are supported. Clients will find out that configs are not
// supported when VideoDecoder::Initialize() fails.
if (!supported_decoder_configs_)
return true;
for (const media::mojom::SupportedVideoDecoderConfigPtr& supported :
*supported_decoder_configs_) {
if (config.profile() >= supported->profile_min &&
config.profile() <= supported->profile_max &&
config.coded_size().width() >= supported->coded_size_min.width() &&
config.coded_size().width() <= supported->coded_size_max.width() &&
config.coded_size().height() >= supported->coded_size_min.height() &&
config.coded_size().height() <= supported->coded_size_max.height() &&
(config.is_encrypted() ? supported->allow_encrypted
: !supported->require_encrypted)) {
return true;
}
}
return false;
}
std::unique_ptr<media::VideoDecoder> std::unique_ptr<media::VideoDecoder>
GpuVideoAcceleratorFactoriesImpl::CreateVideoDecoder( GpuVideoAcceleratorFactoriesImpl::CreateVideoDecoder(
media::MediaLog* media_log, media::MediaLog* media_log,
......
...@@ -14,12 +14,14 @@ ...@@ -14,12 +14,14 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/single_thread_task_runner.h" #include "base/single_thread_task_runner.h"
#include "base/synchronization/waitable_event.h" #include "base/synchronization/waitable_event.h"
#include "base/unguessable_token.h" #include "base/unguessable_token.h"
#include "content/child/thread_safe_sender.h" #include "content/child/thread_safe_sender.h"
#include "content/common/content_export.h" #include "content/common/content_export.h"
#include "media/mojo/interfaces/interface_factory.mojom.h" #include "media/mojo/interfaces/interface_factory.mojom.h"
#include "media/mojo/interfaces/video_decoder.mojom.h"
#include "media/mojo/interfaces/video_encode_accelerator.mojom.h" #include "media/mojo/interfaces/video_encode_accelerator.mojom.h"
#include "media/video/gpu_video_accelerator_factories.h" #include "media/video/gpu_video_accelerator_factories.h"
#include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size.h"
...@@ -31,7 +33,7 @@ class GpuMemoryBufferManager; ...@@ -31,7 +33,7 @@ class GpuMemoryBufferManager;
namespace ui { namespace ui {
class ContextProviderCommandBuffer; class ContextProviderCommandBuffer;
} } // namespace ui
namespace content { namespace content {
...@@ -70,6 +72,8 @@ class CONTENT_EXPORT GpuVideoAcceleratorFactoriesImpl ...@@ -70,6 +72,8 @@ class CONTENT_EXPORT GpuVideoAcceleratorFactoriesImpl
media::MediaLog* media_log, media::MediaLog* media_log,
const media::RequestOverlayInfoCB& request_overlay_info_cb, const media::RequestOverlayInfoCB& request_overlay_info_cb,
const gfx::ColorSpace& target_color_space) override; const gfx::ColorSpace& target_color_space) override;
bool IsDecoderConfigSupported(
const media::VideoDecoderConfig& config) override;
std::unique_ptr<media::VideoDecodeAccelerator> CreateVideoDecodeAccelerator() std::unique_ptr<media::VideoDecodeAccelerator> CreateVideoDecodeAccelerator()
override; override;
std::unique_ptr<media::VideoEncodeAccelerator> CreateVideoEncodeAccelerator() std::unique_ptr<media::VideoEncodeAccelerator> CreateVideoEncodeAccelerator()
...@@ -151,6 +155,10 @@ class CONTENT_EXPORT GpuVideoAcceleratorFactoriesImpl ...@@ -151,6 +155,10 @@ class CONTENT_EXPORT GpuVideoAcceleratorFactoriesImpl
void SetContextProviderLost(); void SetContextProviderLost();
void SetContextProviderLostOnMainThread(); void SetContextProviderLostOnMainThread();
void OnSupportedDecoderConfigs(
std::vector<media::mojom::SupportedVideoDecoderConfigPtr>
supported_configs);
const scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_; const scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
const scoped_refptr<gpu::GpuChannelHost> gpu_channel_host_; const scoped_refptr<gpu::GpuChannelHost> gpu_channel_host_;
...@@ -180,6 +188,11 @@ class CONTENT_EXPORT GpuVideoAcceleratorFactoriesImpl ...@@ -180,6 +188,11 @@ class CONTENT_EXPORT GpuVideoAcceleratorFactoriesImpl
media::mojom::InterfaceFactoryPtr interface_factory_; media::mojom::InterfaceFactoryPtr interface_factory_;
media::mojom::VideoEncodeAcceleratorProviderPtr vea_provider_; media::mojom::VideoEncodeAcceleratorProviderPtr vea_provider_;
// SupportedDecoderConfigs state.
mojo::InterfacePtr<media::mojom::VideoDecoder> video_decoder_;
base::Optional<std::vector<media::mojom::SupportedVideoDecoderConfigPtr>>
supported_decoder_configs_;
// For sending requests to allocate shared memory in the Browser process. // For sending requests to allocate shared memory in the Browser process.
scoped_refptr<ThreadSafeSender> thread_safe_sender_; scoped_refptr<ThreadSafeSender> thread_safe_sender_;
......
...@@ -30,30 +30,6 @@ ...@@ -30,30 +30,6 @@
namespace media { namespace media {
namespace {
bool IsSupportedConfig(
const VideoDecodeAccelerator::SupportedProfiles& supported_profiles,
const VideoDecoderConfig& config) {
for (const auto& supported_profile : supported_profiles) {
if (config.profile() == supported_profile.profile &&
(!supported_profile.encrypted_only || config.is_encrypted()) &&
config.coded_size().width() >=
supported_profile.min_resolution.width() &&
config.coded_size().width() <=
supported_profile.max_resolution.width() &&
config.coded_size().height() >=
supported_profile.min_resolution.height() &&
config.coded_size().height() <=
supported_profile.max_resolution.height()) {
return true;
}
}
return false;
}
} // namespace
// Provides a thread-safe channel for VideoFrame destruction events. // Provides a thread-safe channel for VideoFrame destruction events.
class MojoVideoFrameHandleReleaser class MojoVideoFrameHandleReleaser
: public base::RefCountedThreadSafe<MojoVideoFrameHandleReleaser> { : public base::RefCountedThreadSafe<MojoVideoFrameHandleReleaser> {
...@@ -146,14 +122,10 @@ void MojoVideoDecoder::Initialize( ...@@ -146,14 +122,10 @@ void MojoVideoDecoder::Initialize(
DCHECK(task_runner_->BelongsToCurrentThread()); DCHECK(task_runner_->BelongsToCurrentThread());
// Fail immediately if we know that the remote side cannot support |config|. // Fail immediately if we know that the remote side cannot support |config|.
// if (gpu_factories_ && !gpu_factories_->IsDecoderConfigSupported(config)) {
// TODO(sandersd): Implement a generic mechanism for communicating supported // TODO(liberato): Remove bypass once D3D11VideoDecoder provides
// profiles. https://crbug.com/839951 // SupportedVideoDecoderConfigs.
if (gpu_factories_) { if (!base::FeatureList::IsEnabled(kD3D11VideoDecoder)) {
VideoDecodeAccelerator::Capabilities capabilities =
gpu_factories_->GetVideoDecodeAcceleratorCapabilities();
if (!base::FeatureList::IsEnabled(kD3D11VideoDecoder) &&
!IsSupportedConfig(capabilities.supported_profiles, config)) {
task_runner_->PostTask(FROM_HERE, base::BindRepeating(init_cb, false)); task_runner_->PostTask(FROM_HERE, base::BindRepeating(init_cb, false));
return; return;
} }
......
...@@ -8,8 +8,28 @@ import "gpu/ipc/common/sync_token.mojom"; ...@@ -8,8 +8,28 @@ import "gpu/ipc/common/sync_token.mojom";
import "media/mojo/interfaces/media_log.mojom"; import "media/mojo/interfaces/media_log.mojom";
import "media/mojo/interfaces/media_types.mojom"; import "media/mojo/interfaces/media_types.mojom";
import "mojo/public/mojom/base/unguessable_token.mojom"; import "mojo/public/mojom/base/unguessable_token.mojom";
import "ui/gfx/geometry/mojo/geometry.mojom";
import "ui/gfx/mojo/color_space.mojom"; import "ui/gfx/mojo/color_space.mojom";
// Serializable rule for matching VideoDecoderConfigs.
struct SupportedVideoDecoderConfig {
// Range of VideoCodecProfiles to match, inclusive.
VideoCodecProfile profile_min;
VideoCodecProfile profile_max;
// Range of coded sizes to match, inclusive in each dimension.
gfx.mojom.Size coded_size_min;
gfx.mojom.Size coded_size_max;
// Match configs that have encryption configured.
bool allow_encrypted;
// Do not match configs that do not have encryption configured. This is used
// on Android when the internal software decoder is preferred over the
// platform decoder (eg. when the platform decoder is a software decoder).
bool require_encrypted;
};
// Identifies a CommandBufferStub. MediaGpuChannelManager is responsible // Identifies a CommandBufferStub. MediaGpuChannelManager is responsible
// for minting |channel_token| values. // for minting |channel_token| values.
struct CommandBufferId { struct CommandBufferId {
...@@ -17,6 +37,11 @@ struct CommandBufferId { ...@@ -17,6 +37,11 @@ struct CommandBufferId {
int32 route_id; int32 route_id;
}; };
[Native]
struct OverlayInfo;
// Interface for releasing remote VideoFrames. It is separated from VideoDecoder
// so that VideoFrames can outlive their VideoDecoder.
interface VideoFrameHandleReleaser { interface VideoFrameHandleReleaser {
// Signals that the VideoFrame identified by |release_token| should be // Signals that the VideoFrame identified by |release_token| should be
// released. |release_sync_token| indicates the last use of the VideoFrame // released. |release_sync_token| indicates the last use of the VideoFrame
...@@ -28,14 +53,19 @@ interface VideoFrameHandleReleaser { ...@@ -28,14 +53,19 @@ interface VideoFrameHandleReleaser {
gpu.mojom.SyncToken release_sync_token); gpu.mojom.SyncToken release_sync_token);
}; };
[Native]
struct OverlayInfo;
// A Mojo equivalent of media::VideoDecoder. In practice, this is used for // A Mojo equivalent of media::VideoDecoder. In practice, this is used for
// hardware decode offloading; in this case the client is a <video> tag running // hardware decode offloading; in this case the client is a <video> tag running
// in a renderer, and the implementation is running in the GPU process. // in a renderer, and the implementation is running in the GPU process.
interface VideoDecoder { interface VideoDecoder {
// Initialize the decoder. This must be called before any other method. // Returns a list of supported configs. It is expected that Initialize() will
// fail for any config that does not match an entry in this list.
//
// May be called before Construct().
GetSupportedConfigs() =>
(array<SupportedVideoDecoderConfig> supported_configs);
// Initialize the decoder. This must be called before any method other than
// GetSupportedConfigs().
// //
// |client| provides asynchronous client methods to the VideoDecoder, such // |client| provides asynchronous client methods to the VideoDecoder, such
// as delivery of decoded VideoFrame outputs. // as delivery of decoded VideoFrame outputs.
......
...@@ -15,8 +15,12 @@ ...@@ -15,8 +15,12 @@
#include "media/base/media_switches.h" #include "media/base/media_switches.h"
#include "media/base/video_decoder.h" #include "media/base/video_decoder.h"
#include "media/gpu/buildflags.h" #include "media/gpu/buildflags.h"
#include "media/gpu/gpu_video_accelerator_util.h"
#include "media/gpu/gpu_video_decode_accelerator_factory.h"
#include "media/gpu/ipc/service/media_gpu_channel_manager.h" #include "media/gpu/ipc/service/media_gpu_channel_manager.h"
#include "media/gpu/ipc/service/vda_video_decoder.h" #include "media/gpu/ipc/service/vda_video_decoder.h"
#include "media/mojo/interfaces/video_decoder.mojom.h"
#include "media/video/video_decode_accelerator.h"
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
...@@ -94,13 +98,37 @@ std::unique_ptr<AudioDecoder> GpuMojoMediaClient::CreateAudioDecoder( ...@@ -94,13 +98,37 @@ std::unique_ptr<AudioDecoder> GpuMojoMediaClient::CreateAudioDecoder(
#endif // defined(OS_ANDROID) #endif // defined(OS_ANDROID)
} }
std::vector<mojom::SupportedVideoDecoderConfigPtr>
GpuMojoMediaClient::GetSupportedVideoDecoderConfigs() {
// TODO(liberato): Implement for D3D11VideoDecoder and MediaCodecVideoDecoder.
VideoDecodeAccelerator::Capabilities capabilities =
GpuVideoAcceleratorUtil::ConvertGpuToMediaDecodeCapabilities(
GpuVideoDecodeAcceleratorFactory::GetDecoderCapabilities(
gpu_preferences_, gpu_workarounds_));
bool allow_encrypted =
capabilities.flags &
VideoDecodeAccelerator::Capabilities::SUPPORTS_ENCRYPTED_STREAMS;
std::vector<mojom::SupportedVideoDecoderConfigPtr> supported_configs;
for (const auto& supported_profile : capabilities.supported_profiles) {
supported_configs.push_back(mojom::SupportedVideoDecoderConfig::New(
supported_profile.profile, // profile_min
supported_profile.profile, // profile_max
supported_profile.min_resolution, // coded_size_min
supported_profile.max_resolution, // coded_size_max
allow_encrypted, // allow_encrypted
supported_profile.encrypted_only)); // require_encrypted
}
return supported_configs;
}
std::unique_ptr<VideoDecoder> GpuMojoMediaClient::CreateVideoDecoder( std::unique_ptr<VideoDecoder> GpuMojoMediaClient::CreateVideoDecoder(
scoped_refptr<base::SingleThreadTaskRunner> task_runner, scoped_refptr<base::SingleThreadTaskRunner> task_runner,
MediaLog* media_log, MediaLog* media_log,
mojom::CommandBufferIdPtr command_buffer_id, mojom::CommandBufferIdPtr command_buffer_id,
RequestOverlayInfoCB request_overlay_info_cb, RequestOverlayInfoCB request_overlay_info_cb,
const gfx::ColorSpace& target_color_space) { const gfx::ColorSpace& target_color_space) {
// All implemetnations require a command buffer. // All implementations require a command buffer.
if (!command_buffer_id) if (!command_buffer_id)
return nullptr; return nullptr;
......
...@@ -37,6 +37,8 @@ class GpuMojoMediaClient : public MojoMediaClient { ...@@ -37,6 +37,8 @@ class GpuMojoMediaClient : public MojoMediaClient {
~GpuMojoMediaClient() final; ~GpuMojoMediaClient() final;
// MojoMediaClient implementation. // MojoMediaClient implementation.
std::vector<mojom::SupportedVideoDecoderConfigPtr>
GetSupportedVideoDecoderConfigs() final;
void Initialize(service_manager::Connector* connector) final; void Initialize(service_manager::Connector* connector) final;
std::unique_ptr<AudioDecoder> CreateAudioDecoder( std::unique_ptr<AudioDecoder> CreateAudioDecoder(
scoped_refptr<base::SingleThreadTaskRunner> task_runner) final; scoped_refptr<base::SingleThreadTaskRunner> task_runner) final;
......
...@@ -28,6 +28,11 @@ std::unique_ptr<AudioDecoder> MojoMediaClient::CreateAudioDecoder( ...@@ -28,6 +28,11 @@ std::unique_ptr<AudioDecoder> MojoMediaClient::CreateAudioDecoder(
return nullptr; return nullptr;
} }
std::vector<mojom::SupportedVideoDecoderConfigPtr>
MojoMediaClient::GetSupportedVideoDecoderConfigs() {
return std::vector<mojom::SupportedVideoDecoderConfigPtr>();
}
std::unique_ptr<VideoDecoder> MojoMediaClient::CreateVideoDecoder( std::unique_ptr<VideoDecoder> MojoMediaClient::CreateVideoDecoder(
scoped_refptr<base::SingleThreadTaskRunner> task_runner, scoped_refptr<base::SingleThreadTaskRunner> task_runner,
MediaLog* media_log, MediaLog* media_log,
......
...@@ -54,6 +54,9 @@ class MEDIA_MOJO_EXPORT MojoMediaClient { ...@@ -54,6 +54,9 @@ class MEDIA_MOJO_EXPORT MojoMediaClient {
virtual std::unique_ptr<AudioDecoder> CreateAudioDecoder( virtual std::unique_ptr<AudioDecoder> CreateAudioDecoder(
scoped_refptr<base::SingleThreadTaskRunner> task_runner); scoped_refptr<base::SingleThreadTaskRunner> task_runner);
virtual std::vector<mojom::SupportedVideoDecoderConfigPtr>
GetSupportedVideoDecoderConfigs();
virtual std::unique_ptr<VideoDecoder> CreateVideoDecoder( virtual std::unique_ptr<VideoDecoder> CreateVideoDecoder(
scoped_refptr<base::SingleThreadTaskRunner> task_runner, scoped_refptr<base::SingleThreadTaskRunner> task_runner,
MediaLog* media_log, MediaLog* media_log,
......
...@@ -119,6 +119,14 @@ MojoVideoDecoderService::~MojoVideoDecoderService() { ...@@ -119,6 +119,14 @@ MojoVideoDecoderService::~MojoVideoDecoderService() {
g_num_active_mvd_instances--; g_num_active_mvd_instances--;
} }
void MojoVideoDecoderService::GetSupportedConfigs(
GetSupportedConfigsCallback callback) {
DVLOG(3) << __func__;
std::move(callback).Run(
mojo_media_client_->GetSupportedVideoDecoderConfigs());
}
void MojoVideoDecoderService::Construct( void MojoVideoDecoderService::Construct(
mojom::VideoDecoderClientAssociatedPtrInfo client, mojom::VideoDecoderClientAssociatedPtrInfo client,
mojom::MediaLogAssociatedPtrInfo media_log, mojom::MediaLogAssociatedPtrInfo media_log,
...@@ -129,8 +137,7 @@ void MojoVideoDecoderService::Construct( ...@@ -129,8 +137,7 @@ void MojoVideoDecoderService::Construct(
DVLOG(1) << __func__; DVLOG(1) << __func__;
if (decoder_) { if (decoder_) {
// TODO(sandersd): Close the channel. mojo::ReportBadMessage("Construct() already called");
DLOG(ERROR) << "|decoder_| already exists";
return; return;
} }
......
...@@ -41,6 +41,7 @@ class MEDIA_MOJO_EXPORT MojoVideoDecoderService final ...@@ -41,6 +41,7 @@ class MEDIA_MOJO_EXPORT MojoVideoDecoderService final
~MojoVideoDecoderService() final; ~MojoVideoDecoderService() final;
// mojom::VideoDecoder implementation // mojom::VideoDecoder implementation
void GetSupportedConfigs(GetSupportedConfigsCallback callback) final;
void Construct( void Construct(
mojom::VideoDecoderClientAssociatedPtrInfo client, mojom::VideoDecoderClientAssociatedPtrInfo client,
mojom::MediaLogAssociatedPtrInfo media_log, mojom::MediaLogAssociatedPtrInfo media_log,
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "media/base/decode_status.h" #include "media/base/decode_status.h"
#include "media/base/decoder_buffer.h" #include "media/base/decoder_buffer.h"
#include "media/base/gmock_callback_support.h" #include "media/base/gmock_callback_support.h"
#include "media/base/media_log.h"
#include "media/base/mock_media_log.h" #include "media/base/mock_media_log.h"
#include "media/base/test_helpers.h" #include "media/base/test_helpers.h"
#include "media/base/video_decoder.h" #include "media/base/video_decoder.h"
...@@ -37,6 +38,7 @@ ...@@ -37,6 +38,7 @@
using ::testing::_; using ::testing::_;
using ::testing::AtLeast; using ::testing::AtLeast;
using ::testing::HasSubstr;
using ::testing::Invoke; using ::testing::Invoke;
using ::testing::InSequence; using ::testing::InSequence;
using ::testing::Mock; using ::testing::Mock;
...@@ -66,7 +68,6 @@ class MockVideoDecoder : public VideoDecoder { ...@@ -66,7 +68,6 @@ class MockVideoDecoder : public VideoDecoder {
.WillRepeatedly(Return(kMaxDecodeRequests)); .WillRepeatedly(Return(kMaxDecodeRequests));
// For regular methods, only configure a default action. // For regular methods, only configure a default action.
ON_CALL(*this, DoInitialize(_)).WillByDefault(RunCallback<0>(true));
ON_CALL(*this, Decode(_, _)) ON_CALL(*this, Decode(_, _))
.WillByDefault(Invoke(this, &MockVideoDecoder::DoDecode)); .WillByDefault(Invoke(this, &MockVideoDecoder::DoDecode));
ON_CALL(*this, Reset(_)) ON_CALL(*this, Reset(_))
...@@ -178,17 +179,7 @@ class MojoVideoDecoderIntegrationTest : public ::testing::Test { ...@@ -178,17 +179,7 @@ class MojoVideoDecoderIntegrationTest : public ::testing::Test {
MojoVideoDecoderIntegrationTest() MojoVideoDecoderIntegrationTest()
: mojo_media_client_( : mojo_media_client_(
base::Bind(&MojoVideoDecoderIntegrationTest::CreateVideoDecoder, base::Bind(&MojoVideoDecoderIntegrationTest::CreateVideoDecoder,
base::Unretained(this))) { base::Unretained(this))) {}
mojom::VideoDecoderPtr remote_video_decoder;
binding_ = mojo::MakeStrongBinding(
std::make_unique<MojoVideoDecoderService>(&mojo_media_client_,
&mojo_cdm_service_context_),
mojo::MakeRequest(&remote_video_decoder));
client_ = std::make_unique<MojoVideoDecoder>(
base::ThreadTaskRunnerHandle::Get(), nullptr, &client_media_log_,
std::move(remote_video_decoder), RequestOverlayInfoCB(),
gfx::ColorSpace());
}
void TearDown() override { void TearDown() override {
if (client_) { if (client_) {
...@@ -200,15 +191,34 @@ class MojoVideoDecoderIntegrationTest : public ::testing::Test { ...@@ -200,15 +191,34 @@ class MojoVideoDecoderIntegrationTest : public ::testing::Test {
protected: protected:
void RunUntilIdle() { scoped_task_environment_.RunUntilIdle(); } void RunUntilIdle() { scoped_task_environment_.RunUntilIdle(); }
void SetWriterCapacity(uint32_t capacity) { void SetWriterCapacity(uint32_t capacity) { writer_capacity_ = capacity; }
client_->set_writer_capacity_for_testing(capacity);
mojom::VideoDecoderPtr CreateRemoteVideoDecoder() {
mojom::VideoDecoderPtr remote_video_decoder;
mojo::MakeStrongBinding(
std::make_unique<MojoVideoDecoderService>(&mojo_media_client_,
&mojo_cdm_service_context_),
mojo::MakeRequest(&remote_video_decoder));
return remote_video_decoder;
}
void CreateClient() {
DCHECK(!client_);
// TODO(sandersd): Pass a GpuVideoAcceleratorFactories so that the cache can
// be tested.
client_ = std::make_unique<MojoVideoDecoder>(
base::ThreadTaskRunnerHandle::Get(), nullptr, &client_media_log_,
CreateRemoteVideoDecoder(), RequestOverlayInfoCB(), gfx::ColorSpace());
if (writer_capacity_)
client_->set_writer_capacity_for_testing(writer_capacity_);
} }
bool Initialize() { bool Initialize() {
bool result = false; CreateClient();
EXPECT_CALL(*decoder_, DoInitialize(_)); EXPECT_CALL(*decoder_, DoInitialize(_)).WillOnce(RunCallback<0>(true));
bool result = false;
StrictMock<base::MockCallback<VideoDecoder::InitCB>> init_cb; StrictMock<base::MockCallback<VideoDecoder::InitCB>> init_cb;
EXPECT_CALL(init_cb, Run(_)).WillOnce(SaveArg<0>(&result)); EXPECT_CALL(init_cb, Run(_)).WillOnce(SaveArg<0>(&result));
...@@ -282,19 +292,31 @@ class MojoVideoDecoderIntegrationTest : public ::testing::Test { ...@@ -282,19 +292,31 @@ class MojoVideoDecoderIntegrationTest : public ::testing::Test {
base::test::ScopedTaskEnvironment scoped_task_environment_; base::test::ScopedTaskEnvironment scoped_task_environment_;
// Capacity that will be used for the MojoDecoderBufferWriter.
uint32_t writer_capacity_ = 0;
MojoCdmServiceContext mojo_cdm_service_context_; MojoCdmServiceContext mojo_cdm_service_context_;
// Provides |decoder_| to the service. // Provides |decoder_| to the service.
FakeMojoMediaClient mojo_media_client_; FakeMojoMediaClient mojo_media_client_;
// Owns the service, bound to |client_|.
mojo::StrongBindingPtr<mojom::VideoDecoder> binding_;
DISALLOW_COPY_AND_ASSIGN(MojoVideoDecoderIntegrationTest); DISALLOW_COPY_AND_ASSIGN(MojoVideoDecoderIntegrationTest);
}; };
TEST_F(MojoVideoDecoderIntegrationTest, CreateAndDestroy) {} TEST_F(MojoVideoDecoderIntegrationTest, CreateAndDestroy) {}
TEST_F(MojoVideoDecoderIntegrationTest, GetSupportedConfigs) {
mojom::VideoDecoderPtr remote_video_decoder = CreateRemoteVideoDecoder();
StrictMock<
base::MockCallback<mojom::VideoDecoder::GetSupportedConfigsCallback>>
callback;
// TODO(sandersd): Expect there to be an entry.
EXPECT_CALL(callback, Run(_));
remote_video_decoder->GetSupportedConfigs(callback.Get());
RunUntilIdle();
}
TEST_F(MojoVideoDecoderIntegrationTest, Initialize) { TEST_F(MojoVideoDecoderIntegrationTest, Initialize) {
ASSERT_TRUE(Initialize()); ASSERT_TRUE(Initialize());
EXPECT_EQ(client_->GetDisplayName(), "MojoVideoDecoder"); EXPECT_EQ(client_->GetDisplayName(), "MojoVideoDecoder");
...@@ -303,6 +325,13 @@ TEST_F(MojoVideoDecoderIntegrationTest, Initialize) { ...@@ -303,6 +325,13 @@ TEST_F(MojoVideoDecoderIntegrationTest, Initialize) {
EXPECT_EQ(client_->GetMaxDecodeRequests(), kMaxDecodeRequests); EXPECT_EQ(client_->GetMaxDecodeRequests(), kMaxDecodeRequests);
} }
TEST_F(MojoVideoDecoderIntegrationTest, MediaLogIsProxied) {
ASSERT_TRUE(Initialize());
EXPECT_MEDIA_LOG_ON(client_media_log_, HasSubstr("\"test\""));
MEDIA_LOG(DEBUG, decoder_media_log_) << "test";
RunUntilIdle();
}
TEST_F(MojoVideoDecoderIntegrationTest, Decode) { TEST_F(MojoVideoDecoderIntegrationTest, Decode) {
ASSERT_TRUE(Initialize()); ASSERT_TRUE(Initialize());
...@@ -374,7 +403,6 @@ TEST_F(MojoVideoDecoderIntegrationTest, ResetDuringDecode) { ...@@ -374,7 +403,6 @@ TEST_F(MojoVideoDecoderIntegrationTest, ResetDuringDecode) {
TEST_F(MojoVideoDecoderIntegrationTest, ResetDuringDecode_ChunkedWrite) { TEST_F(MojoVideoDecoderIntegrationTest, ResetDuringDecode_ChunkedWrite) {
// Use a small writer capacity to force chunked write. // Use a small writer capacity to force chunked write.
SetWriterCapacity(10); SetWriterCapacity(10);
ASSERT_TRUE(Initialize()); ASSERT_TRUE(Initialize());
VideoFrame::ReleaseMailboxCB release_cb = VideoFrame::ReleaseMailboxCB(); VideoFrame::ReleaseMailboxCB release_cb = VideoFrame::ReleaseMailboxCB();
......
...@@ -78,6 +78,10 @@ class MEDIA_EXPORT GpuVideoAcceleratorFactories { ...@@ -78,6 +78,10 @@ class MEDIA_EXPORT GpuVideoAcceleratorFactories {
// Returns the |route_id| of the command buffer, or 0 if there is none. // Returns the |route_id| of the command buffer, or 0 if there is none.
virtual int32_t GetCommandBufferRouteId() = 0; virtual int32_t GetCommandBufferRouteId() = 0;
// Return true if |config| is potentially supported by a decoder created with
// CreateVideoDecoder().
virtual bool IsDecoderConfigSupported(const VideoDecoderConfig& config) = 0;
virtual std::unique_ptr<media::VideoDecoder> CreateVideoDecoder( virtual std::unique_ptr<media::VideoDecoder> CreateVideoDecoder(
MediaLog* media_log, MediaLog* media_log,
const RequestOverlayInfoCB& request_overlay_info_cb, const RequestOverlayInfoCB& request_overlay_info_cb,
......
...@@ -36,6 +36,7 @@ class MockGpuVideoAcceleratorFactories : public GpuVideoAcceleratorFactories { ...@@ -36,6 +36,7 @@ class MockGpuVideoAcceleratorFactories : public GpuVideoAcceleratorFactories {
MOCK_METHOD0(GetChannelToken, base::UnguessableToken()); MOCK_METHOD0(GetChannelToken, base::UnguessableToken());
MOCK_METHOD0(GetCommandBufferRouteId, int32_t()); MOCK_METHOD0(GetCommandBufferRouteId, int32_t());
MOCK_METHOD1(IsDecoderConfigSupported, bool(const VideoDecoderConfig&));
MOCK_METHOD3(CreateVideoDecoder, MOCK_METHOD3(CreateVideoDecoder,
std::unique_ptr<media::VideoDecoder>(MediaLog*, std::unique_ptr<media::VideoDecoder>(MediaLog*,
const RequestOverlayInfoCB&, const RequestOverlayInfoCB&,
......
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