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, ...@@ -881,6 +881,17 @@ base::Optional<struct v4l2_format> V4L2Queue::SetFormat(uint32_t fourcc,
return current_format_; 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) { size_t V4L2Queue::AllocateBuffers(size_t count, enum v4l2_memory memory) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!free_buffers_); DCHECK(!free_buffers_);
...@@ -906,13 +917,12 @@ size_t V4L2Queue::AllocateBuffers(size_t count, enum v4l2_memory memory) { ...@@ -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 // 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 // output buffers if the number of specified planes does not exactly match the
// format. // format.
struct v4l2_format format = {.type = type_}; base::Optional<v4l2_format> format = GetFormat().first;
int ret = device_->Ioctl(VIDIOC_G_FMT, &format); if (!format) {
if (ret) { VQLOGF(1) << "Cannot get format.";
VPQLOGF(1) << "VIDIOC_G_FMT failed";
return 0; 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)); DCHECK_LE(planes_count_, static_cast<size_t>(VIDEO_MAX_PLANES));
struct v4l2_requestbuffers reqbufs = {}; struct v4l2_requestbuffers reqbufs = {};
...@@ -921,7 +931,7 @@ size_t V4L2Queue::AllocateBuffers(size_t count, enum v4l2_memory memory) { ...@@ -921,7 +931,7 @@ size_t V4L2Queue::AllocateBuffers(size_t count, enum v4l2_memory memory) {
reqbufs.memory = memory; reqbufs.memory = memory;
DVQLOGF(3) << "Requesting " << count << " buffers."; DVQLOGF(3) << "Requesting " << count << " buffers.";
ret = device_->Ioctl(VIDIOC_REQBUFS, &reqbufs); int ret = device_->Ioctl(VIDIOC_REQBUFS, &reqbufs);
if (ret) { if (ret) {
VPQLOGF(1) << "VIDIOC_REQBUFS failed"; VPQLOGF(1) << "VIDIOC_REQBUFS failed";
return 0; return 0;
...@@ -934,7 +944,7 @@ size_t V4L2Queue::AllocateBuffers(size_t count, enum v4l2_memory memory) { ...@@ -934,7 +944,7 @@ size_t V4L2Queue::AllocateBuffers(size_t count, enum v4l2_memory memory) {
// Now query all buffer information. // Now query all buffer information.
for (size_t i = 0; i < reqbufs.count; i++) { 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) { if (!buffer) {
DeallocateBuffers(); DeallocateBuffers();
......
...@@ -293,6 +293,22 @@ class MEDIA_GPU_EXPORT V4L2Queue ...@@ -293,6 +293,22 @@ class MEDIA_GPU_EXPORT V4L2Queue
size_t buffer_size) size_t buffer_size)
WARN_UNUSED_RESULT; 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 // Allocate |count| buffers for the current format of this queue, with a
// specific |memory| allocation, and returns the number of buffers allocated // specific |memory| allocation, and returns the number of buffers allocated
// or zero if an error occurred, or if references to any previously allocated // or zero if an error occurred, or if references to any previously allocated
......
...@@ -649,15 +649,12 @@ bool V4L2SliceVideoDecodeAccelerator::CreateOutputBuffers() { ...@@ -649,15 +649,12 @@ bool V4L2SliceVideoDecodeAccelerator::CreateOutputBuffers() {
// Since VdaVideoDecoder doesn't allocate PictureBuffer with size adjusted by // Since VdaVideoDecoder doesn't allocate PictureBuffer with size adjusted by
// itself, we have to adjust here. // itself, we have to adjust here.
struct v4l2_format format; auto ret = input_queue_->GetFormat().first;
memset(&format, 0, sizeof(format)); if (!ret) {
format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
if (device_->Ioctl(VIDIOC_G_FMT, &format) != 0) {
PLOG(ERROR) << "Failed getting OUTPUT format";
NOTIFY_ERROR(PLATFORM_FAILURE); NOTIFY_ERROR(PLATFORM_FAILURE);
return false; return false;
} }
struct v4l2_format format = std::move(*ret);
format.fmt.pix_mp.width = pic_size.width(); format.fmt.pix_mp.width = pic_size.width();
format.fmt.pix_mp.height = pic_size.height(); format.fmt.pix_mp.height = pic_size.height();
...@@ -669,13 +666,12 @@ bool V4L2SliceVideoDecodeAccelerator::CreateOutputBuffers() { ...@@ -669,13 +666,12 @@ bool V4L2SliceVideoDecodeAccelerator::CreateOutputBuffers() {
} }
// Get the coded size from the CAPTURE queue // Get the coded size from the CAPTURE queue
memset(&format, 0, sizeof(format)); ret = output_queue_->GetFormat().first;
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; if (!ret) {
if (device_->Ioctl(VIDIOC_G_FMT, &format) != 0) {
PLOG(ERROR) << "Failed getting CAPTURE format";
NOTIFY_ERROR(PLATFORM_FAILURE); NOTIFY_ERROR(PLATFORM_FAILURE);
return false; return false;
} }
format = std::move(*ret);
coded_size_.SetSize(base::checked_cast<int>(format.fmt.pix_mp.width), coded_size_.SetSize(base::checked_cast<int>(format.fmt.pix_mp.width),
base::checked_cast<int>(format.fmt.pix_mp.height)); base::checked_cast<int>(format.fmt.pix_mp.height));
......
...@@ -2084,18 +2084,19 @@ bool V4L2VideoDecodeAccelerator::GetFormatInfo(struct v4l2_format* format, ...@@ -2084,18 +2084,19 @@ bool V4L2VideoDecodeAccelerator::GetFormatInfo(struct v4l2_format* format,
DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
*again = false; *again = false;
memset(format, 0, sizeof(*format));
format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; auto ret = output_queue_->GetFormat();
if (device_->Ioctl(VIDIOC_G_FMT, format) != 0) { switch (ret.second) {
if (errno == EINVAL) { case 0:
*format = *ret.first;
break;
case EINVAL:
// EINVAL means we haven't seen sufficient stream to decode the format. // EINVAL means we haven't seen sufficient stream to decode the format.
*again = true; *again = true;
return true; return true;
} else { default:
PLOG(ERROR) << "ioctl() failed: VIDIOC_G_FMT";
NOTIFY_ERROR(PLATFORM_FAILURE); NOTIFY_ERROR(PLATFORM_FAILURE);
return false; return false;
}
} }
// Make sure we are still getting the format we set on initialization. // Make sure we are still getting the format we set on initialization.
......
...@@ -529,13 +529,12 @@ bool V4L2StatelessVideoDecoderBackend::ApplyResolution( ...@@ -529,13 +529,12 @@ bool V4L2StatelessVideoDecoderBackend::ApplyResolution(
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_EQ(input_queue_->QueuedBuffersCount(), 0u); DCHECK_EQ(input_queue_->QueuedBuffersCount(), 0u);
struct v4l2_format format = {}; auto ret = input_queue_->GetFormat().first;
if (!ret) {
format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
if (device_->Ioctl(VIDIOC_G_FMT, &format) != 0) {
VPLOGF(1) << "Failed getting OUTPUT format"; VPLOGF(1) << "Failed getting OUTPUT format";
return false; return false;
} }
struct v4l2_format format = std::move(*ret);
format.fmt.pix_mp.width = pic_size.width(); format.fmt.pix_mp.width = pic_size.width();
format.fmt.pix_mp.height = pic_size.height(); 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