Commit ea271994 authored by Hirokazu Honda's avatar Hirokazu Honda Committed by Commit Bot

media/gpu/v4l2IP: Factorize code to apply visible rectangle to v4l2 queue

Bug: 1033799
Test: ip_test on kukui
Test: appr.tc on kukui
Change-Id: I475f526f8d39535cfe0be696e657b27b82cc135b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2102303
Commit-Queue: Hirokazu Honda <hiroh@chromium.org>
Reviewed-by: default avatarAlexandre Courbot <acourbot@chromium.org>
Cr-Commit-Position: refs/heads/master@{#754827}
parent 4f59ba09
......@@ -44,6 +44,17 @@ namespace media {
namespace {
enum v4l2_buf_type ToSingleV4L2Planar(enum v4l2_buf_type type) {
switch (type) {
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
return V4L2_BUF_TYPE_VIDEO_OUTPUT;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
return V4L2_BUF_TYPE_VIDEO_CAPTURE;
default:
return type;
}
}
base::Optional<gfx::GpuMemoryBufferHandle> CreateHandle(
const VideoFrame* frame) {
gfx::GpuMemoryBufferHandle handle = CreateGpuMemoryBufferHandle(frame);
......@@ -84,15 +95,6 @@ void FillV4L2BufferByGpuMemoryBufferHandle(
}
}
struct v4l2_rect ToV4L2Rect(const gfx::Rect& visible_rect) {
struct v4l2_rect rect;
rect.left = base::checked_cast<__u32>(visible_rect.x());
rect.top = base::checked_cast<__u32>(visible_rect.y());
rect.width = base::checked_cast<__u32>(visible_rect.width());
rect.height = base::checked_cast<__u32>(visible_rect.height());
return rect;
}
bool AllocateV4L2Buffers(V4L2Queue* queue,
size_t num_buffers,
v4l2_memory memory_type) {
......@@ -594,6 +596,52 @@ void V4L2ImageProcessorBackend::Reset() {
running_jobs_ = {};
}
bool V4L2ImageProcessorBackend::ApplyCrop(const gfx::Rect& visible_rect,
enum v4l2_buf_type type) {
DCHECK(V4L2_TYPE_IS_MULTIPLANAR(type));
struct v4l2_rect rect {};
rect.left = visible_rect.x();
rect.top = visible_rect.y();
rect.width = visible_rect.width();
rect.height = visible_rect.height();
struct v4l2_selection selection_arg {};
// Multiplanar buffer types are messed up in S_SELECTION API, so all drivers
// don't necessarily work with MPLANE types. This issue is resolved with
// kernel 4.13. As we use kernel < 4.13 today, we use single planar buffer
// types. See
// https://linuxtv.org/downloads/v4l-dvb-apis/uapi/v4l/vidioc-g-selection.html.
selection_arg.type = ToSingleV4L2Planar(type);
selection_arg.target =
V4L2_TYPE_IS_OUTPUT(type) ? V4L2_SEL_TGT_CROP : V4L2_SEL_TGT_COMPOSE;
selection_arg.r = rect;
if (device_->Ioctl(VIDIOC_S_SELECTION, &selection_arg) == 0) {
DVLOGF(2) << "VIDIOC_S_SELECTION is supported";
rect = selection_arg.r;
} else {
DVLOGF(2) << "Fallback to VIDIOC_S/G_CROP";
struct v4l2_crop crop {};
crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
crop.c = rect;
if (device_->Ioctl(VIDIOC_S_CROP, &crop) != 0) {
VPLOGF(1) << "VIDIOC_S_CROP failed: ";
return false;
}
rect = crop.c;
}
const gfx::Rect adjusted_visible_rect(rect.left, rect.top, rect.width,
rect.height);
if (visible_rect != adjusted_visible_rect) {
VLOGF(1) << "Unsupported visible rectangle: " << visible_rect.ToString()
<< ", the rectangle adjusted by the driver: "
<< adjusted_visible_rect.ToString();
return false;
}
return true;
}
bool V4L2ImageProcessorBackend::CreateInputBuffers() {
VLOGF(2);
DCHECK_CALLED_ON_VALID_SEQUENCE(backend_sequence_checker_);
......@@ -621,20 +669,9 @@ bool V4L2ImageProcessorBackend::CreateInputBuffers() {
if (device_->Ioctl(VIDIOC_S_CTRL, &control) != 0)
DVLOGF(4) << "V4L2_CID_ALPHA_COMPONENT is not supported";
struct v4l2_rect visible_rect = ToV4L2Rect(input_config_.visible_rect);
struct v4l2_selection selection_arg;
memset(&selection_arg, 0, sizeof(selection_arg));
selection_arg.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
selection_arg.target = V4L2_SEL_TGT_CROP;
selection_arg.r = visible_rect;
if (device_->Ioctl(VIDIOC_S_SELECTION, &selection_arg) != 0) {
VLOGF(2) << "Fallback to VIDIOC_S_CROP for input buffers.";
struct v4l2_crop crop;
memset(&crop, 0, sizeof(crop));
crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
crop.c = visible_rect;
IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_CROP, &crop);
if (!ApplyCrop(input_config_.visible_rect, V4L2_BUF_TYPE_VIDEO_OUTPUT)) {
VLOGF(2) << "Failed to apply crop to input queue";
return false;
}
input_queue_ = device_->GetQueue(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
......@@ -647,19 +684,8 @@ bool V4L2ImageProcessorBackend::CreateOutputBuffers() {
DCHECK_CALLED_ON_VALID_SEQUENCE(backend_sequence_checker_);
DCHECK_EQ(output_queue_, nullptr);
struct v4l2_rect visible_rect = ToV4L2Rect(output_config_.visible_rect);
struct v4l2_selection selection_arg;
memset(&selection_arg, 0, sizeof(selection_arg));
selection_arg.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
selection_arg.target = V4L2_SEL_TGT_COMPOSE;
selection_arg.r = visible_rect;
if (device_->Ioctl(VIDIOC_S_SELECTION, &selection_arg) != 0) {
VLOGF(2) << "Fallback to VIDIOC_S_CROP for output buffers.";
struct v4l2_crop crop;
memset(&crop, 0, sizeof(crop));
crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
crop.c = visible_rect;
IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_CROP, &crop);
if (!ApplyCrop(output_config_.visible_rect, V4L2_BUF_TYPE_VIDEO_CAPTURE)) {
return false;
}
output_queue_ = device_->GetQueue(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
......
......@@ -133,10 +133,12 @@ class MEDIA_GPU_EXPORT V4L2ImageProcessorBackend
bool EnqueueOutputRecord(JobRecord* job_record, V4L2WritableBufferRef buffer);
bool CreateInputBuffers();
bool CreateOutputBuffers();
// Specify |visible_rect| to v4l2 |type| queue.
bool ApplyCrop(const gfx::Rect& visible_rect, enum v4l2_buf_type type);
// Callback of VideoFrame destruction. Since VideoFrame destruction callback
// might be executed on any sequence, we use a thunk to post the task to
// |device_task_runner_|.
// Callback of VideoFrame destruction. Since VideoFrame destruction
// callback might be executed on any sequence, we use a thunk to post the
// task to |device_task_runner_|.
static void V4L2VFRecycleThunk(
scoped_refptr<base::SequencedTaskRunner> task_runner,
base::Optional<base::WeakPtr<V4L2ImageProcessorBackend>> image_processor,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment