OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 <dlfcn.h> | 5 #include <dlfcn.h> |
6 #include <errno.h> | 6 #include <errno.h> |
7 #include <fcntl.h> | 7 #include <fcntl.h> |
8 #include <linux/videodev2.h> | 8 #include <linux/videodev2.h> |
9 #include <poll.h> | 9 #include <poll.h> |
10 #include <string.h> | 10 #include <string.h> |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
198 DCHECK(input_buffer_map_.empty()); | 198 DCHECK(input_buffer_map_.empty()); |
199 DCHECK(output_buffer_map_.empty()); | 199 DCHECK(output_buffer_map_.empty()); |
200 } | 200 } |
201 | 201 |
202 bool V4L2VideoDecodeAccelerator::Initialize(const Config& config, | 202 bool V4L2VideoDecodeAccelerator::Initialize(const Config& config, |
203 Client* client) { | 203 Client* client) { |
204 DVLOG(3) << "Initialize()"; | 204 DVLOG(3) << "Initialize()"; |
205 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 205 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
206 DCHECK_EQ(decoder_state_, kUninitialized); | 206 DCHECK_EQ(decoder_state_, kUninitialized); |
207 | 207 |
208 if (get_gl_context_cb_.is_null() || make_context_current_cb_.is_null()) { | 208 if (!device_->SupportsDecodeProfileForV4L2PixelFormats( |
209 NOTREACHED() << "GL callbacks are required for this VDA"; | 209 config.profile, arraysize(supported_input_fourccs_), |
| 210 supported_input_fourccs_)) { |
| 211 DVLOG(1) << "Initialize(): unsupported profile=" << config.profile; |
210 return false; | 212 return false; |
211 } | 213 } |
212 | 214 |
213 if (config.is_encrypted) { | 215 if (config.is_encrypted) { |
214 NOTREACHED() << "Encrypted streams are not supported for this VDA"; | 216 NOTREACHED() << "Encrypted streams are not supported for this VDA"; |
215 return false; | 217 return false; |
216 } | 218 } |
217 | 219 |
218 if (!device_->SupportsDecodeProfileForV4L2PixelFormats( | 220 if (config.output_mode != Config::OutputMode::ALLOCATE) { |
219 config.profile, arraysize(supported_input_fourccs_), | 221 NOTREACHED() << "Only ALLOCATE OutputMode is supported by this VDA"; |
220 supported_input_fourccs_)) { | |
221 DVLOG(1) << "Initialize(): unsupported profile=" << config.profile; | |
222 return false; | 222 return false; |
223 } | 223 } |
224 | 224 |
| 225 if (get_gl_context_cb_.is_null() || make_context_current_cb_.is_null()) { |
| 226 NOTREACHED() << "GL callbacks are required for this VDA"; |
| 227 return false; |
| 228 } |
| 229 |
225 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client)); | 230 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client)); |
226 client_ = client_ptr_factory_->GetWeakPtr(); | 231 client_ = client_ptr_factory_->GetWeakPtr(); |
227 // If we haven't been set up to decode on separate thread via | 232 // If we haven't been set up to decode on separate thread via |
228 // TryToSetupDecodeOnSeparateThread(), use the main thread/client for | 233 // TryToSetupDecodeOnSeparateThread(), use the main thread/client for |
229 // decode tasks. | 234 // decode tasks. |
230 if (!decode_task_runner_) { | 235 if (!decode_task_runner_) { |
231 decode_task_runner_ = child_task_runner_; | 236 decode_task_runner_ = child_task_runner_; |
232 DCHECK(!decode_client_); | 237 DCHECK(!decode_client_); |
233 decode_client_ = client_; | 238 decode_client_ = client_; |
234 } | 239 } |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
368 | 373 |
369 OutputRecord& output_record = output_buffer_map_[i]; | 374 OutputRecord& output_record = output_buffer_map_[i]; |
370 DCHECK(!output_record.at_device); | 375 DCHECK(!output_record.at_device); |
371 DCHECK(!output_record.at_client); | 376 DCHECK(!output_record.at_client); |
372 DCHECK_EQ(output_record.egl_image, EGL_NO_IMAGE_KHR); | 377 DCHECK_EQ(output_record.egl_image, EGL_NO_IMAGE_KHR); |
373 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); | 378 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); |
374 DCHECK_EQ(output_record.picture_id, -1); | 379 DCHECK_EQ(output_record.picture_id, -1); |
375 DCHECK_EQ(output_record.cleared, false); | 380 DCHECK_EQ(output_record.cleared, false); |
376 DCHECK_LE(1u, buffers[i].texture_ids().size()); | 381 DCHECK_LE(1u, buffers[i].texture_ids().size()); |
377 | 382 |
378 EGLImageKHR egl_image = device_->CreateEGLImage( | 383 std::vector<base::ScopedFD> dmabuf_fds; |
379 egl_display_, gl_context->GetHandle(), buffers[i].texture_ids()[0], | 384 dmabuf_fds = device_->GetDmabufsForV4L2Buffer( |
380 coded_size_, i, output_format_fourcc_, output_planes_count_); | 385 i, output_planes_count_, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); |
| 386 if (dmabuf_fds.empty()) { |
| 387 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 388 return; |
| 389 } |
| 390 |
| 391 EGLImageKHR egl_image = device_->CreateEGLImage(egl_display_, |
| 392 gl_context->GetHandle(), |
| 393 buffers[i].texture_ids()[0], |
| 394 coded_size_, |
| 395 i, |
| 396 output_format_fourcc_, |
| 397 dmabuf_fds); |
381 if (egl_image == EGL_NO_IMAGE_KHR) { | 398 if (egl_image == EGL_NO_IMAGE_KHR) { |
382 LOG(ERROR) << "AssignPictureBuffers(): could not create EGLImageKHR"; | 399 LOG(ERROR) << "AssignPictureBuffers(): could not create EGLImageKHR"; |
383 // Ownership of EGLImages allocated in previous iterations of this loop | 400 // Ownership of EGLImages allocated in previous iterations of this loop |
384 // has been transferred to output_buffer_map_. After we error-out here | 401 // has been transferred to output_buffer_map_. After we error-out here |
385 // the destructor will handle their cleanup. | 402 // the destructor will handle their cleanup. |
386 NOTIFY_ERROR(PLATFORM_FAILURE); | 403 NOTIFY_ERROR(PLATFORM_FAILURE); |
387 return; | 404 return; |
388 } | 405 } |
389 | 406 |
390 output_record.egl_image = egl_image; | 407 output_record.egl_image = egl_image; |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
464 } | 481 } |
465 | 482 |
466 bool V4L2VideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread( | 483 bool V4L2VideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread( |
467 const base::WeakPtr<Client>& decode_client, | 484 const base::WeakPtr<Client>& decode_client, |
468 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) { | 485 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) { |
469 decode_client_ = decode_client_; | 486 decode_client_ = decode_client_; |
470 decode_task_runner_ = decode_task_runner; | 487 decode_task_runner_ = decode_task_runner; |
471 return true; | 488 return true; |
472 } | 489 } |
473 | 490 |
| 491 media::VideoPixelFormat V4L2VideoDecodeAccelerator::GetOutputFormat() const { |
| 492 return V4L2Device::V4L2PixFmtToVideoPixelFormat(output_format_fourcc_); |
| 493 } |
| 494 |
474 // static | 495 // static |
475 media::VideoDecodeAccelerator::SupportedProfiles | 496 media::VideoDecodeAccelerator::SupportedProfiles |
476 V4L2VideoDecodeAccelerator::GetSupportedProfiles() { | 497 V4L2VideoDecodeAccelerator::GetSupportedProfiles() { |
477 scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder); | 498 scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder); |
478 if (!device) | 499 if (!device) |
479 return SupportedProfiles(); | 500 return SupportedProfiles(); |
480 | 501 |
481 return device->GetSupportedDecodeProfiles(arraysize(supported_input_fourccs_), | 502 return device->GetSupportedDecodeProfiles(arraysize(supported_input_fourccs_), |
482 supported_input_fourccs_); | 503 supported_input_fourccs_); |
483 } | 504 } |
(...skipping 1559 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2043 | 2064 |
2044 void V4L2VideoDecodeAccelerator::PictureCleared() { | 2065 void V4L2VideoDecodeAccelerator::PictureCleared() { |
2045 DVLOG(3) << "PictureCleared(). clearing count=" << picture_clearing_count_; | 2066 DVLOG(3) << "PictureCleared(). clearing count=" << picture_clearing_count_; |
2046 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 2067 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
2047 DCHECK_GT(picture_clearing_count_, 0); | 2068 DCHECK_GT(picture_clearing_count_, 0); |
2048 picture_clearing_count_--; | 2069 picture_clearing_count_--; |
2049 SendPictureReady(); | 2070 SendPictureReady(); |
2050 } | 2071 } |
2051 | 2072 |
2052 } // namespace content | 2073 } // namespace content |
OLD | NEW |