gpu: Migrate Media GPU VDA IPCs to Mojo
GpuVideoDecodeAccelerator/Host runs IPCs between renderer and GPU processes, sharing a route with a specific CommandBufferStub/ProxyImpl. This is a bit tricky to do with Mojo because Media IPCs are a layer above GPU, and we therefore need CommandBuffer-associated interfaces that CommandBuffer doesn't know about. To facilitate this we introduce a generic BindMediaReceiver API on CommandBuffer which takes a mojo::GenericPendingAssociatedReceiver, i.e. an associated interface endpoint that can be of any type. We then introduce a GPU-side hook that the Media stack can use to handle such requests. The primordial associated interface introduced here is GpuAcceleratedVideoDecoderProvider, which in turn has a single IPC for binding a GpuAcceleratedVideoDecoder/Client pair, also associated with the CommandBuffer. This migration removes the last remaining legacy IPC messages used by the GPU process, so once this is landed we can altogether remove IPC Channel from GPU code. Bug: 1196476, 993189 Change-Id: Ife986434b3c10b5796ce995d837a37c29514af49 Test: manually tested with custom extension doing a hardware VP9 decode via pp::VideoDecoder Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2956897 Reviewed-by: Tom Sepez <tsepez@chromium.org> Reviewed-by: Avi Drissman <avi@chromium.org> Reviewed-by: Sean Topping <seantopping@chromium.org> Reviewed-by: Robert Sesek <rsesek@chromium.org> Reviewed-by: Sunny Sachanandani <sunnyps@chromium.org> Reviewed-by: Dan Sanders <sandersd@chromium.org> Commit-Queue: Ken Rockot <rockot@google.com> Cr-Commit-Position: refs/heads/master@{#893111}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
b9d7179486
commit
a55ea67117
chromecast/media/gpu
content
browser
media
renderer
gpu/ipc
client
common
service
ipc
media
gpu
ipc
client
common
service
mojo
mojo/public/cpp/bindings
tools/ipc_fuzzer
@ -14,7 +14,6 @@
|
|||||||
#include "media/base/media_util.h"
|
#include "media/base/media_util.h"
|
||||||
#include "media/gpu/gpu_video_accelerator_util.h"
|
#include "media/gpu/gpu_video_accelerator_util.h"
|
||||||
#include "media/gpu/ipc/client/gpu_video_decode_accelerator_host.h"
|
#include "media/gpu/ipc/client/gpu_video_decode_accelerator_host.h"
|
||||||
#include "media/gpu/ipc/common/media_messages.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 "services/viz/public/cpp/gpu/context_provider_command_buffer.h"
|
#include "services/viz/public/cpp/gpu/context_provider_command_buffer.h"
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
#include "gpu/ipc/client/command_buffer_proxy_impl.h"
|
#include "gpu/ipc/client/command_buffer_proxy_impl.h"
|
||||||
#include "gpu/ipc/client/gpu_channel_host.h"
|
#include "gpu/ipc/client/gpu_channel_host.h"
|
||||||
#include "media/gpu/gpu_video_accelerator_util.h"
|
#include "media/gpu/gpu_video_accelerator_util.h"
|
||||||
#include "media/gpu/ipc/common/media_messages.h"
|
|
||||||
#include "services/viz/public/cpp/gpu/context_provider_command_buffer.h"
|
#include "services/viz/public/cpp/gpu/context_provider_command_buffer.h"
|
||||||
|
|
||||||
namespace content {
|
namespace content {
|
||||||
|
@ -28,7 +28,6 @@
|
|||||||
#include "gpu/ipc/common/gpu_memory_buffer_support.h"
|
#include "gpu/ipc/common/gpu_memory_buffer_support.h"
|
||||||
#include "media/base/bind_to_current_loop.h"
|
#include "media/base/bind_to_current_loop.h"
|
||||||
#include "media/gpu/gpu_video_accelerator_util.h"
|
#include "media/gpu/gpu_video_accelerator_util.h"
|
||||||
#include "media/gpu/ipc/common/media_messages.h"
|
|
||||||
#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"
|
||||||
|
@ -158,6 +158,11 @@ void CommandBufferProxyImpl::OnDisconnect() {
|
|||||||
OnGpuAsyncMessageError(context_lost_reason, gpu::error::kLostContext);
|
OnGpuAsyncMessageError(context_lost_reason, gpu::error::kLostContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CommandBufferProxyImpl::BindMediaReceiver(
|
||||||
|
mojo::GenericPendingAssociatedReceiver receiver) {
|
||||||
|
command_buffer_->BindMediaReceiver(std::move(receiver));
|
||||||
|
}
|
||||||
|
|
||||||
void CommandBufferProxyImpl::OnDestroyed(gpu::error::ContextLostReason reason,
|
void CommandBufferProxyImpl::OnDestroyed(gpu::error::ContextLostReason reason,
|
||||||
gpu::error::Error error) {
|
gpu::error::Error error) {
|
||||||
base::AutoLockMaybe lock(lock_);
|
base::AutoLockMaybe lock(lock_);
|
||||||
|
@ -97,6 +97,11 @@ class GPU_EXPORT CommandBufferProxyImpl : public gpu::CommandBuffer,
|
|||||||
|
|
||||||
void OnDisconnect();
|
void OnDisconnect();
|
||||||
|
|
||||||
|
// Asks the GPU side to bind an associated interface which will share message
|
||||||
|
// ordering with this command buffer. Used by media clients for interfaces not
|
||||||
|
// defined at the GPU layer.
|
||||||
|
void BindMediaReceiver(mojo::GenericPendingAssociatedReceiver receiver);
|
||||||
|
|
||||||
// CommandBuffer implementation:
|
// CommandBuffer implementation:
|
||||||
State GetLastState() override;
|
State GetLastState() override;
|
||||||
void Flush(int32_t put_offset) override;
|
void Flush(int32_t put_offset) override;
|
||||||
|
@ -12,6 +12,7 @@ import "gpu/ipc/common/sync_token.mojom";
|
|||||||
import "gpu/ipc/common/vulkan_ycbcr_info.mojom";
|
import "gpu/ipc/common/vulkan_ycbcr_info.mojom";
|
||||||
import "mojo/public/mojom/base/shared_memory.mojom";
|
import "mojo/public/mojom/base/shared_memory.mojom";
|
||||||
import "mojo/public/mojom/base/unguessable_token.mojom";
|
import "mojo/public/mojom/base/unguessable_token.mojom";
|
||||||
|
import "mojo/public/mojom/base/generic_pending_associated_receiver.mojom";
|
||||||
import "services/viz/public/mojom/compositing/resource_format.mojom";
|
import "services/viz/public/mojom/compositing/resource_format.mojom";
|
||||||
import "skia/public/mojom/image_info.mojom";
|
import "skia/public/mojom/image_info.mojom";
|
||||||
import "skia/public/mojom/surface_origin.mojom";
|
import "skia/public/mojom/surface_origin.mojom";
|
||||||
@ -268,6 +269,13 @@ interface CommandBuffer {
|
|||||||
// then sends a corresponding SignalAck on the CommandBufferClient interface,
|
// then sends a corresponding SignalAck on the CommandBufferClient interface,
|
||||||
// using `signal_id` to identify this request.
|
// using `signal_id` to identify this request.
|
||||||
SignalQuery(uint32 query, uint32 signal_id);
|
SignalQuery(uint32 query, uint32 signal_id);
|
||||||
|
|
||||||
|
// Binds an associated interface which shares its message ordering with this
|
||||||
|
// CommandBuffer. This allows the Media stack above the core GPU layer to
|
||||||
|
// establish such interfaces without introducing a layering violation. See
|
||||||
|
// GpuChannel::set_command_buffer_media_binder().
|
||||||
|
[Sync] BindMediaReceiver(
|
||||||
|
mojo_base.mojom.GenericPendingAssociatedReceiver receiver) => ();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Corresponds to gpu::SwapBuffersCompleteParams.
|
// Corresponds to gpu::SwapBuffersCompleteParams.
|
||||||
|
@ -600,6 +600,16 @@ void CommandBufferStub::SignalQuery(uint32_t query_id, uint32_t id) {
|
|||||||
OnSignalAck(id);
|
OnSignalAck(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CommandBufferStub::BindMediaReceiver(
|
||||||
|
mojo::GenericPendingAssociatedReceiver receiver,
|
||||||
|
BindMediaReceiverCallback callback) {
|
||||||
|
const auto& binder = channel_->command_buffer_media_binder();
|
||||||
|
if (binder)
|
||||||
|
binder.Run(this, std::move(receiver));
|
||||||
|
std::move(callback).Run();
|
||||||
|
}
|
||||||
|
|
||||||
void CommandBufferStub::OnFenceSyncRelease(uint64_t release) {
|
void CommandBufferStub::OnFenceSyncRelease(uint64_t release) {
|
||||||
SyncToken sync_token(CommandBufferNamespace::GPU_IO, command_buffer_id_,
|
SyncToken sync_token(CommandBufferNamespace::GPU_IO, command_buffer_id_,
|
||||||
release);
|
release);
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "gpu/command_buffer/service/context_group.h"
|
#include "gpu/command_buffer/service/context_group.h"
|
||||||
#include "gpu/command_buffer/service/decoder_client.h"
|
#include "gpu/command_buffer/service/decoder_client.h"
|
||||||
#include "gpu/command_buffer/service/program_cache.h"
|
#include "gpu/command_buffer/service/program_cache.h"
|
||||||
|
#include "gpu/command_buffer/service/scheduler_task_runner.h"
|
||||||
#include "gpu/command_buffer/service/sequence_id.h"
|
#include "gpu/command_buffer/service/sequence_id.h"
|
||||||
#include "gpu/ipc/common/gpu_channel.mojom.h"
|
#include "gpu/ipc/common/gpu_channel.mojom.h"
|
||||||
#include "gpu/ipc/common/surface_handle.h"
|
#include "gpu/ipc/common/surface_handle.h"
|
||||||
@ -50,7 +51,6 @@ class MemoryTracker;
|
|||||||
struct SyncToken;
|
struct SyncToken;
|
||||||
struct WaitForCommandState;
|
struct WaitForCommandState;
|
||||||
class GpuChannel;
|
class GpuChannel;
|
||||||
class SchedulerTaskRunner;
|
|
||||||
class SyncPointClientState;
|
class SyncPointClientState;
|
||||||
|
|
||||||
// CommandBufferStub is a base class for different CommandBuffer backends
|
// CommandBufferStub is a base class for different CommandBuffer backends
|
||||||
@ -89,6 +89,13 @@ class GPU_IPC_SERVICE_EXPORT CommandBufferStub
|
|||||||
|
|
||||||
~CommandBufferStub() override;
|
~CommandBufferStub() override;
|
||||||
|
|
||||||
|
// Exposes a SequencedTaskRunner which can be used to schedule tasks in
|
||||||
|
// sequence with this CommandBufferStub -- that is, on the same gpu::Scheduler
|
||||||
|
// sequence. Does not support nested loops or delayed tasks.
|
||||||
|
scoped_refptr<base::SequencedTaskRunner> task_runner() const {
|
||||||
|
return scheduler_task_runner_;
|
||||||
|
}
|
||||||
|
|
||||||
// This must leave the GL context associated with the newly-created
|
// This must leave the GL context associated with the newly-created
|
||||||
// CommandBufferStub current, so the GpuChannel can initialize
|
// CommandBufferStub current, so the GpuChannel can initialize
|
||||||
// the gpu::Capabilities.
|
// the gpu::Capabilities.
|
||||||
@ -221,6 +228,8 @@ class GPU_IPC_SERVICE_EXPORT CommandBufferStub
|
|||||||
void DestroyImage(int32_t id) override;
|
void DestroyImage(int32_t id) override;
|
||||||
void SignalSyncToken(const SyncToken& sync_token, uint32_t id) override;
|
void SignalSyncToken(const SyncToken& sync_token, uint32_t id) override;
|
||||||
void SignalQuery(uint32_t query, uint32_t id) override;
|
void SignalQuery(uint32_t query, uint32_t id) override;
|
||||||
|
void BindMediaReceiver(mojo::GenericPendingAssociatedReceiver receiver,
|
||||||
|
BindMediaReceiverCallback callback) override;
|
||||||
|
|
||||||
virtual void OnTakeFrontBuffer(const Mailbox& mailbox) {}
|
virtual void OnTakeFrontBuffer(const Mailbox& mailbox) {}
|
||||||
virtual void OnReturnFrontBuffer(const Mailbox& mailbox, bool is_lost) {}
|
virtual void OnReturnFrontBuffer(const Mailbox& mailbox, bool is_lost) {}
|
||||||
|
@ -347,33 +347,7 @@ void GpuChannelMessageFilter::RemoveChannelFilter(
|
|||||||
bool GpuChannelMessageFilter::OnMessageReceived(const IPC::Message& message) {
|
bool GpuChannelMessageFilter::OnMessageReceived(const IPC::Message& message) {
|
||||||
DCHECK(io_thread_checker_.CalledOnValidThread());
|
DCHECK(io_thread_checker_.CalledOnValidThread());
|
||||||
DCHECK(ipc_channel_);
|
DCHECK(ipc_channel_);
|
||||||
|
return false;
|
||||||
if (message.should_unblock() || message.is_reply())
|
|
||||||
return MessageErrorHandler(message, "Unexpected message type");
|
|
||||||
|
|
||||||
for (scoped_refptr<IPC::MessageFilter>& filter : channel_filters_) {
|
|
||||||
if (filter->OnMessageReceived(message))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
base::AutoLock auto_lock(gpu_channel_lock_);
|
|
||||||
if (!gpu_channel_)
|
|
||||||
return MessageErrorHandler(message, "Channel destroyed");
|
|
||||||
|
|
||||||
if (message.routing_id() == MSG_ROUTING_CONTROL)
|
|
||||||
return MessageErrorHandler(message, "Invalid control message");
|
|
||||||
|
|
||||||
// Messages which do not have sync token dependencies.
|
|
||||||
SequenceId sequence_id = GetSequenceId(message.routing_id());
|
|
||||||
if (sequence_id.is_null())
|
|
||||||
return MessageErrorHandler(message, "Invalid route id");
|
|
||||||
|
|
||||||
scheduler_->ScheduleTask(
|
|
||||||
Scheduler::Task(sequence_id,
|
|
||||||
base::BindOnce(&gpu::GpuChannel::HandleMessage,
|
|
||||||
gpu_channel_->AsWeakPtr(), message),
|
|
||||||
std::vector<SyncToken>()));
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SequenceId GpuChannelMessageFilter::GetSequenceId(int32_t route_id) const {
|
SequenceId GpuChannelMessageFilter::GetSequenceId(int32_t route_id) const {
|
||||||
@ -650,18 +624,6 @@ void GpuChannel::Init(IPC::ChannelHandle channel_handle,
|
|||||||
channel_ = sync_channel_.get();
|
channel_ = sync_channel_.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpuChannel::InitForTesting(IPC::Channel* channel) {
|
|
||||||
channel_ = channel;
|
|
||||||
// |channel| is an IPC::TestSink in tests, so don't add the filter to it
|
|
||||||
// because it will forward sent messages back to the filter.
|
|
||||||
// Call OnFilterAdded() to prevent DCHECK failures.
|
|
||||||
filter_->OnFilterAdded(channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GpuChannel::SetUnhandledMessageListener(IPC::Listener* listener) {
|
|
||||||
unhandled_message_listener_ = listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
base::WeakPtr<GpuChannel> GpuChannel::AsWeakPtr() {
|
base::WeakPtr<GpuChannel> GpuChannel::AsWeakPtr() {
|
||||||
return weak_factory_.GetWeakPtr();
|
return weak_factory_.GetWeakPtr();
|
||||||
}
|
}
|
||||||
@ -820,11 +782,6 @@ void GpuChannel::WaitForGetOffsetInRange(
|
|||||||
std::move(callback));
|
std::move(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpuChannel::HandleMessageForTesting(const IPC::Message& msg) {
|
|
||||||
// Message filter gets message first on IO thread.
|
|
||||||
filter_->OnMessageReceived(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
mojom::GpuChannel& GpuChannel::GetGpuChannelForTesting() {
|
mojom::GpuChannel& GpuChannel::GetGpuChannelForTesting() {
|
||||||
return *filter_;
|
return *filter_;
|
||||||
}
|
}
|
||||||
@ -847,23 +804,6 @@ bool GpuChannel::CreateSharedImageStub() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpuChannel::HandleMessage(const IPC::Message& msg) {
|
|
||||||
int32_t routing_id = msg.routing_id();
|
|
||||||
CommandBufferStub* stub = LookupCommandBuffer(routing_id);
|
|
||||||
|
|
||||||
DCHECK(!stub || stub->IsScheduled());
|
|
||||||
|
|
||||||
DVLOG(1) << "received message @" << &msg << " on channel @" << this
|
|
||||||
<< " with type " << msg.type();
|
|
||||||
|
|
||||||
bool handled = false;
|
|
||||||
if (routing_id != MSG_ROUTING_CONTROL)
|
|
||||||
handled = router_.RouteMessage(msg);
|
|
||||||
|
|
||||||
if (!handled && unhandled_message_listener_)
|
|
||||||
handled = unhandled_message_listener_->OnMessageReceived(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(OS_ANDROID)
|
#if defined(OS_ANDROID)
|
||||||
const CommandBufferStub* GpuChannel::GetOneStub() const {
|
const CommandBufferStub* GpuChannel::GetOneStub() const {
|
||||||
for (const auto& kv : stubs_) {
|
for (const auto& kv : stubs_) {
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include "ipc/ipc_sender.h"
|
#include "ipc/ipc_sender.h"
|
||||||
#include "ipc/ipc_sync_channel.h"
|
#include "ipc/ipc_sync_channel.h"
|
||||||
#include "ipc/message_router.h"
|
#include "ipc/message_router.h"
|
||||||
|
#include "mojo/public/cpp/bindings/generic_pending_associated_receiver.h"
|
||||||
#include "ui/gfx/geometry/size.h"
|
#include "ui/gfx/geometry/size.h"
|
||||||
#include "ui/gfx/native_widget_types.h"
|
#include "ui/gfx/native_widget_types.h"
|
||||||
#include "ui/gl/gl_share_group.h"
|
#include "ui/gl/gl_share_group.h"
|
||||||
@ -84,7 +85,16 @@ class GPU_IPC_SERVICE_EXPORT GpuChannel : public IPC::Listener,
|
|||||||
|
|
||||||
base::WeakPtr<GpuChannel> AsWeakPtr();
|
base::WeakPtr<GpuChannel> AsWeakPtr();
|
||||||
|
|
||||||
void SetUnhandledMessageListener(IPC::Listener* listener);
|
using CommandBufferMediaBinder =
|
||||||
|
base::RepeatingCallback<void(CommandBufferStub*,
|
||||||
|
mojo::GenericPendingAssociatedReceiver)>;
|
||||||
|
void set_command_buffer_media_binder(CommandBufferMediaBinder binder) {
|
||||||
|
command_buffer_media_binder_ = std::move(binder);
|
||||||
|
}
|
||||||
|
|
||||||
|
const CommandBufferMediaBinder& command_buffer_media_binder() const {
|
||||||
|
return command_buffer_media_binder_;
|
||||||
|
}
|
||||||
|
|
||||||
// Get the GpuChannelManager that owns this channel.
|
// Get the GpuChannelManager that owns this channel.
|
||||||
GpuChannelManager* gpu_channel_manager() const {
|
GpuChannelManager* gpu_channel_manager() const {
|
||||||
@ -155,8 +165,6 @@ class GPU_IPC_SERVICE_EXPORT GpuChannel : public IPC::Listener,
|
|||||||
gfx::BufferPlane plane,
|
gfx::BufferPlane plane,
|
||||||
SurfaceHandle surface_handle);
|
SurfaceHandle surface_handle);
|
||||||
|
|
||||||
void HandleMessage(const IPC::Message& msg);
|
|
||||||
|
|
||||||
// Executes a DeferredRequest that was previously received and has now been
|
// Executes a DeferredRequest that was previously received and has now been
|
||||||
// scheduled by the scheduler.
|
// scheduled by the scheduler.
|
||||||
void ExecuteDeferredRequest(mojom::DeferredRequestParamsPtr params);
|
void ExecuteDeferredRequest(mojom::DeferredRequestParamsPtr params);
|
||||||
@ -173,7 +181,6 @@ class GPU_IPC_SERVICE_EXPORT GpuChannel : public IPC::Listener,
|
|||||||
int32_t end,
|
int32_t end,
|
||||||
mojom::GpuChannel::WaitForGetOffsetInRangeCallback callback);
|
mojom::GpuChannel::WaitForGetOffsetInRangeCallback callback);
|
||||||
|
|
||||||
void HandleMessageForTesting(const IPC::Message& msg);
|
|
||||||
mojom::GpuChannel& GetGpuChannelForTesting();
|
mojom::GpuChannel& GetGpuChannelForTesting();
|
||||||
|
|
||||||
ImageDecodeAcceleratorStub* GetImageDecodeAcceleratorStub() const;
|
ImageDecodeAcceleratorStub* GetImageDecodeAcceleratorStub() const;
|
||||||
@ -239,6 +246,10 @@ class GPU_IPC_SERVICE_EXPORT GpuChannel : public IPC::Listener,
|
|||||||
// The message filter on the io thread.
|
// The message filter on the io thread.
|
||||||
scoped_refptr<GpuChannelMessageFilter> filter_;
|
scoped_refptr<GpuChannelMessageFilter> filter_;
|
||||||
|
|
||||||
|
// An optional binder to handle associated interface requests from the Media
|
||||||
|
// stack, targeting a specific CommandBuffer.
|
||||||
|
CommandBufferMediaBinder command_buffer_media_binder_;
|
||||||
|
|
||||||
// Map of routing id to command buffer stub.
|
// Map of routing id to command buffer stub.
|
||||||
base::flat_map<int32_t, std::unique_ptr<CommandBufferStub>> stubs_;
|
base::flat_map<int32_t, std::unique_ptr<CommandBufferStub>> stubs_;
|
||||||
|
|
||||||
@ -256,8 +267,6 @@ class GPU_IPC_SERVICE_EXPORT GpuChannel : public IPC::Listener,
|
|||||||
// message loop.
|
// message loop.
|
||||||
SyncPointManager* const sync_point_manager_;
|
SyncPointManager* const sync_point_manager_;
|
||||||
|
|
||||||
IPC::Listener* unhandled_message_listener_ = nullptr;
|
|
||||||
|
|
||||||
// Used to implement message routing functionality to CommandBuffer objects
|
// Used to implement message routing functionality to CommandBuffer objects
|
||||||
IPC::MessageRouter router_;
|
IPC::MessageRouter router_;
|
||||||
|
|
||||||
|
@ -115,7 +115,6 @@ GpuChannel* GpuChannelTestCommon::CreateChannel(int32_t client_id,
|
|||||||
GpuChannel* channel = channel_manager()->EstablishChannel(
|
GpuChannel* channel = channel_manager()->EstablishChannel(
|
||||||
base::UnguessableToken::Create(), client_id, kClientTracingId,
|
base::UnguessableToken::Create(), client_id, kClientTracingId,
|
||||||
is_gpu_host, true);
|
is_gpu_host, true);
|
||||||
channel->InitForTesting(&sink_);
|
|
||||||
base::ProcessId kProcessId = 1;
|
base::ProcessId kProcessId = 1;
|
||||||
channel->OnChannelConnected(kProcessId);
|
channel->OnChannelConnected(kProcessId);
|
||||||
return channel;
|
return channel;
|
||||||
@ -146,43 +145,6 @@ void GpuChannelTestCommon::CreateCommandBuffer(
|
|||||||
loop.Run();
|
loop.Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpuChannelTestCommon::HandleMessage(GpuChannel* channel,
|
|
||||||
IPC::Message* msg) {
|
|
||||||
// Some IPCs (such as GpuCommandBufferMsg_Initialize) will generate more
|
|
||||||
// delayed responses, drop those if they exist.
|
|
||||||
sink_.ClearMessages();
|
|
||||||
|
|
||||||
// Needed to appease DCHECKs.
|
|
||||||
msg->set_unblock(false);
|
|
||||||
|
|
||||||
// Message filter gets message first on IO thread.
|
|
||||||
channel->HandleMessageForTesting(*msg);
|
|
||||||
|
|
||||||
// Run the HandleMessage task posted to the main thread.
|
|
||||||
task_environment_.RunUntilIdle();
|
|
||||||
|
|
||||||
// Replies are sent to the sink.
|
|
||||||
if (msg->is_sync()) {
|
|
||||||
const IPC::Message* reply_msg = sink_.GetMessageAt(0);
|
|
||||||
ASSERT_TRUE(reply_msg);
|
|
||||||
EXPECT_TRUE(!reply_msg->is_reply_error());
|
|
||||||
|
|
||||||
EXPECT_TRUE(IPC::SyncMessage::IsMessageReplyTo(
|
|
||||||
*reply_msg, IPC::SyncMessage::GetMessageId(*msg)));
|
|
||||||
|
|
||||||
IPC::MessageReplyDeserializer* deserializer =
|
|
||||||
static_cast<IPC::SyncMessage*>(msg)->GetReplyDeserializer();
|
|
||||||
ASSERT_TRUE(deserializer);
|
|
||||||
deserializer->SerializeOutputParameters(*reply_msg);
|
|
||||||
|
|
||||||
delete deserializer;
|
|
||||||
}
|
|
||||||
|
|
||||||
sink_.ClearMessages();
|
|
||||||
|
|
||||||
delete msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
base::UnsafeSharedMemoryRegion GpuChannelTestCommon::GetSharedMemoryRegion() {
|
base::UnsafeSharedMemoryRegion GpuChannelTestCommon::GetSharedMemoryRegion() {
|
||||||
return base::UnsafeSharedMemoryRegion::Create(
|
return base::UnsafeSharedMemoryRegion::Create(
|
||||||
sizeof(CommandBufferSharedState));
|
sizeof(CommandBufferSharedState));
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
#include "gpu/command_buffer/common/capabilities.h"
|
#include "gpu/command_buffer/common/capabilities.h"
|
||||||
#include "gpu/command_buffer/common/context_result.h"
|
#include "gpu/command_buffer/common/context_result.h"
|
||||||
#include "gpu/ipc/common/gpu_channel.mojom.h"
|
#include "gpu/ipc/common/gpu_channel.mojom.h"
|
||||||
#include "ipc/ipc_test_sink.h"
|
|
||||||
#include "testing/gtest/include/gtest/gtest.h"
|
#include "testing/gtest/include/gtest/gtest.h"
|
||||||
|
|
||||||
namespace base {
|
namespace base {
|
||||||
@ -24,10 +23,6 @@ class MemoryDumpManager;
|
|||||||
} // namespace trace_event
|
} // namespace trace_event
|
||||||
} // namespace base
|
} // namespace base
|
||||||
|
|
||||||
namespace IPC {
|
|
||||||
class Message;
|
|
||||||
} // namespace IPC
|
|
||||||
|
|
||||||
namespace gpu {
|
namespace gpu {
|
||||||
class GpuChannel;
|
class GpuChannel;
|
||||||
class GpuChannelManager;
|
class GpuChannelManager;
|
||||||
@ -58,14 +53,11 @@ class GpuChannelTestCommon : public testing::Test {
|
|||||||
ContextResult* out_result,
|
ContextResult* out_result,
|
||||||
Capabilities* out_capabilities);
|
Capabilities* out_capabilities);
|
||||||
|
|
||||||
void HandleMessage(GpuChannel* channel, IPC::Message* msg);
|
|
||||||
|
|
||||||
base::UnsafeSharedMemoryRegion GetSharedMemoryRegion();
|
base::UnsafeSharedMemoryRegion GetSharedMemoryRegion();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
base::test::TaskEnvironment task_environment_;
|
base::test::TaskEnvironment task_environment_;
|
||||||
std::unique_ptr<base::trace_event::MemoryDumpManager> memory_dump_manager_;
|
std::unique_ptr<base::trace_event::MemoryDumpManager> memory_dump_manager_;
|
||||||
IPC::TestSink sink_;
|
|
||||||
std::unique_ptr<SyncPointManager> sync_point_manager_;
|
std::unique_ptr<SyncPointManager> sync_point_manager_;
|
||||||
std::unique_ptr<SharedImageManager> shared_image_manager_;
|
std::unique_ptr<SharedImageManager> shared_image_manager_;
|
||||||
std::unique_ptr<Scheduler> scheduler_;
|
std::unique_ptr<Scheduler> scheduler_;
|
||||||
|
@ -529,15 +529,7 @@ class ChannelAssociatedGroupController
|
|||||||
task_runner_ = std::move(runner);
|
task_runner_ = std::move(runner);
|
||||||
client_ = client;
|
client_ = client;
|
||||||
|
|
||||||
const bool binding_to_calling_sequence =
|
if (CanBindOffSequence())
|
||||||
task_runner_->RunsTasksInCurrentSequence();
|
|
||||||
const bool binding_to_channel_sequence =
|
|
||||||
binding_to_calling_sequence &&
|
|
||||||
(controller_->proxy_task_runner_->RunsTasksInCurrentSequence() ||
|
|
||||||
controller_->task_runner_->RunsTasksInCurrentSequence());
|
|
||||||
const bool tried_to_bind_off_sequence =
|
|
||||||
!binding_to_calling_sequence || !binding_to_channel_sequence;
|
|
||||||
if (tried_to_bind_off_sequence && CanBindOffSequence())
|
|
||||||
was_bound_off_sequence_ = true;
|
was_bound_off_sequence_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -994,7 +986,6 @@ class ChannelAssociatedGroupController
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AcceptSyncMessage(mojo::InterfaceId interface_id, uint32_t message_id) {
|
void AcceptSyncMessage(mojo::InterfaceId interface_id, uint32_t message_id) {
|
||||||
DCHECK(proxy_task_runner_->BelongsToCurrentThread());
|
|
||||||
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("mojom"),
|
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("mojom"),
|
||||||
"ChannelAssociatedGroupController::AcceptSyncMessage");
|
"ChannelAssociatedGroupController::AcceptSyncMessage");
|
||||||
|
|
||||||
@ -1012,7 +1003,8 @@ class ChannelAssociatedGroupController
|
|||||||
// Using client->interface_name() is safe here because this is a static
|
// Using client->interface_name() is safe here because this is a static
|
||||||
// string defined for each mojo interface.
|
// string defined for each mojo interface.
|
||||||
TRACE_EVENT0("mojom", client->interface_name());
|
TRACE_EVENT0("mojom", client->interface_name());
|
||||||
DCHECK(endpoint->task_runner()->RunsTasksInCurrentSequence());
|
DCHECK(endpoint->task_runner()->RunsTasksInCurrentSequence() ||
|
||||||
|
proxy_task_runner_->RunsTasksInCurrentSequence());
|
||||||
MessageWrapper message_wrapper = endpoint->PopSyncMessage(message_id);
|
MessageWrapper message_wrapper = endpoint->PopSyncMessage(message_id);
|
||||||
|
|
||||||
// The message must have already been dequeued by the endpoint waking up
|
// The message must have already been dequeued by the endpoint waking up
|
||||||
|
@ -18,6 +18,7 @@ source_set("client") {
|
|||||||
"//media:media_buildflags",
|
"//media:media_buildflags",
|
||||||
"//media/gpu",
|
"//media/gpu",
|
||||||
"//media/gpu/ipc/common",
|
"//media/gpu/ipc/common",
|
||||||
|
"//media/mojo/mojom",
|
||||||
"//ui/gfx:memory_buffer",
|
"//ui/gfx:memory_buffer",
|
||||||
"//ui/gfx/geometry",
|
"//ui/gfx/geometry",
|
||||||
"//ui/gfx/ipc",
|
"//ui/gfx/ipc",
|
||||||
|
@ -9,20 +9,15 @@
|
|||||||
#include "base/threading/thread_task_runner_handle.h"
|
#include "base/threading/thread_task_runner_handle.h"
|
||||||
#include "build/build_config.h"
|
#include "build/build_config.h"
|
||||||
#include "gpu/ipc/client/gpu_channel_host.h"
|
#include "gpu/ipc/client/gpu_channel_host.h"
|
||||||
#include "ipc/ipc_message_macros.h"
|
#include "mojo/public/cpp/bindings/associated_remote.h"
|
||||||
#include "ipc/ipc_message_utils.h"
|
|
||||||
#include "media/gpu/ipc/common/media_messages.h"
|
|
||||||
|
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
GpuVideoDecodeAcceleratorHost::GpuVideoDecodeAcceleratorHost(
|
GpuVideoDecodeAcceleratorHost::GpuVideoDecodeAcceleratorHost(
|
||||||
gpu::CommandBufferProxyImpl* impl)
|
gpu::CommandBufferProxyImpl* impl)
|
||||||
: channel_(impl->channel()),
|
: client_(nullptr),
|
||||||
decoder_route_id_(MSG_ROUTING_NONE),
|
|
||||||
client_(nullptr),
|
|
||||||
impl_(impl),
|
impl_(impl),
|
||||||
media_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
|
media_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
|
||||||
DCHECK(channel_);
|
|
||||||
DCHECK(impl_);
|
DCHECK(impl_);
|
||||||
|
|
||||||
weak_this_ = weak_this_factory_.GetWeakPtr();
|
weak_this_ = weak_this_factory_.GetWeakPtr();
|
||||||
@ -31,49 +26,16 @@ GpuVideoDecodeAcceleratorHost::GpuVideoDecodeAcceleratorHost(
|
|||||||
|
|
||||||
GpuVideoDecodeAcceleratorHost::~GpuVideoDecodeAcceleratorHost() {
|
GpuVideoDecodeAcceleratorHost::~GpuVideoDecodeAcceleratorHost() {
|
||||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
|
|
||||||
if (channel_ && decoder_route_id_ != MSG_ROUTING_NONE)
|
|
||||||
channel_->RemoveRoute(decoder_route_id_);
|
|
||||||
|
|
||||||
base::AutoLock lock(impl_lock_);
|
base::AutoLock lock(impl_lock_);
|
||||||
if (impl_)
|
if (impl_)
|
||||||
impl_->RemoveDeletionObserver(this);
|
impl_->RemoveDeletionObserver(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GpuVideoDecodeAcceleratorHost::OnMessageReceived(const IPC::Message& msg) {
|
void GpuVideoDecodeAcceleratorHost::OnDisconnectedFromGpuProcess() {
|
||||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
bool handled = true;
|
decoder_.reset();
|
||||||
IPC_BEGIN_MESSAGE_MAP(GpuVideoDecodeAcceleratorHost, msg)
|
client_receiver_.reset();
|
||||||
IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_InitializationComplete,
|
DLOG(ERROR) << "OnDisconnectedFromGpuProcess()";
|
||||||
OnInitializationComplete)
|
|
||||||
IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed,
|
|
||||||
OnBitstreamBufferProcessed)
|
|
||||||
IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ProvidePictureBuffers,
|
|
||||||
OnProvidePictureBuffers)
|
|
||||||
IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_PictureReady,
|
|
||||||
OnPictureReady)
|
|
||||||
IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_FlushDone, OnFlushDone)
|
|
||||||
IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ResetDone, OnResetDone)
|
|
||||||
IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ErrorNotification,
|
|
||||||
OnNotifyError)
|
|
||||||
IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_DismissPictureBuffer,
|
|
||||||
OnDismissPictureBuffer)
|
|
||||||
IPC_MESSAGE_UNHANDLED(handled = false)
|
|
||||||
IPC_END_MESSAGE_MAP()
|
|
||||||
DCHECK(handled);
|
|
||||||
// See OnNotifyError for why |this| mustn't be used after OnNotifyError might
|
|
||||||
// have been called above.
|
|
||||||
return handled;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GpuVideoDecodeAcceleratorHost::OnChannelError() {
|
|
||||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
|
||||||
if (channel_) {
|
|
||||||
if (decoder_route_id_ != MSG_ROUTING_NONE)
|
|
||||||
channel_->RemoveRoute(decoder_route_id_);
|
|
||||||
channel_ = nullptr;
|
|
||||||
}
|
|
||||||
DLOG(ERROR) << "OnChannelError()";
|
|
||||||
PostNotifyError(PLATFORM_FAILURE);
|
PostNotifyError(PLATFORM_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,52 +48,46 @@ bool GpuVideoDecodeAcceleratorHost::Initialize(const Config& config,
|
|||||||
if (!impl_)
|
if (!impl_)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int32_t route_id = channel_->GenerateRouteID();
|
const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner =
|
||||||
channel_->AddRoute(route_id, weak_this_);
|
impl_->channel()->io_task_runner();
|
||||||
|
|
||||||
bool succeeded = false;
|
bool succeeded = false;
|
||||||
Send(new GpuCommandBufferMsg_CreateVideoDecoder(impl_->route_id(), config,
|
mojo::SharedAssociatedRemote<mojom::GpuAcceleratedVideoDecoderProvider>
|
||||||
route_id, &succeeded));
|
provider;
|
||||||
|
impl_->BindMediaReceiver(
|
||||||
|
provider.BindNewEndpointAndPassReceiver(io_task_runner));
|
||||||
|
provider->CreateAcceleratedVideoDecoder(
|
||||||
|
config, decoder_.BindNewEndpointAndPassReceiver(io_task_runner),
|
||||||
|
client_receiver_.BindNewEndpointAndPassRemote(), &succeeded);
|
||||||
if (!succeeded) {
|
if (!succeeded) {
|
||||||
DLOG(ERROR) << "Send(GpuCommandBufferMsg_CreateVideoDecoder()) failed";
|
DLOG(ERROR) << "CreateAcceleratedVideoDecoder() failed";
|
||||||
PostNotifyError(PLATFORM_FAILURE);
|
PostNotifyError(PLATFORM_FAILURE);
|
||||||
channel_->RemoveRoute(route_id);
|
decoder_.reset();
|
||||||
|
client_receiver_.reset();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
decoder_route_id_ = route_id;
|
|
||||||
|
decoder_.set_disconnect_handler(
|
||||||
|
base::BindOnce(
|
||||||
|
&GpuVideoDecodeAcceleratorHost::OnDisconnectedFromGpuProcess,
|
||||||
|
weak_this_),
|
||||||
|
base::SequencedTaskRunnerHandle::Get());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpuVideoDecodeAcceleratorHost::Decode(BitstreamBuffer bitstream_buffer) {
|
void GpuVideoDecodeAcceleratorHost::Decode(BitstreamBuffer bitstream_buffer) {
|
||||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
if (!channel_)
|
if (!decoder_)
|
||||||
return;
|
return;
|
||||||
if (channel_->IsLost()) {
|
decoder_->Decode(std::move(bitstream_buffer));
|
||||||
Send(new AcceleratedVideoDecoderMsg_Decode(
|
|
||||||
decoder_route_id_,
|
|
||||||
BitstreamBuffer(bitstream_buffer.id(),
|
|
||||||
base::subtle::PlatformSharedMemoryRegion(),
|
|
||||||
bitstream_buffer.size(), bitstream_buffer.offset(),
|
|
||||||
bitstream_buffer.presentation_timestamp())));
|
|
||||||
} else {
|
|
||||||
// The legacy IPC call will duplicate the shared memory region in
|
|
||||||
// bitstream_buffer.
|
|
||||||
Send(new AcceleratedVideoDecoderMsg_Decode(decoder_route_id_,
|
|
||||||
bitstream_buffer));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpuVideoDecodeAcceleratorHost::AssignPictureBuffers(
|
void GpuVideoDecodeAcceleratorHost::AssignPictureBuffers(
|
||||||
const std::vector<PictureBuffer>& buffers) {
|
const std::vector<PictureBuffer>& buffers) {
|
||||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
if (!channel_)
|
if (!decoder_)
|
||||||
return;
|
return;
|
||||||
// Rearrange data for IPC command.
|
std::vector<mojom::PictureBufferAssignmentPtr> assignments;
|
||||||
std::vector<int32_t> buffer_ids;
|
for (const auto& buffer : buffers) {
|
||||||
std::vector<PictureBuffer::TextureIds> texture_ids;
|
|
||||||
for (uint32_t i = 0; i < buffers.size(); i++) {
|
|
||||||
const PictureBuffer& buffer = buffers[i];
|
|
||||||
if (buffer.size() != picture_buffer_dimensions_) {
|
if (buffer.size() != picture_buffer_dimensions_) {
|
||||||
DLOG(ERROR) << "buffer.size() invalid: expected "
|
DLOG(ERROR) << "buffer.size() invalid: expected "
|
||||||
<< picture_buffer_dimensions_.ToString() << ", got "
|
<< picture_buffer_dimensions_.ToString() << ", got "
|
||||||
@ -139,49 +95,46 @@ void GpuVideoDecodeAcceleratorHost::AssignPictureBuffers(
|
|||||||
PostNotifyError(INVALID_ARGUMENT);
|
PostNotifyError(INVALID_ARGUMENT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
texture_ids.push_back(buffer.client_texture_ids());
|
assignments.push_back(mojom::PictureBufferAssignment::New(
|
||||||
buffer_ids.push_back(buffer.id());
|
buffer.id(), buffer.client_texture_ids()));
|
||||||
}
|
}
|
||||||
Send(new AcceleratedVideoDecoderMsg_AssignPictureBuffers(
|
decoder_->AssignPictureBuffers(std::move(assignments));
|
||||||
decoder_route_id_, buffer_ids, texture_ids));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpuVideoDecodeAcceleratorHost::ReusePictureBuffer(
|
void GpuVideoDecodeAcceleratorHost::ReusePictureBuffer(
|
||||||
int32_t picture_buffer_id) {
|
int32_t picture_buffer_id) {
|
||||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
if (!channel_)
|
if (!decoder_)
|
||||||
return;
|
return;
|
||||||
Send(new AcceleratedVideoDecoderMsg_ReusePictureBuffer(decoder_route_id_,
|
decoder_->ReusePictureBuffer(picture_buffer_id);
|
||||||
picture_buffer_id));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpuVideoDecodeAcceleratorHost::Flush() {
|
void GpuVideoDecodeAcceleratorHost::Flush() {
|
||||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
if (!channel_)
|
if (!decoder_)
|
||||||
return;
|
return;
|
||||||
Send(new AcceleratedVideoDecoderMsg_Flush(decoder_route_id_));
|
decoder_->Flush(base::BindOnce(&GpuVideoDecodeAcceleratorHost::OnFlushDone,
|
||||||
|
base::Unretained(this)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpuVideoDecodeAcceleratorHost::Reset() {
|
void GpuVideoDecodeAcceleratorHost::Reset() {
|
||||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
if (!channel_)
|
if (!decoder_)
|
||||||
return;
|
return;
|
||||||
Send(new AcceleratedVideoDecoderMsg_Reset(decoder_route_id_));
|
decoder_->Flush(base::BindOnce(&GpuVideoDecodeAcceleratorHost::OnResetDone,
|
||||||
|
base::Unretained(this)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpuVideoDecodeAcceleratorHost::SetOverlayInfo(
|
void GpuVideoDecodeAcceleratorHost::SetOverlayInfo(
|
||||||
const OverlayInfo& overlay_info) {
|
const OverlayInfo& overlay_info) {
|
||||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
if (!channel_)
|
if (!decoder_)
|
||||||
return;
|
return;
|
||||||
Send(new AcceleratedVideoDecoderMsg_SetOverlayInfo(decoder_route_id_,
|
decoder_->SetOverlayInfo(overlay_info);
|
||||||
overlay_info));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpuVideoDecodeAcceleratorHost::Destroy() {
|
void GpuVideoDecodeAcceleratorHost::Destroy() {
|
||||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
if (channel_)
|
|
||||||
Send(new AcceleratedVideoDecoderMsg_Destroy(decoder_route_id_));
|
|
||||||
client_ = nullptr;
|
client_ = nullptr;
|
||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
@ -192,33 +145,27 @@ void GpuVideoDecodeAcceleratorHost::OnWillDeleteImpl() {
|
|||||||
|
|
||||||
// The gpu::CommandBufferProxyImpl is going away; error out this VDA.
|
// The gpu::CommandBufferProxyImpl is going away; error out this VDA.
|
||||||
media_task_runner_->PostTask(
|
media_task_runner_->PostTask(
|
||||||
FROM_HERE, base::BindOnce(&GpuVideoDecodeAcceleratorHost::OnChannelError,
|
FROM_HERE,
|
||||||
weak_this_));
|
base::BindOnce(
|
||||||
|
&GpuVideoDecodeAcceleratorHost::OnDisconnectedFromGpuProcess,
|
||||||
|
weak_this_));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpuVideoDecodeAcceleratorHost::PostNotifyError(Error error) {
|
void GpuVideoDecodeAcceleratorHost::PostNotifyError(Error error) {
|
||||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
DVLOG(2) << "PostNotifyError(): error=" << error;
|
DVLOG(2) << "PostNotifyError(): error=" << error;
|
||||||
media_task_runner_->PostTask(
|
media_task_runner_->PostTask(
|
||||||
FROM_HERE, base::BindOnce(&GpuVideoDecodeAcceleratorHost::OnNotifyError,
|
FROM_HERE, base::BindOnce(&GpuVideoDecodeAcceleratorHost::OnError,
|
||||||
weak_this_, error));
|
weak_this_, error));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpuVideoDecodeAcceleratorHost::Send(IPC::Message* message) {
|
|
||||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
|
||||||
uint32_t message_type = message->type();
|
|
||||||
if (!channel_->Send(message)) {
|
|
||||||
DLOG(ERROR) << "Send(" << message_type << ") failed";
|
|
||||||
PostNotifyError(PLATFORM_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(tmathmeyer) This needs to accept a Status at some point
|
// TODO(tmathmeyer) This needs to accept a Status at some point
|
||||||
void GpuVideoDecodeAcceleratorHost::OnInitializationComplete(bool success) {
|
void GpuVideoDecodeAcceleratorHost::OnInitializationComplete(bool success) {
|
||||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
if (client_)
|
if (client_) {
|
||||||
client_->NotifyInitializationComplete(
|
client_->NotifyInitializationComplete(
|
||||||
success ? OkStatus() : StatusCode::kInitializationUnspecifiedFailure);
|
success ? OkStatus() : StatusCode::kInitializationUnspecifiedFailure);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpuVideoDecodeAcceleratorHost::OnBitstreamBufferProcessed(
|
void GpuVideoDecodeAcceleratorHost::OnBitstreamBufferProcessed(
|
||||||
@ -258,17 +205,17 @@ void GpuVideoDecodeAcceleratorHost::OnDismissPictureBuffer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GpuVideoDecodeAcceleratorHost::OnPictureReady(
|
void GpuVideoDecodeAcceleratorHost::OnPictureReady(
|
||||||
const AcceleratedVideoDecoderHostMsg_PictureReady_Params& params) {
|
mojom::PictureReadyParamsPtr params) {
|
||||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
if (!client_)
|
if (!client_)
|
||||||
return;
|
return;
|
||||||
Picture picture(params.picture_buffer_id, params.bitstream_buffer_id,
|
Picture picture(params->picture_buffer_id, params->bitstream_buffer_id,
|
||||||
params.visible_rect, params.color_space,
|
params->visible_rect, params->color_space,
|
||||||
params.allow_overlay);
|
params->allow_overlay);
|
||||||
picture.set_read_lock_fences_enabled(params.read_lock_fences_enabled);
|
picture.set_read_lock_fences_enabled(params->read_lock_fences_enabled);
|
||||||
picture.set_size_changed(params.size_changed);
|
picture.set_size_changed(params->size_changed);
|
||||||
picture.set_texture_owner(params.surface_texture);
|
picture.set_texture_owner(params->surface_texture);
|
||||||
picture.set_wants_promotion_hint(params.wants_promotion_hint);
|
picture.set_wants_promotion_hint(params->wants_promotion_hint);
|
||||||
client_->PictureReady(picture);
|
client_->PictureReady(picture);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,7 +231,7 @@ void GpuVideoDecodeAcceleratorHost::OnResetDone() {
|
|||||||
client_->NotifyResetDone();
|
client_->NotifyResetDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpuVideoDecodeAcceleratorHost::OnNotifyError(uint32_t error) {
|
void GpuVideoDecodeAcceleratorHost::OnError(uint32_t error) {
|
||||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
if (!client_)
|
if (!client_)
|
||||||
return;
|
return;
|
||||||
|
@ -14,32 +14,24 @@
|
|||||||
#include "base/sequence_checker.h"
|
#include "base/sequence_checker.h"
|
||||||
#include "base/single_thread_task_runner.h"
|
#include "base/single_thread_task_runner.h"
|
||||||
#include "gpu/ipc/client/command_buffer_proxy_impl.h"
|
#include "gpu/ipc/client/command_buffer_proxy_impl.h"
|
||||||
#include "ipc/ipc_listener.h"
|
#include "media/mojo/mojom/gpu_accelerated_video_decoder.mojom.h"
|
||||||
#include "media/video/video_decode_accelerator.h"
|
#include "media/video/video_decode_accelerator.h"
|
||||||
|
#include "mojo/public/cpp/bindings/associated_receiver.h"
|
||||||
|
#include "mojo/public/cpp/bindings/shared_associated_remote.h"
|
||||||
#include "ui/gfx/geometry/size.h"
|
#include "ui/gfx/geometry/size.h"
|
||||||
|
|
||||||
struct AcceleratedVideoDecoderHostMsg_PictureReady_Params;
|
|
||||||
|
|
||||||
namespace gpu {
|
|
||||||
class GpuChannelHost;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
// This class is used to talk to VideoDecodeAccelerator in the Gpu process
|
// This class is used to talk to VideoDecodeAccelerator in the Gpu process
|
||||||
// through IPC messages.
|
// through IPC messages.
|
||||||
class GpuVideoDecodeAcceleratorHost
|
class GpuVideoDecodeAcceleratorHost
|
||||||
: public IPC::Listener,
|
: public VideoDecodeAccelerator,
|
||||||
public VideoDecodeAccelerator,
|
public gpu::CommandBufferProxyImpl::DeletionObserver,
|
||||||
public gpu::CommandBufferProxyImpl::DeletionObserver {
|
public mojom::GpuAcceleratedVideoDecoderClient {
|
||||||
public:
|
public:
|
||||||
// |this| is guaranteed not to outlive |impl|. (See comments for |impl_|.)
|
// |this| is guaranteed not to outlive |impl|. (See comments for |impl_|.)
|
||||||
explicit GpuVideoDecodeAcceleratorHost(gpu::CommandBufferProxyImpl* impl);
|
explicit GpuVideoDecodeAcceleratorHost(gpu::CommandBufferProxyImpl* impl);
|
||||||
|
|
||||||
// IPC::Listener implementation.
|
|
||||||
void OnChannelError() override;
|
|
||||||
bool OnMessageReceived(const IPC::Message& message) override;
|
|
||||||
|
|
||||||
// VideoDecodeAccelerator implementation.
|
// VideoDecodeAccelerator implementation.
|
||||||
bool Initialize(const Config& config, Client* client) override;
|
bool Initialize(const Config& config, Client* client) override;
|
||||||
void Decode(BitstreamBuffer bitstream_buffer) override;
|
void Decode(BitstreamBuffer bitstream_buffer) override;
|
||||||
@ -57,31 +49,32 @@ class GpuVideoDecodeAcceleratorHost
|
|||||||
// Only Destroy() should be deleting |this|.
|
// Only Destroy() should be deleting |this|.
|
||||||
~GpuVideoDecodeAcceleratorHost() override;
|
~GpuVideoDecodeAcceleratorHost() override;
|
||||||
|
|
||||||
|
void OnDisconnectedFromGpuProcess();
|
||||||
|
|
||||||
// Notify |client_| of an error. Posts a task to avoid re-entrancy.
|
// Notify |client_| of an error. Posts a task to avoid re-entrancy.
|
||||||
void PostNotifyError(Error);
|
void PostNotifyError(Error);
|
||||||
|
|
||||||
void Send(IPC::Message* message);
|
// mojom::GpuAcceleratedVideoDecoderClient:
|
||||||
|
void OnInitializationComplete(bool success) override;
|
||||||
// IPC handlers, proxying VideoDecodeAccelerator::Client for the GPU
|
void OnBitstreamBufferProcessed(int32_t bitstream_buffer_id) override;
|
||||||
// process. Should not be called directly.
|
|
||||||
void OnInitializationComplete(bool success);
|
|
||||||
void OnBitstreamBufferProcessed(int32_t bitstream_buffer_id);
|
|
||||||
void OnProvidePictureBuffers(uint32_t num_requested_buffers,
|
void OnProvidePictureBuffers(uint32_t num_requested_buffers,
|
||||||
VideoPixelFormat format,
|
VideoPixelFormat format,
|
||||||
uint32_t textures_per_buffer,
|
uint32_t textures_per_buffer,
|
||||||
const gfx::Size& dimensions,
|
const gfx::Size& dimensions,
|
||||||
uint32_t texture_target);
|
uint32_t texture_target) override;
|
||||||
void OnDismissPictureBuffer(int32_t picture_buffer_id);
|
void OnDismissPictureBuffer(int32_t picture_buffer_id) override;
|
||||||
void OnPictureReady(
|
void OnPictureReady(mojom::PictureReadyParamsPtr params) override;
|
||||||
const AcceleratedVideoDecoderHostMsg_PictureReady_Params& params);
|
void OnError(uint32_t error) override;
|
||||||
|
|
||||||
void OnFlushDone();
|
void OnFlushDone();
|
||||||
void OnResetDone();
|
void OnResetDone();
|
||||||
void OnNotifyError(uint32_t error);
|
|
||||||
|
|
||||||
scoped_refptr<gpu::GpuChannelHost> channel_;
|
// Receiver and remote endpoints for connections to the GPU process. These are
|
||||||
|
// associated with the corresponding CommandBuffer interface given at
|
||||||
// Route ID for the associated decoder in the GPU process.
|
// construction time.
|
||||||
int32_t decoder_route_id_;
|
mojo::AssociatedReceiver<mojom::GpuAcceleratedVideoDecoderClient>
|
||||||
|
client_receiver_{this};
|
||||||
|
mojo::SharedAssociatedRemote<mojom::GpuAcceleratedVideoDecoder> decoder_;
|
||||||
|
|
||||||
// The client that will receive callbacks from the decoder.
|
// The client that will receive callbacks from the decoder.
|
||||||
Client* client_;
|
Client* client_;
|
||||||
|
@ -4,9 +4,6 @@
|
|||||||
|
|
||||||
source_set("common") {
|
source_set("common") {
|
||||||
sources = [
|
sources = [
|
||||||
"media_message_generator.cc",
|
|
||||||
"media_message_generator.h",
|
|
||||||
"media_messages.h",
|
|
||||||
"media_param_traits.cc",
|
"media_param_traits.cc",
|
||||||
"media_param_traits.h",
|
"media_param_traits.h",
|
||||||
"media_param_traits_macros.h",
|
"media_param_traits_macros.h",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Changes to IPCs require a security review to avoid introducing
|
# Changes to IPCs require a security review to avoid introducing
|
||||||
# new sandbox escapes.
|
# new sandbox escapes.
|
||||||
per-file *_messages*.h=set noparent
|
|
||||||
per-file *_messages*.h=file://ipc/SECURITY_OWNERS
|
|
||||||
per-file *_param_traits*.*=set noparent
|
per-file *_param_traits*.*=set noparent
|
||||||
per-file *_param_traits*.*=file://ipc/SECURITY_OWNERS
|
per-file *_param_traits*.*=file://ipc/SECURITY_OWNERS
|
||||||
|
per-file *.mojom=set noparent
|
||||||
|
per-file *.mojom=file://ipc/SECURITY_OWNERS
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
// 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.
|
|
||||||
|
|
||||||
// Get basic type definitions.
|
|
||||||
#define IPC_MESSAGE_IMPL
|
|
||||||
#include "media/gpu/ipc/common/media_message_generator.h"
|
|
||||||
|
|
||||||
// Generate constructors.
|
|
||||||
#include "ipc/struct_constructor_macros.h"
|
|
||||||
#include "media/gpu/ipc/common/media_message_generator.h"
|
|
||||||
|
|
||||||
// Generate param traits write methods.
|
|
||||||
#include "ipc/param_traits_write_macros.h"
|
|
||||||
namespace IPC {
|
|
||||||
#include "media/gpu/ipc/common/media_message_generator.h"
|
|
||||||
} // namespace IPC
|
|
||||||
|
|
||||||
// Generate param traits read methods.
|
|
||||||
#include "ipc/param_traits_read_macros.h"
|
|
||||||
namespace IPC {
|
|
||||||
#include "media/gpu/ipc/common/media_message_generator.h"
|
|
||||||
} // namespace IPC
|
|
||||||
|
|
||||||
// Generate param traits log methods.
|
|
||||||
#include "ipc/param_traits_log_macros.h"
|
|
||||||
namespace IPC {
|
|
||||||
#include "media/gpu/ipc/common/media_message_generator.h"
|
|
||||||
} // namespace IPC
|
|
@ -1,8 +0,0 @@
|
|||||||
// 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.
|
|
||||||
|
|
||||||
// Multiply-included file, hence no include guard.
|
|
||||||
|
|
||||||
#include "build/build_config.h"
|
|
||||||
#include "media/gpu/ipc/common/media_messages.h"
|
|
@ -1,114 +0,0 @@
|
|||||||
// 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.
|
|
||||||
|
|
||||||
// Multiply-included message file, hence no include guard here, but see below
|
|
||||||
// for a much smaller-than-usual include guard section.
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include "base/unguessable_token.h"
|
|
||||||
#include "gpu/config/gpu_info.h"
|
|
||||||
#include "gpu/ipc/common/gpu_param_traits_macros.h"
|
|
||||||
#include "ipc/ipc_message_macros.h"
|
|
||||||
#include "ipc/ipc_message_start.h"
|
|
||||||
#include "ipc/param_traits_macros.h"
|
|
||||||
#include "media/base/overlay_info.h"
|
|
||||||
#include "media/gpu/ipc/common/media_param_traits.h"
|
|
||||||
#include "media/video/video_decode_accelerator.h"
|
|
||||||
#include "ui/gfx/ipc/color/gfx_param_traits.h"
|
|
||||||
#include "ui/gfx/ipc/gfx_param_traits.h"
|
|
||||||
|
|
||||||
#define IPC_MESSAGE_START MediaMsgStart
|
|
||||||
|
|
||||||
IPC_STRUCT_BEGIN(AcceleratedVideoDecoderHostMsg_PictureReady_Params)
|
|
||||||
IPC_STRUCT_MEMBER(int32_t, picture_buffer_id)
|
|
||||||
IPC_STRUCT_MEMBER(int32_t, bitstream_buffer_id)
|
|
||||||
IPC_STRUCT_MEMBER(gfx::Rect, visible_rect)
|
|
||||||
IPC_STRUCT_MEMBER(gfx::ColorSpace, color_space)
|
|
||||||
IPC_STRUCT_MEMBER(bool, allow_overlay)
|
|
||||||
IPC_STRUCT_MEMBER(bool, read_lock_fences_enabled)
|
|
||||||
IPC_STRUCT_MEMBER(bool, size_changed)
|
|
||||||
IPC_STRUCT_MEMBER(bool, surface_texture)
|
|
||||||
IPC_STRUCT_MEMBER(bool, wants_promotion_hint)
|
|
||||||
IPC_STRUCT_END()
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// Accelerated Video Decoder Messages
|
|
||||||
// These messages are sent from Renderer process to GPU process.
|
|
||||||
|
|
||||||
// Create and initialize a hardware video decoder using the specified route_id.
|
|
||||||
// Created decoders should be freed with AcceleratedVideoDecoderMsg_Destroy when
|
|
||||||
// no longer needed.
|
|
||||||
IPC_SYNC_MESSAGE_ROUTED2_1(GpuCommandBufferMsg_CreateVideoDecoder,
|
|
||||||
media::VideoDecodeAccelerator::Config /* config */,
|
|
||||||
int32_t /* decoder_route_id */,
|
|
||||||
bool /* succeeded */)
|
|
||||||
|
|
||||||
// Send input buffer for decoding.
|
|
||||||
IPC_MESSAGE_ROUTED1(AcceleratedVideoDecoderMsg_Decode, media::BitstreamBuffer)
|
|
||||||
|
|
||||||
// Give the texture IDs for the textures the decoder will use for output.
|
|
||||||
IPC_MESSAGE_ROUTED2(
|
|
||||||
AcceleratedVideoDecoderMsg_AssignPictureBuffers,
|
|
||||||
std::vector<int32_t>, /* Picture buffer ID */
|
|
||||||
std::vector<media::PictureBuffer::TextureIds>) /* Texture ID */
|
|
||||||
|
|
||||||
// Send from Renderer process to the GPU process to recycle the given picture
|
|
||||||
// buffer for further decoding.
|
|
||||||
IPC_MESSAGE_ROUTED1(AcceleratedVideoDecoderMsg_ReusePictureBuffer,
|
|
||||||
int32_t) /* Picture buffer ID */
|
|
||||||
|
|
||||||
// Send flush request to the decoder.
|
|
||||||
IPC_MESSAGE_ROUTED0(AcceleratedVideoDecoderMsg_Flush)
|
|
||||||
|
|
||||||
// Send reset request to the decoder.
|
|
||||||
IPC_MESSAGE_ROUTED0(AcceleratedVideoDecoderMsg_Reset)
|
|
||||||
|
|
||||||
// Send overlay info to the decoder.
|
|
||||||
IPC_MESSAGE_ROUTED1(AcceleratedVideoDecoderMsg_SetOverlayInfo,
|
|
||||||
media::OverlayInfo)
|
|
||||||
|
|
||||||
// Send destroy request to the decoder.
|
|
||||||
IPC_MESSAGE_ROUTED0(AcceleratedVideoDecoderMsg_Destroy)
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// Accelerated Video Decoder Host Messages
|
|
||||||
// These messages are sent from GPU process to Renderer process.
|
|
||||||
// Inform AcceleratedVideoDecoderHost that AcceleratedVideoDecoder has been
|
|
||||||
// created.
|
|
||||||
|
|
||||||
// Notify the deferred initialization result.
|
|
||||||
IPC_MESSAGE_ROUTED1(AcceleratedVideoDecoderHostMsg_InitializationComplete,
|
|
||||||
bool) /* success */
|
|
||||||
|
|
||||||
// Accelerated video decoder has consumed input buffer from transfer buffer.
|
|
||||||
IPC_MESSAGE_ROUTED1(AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed,
|
|
||||||
int32_t) /* Processed buffer ID */
|
|
||||||
|
|
||||||
// Allocate video frames for output of the hardware video decoder.
|
|
||||||
IPC_MESSAGE_ROUTED5(AcceleratedVideoDecoderHostMsg_ProvidePictureBuffers,
|
|
||||||
int32_t, /* Number of video frames to generate */
|
|
||||||
media::VideoPixelFormat, /* Picture buffer format */
|
|
||||||
uint32_t, /* Number of textures per frame */
|
|
||||||
gfx::Size, /* Requested size of buffer */
|
|
||||||
uint32_t) /* Texture target */
|
|
||||||
|
|
||||||
// Decoder reports that a picture is ready and buffer does not need to be passed
|
|
||||||
// back to the decoder.
|
|
||||||
IPC_MESSAGE_ROUTED1(AcceleratedVideoDecoderHostMsg_DismissPictureBuffer,
|
|
||||||
int32_t) /* Picture buffer ID */
|
|
||||||
|
|
||||||
// Decoder reports that a picture is ready.
|
|
||||||
IPC_MESSAGE_ROUTED1(AcceleratedVideoDecoderHostMsg_PictureReady,
|
|
||||||
AcceleratedVideoDecoderHostMsg_PictureReady_Params)
|
|
||||||
|
|
||||||
// Confirm decoder has been flushed.
|
|
||||||
IPC_MESSAGE_ROUTED0(AcceleratedVideoDecoderHostMsg_FlushDone)
|
|
||||||
|
|
||||||
// Confirm decoder has been reset.
|
|
||||||
IPC_MESSAGE_ROUTED0(AcceleratedVideoDecoderHostMsg_ResetDone)
|
|
||||||
|
|
||||||
// Video decoder has encountered an error.
|
|
||||||
IPC_MESSAGE_ROUTED1(AcceleratedVideoDecoderHostMsg_ErrorNotification,
|
|
||||||
uint32_t /* Error ID */)
|
|
@ -36,6 +36,7 @@ target(link_target_type, "service") {
|
|||||||
"//ipc",
|
"//ipc",
|
||||||
"//media",
|
"//media",
|
||||||
"//media/gpu",
|
"//media/gpu",
|
||||||
|
"//media/mojo/mojom",
|
||||||
]
|
]
|
||||||
deps = [
|
deps = [
|
||||||
"//build:chromeos_buildflags",
|
"//build:chromeos_buildflags",
|
||||||
|
3
media/gpu/ipc/service/OWNERS
Normal file
3
media/gpu/ipc/service/OWNERS
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# For security review.
|
||||||
|
per-file media_gpu_channel.cc=set noparent
|
||||||
|
per-file media_gpu_channel.cc=file://ipc/SECURITY_OWNERS
|
@ -8,10 +8,12 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "base/bind.h"
|
#include "base/bind.h"
|
||||||
|
#include "base/bind_post_task.h"
|
||||||
#include "base/location.h"
|
#include "base/location.h"
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
#include "base/memory/ref_counted.h"
|
#include "base/memory/ref_counted.h"
|
||||||
#include "base/single_thread_task_runner.h"
|
#include "base/single_thread_task_runner.h"
|
||||||
|
#include "base/synchronization/waitable_event.h"
|
||||||
#include "base/threading/thread_task_runner_handle.h"
|
#include "base/threading/thread_task_runner_handle.h"
|
||||||
#include "build/build_config.h"
|
#include "build/build_config.h"
|
||||||
#include "gpu/command_buffer/common/command_buffer.h"
|
#include "gpu/command_buffer/common/command_buffer.h"
|
||||||
@ -24,7 +26,7 @@
|
|||||||
#include "media/base/limits.h"
|
#include "media/base/limits.h"
|
||||||
#include "media/gpu/gpu_video_accelerator_util.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_factory.h"
|
||||||
#include "media/gpu/ipc/common/media_messages.h"
|
#include "mojo/public/cpp/bindings/associated_receiver.h"
|
||||||
#include "ui/gfx/geometry/size.h"
|
#include "ui/gfx/geometry/size.h"
|
||||||
#include "ui/gl/gl_context.h"
|
#include "ui/gl/gl_context.h"
|
||||||
#include "ui/gl/gl_image.h"
|
#include "ui/gl/gl_image.h"
|
||||||
@ -115,65 +117,159 @@ class DebugAutoLock {
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class GpuVideoDecodeAccelerator::MessageFilter : public IPC::MessageFilter {
|
// Receives incoming messages for the decoder. Operates exclusively on the IO
|
||||||
|
// thread, since sometimes we want to do decodes directly from there.
|
||||||
|
class GpuVideoDecodeAccelerator::MessageFilter
|
||||||
|
: public mojom::GpuAcceleratedVideoDecoder {
|
||||||
public:
|
public:
|
||||||
MessageFilter(GpuVideoDecodeAccelerator* owner, int32_t host_route_id)
|
MessageFilter(GpuVideoDecodeAccelerator* owner,
|
||||||
: owner_(owner), host_route_id_(host_route_id) {}
|
scoped_refptr<base::SequencedTaskRunner> owner_task_runner,
|
||||||
|
bool decode_on_io)
|
||||||
|
: owner_(owner),
|
||||||
|
owner_task_runner_(std::move(owner_task_runner)),
|
||||||
|
decode_on_io_(decode_on_io) {}
|
||||||
|
~MessageFilter() override = default;
|
||||||
|
|
||||||
void OnChannelError() override { sender_ = nullptr; }
|
// Called from the main thread. Posts to `io_task_runner` to do the binding
|
||||||
|
// and waits for completion before returning. This ensures the decoder's
|
||||||
void OnChannelClosing() override { sender_ = nullptr; }
|
// endpoint is established before the synchronous request to establish it is
|
||||||
|
// acknowledged to the client.
|
||||||
void OnFilterAdded(IPC::Channel* channel) override { sender_ = channel; }
|
bool Bind(mojo::PendingAssociatedReceiver<mojom::GpuAcceleratedVideoDecoder>
|
||||||
|
receiver,
|
||||||
void OnFilterRemoved() override {
|
const scoped_refptr<base::SequencedTaskRunner>& io_task_runner) {
|
||||||
// This will delete |owner_| and |this|.
|
base::WaitableEvent bound_event;
|
||||||
owner_->OnFilterRemoved();
|
if (!io_task_runner->PostTask(
|
||||||
}
|
FROM_HERE, base::BindOnce(&MessageFilter::BindOnIoThread,
|
||||||
|
base::Unretained(this),
|
||||||
bool OnMessageReceived(const IPC::Message& msg) override {
|
std::move(receiver), &bound_event))) {
|
||||||
if (msg.routing_id() != host_route_id_)
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
IPC_BEGIN_MESSAGE_MAP(MessageFilter, msg)
|
bound_event.Wait();
|
||||||
IPC_MESSAGE_FORWARD(AcceleratedVideoDecoderMsg_Decode, owner_,
|
|
||||||
GpuVideoDecodeAccelerator::OnDecode)
|
|
||||||
IPC_MESSAGE_UNHANDLED(return false)
|
|
||||||
IPC_END_MESSAGE_MAP()
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SendOnIOThread(IPC::Message* message) {
|
// Must be called on the IO thread. Posts back to the owner's task runner to
|
||||||
DCHECK(!message->is_sync());
|
// destroy it.
|
||||||
if (!sender_) {
|
void RequestShutdown() {
|
||||||
delete message;
|
if (!owner_)
|
||||||
return false;
|
return;
|
||||||
}
|
|
||||||
return sender_->Send(message);
|
// Must be reset here on the IO thread before `this` is destroyed.
|
||||||
|
receiver_.reset();
|
||||||
|
|
||||||
|
GpuVideoDecodeAccelerator* owner = owner_;
|
||||||
|
owner_ = nullptr;
|
||||||
|
|
||||||
|
// Invalidate any IO thread WeakPtrs which may be held by the
|
||||||
|
// VideoDecodeAccelerator, and post to delete our owner which will in turn
|
||||||
|
// delete us. Note that it is unsafe to access any members of `this` once
|
||||||
|
// the task below is posted.
|
||||||
|
owner->weak_factory_for_io_.InvalidateWeakPtrs();
|
||||||
|
owner_task_runner_->PostTask(
|
||||||
|
FROM_HERE, base::BindOnce(&GpuVideoDecodeAccelerator::DeleteSelfNow,
|
||||||
|
base::Unretained(owner)));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
// mojom::GpuAcceleratedVideoDecoder:
|
||||||
~MessageFilter() override = default;
|
void Decode(BitstreamBuffer buffer) override;
|
||||||
|
void AssignPictureBuffers(
|
||||||
|
std::vector<mojom::PictureBufferAssignmentPtr> assignments) override;
|
||||||
|
void ReusePictureBuffer(int32_t picture_buffer_id) override;
|
||||||
|
void Flush(FlushCallback callback) override;
|
||||||
|
void Reset(ResetCallback callback) override;
|
||||||
|
void SetOverlayInfo(const OverlayInfo& overlay_info) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GpuVideoDecodeAccelerator* const owner_;
|
void BindOnIoThread(mojo::PendingAssociatedReceiver<
|
||||||
const int32_t host_route_id_;
|
mojom::GpuAcceleratedVideoDecoder> receiver,
|
||||||
// The sender to which this filter was added.
|
base::WaitableEvent* bound_event) {
|
||||||
IPC::Sender* sender_;
|
receiver_.Bind(std::move(receiver));
|
||||||
|
receiver_.set_disconnect_handler(
|
||||||
|
base::BindOnce(&MessageFilter::OnDisconnect, base::Unretained(this)));
|
||||||
|
bound_event->Signal();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnDisconnect() {
|
||||||
|
if (!owner_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
owner_task_runner_->PostTask(
|
||||||
|
FROM_HERE, base::BindOnce(&GpuVideoDecodeAccelerator::OnDestroy,
|
||||||
|
base::Unretained(owner_)));
|
||||||
|
}
|
||||||
|
|
||||||
|
GpuVideoDecodeAccelerator* owner_;
|
||||||
|
const scoped_refptr<base::SequencedTaskRunner> owner_task_runner_;
|
||||||
|
const bool decode_on_io_;
|
||||||
|
mojo::AssociatedReceiver<mojom::GpuAcceleratedVideoDecoder> receiver_{this};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void GpuVideoDecodeAccelerator::MessageFilter::Decode(BitstreamBuffer buffer) {
|
||||||
|
if (!owner_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (decode_on_io_) {
|
||||||
|
owner_->OnDecode(std::move(buffer));
|
||||||
|
} else {
|
||||||
|
owner_task_runner_->PostTask(
|
||||||
|
FROM_HERE, base::BindOnce(&GpuVideoDecodeAccelerator::OnDecode,
|
||||||
|
base::Unretained(owner_), std::move(buffer)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpuVideoDecodeAccelerator::MessageFilter::AssignPictureBuffers(
|
||||||
|
std::vector<mojom::PictureBufferAssignmentPtr> assignments) {
|
||||||
|
if (!owner_)
|
||||||
|
return;
|
||||||
|
owner_task_runner_->PostTask(
|
||||||
|
FROM_HERE,
|
||||||
|
base::BindOnce(&GpuVideoDecodeAccelerator::OnAssignPictureBuffers,
|
||||||
|
base::Unretained(owner_), std::move(assignments)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpuVideoDecodeAccelerator::MessageFilter::ReusePictureBuffer(
|
||||||
|
int32_t picture_buffer_id) {
|
||||||
|
if (!owner_)
|
||||||
|
return;
|
||||||
|
owner_task_runner_->PostTask(
|
||||||
|
FROM_HERE,
|
||||||
|
base::BindOnce(&GpuVideoDecodeAccelerator::OnReusePictureBuffer,
|
||||||
|
base::Unretained(owner_), picture_buffer_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpuVideoDecodeAccelerator::MessageFilter::Flush(FlushCallback callback) {
|
||||||
|
if (!owner_)
|
||||||
|
return;
|
||||||
|
owner_task_runner_->PostTask(
|
||||||
|
FROM_HERE, base::BindOnce(&GpuVideoDecodeAccelerator::OnFlush,
|
||||||
|
base::Unretained(owner_), std::move(callback)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpuVideoDecodeAccelerator::MessageFilter::Reset(ResetCallback callback) {
|
||||||
|
if (!owner_)
|
||||||
|
return;
|
||||||
|
owner_task_runner_->PostTask(
|
||||||
|
FROM_HERE, base::BindOnce(&GpuVideoDecodeAccelerator::OnReset,
|
||||||
|
base::Unretained(owner_), std::move(callback)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpuVideoDecodeAccelerator::MessageFilter::SetOverlayInfo(
|
||||||
|
const OverlayInfo& overlay_info) {
|
||||||
|
if (!owner_)
|
||||||
|
return;
|
||||||
|
owner_task_runner_->PostTask(
|
||||||
|
FROM_HERE, base::BindOnce(&GpuVideoDecodeAccelerator::OnSetOverlayInfo,
|
||||||
|
base::Unretained(owner_), overlay_info));
|
||||||
|
}
|
||||||
|
|
||||||
GpuVideoDecodeAccelerator::GpuVideoDecodeAccelerator(
|
GpuVideoDecodeAccelerator::GpuVideoDecodeAccelerator(
|
||||||
int32_t host_route_id,
|
|
||||||
gpu::CommandBufferStub* stub,
|
gpu::CommandBufferStub* stub,
|
||||||
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
|
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
|
||||||
const AndroidOverlayMojoFactoryCB& overlay_factory_cb)
|
const AndroidOverlayMojoFactoryCB& overlay_factory_cb)
|
||||||
: host_route_id_(host_route_id),
|
: stub_(stub),
|
||||||
stub_(stub),
|
|
||||||
texture_target_(0),
|
texture_target_(0),
|
||||||
pixel_format_(PIXEL_FORMAT_UNKNOWN),
|
pixel_format_(PIXEL_FORMAT_UNKNOWN),
|
||||||
textures_per_buffer_(0),
|
textures_per_buffer_(0),
|
||||||
filter_removed_(base::WaitableEvent::ResetPolicy::MANUAL,
|
|
||||||
base::WaitableEvent::InitialState::NOT_SIGNALED),
|
|
||||||
child_task_runner_(base::ThreadTaskRunnerHandle::Get()),
|
child_task_runner_(base::ThreadTaskRunnerHandle::Get()),
|
||||||
io_task_runner_(io_task_runner),
|
io_task_runner_(io_task_runner),
|
||||||
overlay_factory_cb_(overlay_factory_cb) {
|
overlay_factory_cb_(overlay_factory_cb) {
|
||||||
@ -202,6 +298,10 @@ GpuVideoDecodeAccelerator::~GpuVideoDecodeAccelerator() {
|
|||||||
DCHECK(!video_decode_accelerator_);
|
DCHECK(!video_decode_accelerator_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GpuVideoDecodeAccelerator::DeleteSelfNow() {
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
gpu::VideoDecodeAcceleratorCapabilities
|
gpu::VideoDecodeAcceleratorCapabilities
|
||||||
GpuVideoDecodeAccelerator::GetCapabilities(
|
GpuVideoDecodeAccelerator::GetCapabilities(
|
||||||
@ -211,33 +311,8 @@ GpuVideoDecodeAccelerator::GetCapabilities(
|
|||||||
gpu_preferences, workarounds);
|
gpu_preferences, workarounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GpuVideoDecodeAccelerator::OnMessageReceived(const IPC::Message& msg) {
|
|
||||||
if (!video_decode_accelerator_)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
bool handled = true;
|
|
||||||
IPC_BEGIN_MESSAGE_MAP(GpuVideoDecodeAccelerator, msg)
|
|
||||||
IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_Decode, OnDecode)
|
|
||||||
IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_AssignPictureBuffers,
|
|
||||||
OnAssignPictureBuffers)
|
|
||||||
IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_ReusePictureBuffer,
|
|
||||||
OnReusePictureBuffer)
|
|
||||||
IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_Flush, OnFlush)
|
|
||||||
IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_Reset, OnReset)
|
|
||||||
IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_SetOverlayInfo,
|
|
||||||
OnSetOverlayInfo)
|
|
||||||
IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_Destroy, OnDestroy)
|
|
||||||
IPC_MESSAGE_UNHANDLED(handled = false)
|
|
||||||
IPC_END_MESSAGE_MAP()
|
|
||||||
return handled;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GpuVideoDecodeAccelerator::NotifyInitializationComplete(Status status) {
|
void GpuVideoDecodeAccelerator::NotifyInitializationComplete(Status status) {
|
||||||
// TODO(tmathmeyer) convert the IPC send to a Status.
|
decoder_client_->OnInitializationComplete(status.is_ok());
|
||||||
if (!Send(new AcceleratedVideoDecoderHostMsg_InitializationComplete(
|
|
||||||
host_route_id_, status.is_ok())))
|
|
||||||
DLOG(ERROR)
|
|
||||||
<< "Send(AcceleratedVideoDecoderHostMsg_InitializationComplete) failed";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpuVideoDecodeAccelerator::ProvidePictureBuffers(
|
void GpuVideoDecodeAccelerator::ProvidePictureBuffers(
|
||||||
@ -252,26 +327,21 @@ void GpuVideoDecodeAccelerator::ProvidePictureBuffers(
|
|||||||
NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE);
|
NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!Send(new AcceleratedVideoDecoderHostMsg_ProvidePictureBuffers(
|
|
||||||
host_route_id_, requested_num_of_buffers, format, textures_per_buffer,
|
|
||||||
dimensions, texture_target))) {
|
|
||||||
DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ProvidePictureBuffers) "
|
|
||||||
<< "failed";
|
|
||||||
}
|
|
||||||
texture_dimensions_ = dimensions;
|
texture_dimensions_ = dimensions;
|
||||||
textures_per_buffer_ = textures_per_buffer;
|
textures_per_buffer_ = textures_per_buffer;
|
||||||
texture_target_ = texture_target;
|
texture_target_ = texture_target;
|
||||||
pixel_format_ = format;
|
pixel_format_ = format;
|
||||||
|
|
||||||
|
decoder_client_->OnProvidePictureBuffers(requested_num_of_buffers, format,
|
||||||
|
textures_per_buffer, dimensions,
|
||||||
|
texture_target);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpuVideoDecodeAccelerator::DismissPictureBuffer(
|
void GpuVideoDecodeAccelerator::DismissPictureBuffer(
|
||||||
int32_t picture_buffer_id) {
|
int32_t picture_buffer_id) {
|
||||||
// Notify client that picture buffer is now unused.
|
// Notify client that picture buffer is now unused.
|
||||||
if (!Send(new AcceleratedVideoDecoderHostMsg_DismissPictureBuffer(
|
decoder_client_->OnDismissPictureBuffer(picture_buffer_id);
|
||||||
host_route_id_, picture_buffer_id))) {
|
|
||||||
DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_DismissPictureBuffer) "
|
|
||||||
<< "failed";
|
|
||||||
}
|
|
||||||
DebugAutoLock auto_lock(debug_uncleared_textures_lock_);
|
DebugAutoLock auto_lock(debug_uncleared_textures_lock_);
|
||||||
uncleared_textures_.erase(picture_buffer_id);
|
uncleared_textures_.erase(picture_buffer_id);
|
||||||
}
|
}
|
||||||
@ -288,49 +358,39 @@ void GpuVideoDecodeAccelerator::PictureReady(const Picture& picture) {
|
|||||||
DCHECK_EQ(0u, uncleared_textures_.count(picture.picture_buffer_id()));
|
DCHECK_EQ(0u, uncleared_textures_.count(picture.picture_buffer_id()));
|
||||||
}
|
}
|
||||||
|
|
||||||
AcceleratedVideoDecoderHostMsg_PictureReady_Params params;
|
auto params = mojom::PictureReadyParams::New();
|
||||||
params.picture_buffer_id = picture.picture_buffer_id();
|
params->picture_buffer_id = picture.picture_buffer_id();
|
||||||
params.bitstream_buffer_id = picture.bitstream_buffer_id();
|
params->bitstream_buffer_id = picture.bitstream_buffer_id();
|
||||||
params.visible_rect = picture.visible_rect();
|
params->visible_rect = picture.visible_rect();
|
||||||
params.color_space = picture.color_space();
|
params->color_space = picture.color_space();
|
||||||
params.allow_overlay = picture.allow_overlay();
|
params->allow_overlay = picture.allow_overlay();
|
||||||
params.read_lock_fences_enabled = picture.read_lock_fences_enabled();
|
params->read_lock_fences_enabled = picture.read_lock_fences_enabled();
|
||||||
params.size_changed = picture.size_changed();
|
params->size_changed = picture.size_changed();
|
||||||
params.surface_texture = picture.texture_owner();
|
params->surface_texture = picture.texture_owner();
|
||||||
params.wants_promotion_hint = picture.wants_promotion_hint();
|
params->wants_promotion_hint = picture.wants_promotion_hint();
|
||||||
if (!Send(new AcceleratedVideoDecoderHostMsg_PictureReady(host_route_id_,
|
decoder_client_->OnPictureReady(std::move(params));
|
||||||
params))) {
|
|
||||||
DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_PictureReady) failed";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpuVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer(
|
void GpuVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer(
|
||||||
int32_t bitstream_buffer_id) {
|
int32_t bitstream_buffer_id) {
|
||||||
if (!Send(new AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed(
|
decoder_client_->OnBitstreamBufferProcessed(bitstream_buffer_id);
|
||||||
host_route_id_, bitstream_buffer_id))) {
|
|
||||||
DLOG(ERROR)
|
|
||||||
<< "Send(AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed) "
|
|
||||||
<< "failed";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpuVideoDecodeAccelerator::NotifyFlushDone() {
|
void GpuVideoDecodeAccelerator::NotifyFlushDone() {
|
||||||
if (!Send(new AcceleratedVideoDecoderHostMsg_FlushDone(host_route_id_)))
|
DCHECK(!pending_flushes_.empty());
|
||||||
DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_FlushDone) failed";
|
std::move(pending_flushes_.front()).Run();
|
||||||
|
pending_flushes_.pop_front();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpuVideoDecodeAccelerator::NotifyResetDone() {
|
void GpuVideoDecodeAccelerator::NotifyResetDone() {
|
||||||
if (!Send(new AcceleratedVideoDecoderHostMsg_ResetDone(host_route_id_)))
|
DCHECK(!pending_resets_.empty());
|
||||||
DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ResetDone) failed";
|
std::move(pending_resets_.front()).Run();
|
||||||
|
pending_resets_.pop_front();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpuVideoDecodeAccelerator::NotifyError(
|
void GpuVideoDecodeAccelerator::NotifyError(
|
||||||
VideoDecodeAccelerator::Error error) {
|
VideoDecodeAccelerator::Error error) {
|
||||||
if (!Send(new AcceleratedVideoDecoderHostMsg_ErrorNotification(host_route_id_,
|
decoder_client_->OnError(error);
|
||||||
error))) {
|
|
||||||
DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ErrorNotification) "
|
|
||||||
<< "failed";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpuVideoDecodeAccelerator::OnWillDestroyStub(bool have_context) {
|
void GpuVideoDecodeAccelerator::OnWillDestroyStub(bool have_context) {
|
||||||
@ -342,34 +402,23 @@ void GpuVideoDecodeAccelerator::OnWillDestroyStub(bool have_context) {
|
|||||||
// we don't want to synchronize the IO thread with the ChildThread.
|
// we don't want to synchronize the IO thread with the ChildThread.
|
||||||
// So we have to wait for the RemoveFilter callback here instead and remove
|
// So we have to wait for the RemoveFilter callback here instead and remove
|
||||||
// the VDA after it arrives and before returning.
|
// the VDA after it arrives and before returning.
|
||||||
|
stub_->RemoveDestructionObserver(this);
|
||||||
if (filter_) {
|
if (filter_) {
|
||||||
stub_->channel()->RemoveFilter(filter_.get());
|
io_task_runner_->PostTask(FROM_HERE,
|
||||||
filter_removed_.Wait();
|
base::BindOnce(&MessageFilter::RequestShutdown,
|
||||||
|
base::Unretained(filter_.get())));
|
||||||
}
|
}
|
||||||
|
|
||||||
stub_->channel()->RemoveRoute(host_route_id_);
|
|
||||||
stub_->RemoveDestructionObserver(this);
|
|
||||||
|
|
||||||
video_decode_accelerator_.reset();
|
video_decode_accelerator_.reset();
|
||||||
delete this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GpuVideoDecodeAccelerator::Send(IPC::Message* message) {
|
|
||||||
if (filter_ && io_task_runner_->BelongsToCurrentThread())
|
|
||||||
return filter_->SendOnIOThread(message);
|
|
||||||
DCHECK(child_task_runner_->BelongsToCurrentThread());
|
|
||||||
return stub_->channel()->Send(message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GpuVideoDecodeAccelerator::Initialize(
|
bool GpuVideoDecodeAccelerator::Initialize(
|
||||||
const VideoDecodeAccelerator::Config& config) {
|
const VideoDecodeAccelerator::Config& config,
|
||||||
|
mojo::PendingAssociatedReceiver<mojom::GpuAcceleratedVideoDecoder> receiver,
|
||||||
|
mojo::PendingAssociatedRemote<mojom::GpuAcceleratedVideoDecoderClient>
|
||||||
|
client) {
|
||||||
DCHECK(!video_decode_accelerator_);
|
DCHECK(!video_decode_accelerator_);
|
||||||
|
|
||||||
if (!stub_->channel()->AddRoute(host_route_id_, stub_->sequence_id(), this)) {
|
|
||||||
DLOG(ERROR) << "Initialize(): failed to add route";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(OS_WIN)
|
#if !defined(OS_WIN)
|
||||||
// Ensure we will be able to get a GL context at all before initializing
|
// Ensure we will be able to get a GL context at all before initializing
|
||||||
// non-Windows VDAs.
|
// non-Windows VDAs.
|
||||||
@ -404,15 +453,19 @@ bool GpuVideoDecodeAccelerator::Initialize(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
decoder_client_.Bind(std::move(client), io_task_runner_);
|
||||||
|
|
||||||
// Attempt to set up performing decoding tasks on IO thread, if supported by
|
// Attempt to set up performing decoding tasks on IO thread, if supported by
|
||||||
// the VDA.
|
// the VDA.
|
||||||
if (video_decode_accelerator_->TryToSetupDecodeOnSeparateThread(
|
bool decode_on_io =
|
||||||
weak_factory_for_io_.GetWeakPtr(), io_task_runner_)) {
|
video_decode_accelerator_->TryToSetupDecodeOnSeparateThread(
|
||||||
filter_ = new MessageFilter(this, host_route_id_);
|
weak_factory_for_io_.GetWeakPtr(), io_task_runner_);
|
||||||
stub_->channel()->AddFilter(filter_.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
// Bind the receiver on the IO thread. We wait here for it to be bound
|
||||||
|
// before returning and signaling that the decoder has been created.
|
||||||
|
filter_ =
|
||||||
|
std::make_unique<MessageFilter>(this, stub_->task_runner(), decode_on_io);
|
||||||
|
return filter_->Bind(std::move(receiver), io_task_runner_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Runs on IO thread if VDA::TryToSetupDecodeOnSeparateThread() succeeded,
|
// Runs on IO thread if VDA::TryToSetupDecodeOnSeparateThread() succeeded,
|
||||||
@ -423,27 +476,21 @@ void GpuVideoDecodeAccelerator::OnDecode(BitstreamBuffer bitstream_buffer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GpuVideoDecodeAccelerator::OnAssignPictureBuffers(
|
void GpuVideoDecodeAccelerator::OnAssignPictureBuffers(
|
||||||
const std::vector<int32_t>& buffer_ids,
|
std::vector<mojom::PictureBufferAssignmentPtr> assignments) {
|
||||||
const std::vector<PictureBuffer::TextureIds>& texture_ids) {
|
|
||||||
if (buffer_ids.size() != texture_ids.size()) {
|
|
||||||
NotifyError(VideoDecodeAccelerator::INVALID_ARGUMENT);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
gpu::DecoderContext* decoder_context = stub_->decoder_context();
|
gpu::DecoderContext* decoder_context = stub_->decoder_context();
|
||||||
gpu::gles2::TextureManager* texture_manager =
|
gpu::gles2::TextureManager* texture_manager =
|
||||||
stub_->decoder_context()->GetContextGroup()->texture_manager();
|
stub_->decoder_context()->GetContextGroup()->texture_manager();
|
||||||
|
|
||||||
std::vector<PictureBuffer> buffers;
|
std::vector<PictureBuffer> buffers;
|
||||||
std::vector<std::vector<scoped_refptr<gpu::gles2::TextureRef>>> textures;
|
std::vector<std::vector<scoped_refptr<gpu::gles2::TextureRef>>> textures;
|
||||||
for (uint32_t i = 0; i < buffer_ids.size(); ++i) {
|
for (const auto& assignment : assignments) {
|
||||||
if (buffer_ids[i] < 0) {
|
if (assignment->buffer_id < 0) {
|
||||||
DLOG(ERROR) << "Buffer id " << buffer_ids[i] << " out of range";
|
DLOG(ERROR) << "Buffer id " << assignment->buffer_id << " out of range";
|
||||||
NotifyError(VideoDecodeAccelerator::INVALID_ARGUMENT);
|
NotifyError(VideoDecodeAccelerator::INVALID_ARGUMENT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::vector<scoped_refptr<gpu::gles2::TextureRef>> current_textures;
|
std::vector<scoped_refptr<gpu::gles2::TextureRef>> current_textures;
|
||||||
PictureBuffer::TextureIds buffer_texture_ids = texture_ids[i];
|
PictureBuffer::TextureIds buffer_texture_ids = assignment->texture_ids;
|
||||||
PictureBuffer::TextureIds service_ids;
|
PictureBuffer::TextureIds service_ids;
|
||||||
if (buffer_texture_ids.size() != textures_per_buffer_) {
|
if (buffer_texture_ids.size() != textures_per_buffer_) {
|
||||||
DLOG(ERROR) << "Requested " << textures_per_buffer_
|
DLOG(ERROR) << "Requested " << textures_per_buffer_
|
||||||
@ -511,14 +558,14 @@ void GpuVideoDecodeAccelerator::OnAssignPictureBuffers(
|
|||||||
service_ids.push_back(texture_base->service_id());
|
service_ids.push_back(texture_base->service_id());
|
||||||
}
|
}
|
||||||
textures.push_back(current_textures);
|
textures.push_back(current_textures);
|
||||||
buffers.push_back(PictureBuffer(buffer_ids[i], texture_dimensions_,
|
buffers.emplace_back(assignment->buffer_id, texture_dimensions_,
|
||||||
buffer_texture_ids, service_ids,
|
buffer_texture_ids, service_ids, texture_target_,
|
||||||
texture_target_, pixel_format_));
|
pixel_format_);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
DebugAutoLock auto_lock(debug_uncleared_textures_lock_);
|
DebugAutoLock auto_lock(debug_uncleared_textures_lock_);
|
||||||
for (uint32_t i = 0; i < buffer_ids.size(); ++i)
|
for (uint32_t i = 0; i < assignments.size(); ++i)
|
||||||
uncleared_textures_[buffer_ids[i]] = textures[i];
|
uncleared_textures_[assignments[i]->buffer_id] = textures[i];
|
||||||
}
|
}
|
||||||
video_decode_accelerator_->AssignPictureBuffers(buffers);
|
video_decode_accelerator_->AssignPictureBuffers(buffers);
|
||||||
}
|
}
|
||||||
@ -529,13 +576,17 @@ void GpuVideoDecodeAccelerator::OnReusePictureBuffer(
|
|||||||
video_decode_accelerator_->ReusePictureBuffer(picture_buffer_id);
|
video_decode_accelerator_->ReusePictureBuffer(picture_buffer_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpuVideoDecodeAccelerator::OnFlush() {
|
void GpuVideoDecodeAccelerator::OnFlush(base::OnceClosure callback) {
|
||||||
DCHECK(video_decode_accelerator_);
|
DCHECK(video_decode_accelerator_);
|
||||||
|
pending_flushes_.push_back(
|
||||||
|
base::BindPostTask(io_task_runner_, std::move(callback)));
|
||||||
video_decode_accelerator_->Flush();
|
video_decode_accelerator_->Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpuVideoDecodeAccelerator::OnReset() {
|
void GpuVideoDecodeAccelerator::OnReset(base::OnceClosure callback) {
|
||||||
DCHECK(video_decode_accelerator_);
|
DCHECK(video_decode_accelerator_);
|
||||||
|
pending_resets_.push_back(
|
||||||
|
base::BindPostTask(io_task_runner_, std::move(callback)));
|
||||||
video_decode_accelerator_->Reset();
|
video_decode_accelerator_->Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -550,12 +601,6 @@ void GpuVideoDecodeAccelerator::OnDestroy() {
|
|||||||
OnWillDestroyStub(false);
|
OnWillDestroyStub(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpuVideoDecodeAccelerator::OnFilterRemoved() {
|
|
||||||
// We're destroying; cancel all callbacks.
|
|
||||||
weak_factory_for_io_.InvalidateWeakPtrs();
|
|
||||||
filter_removed_.Signal();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GpuVideoDecodeAccelerator::SetTextureCleared(const Picture& picture) {
|
void GpuVideoDecodeAccelerator::SetTextureCleared(const Picture& picture) {
|
||||||
DCHECK(child_task_runner_->BelongsToCurrentThread());
|
DCHECK(child_task_runner_->BelongsToCurrentThread());
|
||||||
DebugAutoLock auto_lock(debug_uncleared_textures_lock_);
|
DebugAutoLock auto_lock(debug_uncleared_textures_lock_);
|
||||||
|
@ -11,18 +11,21 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "base/callback.h"
|
||||||
#include "base/compiler_specific.h"
|
#include "base/compiler_specific.h"
|
||||||
|
#include "base/containers/circular_deque.h"
|
||||||
#include "base/macros.h"
|
#include "base/macros.h"
|
||||||
#include "base/memory/ref_counted.h"
|
#include "base/memory/ref_counted.h"
|
||||||
#include "base/synchronization/waitable_event.h"
|
|
||||||
#include "gpu/command_buffer/service/texture_manager.h"
|
#include "gpu/command_buffer/service/texture_manager.h"
|
||||||
#include "gpu/config/gpu_info.h"
|
#include "gpu/config/gpu_info.h"
|
||||||
#include "gpu/ipc/service/command_buffer_stub.h"
|
#include "gpu/ipc/service/command_buffer_stub.h"
|
||||||
#include "ipc/ipc_listener.h"
|
|
||||||
#include "ipc/ipc_sender.h"
|
|
||||||
#include "media/base/android_overlay_mojo_factory.h"
|
#include "media/base/android_overlay_mojo_factory.h"
|
||||||
#include "media/gpu/gpu_video_decode_accelerator_helpers.h"
|
#include "media/gpu/gpu_video_decode_accelerator_helpers.h"
|
||||||
|
#include "media/mojo/mojom/gpu_accelerated_video_decoder.mojom.h"
|
||||||
#include "media/video/video_decode_accelerator.h"
|
#include "media/video/video_decode_accelerator.h"
|
||||||
|
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
|
||||||
|
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
|
||||||
|
#include "mojo/public/cpp/bindings/shared_associated_remote.h"
|
||||||
#include "ui/gfx/geometry/size.h"
|
#include "ui/gfx/geometry/size.h"
|
||||||
|
|
||||||
namespace gpu {
|
namespace gpu {
|
||||||
@ -33,16 +36,13 @@ struct GpuPreferences;
|
|||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
class GpuVideoDecodeAccelerator
|
class GpuVideoDecodeAccelerator
|
||||||
: public IPC::Listener,
|
: public VideoDecodeAccelerator::Client,
|
||||||
public IPC::Sender,
|
|
||||||
public VideoDecodeAccelerator::Client,
|
|
||||||
public gpu::CommandBufferStub::DestructionObserver {
|
public gpu::CommandBufferStub::DestructionObserver {
|
||||||
public:
|
public:
|
||||||
// Each of the arguments to the constructor must outlive this object.
|
// Each of the arguments to the constructor must outlive this object.
|
||||||
// |stub->decoder()| will be made current around any operation that touches
|
// |stub->decoder()| will be made current around any operation that touches
|
||||||
// the underlying VDA so that it can make GL calls safely.
|
// the underlying VDA so that it can make GL calls safely.
|
||||||
GpuVideoDecodeAccelerator(
|
GpuVideoDecodeAccelerator(
|
||||||
int32_t host_route_id,
|
|
||||||
gpu::CommandBufferStub* stub,
|
gpu::CommandBufferStub* stub,
|
||||||
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
|
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
|
||||||
const AndroidOverlayMojoFactoryCB& factory);
|
const AndroidOverlayMojoFactoryCB& factory);
|
||||||
@ -54,9 +54,6 @@ class GpuVideoDecodeAccelerator
|
|||||||
const gpu::GpuPreferences& gpu_preferences,
|
const gpu::GpuPreferences& gpu_preferences,
|
||||||
const gpu::GpuDriverBugWorkarounds& workarounds);
|
const gpu::GpuDriverBugWorkarounds& workarounds);
|
||||||
|
|
||||||
// IPC::Listener implementation.
|
|
||||||
bool OnMessageReceived(const IPC::Message& message) override;
|
|
||||||
|
|
||||||
// VideoDecodeAccelerator::Client implementation.
|
// VideoDecodeAccelerator::Client implementation.
|
||||||
void NotifyInitializationComplete(Status status) override;
|
void NotifyInitializationComplete(Status status) override;
|
||||||
void ProvidePictureBuffers(uint32_t requested_num_of_buffers,
|
void ProvidePictureBuffers(uint32_t requested_num_of_buffers,
|
||||||
@ -74,44 +71,41 @@ class GpuVideoDecodeAccelerator
|
|||||||
// CommandBufferStub::DestructionObserver implementation.
|
// CommandBufferStub::DestructionObserver implementation.
|
||||||
void OnWillDestroyStub(bool have_context) override;
|
void OnWillDestroyStub(bool have_context) override;
|
||||||
|
|
||||||
// Function to delegate sending to actual sender.
|
|
||||||
bool Send(IPC::Message* message) override;
|
|
||||||
|
|
||||||
// Initialize VDAs from the set of VDAs supported for current platform until
|
// Initialize VDAs from the set of VDAs supported for current platform until
|
||||||
// one of them succeeds for given |config|. Send the |init_done_msg| when
|
// one of them succeeds for given |config|. Send the |init_done_msg| when
|
||||||
// done. filter_ is passed to gpu::CommandBufferStub channel only if the
|
// done. filter_ is passed to gpu::CommandBufferStub channel only if the
|
||||||
// chosen VDA can decode on IO thread.
|
// chosen VDA can decode on IO thread.
|
||||||
bool Initialize(const VideoDecodeAccelerator::Config& config);
|
bool Initialize(
|
||||||
|
const VideoDecodeAccelerator::Config& config,
|
||||||
|
mojo::PendingAssociatedReceiver<mojom::GpuAcceleratedVideoDecoder>
|
||||||
|
receiver,
|
||||||
|
mojo::PendingAssociatedRemote<mojom::GpuAcceleratedVideoDecoderClient>
|
||||||
|
client);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class MessageFilter;
|
class MessageFilter;
|
||||||
|
|
||||||
// We only allow self-delete, from OnWillDestroyStub(), after cleanup there.
|
// We only allow self-delete, from DeleteSelfNow().
|
||||||
~GpuVideoDecodeAccelerator() override;
|
~GpuVideoDecodeAccelerator() override;
|
||||||
|
|
||||||
|
void DeleteSelfNow();
|
||||||
|
|
||||||
// Handlers for IPC messages.
|
// Handlers for IPC messages.
|
||||||
void OnDecode(BitstreamBuffer bitstream_buffer);
|
void OnDecode(BitstreamBuffer bitstream_buffer);
|
||||||
void OnAssignPictureBuffers(
|
void OnAssignPictureBuffers(
|
||||||
const std::vector<int32_t>& buffer_ids,
|
std::vector<mojom::PictureBufferAssignmentPtr> assignments);
|
||||||
const std::vector<PictureBuffer::TextureIds>& texture_ids);
|
|
||||||
void OnReusePictureBuffer(int32_t picture_buffer_id);
|
void OnReusePictureBuffer(int32_t picture_buffer_id);
|
||||||
void OnFlush();
|
void OnFlush(base::OnceClosure callback);
|
||||||
void OnReset();
|
void OnReset(base::OnceClosure callback);
|
||||||
void OnSetOverlayInfo(const OverlayInfo& overlay_info);
|
void OnSetOverlayInfo(const OverlayInfo& overlay_info);
|
||||||
void OnDestroy();
|
void OnDestroy();
|
||||||
|
|
||||||
// Called on IO thread when |filter_| has been removed.
|
|
||||||
void OnFilterRemoved();
|
|
||||||
|
|
||||||
// Sets the texture to cleared.
|
// Sets the texture to cleared.
|
||||||
void SetTextureCleared(const Picture& picture);
|
void SetTextureCleared(const Picture& picture);
|
||||||
|
|
||||||
// OpenGL Callback methods.
|
// OpenGL Callback methods.
|
||||||
GpuVideoDecodeGLClient gl_client_;
|
GpuVideoDecodeGLClient gl_client_;
|
||||||
|
|
||||||
// Route ID to communicate with the host.
|
|
||||||
const int32_t host_route_id_;
|
|
||||||
|
|
||||||
// Unowned pointer to the underlying gpu::CommandBufferStub. |this| is
|
// Unowned pointer to the underlying gpu::CommandBufferStub. |this| is
|
||||||
// registered as a DestuctionObserver of |stub_| and will self-delete when
|
// registered as a DestuctionObserver of |stub_| and will self-delete when
|
||||||
// |stub_| is destroyed.
|
// |stub_| is destroyed.
|
||||||
@ -120,6 +114,14 @@ class GpuVideoDecodeAccelerator
|
|||||||
// The underlying VideoDecodeAccelerator.
|
// The underlying VideoDecodeAccelerator.
|
||||||
std::unique_ptr<VideoDecodeAccelerator> video_decode_accelerator_;
|
std::unique_ptr<VideoDecodeAccelerator> video_decode_accelerator_;
|
||||||
|
|
||||||
|
// An interface back to the client of this decoder.
|
||||||
|
mojo::SharedAssociatedRemote<mojom::GpuAcceleratedVideoDecoderClient>
|
||||||
|
decoder_client_;
|
||||||
|
|
||||||
|
// Pending replies to Flush and Reset operations.
|
||||||
|
base::circular_deque<base::OnceClosure> pending_flushes_;
|
||||||
|
base::circular_deque<base::OnceClosure> pending_resets_;
|
||||||
|
|
||||||
// The texture dimensions as requested by ProvidePictureBuffers().
|
// The texture dimensions as requested by ProvidePictureBuffers().
|
||||||
gfx::Size texture_dimensions_;
|
gfx::Size texture_dimensions_;
|
||||||
|
|
||||||
@ -134,11 +136,7 @@ class GpuVideoDecodeAccelerator
|
|||||||
uint32_t textures_per_buffer_;
|
uint32_t textures_per_buffer_;
|
||||||
|
|
||||||
// The message filter to run VDA::Decode on IO thread if VDA supports it.
|
// The message filter to run VDA::Decode on IO thread if VDA supports it.
|
||||||
scoped_refptr<MessageFilter> filter_;
|
std::unique_ptr<MessageFilter> filter_;
|
||||||
|
|
||||||
// Used to wait on for |filter_| to be removed, before we can safely
|
|
||||||
// destroy the VDA.
|
|
||||||
base::WaitableEvent filter_removed_;
|
|
||||||
|
|
||||||
// GPU child thread task runner.
|
// GPU child thread task runner.
|
||||||
const scoped_refptr<base::SingleThreadTaskRunner> child_task_runner_;
|
const scoped_refptr<base::SingleThreadTaskRunner> child_task_runner_;
|
||||||
|
@ -4,81 +4,85 @@
|
|||||||
|
|
||||||
#include "media/gpu/ipc/service/media_gpu_channel.h"
|
#include "media/gpu/ipc/service/media_gpu_channel.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include "base/bind.h"
|
||||||
#include "base/single_thread_task_runner.h"
|
#include "base/single_thread_task_runner.h"
|
||||||
|
#include "base/unguessable_token.h"
|
||||||
|
#include "gpu/ipc/service/command_buffer_stub.h"
|
||||||
#include "gpu/ipc/service/gpu_channel.h"
|
#include "gpu/ipc/service/gpu_channel.h"
|
||||||
#include "media/gpu/ipc/common/media_messages.h"
|
#include "ipc/ipc_mojo_bootstrap.h"
|
||||||
#include "media/gpu/ipc/service/gpu_video_decode_accelerator.h"
|
#include "media/gpu/ipc/service/gpu_video_decode_accelerator.h"
|
||||||
|
#include "media/mojo/mojom/gpu_accelerated_video_decoder.mojom.h"
|
||||||
|
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
class MediaGpuChannelDispatchHelper {
|
namespace {
|
||||||
|
|
||||||
|
class DecoderProviderImpl : public mojom::GpuAcceleratedVideoDecoderProvider,
|
||||||
|
public gpu::CommandBufferStub::DestructionObserver {
|
||||||
public:
|
public:
|
||||||
MediaGpuChannelDispatchHelper(MediaGpuChannel* channel, int32_t routing_id)
|
DecoderProviderImpl(gpu::CommandBufferStub* stub,
|
||||||
: channel_(channel), routing_id_(routing_id) {}
|
const AndroidOverlayMojoFactoryCB& overlay_factory_cb)
|
||||||
|
: stub_(stub), overlay_factory_cb_(overlay_factory_cb) {}
|
||||||
|
DecoderProviderImpl(const DecoderProviderImpl&) = delete;
|
||||||
|
DecoderProviderImpl& operator=(const DecoderProviderImpl&) = delete;
|
||||||
|
~DecoderProviderImpl() override = default;
|
||||||
|
|
||||||
bool Send(IPC::Message* msg) { return channel_->Send(msg); }
|
// mojom::GpuAcceleratedVideoDecoderProvider:
|
||||||
|
void CreateAcceleratedVideoDecoder(
|
||||||
|
const VideoDecodeAccelerator::Config& config,
|
||||||
|
mojo::PendingAssociatedReceiver<mojom::GpuAcceleratedVideoDecoder>
|
||||||
|
receiver,
|
||||||
|
mojo::PendingAssociatedRemote<mojom::GpuAcceleratedVideoDecoderClient>
|
||||||
|
client,
|
||||||
|
CreateAcceleratedVideoDecoderCallback callback) override {
|
||||||
|
TRACE_EVENT0("gpu", "DecoderProviderImpl::CreateAcceleratedVideoDecoder");
|
||||||
|
// Only allow stubs that have a ContextGroup, that is, the GLES2 ones. Later
|
||||||
|
// code assumes the ContextGroup is valid.
|
||||||
|
if (!stub_ || !stub_->decoder_context()->GetContextGroup()) {
|
||||||
|
std::move(callback).Run(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
void OnCreateVideoDecoder(const VideoDecodeAccelerator::Config& config,
|
// Note that `decoder` is a self-deleting object.
|
||||||
int32_t decoder_route_id,
|
GpuVideoDecodeAccelerator* decoder = new GpuVideoDecodeAccelerator(
|
||||||
IPC::Message* reply_message) {
|
stub_, stub_->channel()->io_task_runner(), overlay_factory_cb_);
|
||||||
channel_->OnCreateVideoDecoder(routing_id_, config, decoder_route_id,
|
std::move(callback).Run(
|
||||||
reply_message);
|
decoder->Initialize(config, std::move(receiver), std::move(client)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MediaGpuChannel* const channel_;
|
// gpu::CommandBufferStub::DestructionObserver:
|
||||||
const int32_t routing_id_;
|
void OnWillDestroyStub(bool have_context) override { stub_ = nullptr; }
|
||||||
DISALLOW_COPY_AND_ASSIGN(MediaGpuChannelDispatchHelper);
|
|
||||||
|
gpu::CommandBufferStub* stub_;
|
||||||
|
const AndroidOverlayMojoFactoryCB overlay_factory_cb_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
MediaGpuChannel::MediaGpuChannel(
|
MediaGpuChannel::MediaGpuChannel(
|
||||||
gpu::GpuChannel* channel,
|
gpu::GpuChannel* channel,
|
||||||
const AndroidOverlayMojoFactoryCB& overlay_factory_cb)
|
const AndroidOverlayMojoFactoryCB& overlay_factory_cb)
|
||||||
: channel_(channel), overlay_factory_cb_(overlay_factory_cb) {}
|
: channel_(channel), overlay_factory_cb_(overlay_factory_cb) {
|
||||||
|
channel_->set_command_buffer_media_binder(
|
||||||
|
base::BindRepeating(&MediaGpuChannel::BindCommandBufferMediaReceiver,
|
||||||
|
base::Unretained(this)));
|
||||||
|
}
|
||||||
|
|
||||||
MediaGpuChannel::~MediaGpuChannel() = default;
|
MediaGpuChannel::~MediaGpuChannel() = default;
|
||||||
|
|
||||||
bool MediaGpuChannel::Send(IPC::Message* msg) {
|
void MediaGpuChannel::BindCommandBufferMediaReceiver(
|
||||||
return channel_->Send(msg);
|
gpu::CommandBufferStub* stub,
|
||||||
}
|
mojo::GenericPendingAssociatedReceiver receiver) {
|
||||||
|
if (auto r = receiver.As<mojom::GpuAcceleratedVideoDecoderProvider>()) {
|
||||||
bool MediaGpuChannel::OnMessageReceived(const IPC::Message& message) {
|
IPC::ScopedAllowOffSequenceChannelAssociatedBindings allow_binding;
|
||||||
MediaGpuChannelDispatchHelper helper(this, message.routing_id());
|
accelerated_video_decoder_providers_.Add(
|
||||||
bool handled = true;
|
std::make_unique<DecoderProviderImpl>(stub, overlay_factory_cb_),
|
||||||
IPC_BEGIN_MESSAGE_MAP(MediaGpuChannel, message)
|
std::move(r), stub->task_runner());
|
||||||
IPC_MESSAGE_FORWARD_DELAY_REPLY(
|
|
||||||
GpuCommandBufferMsg_CreateVideoDecoder, &helper,
|
|
||||||
MediaGpuChannelDispatchHelper::OnCreateVideoDecoder)
|
|
||||||
IPC_MESSAGE_UNHANDLED(handled = false)
|
|
||||||
IPC_END_MESSAGE_MAP()
|
|
||||||
return handled;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MediaGpuChannel::OnCreateVideoDecoder(
|
|
||||||
int32_t command_buffer_route_id,
|
|
||||||
const VideoDecodeAccelerator::Config& config,
|
|
||||||
int32_t decoder_route_id,
|
|
||||||
IPC::Message* reply_message) {
|
|
||||||
TRACE_EVENT0("gpu", "MediaGpuChannel::OnCreateVideoDecoder");
|
|
||||||
gpu::CommandBufferStub* stub =
|
|
||||||
channel_->LookupCommandBuffer(command_buffer_route_id);
|
|
||||||
// Only allow stubs that have a ContextGroup, that is, the GLES2 ones. Later
|
|
||||||
// code assumes the ContextGroup is valid.
|
|
||||||
if (!stub || !stub->decoder_context()->GetContextGroup()) {
|
|
||||||
reply_message->set_reply_error();
|
|
||||||
Send(reply_message);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
GpuVideoDecodeAccelerator* decoder = new GpuVideoDecodeAccelerator(
|
|
||||||
decoder_route_id, stub, stub->channel()->io_task_runner(),
|
|
||||||
overlay_factory_cb_);
|
|
||||||
bool succeeded = decoder->Initialize(config);
|
|
||||||
GpuCommandBufferMsg_CreateVideoDecoder::WriteReplyParams(reply_message,
|
|
||||||
succeeded);
|
|
||||||
Send(reply_message);
|
|
||||||
|
|
||||||
// decoder is registered as a DestructionObserver of this stub and will
|
|
||||||
// self-delete during destruction of this stub.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
@ -6,42 +6,34 @@
|
|||||||
#define MEDIA_GPU_IPC_SERVICE_MEDIA_GPU_CHANNEL_H_
|
#define MEDIA_GPU_IPC_SERVICE_MEDIA_GPU_CHANNEL_H_
|
||||||
|
|
||||||
#include "base/unguessable_token.h"
|
#include "base/unguessable_token.h"
|
||||||
#include "ipc/ipc_listener.h"
|
|
||||||
#include "ipc/ipc_sender.h"
|
|
||||||
#include "media/base/android_overlay_mojo_factory.h"
|
#include "media/base/android_overlay_mojo_factory.h"
|
||||||
|
#include "media/mojo/mojom/gpu_accelerated_video_decoder.mojom.h"
|
||||||
#include "media/video/video_decode_accelerator.h"
|
#include "media/video/video_decode_accelerator.h"
|
||||||
|
#include "mojo/public/cpp/bindings/generic_pending_associated_receiver.h"
|
||||||
|
#include "mojo/public/cpp/bindings/unique_associated_receiver_set.h"
|
||||||
|
|
||||||
namespace gpu {
|
namespace gpu {
|
||||||
|
class CommandBufferStub;
|
||||||
class GpuChannel;
|
class GpuChannel;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
class MediaGpuChannelDispatchHelper;
|
class MediaGpuChannel {
|
||||||
|
|
||||||
class MediaGpuChannel : public IPC::Listener, public IPC::Sender {
|
|
||||||
public:
|
public:
|
||||||
MediaGpuChannel(gpu::GpuChannel* channel,
|
MediaGpuChannel(gpu::GpuChannel* channel,
|
||||||
const AndroidOverlayMojoFactoryCB& overlay_factory_cb);
|
const AndroidOverlayMojoFactoryCB& overlay_factory_cb);
|
||||||
~MediaGpuChannel() override;
|
~MediaGpuChannel();
|
||||||
|
|
||||||
// IPC::Sender implementation:
|
|
||||||
bool Send(IPC::Message* msg) override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class MediaGpuChannelDispatchHelper;
|
void BindCommandBufferMediaReceiver(
|
||||||
|
gpu::CommandBufferStub* stub,
|
||||||
// IPC::Listener implementation:
|
mojo::GenericPendingAssociatedReceiver receiver);
|
||||||
bool OnMessageReceived(const IPC::Message& message) override;
|
|
||||||
|
|
||||||
// Message handlers.
|
|
||||||
void OnCreateVideoDecoder(int32_t command_buffer_route_id,
|
|
||||||
const VideoDecodeAccelerator::Config& config,
|
|
||||||
int32_t route_id,
|
|
||||||
IPC::Message* reply_message);
|
|
||||||
|
|
||||||
gpu::GpuChannel* const channel_;
|
gpu::GpuChannel* const channel_;
|
||||||
AndroidOverlayMojoFactoryCB overlay_factory_cb_;
|
AndroidOverlayMojoFactoryCB overlay_factory_cb_;
|
||||||
|
mojo::UniqueAssociatedReceiverSet<mojom::GpuAcceleratedVideoDecoderProvider>
|
||||||
|
accelerated_video_decoder_providers_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(MediaGpuChannel);
|
DISALLOW_COPY_AND_ASSIGN(MediaGpuChannel);
|
||||||
};
|
};
|
||||||
|
@ -29,7 +29,6 @@ void MediaGpuChannelManager::AddChannel(
|
|||||||
DCHECK(gpu_channel);
|
DCHECK(gpu_channel);
|
||||||
auto media_gpu_channel =
|
auto media_gpu_channel =
|
||||||
std::make_unique<MediaGpuChannel>(gpu_channel, overlay_factory_cb_);
|
std::make_unique<MediaGpuChannel>(gpu_channel, overlay_factory_cb_);
|
||||||
gpu_channel->SetUnhandledMessageListener(media_gpu_channel.get());
|
|
||||||
media_gpu_channels_[client_id] = std::move(media_gpu_channel);
|
media_gpu_channels_[client_id] = std::move(media_gpu_channel);
|
||||||
channel_to_token_[client_id] = channel_token;
|
channel_to_token_[client_id] = channel_token;
|
||||||
token_to_channel_[channel_token] = client_id;
|
token_to_channel_[channel_token] = client_id;
|
||||||
|
@ -27,6 +27,7 @@ mojom("mojom") {
|
|||||||
"demuxer_stream.mojom",
|
"demuxer_stream.mojom",
|
||||||
"display_media_information.mojom",
|
"display_media_information.mojom",
|
||||||
"frame_interface_factory.mojom",
|
"frame_interface_factory.mojom",
|
||||||
|
"gpu_accelerated_video_decoder.mojom",
|
||||||
"interface_factory.mojom",
|
"interface_factory.mojom",
|
||||||
"key_system_support.mojom",
|
"key_system_support.mojom",
|
||||||
"media_log.mojom",
|
"media_log.mojom",
|
||||||
@ -158,6 +159,21 @@ mojom("mojom") {
|
|||||||
"//media/base/ipc",
|
"//media/base/ipc",
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
types = [
|
||||||
|
{
|
||||||
|
mojom = "media.mojom.BitstreamBuffer"
|
||||||
|
cpp = "::media::BitstreamBuffer"
|
||||||
|
move_only = true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mojom = "media.mojom.VideoDecodeAcceleratorConfig"
|
||||||
|
cpp = "::media::VideoDecodeAccelerator::Config"
|
||||||
|
},
|
||||||
|
]
|
||||||
|
traits_headers = [ "//media/gpu/ipc/common/media_param_traits.h" ]
|
||||||
|
traits_public_deps = [ "//media/gpu/ipc/common" ]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
types = [
|
types = [
|
||||||
{
|
{
|
||||||
|
98
media/mojo/mojom/gpu_accelerated_video_decoder.mojom
Normal file
98
media/mojo/mojom/gpu_accelerated_video_decoder.mojom
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
// Copyright 2021 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.
|
||||||
|
|
||||||
|
module media.mojom;
|
||||||
|
|
||||||
|
import "media/mojo/mojom/media_types.mojom";
|
||||||
|
import "media/mojo/mojom/video_decoder.mojom";
|
||||||
|
import "ui/gfx/geometry/mojom/geometry.mojom";
|
||||||
|
import "ui/gfx/mojom/color_space.mojom";
|
||||||
|
|
||||||
|
[Native]
|
||||||
|
struct VideoDecodeAcceleratorConfig;
|
||||||
|
|
||||||
|
// Used by media clients to acquire new VideoDecoder instances from the GPU
|
||||||
|
// process.
|
||||||
|
interface GpuAcceleratedVideoDecoderProvider {
|
||||||
|
// Creates and initializes a new hardware video decoder instance.
|
||||||
|
[Sync]
|
||||||
|
CreateAcceleratedVideoDecoder(
|
||||||
|
VideoDecodeAcceleratorConfig config,
|
||||||
|
pending_associated_receiver<GpuAcceleratedVideoDecoder> receiver,
|
||||||
|
pending_associated_remote<GpuAcceleratedVideoDecoderClient> client)
|
||||||
|
=> (bool success);
|
||||||
|
};
|
||||||
|
|
||||||
|
[Native]
|
||||||
|
struct BitstreamBuffer;
|
||||||
|
|
||||||
|
// Links a set of texture IDs to a given PictureBuffer ID.
|
||||||
|
struct PictureBufferAssignment {
|
||||||
|
int32 buffer_id;
|
||||||
|
array<uint32> texture_ids;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Interface to control a single hardware video decoder instance. This is
|
||||||
|
// implemented in the GPU process and called by renderer clients.
|
||||||
|
interface GpuAcceleratedVideoDecoder {
|
||||||
|
// Sends an input buffer for decoding.
|
||||||
|
Decode(BitstreamBuffer buffer);
|
||||||
|
|
||||||
|
// Give texture IDs for the textures to use for output.
|
||||||
|
AssignPictureBuffers(array<PictureBufferAssignment> assignments);
|
||||||
|
|
||||||
|
// Indicates that the given picture buffer can be recycled for subsequent
|
||||||
|
// decode operations.
|
||||||
|
ReusePictureBuffer(int32 picture_buffer_id);
|
||||||
|
|
||||||
|
// Flushes the decoder.
|
||||||
|
Flush() => ();
|
||||||
|
|
||||||
|
// Resets the decoder.
|
||||||
|
Reset() => ();
|
||||||
|
|
||||||
|
// Sends overlay info to the decoder.
|
||||||
|
SetOverlayInfo(OverlayInfo overlay_info);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Client interface corresponding with a single AcceleratedVideoDecoder
|
||||||
|
// instance. This is implemented by renderer clients and called from by the GPU
|
||||||
|
// process.
|
||||||
|
interface GpuAcceleratedVideoDecoderClient {
|
||||||
|
// Notifies the client that deferred initialization has completed.
|
||||||
|
OnInitializationComplete(bool success);
|
||||||
|
|
||||||
|
// Notifies the client that an input buffer has been consumed.
|
||||||
|
OnBitstreamBufferProcessed(int32 buffer_id);
|
||||||
|
|
||||||
|
// Allocates video frames for decoder output.
|
||||||
|
OnProvidePictureBuffers(
|
||||||
|
uint32 num_frames, VideoPixelFormat format, uint32 num_textures_per_frame,
|
||||||
|
gfx.mojom.Size buffer_size, uint32 texture_target);
|
||||||
|
|
||||||
|
// Notifies the client that a picture is ready.
|
||||||
|
OnPictureReady(PictureReadyParams params);
|
||||||
|
|
||||||
|
// Notifies the client that a picture is ready and the buffer does not need to
|
||||||
|
// be passed back to the decoder.
|
||||||
|
OnDismissPictureBuffer(int32 buffer_id);
|
||||||
|
|
||||||
|
// Notifies the client of an error encountered by the decoder.
|
||||||
|
OnError(uint32 error_id);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Parameters passed to AcceleratedVideoDecoderClient.OnPictureReady from the
|
||||||
|
// GPU process to the client renderer.
|
||||||
|
struct PictureReadyParams {
|
||||||
|
int32 picture_buffer_id;
|
||||||
|
int32 bitstream_buffer_id;
|
||||||
|
gfx.mojom.Rect visible_rect;
|
||||||
|
gfx.mojom.ColorSpace color_space;
|
||||||
|
bool allow_overlay;
|
||||||
|
bool read_lock_fences_enabled;
|
||||||
|
bool size_changed;
|
||||||
|
bool surface_texture;
|
||||||
|
bool wants_promotion_hint;
|
||||||
|
};
|
||||||
|
|
@ -789,7 +789,7 @@ void InterfaceEndpointClient::InitControllerIfNecessary() {
|
|||||||
|
|
||||||
controller_ = handle_.group_controller()->AttachEndpointClient(handle_, this,
|
controller_ = handle_.group_controller()->AttachEndpointClient(handle_, this,
|
||||||
task_runner_);
|
task_runner_);
|
||||||
if (expect_sync_requests_)
|
if (expect_sync_requests_ && task_runner_->RunsTasksInCurrentSequence())
|
||||||
controller_->AllowWokenUpBySyncWatchOnSameThread();
|
controller_->AllowWokenUpBySyncWatchOnSameThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +45,13 @@ class SharedAssociatedRemote {
|
|||||||
Interface* operator->() const { return get(); }
|
Interface* operator->() const { return get(); }
|
||||||
Interface& operator*() const { return *get(); }
|
Interface& operator*() const { return *get(); }
|
||||||
|
|
||||||
|
void set_disconnect_handler(
|
||||||
|
base::OnceClosure handler,
|
||||||
|
scoped_refptr<base::SequencedTaskRunner> handler_task_runner) {
|
||||||
|
remote_->set_disconnect_handler(std::move(handler),
|
||||||
|
std::move(handler_task_runner));
|
||||||
|
}
|
||||||
|
|
||||||
// Clears this SharedAssociatedRemote. Note that this does *not* necessarily
|
// Clears this SharedAssociatedRemote. Note that this does *not* necessarily
|
||||||
// close the remote's endpoint as other SharedAssociatedRemote instances may
|
// close the remote's endpoint as other SharedAssociatedRemote instances may
|
||||||
// reference the same underlying endpoint.
|
// reference the same underlying endpoint.
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
include_rules = [
|
include_rules = [
|
||||||
"+components/content_settings",
|
"+components/content_settings",
|
||||||
"+components/viz/common",
|
"+components/viz/common",
|
||||||
|
"+gpu/ipc/common",
|
||||||
|
"+media/gpu/ipc/common",
|
||||||
"+printing/mojom",
|
"+printing/mojom",
|
||||||
"+third_party/skia/include",
|
"+third_party/skia/include",
|
||||||
"+third_party/blink/public",
|
"+third_party/blink/public",
|
||||||
|
@ -20,10 +20,12 @@
|
|||||||
#include "build/build_config.h"
|
#include "build/build_config.h"
|
||||||
#include "components/content_settings/core/common/content_settings_pattern.h"
|
#include "components/content_settings/core/common/content_settings_pattern.h"
|
||||||
#include "components/viz/common/surfaces/frame_sink_id.h"
|
#include "components/viz/common/surfaces/frame_sink_id.h"
|
||||||
|
#include "gpu/ipc/common/gpu_param_traits_macros.h"
|
||||||
#include "ipc/ipc_message.h"
|
#include "ipc/ipc_message.h"
|
||||||
#include "ipc/ipc_message_utils.h"
|
#include "ipc/ipc_message_utils.h"
|
||||||
#include "ipc/ipc_sync_channel.h"
|
#include "ipc/ipc_sync_channel.h"
|
||||||
#include "ipc/ipc_sync_message.h"
|
#include "ipc/ipc_sync_message.h"
|
||||||
|
#include "media/gpu/ipc/common/media_param_traits.h"
|
||||||
#include "printing/mojom/print.mojom-shared.h"
|
#include "printing/mojom/print.mojom-shared.h"
|
||||||
#include "third_party/blink/public/common/page_state/page_state.h"
|
#include "third_party/blink/public/common/page_state/page_state.h"
|
||||||
#include "third_party/skia/include/core/SkBitmap.h"
|
#include "third_party/skia/include/core/SkBitmap.h"
|
||||||
|
@ -24,5 +24,4 @@
|
|||||||
#include "components/guest_view/common/guest_view_message_generator.h"
|
#include "components/guest_view/common/guest_view_message_generator.h"
|
||||||
#include "content/common/all_messages.h"
|
#include "content/common/all_messages.h"
|
||||||
#include "extensions/common/extension_message_generator.h"
|
#include "extensions/common/extension_message_generator.h"
|
||||||
#include "media/gpu/ipc/common/media_message_generator.h"
|
|
||||||
#include "remoting/host/chromoting_messages.h"
|
#include "remoting/host/chromoting_messages.h"
|
||||||
|
Reference in New Issue
Block a user