Commit 2b1b0cc6 authored by Alexandre Courbot's avatar Alexandre Courbot Committed by Commit Bot

media/gpu/v4l2: add and use V4L2Queue::GetFormat()

Getting the currently set format on a queue is a frequent operation. Add
a dedicated method for this so we can factorize the code across the
various users.

BUG=b:149663704
TEST=vdatest passing on Kukui.
TEST=vdatest passing on Hana.

Change-Id: Ie98b86db7a40d277adaab04703327340c61dfddf
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2131430
Commit-Queue: Alexandre Courbot <acourbot@chromium.org>
Reviewed-by: default avatarChih-Yu Huang <akahuang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#756156}
parent 3f769d3c
......@@ -881,6 +881,17 @@ base::Optional<struct v4l2_format> V4L2Queue::SetFormat(uint32_t fourcc,
return current_format_;
}
std::pair<base::Optional<struct v4l2_format>, int> V4L2Queue::GetFormat() {
struct v4l2_format format = {};
format.type = type_;
if (device_->Ioctl(VIDIOC_G_FMT, &format) != 0) {
VPQLOGF(2) << "Failed to get format";
return std::make_pair(base::nullopt, errno);
}
return std::make_pair(format, 0);
}
size_t V4L2Queue::AllocateBuffers(size_t count, enum v4l2_memory memory) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!free_buffers_);
......@@ -906,13 +917,12 @@ size_t V4L2Queue::AllocateBuffers(size_t count, enum v4l2_memory memory) {
// This should not be required, but Tegra's VIDIOC_QUERYBUF will fail on
// output buffers if the number of specified planes does not exactly match the
// format.
struct v4l2_format format = {.type = type_};
int ret = device_->Ioctl(VIDIOC_G_FMT, &format);
if (ret) {
VPQLOGF(1) << "VIDIOC_G_FMT failed";
base::Optional<v4l2_format> format = GetFormat().first;
if (!format) {
VQLOGF(1) << "Cannot get format.";
return 0;
}
planes_count_ = format.fmt.pix_mp.num_planes;
planes_count_ = format->fmt.pix_mp.num_planes;
DCHECK_LE(planes_count_, static_cast<size_t>(VIDEO_MAX_PLANES));
struct v4l2_requestbuffers reqbufs = {};
......@@ -921,7 +931,7 @@ size_t V4L2Queue::AllocateBuffers(size_t count, enum v4l2_memory memory) {
reqbufs.memory = memory;
DVQLOGF(3) << "Requesting " << count << " buffers.";
ret = device_->Ioctl(VIDIOC_REQBUFS, &reqbufs);
int ret = device_->Ioctl(VIDIOC_REQBUFS, &reqbufs);
if (ret) {
VPQLOGF(1) << "VIDIOC_REQBUFS failed";
return 0;
......@@ -934,7 +944,7 @@ size_t V4L2Queue::AllocateBuffers(size_t count, enum v4l2_memory memory) {
// Now query all buffer information.
for (size_t i = 0; i < reqbufs.count; i++) {
auto buffer = V4L2Buffer::Create(device_, type_, memory_, format, i);
auto buffer = V4L2Buffer::Create(device_, type_, memory_, *format, i);
if (!buffer) {
DeallocateBuffers();
......
......@@ -293,6 +293,22 @@ class MEDIA_GPU_EXPORT V4L2Queue
size_t buffer_size)
WARN_UNUSED_RESULT;
// Returns the currently set format on the queue. The result is returned as
// a std::pair where the first member is the format, or base::nullopt if the
// format could not be obtained due to an ioctl error. The second member is
// only used in case of an error and contains the |errno| set by the failing
// ioctl. If the first member is not base::nullopt, the second member will
// always be zero.
//
// If the second member is 0, then the first member is guaranteed to have
// a valid value. So clients that are not interested in the precise error
// message can just check that the first member is valid and go on.
//
// This pair is used because not all failures to get the format are
// necessarily errors, so we need to way to let the use decide whether it
// is one or not.
std::pair<base::Optional<struct v4l2_format>, int> GetFormat();
// Allocate |count| buffers for the current format of this queue, with a
// specific |memory| allocation, and returns the number of buffers allocated
// or zero if an error occurred, or if references to any previously allocated
......
......@@ -649,15 +649,12 @@ bool V4L2SliceVideoDecodeAccelerator::CreateOutputBuffers() {
// Since VdaVideoDecoder doesn't allocate PictureBuffer with size adjusted by
// itself, we have to adjust here.
struct v4l2_format format;
memset(&format, 0, sizeof(format));
format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
if (device_->Ioctl(VIDIOC_G_FMT, &format) != 0) {
PLOG(ERROR) << "Failed getting OUTPUT format";
auto ret = input_queue_->GetFormat().first;
if (!ret) {
NOTIFY_ERROR(PLATFORM_FAILURE);
return false;
}
struct v4l2_format format = std::move(*ret);
format.fmt.pix_mp.width = pic_size.width();
format.fmt.pix_mp.height = pic_size.height();
......@@ -669,13 +666,12 @@ bool V4L2SliceVideoDecodeAccelerator::CreateOutputBuffers() {
}
// Get the coded size from the CAPTURE queue
memset(&format, 0, sizeof(format));
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
if (device_->Ioctl(VIDIOC_G_FMT, &format) != 0) {
PLOG(ERROR) << "Failed getting CAPTURE format";
ret = output_queue_->GetFormat().first;
if (!ret) {
NOTIFY_ERROR(PLATFORM_FAILURE);
return false;
}
format = std::move(*ret);
coded_size_.SetSize(base::checked_cast<int>(format.fmt.pix_mp.width),
base::checked_cast<int>(format.fmt.pix_mp.height));
......
......@@ -2084,18 +2084,19 @@ bool V4L2VideoDecodeAccelerator::GetFormatInfo(struct v4l2_format* format,
DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
*again = false;
memset(format, 0, sizeof(*format));
format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
if (device_->Ioctl(VIDIOC_G_FMT, format) != 0) {
if (errno == EINVAL) {
auto ret = output_queue_->GetFormat();
switch (ret.second) {
case 0:
*format = *ret.first;
break;
case EINVAL:
// EINVAL means we haven't seen sufficient stream to decode the format.
*again = true;
return true;
} else {
PLOG(ERROR) << "ioctl() failed: VIDIOC_G_FMT";
default:
NOTIFY_ERROR(PLATFORM_FAILURE);
return false;
}
}
// Make sure we are still getting the format we set on initialization.
......
......@@ -529,13 +529,12 @@ bool V4L2StatelessVideoDecoderBackend::ApplyResolution(
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_EQ(input_queue_->QueuedBuffersCount(), 0u);
struct v4l2_format format = {};
format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
if (device_->Ioctl(VIDIOC_G_FMT, &format) != 0) {
auto ret = input_queue_->GetFormat().first;
if (!ret) {
VPLOGF(1) << "Failed getting OUTPUT format";
return false;
}
struct v4l2_format format = std::move(*ret);
format.fmt.pix_mp.width = pic_size.width();
format.fmt.pix_mp.height = pic_size.height();
......
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