OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "media/gpu/ipc/service/gpu_jpeg_decode_accelerator.h" | 5 #include "media/gpu/ipc/service/gpu_jpeg_decode_accelerator.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <memory> | 9 #include <memory> |
10 #include <utility> | 10 #include <utility> |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 return false; | 65 return false; |
66 } | 66 } |
67 | 67 |
68 return true; | 68 return true; |
69 } | 69 } |
70 | 70 |
71 } // namespace | 71 } // namespace |
72 | 72 |
73 namespace media { | 73 namespace media { |
74 | 74 |
75 class GpuJpegDecodeAccelerator::Client | 75 class GpuJpegDecodeAccelerator::Client : public JpegDecodeAccelerator::Client, |
76 : public media::JpegDecodeAccelerator::Client, | 76 public base::NonThreadSafe { |
77 public base::NonThreadSafe { | |
78 public: | 77 public: |
79 Client(media::GpuJpegDecodeAccelerator* owner, int32_t route_id) | 78 Client(GpuJpegDecodeAccelerator* owner, int32_t route_id) |
80 : owner_(owner->AsWeakPtr()), route_id_(route_id) {} | 79 : owner_(owner->AsWeakPtr()), route_id_(route_id) {} |
81 | 80 |
82 ~Client() override { DCHECK(CalledOnValidThread()); } | 81 ~Client() override { DCHECK(CalledOnValidThread()); } |
83 | 82 |
84 // media::JpegDecodeAccelerator::Client implementation. | 83 // JpegDecodeAccelerator::Client implementation. |
85 void VideoFrameReady(int32_t bitstream_buffer_id) override { | 84 void VideoFrameReady(int32_t bitstream_buffer_id) override { |
86 DCHECK(CalledOnValidThread()); | 85 DCHECK(CalledOnValidThread()); |
87 if (owner_) | 86 if (owner_) |
88 owner_->NotifyDecodeStatus(route_id_, bitstream_buffer_id, | 87 owner_->NotifyDecodeStatus(route_id_, bitstream_buffer_id, |
89 media::JpegDecodeAccelerator::NO_ERRORS); | 88 JpegDecodeAccelerator::NO_ERRORS); |
90 } | 89 } |
91 | 90 |
92 void NotifyError(int32_t bitstream_buffer_id, | 91 void NotifyError(int32_t bitstream_buffer_id, |
93 media::JpegDecodeAccelerator::Error error) override { | 92 JpegDecodeAccelerator::Error error) override { |
94 DCHECK(CalledOnValidThread()); | 93 DCHECK(CalledOnValidThread()); |
95 if (owner_) | 94 if (owner_) |
96 owner_->NotifyDecodeStatus(route_id_, bitstream_buffer_id, error); | 95 owner_->NotifyDecodeStatus(route_id_, bitstream_buffer_id, error); |
97 } | 96 } |
98 | 97 |
99 void Decode(const media::BitstreamBuffer& bitstream_buffer, | 98 void Decode(const BitstreamBuffer& bitstream_buffer, |
100 const scoped_refptr<media::VideoFrame>& video_frame) { | 99 const scoped_refptr<VideoFrame>& video_frame) { |
101 DCHECK(CalledOnValidThread()); | 100 DCHECK(CalledOnValidThread()); |
102 DCHECK(accelerator_); | 101 DCHECK(accelerator_); |
103 accelerator_->Decode(bitstream_buffer, video_frame); | 102 accelerator_->Decode(bitstream_buffer, video_frame); |
104 } | 103 } |
105 | 104 |
106 void set_accelerator( | 105 void set_accelerator(std::unique_ptr<JpegDecodeAccelerator> accelerator) { |
107 std::unique_ptr<media::JpegDecodeAccelerator> accelerator) { | |
108 DCHECK(CalledOnValidThread()); | 106 DCHECK(CalledOnValidThread()); |
109 accelerator_ = std::move(accelerator); | 107 accelerator_ = std::move(accelerator); |
110 } | 108 } |
111 | 109 |
112 private: | 110 private: |
113 base::WeakPtr<media::GpuJpegDecodeAccelerator> owner_; | 111 base::WeakPtr<GpuJpegDecodeAccelerator> owner_; |
114 int32_t route_id_; | 112 int32_t route_id_; |
115 std::unique_ptr<media::JpegDecodeAccelerator> accelerator_; | 113 std::unique_ptr<JpegDecodeAccelerator> accelerator_; |
116 }; | 114 }; |
117 | 115 |
118 // Create, destroy, and RemoveClient run on child thread. All other methods run | 116 // Create, destroy, and RemoveClient run on child thread. All other methods run |
119 // on IO thread. | 117 // on IO thread. |
120 class GpuJpegDecodeAccelerator::MessageFilter : public IPC::MessageFilter { | 118 class GpuJpegDecodeAccelerator::MessageFilter : public IPC::MessageFilter { |
121 public: | 119 public: |
122 explicit MessageFilter(GpuJpegDecodeAccelerator* owner) | 120 explicit MessageFilter(GpuJpegDecodeAccelerator* owner) |
123 : owner_(owner->AsWeakPtr()), | 121 : owner_(owner->AsWeakPtr()), |
124 child_task_runner_(owner_->child_task_runner_), | 122 child_task_runner_(owner_->child_task_runner_), |
125 io_task_runner_(owner_->io_task_runner_) {} | 123 io_task_runner_(owner_->io_task_runner_) {} |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
178 | 176 |
179 void DestroyClient(Client* client) { | 177 void DestroyClient(Client* client) { |
180 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 178 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
181 delete client; | 179 delete client; |
182 if (owner_) | 180 if (owner_) |
183 owner_->ClientRemoved(); | 181 owner_->ClientRemoved(); |
184 } | 182 } |
185 | 183 |
186 void NotifyDecodeStatusOnIOThread(int32_t route_id, | 184 void NotifyDecodeStatusOnIOThread(int32_t route_id, |
187 int32_t buffer_id, | 185 int32_t buffer_id, |
188 media::JpegDecodeAccelerator::Error error) { | 186 JpegDecodeAccelerator::Error error) { |
189 DCHECK(io_task_runner_->BelongsToCurrentThread()); | 187 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
190 SendOnIOThread(new AcceleratedJpegDecoderHostMsg_DecodeAck( | 188 SendOnIOThread(new AcceleratedJpegDecoderHostMsg_DecodeAck( |
191 route_id, buffer_id, error)); | 189 route_id, buffer_id, error)); |
192 } | 190 } |
193 | 191 |
194 void OnDecodeOnIOThread( | 192 void OnDecodeOnIOThread( |
195 const int32_t* route_id, | 193 const int32_t* route_id, |
196 const AcceleratedJpegDecoderMsg_Decode_Params& params) { | 194 const AcceleratedJpegDecoderMsg_Decode_Params& params) { |
197 DCHECK(io_task_runner_->BelongsToCurrentThread()); | 195 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
198 DCHECK(route_id); | 196 DCHECK(route_id); |
199 TRACE_EVENT0("jpeg", "GpuJpegDecodeAccelerator::MessageFilter::OnDecode"); | 197 TRACE_EVENT0("jpeg", "GpuJpegDecodeAccelerator::MessageFilter::OnDecode"); |
200 | 198 |
201 if (!VerifyDecodeParams(params)) { | 199 if (!VerifyDecodeParams(params)) { |
202 NotifyDecodeStatusOnIOThread( | 200 NotifyDecodeStatusOnIOThread(*route_id, params.input_buffer.id(), |
203 *route_id, params.input_buffer.id(), | 201 JpegDecodeAccelerator::INVALID_ARGUMENT); |
204 media::JpegDecodeAccelerator::INVALID_ARGUMENT); | |
205 if (base::SharedMemory::IsHandleValid(params.output_video_frame_handle)) | 202 if (base::SharedMemory::IsHandleValid(params.output_video_frame_handle)) |
206 base::SharedMemory::CloseHandle(params.output_video_frame_handle); | 203 base::SharedMemory::CloseHandle(params.output_video_frame_handle); |
207 return; | 204 return; |
208 } | 205 } |
209 | 206 |
210 // For handles in |params|, from now on, |params.output_video_frame_handle| | 207 // For handles in |params|, from now on, |params.output_video_frame_handle| |
211 // is taken cared by scoper. |params.input_buffer.handle()| need to be | 208 // is taken cared by scoper. |params.input_buffer.handle()| need to be |
212 // closed manually for early exits. | 209 // closed manually for early exits. |
213 std::unique_ptr<base::SharedMemory> output_shm( | 210 std::unique_ptr<base::SharedMemory> output_shm( |
214 new base::SharedMemory(params.output_video_frame_handle, false)); | 211 new base::SharedMemory(params.output_video_frame_handle, false)); |
215 if (!output_shm->Map(params.output_buffer_size)) { | 212 if (!output_shm->Map(params.output_buffer_size)) { |
216 LOG(ERROR) << "Could not map output shared memory for input buffer id " | 213 LOG(ERROR) << "Could not map output shared memory for input buffer id " |
217 << params.input_buffer.id(); | 214 << params.input_buffer.id(); |
218 NotifyDecodeStatusOnIOThread( | 215 NotifyDecodeStatusOnIOThread(*route_id, params.input_buffer.id(), |
219 *route_id, params.input_buffer.id(), | 216 JpegDecodeAccelerator::PLATFORM_FAILURE); |
220 media::JpegDecodeAccelerator::PLATFORM_FAILURE); | |
221 base::SharedMemory::CloseHandle(params.input_buffer.handle()); | 217 base::SharedMemory::CloseHandle(params.input_buffer.handle()); |
222 return; | 218 return; |
223 } | 219 } |
224 | 220 |
225 uint8_t* shm_memory = static_cast<uint8_t*>(output_shm->memory()); | 221 uint8_t* shm_memory = static_cast<uint8_t*>(output_shm->memory()); |
226 scoped_refptr<media::VideoFrame> frame = | 222 scoped_refptr<VideoFrame> frame = VideoFrame::WrapExternalSharedMemory( |
227 media::VideoFrame::WrapExternalSharedMemory( | 223 PIXEL_FORMAT_I420, // format |
228 media::PIXEL_FORMAT_I420, // format | 224 params.coded_size, // coded_size |
229 params.coded_size, // coded_size | 225 gfx::Rect(params.coded_size), // visible_rect |
230 gfx::Rect(params.coded_size), // visible_rect | 226 params.coded_size, // natural_size |
231 params.coded_size, // natural_size | 227 shm_memory, // data |
232 shm_memory, // data | 228 params.output_buffer_size, // data_size |
233 params.output_buffer_size, // data_size | 229 params.output_video_frame_handle, // handle |
234 params.output_video_frame_handle, // handle | 230 0, // data_offset |
235 0, // data_offset | 231 base::TimeDelta()); // timestamp |
236 base::TimeDelta()); // timestamp | |
237 if (!frame.get()) { | 232 if (!frame.get()) { |
238 LOG(ERROR) << "Could not create VideoFrame for input buffer id " | 233 LOG(ERROR) << "Could not create VideoFrame for input buffer id " |
239 << params.input_buffer.id(); | 234 << params.input_buffer.id(); |
240 NotifyDecodeStatusOnIOThread( | 235 NotifyDecodeStatusOnIOThread(*route_id, params.input_buffer.id(), |
241 *route_id, params.input_buffer.id(), | 236 JpegDecodeAccelerator::PLATFORM_FAILURE); |
242 media::JpegDecodeAccelerator::PLATFORM_FAILURE); | |
243 base::SharedMemory::CloseHandle(params.input_buffer.handle()); | 237 base::SharedMemory::CloseHandle(params.input_buffer.handle()); |
244 return; | 238 return; |
245 } | 239 } |
246 frame->AddDestructionObserver( | 240 frame->AddDestructionObserver( |
247 base::Bind(DecodeFinished, base::Passed(&output_shm))); | 241 base::Bind(DecodeFinished, base::Passed(&output_shm))); |
248 | 242 |
249 DCHECK_GT(client_map_.count(*route_id), 0u); | 243 DCHECK_GT(client_map_.count(*route_id), 0u); |
250 Client* client = client_map_[*route_id]; | 244 Client* client = client_map_[*route_id]; |
251 client->Decode(params.input_buffer, frame); | 245 client->Decode(params.input_buffer, frame); |
252 } | 246 } |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
317 // When adding non-chromeos platforms, VideoCaptureGpuJpegDecoder::Initialize | 311 // When adding non-chromeos platforms, VideoCaptureGpuJpegDecoder::Initialize |
318 // needs to be updated. | 312 // needs to be updated. |
319 | 313 |
320 // This list is ordered by priority of use. | 314 // This list is ordered by priority of use. |
321 const GpuJpegDecodeAccelerator::CreateJDAFp create_jda_fps[] = { | 315 const GpuJpegDecodeAccelerator::CreateJDAFp create_jda_fps[] = { |
322 &GpuJpegDecodeAccelerator::CreateV4L2JDA, | 316 &GpuJpegDecodeAccelerator::CreateV4L2JDA, |
323 &GpuJpegDecodeAccelerator::CreateVaapiJDA, | 317 &GpuJpegDecodeAccelerator::CreateVaapiJDA, |
324 }; | 318 }; |
325 | 319 |
326 std::unique_ptr<Client> client(new Client(this, route_id)); | 320 std::unique_ptr<Client> client(new Client(this, route_id)); |
327 std::unique_ptr<media::JpegDecodeAccelerator> accelerator; | 321 std::unique_ptr<JpegDecodeAccelerator> accelerator; |
328 for (const auto& create_jda_function : create_jda_fps) { | 322 for (const auto& create_jda_function : create_jda_fps) { |
329 std::unique_ptr<media::JpegDecodeAccelerator> tmp_accelerator = | 323 std::unique_ptr<JpegDecodeAccelerator> tmp_accelerator = |
330 (*create_jda_function)(io_task_runner_); | 324 (*create_jda_function)(io_task_runner_); |
331 if (tmp_accelerator && tmp_accelerator->Initialize(client.get())) { | 325 if (tmp_accelerator && tmp_accelerator->Initialize(client.get())) { |
332 accelerator = std::move(tmp_accelerator); | 326 accelerator = std::move(tmp_accelerator); |
333 break; | 327 break; |
334 } | 328 } |
335 } | 329 } |
336 | 330 |
337 if (!accelerator) { | 331 if (!accelerator) { |
338 DLOG(ERROR) << "JPEG accelerator Initialize failed"; | 332 DLOG(ERROR) << "JPEG accelerator Initialize failed"; |
339 response.Run(false); | 333 response.Run(false); |
(...skipping 16 matching lines...) Expand all Loading... |
356 // we're going to tear down the process anyway. So we just crossed fingers | 350 // we're going to tear down the process anyway. So we just crossed fingers |
357 // here instead of making the code unnecessary complicated. | 351 // here instead of making the code unnecessary complicated. |
358 io_task_runner_->PostTask( | 352 io_task_runner_->PostTask( |
359 FROM_HERE, base::Bind(&MessageFilter::AddClientOnIOThread, filter_, | 353 FROM_HERE, base::Bind(&MessageFilter::AddClientOnIOThread, filter_, |
360 route_id, client.release(), response)); | 354 route_id, client.release(), response)); |
361 } | 355 } |
362 | 356 |
363 void GpuJpegDecodeAccelerator::NotifyDecodeStatus( | 357 void GpuJpegDecodeAccelerator::NotifyDecodeStatus( |
364 int32_t route_id, | 358 int32_t route_id, |
365 int32_t buffer_id, | 359 int32_t buffer_id, |
366 media::JpegDecodeAccelerator::Error error) { | 360 JpegDecodeAccelerator::Error error) { |
367 DCHECK(CalledOnValidThread()); | 361 DCHECK(CalledOnValidThread()); |
368 Send(new AcceleratedJpegDecoderHostMsg_DecodeAck(route_id, buffer_id, error)); | 362 Send(new AcceleratedJpegDecoderHostMsg_DecodeAck(route_id, buffer_id, error)); |
369 } | 363 } |
370 | 364 |
371 void GpuJpegDecodeAccelerator::ClientRemoved() { | 365 void GpuJpegDecodeAccelerator::ClientRemoved() { |
372 DCHECK(CalledOnValidThread()); | 366 DCHECK(CalledOnValidThread()); |
373 DCHECK_GT(client_number_, 0); | 367 DCHECK_GT(client_number_, 0); |
374 client_number_--; | 368 client_number_--; |
375 if (client_number_ == 0) { | 369 if (client_number_ == 0) { |
376 channel_->RemoveFilter(filter_.get()); | 370 channel_->RemoveFilter(filter_.get()); |
377 filter_ = nullptr; | 371 filter_ = nullptr; |
378 } | 372 } |
379 } | 373 } |
380 | 374 |
381 bool GpuJpegDecodeAccelerator::Send(IPC::Message* message) { | 375 bool GpuJpegDecodeAccelerator::Send(IPC::Message* message) { |
382 DCHECK(CalledOnValidThread()); | 376 DCHECK(CalledOnValidThread()); |
383 return channel_->Send(message); | 377 return channel_->Send(message); |
384 } | 378 } |
385 | 379 |
386 // static | 380 // static |
387 std::unique_ptr<media::JpegDecodeAccelerator> | 381 std::unique_ptr<JpegDecodeAccelerator> GpuJpegDecodeAccelerator::CreateV4L2JDA( |
388 GpuJpegDecodeAccelerator::CreateV4L2JDA( | |
389 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) { | 382 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) { |
390 std::unique_ptr<media::JpegDecodeAccelerator> decoder; | 383 std::unique_ptr<JpegDecodeAccelerator> decoder; |
391 #if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC) | 384 #if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC) |
392 scoped_refptr<V4L2Device> device = | 385 scoped_refptr<V4L2Device> device = |
393 V4L2Device::Create(V4L2Device::kJpegDecoder); | 386 V4L2Device::Create(V4L2Device::kJpegDecoder); |
394 if (device) | 387 if (device) |
395 decoder.reset(new V4L2JpegDecodeAccelerator(device, io_task_runner)); | 388 decoder.reset(new V4L2JpegDecodeAccelerator(device, io_task_runner)); |
396 #endif | 389 #endif |
397 return decoder; | 390 return decoder; |
398 } | 391 } |
399 | 392 |
400 // static | 393 // static |
401 std::unique_ptr<media::JpegDecodeAccelerator> | 394 std::unique_ptr<JpegDecodeAccelerator> GpuJpegDecodeAccelerator::CreateVaapiJDA( |
402 GpuJpegDecodeAccelerator::CreateVaapiJDA( | |
403 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) { | 395 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) { |
404 std::unique_ptr<media::JpegDecodeAccelerator> decoder; | 396 std::unique_ptr<JpegDecodeAccelerator> decoder; |
405 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) | 397 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) |
406 decoder.reset(new VaapiJpegDecodeAccelerator(io_task_runner)); | 398 decoder.reset(new VaapiJpegDecodeAccelerator(io_task_runner)); |
407 #endif | 399 #endif |
408 return decoder; | 400 return decoder; |
409 } | 401 } |
410 | 402 |
411 // static | 403 // static |
412 bool GpuJpegDecodeAccelerator::IsSupported() { | 404 bool GpuJpegDecodeAccelerator::IsSupported() { |
413 const GpuJpegDecodeAccelerator::CreateJDAFp create_jda_fps[] = { | 405 const GpuJpegDecodeAccelerator::CreateJDAFp create_jda_fps[] = { |
414 &GpuJpegDecodeAccelerator::CreateV4L2JDA, | 406 &GpuJpegDecodeAccelerator::CreateV4L2JDA, |
415 &GpuJpegDecodeAccelerator::CreateVaapiJDA, | 407 &GpuJpegDecodeAccelerator::CreateVaapiJDA, |
416 }; | 408 }; |
417 for (const auto& create_jda_function : create_jda_fps) { | 409 for (const auto& create_jda_function : create_jda_fps) { |
418 std::unique_ptr<media::JpegDecodeAccelerator> accelerator = | 410 std::unique_ptr<JpegDecodeAccelerator> accelerator = |
419 (*create_jda_function)(base::ThreadTaskRunnerHandle::Get()); | 411 (*create_jda_function)(base::ThreadTaskRunnerHandle::Get()); |
420 if (accelerator && accelerator->IsSupported()) | 412 if (accelerator && accelerator->IsSupported()) |
421 return true; | 413 return true; |
422 } | 414 } |
423 return false; | 415 return false; |
424 } | 416 } |
425 | 417 |
426 } // namespace media | 418 } // namespace media |
OLD | NEW |