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"
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(
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)
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
);
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(
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.
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";
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