Commit 43b898be authored by Yuta Kitamura's avatar Yuta Kitamura Committed by Commit Bot

Revert "media/gpu/test: Initial version of the Test Video player."

This reverts commit 493db4b2.

Reason for revert: Compile error on win-rel builder.
https://ci.chromium.org/p/chromium/builders/luci.chromium.ci/win-rel/6451

Original change's description:
> media/gpu/test: Initial version of the Test Video player.
> 
> The test video player is created to improve the way VDA (video decode
> accelerator) tests are created, and to allow more control of the test flow.
> 
> This is an early prototype, that only supports playing a video from start to
> finish. More complex tests and their required functionality will be added soon.
> 
> TEST=ran new VDA tests on eve and kevin
> 
> BUG=879065
> 
> Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:linux_optional_gpu_tests_rel;luci.chromium.try:mac_optional_gpu_tests_rel;luci.chromium.try:win_optional_gpu_tests_rel
> Change-Id: Ida7396e7294c0e367417c352284e4a601daa0cba
> Reviewed-on: https://chromium-review.googlesource.com/c/1179484
> Commit-Queue: David Staessens <dstaessens@chromium.org>
> Reviewed-by: Hirokazu Honda <hiroh@chromium.org>
> Reviewed-by: Takuto Ikuta <tikuta@chromium.org>
> Reviewed-by: Alexandre Courbot <acourbot@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#609622}

TBR=posciak@chromium.org,sandersd@chromium.org,tikuta@chromium.org,hiroh@chromium.org,acourbot@chromium.org,keiichiw@chromium.org,dstaessens@chromium.org

