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 <sys/eventfd.h> | 10 #include <sys/eventfd.h> |
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
316 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 316 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( |
317 &V4L2VideoDecodeAccelerator::DecodeTask, base::Unretained(this), | 317 &V4L2VideoDecodeAccelerator::DecodeTask, base::Unretained(this), |
318 bitstream_buffer)); | 318 bitstream_buffer)); |
319 } | 319 } |
320 | 320 |
321 void V4L2VideoDecodeAccelerator::AssignPictureBuffers( | 321 void V4L2VideoDecodeAccelerator::AssignPictureBuffers( |
322 const std::vector<media::PictureBuffer>& buffers) { | 322 const std::vector<media::PictureBuffer>& buffers) { |
323 DVLOG(3) << "AssignPictureBuffers(): buffer_count=" << buffers.size(); | 323 DVLOG(3) << "AssignPictureBuffers(): buffer_count=" << buffers.size(); |
324 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 324 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
325 | 325 |
326 if (buffers.size() != output_buffer_map_.size()) { | 326 const uint32_t req_buffer_count = |
| 327 output_dpb_size_ + kDpbOutputBufferExtraCount; |
| 328 |
| 329 if (buffers.size() < req_buffer_count) { |
327 LOG(ERROR) << "AssignPictureBuffers(): Failed to provide requested picture" | 330 LOG(ERROR) << "AssignPictureBuffers(): Failed to provide requested picture" |
328 " buffers. (Got " << buffers.size() | 331 " buffers. (Got " << buffers.size() |
329 << ", requested " << output_buffer_map_.size() << ")"; | 332 << ", requested " << req_buffer_count << ")"; |
330 NOTIFY_ERROR(INVALID_ARGUMENT); | 333 NOTIFY_ERROR(INVALID_ARGUMENT); |
331 return; | 334 return; |
332 } | 335 } |
333 | 336 |
334 if (!make_context_current_.Run()) { | 337 if (!make_context_current_.Run()) { |
335 LOG(ERROR) << "AssignPictureBuffers(): could not make context current"; | 338 LOG(ERROR) << "AssignPictureBuffers(): could not make context current"; |
336 NOTIFY_ERROR(PLATFORM_FAILURE); | 339 NOTIFY_ERROR(PLATFORM_FAILURE); |
337 return; | 340 return; |
338 } | 341 } |
339 | 342 |
340 gfx::ScopedTextureBinder bind_restore(GL_TEXTURE_EXTERNAL_OES, 0); | 343 gfx::ScopedTextureBinder bind_restore(GL_TEXTURE_EXTERNAL_OES, 0); |
341 | 344 |
342 // It's safe to manipulate all the buffer state here, because the decoder | 345 // It's safe to manipulate all the buffer state here, because the decoder |
343 // thread is waiting on pictures_assigned_. | 346 // thread is waiting on pictures_assigned_. |
| 347 |
| 348 // Allocate the output buffers. |
| 349 struct v4l2_requestbuffers reqbufs; |
| 350 memset(&reqbufs, 0, sizeof(reqbufs)); |
| 351 reqbufs.count = buffers.size(); |
| 352 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 353 reqbufs.memory = V4L2_MEMORY_MMAP; |
| 354 IOCTL_OR_ERROR_RETURN(VIDIOC_REQBUFS, &reqbufs); |
| 355 |
| 356 if (reqbufs.count != buffers.size()) { |
| 357 DLOG(ERROR) << "Could not allocate enough output buffers"; |
| 358 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 359 return; |
| 360 } |
| 361 |
| 362 output_buffer_map_.resize(buffers.size()); |
| 363 |
344 DCHECK(free_output_buffers_.empty()); | 364 DCHECK(free_output_buffers_.empty()); |
345 for (size_t i = 0; i < output_buffer_map_.size(); ++i) { | 365 for (size_t i = 0; i < output_buffer_map_.size(); ++i) { |
346 DCHECK(buffers[i].size() == coded_size_); | 366 DCHECK(buffers[i].size() == coded_size_); |
347 | 367 |
348 OutputRecord& output_record = output_buffer_map_[i]; | 368 OutputRecord& output_record = output_buffer_map_[i]; |
349 DCHECK(!output_record.at_device); | 369 DCHECK(!output_record.at_device); |
350 DCHECK(!output_record.at_client); | 370 DCHECK(!output_record.at_client); |
351 DCHECK_EQ(output_record.egl_image, EGL_NO_IMAGE_KHR); | 371 DCHECK_EQ(output_record.egl_image, EGL_NO_IMAGE_KHR); |
352 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); | 372 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); |
353 DCHECK_EQ(output_record.picture_id, -1); | 373 DCHECK_EQ(output_record.picture_id, -1); |
(...skipping 1472 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1826 | 1846 |
1827 // Number of output buffers we need. | 1847 // Number of output buffers we need. |
1828 struct v4l2_control ctrl; | 1848 struct v4l2_control ctrl; |
1829 memset(&ctrl, 0, sizeof(ctrl)); | 1849 memset(&ctrl, 0, sizeof(ctrl)); |
1830 ctrl.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE; | 1850 ctrl.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE; |
1831 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_G_CTRL, &ctrl); | 1851 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_G_CTRL, &ctrl); |
1832 output_dpb_size_ = ctrl.value; | 1852 output_dpb_size_ = ctrl.value; |
1833 | 1853 |
1834 // Output format setup in Initialize(). | 1854 // Output format setup in Initialize(). |
1835 | 1855 |
1836 // Allocate the output buffers. | 1856 const uint32_t buffer_count = output_dpb_size_ + kDpbOutputBufferExtraCount; |
1837 struct v4l2_requestbuffers reqbufs; | |
1838 memset(&reqbufs, 0, sizeof(reqbufs)); | |
1839 reqbufs.count = output_dpb_size_ + kDpbOutputBufferExtraCount; | |
1840 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | |
1841 reqbufs.memory = V4L2_MEMORY_MMAP; | |
1842 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs); | |
1843 | |
1844 output_buffer_map_.resize(reqbufs.count); | |
1845 | |
1846 DVLOG(3) << "CreateOutputBuffers(): ProvidePictureBuffers(): " | 1857 DVLOG(3) << "CreateOutputBuffers(): ProvidePictureBuffers(): " |
1847 << "buffer_count=" << output_buffer_map_.size() | 1858 << "buffer_count=" << buffer_count |
1848 << ", coded_size=" << coded_size_.ToString(); | 1859 << ", coded_size=" << coded_size_.ToString(); |
1849 child_task_runner_->PostTask( | 1860 child_task_runner_->PostTask( |
1850 FROM_HERE, base::Bind(&Client::ProvidePictureBuffers, client_, | 1861 FROM_HERE, base::Bind(&Client::ProvidePictureBuffers, client_, |
1851 output_buffer_map_.size(), coded_size_, | 1862 buffer_count, coded_size_, |
1852 device_->GetTextureTarget())); | 1863 device_->GetTextureTarget())); |
1853 | 1864 |
1854 // Wait for the client to call AssignPictureBuffers() on the Child thread. | 1865 // Wait for the client to call AssignPictureBuffers() on the Child thread. |
1855 // We do this, because if we continue decoding without finishing buffer | 1866 // We do this, because if we continue decoding without finishing buffer |
1856 // allocation, we may end up Resetting before AssignPictureBuffers arrives, | 1867 // allocation, we may end up Resetting before AssignPictureBuffers arrives, |
1857 // resulting in unnecessary complications and subtle bugs. | 1868 // resulting in unnecessary complications and subtle bugs. |
1858 // For example, if the client calls Decode(Input1), Reset(), Decode(Input2) | 1869 // For example, if the client calls Decode(Input1), Reset(), Decode(Input2) |
1859 // in a sequence, and Decode(Input1) results in us getting here and exiting | 1870 // in a sequence, and Decode(Input1) results in us getting here and exiting |
1860 // without waiting, we might end up running Reset{,Done}Task() before | 1871 // without waiting, we might end up running Reset{,Done}Task() before |
1861 // AssignPictureBuffers is scheduled, thus cleaning up and pushing buffers | 1872 // AssignPictureBuffers is scheduled, thus cleaning up and pushing buffers |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2028 gfx::Size new_coded_size(base::checked_cast<int>(format.fmt.pix_mp.width), | 2039 gfx::Size new_coded_size(base::checked_cast<int>(format.fmt.pix_mp.width), |
2029 base::checked_cast<int>(format.fmt.pix_mp.height)); | 2040 base::checked_cast<int>(format.fmt.pix_mp.height)); |
2030 if (coded_size_ != new_coded_size) { | 2041 if (coded_size_ != new_coded_size) { |
2031 DVLOG(3) << "IsResolutionChangeNecessary(): Resolution change detected"; | 2042 DVLOG(3) << "IsResolutionChangeNecessary(): Resolution change detected"; |
2032 return true; | 2043 return true; |
2033 } | 2044 } |
2034 return false; | 2045 return false; |
2035 } | 2046 } |
2036 | 2047 |
2037 } // namespace content | 2048 } // namespace content |
OLD | NEW |