Commit d3276282 authored by David Staessens's avatar David Staessens Committed by Commit Bot

media/gpu/test: Move test image loading and metadata management to separate file

This CL moves code to load and manage test image files to a dedicated class.
Image metadata (such as image size, checksum,...) is stored in json files
accompanying the test files, so it doesn't need to be hardcoded in every test
anymore.

TEST=ran image_processor_test on nocturne

BUG=925223

Change-Id: I94d827be438e691f8c18307227bcd86a767e24a5
Reviewed-on: https://chromium-review.googlesource.com/c/1436278
Commit-Queue: David Staessens <dstaessens@chromium.org>
Reviewed-by: default avatarHirokazu Honda <hiroh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#626933}
parent 00afa042
...@@ -660,6 +660,7 @@ test("image_processor_test") { ...@@ -660,6 +660,7 @@ test("image_processor_test") {
":buildflags", ":buildflags",
":gpu", ":gpu",
"test:image_processor", "test:image_processor",
"test:render_helpers",
"//base/test:test_support", "//base/test:test_support",
"//media:test_support", "//media:test_support",
"//mojo/core/embedder", "//mojo/core/embedder",
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include <memory>
#include <string> #include <string>
#include <tuple> #include <tuple>
...@@ -11,10 +12,12 @@ ...@@ -11,10 +12,12 @@
#include "base/test/test_suite.h" #include "base/test/test_suite.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "media/base/video_frame.h" #include "media/base/video_frame.h"
#include "media/base/video_frame_layout.h"
#include "media/base/video_types.h" #include "media/base/video_types.h"
#include "media/gpu/image_processor.h" #include "media/gpu/image_processor.h"
#include "media/gpu/test/image.h"
#include "media/gpu/test/image_processor/image_processor_client.h" #include "media/gpu/test/image_processor/image_processor_client.h"
#include "media/gpu/test/video_image_info.h" #include "media/gpu/test/video_frame_helpers.h"
#include "mojo/core/embedder/embedder.h" #include "mojo/core/embedder/embedder.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size.h"
...@@ -22,44 +25,35 @@ ...@@ -22,44 +25,35 @@
namespace media { namespace media {
namespace { namespace {
// I420 formatted 320x192 video frame. (bear) constexpr const base::FilePath::CharType* kI420Image =
// TODO(crbug.com/917951): Dynamically load this info from json file. FILE_PATH_LITERAL("bear_320x192.i420.yuv");
constexpr test::VideoImageInfo kI420Image( constexpr const base::FilePath::CharType* kNV12Image =
FILE_PATH_LITERAL("bear_320x192.i420.yuv"), FILE_PATH_LITERAL("bear_320x192.nv12.yuv");
"962820755c74b28f9385fd67219cc04a",
PIXEL_FORMAT_I420,
gfx::Size(320, 192));
// NV12 formatted 320x192 video frame. (bear)
// TODO(crbug.com/917951): Dynamically load this info from json file.
constexpr test::VideoImageInfo kNV12Image(
FILE_PATH_LITERAL("bear_320x192.i420.nv12.yuv"),
"ce21986434743d3671056719136d46ff",
PIXEL_FORMAT_NV12,
gfx::Size(320, 192));
class ImageProcessorSimpleParamTest class ImageProcessorSimpleParamTest
: public ::testing::Test, : public ::testing::Test,
public ::testing::WithParamInterface< public ::testing::WithParamInterface<
std::tuple<test::VideoImageInfo, test::VideoImageInfo>> { std::tuple<base::FilePath, base::FilePath>> {
public: public:
// TODO(crbug.com/917951): Initialize Ozone once. // TODO(crbug.com/917951): Initialize Ozone once.
void SetUp() override {} void SetUp() override {}
void TearDown() override {} void TearDown() override {}
std::unique_ptr<test::ImageProcessorClient> CreateImageProcessorClient( std::unique_ptr<test::ImageProcessorClient> CreateImageProcessorClient(
const test::VideoImageInfo& input_image_info, const test::Image& input_image,
const test::VideoImageInfo& output_image_info) { const test::Image& output_image) {
// TODO(crbug.com/917951): Pass VideoFrameProcessor. // TODO(crbug.com/917951): Pass VideoFrameProcessor.
auto input_config_layout = input_image_info.VideoFrameLayout(); auto input_config_layout = test::CreateVideoFrameLayout(
auto output_config_layout = output_image_info.VideoFrameLayout(); input_image.PixelFormat(), input_image.Size());
auto output_config_layout = test::CreateVideoFrameLayout(
output_image.PixelFormat(), output_image.Size());
LOG_ASSERT(input_config_layout); LOG_ASSERT(input_config_layout);
LOG_ASSERT(output_config_layout); LOG_ASSERT(output_config_layout);
ImageProcessor::PortConfig input_config(*input_config_layout, ImageProcessor::PortConfig input_config(*input_config_layout,
input_image_info.visible_size, input_image.Size(),
{VideoFrame::STORAGE_OWNED_MEMORY}); {VideoFrame::STORAGE_OWNED_MEMORY});
ImageProcessor::PortConfig output_config( ImageProcessor::PortConfig output_config(
*output_config_layout, output_image_info.visible_size, *output_config_layout, output_image.Size(),
{VideoFrame::STORAGE_OWNED_MEMORY}); {VideoFrame::STORAGE_OWNED_MEMORY});
// TODO(crbug.com/917951): Select more appropriate number of buffers. // TODO(crbug.com/917951): Select more appropriate number of buffers.
constexpr size_t kNumBuffers = 1; constexpr size_t kNumBuffers = 1;
...@@ -71,12 +65,15 @@ class ImageProcessorSimpleParamTest ...@@ -71,12 +65,15 @@ class ImageProcessorSimpleParamTest
}; };
TEST_P(ImageProcessorSimpleParamTest, ConvertOneTimeFromMemToMem) { TEST_P(ImageProcessorSimpleParamTest, ConvertOneTimeFromMemToMem) {
test::VideoImageInfo input_image_info = std::get<0>(GetParam()); // Load the test input image. We only need the output image's metadata so we
test::VideoImageInfo output_image_info = std::get<1>(GetParam()); // can compare checksums.
auto ip_client = test::Image input_image(std::get<0>(GetParam()));
CreateImageProcessorClient(input_image_info, output_image_info); test::Image output_image(std::get<1>(GetParam()));
ASSERT_TRUE(input_image.Load());
ip_client->Process(input_image_info, output_image_info); ASSERT_TRUE(output_image.LoadMetadata());
auto ip_client = CreateImageProcessorClient(input_image, output_image);
ip_client->Process(input_image, output_image);
EXPECT_TRUE(ip_client->WaitUntilNumImageProcessed(1u)); EXPECT_TRUE(ip_client->WaitUntilNumImageProcessed(1u));
EXPECT_EQ(ip_client->GetErrorCount(), 0u); EXPECT_EQ(ip_client->GetErrorCount(), 0u);
EXPECT_EQ(ip_client->GetNumOfProcessedImages(), 1u); EXPECT_EQ(ip_client->GetNumOfProcessedImages(), 1u);
...@@ -93,7 +90,7 @@ TEST_P(ImageProcessorSimpleParamTest, ConvertOneTimeFromMemToMem) { ...@@ -93,7 +90,7 @@ TEST_P(ImageProcessorSimpleParamTest, ConvertOneTimeFromMemToMem) {
VideoFrame::HashFrameForTesting(&context, processed_frame); VideoFrame::HashFrameForTesting(&context, processed_frame);
base::MD5Digest digest; base::MD5Digest digest;
base::MD5Final(&digest, &context); base::MD5Final(&digest, &context);
std::string expected_md5 = output_image_info.md5sum; std::string expected_md5 = output_image.Checksum();
std::string computed_md5 = MD5DigestToBase16(digest); std::string computed_md5 = MD5DigestToBase16(digest);
EXPECT_EQ(expected_md5, computed_md5); EXPECT_EQ(expected_md5, computed_md5);
}; };
......
...@@ -161,11 +161,13 @@ if (is_chromeos) { ...@@ -161,11 +161,13 @@ if (is_chromeos) {
static_library("image_processor") { static_library("image_processor") {
testonly = true testonly = true
sources = [ sources = [
"image.cc",
"image.h",
"image_processor/image_processor_client.cc", "image_processor/image_processor_client.cc",
"image_processor/image_processor_client.h", "image_processor/image_processor_client.h",
"video_image_info.h",
] ]
deps = [ deps = [
":render_helpers",
"//media:test_support", "//media:test_support",
"//media/gpu", "//media/gpu",
"//testing/gtest", "//testing/gtest",
......
// 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/test/image.h"
#include <memory>
#include "base/files/file_util.h"
#include "base/json/json_reader.h"
#include "base/md5.h"
#include "base/values.h"
#include "media/base/test_data_util.h"
#define VLOGF(level) VLOG(level) << __func__ << "(): "
namespace media {
namespace test {
namespace {
// Resolve the specified test file path to an absolute path. The path can be
// either an absolute path, a path relative to the current directory, or a path
// relative to the test data path.
void ResolveTestFilePath(base::FilePath* file_path) {
if (!file_path->IsAbsolute()) {
if (!PathExists(*file_path))
*file_path = media::GetTestDataPath().Append(*file_path);
*file_path = base::MakeAbsoluteFilePath(*file_path);
}
}
// Converts the |pixel_format| string into a VideoPixelFormat.
VideoPixelFormat ConvertStringtoPixelFormat(const std::string& pixel_format) {
if (pixel_format == "I420") {
return PIXEL_FORMAT_I420;
} else if (pixel_format == "NV12") {
return PIXEL_FORMAT_NV12;
} else {
VLOG(2) << pixel_format << " is not supported.";
return PIXEL_FORMAT_UNKNOWN;
}
}
} // namespace
// Suffix to append to the image file path to get the metadata file path.
constexpr const base::FilePath::CharType* kMetadataSuffix =
FILE_PATH_LITERAL(".json");
Image::Image(const base::FilePath& file_path) : file_path_(file_path) {}
Image::~Image() {}
bool Image::Load() {
DCHECK(!file_path_.empty());
DCHECK(!IsLoaded());
ResolveTestFilePath(&file_path_);
if (!mapped_file_.Initialize(file_path_)) {
LOG(ERROR) << "Failed to read file: " << file_path_;
return false;
}
if (!LoadMetadata()) {
LOG(ERROR) << "Failed to load metadata";
return false;
}
// Verify that the image's checksum matches the checksum in the metadata.
base::MD5Digest digest;
base::MD5Sum(mapped_file_.data(), mapped_file_.length(), &digest);
if (base::MD5DigestToBase16(digest) != checksum_) {
LOG(ERROR) << "Image checksum not matching metadata";
return false;
}
return true;
}
bool Image::IsLoaded() const {
return mapped_file_.IsValid();
}
bool Image::LoadMetadata() {
if (IsMetadataLoaded()) {
return true;
}
base::FilePath json_path = file_path_.AddExtension(kMetadataSuffix);
ResolveTestFilePath(&json_path);
if (!base::PathExists(json_path)) {
VLOGF(1) << "Image metadata file not found: " << json_path.BaseName();
return false;
}
std::string json_data;
if (!base::ReadFileToString(json_path, &json_data)) {
VLOGF(1) << "Failed to read image metadata file: " << json_path;
return false;
}
base::JSONReader reader;
std::unique_ptr<base::Value> metadata(reader.ReadToValue(json_data));
if (!metadata) {
VLOGF(1) << "Failed to parse image metadata: " << json_path << ": "
<< reader.GetErrorMessage();
return false;
}
// Get the pixel format from the json data.
const base::Value* pixel_format =
metadata->FindKeyOfType("pixel_format", base::Value::Type::STRING);
if (!pixel_format) {
VLOGF(1) << "Key \"pixel_format\" is not found in " << json_path;
return false;
}
pixel_format_ = ConvertStringtoPixelFormat(pixel_format->GetString());
if (pixel_format_ == PIXEL_FORMAT_UNKNOWN) {
VLOGF(1) << pixel_format->GetString() << " is not supported";
return false;
}
// Get the image dimensions from the json data.
const base::Value* width =
metadata->FindKeyOfType("width", base::Value::Type::INTEGER);
if (!width) {
VLOGF(1) << "Key \"width\" is not found in " << json_path;
return false;
}
const base::Value* height =
metadata->FindKeyOfType("height", base::Value::Type::INTEGER);
if (!height) {
VLOGF(1) << "Key \"height\" is not found in " << json_path;
return false;
}
size_ = gfx::Size(width->GetInt(), height->GetInt());
// Get the image checksum from the json data.
const base::Value* checksum =
metadata->FindKeyOfType("checksum", base::Value::Type::STRING);
if (!checksum) {
VLOGF(1) << "Key \"checksum\" is not found in " << json_path;
return false;
}
checksum_ = checksum->GetString();
return true;
}
bool Image::IsMetadataLoaded() const {
return pixel_format_ != PIXEL_FORMAT_UNKNOWN;
}
uint8_t* Image::Data() const {
return mapped_file_.data();
}
size_t Image::DataSize() const {
return mapped_file_.length();
}
VideoPixelFormat Image::PixelFormat() const {
return pixel_format_;
}
const gfx::Size& Image::Size() const {
return size_;
}
const char* Image::Checksum() const {
return checksum_.data();
}
} // namespace test
} // namespace media
// 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.
#ifndef MEDIA_GPU_TEST_IMAGE_H_
#define MEDIA_GPU_TEST_IMAGE_H_
#include <string>
#include "base/files/file_path.h"
#include "base/files/memory_mapped_file.h"
#include "media/base/video_types.h"
#include "ui/gfx/geometry/size.h"
namespace media {
namespace test {
// The Image class provides functionality to load image files and manage their
// properties such as format, size, checksums,... Currently only raw yuv files
// are supported.
class Image {
public:
explicit Image(const base::FilePath& file_path);
~Image();
// Load the image file and accompanying metadata from disk.
bool Load();
// Returns true if the Image file was loaded.
bool IsLoaded() const;
// Load image metadata from the json file accompanying the image file.
bool LoadMetadata();
// Return true if image metadata is already loaded.
bool IsMetadataLoaded() const;
// Get the image data.
uint8_t* Data() const;
// Get the image data size.
size_t DataSize() const;
// Get the image pixel format.
VideoPixelFormat PixelFormat() const;
// Get the image size.
const gfx::Size& Size() const;
// Get the image checksum.
const char* Checksum() const;
private:
// The image file path, can be absolute or relative to the test data path.
base::FilePath file_path_;
// The mapped image data.
// TODO(dstaessens@) Investigate creating const video frames from const data
// so we can remove mutable here.
mutable base::MemoryMappedFile mapped_file_;
// The image pixel format.
VideoPixelFormat pixel_format_ = PIXEL_FORMAT_UNKNOWN;
// The image size.
gfx::Size size_;
// The image md5 checksum.
std::string checksum_;
DISALLOW_COPY_AND_ASSIGN(Image);
};
} // namespace test
} // namespace media
#endif // MEDIA_GPU_TEST_IMAGE_H_
...@@ -10,17 +10,15 @@ ...@@ -10,17 +10,15 @@
#include "third_party/libyuv/include/libyuv/planar_functions.h" #include "third_party/libyuv/include/libyuv/planar_functions.h"
#include "base/bind_helpers.h" #include "base/bind_helpers.h"
#include "base/files/file_util.h"
#include "base/files/memory_mapped_file.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "base/synchronization/waitable_event.h" #include "base/synchronization/waitable_event.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "media/base/bind_to_current_loop.h" #include "media/base/bind_to_current_loop.h"
#include "media/base/test_data_util.h"
#include "media/base/video_frame.h" #include "media/base/video_frame.h"
#include "media/base/video_frame_layout.h" #include "media/base/video_frame_layout.h"
#include "media/gpu/image_processor_factory.h" #include "media/gpu/image_processor_factory.h"
#include "media/gpu/test/image.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect.h"
...@@ -30,22 +28,6 @@ namespace test { ...@@ -30,22 +28,6 @@ namespace test {
namespace { namespace {
// TODO(crbug.com/917951): Move these functions to video_frame_helpers.h // TODO(crbug.com/917951): Move these functions to video_frame_helpers.h
// Find the file path for |file_name|.
base::FilePath GetFilePath(const base::FilePath::CharType* const file_name) {
// 1. Try to find |file_name| in the current directory.
base::FilePath file_path =
base::FilePath(base::FilePath::kCurrentDirectory).Append(file_name);
if (base::PathExists(file_path)) {
return file_path;
}
// 2. Try media::GetTestDataFilePath(|file_name|), that is,
// media/test/data/file_name. This is mainly for Try bot.
file_path = media::GetTestDataPath().Append(file_name);
LOG_ASSERT(base::PathExists(file_path)) << " Cannot find " << file_name;
return file_path;
}
// Copy |src_frame| into a new VideoFrame with |dst_layout|. The created // Copy |src_frame| into a new VideoFrame with |dst_layout|. The created
// VideoFrame's content is the same as |src_frame|. Returns nullptr on failure. // VideoFrame's content is the same as |src_frame|. Returns nullptr on failure.
scoped_refptr<VideoFrame> CloneVideoFrameWithLayout( scoped_refptr<VideoFrame> CloneVideoFrameWithLayout(
...@@ -79,61 +61,6 @@ scoped_refptr<VideoFrame> CloneVideoFrameWithLayout( ...@@ -79,61 +61,6 @@ scoped_refptr<VideoFrame> CloneVideoFrameWithLayout(
return dst_frame; return dst_frame;
} }
// Create VideoFrame from |info| loading |info.file_name|. Return nullptr on
// failure.
scoped_refptr<VideoFrame> ReadVideoFrame(const VideoImageInfo& info) {
auto path = GetFilePath(info.file_name);
// First read file.
auto mapped_file = std::make_unique<base::MemoryMappedFile>();
if (!mapped_file->Initialize(path)) {
LOG(ERROR) << "Failed to read file: " << path;
return nullptr;
}
const auto format = info.pixel_format;
const auto visible_size = info.visible_size;
// Check the file length and md5sum.
LOG_ASSERT(mapped_file->length() ==
VideoFrame::AllocationSize(format, visible_size));
base::MD5Digest digest;
base::MD5Sum(mapped_file->data(), mapped_file->length(), &digest);
LOG_ASSERT(base::MD5DigestToBase16(digest) == info.md5sum);
// Create planes for layout. We cannot use WrapExternalData() because it calls
// GetDefaultLayout() and it supports only a few pixel formats.
const size_t num_planes = VideoFrame::NumPlanes(format);
std::vector<VideoFrameLayout::Plane> planes(num_planes);
const auto strides = VideoFrame::ComputeStrides(format, visible_size);
size_t offset = 0;
for (size_t i = 0; i < num_planes; ++i) {
planes[i].stride = strides[i];
planes[i].offset = offset;
offset += VideoFrame::PlaneSize(format, i, visible_size).GetArea();
}
auto layout = VideoFrameLayout::CreateWithPlanes(
format, visible_size, std::move(planes), {mapped_file->length()});
if (!layout) {
LOG(ERROR) << "Failed to create VideoFrameLayout";
return nullptr;
}
auto frame = VideoFrame::WrapExternalDataWithLayout(
*layout, gfx::Rect(visible_size), visible_size, mapped_file->data(),
mapped_file->length(), base::TimeDelta());
if (!frame) {
LOG(ERROR) << "Failed to create VideoFrame";
return nullptr;
}
// Automatically unmap the memory mapped file when the video frame is
// destroyed.
frame->AddDestructionObserver(base::BindOnce(
base::DoNothing::Once<std::unique_ptr<base::MemoryMappedFile>>(),
std::move(mapped_file)));
return frame;
}
} // namespace } // namespace
// static // static
...@@ -211,15 +138,48 @@ void ImageProcessorClient::CreateImageProcessorTask( ...@@ -211,15 +138,48 @@ void ImageProcessorClient::CreateImageProcessorTask(
} }
scoped_refptr<VideoFrame> ImageProcessorClient::CreateInputFrame( scoped_refptr<VideoFrame> ImageProcessorClient::CreateInputFrame(
const VideoImageInfo& input_image_info) const { const Image& input_image) const {
DCHECK_CALLED_ON_VALID_THREAD(test_main_thread_checker_); DCHECK_CALLED_ON_VALID_THREAD(test_main_thread_checker_);
LOG_ASSERT(image_processor_); LOG_ASSERT(image_processor_);
LOG_ASSERT(input_image.IsLoaded());
LOG_ASSERT(input_image.DataSize() ==
VideoFrame::AllocationSize(input_image.PixelFormat(),
input_image.Size()));
const auto format = input_image.PixelFormat();
const auto visible_size = input_image.Size();
// Create planes for layout. We cannot use WrapExternalData() because it
// calls GetDefaultLayout() and it supports only a few pixel formats.
const size_t num_planes = VideoFrame::NumPlanes(format);
std::vector<VideoFrameLayout::Plane> planes(num_planes);
const auto strides = VideoFrame::ComputeStrides(format, visible_size);
size_t offset = 0;
for (size_t i = 0; i < num_planes; ++i) {
planes[i].stride = strides[i];
planes[i].offset = offset;
offset += VideoFrame::PlaneSize(format, i, visible_size).GetArea();
}
auto layout = VideoFrameLayout::CreateWithPlanes(
format, visible_size, std::move(planes), {input_image.DataSize()});
if (!layout) {
LOG(ERROR) << "Failed to create VideoFrameLayout";
return nullptr;
}
auto frame = VideoFrame::WrapExternalDataWithLayout(
*layout, gfx::Rect(visible_size), visible_size, input_image.Data(),
input_image.DataSize(), base::TimeDelta());
if (!frame) {
LOG(ERROR) << "Failed to create VideoFrame";
return nullptr;
}
auto mapped_frame = ReadVideoFrame(input_image_info);
const auto& input_layout = image_processor_->input_layout(); const auto& input_layout = image_processor_->input_layout();
if (VideoFrame::IsStorageTypeMappable( if (VideoFrame::IsStorageTypeMappable(
image_processor_->input_storage_type())) { image_processor_->input_storage_type())) {
return CloneVideoFrameWithLayout(mapped_frame.get(), input_layout); return CloneVideoFrameWithLayout(frame.get(), input_layout);
} else { } else {
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
LOG_ASSERT(image_processor_->input_storage_type() == LOG_ASSERT(image_processor_->input_storage_type() ==
...@@ -232,18 +192,17 @@ scoped_refptr<VideoFrame> ImageProcessorClient::CreateInputFrame( ...@@ -232,18 +192,17 @@ scoped_refptr<VideoFrame> ImageProcessorClient::CreateInputFrame(
} }
scoped_refptr<VideoFrame> ImageProcessorClient::CreateOutputFrame( scoped_refptr<VideoFrame> ImageProcessorClient::CreateOutputFrame(
const VideoImageInfo& output_image_info) const { const Image& output_image) const {
DCHECK_CALLED_ON_VALID_THREAD(test_main_thread_checker_); DCHECK_CALLED_ON_VALID_THREAD(test_main_thread_checker_);
LOG_ASSERT(output_image.IsMetadataLoaded());
LOG_ASSERT(image_processor_); LOG_ASSERT(image_processor_);
const auto& output_layout = image_processor_->output_layout(); const auto& output_layout = image_processor_->output_layout();
if (VideoFrame::IsStorageTypeMappable( if (VideoFrame::IsStorageTypeMappable(
image_processor_->input_storage_type())) { image_processor_->input_storage_type())) {
return VideoFrame::CreateFrameWithLayout( return VideoFrame::CreateFrameWithLayout(
output_layout, gfx::Rect(output_image_info.visible_size), output_layout, gfx::Rect(output_image.Size()), output_image.Size(),
output_image_info.visible_size, base::TimeDelta(), base::TimeDelta(), false /* zero_initialize_memory*/);
false /* zero_initialize_memory*/
);
} else { } else {
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
LOG_ASSERT(image_processor_->input_storage_type() == LOG_ASSERT(image_processor_->input_storage_type() ==
...@@ -307,12 +266,12 @@ void ImageProcessorClient::NotifyError() { ...@@ -307,12 +266,12 @@ void ImageProcessorClient::NotifyError() {
image_processor_error_count_++; image_processor_error_count_++;
} }
void ImageProcessorClient::Process(const VideoImageInfo& input_info, void ImageProcessorClient::Process(const Image& input_image,
const VideoImageInfo& output_info) { const Image& output_image) {
DCHECK_CALLED_ON_VALID_THREAD(test_main_thread_checker_); DCHECK_CALLED_ON_VALID_THREAD(test_main_thread_checker_);
auto input_frame = CreateInputFrame(input_info); auto input_frame = CreateInputFrame(input_image);
ASSERT_TRUE(input_frame); ASSERT_TRUE(input_frame);
auto output_frame = CreateOutputFrame(input_info); auto output_frame = CreateOutputFrame(output_image);
ASSERT_TRUE(output_frame); ASSERT_TRUE(output_frame);
image_processor_client_thread_.task_runner()->PostTask( image_processor_client_thread_.task_runner()->PostTask(
FROM_HERE, FROM_HERE,
......
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
#include "base/threading/thread_checker.h" #include "base/threading/thread_checker.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "media/gpu/image_processor.h" #include "media/gpu/image_processor.h"
#include "media/gpu/test/video_image_info.h"
namespace base { namespace base {
...@@ -31,6 +30,8 @@ class VideoFrame; ...@@ -31,6 +30,8 @@ class VideoFrame;
namespace test { namespace test {
class Image;
// ImageProcessorClient is a client of ImageProcessor for testing purpose. // ImageProcessorClient is a client of ImageProcessor for testing purpose.
// All the public functions must be called on the same thread, usually the test // All the public functions must be called on the same thread, usually the test
// main thread. // main thread.
...@@ -50,8 +51,9 @@ class ImageProcessorClient { ...@@ -50,8 +51,9 @@ class ImageProcessorClient {
~ImageProcessorClient(); ~ImageProcessorClient();
// Process |input_frame| and |output_frame| with |image_processor_|. // Process |input_frame| and |output_frame| with |image_processor_|.
void Process(const VideoImageInfo& input_info, // Processing is done asynchronously, the WaitUntilNumImageProcessed()
const VideoImageInfo& output_info); // function can be used to wait for the results.
void Process(const Image& input_image, const Image& output_image);
// TODO(crbug.com/917951): Add Reset() when we test Reset() test case. // TODO(crbug.com/917951): Add Reset() when we test Reset() test case.
...@@ -74,7 +76,7 @@ class ImageProcessorClient { ...@@ -74,7 +76,7 @@ class ImageProcessorClient {
size_t GetErrorCount() const; size_t GetErrorCount() const;
private: private:
ImageProcessorClient(bool store_processed_video_frames); explicit ImageProcessorClient(bool store_processed_video_frames);
// Create ImageProcessor with |input_config|, |output_config| and // Create ImageProcessor with |input_config|, |output_config| and
// |num_buffers|. // |num_buffers|.
...@@ -100,11 +102,9 @@ class ImageProcessorClient { ...@@ -100,11 +102,9 @@ class ImageProcessorClient {
// These are test helper functions to create a VideoFrame from VideoImageInfo, // These are test helper functions to create a VideoFrame from VideoImageInfo,
// which will be input in Process(). // which will be input in Process().
// Create a VideoFrame using the input layout required by |image_processor_|. // Create a VideoFrame using the input layout required by |image_processor_|.
scoped_refptr<VideoFrame> CreateInputFrame( scoped_refptr<VideoFrame> CreateInputFrame(const Image& input_image) const;
const VideoImageInfo& input_image_info) const;
// Create a VideoFrame using the output layout required by |image_processor_|. // Create a VideoFrame using the output layout required by |image_processor_|.
scoped_refptr<VideoFrame> CreateOutputFrame( scoped_refptr<VideoFrame> CreateOutputFrame(const Image& output_image) const;
const VideoImageInfo& output_image_info) const;
std::unique_ptr<ImageProcessor> image_processor_; std::unique_ptr<ImageProcessor> image_processor_;
......
...@@ -191,5 +191,14 @@ gfx::GpuMemoryBufferHandle CreateGpuMemoryBufferHandle( ...@@ -191,5 +191,14 @@ gfx::GpuMemoryBufferHandle CreateGpuMemoryBufferHandle(
return handle; return handle;
} }
base::Optional<VideoFrameLayout> CreateVideoFrameLayout(
VideoPixelFormat pixel_format,
const gfx::Size& size) {
return VideoFrameLayout::CreateWithStrides(
pixel_format, size, VideoFrame::ComputeStrides(pixel_format, size),
std::vector<size_t>(VideoFrame::NumPlanes(pixel_format),
0) /* buffer_sizes */);
}
} // namespace test } // namespace test
} // namespace media } // namespace media
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define MEDIA_GPU_TEST_VIDEO_FRAME_HELPERS_H_ #define MEDIA_GPU_TEST_VIDEO_FRAME_HELPERS_H_
#include "base/memory/scoped_refptr.h" #include "base/memory/scoped_refptr.h"
#include "media/base/video_frame_layout.h"
#include "media/base/video_types.h" #include "media/base/video_types.h"
#include "ui/gfx/buffer_types.h" #include "ui/gfx/buffer_types.h"
#include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size.h"
...@@ -60,6 +61,12 @@ scoped_refptr<VideoFrame> CreatePlatformVideoFrame( ...@@ -60,6 +61,12 @@ scoped_refptr<VideoFrame> CreatePlatformVideoFrame(
gfx::GpuMemoryBufferHandle CreateGpuMemoryBufferHandle( gfx::GpuMemoryBufferHandle CreateGpuMemoryBufferHandle(
scoped_refptr<VideoFrame> video_frame); scoped_refptr<VideoFrame> video_frame);
// Create a video frame layout for the specified |pixel_format| and |size|. The
// created layout will have a separate buffer for each plane in the format.
base::Optional<VideoFrameLayout> CreateVideoFrameLayout(
VideoPixelFormat pixel_format,
const gfx::Size& size);
} // namespace test } // namespace test
} // namespace media } // namespace media
......
// 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.
#ifndef MEDIA_GPU_TEST_VIDEO_IMAGE_INFO_H_
#define MEDIA_GPU_TEST_VIDEO_IMAGE_INFO_H_
#include <vector>
#include "base/files/file_path.h"
#include "base/optional.h"
#include "media/base/video_frame.h"
#include "media/base/video_frame_layout.h"
#include "media/base/video_types.h"
#include "ui/gfx/geometry/size.h"
namespace media {
namespace test {
// VideoImageInfo is the information about raw video frame in file.
struct VideoImageInfo {
// TODO(crbug.com/917951): Deprecate this constructor once we load these info
// from json file.
constexpr VideoImageInfo(const base::FilePath::CharType* const file_name,
const char* const md5sum,
VideoPixelFormat pixel_format,
gfx::Size size)
: file_name(file_name),
md5sum(md5sum),
pixel_format(pixel_format),
visible_size(size.width(), size.height()) {}
VideoImageInfo() = delete;
~VideoImageInfo() = default;
base::Optional<VideoFrameLayout> VideoFrameLayout() const {
return VideoFrameLayout::CreateWithStrides(
pixel_format, visible_size,
VideoFrame::ComputeStrides(pixel_format, visible_size),
std::vector<size_t>(VideoFrame::NumPlanes(pixel_format),
0) /* buffer_sizes */);
}
// |file_name| is a file name to be read(e.g. "bear_320x192.i420.yuv"), not
// file path.
const base::FilePath::CharType* const file_name;
//| md5sum| is the md5sum value of the video frame, whose coded_size is the
// same as visible size.
const char* const md5sum;
// |pixel_format| and |visible_size| of the video frame in file.
// NOTE: visible_size should be the same as coded_size, i.e., there is no
// extra padding in the file.
const VideoPixelFormat pixel_format;
const gfx::Size visible_size;
};
} // namespace test
} // namespace media
#endif // MEDIA_GPU_TEST_VIDEO_IMAGE_INFO_H_
...@@ -767,9 +767,15 @@ video_encode_accelerator_unittest. ...@@ -767,9 +767,15 @@ video_encode_accelerator_unittest.
#### bear\_320x192.i420.yuv #### bear\_320x192.i420.yuv
First frame of bear\_320x192\_40frames.yuv for image\_processor_test. First frame of bear\_320x192\_40frames.yuv for image\_processor_test.
#### bear\_320x192.i420.yuv.json
Metadata describing bear\_320x192.i420.yuv.
#### bear\_320x192.nv12.yuv #### bear\_320x192.nv12.yuv
First frame of bear\_320x192\_40frames.nv12.yuv for image\_processor_test. First frame of bear\_320x192\_40frames.nv12.yuv for image\_processor_test.
#### bear\_320x192.nv12.yuv.json
Metadata describing bear\_320x192.nv12.yuv.
#### bear\_320x192.yv21.yuv #### bear\_320x192.yv21.yuv
First frame of bear\_320x192\_40frames.yv21.yuv for image\_processor_test. First frame of bear\_320x192\_40frames.yv21.yuv for image\_processor_test.
......
{
"pixel_format": "I420",
"width": 320,
"height": 192,
"checksum": "962820755c74b28f9385fd67219cc04a"
}
{
"pixel_format": "NV12",
"width": 320,
"height": 192,
"checksum": "ce21986434743d3671056719136d46ff"
}
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