Chromium Code Reviews| 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/common/video_accelerator.mojom.h" | |
| 17 #include "mojo/edk/embedder/embedder.h" | |
| 18 #include "mojo/public/cpp/bindings/binding.h" | |
| 19 #include "mojo/public/cpp/bindings/type_converter.h" | |
| 20 | |
| 21 namespace { | |
| 22 | |
| 23 // Child process may be created in the different namespace, thus we don't have | |
| 24 // its real PID. Since Mojo in POSIX only uses the value as identifier for the | |
| 25 // routing table, we can give it fake value as long as it is unique. | |
| 26 // Chrome OS uses default pid_max of 32k, so we can safely shift the pid range | |
| 27 // by kPidBase and don't conflict with legitimate process. | |
| 28 // | |
| 29 // This assumes all video accelerator clients are from the same namespace and | |
| 30 // the max pid of the said namespace is kPidMask. | |
| 31 base::ProcessHandle RemapChildPid(uint32_t pid) { | |
|
Luis Héctor Chávez
2016/03/24 17:24:20
Can you move this somewhere in components/arc and
kcwu
2016/03/28 13:17:35
Done.
| |
| 32 uint32_t kPidBase = 0x3F000000; // arbitrarily chosen. | |
| 33 uint32_t kPidMask = 0x7fff; // the default, 32k. | |
| 34 return kPidBase + (pid & kPidMask); | |
| 35 } | |
| 36 | |
| 37 } // namespace | |
| 38 | |
| 39 namespace mojo { | |
| 40 | |
| 41 template <> | |
| 42 struct TypeConverter<arc::BufferMetadataPtr, chromeos::arc::BufferMetadata> { | |
| 43 static arc::BufferMetadataPtr Convert( | |
| 44 const chromeos::arc::BufferMetadata& input) { | |
| 45 arc::BufferMetadataPtr result = arc::BufferMetadata::New(); | |
| 46 result->timestamp = input.timestamp; | |
| 47 result->flags = input.flags; | |
| 48 result->bytes_used = input.bytes_used; | |
| 49 return result; | |
| 50 } | |
| 51 }; | |
| 52 | |
| 53 template <> | |
| 54 struct TypeConverter<chromeos::arc::BufferMetadata, arc::BufferMetadataPtr> { | |
| 55 static chromeos::arc::BufferMetadata Convert( | |
| 56 const arc::BufferMetadataPtr& input) { | |
| 57 chromeos::arc::BufferMetadata result; | |
| 58 result.timestamp = input->timestamp; | |
| 59 result.flags = input->flags; | |
| 60 result.bytes_used = input->bytes_used; | |
| 61 return result; | |
| 62 } | |
| 63 }; | |
| 64 | |
| 65 template <> | |
| 66 struct TypeConverter<arc::VideoFormatPtr, chromeos::arc::VideoFormat> { | |
| 67 static arc::VideoFormatPtr Convert(const chromeos::arc::VideoFormat& input) { | |
| 68 arc::VideoFormatPtr result = arc::VideoFormat::New(); | |
| 69 result->pixel_format = input.pixel_format; | |
| 70 result->buffer_size = input.buffer_size; | |
| 71 result->min_num_buffers = input.min_num_buffers; | |
| 72 result->coded_width = input.coded_width; | |
| 73 result->coded_height = input.coded_height; | |
| 74 result->crop_left = input.crop_left; | |
| 75 result->crop_width = input.crop_width; | |
| 76 result->crop_top = input.crop_top; | |
| 77 result->crop_height = input.crop_height; | |
| 78 return result; | |
| 79 } | |
| 80 }; | |
| 81 | |
| 82 template <> | |
| 83 struct TypeConverter<chromeos::arc::ArcVideoAccelerator::Config, | |
| 84 arc::ArcVideoAcceleratorConfigPtr> { | |
| 85 static chromeos::arc::ArcVideoAccelerator::Config Convert( | |
| 86 const arc::ArcVideoAcceleratorConfigPtr& input) { | |
| 87 chromeos::arc::ArcVideoAccelerator::Config result; | |
| 88 result.device_type = | |
| 89 static_cast<chromeos::arc::ArcVideoAccelerator::Config::DeviceType>( | |
| 90 input->device_type); | |
| 91 result.num_input_buffers = input->num_input_buffers; | |
| 92 result.input_pixel_format = input->input_pixel_format; | |
| 93 return result; | |
| 94 } | |
| 95 }; | |
| 96 | |
| 97 } // namespace mojo | |
| 98 | |
| 99 namespace chromeos { | |
| 100 namespace arc { | |
| 101 | |
| 102 class GpuArcVideoService::AcceleratorStub | |
| 103 : public ::arc::VideoAcceleratorService, | |
| 104 public ArcVideoAccelerator::Client { | |
| 105 public: | |
| 106 // |owner| outlives AcceleratorStub. | |
| 107 explicit AcceleratorStub(GpuArcVideoService* owner) | |
| 108 : owner_(owner), binding_(this) {} | |
| 109 | |
| 110 ~AcceleratorStub() override { DCHECK(thread_checker_.CalledOnValidThread()); } | |
| 111 | |
| 112 bool Connect(const gpu::GpuPreferences& gpu_preferences, | |
| 113 const std::string& token) { | |
| 114 DVLOG(2) << "Connect"; | |
| 115 | |
| 116 mojo::ScopedMessagePipeHandle server_pipe = | |
| 117 mojo::edk::CreateParentMessagePipe(token); | |
| 118 if (!server_pipe.is_valid()) { | |
| 119 LOG(ERROR) << "Invalid pipe"; | |
| 120 return false; | |
| 121 } | |
| 122 | |
| 123 client_.Bind(mojo::InterfacePtrInfo<::arc::VideoAcceleratorServiceClient>( | |
| 124 std::move(server_pipe), 0u)); | |
| 125 | |
| 126 // base::Unretained is safe because we own |client_| | |
| 127 client_.set_connection_error_handler( | |
| 128 base::Bind(&GpuArcVideoService::AcceleratorStub::OnConnectionError, | |
| 129 base::Unretained(this))); | |
| 130 | |
| 131 accelerator_.reset(new ArcGpuVideoDecodeAccelerator(gpu_preferences)); | |
| 132 | |
| 133 ::arc::VideoAcceleratorServicePtr service; | |
| 134 binding_.Bind(GetProxy(&service)); | |
| 135 // base::Unretained is safe because we own |binding_| | |
| 136 binding_.set_connection_error_handler( | |
| 137 base::Bind(&GpuArcVideoService::AcceleratorStub::OnConnectionError, | |
| 138 base::Unretained(this))); | |
| 139 | |
| 140 client_->Init(std::move(service)); | |
| 141 return true; | |
| 142 } | |
| 143 | |
| 144 void OnConnectionError() { | |
| 145 DVLOG(2) << "OnConnectionError"; | |
| 146 owner_->RemoveClient(this); | |
| 147 // |this| is deleted. | |
| 148 } | |
| 149 | |
| 150 // ArcVideoAccelerator::Client implementation: | |
| 151 void OnError(ArcVideoAccelerator::Error error) override { | |
| 152 DVLOG(2) << "OnError " << error; | |
| 153 client_->OnError( | |
| 154 static_cast<::arc::VideoAcceleratorServiceClient::Error>(error)); | |
| 155 } | |
| 156 | |
| 157 void OnBufferDone(PortType port, | |
| 158 uint32_t index, | |
| 159 const BufferMetadata& metadata) override { | |
| 160 DVLOG(2) << "OnBufferDone " << port << "," << index; | |
| 161 client_->OnBufferDone(static_cast<::arc::PortType>(port), index, | |
| 162 ::arc::BufferMetadata::From(metadata)); | |
| 163 } | |
| 164 | |
| 165 void OnResetDone() override { | |
| 166 DVLOG(2) << "OnResetDone"; | |
| 167 client_->OnResetDone(); | |
| 168 } | |
| 169 | |
| 170 void OnOutputFormatChanged(const VideoFormat& format) override { | |
| 171 DVLOG(2) << "OnOutputFormatChanged"; | |
| 172 client_->OnOutputFormatChanged(::arc::VideoFormat::From(format)); | |
| 173 } | |
| 174 | |
| 175 // ::arc::VideoAcceleratorService impementation: | |
| 176 void Initialize(::arc::ArcVideoAcceleratorConfigPtr config, | |
| 177 const InitializeCallback& callback) override { | |
| 178 DVLOG(2) << "Initialize"; | |
| 179 bool result = accelerator_->Initialize( | |
| 180 config.To<ArcVideoAccelerator::Config>(), this); | |
| 181 callback.Run(result); | |
| 182 } | |
| 183 | |
| 184 void BindSharedMemory(::arc::PortType port, | |
| 185 uint32_t index, | |
| 186 mojo::ScopedHandle ashmem_handle, | |
| 187 uint64_t offset, | |
| 188 uint64_t length) override { | |
| 189 DVLOG(2) << "BindSharedMemoryCallback port=" << port << ", index=" << index | |
| 190 << ", offset=" << offset << ", length=" << length; | |
| 191 // TODO(kcwu) make sure do we need special care for invalid handle? | |
| 192 mojo::edk::ScopedPlatformHandle scoped_platform_handle; | |
| 193 MojoResult mojo_result = mojo::edk::PassWrappedPlatformHandle( | |
| 194 ashmem_handle.release().value(), &scoped_platform_handle); | |
|
dcheng
2016/03/24 20:29:14
Mojo folks: can we make this API a little more str
| |
| 195 DCHECK_EQ(mojo_result, MOJO_RESULT_OK); | |
| 196 | |
| 197 int fd = scoped_platform_handle.release().handle; | |
| 198 accelerator_->BindSharedMemory(static_cast<PortType>(port), index, fd, | |
| 199 static_cast<size_t>(offset), | |
|
dcheng
2016/03/24 20:29:14
These static casts make me nervous, is there some
Luis Héctor Chávez
2016/03/24 23:16:53
No, and in fact for x86_64 devices it is guarantee
dcheng
2016/03/30 16:52:36
If that's the case, why not just make the argument
| |
| 200 static_cast<size_t>(length)); | |
| 201 } | |
| 202 | |
| 203 void BindDmabuf(::arc::PortType port, | |
| 204 uint32_t index, | |
| 205 mojo::ScopedHandle dmabuf_handle) override { | |
| 206 DVLOG(2) << "BindDmabuf port=" << port << ", index=" << index; | |
| 207 mojo::edk::ScopedPlatformHandle scoped_platform_handle; | |
| 208 MojoResult mojo_result = mojo::edk::PassWrappedPlatformHandle( | |
| 209 dmabuf_handle.release().value(), &scoped_platform_handle); | |
| 210 DCHECK_EQ(mojo_result, MOJO_RESULT_OK); | |
| 211 | |
| 212 int fd = scoped_platform_handle.release().handle; | |
| 213 accelerator_->BindDmabuf(static_cast<PortType>(port), index, fd); | |
| 214 } | |
| 215 | |
| 216 void UseBuffer(::arc::PortType port, | |
| 217 uint32_t index, | |
| 218 ::arc::BufferMetadataPtr metadata) override { | |
| 219 DVLOG(2) << "UseBuffer port=" << port << ", index=" << index; | |
| 220 accelerator_->UseBuffer(static_cast<PortType>(port), index, | |
| 221 metadata.To<BufferMetadata>()); | |
| 222 } | |
| 223 | |
| 224 void SetNumberOfOutputBuffers(uint64_t number) override { | |
| 225 DVLOG(2) << "SetNumberOfOutputBuffers number=" << number; | |
| 226 accelerator_->SetNumberOfOutputBuffers(static_cast<size_t>(number)); | |
| 227 } | |
| 228 | |
| 229 void Reset() override { accelerator_->Reset(); } | |
| 230 | |
| 231 private: | |
| 232 base::ThreadChecker thread_checker_; | |
| 233 GpuArcVideoService* const owner_; | |
| 234 scoped_ptr<ArcVideoAccelerator> accelerator_; | |
| 235 ::arc::VideoAcceleratorServiceClientPtr client_; | |
| 236 mojo::Binding<::arc::VideoAcceleratorService> binding_; | |
| 237 }; | |
| 238 | |
| 239 GpuArcVideoService::GpuArcVideoService( | |
| 240 mojo::InterfaceRequest<::arc::VideoHost> request, | |
| 241 const gpu::GpuPreferences& gpu_preferences) | |
| 242 : binding_(this, std::move(request)), gpu_preferences_(gpu_preferences) {} | |
| 243 | |
| 244 GpuArcVideoService::~GpuArcVideoService() {} | |
| 245 | |
| 246 void GpuArcVideoService::OnRequestArcVideoAcceleratorChannel( | |
| 247 uint32_t pid, | |
| 248 const OnRequestArcVideoAcceleratorChannelCallback& callback) { | |
| 249 DVLOG(1) << "OnRequestArcVideoAcceleratorChannelCallback"; | |
| 250 | |
| 251 mojo::edk::ScopedPlatformHandle child_handle = | |
| 252 mojo::edk::ChildProcessLaunched(RemapChildPid(pid)); | |
| 253 | |
| 254 MojoHandle wrapped_handle; | |
| 255 MojoResult wrap_result = mojo::edk::CreatePlatformHandleWrapper( | |
| 256 std::move(child_handle), &wrapped_handle); | |
| 257 if (wrap_result != MOJO_RESULT_OK) { | |
| 258 LOG(WARNING) << "Pipe failed to wrap handles. Closing: " << wrap_result; | |
| 259 callback.Run(mojo::ScopedHandle(), std::string()); | |
| 260 return; | |
| 261 } | |
| 262 | |
| 263 scoped_ptr<AcceleratorStub> stub(new AcceleratorStub(this)); | |
| 264 | |
| 265 std::string token = mojo::edk::GenerateRandomToken(); | |
| 266 if (!stub->Connect(gpu_preferences_, token)) { | |
| 267 callback.Run(mojo::ScopedHandle(), std::string()); | |
| 268 return; | |
| 269 } | |
| 270 accelerator_stubs_[stub.get()] = std::move(stub); | |
|
Luis Héctor Chávez
2016/03/24 17:24:20
nit: accelerator_stubs_.insert(std::make_pair(stub
kcwu
2016/03/28 13:17:34
Done.
| |
| 271 | |
| 272 callback.Run(mojo::ScopedHandle(mojo::Handle(wrapped_handle)), token); | |
| 273 } | |
| 274 | |
| 275 void GpuArcVideoService::RemoveClient(AcceleratorStub* stub) { | |
| 276 accelerator_stubs_.erase(stub); | |
| 277 } | |
| 278 | |
| 279 } // namespace arc | |
| 280 } // namespace chromeos | |
| OLD | NEW |