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> |
11 #include <sys/ioctl.h> | 11 #include <sys/ioctl.h> |
12 #include <sys/mman.h> | 12 #include <sys/mman.h> |
13 | 13 |
14 #include "base/bind.h" | 14 #include "base/bind.h" |
15 #include "base/command_line.h" | 15 #include "base/command_line.h" |
16 #include "base/memory/shared_memory.h" | 16 #include "base/memory/shared_memory.h" |
17 #include "base/message_loop/message_loop.h" | 17 #include "base/message_loop/message_loop.h" |
18 #include "base/message_loop/message_loop_proxy.h" | 18 #include "base/message_loop/message_loop_proxy.h" |
19 #include "base/numerics/safe_conversions.h" | 19 #include "base/numerics/safe_conversions.h" |
20 #include "base/trace_event/trace_event.h" | 20 #include "base/trace_event/trace_event.h" |
21 #include "content/common/gpu/media/v4l2_video_decode_accelerator.h" | 21 #include "content/common/gpu/media/v4l2_video_decode_accelerator.h" |
22 #include "media/base/media_switches.h" | 22 #include "media/base/media_switches.h" |
23 #include "media/filters/h264_parser.h" | 23 #include "media/filters/h264_parser.h" |
| 24 #include "ui/gfx/geometry/rect.h" |
24 #include "ui/gl/scoped_binders.h" | 25 #include "ui/gl/scoped_binders.h" |
25 | 26 |
26 #define NOTIFY_ERROR(x) \ | 27 #define NOTIFY_ERROR(x) \ |
27 do { \ | 28 do { \ |
28 LOG(ERROR) << "Setting error state:" << x; \ | 29 LOG(ERROR) << "Setting error state:" << x; \ |
29 SetErrorState(x); \ | 30 SetErrorState(x); \ |
30 } while (0) | 31 } while (0) |
31 | 32 |
32 #define IOCTL_OR_ERROR_RETURN_VALUE(type, arg, value) \ | 33 #define IOCTL_OR_ERROR_RETURN_VALUE(type, arg, value) \ |
33 do { \ | 34 do { \ |
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
332 NOTIFY_ERROR(PLATFORM_FAILURE); | 333 NOTIFY_ERROR(PLATFORM_FAILURE); |
333 return; | 334 return; |
334 } | 335 } |
335 | 336 |
336 gfx::ScopedTextureBinder bind_restore(GL_TEXTURE_EXTERNAL_OES, 0); | 337 gfx::ScopedTextureBinder bind_restore(GL_TEXTURE_EXTERNAL_OES, 0); |
337 | 338 |
338 // It's safe to manipulate all the buffer state here, because the decoder | 339 // It's safe to manipulate all the buffer state here, because the decoder |
339 // thread is waiting on pictures_assigned_. | 340 // thread is waiting on pictures_assigned_. |
340 DCHECK(free_output_buffers_.empty()); | 341 DCHECK(free_output_buffers_.empty()); |
341 for (size_t i = 0; i < output_buffer_map_.size(); ++i) { | 342 for (size_t i = 0; i < output_buffer_map_.size(); ++i) { |
342 DCHECK(buffers[i].size() == frame_buffer_size_); | 343 DCHECK(buffers[i].size() == coded_size_); |
343 | 344 |
344 OutputRecord& output_record = output_buffer_map_[i]; | 345 OutputRecord& output_record = output_buffer_map_[i]; |
345 DCHECK(!output_record.at_device); | 346 DCHECK(!output_record.at_device); |
346 DCHECK(!output_record.at_client); | 347 DCHECK(!output_record.at_client); |
347 DCHECK_EQ(output_record.egl_image, EGL_NO_IMAGE_KHR); | 348 DCHECK_EQ(output_record.egl_image, EGL_NO_IMAGE_KHR); |
348 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); | 349 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); |
349 DCHECK_EQ(output_record.picture_id, -1); | 350 DCHECK_EQ(output_record.picture_id, -1); |
350 DCHECK_EQ(output_record.cleared, false); | 351 DCHECK_EQ(output_record.cleared, false); |
351 | 352 |
352 EGLImageKHR egl_image = device_->CreateEGLImage(egl_display_, | 353 EGLImageKHR egl_image = device_->CreateEGLImage(egl_display_, |
353 egl_context_, | 354 egl_context_, |
354 buffers[i].texture_id(), | 355 buffers[i].texture_id(), |
355 frame_buffer_size_, | 356 coded_size_, |
356 i, | 357 i, |
357 output_format_fourcc_, | 358 output_format_fourcc_, |
358 output_planes_count_); | 359 output_planes_count_); |
359 if (egl_image == EGL_NO_IMAGE_KHR) { | 360 if (egl_image == EGL_NO_IMAGE_KHR) { |
360 LOG(ERROR) << "AssignPictureBuffers(): could not create EGLImageKHR"; | 361 LOG(ERROR) << "AssignPictureBuffers(): could not create EGLImageKHR"; |
361 // Ownership of EGLImages allocated in previous iterations of this loop | 362 // Ownership of EGLImages allocated in previous iterations of this loop |
362 // has been transferred to output_buffer_map_. After we error-out here | 363 // has been transferred to output_buffer_map_. After we error-out here |
363 // the destructor will handle their cleanup. | 364 // the destructor will handle their cleanup. |
364 NOTIFY_ERROR(PLATFORM_FAILURE); | 365 NOTIFY_ERROR(PLATFORM_FAILURE); |
365 return; | 366 return; |
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
722 return true; | 723 return true; |
723 | 724 |
724 if (!FlushInputFrame()) | 725 if (!FlushInputFrame()) |
725 return false; | 726 return false; |
726 | 727 |
727 // Recycle buffers. | 728 // Recycle buffers. |
728 Dequeue(); | 729 Dequeue(); |
729 | 730 |
730 // Check and see if we have format info yet. | 731 // Check and see if we have format info yet. |
731 struct v4l2_format format; | 732 struct v4l2_format format; |
| 733 gfx::Size visible_size; |
732 bool again = false; | 734 bool again = false; |
733 if (!GetFormatInfo(&format, &again)) | 735 if (!GetFormatInfo(&format, &visible_size, &again)) |
734 return false; | 736 return false; |
735 | 737 |
736 if (again) { | 738 if (again) { |
737 // Need more stream to decode format, return true and schedule next buffer. | 739 // Need more stream to decode format, return true and schedule next buffer. |
738 *endpos = size; | 740 *endpos = size; |
739 return true; | 741 return true; |
740 } | 742 } |
741 | 743 |
742 // Run this initialization only on first startup. | 744 // Run this initialization only on first startup. |
743 if (decoder_state_ == kInitialized) { | 745 if (decoder_state_ == kInitialized) { |
744 DVLOG(3) << "DecodeBufferInitial(): running initialization"; | 746 DVLOG(3) << "DecodeBufferInitial(): running initialization"; |
745 // Success! Setup our parameters. | 747 // Success! Setup our parameters. |
746 if (!CreateBuffersForFormat(format)) | 748 if (!CreateBuffersForFormat(format, visible_size)) |
747 return false; | 749 return false; |
748 | 750 |
749 // We expect to process the initial buffer once during stream init to | 751 // We expect to process the initial buffer once during stream init to |
750 // configure stream parameters, but will not consume the steam data on that | 752 // configure stream parameters, but will not consume the steam data on that |
751 // iteration. Subsequent iterations (including after reset) do not require | 753 // iteration. Subsequent iterations (including after reset) do not require |
752 // the stream init step. | 754 // the stream init step. |
753 *endpos = 0; | 755 *endpos = 0; |
754 } else { | 756 } else { |
755 *endpos = size; | 757 *endpos = size; |
756 } | 758 } |
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1078 if (dqbuf.m.planes[0].bytesused == 0) { | 1080 if (dqbuf.m.planes[0].bytesused == 0) { |
1079 // This is an empty output buffer returned as part of a flush. | 1081 // This is an empty output buffer returned as part of a flush. |
1080 free_output_buffers_.push(dqbuf.index); | 1082 free_output_buffers_.push(dqbuf.index); |
1081 } else { | 1083 } else { |
1082 DCHECK_GE(dqbuf.timestamp.tv_sec, 0); | 1084 DCHECK_GE(dqbuf.timestamp.tv_sec, 0); |
1083 output_record.at_client = true; | 1085 output_record.at_client = true; |
1084 DVLOG(3) << "Dequeue(): returning input_id=" << dqbuf.timestamp.tv_sec | 1086 DVLOG(3) << "Dequeue(): returning input_id=" << dqbuf.timestamp.tv_sec |
1085 << " as picture_id=" << output_record.picture_id; | 1087 << " as picture_id=" << output_record.picture_id; |
1086 const media::Picture& picture = | 1088 const media::Picture& picture = |
1087 media::Picture(output_record.picture_id, dqbuf.timestamp.tv_sec, | 1089 media::Picture(output_record.picture_id, dqbuf.timestamp.tv_sec, |
1088 gfx::Rect(frame_buffer_size_), false); | 1090 gfx::Rect(visible_size_), false); |
1089 pending_picture_ready_.push( | 1091 pending_picture_ready_.push( |
1090 PictureRecord(output_record.cleared, picture)); | 1092 PictureRecord(output_record.cleared, picture)); |
1091 SendPictureReady(); | 1093 SendPictureReady(); |
1092 output_record.cleared = true; | 1094 output_record.cleared = true; |
1093 decoder_frames_at_client_++; | 1095 decoder_frames_at_client_++; |
1094 } | 1096 } |
1095 output_buffer_queued_count_--; | 1097 output_buffer_queued_count_--; |
1096 } | 1098 } |
1097 | 1099 |
1098 NotifyFlushDoneIfNeeded(); | 1100 NotifyFlushDoneIfNeeded(); |
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1526 DCHECK_EQ(decoder_state_, kChangingResolution); | 1528 DCHECK_EQ(decoder_state_, kChangingResolution); |
1527 DVLOG(3) << "FinishResolutionChange()"; | 1529 DVLOG(3) << "FinishResolutionChange()"; |
1528 | 1530 |
1529 if (decoder_state_ == kError) { | 1531 if (decoder_state_ == kError) { |
1530 DVLOG(2) << "FinishResolutionChange(): early out: kError state"; | 1532 DVLOG(2) << "FinishResolutionChange(): early out: kError state"; |
1531 return; | 1533 return; |
1532 } | 1534 } |
1533 | 1535 |
1534 struct v4l2_format format; | 1536 struct v4l2_format format; |
1535 bool again; | 1537 bool again; |
1536 bool ret = GetFormatInfo(&format, &again); | 1538 gfx::Size visible_size; |
| 1539 bool ret = GetFormatInfo(&format, &visible_size, &again); |
1537 if (!ret || again) { | 1540 if (!ret || again) { |
1538 LOG(ERROR) << "Couldn't get format information after resolution change"; | 1541 LOG(ERROR) << "Couldn't get format information after resolution change"; |
1539 NOTIFY_ERROR(PLATFORM_FAILURE); | 1542 NOTIFY_ERROR(PLATFORM_FAILURE); |
1540 return; | 1543 return; |
1541 } | 1544 } |
1542 | 1545 |
1543 if (!CreateBuffersForFormat(format)) { | 1546 if (!CreateBuffersForFormat(format, visible_size)) { |
1544 LOG(ERROR) << "Couldn't reallocate buffers after resolution change"; | 1547 LOG(ERROR) << "Couldn't reallocate buffers after resolution change"; |
1545 NOTIFY_ERROR(PLATFORM_FAILURE); | 1548 NOTIFY_ERROR(PLATFORM_FAILURE); |
1546 return; | 1549 return; |
1547 } | 1550 } |
1548 | 1551 |
1549 decoder_state_ = kDecoding; | 1552 decoder_state_ = kDecoding; |
1550 | 1553 |
1551 if (resolution_change_reset_pending_) { | 1554 if (resolution_change_reset_pending_) { |
1552 resolution_change_reset_pending_ = false; | 1555 resolution_change_reset_pending_ = false; |
1553 ResetTask(); | 1556 ResetTask(); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1608 | 1611 |
1609 // Post NotifyError only if we are already initialized, as the API does | 1612 // Post NotifyError only if we are already initialized, as the API does |
1610 // not allow doing so before that. | 1613 // not allow doing so before that. |
1611 if (decoder_state_ != kError && decoder_state_ != kUninitialized) | 1614 if (decoder_state_ != kError && decoder_state_ != kUninitialized) |
1612 NotifyError(error); | 1615 NotifyError(error); |
1613 | 1616 |
1614 decoder_state_ = kError; | 1617 decoder_state_ = kError; |
1615 } | 1618 } |
1616 | 1619 |
1617 bool V4L2VideoDecodeAccelerator::GetFormatInfo(struct v4l2_format* format, | 1620 bool V4L2VideoDecodeAccelerator::GetFormatInfo(struct v4l2_format* format, |
1618 bool* again) { | 1621 gfx::Size* visible_size, |
| 1622 bool* again) { |
1619 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1623 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
1620 | 1624 |
1621 *again = false; | 1625 *again = false; |
1622 memset(format, 0, sizeof(*format)); | 1626 memset(format, 0, sizeof(*format)); |
1623 format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1627 format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
1624 if (device_->Ioctl(VIDIOC_G_FMT, format) != 0) { | 1628 if (device_->Ioctl(VIDIOC_G_FMT, format) != 0) { |
1625 if (errno == EINVAL) { | 1629 if (errno == EINVAL) { |
1626 // EINVAL means we haven't seen sufficient stream to decode the format. | 1630 // EINVAL means we haven't seen sufficient stream to decode the format. |
1627 *again = true; | 1631 *again = true; |
1628 return true; | 1632 return true; |
1629 } else { | 1633 } else { |
1630 PLOG(ERROR) << __func__ << "(): ioctl() failed: VIDIOC_G_FMT"; | 1634 PLOG(ERROR) << __func__ << "(): ioctl() failed: VIDIOC_G_FMT"; |
1631 NOTIFY_ERROR(PLATFORM_FAILURE); | 1635 NOTIFY_ERROR(PLATFORM_FAILURE); |
1632 return false; | 1636 return false; |
1633 } | 1637 } |
1634 } | 1638 } |
1635 | 1639 |
1636 // Make sure we are still getting the format we set on initialization. | 1640 // Make sure we are still getting the format we set on initialization. |
1637 if (format->fmt.pix_mp.pixelformat != output_format_fourcc_) { | 1641 if (format->fmt.pix_mp.pixelformat != output_format_fourcc_) { |
1638 LOG(ERROR) << "Unexpected format from G_FMT on output"; | 1642 LOG(ERROR) << "Unexpected format from G_FMT on output"; |
1639 return false; | 1643 return false; |
1640 } | 1644 } |
1641 | 1645 |
| 1646 gfx::Size coded_size(format->fmt.pix_mp.width, format->fmt.pix_mp.height); |
| 1647 if (!GetVisibleSize(coded_size, visible_size)) |
| 1648 *visible_size = coded_size; |
| 1649 |
1642 return true; | 1650 return true; |
1643 } | 1651 } |
1644 | 1652 |
1645 bool V4L2VideoDecodeAccelerator::CreateBuffersForFormat( | 1653 bool V4L2VideoDecodeAccelerator::CreateBuffersForFormat( |
1646 const struct v4l2_format& format) { | 1654 const struct v4l2_format& format, |
| 1655 const gfx::Size& visible_size) { |
1647 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1656 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
1648 output_planes_count_ = format.fmt.pix_mp.num_planes; | 1657 output_planes_count_ = format.fmt.pix_mp.num_planes; |
1649 frame_buffer_size_.SetSize( | 1658 coded_size_.SetSize(format.fmt.pix_mp.width, format.fmt.pix_mp.height); |
1650 format.fmt.pix_mp.width, format.fmt.pix_mp.height); | 1659 visible_size_ = visible_size; |
1651 DVLOG(3) << "CreateBuffersForFormat(): new resolution: " | 1660 DVLOG(3) << "CreateBuffersForFormat(): new resolution: " |
1652 << frame_buffer_size_.ToString(); | 1661 << coded_size_.ToString(); |
1653 | 1662 |
1654 if (!CreateOutputBuffers()) | 1663 if (!CreateOutputBuffers()) |
1655 return false; | 1664 return false; |
1656 | 1665 |
1657 return true; | 1666 return true; |
1658 } | 1667 } |
1659 | 1668 |
| 1669 bool V4L2VideoDecodeAccelerator::GetVisibleSize(const gfx::Size& coded_size, |
| 1670 gfx::Size* visible_size) { |
| 1671 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 1672 |
| 1673 struct v4l2_crop crop_arg; |
| 1674 memset(&crop_arg, 0, sizeof(crop_arg)); |
| 1675 crop_arg.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 1676 |
| 1677 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_G_CROP, &crop_arg); |
| 1678 |
| 1679 gfx::Rect rect(crop_arg.c.left, crop_arg.c.top, crop_arg.c.width, |
| 1680 crop_arg.c.height); |
| 1681 DVLOG(3) << "visible rectangle is " << rect.ToString(); |
| 1682 if (!gfx::Rect(coded_size).Contains(rect)) { |
| 1683 DLOG(ERROR) << "visible rectangle " << rect.ToString() |
| 1684 << " is not inside coded size " << coded_size.ToString(); |
| 1685 return false; |
| 1686 } |
| 1687 if (rect.IsEmpty()) { |
| 1688 DLOG(ERROR) << "visible size is empty"; |
| 1689 return false; |
| 1690 } |
| 1691 |
| 1692 // Chrome assume picture frame is coded at (0, 0). |
| 1693 if (!rect.origin().IsOrigin()) { |
| 1694 DLOG(ERROR) << "Unexpected visible rectangle " << rect.ToString() |
| 1695 << ", top-left is not origin"; |
| 1696 return false; |
| 1697 } |
| 1698 *visible_size = rect.size(); |
| 1699 |
| 1700 return true; |
| 1701 } |
| 1702 |
1660 bool V4L2VideoDecodeAccelerator::CreateInputBuffers() { | 1703 bool V4L2VideoDecodeAccelerator::CreateInputBuffers() { |
1661 DVLOG(3) << "CreateInputBuffers()"; | 1704 DVLOG(3) << "CreateInputBuffers()"; |
1662 // We always run this as we prepare to initialize. | 1705 // We always run this as we prepare to initialize. |
1663 DCHECK_EQ(decoder_state_, kUninitialized); | 1706 DCHECK_EQ(decoder_state_, kUninitialized); |
1664 DCHECK(!input_streamon_); | 1707 DCHECK(!input_streamon_); |
1665 DCHECK(input_buffer_map_.empty()); | 1708 DCHECK(input_buffer_map_.empty()); |
1666 | 1709 |
1667 struct v4l2_requestbuffers reqbufs; | 1710 struct v4l2_requestbuffers reqbufs; |
1668 memset(&reqbufs, 0, sizeof(reqbufs)); | 1711 memset(&reqbufs, 0, sizeof(reqbufs)); |
1669 reqbufs.count = kInputBufferCount; | 1712 reqbufs.count = kInputBufferCount; |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1779 memset(&reqbufs, 0, sizeof(reqbufs)); | 1822 memset(&reqbufs, 0, sizeof(reqbufs)); |
1780 reqbufs.count = output_dpb_size_ + kDpbOutputBufferExtraCount; | 1823 reqbufs.count = output_dpb_size_ + kDpbOutputBufferExtraCount; |
1781 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1824 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
1782 reqbufs.memory = V4L2_MEMORY_MMAP; | 1825 reqbufs.memory = V4L2_MEMORY_MMAP; |
1783 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs); | 1826 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs); |
1784 | 1827 |
1785 output_buffer_map_.resize(reqbufs.count); | 1828 output_buffer_map_.resize(reqbufs.count); |
1786 | 1829 |
1787 DVLOG(3) << "CreateOutputBuffers(): ProvidePictureBuffers(): " | 1830 DVLOG(3) << "CreateOutputBuffers(): ProvidePictureBuffers(): " |
1788 << "buffer_count=" << output_buffer_map_.size() | 1831 << "buffer_count=" << output_buffer_map_.size() |
1789 << ", width=" << frame_buffer_size_.width() | 1832 << ", coded_size=" << coded_size_.ToString(); |
1790 << ", height=" << frame_buffer_size_.height(); | |
1791 child_message_loop_proxy_->PostTask(FROM_HERE, | 1833 child_message_loop_proxy_->PostTask(FROM_HERE, |
1792 base::Bind(&Client::ProvidePictureBuffers, | 1834 base::Bind(&Client::ProvidePictureBuffers, |
1793 client_, | 1835 client_, |
1794 output_buffer_map_.size(), | 1836 output_buffer_map_.size(), |
1795 frame_buffer_size_, | 1837 coded_size_, |
1796 device_->GetTextureTarget())); | 1838 device_->GetTextureTarget())); |
1797 | 1839 |
1798 // Wait for the client to call AssignPictureBuffers() on the Child thread. | 1840 // Wait for the client to call AssignPictureBuffers() on the Child thread. |
1799 // We do this, because if we continue decoding without finishing buffer | 1841 // We do this, because if we continue decoding without finishing buffer |
1800 // allocation, we may end up Resetting before AssignPictureBuffers arrives, | 1842 // allocation, we may end up Resetting before AssignPictureBuffers arrives, |
1801 // resulting in unnecessary complications and subtle bugs. | 1843 // resulting in unnecessary complications and subtle bugs. |
1802 // For example, if the client calls Decode(Input1), Reset(), Decode(Input2) | 1844 // For example, if the client calls Decode(Input1), Reset(), Decode(Input2) |
1803 // in a sequence, and Decode(Input1) results in us getting here and exiting | 1845 // in a sequence, and Decode(Input1) results in us getting here and exiting |
1804 // without waiting, we might end up running Reset{,Done}Task() before | 1846 // without waiting, we might end up running Reset{,Done}Task() before |
1805 // AssignPictureBuffers is scheduled, thus cleaning up and pushing buffers | 1847 // AssignPictureBuffers is scheduled, thus cleaning up and pushing buffers |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1958 struct v4l2_control ctrl; | 2000 struct v4l2_control ctrl; |
1959 memset(&ctrl, 0, sizeof(ctrl)); | 2001 memset(&ctrl, 0, sizeof(ctrl)); |
1960 ctrl.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE; | 2002 ctrl.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE; |
1961 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_G_CTRL, &ctrl); | 2003 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_G_CTRL, &ctrl); |
1962 if (ctrl.value != output_dpb_size_) { | 2004 if (ctrl.value != output_dpb_size_) { |
1963 DVLOG(3) | 2005 DVLOG(3) |
1964 << "IsResolutionChangeNecessary(): Returning true since DPB mismatch "; | 2006 << "IsResolutionChangeNecessary(): Returning true since DPB mismatch "; |
1965 return true; | 2007 return true; |
1966 } | 2008 } |
1967 struct v4l2_format format; | 2009 struct v4l2_format format; |
| 2010 gfx::Size visible_size; |
1968 bool again = false; | 2011 bool again = false; |
1969 bool ret = GetFormatInfo(&format, &again); | 2012 bool ret = GetFormatInfo(&format, &visible_size, &again); |
1970 if (!ret || again) { | 2013 if (!ret || again) { |
1971 DVLOG(3) << "IsResolutionChangeNecessary(): GetFormatInfo() failed"; | 2014 DVLOG(3) << "IsResolutionChangeNecessary(): GetFormatInfo() failed"; |
1972 return false; | 2015 return false; |
1973 } | 2016 } |
1974 gfx::Size new_size(base::checked_cast<int>(format.fmt.pix_mp.width), | 2017 gfx::Size new_coded_size(base::checked_cast<int>(format.fmt.pix_mp.width), |
1975 base::checked_cast<int>(format.fmt.pix_mp.height)); | 2018 base::checked_cast<int>(format.fmt.pix_mp.height)); |
1976 if (frame_buffer_size_ != new_size) { | 2019 if (coded_size_ != new_coded_size) { |
1977 DVLOG(3) << "IsResolutionChangeNecessary(): Resolution change detected"; | 2020 DVLOG(3) << "IsResolutionChangeNecessary(): Resolution change detected"; |
1978 return true; | 2021 return true; |
1979 } | 2022 } |
1980 return false; | 2023 return false; |
1981 } | 2024 } |
1982 | 2025 |
1983 } // namespace content | 2026 } // namespace content |
OLD | NEW |