OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "chrome/gpu/gpu_arc_video_service.h" |
| 6 |
| 7 #include <fcntl.h> |
| 8 |
| 9 #include <utility> |
| 10 |
| 11 #include "base/bind.h" |
| 12 #include "base/logging.h" |
| 13 #include "base/thread_task_runner_handle.h" |
| 14 #include "chrome/gpu/arc_gpu_video_decode_accelerator.h" |
| 15 #include "chrome/gpu/arc_video_accelerator.h" |
| 16 #include "components/arc/arc_bridge_bootstrap.h" |
| 17 #include "components/arc/common/video_accelerator.mojom.h" |
| 18 #include "mojo/edk/embedder/embedder.h" |
| 19 #include "mojo/public/cpp/bindings/binding.h" |
| 20 #include "mojo/public/cpp/bindings/type_converter.h" |
| 21 |
| 22 namespace mojo { |
| 23 |
| 24 template <> |
| 25 struct TypeConverter<arc::BufferMetadataPtr, chromeos::arc::BufferMetadata> { |
| 26 static arc::BufferMetadataPtr Convert( |
| 27 const chromeos::arc::BufferMetadata& input) { |
| 28 arc::BufferMetadataPtr result = arc::BufferMetadata::New(); |
| 29 result->timestamp = input.timestamp; |
| 30 result->flags = input.flags; |
| 31 result->bytes_used = input.bytes_used; |
| 32 return result; |
| 33 } |
| 34 }; |
| 35 |
| 36 template <> |
| 37 struct TypeConverter<chromeos::arc::BufferMetadata, arc::BufferMetadataPtr> { |
| 38 static chromeos::arc::BufferMetadata Convert( |
| 39 const arc::BufferMetadataPtr& input) { |
| 40 chromeos::arc::BufferMetadata result; |
| 41 result.timestamp = input->timestamp; |
| 42 result.flags = input->flags; |
| 43 result.bytes_used = input->bytes_used; |
| 44 return result; |
| 45 } |
| 46 }; |
| 47 |
| 48 template <> |
| 49 struct TypeConverter<arc::VideoFormatPtr, chromeos::arc::VideoFormat> { |
| 50 static arc::VideoFormatPtr Convert(const chromeos::arc::VideoFormat& input) { |
| 51 arc::VideoFormatPtr result = arc::VideoFormat::New(); |
| 52 result->pixel_format = input.pixel_format; |
| 53 result->buffer_size = input.buffer_size; |
| 54 result->min_num_buffers = input.min_num_buffers; |
| 55 result->coded_width = input.coded_width; |
| 56 result->coded_height = input.coded_height; |
| 57 result->crop_left = input.crop_left; |
| 58 result->crop_width = input.crop_width; |
| 59 result->crop_top = input.crop_top; |
| 60 result->crop_height = input.crop_height; |
| 61 return result; |
| 62 } |
| 63 }; |
| 64 |
| 65 template <> |
| 66 struct TypeConverter<chromeos::arc::ArcVideoAccelerator::Config, |
| 67 arc::ArcVideoAcceleratorConfigPtr> { |
| 68 static chromeos::arc::ArcVideoAccelerator::Config Convert( |
| 69 const arc::ArcVideoAcceleratorConfigPtr& input) { |
| 70 chromeos::arc::ArcVideoAccelerator::Config result; |
| 71 result.device_type = |
| 72 static_cast<chromeos::arc::ArcVideoAccelerator::Config::DeviceType>( |
| 73 input->device_type); |
| 74 result.num_input_buffers = input->num_input_buffers; |
| 75 result.input_pixel_format = input->input_pixel_format; |
| 76 return result; |
| 77 } |
| 78 }; |
| 79 |
| 80 } // namespace mojo |
| 81 |
| 82 namespace chromeos { |
| 83 namespace arc { |
| 84 |
| 85 class GpuArcVideoService::AcceleratorStub |
| 86 : public ::arc::VideoAcceleratorService, |
| 87 public ArcVideoAccelerator::Client { |
| 88 public: |
| 89 // |owner| outlives AcceleratorStub. |
| 90 explicit AcceleratorStub(GpuArcVideoService* owner) |
| 91 : owner_(owner), binding_(this) {} |
| 92 |
| 93 ~AcceleratorStub() override { DCHECK(thread_checker_.CalledOnValidThread()); } |
| 94 |
| 95 bool Connect(const gpu::GpuPreferences& gpu_preferences, |
| 96 const std::string& token) { |
| 97 DVLOG(2) << "Connect"; |
| 98 |
| 99 mojo::ScopedMessagePipeHandle server_pipe = |
| 100 mojo::edk::CreateParentMessagePipe(token); |
| 101 if (!server_pipe.is_valid()) { |
| 102 LOG(ERROR) << "Invalid pipe"; |
| 103 return false; |
| 104 } |
| 105 |
| 106 client_.Bind(mojo::InterfacePtrInfo<::arc::VideoAcceleratorServiceClient>( |
| 107 std::move(server_pipe), 0u)); |
| 108 |
| 109 // base::Unretained is safe because we own |client_| |
| 110 client_.set_connection_error_handler( |
| 111 base::Bind(&GpuArcVideoService::AcceleratorStub::OnConnectionError, |
| 112 base::Unretained(this))); |
| 113 |
| 114 accelerator_.reset(new ArcGpuVideoDecodeAccelerator(gpu_preferences)); |
| 115 |
| 116 ::arc::VideoAcceleratorServicePtr service; |
| 117 binding_.Bind(GetProxy(&service)); |
| 118 // base::Unretained is safe because we own |binding_| |
| 119 binding_.set_connection_error_handler( |
| 120 base::Bind(&GpuArcVideoService::AcceleratorStub::OnConnectionError, |
| 121 base::Unretained(this))); |
| 122 |
| 123 client_->Init(std::move(service)); |
| 124 return true; |
| 125 } |
| 126 |
| 127 void OnConnectionError() { |
| 128 DVLOG(2) << "OnConnectionError"; |
| 129 owner_->RemoveClient(this); |
| 130 // |this| is deleted. |
| 131 } |
| 132 |
| 133 // ArcVideoAccelerator::Client implementation: |
| 134 void OnError(ArcVideoAccelerator::Error error) override { |
| 135 DVLOG(2) << "OnError " << error; |
| 136 client_->OnError( |
| 137 static_cast<::arc::VideoAcceleratorServiceClient::Error>(error)); |
| 138 } |
| 139 |
| 140 void OnBufferDone(PortType port, |
| 141 uint32_t index, |
| 142 const BufferMetadata& metadata) override { |
| 143 DVLOG(2) << "OnBufferDone " << port << "," << index; |
| 144 client_->OnBufferDone(static_cast<::arc::PortType>(port), index, |
| 145 ::arc::BufferMetadata::From(metadata)); |
| 146 } |
| 147 |
| 148 void OnResetDone() override { |
| 149 DVLOG(2) << "OnResetDone"; |
| 150 client_->OnResetDone(); |
| 151 } |
| 152 |
| 153 void OnOutputFormatChanged(const VideoFormat& format) override { |
| 154 DVLOG(2) << "OnOutputFormatChanged"; |
| 155 client_->OnOutputFormatChanged(::arc::VideoFormat::From(format)); |
| 156 } |
| 157 |
| 158 // ::arc::VideoAcceleratorService impementation: |
| 159 void Initialize(::arc::ArcVideoAcceleratorConfigPtr config, |
| 160 const InitializeCallback& callback) override { |
| 161 DVLOG(2) << "Initialize"; |
| 162 bool result = accelerator_->Initialize( |
| 163 config.To<ArcVideoAccelerator::Config>(), this); |
| 164 callback.Run(result); |
| 165 } |
| 166 |
| 167 void BindSharedMemory(::arc::PortType port, |
| 168 uint32_t index, |
| 169 mojo::ScopedHandle ashmem_handle, |
| 170 uint64_t offset, |
| 171 uint64_t length) override { |
| 172 DVLOG(2) << "BindSharedMemoryCallback port=" << port << ", index=" << index |
| 173 << ", offset=" << offset << ", length=" << length; |
| 174 // TODO(kcwu) make sure do we need special care for invalid handle? |
| 175 mojo::edk::ScopedPlatformHandle scoped_platform_handle; |
| 176 MojoResult mojo_result = mojo::edk::PassWrappedPlatformHandle( |
| 177 ashmem_handle.release().value(), &scoped_platform_handle); |
| 178 DCHECK_EQ(mojo_result, MOJO_RESULT_OK); |
| 179 |
| 180 int fd = scoped_platform_handle.release().handle; |
| 181 accelerator_->BindSharedMemory(static_cast<PortType>(port), index, fd, |
| 182 static_cast<size_t>(offset), |
| 183 static_cast<size_t>(length)); |
| 184 } |
| 185 |
| 186 void BindDmabuf(::arc::PortType port, |
| 187 uint32_t index, |
| 188 mojo::ScopedHandle dmabuf_handle) override { |
| 189 DVLOG(2) << "BindDmabuf port=" << port << ", index=" << index; |
| 190 mojo::edk::ScopedPlatformHandle scoped_platform_handle; |
| 191 MojoResult mojo_result = mojo::edk::PassWrappedPlatformHandle( |
| 192 dmabuf_handle.release().value(), &scoped_platform_handle); |
| 193 DCHECK_EQ(mojo_result, MOJO_RESULT_OK); |
| 194 |
| 195 int fd = scoped_platform_handle.release().handle; |
| 196 accelerator_->BindDmabuf(static_cast<PortType>(port), index, fd); |
| 197 } |
| 198 |
| 199 void UseBuffer(::arc::PortType port, |
| 200 uint32_t index, |
| 201 ::arc::BufferMetadataPtr metadata) override { |
| 202 DVLOG(2) << "UseBuffer port=" << port << ", index=" << index; |
| 203 accelerator_->UseBuffer(static_cast<PortType>(port), index, |
| 204 metadata.To<BufferMetadata>()); |
| 205 } |
| 206 |
| 207 void SetNumberOfOutputBuffers(uint64_t number) override { |
| 208 DVLOG(2) << "SetNumberOfOutputBuffers number=" << number; |
| 209 accelerator_->SetNumberOfOutputBuffers(static_cast<size_t>(number)); |
| 210 } |
| 211 |
| 212 void Reset() override { accelerator_->Reset(); } |
| 213 |
| 214 private: |
| 215 base::ThreadChecker thread_checker_; |
| 216 GpuArcVideoService* const owner_; |
| 217 scoped_ptr<ArcVideoAccelerator> accelerator_; |
| 218 ::arc::VideoAcceleratorServiceClientPtr client_; |
| 219 mojo::Binding<::arc::VideoAcceleratorService> binding_; |
| 220 }; |
| 221 |
| 222 GpuArcVideoService::GpuArcVideoService( |
| 223 mojo::InterfaceRequest<::arc::VideoHost> request, |
| 224 const gpu::GpuPreferences& gpu_preferences) |
| 225 : binding_(this, std::move(request)), gpu_preferences_(gpu_preferences) {} |
| 226 |
| 227 GpuArcVideoService::~GpuArcVideoService() {} |
| 228 |
| 229 void GpuArcVideoService::OnRequestArcVideoAcceleratorChannel( |
| 230 uint32_t pid, |
| 231 const OnRequestArcVideoAcceleratorChannelCallback& callback) { |
| 232 DVLOG(1) << "OnRequestArcVideoAcceleratorChannelCallback"; |
| 233 |
| 234 mojo::edk::ScopedPlatformHandle child_handle = |
| 235 mojo::edk::ChildProcessLaunched(::arc::RemapChildPid(pid)); |
| 236 |
| 237 MojoHandle wrapped_handle; |
| 238 MojoResult wrap_result = mojo::edk::CreatePlatformHandleWrapper( |
| 239 std::move(child_handle), &wrapped_handle); |
| 240 if (wrap_result != MOJO_RESULT_OK) { |
| 241 LOG(WARNING) << "Pipe failed to wrap handles. Closing: " << wrap_result; |
| 242 callback.Run(mojo::ScopedHandle(), std::string()); |
| 243 return; |
| 244 } |
| 245 |
| 246 scoped_ptr<AcceleratorStub> stub(new AcceleratorStub(this)); |
| 247 |
| 248 std::string token = mojo::edk::GenerateRandomToken(); |
| 249 if (!stub->Connect(gpu_preferences_, token)) { |
| 250 callback.Run(mojo::ScopedHandle(), std::string()); |
| 251 return; |
| 252 } |
| 253 accelerator_stubs_.insert(std::make_pair(stub.get(), std::move(stub))); |
| 254 |
| 255 callback.Run(mojo::ScopedHandle(mojo::Handle(wrapped_handle)), token); |
| 256 } |
| 257 |
| 258 void GpuArcVideoService::RemoveClient(AcceleratorStub* stub) { |
| 259 accelerator_stubs_.erase(stub); |
| 260 } |
| 261 |
| 262 } // namespace arc |
| 263 } // namespace chromeos |
OLD | NEW |