blob: c80fdea610af9c5c46e498f4b6ff9caef72fdb52 [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/gpu/v4l2/v4l2_vda_helpers.h"
#include "media/base/color_plane_layout.h"
#include "media/gpu/chromeos/fourcc.h"
#include "media/gpu/macros.h"
#include "media/gpu/v4l2/v4l2_device.h"
#include "media/gpu/v4l2/v4l2_image_processor.h"
namespace media {
namespace v4l2_vda_helpers {
uint32_t FindImageProcessorInputFormat(V4L2Device* vda_device) {
std::vector<uint32_t> processor_input_formats =
V4L2ImageProcessor::GetSupportedInputFormats();
struct v4l2_fmtdesc fmtdesc = {};
fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
while (vda_device->Ioctl(VIDIOC_ENUM_FMT, &fmtdesc) == 0) {
if (std::find(processor_input_formats.begin(),
processor_input_formats.end(),
fmtdesc.pixelformat) != processor_input_formats.end()) {
DVLOGF(3) << "Image processor input format=" << fmtdesc.description;
return fmtdesc.pixelformat;
}
++fmtdesc.index;
}
return 0;
}
uint32_t FindImageProcessorOutputFormat(V4L2Device* ip_device) {
// Prefer YVU420 and NV12 because ArcGpuVideoDecodeAccelerator only supports
// single physical plane.
static constexpr uint32_t kPreferredFormats[] = {V4L2_PIX_FMT_NV12,
V4L2_PIX_FMT_YVU420};
auto preferred_formats_first = [](uint32_t a, uint32_t b) -> bool {
auto* iter_a = std::find(std::begin(kPreferredFormats),
std::end(kPreferredFormats), a);
auto* iter_b = std::find(std::begin(kPreferredFormats),
std::end(kPreferredFormats), b);
return iter_a < iter_b;
};
std::vector<uint32_t> processor_output_formats =
V4L2ImageProcessor::GetSupportedOutputFormats();
// Move the preferred formats to the front.
std::sort(processor_output_formats.begin(), processor_output_formats.end(),
preferred_formats_first);
for (uint32_t processor_output_format : processor_output_formats) {
if (ip_device->CanCreateEGLImageFrom(processor_output_format)) {
DVLOGF(3) << "Image processor output format=" << processor_output_format;
return processor_output_format;
}
}
return 0;
}
std::unique_ptr<ImageProcessor> CreateImageProcessor(
uint32_t vda_output_format,
uint32_t ip_output_format,
const gfx::Size& vda_output_coded_size,
const gfx::Size& ip_output_coded_size,
const gfx::Size& visible_size,
size_t nb_buffers,
scoped_refptr<V4L2Device> image_processor_device,
ImageProcessor::OutputMode image_processor_output_mode,
scoped_refptr<base::SequencedTaskRunner> client_task_runner,
ImageProcessor::ErrorCB error_cb) {
// TODO(crbug.com/917798): Use ImageProcessorFactory::Create() once we remove
// |image_processor_device_| from V4L2VideoDecodeAccelerator.
auto image_processor = V4L2ImageProcessor::Create(
std::move(client_task_runner), image_processor_device,
ImageProcessor::PortConfig(Fourcc::FromV4L2PixFmt(vda_output_format),
vda_output_coded_size, {}, visible_size,
{VideoFrame::STORAGE_DMABUFS}),
ImageProcessor::PortConfig(Fourcc::FromV4L2PixFmt(ip_output_format),
ip_output_coded_size, {}, visible_size,
{VideoFrame::STORAGE_DMABUFS}),
image_processor_output_mode, nb_buffers, std::move(error_cb));
if (!image_processor)
return nullptr;
if (image_processor->output_config().size != ip_output_coded_size) {
VLOGF(1) << "Image processor should be able to use the requested output "
<< "coded size " << ip_output_coded_size.ToString()
<< " without adjusting to "
<< image_processor->output_config().size.ToString();
return nullptr;
}
if (image_processor->input_config().size != vda_output_coded_size) {
VLOGF(1) << "Image processor should be able to take the output coded "
<< "size of decoder " << vda_output_coded_size.ToString()
<< " without adjusting to "
<< image_processor->input_config().size.ToString();
return nullptr;
}
return image_processor;
}
} // namespace v4l2_vda_helpers
} // namespace media