blob: ccdfcf4c1ca3d2b508a4650f06716b51804c6cca [file] [log] [blame]
// Copyright 2018 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/chromeos/image_processor_factory.h"
#include <stddef.h>
#include "base/bind.h"
#include "base/callback.h"
#include "base/memory/scoped_refptr.h"
#include "media/base/video_types.h"
#include "media/gpu/buildflags.h"
#include "media/gpu/chromeos/libyuv_image_processor_backend.h"
#include "media/gpu/macros.h"
#if BUILDFLAG(USE_VAAPI)
#include "media/gpu/vaapi/vaapi_image_processor_backend.h"
#endif // BUILDFLAG(USE_VAAPI)
#if BUILDFLAG(USE_V4L2_CODEC)
#include "media/gpu/v4l2/v4l2_device.h"
#include "media/gpu/v4l2/v4l2_image_processor_backend.h"
#include "media/gpu/v4l2/v4l2_vda_helpers.h"
#endif // BUILDFLAG(USE_V4L2_CODEC)
namespace media {
namespace {
#if BUILDFLAG(USE_V4L2_CODEC)
std::unique_ptr<ImageProcessor> CreateV4L2ImageProcessorWithInputCandidates(
const std::vector<std::pair<Fourcc, gfx::Size>>& input_candidates,
const gfx::Size& visible_size,
size_t num_buffers,
scoped_refptr<base::SequencedTaskRunner> client_task_runner,
ImageProcessorFactory::PickFormatCB out_format_picker,
ImageProcessor::ErrorCB error_cb) {
// Pick a renderable output format, and try each available input format.
// TODO(akahuang): let |out_format_picker| return a list of supported output
// formats, and try all combination of input/output format, if any platform
// fails to create ImageProcessor via current approach.
const std::vector<uint32_t> supported_output_formats =
V4L2ImageProcessorBackend::GetSupportedOutputFormats();
std::vector<Fourcc> supported_fourccs;
for (const auto& format : supported_output_formats) {
const auto fourcc = Fourcc::FromV4L2PixFmt(format);
if (!fourcc) {
VLOGF(1) << "unsupported image processor format "
<< FourccToString(format) << ", skipping...";
continue;
}
supported_fourccs.push_back(*fourcc);
}
const auto output_fourcc = out_format_picker.Run(supported_fourccs);
if (!output_fourcc)
return nullptr;
const auto supported_input_pixfmts =
V4L2ImageProcessorBackend::GetSupportedInputFormats();
for (const auto& input_candidate : input_candidates) {
const Fourcc input_fourcc = input_candidate.first;
const gfx::Size& input_size = input_candidate.second;
if (std::find(supported_input_pixfmts.begin(),
supported_input_pixfmts.end(), input_fourcc.ToV4L2PixFmt()) ==
supported_input_pixfmts.end()) {
continue;
}
// Try to get an image size as close as possible to the final size.
gfx::Size output_size(visible_size.width(), visible_size.height());
size_t num_planes = 0;
if (!V4L2ImageProcessorBackend::TryOutputFormat(
input_fourcc.ToV4L2PixFmt(), output_fourcc->ToV4L2PixFmt(),
input_size, &output_size, &num_planes)) {
VLOGF(2) << "Failed to get output size and plane count of IP";
continue;
}
return v4l2_vda_helpers::CreateImageProcessor(
input_fourcc, *output_fourcc, input_size, output_size, visible_size,
VideoFrame::StorageType::STORAGE_GPU_MEMORY_BUFFER, num_buffers,
V4L2Device::Create(), ImageProcessor::OutputMode::IMPORT,
std::move(client_task_runner), std::move(error_cb));
}
return nullptr;
}
#endif // BUILDFLAG(USE_V4L2_CODEC)
} // namespace
// static
std::unique_ptr<ImageProcessor> ImageProcessorFactory::Create(
const ImageProcessor::PortConfig& input_config,
const ImageProcessor::PortConfig& output_config,
const std::vector<ImageProcessor::OutputMode>& preferred_output_modes,
size_t num_buffers,
VideoRotation relative_rotation,
scoped_refptr<base::SequencedTaskRunner> client_task_runner,
ImageProcessor::ErrorCB error_cb) {
std::vector<ImageProcessor::CreateBackendCB> create_funcs;
#if BUILDFLAG(USE_VAAPI)
create_funcs.push_back(
base::BindRepeating(&VaapiImageProcessorBackend::Create));
#endif // BUILDFLAG(USE_VAAPI)
#if BUILDFLAG(USE_V4L2_CODEC)
create_funcs.push_back(base::BindRepeating(
&V4L2ImageProcessorBackend::Create, V4L2Device::Create(), num_buffers));
#endif // BUILDFLAG(USE_V4L2_CODEC)
create_funcs.push_back(
base::BindRepeating(&LibYUVImageProcessorBackend::Create));
std::unique_ptr<ImageProcessor> image_processor;
for (auto& create_func : create_funcs) {
image_processor =
ImageProcessor::Create(std::move(create_func), input_config,
output_config, preferred_output_modes,
relative_rotation, error_cb, client_task_runner);
if (image_processor)
return image_processor;
}
return nullptr;
}
// static
std::unique_ptr<ImageProcessor>
ImageProcessorFactory::CreateWithInputCandidates(
const std::vector<std::pair<Fourcc, gfx::Size>>& input_candidates,
const gfx::Size& visible_size,
size_t num_buffers,
scoped_refptr<base::SequencedTaskRunner> client_task_runner,
PickFormatCB out_format_picker,
ImageProcessor::ErrorCB error_cb) {
#if BUILDFLAG(USE_V4L2_CODEC)
auto processor = CreateV4L2ImageProcessorWithInputCandidates(
input_candidates, visible_size, num_buffers, client_task_runner,
out_format_picker, error_cb);
if (processor)
return processor;
#endif // BUILDFLAG(USE_V4L2_CODEC)
// TODO(crbug.com/1004727): Implement LibYUVImageProcessorBackend and
// VaapiImageProcessorBackend.
return nullptr;
}
} // namespace media