blob: b54ec4dc0eda57b5961c125bb83581dc92500d98 [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.h"
#include <ostream>
#include <sstream>
#include "base/strings/stringprintf.h"
#include "media/base/video_frame.h"
#include "media/base/video_types.h"
#include "media/gpu/macros.h"
namespace media {
namespace {
std::ostream& operator<<(std::ostream& ostream,
const VideoFrame::StorageType& storage_type) {
ostream << VideoFrame::StorageTypeToString(storage_type);
return ostream;
}
template <class T>
std::string VectorToString(const std::vector<T>& vec) {
std::ostringstream result;
std::string delim;
result << "[";
for (const T& v : vec) {
result << delim << v;
if (delim.size() == 0)
delim = ", ";
}
result << "]";
return result.str();
}
// Verify if the format of |frame| matches |config|.
bool CheckVideoFrameFormat(const ImageProcessor::PortConfig& config,
const VideoFrame& frame) {
// Because propriatary format fourcc will map to other common VideoPixelFormat
// with same layout, we convert to VideoPixelFormat to check.
if (frame.format() != config.fourcc.ToVideoPixelFormat()) {
VLOGF(1) << "Invalid frame format="
<< VideoPixelFormatToString(frame.format())
<< ", expected=" << config.fourcc.ToString();
return false;
}
if (frame.layout().coded_size() != config.size) {
VLOGF(1) << "Invalid frame size=" << frame.layout().coded_size().ToString()
<< ", expected=" << config.size.ToString();
return false;
}
if (frame.storage_type() != config.storage_type()) {
VLOGF(1) << "Invalid frame.storage_type=" << frame.storage_type()
<< ", input_storage_type=" << config.storage_type();
return false;
}
return true;
}
} // namespace
ImageProcessor::PortConfig::PortConfig(const PortConfig&) = default;
ImageProcessor::PortConfig::PortConfig(
Fourcc fourcc,
const gfx::Size& size,
const std::vector<ColorPlaneLayout>& planes,
const gfx::Size& visible_size,
const std::vector<VideoFrame::StorageType>& preferred_storage_types)
: fourcc(fourcc),
size(size),
planes(planes),
visible_size(visible_size),
preferred_storage_types(preferred_storage_types) {}
ImageProcessor::PortConfig::~PortConfig() = default;
std::string ImageProcessor::PortConfig::ToString() const {
return base::StringPrintf(
"PortConfig(format:%s, size:%s, planes: %s, visible_size:%s, "
"storage_types:%s)",
fourcc.ToString().c_str(), size.ToString().c_str(),
VectorToString(planes).c_str(), visible_size.ToString().c_str(),
VectorToString(preferred_storage_types).c_str());
}
ImageProcessor::ImageProcessor(
const ImageProcessor::PortConfig& input_config,
const ImageProcessor::PortConfig& output_config,
OutputMode output_mode,
scoped_refptr<base::SequencedTaskRunner> client_task_runner)
: input_config_(input_config),
output_config_(output_config),
output_mode_(output_mode),
client_task_runner_(std::move(client_task_runner)) {
DETACH_FROM_SEQUENCE(client_sequence_checker_);
}
ImageProcessor::~ImageProcessor() = default;
#if defined(OS_POSIX) || defined(OS_FUCHSIA)
bool ImageProcessor::Process(scoped_refptr<VideoFrame> frame,
LegacyFrameReadyCB cb) {
DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
DCHECK_EQ(output_mode(), OutputMode::ALLOCATE);
return ProcessInternal(std::move(frame), std::move(cb));
}
bool ImageProcessor::ProcessInternal(scoped_refptr<VideoFrame> frame,
LegacyFrameReadyCB cb) {
NOTIMPLEMENTED();
return false;
}
#endif
bool ImageProcessor::Process(scoped_refptr<VideoFrame> input_frame,
scoped_refptr<VideoFrame> output_frame,
FrameReadyCB cb) {
DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
DCHECK_EQ(output_mode(), OutputMode::IMPORT);
DCHECK(input_frame);
DCHECK(output_frame);
if (!CheckVideoFrameFormat(input_config_, *input_frame) ||
!CheckVideoFrameFormat(output_config_, *output_frame))
return false;
return ProcessInternal(std::move(input_frame), std::move(output_frame),
std::move(cb));
}
} // namespace media