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 |