Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / media / capture / video / linux / v4l2_capture_delegate_multi_plane.cc
blob6aab0de49cf61d0d95519ac6aa80af7fceba7ae3
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
3 // found in the LICENSE file.
5 #include "media/capture/video/linux/v4l2_capture_delegate_multi_plane.h"
7 #include <sys/mman.h>
9 namespace media {
11 V4L2CaptureDelegateMultiPlane::V4L2CaptureDelegateMultiPlane(
12 const VideoCaptureDevice::Name& device_name,
13 const scoped_refptr<base::SingleThreadTaskRunner>& v4l2_task_runner,
14 int power_line_frequency)
15 : V4L2CaptureDelegate(device_name, v4l2_task_runner, power_line_frequency) {
18 V4L2CaptureDelegateMultiPlane::~V4L2CaptureDelegateMultiPlane() {
21 scoped_refptr<V4L2CaptureDelegate::BufferTracker>
22 V4L2CaptureDelegateMultiPlane::CreateBufferTracker() const {
23 return make_scoped_refptr(new BufferTrackerMPlane());
26 bool V4L2CaptureDelegateMultiPlane::FillV4L2Format(
27 v4l2_format* format,
28 uint32_t width,
29 uint32_t height,
30 uint32_t pixelformat_fourcc) const {
31 format->fmt.pix_mp.width = width;
32 format->fmt.pix_mp.height = height;
33 format->fmt.pix_mp.pixelformat = pixelformat_fourcc;
35 const size_t num_v4l2_planes =
36 V4L2CaptureDelegate::GetNumPlanesForFourCc(pixelformat_fourcc);
37 if (num_v4l2_planes == 0u)
38 return false;
39 DCHECK_LE(num_v4l2_planes, static_cast<size_t>(VIDEO_MAX_PLANES));
40 format->fmt.pix_mp.num_planes = num_v4l2_planes;
42 v4l2_planes_.resize(num_v4l2_planes);
43 return true;
46 void V4L2CaptureDelegateMultiPlane::FinishFillingV4L2Buffer(
47 v4l2_buffer* buffer) const {
48 buffer->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
49 buffer->length = v4l2_planes_.size();
51 static const struct v4l2_plane empty_plane = {};
52 std::fill(v4l2_planes_.begin(), v4l2_planes_.end(), empty_plane);
53 buffer->m.planes = v4l2_planes_.data();
56 void V4L2CaptureDelegateMultiPlane::SetPayloadSize(
57 const scoped_refptr<BufferTracker>& buffer_tracker,
58 const v4l2_buffer& buffer) const {
59 for (size_t i = 0; i < v4l2_planes_.size() && i < buffer.length; i++)
60 buffer_tracker->SetPlanePayloadSize(i, buffer.m.planes[i].bytesused);
63 void V4L2CaptureDelegateMultiPlane::SendBuffer(
64 const scoped_refptr<BufferTracker>& buffer_tracker,
65 const v4l2_format& format) const {
66 DCHECK_EQ(capture_format().pixel_format, PIXEL_FORMAT_I420);
67 const size_t y_stride = format.fmt.pix_mp.plane_fmt[0].bytesperline;
68 const size_t u_stride = format.fmt.pix_mp.plane_fmt[1].bytesperline;
69 const size_t v_stride = format.fmt.pix_mp.plane_fmt[2].bytesperline;
70 DCHECK_GE(y_stride, 1u * capture_format().frame_size.width());
71 DCHECK_GE(u_stride, 1u * capture_format().frame_size.width() / 2);
72 DCHECK_GE(v_stride, 1u * capture_format().frame_size.width() / 2);
73 client()->OnIncomingCapturedYuvData(
74 buffer_tracker->GetPlaneStart(0), buffer_tracker->GetPlaneStart(1),
75 buffer_tracker->GetPlaneStart(2), y_stride, u_stride, v_stride,
76 capture_format(), rotation(), base::TimeTicks::Now());
79 bool V4L2CaptureDelegateMultiPlane::BufferTrackerMPlane::Init(
80 int fd,
81 const v4l2_buffer& buffer) {
82 for (size_t p = 0; p < buffer.length; ++p) {
83 // Some devices require mmap() to be called with both READ and WRITE.
84 // See http://crbug.com/178582.
85 void* const start =
86 mmap(NULL, buffer.m.planes[p].length, PROT_READ | PROT_WRITE,
87 MAP_SHARED, fd, buffer.m.planes[p].m.mem_offset);
88 if (start == MAP_FAILED) {
89 DLOG(ERROR) << "Error mmap()ing a V4L2 buffer into userspace";
90 return false;
92 AddMmapedPlane(static_cast<uint8_t*>(start), buffer.m.planes[p].length);
93 DVLOG(3) << "Mmap()ed plane #" << p << " of " << buffer.m.planes[p].length
94 << "B";
96 return true;
99 } // namespace media