OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/common/gpu/media/gpu_arc_video_service.h" | 5 #include "content/common/gpu/media/gpu_arc_video_service.h" |
6 | 6 |
| 7 #include <utility> |
| 8 |
7 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/memory/weak_ptr.h" |
| 11 #include "components/arc/common/video_accelerator.mojom.h" |
8 #include "content/common/gpu/gpu_messages.h" | 12 #include "content/common/gpu/gpu_messages.h" |
| 13 #include "content/common/gpu/media/arc/arc_video_accelerator.h" |
9 #include "ipc/ipc_listener.h" | 14 #include "ipc/ipc_listener.h" |
10 #include "ipc/ipc_message_macros.h" | 15 #include "ipc/ipc_message_macros.h" |
11 #include "ipc/ipc_sync_channel.h" | 16 #include "ipc/ipc_sync_channel.h" |
| 17 #include "mojo/public/cpp/bindings/binding.h" |
| 18 #include "mojo/public/cpp/bindings/type_converter.h" |
| 19 #include "third_party/mojo/src/mojo/edk/embedder/embedder.h" |
| 20 #include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h" |
| 21 |
| 22 // TODO debugging: remove before commit |
| 23 #undef DVLOG |
| 24 #define DVLOG VLOG |
| 25 |
| 26 namespace mojo { |
| 27 |
| 28 template <> |
| 29 struct TypeConverter<arc::BufferMetadataPtr, content::arc::BufferMetadata> { |
| 30 static arc::BufferMetadataPtr Convert( |
| 31 const content::arc::BufferMetadata& input) { |
| 32 arc::BufferMetadataPtr result = arc::BufferMetadata::New(); |
| 33 result->timestamp = input.timestamp; |
| 34 result->flags = input.flags; |
| 35 result->bytes_used = input.bytes_used; |
| 36 return result; |
| 37 } |
| 38 }; |
| 39 |
| 40 template <> |
| 41 struct TypeConverter<content::arc::BufferMetadata, arc::BufferMetadataPtr> { |
| 42 static content::arc::BufferMetadata Convert( |
| 43 const arc::BufferMetadataPtr& input) { |
| 44 content::arc::BufferMetadata result; |
| 45 result.timestamp = input->timestamp; |
| 46 result.flags = input->flags; |
| 47 result.bytes_used = input->bytes_used; |
| 48 return result; |
| 49 } |
| 50 }; |
| 51 |
| 52 template <> |
| 53 struct TypeConverter<content::arc::BufferFormat, arc::BufferFormatPtr> { |
| 54 static content::arc::BufferFormat Convert(const arc::BufferFormatPtr& input) { |
| 55 content::arc::BufferFormat result; |
| 56 result.pixel_format = input->pixel_format; |
| 57 result.memory_type = |
| 58 static_cast<content::arc::MemoryType>(input->memory_type); |
| 59 return result; |
| 60 } |
| 61 }; |
| 62 |
| 63 template <> |
| 64 struct TypeConverter<arc::VideoFormatPtr, content::arc::VideoFormat> { |
| 65 static arc::VideoFormatPtr Convert(const content::arc::VideoFormat& input) { |
| 66 arc::VideoFormatPtr result = arc::VideoFormat::New(); |
| 67 result->pixel_format = input.pixel_format; |
| 68 result->image_size = input.image_size; |
| 69 result->min_num_buffers = input.min_num_buffers; |
| 70 result->coded_width = input.coded_width; |
| 71 result->coded_height = input.coded_height; |
| 72 result->crop_left = input.crop_left; |
| 73 result->crop_width = input.crop_width; |
| 74 result->crop_top = input.crop_top; |
| 75 result->crop_height = input.crop_height; |
| 76 return result; |
| 77 } |
| 78 }; |
| 79 |
| 80 } // namespace mojo |
12 | 81 |
13 namespace content { | 82 namespace content { |
14 | 83 namespace arc { |
15 // TODO(kcwu) implement ArcVideoAccelerator::Client. | 84 |
16 class GpuArcVideoService::AcceleratorStub : public IPC::Listener, | 85 class GpuArcVideoService::AcceleratorStub |
17 public IPC::Sender { | 86 : public ::arc::VideoAcceleratorService, |
| 87 public base::SupportsWeakPtr<AcceleratorStub>, |
| 88 public ArcVideoAccelerator::Client { |
18 public: | 89 public: |
19 // |owner| outlives AcceleratorStub. | 90 // |owner| outlives AcceleratorStub. |
20 explicit AcceleratorStub(GpuArcVideoService* owner) : owner_(owner) {} | 91 AcceleratorStub( |
21 | 92 GpuArcVideoService* owner, |
22 ~AcceleratorStub() override { | 93 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) |
23 DCHECK(thread_checker_.CalledOnValidThread()); | 94 : owner_(owner), binding_(this), io_task_runner_(io_task_runner) {} |
24 channel_->Close(); | 95 |
25 } | 96 ~AcceleratorStub() override { DCHECK(thread_checker_.CalledOnValidThread()); } |
26 | 97 |
27 IPC::ChannelHandle CreateChannel( | 98 void OnConnectionError() { |
28 base::WaitableEvent* shutdown_event, | 99 DVLOG(2) << "OnConnectionError"; |
29 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) { | 100 owner_->RemoveClient(this); |
| 101 // |this| is deleted. |
| 102 } |
| 103 |
| 104 void OnChannelCreated(mojo::embedder::ChannelInfo* channel) { |
| 105 DVLOG(1) << "OnChannelCreated"; |
| 106 if (!channel) { |
| 107 LOG(ERROR) << "OnChannelCreated failed"; |
| 108 return; |
| 109 } |
| 110 |
| 111 // accelerator_.reset(new ArcGpuVideoDecodeAccelerator(io_task_runner_)); |
| 112 |
| 113 ::arc::VideoAcceleratorServicePtr service; |
| 114 binding_.Bind(GetProxy(&service)); |
| 115 // base::Unretained is safe because we owned |binding_| |
| 116 binding_.set_connection_error_handler( |
| 117 base::Bind(&GpuArcVideoService::AcceleratorStub::OnConnectionError, |
| 118 base::Unretained(this))); |
| 119 |
| 120 client_->SetService(std::move(service)); |
| 121 } |
| 122 |
| 123 IPC::ChannelHandle CreateChannel(base::WaitableEvent* shutdown_event) { |
30 IPC::ChannelHandle handle = | 124 IPC::ChannelHandle handle = |
31 IPC::Channel::GenerateVerifiedChannelID("arc-video"); | 125 IPC::Channel::GenerateVerifiedChannelID("arc-video"); |
32 channel_ = IPC::SyncChannel::Create(handle, IPC::Channel::MODE_SERVER, this, | 126 mojo::embedder::PlatformChannelPair channel_pair; |
33 io_task_runner, false, shutdown_event); | 127 |
34 base::ScopedFD client_fd = channel_->TakeClientFileDescriptor(); | 128 int fd = channel_pair.PassClientHandle().release().fd; |
35 DCHECK(client_fd.is_valid()); | 129 handle.socket = base::FileDescriptor(base::ScopedFD(fd)); |
36 handle.socket = base::FileDescriptor(std::move(client_fd)); | 130 |
| 131 mojo::embedder::ScopedPlatformHandle server_handle = |
| 132 channel_pair.PassServerHandle(); |
| 133 mojo::ScopedMessagePipeHandle server_pipe = mojo::embedder::CreateChannel( |
| 134 std::move(server_handle), |
| 135 base::Bind(&AcceleratorStub::OnChannelCreated, AsWeakPtr()), |
| 136 base::ThreadTaskRunnerHandle::Get()); |
| 137 client_.Bind(mojo::InterfacePtrInfo<::arc::VideoAcceleratorServiceClient>( |
| 138 std::move(server_pipe), 0u)); |
| 139 // base::Unretained is safe because we owned |client_| |
| 140 client_.set_connection_error_handler( |
| 141 base::Bind(&GpuArcVideoService::AcceleratorStub::OnConnectionError, |
| 142 base::Unretained(this))); |
| 143 |
37 return handle; | 144 return handle; |
38 } | 145 } |
39 | 146 |
40 // IPC::Sender implementation: | 147 // ArcVideoAccelerator::Client implementation: |
41 bool Send(IPC::Message* msg) override { | 148 void OnError(ArcVideoAccelerator::Error error) override { |
42 DCHECK(msg); | 149 DVLOG(2) << "OnError " << error; |
43 return channel_->Send(msg); | 150 client_->OnError( |
44 } | 151 static_cast<::arc::VideoAcceleratorServiceClient::Error>(error)); |
45 | 152 } |
46 // IPC::Listener implementation: | 153 |
47 void OnChannelError() override { | 154 void OnBufferDone(PortType port, |
48 DCHECK(thread_checker_.CalledOnValidThread()); | 155 uint32_t index, |
49 // RemoveClient will delete |this|. | 156 const BufferMetadata& metadata) override { |
50 owner_->RemoveClient(this); | 157 DVLOG(2) << "OnBufferDone " << port << "," << index; |
51 } | 158 client_->OnBufferDone(static_cast<::arc::PortType>(port), index, |
52 | 159 ::arc::BufferMetadata::From(metadata)); |
53 // IPC::Listener implementation: | 160 } |
54 bool OnMessageReceived(const IPC::Message& msg) override { | 161 |
55 DCHECK(thread_checker_.CalledOnValidThread()); | 162 void OnOutputFormatChanged(const VideoFormat& format) override { |
56 | 163 DVLOG(2) << "OnOutputFormatChanged"; |
57 // TODO(kcwu) Add handlers here. | 164 client_->OnOutputFormatChanged(::arc::VideoFormat::From(format)); |
58 return false; | 165 } |
| 166 |
| 167 // ::arc::VideoAcceleratorService impementation: |
| 168 void Initialize(::arc::DeviceType device, |
| 169 const InitializeCallback& callback) override { |
| 170 DVLOG(2) << "Initialize device=" << device; |
| 171 uint32_t result = |
| 172 accelerator_->Initialize(static_cast<DeviceType>(device), this); |
| 173 callback.Run(result); |
| 174 } |
| 175 |
| 176 void BindSharedMemory(::arc::PortType port, |
| 177 uint32_t index, |
| 178 mojo::ScopedHandle ashmem_handle, |
| 179 uint64_t offset, |
| 180 uint64_t length, |
| 181 const BindSharedMemoryCallback& callback) override { |
| 182 DVLOG(2) << "BindSharedMemoryCallback port=" << port << ", index=" << index |
| 183 << ", offset=" << offset << ", length=" << length; |
| 184 // TODO(kcwu) make sure do we need special care for invalid handle? |
| 185 mojo::embedder::ScopedPlatformHandle scoped_platform_handle; |
| 186 MojoResult mojo_result = mojo::embedder::PassWrappedPlatformHandle( |
| 187 ashmem_handle.release().value(), &scoped_platform_handle); |
| 188 DCHECK_EQ(mojo_result, MOJO_RESULT_OK); |
| 189 |
| 190 int fd = scoped_platform_handle.release().fd; |
| 191 bool result = accelerator_->BindSharedMemory( |
| 192 static_cast<PortType>(port), index, fd, static_cast<size_t>(offset), |
| 193 static_cast<size_t>(length)); |
| 194 callback.Run(result); |
| 195 } |
| 196 |
| 197 void BindDmabuf(::arc::PortType port, |
| 198 uint32_t index, |
| 199 mojo::ScopedHandle dmabuf_handle, |
| 200 const BindDmabufCallback& callback) override { |
| 201 DVLOG(2) << "BindDmabuf port=" << port << ", index=" << index; |
| 202 mojo::embedder::ScopedPlatformHandle scoped_platform_handle; |
| 203 MojoResult mojo_result = mojo::embedder::PassWrappedPlatformHandle( |
| 204 dmabuf_handle.release().value(), &scoped_platform_handle); |
| 205 DCHECK_EQ(mojo_result, MOJO_RESULT_OK); |
| 206 |
| 207 int fd = scoped_platform_handle.release().fd; |
| 208 bool result = |
| 209 accelerator_->BindDmabuf(static_cast<PortType>(port), index, fd); |
| 210 callback.Run(result); |
| 211 } |
| 212 |
| 213 void UseBuffer(::arc::PortType port, |
| 214 uint32_t index, |
| 215 ::arc::BufferMetadataPtr metadata) override { |
| 216 DVLOG(2) << "UseBuffer port=" << port << ", index=" << index; |
| 217 accelerator_->UseBuffer(static_cast<PortType>(port), index, |
| 218 metadata.To<BufferMetadata>()); |
| 219 } |
| 220 |
| 221 void SetBufferCount(::arc::PortType port, |
| 222 uint64_t set_count, |
| 223 const SetBufferCountCallback& callback) override { |
| 224 DVLOG(2) << "SetBufferCount port=" << port << ", set_count=" << set_count; |
| 225 size_t count = static_cast<size_t>(set_count); |
| 226 bool result = |
| 227 accelerator_->SetBufferCount(static_cast<PortType>(port), &count); |
| 228 callback.Run(result, count); |
| 229 } |
| 230 |
| 231 void Reset(const ResetCallback& callback) override { |
| 232 DVLOG(2) << "Reset"; |
| 233 accelerator_->Reset(); |
| 234 callback.Run(); |
| 235 } |
| 236 |
| 237 void SetBufferFormat(::arc::PortType port, |
| 238 ::arc::BufferFormatPtr format, |
| 239 const SetBufferFormatCallback& callback) override { |
| 240 DVLOG(2) << "SetBufferFormat port=" << port; |
| 241 bool result = accelerator_->SetBufferFormat(static_cast<PortType>(port), |
| 242 format.To<BufferFormat>()); |
| 243 callback.Run(result); |
59 } | 244 } |
60 | 245 |
61 private: | 246 private: |
62 base::ThreadChecker thread_checker_; | 247 base::ThreadChecker thread_checker_; |
63 GpuArcVideoService* const owner_; | 248 GpuArcVideoService* const owner_; |
64 scoped_ptr<IPC::SyncChannel> channel_; | 249 scoped_ptr<ArcVideoAccelerator> accelerator_; |
| 250 ::arc::VideoAcceleratorServiceClientPtr client_; |
| 251 mojo::Binding<::arc::VideoAcceleratorService> binding_; |
| 252 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; |
65 }; | 253 }; |
66 | 254 |
67 GpuArcVideoService::GpuArcVideoService( | 255 GpuArcVideoService::GpuArcVideoService( |
68 base::WaitableEvent* shutdown_event, | 256 base::WaitableEvent* shutdown_event, |
69 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) | 257 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) |
70 : shutdown_event_(shutdown_event), io_task_runner_(io_task_runner) {} | 258 : shutdown_event_(shutdown_event), io_task_runner_(io_task_runner) {} |
71 | 259 |
72 GpuArcVideoService::~GpuArcVideoService() {} | 260 GpuArcVideoService::~GpuArcVideoService() {} |
73 | 261 |
74 void GpuArcVideoService::CreateChannel(const CreateChannelCallback& callback) { | 262 void GpuArcVideoService::CreateChannel(const CreateChannelCallback& callback) { |
75 DCHECK(thread_checker_.CalledOnValidThread()); | 263 DCHECK(thread_checker_.CalledOnValidThread()); |
76 | 264 |
77 scoped_ptr<AcceleratorStub> stub(new AcceleratorStub(this)); | 265 scoped_ptr<AcceleratorStub> stub(new AcceleratorStub(this, io_task_runner_)); |
78 | 266 |
79 IPC::ChannelHandle handle = | 267 IPC::ChannelHandle handle = stub->CreateChannel(shutdown_event_); |
80 stub->CreateChannel(shutdown_event_, io_task_runner_); | |
81 accelerator_stubs_[stub.get()] = std::move(stub); | 268 accelerator_stubs_[stub.get()] = std::move(stub); |
82 | 269 |
83 callback.Run(handle); | 270 callback.Run(handle); |
84 } | 271 } |
85 | 272 |
86 void GpuArcVideoService::RemoveClient(AcceleratorStub* stub) { | 273 void GpuArcVideoService::RemoveClient(AcceleratorStub* stub) { |
87 DCHECK(thread_checker_.CalledOnValidThread()); | 274 DCHECK(thread_checker_.CalledOnValidThread()); |
88 | 275 |
89 accelerator_stubs_.erase(stub); | 276 accelerator_stubs_.erase(stub); |
90 } | 277 } |
91 | 278 |
| 279 } // namespace arc |
92 } // namespace content | 280 } // namespace content |
OLD | NEW |