blob: c4bcbb2ebb4093e2b7cb08c5775c6d5d6af2b769 [file] [log] [blame]
// Copyright 2016 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 "media/mojo/services/gpu_mojo_media_client.h"
#include <utility>
#include "base/bind.h"
#include "base/feature_list.h"
#include "base/memory/ptr_util.h"
#include "build/chromeos_buildflags.h"
#include "gpu/ipc/service/gpu_channel.h"
#include "media/base/audio_decoder.h"
#include "media/base/cdm_factory.h"
#include "media/base/media_switches.h"
#include "media/base/media_util.h"
#include "media/base/video_decoder.h"
#include "media/gpu/gpu_video_accelerator_util.h"
#include "media/gpu/gpu_video_decode_accelerator_factory.h"
#include "media/gpu/gpu_video_decode_accelerator_helpers.h"
#include "media/gpu/ipc/service/media_gpu_channel_manager.h"
#include "media/gpu/ipc/service/vda_video_decoder.h"
#include "media/mojo/mojom/video_decoder.mojom.h"
#include "media/video/video_decode_accelerator.h"
namespace media {
namespace {
gpu::CommandBufferStub* GetCommandBufferStub(
scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
base::WeakPtr<MediaGpuChannelManager> media_gpu_channel_manager,
base::UnguessableToken channel_token,
int32_t route_id) {
DCHECK(gpu_task_runner->BelongsToCurrentThread());
if (!media_gpu_channel_manager)
return nullptr;
gpu::GpuChannel* channel =
media_gpu_channel_manager->LookupChannel(channel_token);
if (!channel)
return nullptr;
gpu::CommandBufferStub* stub = channel->LookupCommandBuffer(route_id);
if (!stub)
return nullptr;
// Only allow stubs that have a ContextGroup, that is, the GLES2 ones. Later
// code assumes the ContextGroup is valid.
if (!stub->decoder_context()->GetContextGroup())
return nullptr;
return stub;
}
} // namespace
VideoDecoderTraits::~VideoDecoderTraits() = default;
VideoDecoderTraits::VideoDecoderTraits(
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
std::unique_ptr<MediaLog> media_log,
RequestOverlayInfoCB request_overlay_info_cb,
const gfx::ColorSpace* target_color_space,
gpu::GpuMemoryBufferFactory* gpu_memory_buffer_factory,
GetCommandBufferStubCB get_command_buffer_stub_cb,
AndroidOverlayMojoFactoryCB android_overlay_factory_cb)
: task_runner(std::move(task_runner)),
gpu_task_runner(std::move(gpu_task_runner)),
media_log(std::move(media_log)),
request_overlay_info_cb(request_overlay_info_cb),
target_color_space(target_color_space),
gpu_memory_buffer_factory(gpu_memory_buffer_factory),
get_command_buffer_stub_cb(std::move(get_command_buffer_stub_cb)),
android_overlay_factory_cb(std::move(android_overlay_factory_cb)) {}
GpuMojoMediaClient::GpuMojoMediaClient(
const gpu::GpuPreferences& gpu_preferences,
const gpu::GpuDriverBugWorkarounds& gpu_workarounds,
const gpu::GpuFeatureInfo& gpu_feature_info,
scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
base::WeakPtr<MediaGpuChannelManager> media_gpu_channel_manager,
gpu::GpuMemoryBufferFactory* gpu_memory_buffer_factory,
AndroidOverlayMojoFactoryCB android_overlay_factory_cb)
: gpu_preferences_(gpu_preferences),
gpu_workarounds_(gpu_workarounds),
gpu_feature_info_(gpu_feature_info),
gpu_task_runner_(std::move(gpu_task_runner)),
media_gpu_channel_manager_(std::move(media_gpu_channel_manager)),
android_overlay_factory_cb_(std::move(android_overlay_factory_cb)),
gpu_memory_buffer_factory_(gpu_memory_buffer_factory),
platform_(PlatformDelegate::Create(this)) {}
GpuMojoMediaClient::~GpuMojoMediaClient() = default;
GpuMojoMediaClient::PlatformDelegate::~PlatformDelegate() = default;
std::unique_ptr<VideoDecoder>
GpuMojoMediaClient::PlatformDelegate::CreateVideoDecoder(
const VideoDecoderTraits&) {
return nullptr;
}
void GpuMojoMediaClient::PlatformDelegate::GetSupportedVideoDecoderConfigs(
MojoMediaClient::SupportedVideoDecoderConfigsCallback callback) {
std::move(callback).Run({});
}
std::unique_ptr<AudioDecoder>
GpuMojoMediaClient::PlatformDelegate::CreateAudioDecoder(
scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
return nullptr;
}
std::unique_ptr<CdmFactory>
GpuMojoMediaClient::PlatformDelegate::CreateCdmFactory(
mojom::FrameInterfaceFactory* frame_interfaces) {
return nullptr;
}
VideoDecoderType
GpuMojoMediaClient::PlatformDelegate::GetDecoderImplementationType() {
return VideoDecoderType::kUnknown;
}
std::unique_ptr<AudioDecoder> GpuMojoMediaClient::CreateAudioDecoder(
scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
return platform_->CreateAudioDecoder(task_runner);
}
VideoDecoderType GpuMojoMediaClient::GetDecoderImplementationType() {
return platform_->GetDecoderImplementationType();
}
void GpuMojoMediaClient::GetSupportedVideoDecoderConfigs(
MojoMediaClient::SupportedVideoDecoderConfigsCallback callback) {
if (supported_config_cache_) {
DCHECK(pending_supported_config_callbacks_.empty());
std::move(callback).Run(*supported_config_cache_);
return;
}
const bool should_query = pending_supported_config_callbacks_.empty();
pending_supported_config_callbacks_.push_back(std::move(callback));
if (should_query) {
// Only get configurations if there is no query already in flight.
platform_->GetSupportedVideoDecoderConfigs(
base::BindOnce(&GpuMojoMediaClient::OnSupportedVideoDecoderConfigs,
base::Unretained(this)));
}
}
void GpuMojoMediaClient::OnSupportedVideoDecoderConfigs(
SupportedVideoDecoderConfigs configs) {
DCHECK(!pending_supported_config_callbacks_.empty());
// Return the result to all pending queries.
supported_config_cache_ = std::move(configs);
for (auto& callback : pending_supported_config_callbacks_) {
std::move(callback).Run(*supported_config_cache_);
}
pending_supported_config_callbacks_.clear();
}
SupportedVideoDecoderConfigs GpuMojoMediaClient::GetVDAVideoDecoderConfigs() {
VideoDecodeAccelerator::Capabilities capabilities =
GpuVideoAcceleratorUtil::ConvertGpuToMediaDecodeCapabilities(
GpuVideoDecodeAcceleratorFactory::GetDecoderCapabilities(
gpu_preferences_, gpu_workarounds_));
return ConvertFromSupportedProfiles(
capabilities.supported_profiles,
capabilities.flags &
VideoDecodeAccelerator::Capabilities::SUPPORTS_ENCRYPTED_STREAMS);
}
std::unique_ptr<VideoDecoder> GpuMojoMediaClient::CreateVideoDecoder(
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
MediaLog* media_log,
mojom::CommandBufferIdPtr command_buffer_id,
RequestOverlayInfoCB request_overlay_info_cb,
const gfx::ColorSpace& target_color_space) {
// All implementations require a command buffer.
if (!command_buffer_id)
return nullptr;
std::unique_ptr<MediaLog> log =
media_log ? media_log->Clone() : std::make_unique<media::NullMediaLog>();
VideoDecoderTraits traits(
task_runner, gpu_task_runner_, std::move(log),
std::move(request_overlay_info_cb), &target_color_space,
gpu_memory_buffer_factory_,
base::BindRepeating(
&GetCommandBufferStub, gpu_task_runner_, media_gpu_channel_manager_,
command_buffer_id->channel_token, command_buffer_id->route_id),
std::move(android_overlay_factory_cb_));
return platform_->CreateVideoDecoder(traits);
}
std::unique_ptr<CdmFactory> GpuMojoMediaClient::CreateCdmFactory(
mojom::FrameInterfaceFactory* frame_interfaces) {
return platform_->CreateCdmFactory(frame_interfaces);
}
} // namespace media