Change-Id: Ic6ba5ba69c6ebae256d0e39d1b3af739e47b75da
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 879065
Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:linux_optional_gpu_tests_rel;luci.chromium.try:mac_optional_gpu_tests_rel;luci.chromium.try:win_optional_gpu_tests_rel
Reviewed-on: https://chromium-review.googlesource.com/c/1343870Reviewed-by: default avatarYuta Kitamura <yutak@chromium.org>
Commit-Queue: Yuta Kitamura <yutak@chromium.org>
Cr-Commit-Position: refs/heads/master@{#609626}
parent 8979a892
...@@ -304,10 +304,6 @@ group("gn_all") { ...@@ -304,10 +304,6 @@ group("gn_all") {
"//content/public/android:content_junit_tests", "//content/public/android:content_junit_tests",
"//content/shell/android:content_shell_apk", "//content/shell/android:content_shell_apk",
"//device:device_junit_tests", "//device:device_junit_tests",
"//media/gpu:video_decode_accelerator_tests",
# TODO(https://crbug.com/879065): remove once tests have been migrated to
# the above target.
"//media/gpu:video_decode_accelerator_unittest", "//media/gpu:video_decode_accelerator_unittest",
"//net/android:net_junit_tests", "//net/android:net_junit_tests",
"//services:service_junit_tests", "//services:service_junit_tests",
...@@ -887,10 +883,6 @@ if (is_chromeos) { ...@@ -887,10 +883,6 @@ if (is_chromeos) {
if (use_v4l2_codec || use_vaapi) { if (use_v4l2_codec || use_vaapi) {
deps += [ deps += [
"//media/gpu:video_decode_accelerator_tests",
# TODO(https://crbug.com/879065): remove once tests have been migrated
# to the above target.
"//media/gpu:video_decode_accelerator_unittest", "//media/gpu:video_decode_accelerator_unittest",
"//media/gpu:video_encode_accelerator_unittest", "//media/gpu:video_encode_accelerator_unittest",
] ]
......
...@@ -74,7 +74,6 @@ component("gpu") { ...@@ -74,7 +74,6 @@ component("gpu") {
"//content/renderer:*", "//content/renderer:*",
"//media/gpu/ipc/*", "//media/gpu/ipc/*",
"//media/gpu/vaapi/*", "//media/gpu/vaapi/*",
"//media/gpu/test/*",
"//media/mojo/*", "//media/mojo/*",
"//remoting/codec:encoder", "//remoting/codec:encoder",
":*", ":*",
...@@ -392,10 +391,23 @@ if (is_win || is_android || use_v4l2_codec || use_vaapi) { ...@@ -392,10 +391,23 @@ if (is_win || is_android || use_v4l2_codec || use_vaapi) {
configs += [ "//third_party/khronos:khronos_headers" ] configs += [ "//third_party/khronos:khronos_headers" ]
if (is_win || is_chromeos || use_v4l2_codec) { if (is_win || is_chromeos || use_v4l2_codec) {
sources += [ "video_decode_accelerator_unittest.cc" ] sources += [
"test/rendering_helper.cc",
"test/rendering_helper.h",
"test/texture_ref.cc",
"test/texture_ref.h",
"test/video_decode_accelerator_unittest_helpers.cc",
"test/video_decode_accelerator_unittest_helpers.h",
"test/video_frame_mapper.h",
"test/video_frame_mapper_factory.cc",
"test/video_frame_mapper_factory.h",
"test/video_frame_validator.cc",
"test/video_frame_validator.h",
"video_decode_accelerator_unittest.cc",
]
deps += [ deps += [
"test:helpers",
"//mojo/core/embedder", "//mojo/core/embedder",
"//third_party/libyuv",
"//ui/display", "//ui/display",
"//ui/display/types", "//ui/display/types",
"//ui/platform_window", "//ui/platform_window",
...@@ -420,6 +432,19 @@ if (is_win || is_android || use_v4l2_codec || use_vaapi) { ...@@ -420,6 +432,19 @@ if (is_win || is_android || use_v4l2_codec || use_vaapi) {
] ]
} }
if (is_chromeos) {
sources += [
"test/generic_dmabuf_video_frame_mapper.cc",
"test/generic_dmabuf_video_frame_mapper.h",
]
if (use_vaapi) {
sources += [
"test/vaapi_dmabuf_video_frame_mapper.cc",
"test/vaapi_dmabuf_video_frame_mapper.h",
]
}
}
if (use_x11) { if (use_x11) {
configs += [ "//build/config/linux:x11" ] configs += [ "//build/config/linux:x11" ]
deps += [ "//ui/gfx/x" ] deps += [ "//ui/gfx/x" ]
...@@ -477,7 +502,6 @@ source_set("android_video_decode_accelerator_unittests") { ...@@ -477,7 +502,6 @@ source_set("android_video_decode_accelerator_unittests") {
if (use_v4l2_codec || use_vaapi || is_mac || is_win) { if (use_v4l2_codec || use_vaapi || is_mac || is_win) {
test("video_encode_accelerator_unittest") { test("video_encode_accelerator_unittest") {
deps = [ deps = [
"test:helpers",
"//base", "//base",
"//base/test:test_support", "//base/test:test_support",
"//media:test_support", "//media:test_support",
...@@ -493,6 +517,14 @@ if (use_v4l2_codec || use_vaapi || is_mac || is_win) { ...@@ -493,6 +517,14 @@ if (use_v4l2_codec || use_vaapi || is_mac || is_win) {
] ]
configs += [ "//third_party/libyuv:libyuv_config" ] configs += [ "//third_party/libyuv:libyuv_config" ]
sources = [ sources = [
"test/texture_ref.cc",
"test/texture_ref.h",
"test/video_accelerator_unittest_helpers.h",
"test/video_encode_accelerator_unittest_helpers.cc",
"test/video_encode_accelerator_unittest_helpers.h",
"test/video_frame_mapper.h",
"test/video_frame_mapper_factory.cc",
"test/video_frame_mapper_factory.h",
"video_encode_accelerator_unittest.cc", "video_encode_accelerator_unittest.cc",
] ]
if (use_x11) { if (use_x11) {
...@@ -501,6 +533,18 @@ if (use_v4l2_codec || use_vaapi || is_mac || is_win) { ...@@ -501,6 +533,18 @@ if (use_v4l2_codec || use_vaapi || is_mac || is_win) {
if (use_ozone) { if (use_ozone) {
deps += [ "//ui/ozone" ] deps += [ "//ui/ozone" ]
} }
if (is_chromeos) {
sources += [
"test/generic_dmabuf_video_frame_mapper.cc",
"test/generic_dmabuf_video_frame_mapper.h",
]
if (use_vaapi) {
sources += [
"test/vaapi_dmabuf_video_frame_mapper.cc",
"test/vaapi_dmabuf_video_frame_mapper.h",
]
}
}
} }
} }
...@@ -629,22 +673,3 @@ source_set("unit_tests") { ...@@ -629,22 +673,3 @@ source_set("unit_tests") {
libs = [ "dxguid.lib" ] libs = [ "dxguid.lib" ]
} }
} }
test("video_decode_accelerator_tests") {
sources = [
"video_decode_accelerator_tests.cc",
]
data = [
"//media/test/data/",
]
deps = [
":buildflags",
"test:video_player",
"//base/test:test_support",
"//media:test_support",
"//testing/gtest",
]
if (use_vaapi) {
deps += [ "//media/gpu/vaapi" ]
}
}
# 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.
import("//build/config/ui.gni")
import("//media/gpu/args.gni")
# TODO(dstaessens@) Split up in encode/decode/render/common helpers
source_set("helpers") {
testonly = true
sources = [
"rendering_helper.cc",
"rendering_helper.h",
"texture_ref.cc",
"texture_ref.h",
"video_accelerator_unittest_helpers.h",
"video_decode_accelerator_unittest_helpers.cc",
"video_decode_accelerator_unittest_helpers.h",
"video_encode_accelerator_unittest_helpers.cc",
"video_encode_accelerator_unittest_helpers.h",
"video_frame_mapper.h",
"video_frame_mapper_factory.cc",
"video_frame_mapper_factory.h",
"video_frame_validator.cc",
"video_frame_validator.h",
]
if (is_chromeos) {
sources += [
"generic_dmabuf_video_frame_mapper.cc",
"generic_dmabuf_video_frame_mapper.h",
]
if (use_vaapi) {
sources += [
"vaapi_dmabuf_video_frame_mapper.cc",
"vaapi_dmabuf_video_frame_mapper.h",
]
}
}
deps = [
"//media/gpu",
"//testing/gtest",
"//third_party/libyuv",
"//ui/gl/init:init",
]
if (use_ozone) {
deps += [ "//ui/ozone" ]
}
}
static_library("video_player") {
testonly = true
sources = [
"video_player/frame_renderer.h",
"video_player/frame_renderer_dummy.cc",
"video_player/frame_renderer_dummy.h",
"video_player/video.cc",
"video_player/video.h",
"video_player/video_collection.cc",
"video_player/video_collection.h",
"video_player/video_decoder_client.cc",
"video_player/video_decoder_client.h",
"video_player/video_player.cc",
"video_player/video_player.h",
]
data = [
"//media/test/data/",
]
deps = [
":helpers",
"//media/gpu",
]
if (use_ozone) {
deps += [ "//ui/ozone" ]
}
}
...@@ -4,9 +4,6 @@ ...@@ -4,9 +4,6 @@
#include "media/gpu/test/video_decode_accelerator_unittest_helpers.h" #include "media/gpu/test/video_decode_accelerator_unittest_helpers.h"
#include <utility>
#include "base/callback_helpers.h"
#include "base/files/file_util.h" #include "base/files/file_util.h"
#include "base/files/scoped_file.h" #include "base/files/scoped_file.h"
#include "base/strings/string_split.h" #include "base/strings/string_split.h"
...@@ -76,13 +73,6 @@ EncodedDataHelper::EncodedDataHelper(const std::string& data, ...@@ -76,13 +73,6 @@ EncodedDataHelper::EncodedDataHelper(const std::string& data,
VideoCodecProfile profile) VideoCodecProfile profile)
: data_(data), profile_(profile) {} : data_(data), profile_(profile) {}
EncodedDataHelper::EncodedDataHelper(const std::vector<uint8_t>& stream,
VideoCodecProfile profile)
: EncodedDataHelper(
std::string(reinterpret_cast<const char*>(stream.data()),
stream.size()),
profile) {}
EncodedDataHelper::~EncodedDataHelper() { EncodedDataHelper::~EncodedDataHelper() {
base::STLClearObject(&data_); base::STLClearObject(&data_);
} }
......
...@@ -57,10 +57,7 @@ class VideoDecodeAcceleratorTestEnvironment : public ::testing::Environment { ...@@ -57,10 +57,7 @@ class VideoDecodeAcceleratorTestEnvironment : public ::testing::Environment {
class EncodedDataHelper { class EncodedDataHelper {
public: public:
// TODO(dstaessens@) Remove this constructor once the VDA tests are migrated.
EncodedDataHelper(const std::string& encoded_data, VideoCodecProfile profile); EncodedDataHelper(const std::string& encoded_data, VideoCodecProfile profile);
EncodedDataHelper(const std::vector<uint8_t>& stream,
VideoCodecProfile profile);
~EncodedDataHelper(); ~EncodedDataHelper();
// Compute and return the next fragment to be sent to the decoder, starting // Compute and return the next fragment to be sent to the decoder, starting
......
...@@ -3,8 +3,6 @@ ...@@ -3,8 +3,6 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "media/gpu/test/video_frame_validator.h" #include "media/gpu/test/video_frame_validator.h"
// TODO(dstaessens@) Avoid depending on video_decode_accelerator here.
#include "media/gpu/test/video_decode_accelerator_unittest_helpers.h"
#include <libyuv.h> #include <libyuv.h>
......
// 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.
#ifndef MEDIA_GPU_TEST_VIDEO_PLAYER_FRAME_RENDERER_H_
#define MEDIA_GPU_TEST_VIDEO_PLAYER_FRAME_RENDERER_H_
#include <vector>
#include "base/callback_forward.h"
#include "media/base/video_types.h"
#include "media/video/picture.h"
#include "ui/gfx/geometry/size.h"
namespace gl {
class GLContext;
} // namespace gl
namespace media {
namespace test {
// The frame renderer interface can be used to render decoded frames to screen,
// file,... It is responsible for creating picture buffers and maintaining a GL
// context.
class FrameRenderer {
public:
using PictureBuffersCreatedCB =
base::OnceCallback<void(const std::vector<PictureBuffer>)>;
using PictureRenderedCB = base::OnceClosure;
virtual ~FrameRenderer() = default;
// Acquire the GL context for the current thread. This is needed if the
// context is shared between multiple threads.
virtual void AcquireGLContext() = 0;
// Release the GL context on the current thread.
virtual void ReleaseGLContext() = 0;
// Get the current GL context.
virtual gl::GLContext* GetGLContext() = 0;
// Create a set of picture buffers, |cb| should be called upon completion.
virtual void CreatePictureBuffers(size_t requested_num_of_buffers,
VideoPixelFormat pixel_format,
const gfx::Size& size,
uint32_t texture_target,
PictureBuffersCreatedCB cb) = 0;
// Render the specified picture, |cb| should be called once rendering is done
// so the decoder can reuse the picture buffer.
virtual void RenderPicture(const Picture& picture, PictureRenderedCB cb) = 0;
};
} // namespace test
} // namespace media
#endif // MEDIA_GPU_TEST_VIDEO_PLAYER_FRAME_RENDERER_H_
// 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/test/video_player/frame_renderer_dummy.h"
#include <utility>
#include <vector>
#include "base/memory/ptr_util.h"
#include "ui/ozone/public/ozone_gpu_test_helper.h"
#include "ui/ozone/public/ozone_platform.h"
#define VLOGF(level) VLOG(level) << __func__ << "(): "
namespace media {
namespace test {
FrameRendererDummy::FrameRendererDummy() {
DETACH_FROM_SEQUENCE(sequence_checker_);
}
FrameRendererDummy::~FrameRendererDummy() {
Destroy();
}
// static
std::unique_ptr<FrameRendererDummy> FrameRendererDummy::Create() {
auto frame_renderer = base::WrapUnique(new FrameRendererDummy());
if (!frame_renderer->Initialize()) {
return nullptr;
}
return frame_renderer;
}
bool FrameRendererDummy::Initialize() {
#ifdef USE_OZONE
// Initialize Ozone. This is necessary even though we are not doing any actual
// rendering. If not initialized a crash will occur when assigning picture
// buffers, even when passing 0 as texture ID.
// TODO(@dstaessens):
// * Get rid of the Ozone dependency, as it forces us to call 'stop ui' when
// running tests.
LOG(INFO) << "Initializing Ozone Platform...\n"
"If this hangs indefinitely please call 'stop ui' first!";
ui::OzonePlatform::InitParams params = {.single_process = false};
ui::OzonePlatform::InitializeForUI(params);
ui::OzonePlatform::InitializeForGPU(params);
ui::OzonePlatform::GetInstance()->AfterSandboxEntry();
// Initialize the Ozone GPU helper. If this is not done an error will occur:
// "Check failed: drm. No devices available for buffer allocation."
// Note: If a task environment is not set up initialization will hang
// indefinitely here.
gpu_helper_.reset(new ui::OzoneGpuTestHelper());
gpu_helper_->Initialize(base::ThreadTaskRunnerHandle::Get());
#endif
return true;
}
void FrameRendererDummy::Destroy() {
#ifdef USE_OZONE
gpu_helper_.reset();
#endif
}
void FrameRendererDummy::AcquireGLContext() {
// As no actual rendering is done we don't have a GLContext to acquire.
}
void FrameRendererDummy::ReleaseGLContext() {
// As no actual rendering is done we don't have a GLContext to release.
}
gl::GLContext* FrameRendererDummy::GetGLContext() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// As no actual rendering is done we don't have a GLContext.
return nullptr;
}
void FrameRendererDummy::CreatePictureBuffers(size_t requested_num_of_buffers,
VideoPixelFormat pixel_format,
const gfx::Size& size,
uint32_t texture_target,
PictureBuffersCreatedCB cb) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
std::vector<PictureBuffer> buffers;
for (size_t i = 0; i < requested_num_of_buffers; ++i) {
buffers.emplace_back(GetNextPictureBufferId(), size);
}
std::move(cb).Run(std::move(buffers));
}
void FrameRendererDummy::RenderPicture(const Picture& picture,
PictureRenderedCB cb) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
std::move(cb).Run();
}
int32_t FrameRendererDummy::GetNextPictureBufferId() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// The picture buffer ID should always be positive, negative values are
// reserved for uninitialized buffers.
next_picture_buffer_id_ = (next_picture_buffer_id_ + 1) & 0x7FFFFFFF;
return next_picture_buffer_id_;
}
} // namespace test
} // namespace media
// 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.
#ifndef MEDIA_GPU_TEST_VIDEO_PLAYER_FRAME_RENDERER_DUMMY_H_
#define MEDIA_GPU_TEST_VIDEO_PLAYER_FRAME_RENDERER_DUMMY_H_
#include <memory>
#include "base/macros.h"
#include "base/sequence_checker.h"
#include "media/gpu/test/video_player/frame_renderer.h"
#ifdef USE_OZONE
namespace ui {
class OzoneGpuTestHelper;
} // namespace ui
#endif
namespace media {
namespace test {
// The dummy frame renderer can be used when we're not interested in rendering
// the decoded frames to screen or file. No rate-limiting is done, and frames
// are consumed as fast as they are provided.
class FrameRendererDummy : public FrameRenderer {
public:
~FrameRendererDummy() override;
// Create an instance of the dummy frame renderer.
static std::unique_ptr<FrameRendererDummy> Create();
void AcquireGLContext() override;
void ReleaseGLContext() override;
gl::GLContext* GetGLContext() override;
void CreatePictureBuffers(size_t requested_num_of_buffers,
VideoPixelFormat pixel_format,
const gfx::Size& size,
uint32_t texture_target,
PictureBuffersCreatedCB cb) override;
void RenderPicture(const Picture& picture, PictureRenderedCB cb) override;
private:
FrameRendererDummy();
// Initialize the frame renderer, performs all rendering-related setup.
bool Initialize();
// Destroy the frame renderer.
void Destroy();
// Get the next picture buffer id to be used.
int32_t GetNextPictureBufferId();
#ifdef USE_OZONE
std::unique_ptr<ui::OzoneGpuTestHelper> gpu_helper_;
#endif
int32_t next_picture_buffer_id_ = 0;
SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(FrameRendererDummy);
};
} // namespace test
} // namespace media
#endif // MEDIA_GPU_TEST_VIDEO_PLAYER_FRAME_RENDERER_DUMMY_H_
// 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/test/video_player/video.h"
#include <utility>
#include "base/files/file_util.h"
#include "base/numerics/safe_conversions.h"
#define VLOGF(level) VLOG(level) << __func__ << "(): "
namespace media {
namespace test {
base::FilePath Video::test_data_path_ = base::FilePath();
Video::Video(const base::FilePath& file_path) : file_path_(file_path) {}
Video::~Video() {}
bool Video::Load() {
// TODO(dstaessens@) Investigate reusing existing infrastructure such as
// DecoderBuffer.
DCHECK(!file_path_.empty());
DCHECK(data_.empty());
// The specified path can be either an absolute path, a path relative to the
// current directory, or relative to the test data path.
if (!file_path_.IsAbsolute()) {
if (!PathExists(file_path_))
file_path_ = test_data_path_.Append(file_path_);
file_path_ = base::MakeAbsoluteFilePath(file_path_);
}
VLOGF(2) << "File path: " << file_path_;
int64_t file_size;
if (!base::GetFileSize(file_path_, &file_size) || (file_size < 0)) {
VLOGF(1) << "Failed to read file size: " << file_path_;
return false;
}
std::vector<uint8_t> data(file_size);
if (base::ReadFile(file_path_, reinterpret_cast<char*>(data.data()),
base::checked_cast<int>(file_size)) != file_size) {
VLOGF(1) << "Failed to read file: " << file_path_;
return false;
}
data_ = std::move(data);
// TODO(keiitchiw@) Get this from the metadata accompanying each video file.
profile_ = H264PROFILE_BASELINE;
return true;
}
bool Video::IsLoaded() const {
return data_.size() > 0;
}
const std::vector<uint8_t>& Video::GetData() const {
return data_;
}
VideoCodecProfile Video::GetProfile() const {
return profile_;
}
// static
void Video::SetTestDataPath(const base::FilePath& test_data_path) {
test_data_path_ = test_data_path;
}
} // namespace test
} // namespace media
// 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.
#ifndef MEDIA_GPU_TEST_VIDEO_PLAYER_VIDEO_H_
#define MEDIA_GPU_TEST_VIDEO_PLAYER_VIDEO_H_
#include <vector>
#include "base/files/file_path.h"
#include "base/macros.h"
#include "media/base/video_codecs.h"
namespace media {
namespace test {
// The video class provides functionality to load video files and manage their
// properties such as codec, number of frames,...
// TODO(@dstaessens):
// * Define and add functionality to load video properties. Each video should
// have an accompanying json file containing: codec, number of frames,
// MD5 checksums for the frame validator,... We could even go as far as
// having an offset for each individual frame in the video
// * Use a file stream rather than loading potentially huge files into memory.
class Video {
public:
explicit Video(const base::FilePath& file_path);
~Video();
// Load the video file from disk.
bool Load();
// Returns true if the video file was loaded.
bool IsLoaded() const;
// Get the video data, will be empty if the video hasn't been loaded yet.
const std::vector<uint8_t>& GetData() const;
// Get the video's codec.
VideoCodecProfile GetProfile() const;
// Set the default path to the test video data.
static void SetTestDataPath(const base::FilePath& test_data_path);
private:
// The path where all test video files are stored.
// TODO(dstaessens@) Avoid using a static data path here.
static base::FilePath test_data_path_;
// The video file's path, can be absolute or relative to the above path.
base::FilePath file_path_;
std::vector<uint8_t> data_;
VideoCodecProfile profile_ = VIDEO_CODEC_PROFILE_UNKNOWN;
DISALLOW_COPY_AND_ASSIGN(Video);
};
} // namespace test
} // namespace media
#endif // MEDIA_GPU_TEST_VIDEO_PLAYER_VIDEO_H_
// 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/test/video_player/video_collection.h"
#include <utility>
#include "media/gpu/test/video_player/video.h"
namespace media {
namespace test {
const VideoCollection kDefaultTestVideoCollection = std::move(
VideoCollection()
.Add(std::make_unique<Video>(base::FilePath("test-25fps.h264")))
.Add(std::make_unique<Video>(base::FilePath("test-25fps.vp8")))
.Add(std::make_unique<Video>(base::FilePath("test-25fps.vp9"))));
VideoCollection::VideoCollection() {}
VideoCollection::~VideoCollection() {}
VideoCollection::VideoCollection(VideoCollection&& other) {
video_collection_ = std::move(other.video_collection_);
}
VideoCollection& VideoCollection::Add(std::unique_ptr<Video> video) {
video_collection_.push_back(std::move(video));
return *this;
}
const Video& VideoCollection::operator[](size_t index) const {
CHECK_LT(index, video_collection_.size());
Video* video = video_collection_.at(index).get();
// Only load video when actually requested, to avoid loading all videos in the
// collection, even when only a single video is needed.
if (!video->IsLoaded()) {
bool loaded = video->Load();
LOG_IF(FATAL, !loaded) << "Loading video failed";
}
return *video;
}
size_t VideoCollection::Size() const {
return video_collection_.size();
}
} // namespace test
} // namespace media
// 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.
#ifndef MEDIA_GPU_TEST_VIDEO_PLAYER_VIDEO_COLLECTION_H_
#define MEDIA_GPU_TEST_VIDEO_PLAYER_VIDEO_COLLECTION_H_
#include <stdint.h>
#include <memory>
#include <vector>
#include "base/macros.h"
namespace media {
namespace test {
class Video;
// The video collection class helps managing different sets of test videos.
// Multiple test video collections can be maintained:
// * A collection of lightweight videos for CQ testing.
// * A collection of large video files for performance testing.
// * A set of corrupt videos to test decoder stability.
// * A set of small generated video files with various properties.
// TODO(dstaessens@):
// * Add functionality to fetch video by codec/resolution/name/...
// * Add a collection of videos to test different codecs.
// * Add a collection of videos to test various resolutions.
// * Add a collection of lightweight videos (defined directly in code?).
class VideoCollection {
public:
VideoCollection();
~VideoCollection();
VideoCollection(VideoCollection&& other);
// Add a video to the collection, this will transfer ownership.
VideoCollection& Add(std::unique_ptr<Video> video);
// Get the video with specified index from the collection.
const Video& operator[](size_t index) const;
size_t Size() const;
private:
std::vector<std::unique_ptr<Video>> video_collection_;
DISALLOW_COPY_AND_ASSIGN(VideoCollection);
};
// The default video test file collection
extern const VideoCollection kDefaultTestVideoCollection;
} // namespace test
} // namespace media
#endif // MEDIA_GPU_TEST_VIDEO_PLAYER_VIDEO_COLLECTION_H_
This diff is collapsed.
// 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.
#ifndef MEDIA_GPU_TEST_VIDEO_PLAYER_VIDEO_DECODER_CLIENT_H_
#define MEDIA_GPU_TEST_VIDEO_PLAYER_VIDEO_DECODER_CLIENT_H_
#include <stdint.h>
#include <map>
#include <memory>
#include <vector>
#include "base/macros.h"
#include "base/sequence_checker.h"
#include "base/threading/thread.h"
#include "media/gpu/test/video_player/video_player.h"
#include "media/video/video_decode_accelerator.h"
namespace media {
class GpuVideoDecodeAcceleratorFactory;
namespace test {
class EncodedDataHelper;
class FrameRenderer;
// The video decoder client is responsible for the communication between the
// video player and the video decoder. It also communicates with the frame
// renderer and other components. The video decoder client can only have one
// active decoder at any time. To decode a different stream the DestroyDecoder()
// and CreateDecoder() functions have to be called to destroy and re-create the
// decoder.
//
// All communication with the decoder is done on the |decoder_client_thread_|,
// so callbacks scheduled by the decoder can be executed asynchronously. This is
// necessary if we don't want to interrupt the test flow.
class VideoDecoderClient : public VideoDecodeAccelerator::Client {
public:
~VideoDecoderClient() override;
// Return an instance of the VideoDecoderClient. The |frame_renderer| will not
// be owned by the decoder client, the caller should guarantee it exists for
// the entire lifetime of the decoder client. The |event_cb| will be called
// whenever an event occurs (e.g. frame decoded) and should be thread-safe.
static std::unique_ptr<VideoDecoderClient> Create(
const VideoPlayer::EventCallback& event_cb,
FrameRenderer* frame_renderer);
// Create a decoder with specified |config|, video |stream| and video
// |stream_size|. The video stream will not be owned by the decoder client,
// the caller should guarantee it exists until DestroyDecoder() is called.
void CreateDecoder(const VideoDecodeAccelerator::Config& config,
const std::vector<uint8_t>& stream);
// Destroy the currently active decoder.
void DestroyDecoder();
// Queue the next video stream fragment to be decoded.
void DecodeNextFragment();
private:
VideoDecoderClient(const VideoPlayer::EventCallback& event_cb,
FrameRenderer* renderer);
bool Initialize();
void Destroy();
// VideoDecodeAccelerator::Client implementation
void ProvidePictureBuffers(uint32_t requested_num_of_buffers,
VideoPixelFormat pixel_format,
uint32_t textures_per_buffer,
const gfx::Size& size,
uint32_t texture_target) override;
void DismissPictureBuffer(int32_t picture_buffer_id) override;
void PictureReady(const Picture& picture) override;
void NotifyEndOfBitstreamBuffer(int32_t bitstream_buffer_id) override;
void NotifyFlushDone() override;
void NotifyResetDone() override;
void NotifyError(VideoDecodeAccelerator::Error error) override;
void CreateDecoderFactoryTask(base::WaitableEvent* done);
void CreateDecoderTask(VideoDecodeAccelerator::Config config,
const std::vector<uint8_t>* stream,
base::WaitableEvent* done);
void DestroyDecoderTask(base::WaitableEvent* done);
void DecodeNextFragmentTask();
// Called by the renderer in response to a CreatePictureBuffers request.
void OnPictureBuffersCreatedTask(std::vector<PictureBuffer> buffers);
// Called by the renderer in response to a RenderPicture request.
void OnPictureRenderedTask(int32_t picture_buffer_id);
// Get the next bitstream buffer id to be used.
int32_t GetNextBitstreamBufferId();
VideoPlayer::EventCallback event_cb_;
FrameRenderer* const frame_renderer_;
std::unique_ptr<GpuVideoDecodeAcceleratorFactory> decoder_factory_;
std::unique_ptr<VideoDecodeAccelerator> decoder_;
base::Thread decoder_client_thread_;
int32_t next_bitstream_buffer_id_ = 0;
// TODO(dstaessens@) Replace with StreamParser.
std::unique_ptr<media::test::EncodedDataHelper> encoded_data_helper_;
SEQUENCE_CHECKER(video_player_sequence_checker_);
SEQUENCE_CHECKER(decoder_client_sequence_checker_);
base::WeakPtr<VideoDecoderClient> weak_this_;
base::WeakPtrFactory<VideoDecoderClient> weak_this_factory_;
DISALLOW_COPY_AND_ASSIGN(VideoDecoderClient);
};
} // namespace test
} // namespace media
#endif // MEDIA_GPU_TEST_VIDEO_PLAYER_VIDEO_DECODER_CLIENT_H_
// 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/test/video_player/video_player.h"
#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "media/gpu/test/video_player/video.h"
#include "media/gpu/test/video_player/video_decoder_client.h"
#define DVLOGF(level) DVLOG(level) << __func__ << "(): "
namespace media {
namespace test {
VideoPlayer::VideoPlayer(const Video* video)
: video_(video),
video_player_state_(VideoPlayerState::kUninitialized),
event_cv_(&event_lock_),
video_player_event_counts_{} {}
VideoPlayer::~VideoPlayer() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DVLOGF(4);
Destroy();
}
// static
std::unique_ptr<VideoPlayer> VideoPlayer::Create(
const Video* video,
FrameRenderer* frame_renderer) {
DCHECK(video);
auto video_player = base::WrapUnique(new VideoPlayer(video));
if (!video_player->Initialize(frame_renderer)) {
return nullptr;
}
return video_player;
}
bool VideoPlayer::Initialize(FrameRenderer* frame_renderer) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_EQ(video_player_state_, VideoPlayerState::kUninitialized);
DCHECK(frame_renderer);
DVLOGF(4);
EventCallback event_cb =
base::BindRepeating(&VideoPlayer::NotifyEvent, base::Unretained(this));
decoder_client_ = VideoDecoderClient::Create(event_cb, frame_renderer);
CHECK(decoder_client_) << "Failed to create decoder client";
video_player_state_ = VideoPlayerState::kIdle;
return true;
}
void VideoPlayer::Destroy() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_NE(video_player_state_, VideoPlayerState::kDestroyed);
DVLOGF(4);
decoder_client_.reset();
video_player_state_ = VideoPlayerState::kDestroyed;
}
void VideoPlayer::Play() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_EQ(video_player_state_, VideoPlayerState::kIdle);
DVLOGF(4);
// Create a decoder for the specified video.
VideoDecodeAccelerator::Config decoder_config(video_->GetProfile());
decoder_client_->CreateDecoder(decoder_config, video_->GetData());
// Start decoding the video.
video_player_state_ = VideoPlayerState::kDecoding;
decoder_client_->DecodeNextFragment();
}
void VideoPlayer::Stop() {
NOTIMPLEMENTED();
}
void VideoPlayer::Reset() {
NOTIMPLEMENTED();
}
void VideoPlayer::Flush() {
NOTIMPLEMENTED();
}
base::TimeDelta VideoPlayer::GetCurrentTime() const {
NOTIMPLEMENTED();
return base::TimeDelta();
}
size_t VideoPlayer::GetCurrentFrame() const {
NOTIMPLEMENTED();
return 0;
}
VideoPlayerState VideoPlayer::GetState() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::AutoLock auto_lock(event_lock_);
return video_player_state_;
}
size_t VideoPlayer::GetEventCount(VideoPlayerEvent event) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::AutoLock auto_lock(event_lock_);
return video_player_event_counts_[static_cast<size_t>(event)];
}
bool VideoPlayer::WaitForEvent(VideoPlayerEvent event,
base::TimeDelta max_wait) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DVLOGF(4) << "Event ID: " << static_cast<size_t>(event);
static size_t event_id = 0;
base::TimeDelta time_waiting;
base::AutoLock auto_lock(event_lock_);
while (true) {
const base::TimeTicks start_time = base::TimeTicks::Now();
event_cv_.TimedWait(max_wait);
time_waiting += base::TimeTicks::Now() - start_time;
// Go through list of events since last wait, looking for the event we're
// interested in.
for (; event_id < video_player_events_.size(); ++event_id) {
if (video_player_events_[event_id] == event) {
event_id++;
return true;
}
}
// Check whether we've exceeded the maximum time we're allowed to wait.
if (time_waiting >= max_wait)
return false;
}
}
void VideoPlayer::NotifyEvent(VideoPlayerEvent event) {
base::AutoLock auto_lock(event_lock_);
if (event == VideoPlayerEvent::kFlushDone)
video_player_state_ = VideoPlayerState::kIdle;
video_player_events_.push_back(event);
video_player_event_counts_[static_cast<size_t>(event)]++;
event_cv_.Signal();
}
} // namespace test
} // namespace media
// 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.
#ifndef MEDIA_GPU_TEST_VIDEO_PLAYER_VIDEO_PLAYER_H_
#define MEDIA_GPU_TEST_VIDEO_PLAYER_VIDEO_PLAYER_H_
#include <memory>
#include <vector>
#include "base/callback.h"
#include "base/macros.h"
#include "base/sequence_checker.h"
#include "base/synchronization/condition_variable.h"
#include "base/synchronization/lock.h"
#include "base/thread_annotations.h"
namespace media {
namespace test {
class FrameRenderer;
class VideoDecoderClient;
class Video;
enum class VideoPlayerState : size_t {
kUninitialized = 0,
kIdle,
kDecoding,
kDestroyed,
};
enum class VideoPlayerEvent : size_t {
kFlushDone,
kFrameDecoded,
kNumEvents,
};
// The video player provides a framework to build video decode accelerator tests
// upon. It provides methods to manipulate video playback, and wait for specific
// events to occur.
class VideoPlayer {
public:
using EventCallback = base::RepeatingCallback<void(VideoPlayerEvent)>;
~VideoPlayer();
// Return an instance of the video player. The |video| and |frame_renderer|
// will not be owned by the video player. The caller should guarantee they
// exist for the entire lifetime of the video player.
static std::unique_ptr<VideoPlayer> Create(const Video* video,
FrameRenderer* frame_renderer);
void Play();
void Stop();
void Reset();
void Flush();
// Get current media time.
base::TimeDelta GetCurrentTime() const;
// Get the current frame number.
size_t GetCurrentFrame() const;
// Get the current state of the video player.
VideoPlayerState GetState() const;
// Wait for the specified event to occur, will return immediately if the event
// already occurred. All events with different types that precede the
// specified event will be consumed. Will return false if the specified
// timeout is exceeded while waiting for the event.
bool WaitForEvent(
VideoPlayerEvent event,
base::TimeDelta max_wait = base::TimeDelta::FromSeconds(10));
// Get the number of times the specified event occurred.
size_t GetEventCount(VideoPlayerEvent event) const;
private:
explicit VideoPlayer(const Video* video);
bool Initialize(FrameRenderer* frame_renderer);
void Destroy();
// Notify the client an event has occurred (e.g. frame decoded).
void NotifyEvent(VideoPlayerEvent event);
const Video* video_;
VideoPlayerState video_player_state_;
std::unique_ptr<VideoDecoderClient> decoder_client_;
mutable base::Lock event_lock_;
base::ConditionVariable event_cv_;
std::vector<VideoPlayerEvent> video_player_events_ GUARDED_BY(event_lock_);
size_t video_player_event_counts_[static_cast<size_t>(
VideoPlayerEvent::kNumEvents)] GUARDED_BY(event_lock_);
SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(VideoPlayer);
};
} // namespace test
} // namespace media
#endif // MEDIA_GPU_TEST_VIDEO_PLAYER_VIDEO_PLAYER_H_
// 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 "base/at_exit.h"
#include "base/command_line.h"
#include "base/test/scoped_task_environment.h"
#include "media/base/test_data_util.h"
#include "media/gpu/buildflags.h"
#include "media/gpu/test/video_player/frame_renderer_dummy.h"
#include "media/gpu/test/video_player/video.h"
#include "media/gpu/test/video_player/video_collection.h"
#include "media/gpu/test/video_player/video_player.h"
#include "testing/gtest/include/gtest/gtest.h"
#if BUILDFLAG(USE_VAAPI)
#include "media/gpu/vaapi/vaapi_wrapper.h"
#endif
namespace media {
namespace test {
// TODO(dstaessens@)
// * Use a fixture here (TEST_F) with a testing environment that contains all
// required setup code.
// * Fetch the expected number of frames from the video file's metadata.
TEST(VideoDecodeAcceleratorTest, BasicPlayTest) {
auto renderer = FrameRendererDummy::Create();
CHECK(renderer) << "Failed to create renderer";
const Video* video = &kDefaultTestVideoCollection[0];
auto tvp = VideoPlayer::Create(video, renderer.get());
CHECK(tvp) << "Failed to create video player";
tvp->Play();
EXPECT_TRUE(tvp->WaitForEvent(VideoPlayerEvent::kFlushDone));
EXPECT_EQ(tvp->GetEventCount(VideoPlayerEvent::kFlushDone), 1u);
EXPECT_EQ(tvp->GetEventCount(VideoPlayerEvent::kFrameDecoded), 250u);
}
} // namespace test
} // namespace media
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
base::CommandLine::Init(argc, argv);
base::AtExitManager exit_manager;
// Needed to enable DVLOG through --vmodule.
logging::LoggingSettings settings;
settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
LOG_ASSERT(logging::InitLogging(settings));
// Setting up a task environment will create a task runner for the current
// thread and allow posting tasks to other threads. This is required for the
// test video player to function.
base::test::ScopedTaskEnvironment scoped_task_environment(
base::test::ScopedTaskEnvironment::MainThreadType::UI);
// Set the default test data path.
media::test::Video::SetTestDataPath(media::GetTestDataPath());
#if BUILDFLAG(USE_VAAPI)
media::VaapiWrapper::PreSandboxInitialization();
#endif
return RUN_ALL_TESTS();
}
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