| Index: content/common/gpu/media/gpu_arc_video_service.cc
|
| diff --git a/content/common/gpu/media/gpu_arc_video_service.cc b/content/common/gpu/media/gpu_arc_video_service.cc
|
| index 91d36980ad1e0a2fbdb9beb3a4272a0091d6c9dc..a52fd984c0add60f259a2954bdc1f8c7c1496330 100644
|
| --- a/content/common/gpu/media/gpu_arc_video_service.cc
|
| +++ b/content/common/gpu/media/gpu_arc_video_service.cc
|
| @@ -4,64 +4,252 @@
|
|
|
| #include "content/common/gpu/media/gpu_arc_video_service.h"
|
|
|
| +#include <utility>
|
| +
|
| #include "base/logging.h"
|
| +#include "base/memory/weak_ptr.h"
|
| +#include "components/arc/common/video_accelerator.mojom.h"
|
| #include "content/common/gpu/gpu_messages.h"
|
| +#include "content/common/gpu/media/arc/arc_video_accelerator.h"
|
| #include "ipc/ipc_listener.h"
|
| #include "ipc/ipc_message_macros.h"
|
| #include "ipc/ipc_sync_channel.h"
|
| +#include "mojo/public/cpp/bindings/binding.h"
|
| +#include "mojo/public/cpp/bindings/type_converter.h"
|
| +#include "third_party/mojo/src/mojo/edk/embedder/embedder.h"
|
| +#include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h"
|
| +
|
| +// TODO debugging: remove before commit
|
| +#undef DVLOG
|
| +#define DVLOG VLOG
|
| +
|
| +namespace mojo {
|
| +
|
| +template <>
|
| +struct TypeConverter<arc::BufferMetadataPtr, content::arc::BufferMetadata> {
|
| + static arc::BufferMetadataPtr Convert(
|
| + const content::arc::BufferMetadata& input) {
|
| + arc::BufferMetadataPtr result = arc::BufferMetadata::New();
|
| + result->timestamp = input.timestamp;
|
| + result->flags = input.flags;
|
| + result->bytes_used = input.bytes_used;
|
| + return result;
|
| + }
|
| +};
|
| +
|
| +template <>
|
| +struct TypeConverter<content::arc::BufferMetadata, arc::BufferMetadataPtr> {
|
| + static content::arc::BufferMetadata Convert(
|
| + const arc::BufferMetadataPtr& input) {
|
| + content::arc::BufferMetadata result;
|
| + result.timestamp = input->timestamp;
|
| + result.flags = input->flags;
|
| + result.bytes_used = input->bytes_used;
|
| + return result;
|
| + }
|
| +};
|
| +
|
| +template <>
|
| +struct TypeConverter<content::arc::BufferFormat, arc::BufferFormatPtr> {
|
| + static content::arc::BufferFormat Convert(const arc::BufferFormatPtr& input) {
|
| + content::arc::BufferFormat result;
|
| + result.pixel_format = input->pixel_format;
|
| + result.memory_type =
|
| + static_cast<content::arc::MemoryType>(input->memory_type);
|
| + return result;
|
| + }
|
| +};
|
| +
|
| +template <>
|
| +struct TypeConverter<arc::VideoFormatPtr, content::arc::VideoFormat> {
|
| + static arc::VideoFormatPtr Convert(const content::arc::VideoFormat& input) {
|
| + arc::VideoFormatPtr result = arc::VideoFormat::New();
|
| + result->pixel_format = input.pixel_format;
|
| + result->image_size = input.image_size;
|
| + result->min_num_buffers = input.min_num_buffers;
|
| + result->coded_width = input.coded_width;
|
| + result->coded_height = input.coded_height;
|
| + result->crop_left = input.crop_left;
|
| + result->crop_width = input.crop_width;
|
| + result->crop_top = input.crop_top;
|
| + result->crop_height = input.crop_height;
|
| + return result;
|
| + }
|
| +};
|
| +
|
| +} // namespace mojo
|
|
|
| namespace content {
|
| +namespace arc {
|
|
|
| -// TODO(kcwu) implement ArcVideoAccelerator::Client.
|
| -class GpuArcVideoService::AcceleratorStub : public IPC::Listener,
|
| - public IPC::Sender {
|
| +class GpuArcVideoService::AcceleratorStub
|
| + : public ::arc::VideoAcceleratorService,
|
| + public base::SupportsWeakPtr<AcceleratorStub>,
|
| + public ArcVideoAccelerator::Client {
|
| public:
|
| // |owner| outlives AcceleratorStub.
|
| - explicit AcceleratorStub(GpuArcVideoService* owner) : owner_(owner) {}
|
| + AcceleratorStub(
|
| + GpuArcVideoService* owner,
|
| + const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
|
| + : owner_(owner), binding_(this), io_task_runner_(io_task_runner) {}
|
| +
|
| + ~AcceleratorStub() override { DCHECK(thread_checker_.CalledOnValidThread()); }
|
| +
|
| + void OnConnectionError() {
|
| + DVLOG(2) << "OnConnectionError";
|
| + owner_->RemoveClient(this);
|
| + // |this| is deleted.
|
| + }
|
| +
|
| + void OnChannelCreated(mojo::embedder::ChannelInfo* channel) {
|
| + DVLOG(1) << "OnChannelCreated";
|
| + if (!channel) {
|
| + LOG(ERROR) << "OnChannelCreated failed";
|
| + return;
|
| + }
|
|
|
| - ~AcceleratorStub() override {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - channel_->Close();
|
| + // accelerator_.reset(new ArcGpuVideoDecodeAccelerator(io_task_runner_));
|
| +
|
| + ::arc::VideoAcceleratorServicePtr service;
|
| + binding_.Bind(GetProxy(&service));
|
| + // base::Unretained is safe because we owned |binding_|
|
| + binding_.set_connection_error_handler(
|
| + base::Bind(&GpuArcVideoService::AcceleratorStub::OnConnectionError,
|
| + base::Unretained(this)));
|
| +
|
| + client_->SetService(std::move(service));
|
| }
|
|
|
| - IPC::ChannelHandle CreateChannel(
|
| - base::WaitableEvent* shutdown_event,
|
| - const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) {
|
| + IPC::ChannelHandle CreateChannel(base::WaitableEvent* shutdown_event) {
|
| IPC::ChannelHandle handle =
|
| IPC::Channel::GenerateVerifiedChannelID("arc-video");
|
| - channel_ = IPC::SyncChannel::Create(handle, IPC::Channel::MODE_SERVER, this,
|
| - io_task_runner, false, shutdown_event);
|
| - base::ScopedFD client_fd = channel_->TakeClientFileDescriptor();
|
| - DCHECK(client_fd.is_valid());
|
| - handle.socket = base::FileDescriptor(std::move(client_fd));
|
| + mojo::embedder::PlatformChannelPair channel_pair;
|
| +
|
| + int fd = channel_pair.PassClientHandle().release().fd;
|
| + handle.socket = base::FileDescriptor(base::ScopedFD(fd));
|
| +
|
| + mojo::embedder::ScopedPlatformHandle server_handle =
|
| + channel_pair.PassServerHandle();
|
| + mojo::ScopedMessagePipeHandle server_pipe = mojo::embedder::CreateChannel(
|
| + std::move(server_handle),
|
| + base::Bind(&AcceleratorStub::OnChannelCreated, AsWeakPtr()),
|
| + base::ThreadTaskRunnerHandle::Get());
|
| + client_.Bind(mojo::InterfacePtrInfo<::arc::VideoAcceleratorServiceClient>(
|
| + std::move(server_pipe), 0u));
|
| + // base::Unretained is safe because we owned |client_|
|
| + client_.set_connection_error_handler(
|
| + base::Bind(&GpuArcVideoService::AcceleratorStub::OnConnectionError,
|
| + base::Unretained(this)));
|
| +
|
| return handle;
|
| }
|
|
|
| - // IPC::Sender implementation:
|
| - bool Send(IPC::Message* msg) override {
|
| - DCHECK(msg);
|
| - return channel_->Send(msg);
|
| + // ArcVideoAccelerator::Client implementation:
|
| + void OnError(ArcVideoAccelerator::Error error) override {
|
| + DVLOG(2) << "OnError " << error;
|
| + client_->OnError(
|
| + static_cast<::arc::VideoAcceleratorServiceClient::Error>(error));
|
| }
|
|
|
| - // IPC::Listener implementation:
|
| - void OnChannelError() override {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - // RemoveClient will delete |this|.
|
| - owner_->RemoveClient(this);
|
| + void OnBufferDone(PortType port,
|
| + uint32_t index,
|
| + const BufferMetadata& metadata) override {
|
| + DVLOG(2) << "OnBufferDone " << port << "," << index;
|
| + client_->OnBufferDone(static_cast<::arc::PortType>(port), index,
|
| + ::arc::BufferMetadata::From(metadata));
|
| }
|
|
|
| - // IPC::Listener implementation:
|
| - bool OnMessageReceived(const IPC::Message& msg) override {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| + void OnOutputFormatChanged(const VideoFormat& format) override {
|
| + DVLOG(2) << "OnOutputFormatChanged";
|
| + client_->OnOutputFormatChanged(::arc::VideoFormat::From(format));
|
| + }
|
| +
|
| + // ::arc::VideoAcceleratorService impementation:
|
| + void Initialize(::arc::DeviceType device,
|
| + const InitializeCallback& callback) override {
|
| + DVLOG(2) << "Initialize device=" << device;
|
| + uint32_t result =
|
| + accelerator_->Initialize(static_cast<DeviceType>(device), this);
|
| + callback.Run(result);
|
| + }
|
| +
|
| + void BindSharedMemory(::arc::PortType port,
|
| + uint32_t index,
|
| + mojo::ScopedHandle ashmem_handle,
|
| + uint64_t offset,
|
| + uint64_t length,
|
| + const BindSharedMemoryCallback& callback) override {
|
| + DVLOG(2) << "BindSharedMemoryCallback port=" << port << ", index=" << index
|
| + << ", offset=" << offset << ", length=" << length;
|
| + // TODO(kcwu) make sure do we need special care for invalid handle?
|
| + mojo::embedder::ScopedPlatformHandle scoped_platform_handle;
|
| + MojoResult mojo_result = mojo::embedder::PassWrappedPlatformHandle(
|
| + ashmem_handle.release().value(), &scoped_platform_handle);
|
| + DCHECK_EQ(mojo_result, MOJO_RESULT_OK);
|
| +
|
| + int fd = scoped_platform_handle.release().fd;
|
| + bool result = accelerator_->BindSharedMemory(
|
| + static_cast<PortType>(port), index, fd, static_cast<size_t>(offset),
|
| + static_cast<size_t>(length));
|
| + callback.Run(result);
|
| + }
|
| +
|
| + void BindDmabuf(::arc::PortType port,
|
| + uint32_t index,
|
| + mojo::ScopedHandle dmabuf_handle,
|
| + const BindDmabufCallback& callback) override {
|
| + DVLOG(2) << "BindDmabuf port=" << port << ", index=" << index;
|
| + mojo::embedder::ScopedPlatformHandle scoped_platform_handle;
|
| + MojoResult mojo_result = mojo::embedder::PassWrappedPlatformHandle(
|
| + dmabuf_handle.release().value(), &scoped_platform_handle);
|
| + DCHECK_EQ(mojo_result, MOJO_RESULT_OK);
|
| +
|
| + int fd = scoped_platform_handle.release().fd;
|
| + bool result =
|
| + accelerator_->BindDmabuf(static_cast<PortType>(port), index, fd);
|
| + callback.Run(result);
|
| + }
|
| +
|
| + void UseBuffer(::arc::PortType port,
|
| + uint32_t index,
|
| + ::arc::BufferMetadataPtr metadata) override {
|
| + DVLOG(2) << "UseBuffer port=" << port << ", index=" << index;
|
| + accelerator_->UseBuffer(static_cast<PortType>(port), index,
|
| + metadata.To<BufferMetadata>());
|
| + }
|
| +
|
| + void SetBufferCount(::arc::PortType port,
|
| + uint64_t set_count,
|
| + const SetBufferCountCallback& callback) override {
|
| + DVLOG(2) << "SetBufferCount port=" << port << ", set_count=" << set_count;
|
| + size_t count = static_cast<size_t>(set_count);
|
| + bool result =
|
| + accelerator_->SetBufferCount(static_cast<PortType>(port), &count);
|
| + callback.Run(result, count);
|
| + }
|
| +
|
| + void Reset(const ResetCallback& callback) override {
|
| + DVLOG(2) << "Reset";
|
| + accelerator_->Reset();
|
| + callback.Run();
|
| + }
|
|
|
| - // TODO(kcwu) Add handlers here.
|
| - return false;
|
| + void SetBufferFormat(::arc::PortType port,
|
| + ::arc::BufferFormatPtr format,
|
| + const SetBufferFormatCallback& callback) override {
|
| + DVLOG(2) << "SetBufferFormat port=" << port;
|
| + bool result = accelerator_->SetBufferFormat(static_cast<PortType>(port),
|
| + format.To<BufferFormat>());
|
| + callback.Run(result);
|
| }
|
|
|
| private:
|
| base::ThreadChecker thread_checker_;
|
| GpuArcVideoService* const owner_;
|
| - scoped_ptr<IPC::SyncChannel> channel_;
|
| + scoped_ptr<ArcVideoAccelerator> accelerator_;
|
| + ::arc::VideoAcceleratorServiceClientPtr client_;
|
| + mojo::Binding<::arc::VideoAcceleratorService> binding_;
|
| + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
|
| };
|
|
|
| GpuArcVideoService::GpuArcVideoService(
|
| @@ -74,10 +262,9 @@ GpuArcVideoService::~GpuArcVideoService() {}
|
| void GpuArcVideoService::CreateChannel(const CreateChannelCallback& callback) {
|
| DCHECK(thread_checker_.CalledOnValidThread());
|
|
|
| - scoped_ptr<AcceleratorStub> stub(new AcceleratorStub(this));
|
| + scoped_ptr<AcceleratorStub> stub(new AcceleratorStub(this, io_task_runner_));
|
|
|
| - IPC::ChannelHandle handle =
|
| - stub->CreateChannel(shutdown_event_, io_task_runner_);
|
| + IPC::ChannelHandle handle = stub->CreateChannel(shutdown_event_);
|
| accelerator_stubs_[stub.get()] = std::move(stub);
|
|
|
| callback.Run(handle);
|
| @@ -89,4 +276,5 @@ void GpuArcVideoService::RemoveClient(AcceleratorStub* stub) {
|
| accelerator_stubs_.erase(stub);
|
| }
|
|
|
| +} // namespace arc
|
| } // namespace content
|
|
|