Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(119)

Side by Side Diff: content/common/gpu/media/v4l2_video_decode_accelerator.cc

Issue 836093002: V4L2VDA: Fix format initialization order. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « content/common/gpu/media/v4l2_video_decode_accelerator.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 V4L2_CAP_VIDEO_OUTPUT_MPLANE | 260 V4L2_CAP_VIDEO_OUTPUT_MPLANE |
261 V4L2_CAP_STREAMING; 261 V4L2_CAP_STREAMING;
262 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYCAP, &caps); 262 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYCAP, &caps);
263 if ((caps.capabilities & kCapsRequired) != kCapsRequired) { 263 if ((caps.capabilities & kCapsRequired) != kCapsRequired) {
264 LOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP" 264 LOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP"
265 ", caps check failed: 0x" << std::hex << caps.capabilities; 265 ", caps check failed: 0x" << std::hex << caps.capabilities;
266 NOTIFY_ERROR(PLATFORM_FAILURE); 266 NOTIFY_ERROR(PLATFORM_FAILURE);
267 return false; 267 return false;
268 } 268 }
269 269
270 if (!CreateInputBuffers()) 270 if (!SetupFormats())
271 return false;
272
273 if (!SetupOutputFormat())
274 return false; 271 return false;
275 272
276 // Subscribe to the resolution change event. 273 // Subscribe to the resolution change event.
277 struct v4l2_event_subscription sub; 274 struct v4l2_event_subscription sub;
278 memset(&sub, 0, sizeof(sub)); 275 memset(&sub, 0, sizeof(sub));
279 sub.type = V4L2_EVENT_RESOLUTION_CHANGE; 276 sub.type = V4L2_EVENT_RESOLUTION_CHANGE;
280 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_SUBSCRIBE_EVENT, &sub); 277 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_SUBSCRIBE_EVENT, &sub);
281 278
282 if (video_profile_ >= media::H264PROFILE_MIN && 279 if (video_profile_ >= media::H264PROFILE_MIN &&
283 video_profile_ <= media::H264PROFILE_MAX) { 280 video_profile_ <= media::H264PROFILE_MAX) {
284 decoder_h264_parser_.reset(new media::H264Parser()); 281 decoder_h264_parser_.reset(new media::H264Parser());
285 } 282 }
286 283
284 if (!CreateInputBuffers())
285 return false;
286
287 if (!decoder_thread_.Start()) { 287 if (!decoder_thread_.Start()) {
288 LOG(ERROR) << "Initialize(): decoder thread failed to start"; 288 LOG(ERROR) << "Initialize(): decoder thread failed to start";
289 NOTIFY_ERROR(PLATFORM_FAILURE); 289 NOTIFY_ERROR(PLATFORM_FAILURE);
290 return false; 290 return false;
291 } 291 }
292 292
293 // StartDevicePoll will NOTIFY_ERROR on failure, so IgnoreResult is fine here. 293 // StartDevicePoll will NOTIFY_ERROR on failure, so IgnoreResult is fine here.
294 decoder_thread_.message_loop()->PostTask( 294 decoder_thread_.message_loop()->PostTask(
295 FROM_HERE, 295 FROM_HERE,
296 base::Bind( 296 base::Bind(
(...skipping 1325 matching lines...) Expand 10 before | Expand all | Expand 10 after
1622 // EINVAL means we haven't seen sufficient stream to decode the format. 1622 // EINVAL means we haven't seen sufficient stream to decode the format.
1623 *again = true; 1623 *again = true;
1624 return true; 1624 return true;
1625 } else { 1625 } else {
1626 PLOG(ERROR) << __func__ << "(): ioctl() failed: VIDIOC_G_FMT"; 1626 PLOG(ERROR) << __func__ << "(): ioctl() failed: VIDIOC_G_FMT";
1627 NOTIFY_ERROR(PLATFORM_FAILURE); 1627 NOTIFY_ERROR(PLATFORM_FAILURE);
1628 return false; 1628 return false;
1629 } 1629 }
1630 } 1630 }
1631 1631
1632 // Make sure we are still getting the format we set on initialization.
1633 if (format->fmt.pix_mp.pixelformat != output_format_fourcc_) {
1634 LOG(ERROR) << "Unexpected format from G_FMT on output";
1635 return false;
1636 }
1637
1632 return true; 1638 return true;
1633 } 1639 }
1634 1640
1635 bool V4L2VideoDecodeAccelerator::CreateBuffersForFormat( 1641 bool V4L2VideoDecodeAccelerator::CreateBuffersForFormat(
1636 const struct v4l2_format& format) { 1642 const struct v4l2_format& format) {
1637 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); 1643 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1638 output_planes_count_ = format.fmt.pix_mp.num_planes; 1644 output_planes_count_ = format.fmt.pix_mp.num_planes;
1639 frame_buffer_size_.SetSize( 1645 frame_buffer_size_.SetSize(
1640 format.fmt.pix_mp.width, format.fmt.pix_mp.height); 1646 format.fmt.pix_mp.width, format.fmt.pix_mp.height);
1641 DVLOG(3) << "CreateBuffersForFormat(): new resolution: " 1647 DVLOG(3) << "CreateBuffersForFormat(): new resolution: "
1642 << frame_buffer_size_.ToString(); 1648 << frame_buffer_size_.ToString();
1643 1649
1644 if (!CreateOutputBuffers()) 1650 if (!CreateOutputBuffers())
1645 return false; 1651 return false;
1646 1652
1647 return true; 1653 return true;
1648 } 1654 }
1649 1655
1650 bool V4L2VideoDecodeAccelerator::CreateInputBuffers() { 1656 bool V4L2VideoDecodeAccelerator::CreateInputBuffers() {
1651 DVLOG(3) << "CreateInputBuffers()"; 1657 DVLOG(3) << "CreateInputBuffers()";
1652 // We always run this as we prepare to initialize. 1658 // We always run this as we prepare to initialize.
1653 DCHECK_EQ(decoder_state_, kUninitialized); 1659 DCHECK_EQ(decoder_state_, kUninitialized);
1654 DCHECK(!input_streamon_); 1660 DCHECK(!input_streamon_);
1655 DCHECK(input_buffer_map_.empty()); 1661 DCHECK(input_buffer_map_.empty());
1656 1662
1657 __u32 pixelformat = V4L2Device::VideoCodecProfileToV4L2PixFmt(video_profile_);
1658 if (!pixelformat) {
1659 NOTREACHED();
1660 return false;
1661 }
1662
1663 struct v4l2_format format;
1664 memset(&format, 0, sizeof(format));
1665 format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1666 format.fmt.pix_mp.pixelformat = pixelformat;
1667 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
1668 switches::kIgnoreResolutionLimitsForAcceleratedVideoDecode))
1669 format.fmt.pix_mp.plane_fmt[0].sizeimage = kInputBufferMaxSizeFor4k;
1670 else
1671 format.fmt.pix_mp.plane_fmt[0].sizeimage = kInputBufferMaxSizeFor1080p;
1672 format.fmt.pix_mp.num_planes = 1;
1673 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_FMT, &format);
1674
1675 struct v4l2_requestbuffers reqbufs; 1663 struct v4l2_requestbuffers reqbufs;
1676 memset(&reqbufs, 0, sizeof(reqbufs)); 1664 memset(&reqbufs, 0, sizeof(reqbufs));
1677 reqbufs.count = kInputBufferCount; 1665 reqbufs.count = kInputBufferCount;
1678 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 1666 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1679 reqbufs.memory = V4L2_MEMORY_MMAP; 1667 reqbufs.memory = V4L2_MEMORY_MMAP;
1680 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs); 1668 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs);
1681 input_buffer_map_.resize(reqbufs.count); 1669 input_buffer_map_.resize(reqbufs.count);
1682 for (size_t i = 0; i < input_buffer_map_.size(); ++i) { 1670 for (size_t i = 0; i < input_buffer_map_.size(); ++i) {
1683 free_input_buffers_.push_back(i); 1671 free_input_buffers_.push_back(i);
1684 1672
(...skipping 17 matching lines...) Expand all
1702 PLOG(ERROR) << "CreateInputBuffers(): mmap() failed"; 1690 PLOG(ERROR) << "CreateInputBuffers(): mmap() failed";
1703 return false; 1691 return false;
1704 } 1692 }
1705 input_buffer_map_[i].address = address; 1693 input_buffer_map_[i].address = address;
1706 input_buffer_map_[i].length = buffer.m.planes[0].length; 1694 input_buffer_map_[i].length = buffer.m.planes[0].length;
1707 } 1695 }
1708 1696
1709 return true; 1697 return true;
1710 } 1698 }
1711 1699
1712 bool V4L2VideoDecodeAccelerator::SetupOutputFormat() { 1700 bool V4L2VideoDecodeAccelerator::SetupFormats() {
1713 // We have to set up the format for output beforehand, because the driver may 1701 // We always run this as we prepare to initialize.
1714 // not allow changing it once we start streaming; whether it can support our 1702 DCHECK_EQ(decoder_state_, kUninitialized);
1715 // chosen output format or not may depend on the input format. 1703 DCHECK(!input_streamon_);
1704 DCHECK(!output_streamon_);
1705
1706 __u32 input_format_fourcc =
1707 V4L2Device::VideoCodecProfileToV4L2PixFmt(video_profile_);
1708 if (!input_format_fourcc) {
1709 NOTREACHED();
1710 return false;
1711 }
1712
1713 size_t input_size;
1714 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
1715 switches::kIgnoreResolutionLimitsForAcceleratedVideoDecode))
1716 input_size = kInputBufferMaxSizeFor4k;
1717 else
1718 input_size = kInputBufferMaxSizeFor1080p;
1719
1720 struct v4l2_format format;
1721 memset(&format, 0, sizeof(format));
1722 format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1723 format.fmt.pix_mp.pixelformat = input_format_fourcc;
1724 format.fmt.pix_mp.plane_fmt[0].sizeimage = input_size;
1725 format.fmt.pix_mp.num_planes = 1;
1726 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_FMT, &format);
1727
1728 // We have to set up the format for output, because the driver may not allow
1729 // changing it once we start streaming; whether it can support our chosen
1730 // output format or not may depend on the input format.
1716 struct v4l2_fmtdesc fmtdesc; 1731 struct v4l2_fmtdesc fmtdesc;
1717 memset(&fmtdesc, 0, sizeof(fmtdesc)); 1732 memset(&fmtdesc, 0, sizeof(fmtdesc));
1718 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1733 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1719 while (device_->Ioctl(VIDIOC_ENUM_FMT, &fmtdesc) == 0) { 1734 while (device_->Ioctl(VIDIOC_ENUM_FMT, &fmtdesc) == 0) {
1720 if (device_->CanCreateEGLImageFrom(fmtdesc.pixelformat)) { 1735 if (device_->CanCreateEGLImageFrom(fmtdesc.pixelformat)) {
1721 output_format_fourcc_ = fmtdesc.pixelformat; 1736 output_format_fourcc_ = fmtdesc.pixelformat;
1722 break; 1737 break;
1723 } 1738 }
1724 ++fmtdesc.index; 1739 ++fmtdesc.index;
1725 } 1740 }
1726 1741
1727 if (output_format_fourcc_ == 0) { 1742 if (output_format_fourcc_ == 0) {
1728 LOG(ERROR) << "Could not find a usable output format"; 1743 LOG(ERROR) << "Could not find a usable output format";
1729 return false; 1744 return false;
1730 } 1745 }
1731 1746
1732 // Just set the fourcc for output; resolution, etc., will come from the 1747 // Just set the fourcc for output; resolution, etc., will come from the
1733 // driver once it extracts it from the stream. 1748 // driver once it extracts it from the stream.
1734 struct v4l2_format format;
1735 memset(&format, 0, sizeof(format)); 1749 memset(&format, 0, sizeof(format));
1736 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1750 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1737 format.fmt.pix_mp.pixelformat = output_format_fourcc_; 1751 format.fmt.pix_mp.pixelformat = output_format_fourcc_;
1738 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_FMT, &format); 1752 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_FMT, &format);
1739 1753
1740 return true; 1754 return true;
1741 } 1755 }
1742 1756
1743 bool V4L2VideoDecodeAccelerator::CreateOutputBuffers() { 1757 bool V4L2VideoDecodeAccelerator::CreateOutputBuffers() {
1744 DVLOG(3) << "CreateOutputBuffers()"; 1758 DVLOG(3) << "CreateOutputBuffers()";
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
1956 gfx::Size new_size(base::checked_cast<int>(format.fmt.pix_mp.width), 1970 gfx::Size new_size(base::checked_cast<int>(format.fmt.pix_mp.width),
1957 base::checked_cast<int>(format.fmt.pix_mp.height)); 1971 base::checked_cast<int>(format.fmt.pix_mp.height));
1958 if (frame_buffer_size_ != new_size) { 1972 if (frame_buffer_size_ != new_size) {
1959 DVLOG(3) << "IsResolutionChangeNecessary(): Resolution change detected"; 1973 DVLOG(3) << "IsResolutionChangeNecessary(): Resolution change detected";
1960 return true; 1974 return true;
1961 } 1975 }
1962 return false; 1976 return false;
1963 } 1977 }
1964 1978
1965 } // namespace content 1979 } // namespace content
OLDNEW
« no previous file with comments | « content/common/gpu/media/v4l2_video_decode_accelerator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698