Skip to content

Commit

Permalink
media/gpu/test: Allow video frame validator to write corrupted frames…
Browse files Browse the repository at this point in the history
… to disk.

This CL adds functionality to the new video_decode_accelerator_tests to write
frames that fail frame validation to disk. The "--output_frames" parameter now
takes "all" and "corrupt" as possible values. If "corrupt" is specified the
number of frames written to disk is limited to 3 by default, to avoid generating
to may artifacts in Tast tests.

TEST=ran new VDA tests on eve

BUG=962354

Change-Id: Iad086c099d486e05b343d6fe6550807007ef1c92
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1609025
Commit-Queue: David Staessens <dstaessens@chromium.org>
Reviewed-by: Hirokazu Honda <hiroh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#701872}
  • Loading branch information
David Staessens authored and Commit Bot committed Oct 2, 2019
1 parent 95e8cb4 commit d404124
Show file tree
Hide file tree
Showing 9 changed files with 127 additions and 47 deletions.
5 changes: 3 additions & 2 deletions docs/media/gpu/video_decoder_test_usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,9 @@ Multiple command line arguments can be given to the command:
--vmodule enable verbose mode for the specified module,
e.g. --vmodule=*media/gpu*=2.
--disable_validator disable frame validation.
--output_frames write all decoded video frames to the
"<testname>" folder.
--output_frames write the selected video frames to disk, possible
values are "all|corrupt", the default output folder
is "<testname>".
--output_folder overwrite the default output folder used when
"--output_frames" is specified.
--use_vd use the new VD-based video decoders, instead of
Expand Down
17 changes: 13 additions & 4 deletions media/gpu/test/video_frame_file_writer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ namespace media {
namespace test {

VideoFrameFileWriter::VideoFrameFileWriter(const base::FilePath& output_folder,
OutputFormat output_format)
OutputFormat output_format,
size_t output_limit)
: output_folder_(output_folder),
output_format_(output_format),
output_limit_(output_limit),
num_frames_writing_(0),
frame_writer_thread_("FrameWriterThread"),
frame_writer_cv_(&frame_writer_lock_) {
Expand All @@ -40,7 +42,8 @@ VideoFrameFileWriter::~VideoFrameFileWriter() {
// static
std::unique_ptr<VideoFrameFileWriter> VideoFrameFileWriter::Create(
const base::FilePath& output_folder,
OutputFormat output_format) {
OutputFormat output_format,
size_t output_limit) {
// If the directory is not absolute, consider it relative to our working dir.
base::FilePath resolved_output_folder(output_folder);
if (!resolved_output_folder.IsAbsolute()) {
Expand All @@ -58,8 +61,8 @@ std::unique_ptr<VideoFrameFileWriter> VideoFrameFileWriter::Create(
return nullptr;
}

auto frame_file_writer = base::WrapUnique(
new VideoFrameFileWriter(resolved_output_folder, output_format));
auto frame_file_writer = base::WrapUnique(new VideoFrameFileWriter(
resolved_output_folder, output_format, output_limit));
if (!frame_file_writer->Initialize()) {
LOG(ERROR) << "Failed to initialize VideoFrameFileWriter";
return nullptr;
Expand All @@ -80,6 +83,12 @@ bool VideoFrameFileWriter::Initialize() {
void VideoFrameFileWriter::ProcessVideoFrame(
scoped_refptr<const VideoFrame> video_frame,
size_t frame_index) {
// Don't write more frames than the specified output limit.
if (num_frames_writes_requested_ >= output_limit_)
return;

num_frames_writes_requested_++;

base::AutoLock auto_lock(frame_writer_lock_);
num_frames_writing_++;

Expand Down
14 changes: 12 additions & 2 deletions media/gpu/test/video_frame_file_writer.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#ifndef MEDIA_GPU_TEST_VIDEO_FRAME_FILE_WRITER_H_
#define MEDIA_GPU_TEST_VIDEO_FRAME_FILE_WRITER_H_

#include <limits>
#include <memory>

#include "base/files/file_path.h"
Expand Down Expand Up @@ -34,9 +35,13 @@ class VideoFrameFileWriter : public VideoFrameProcessor {
~VideoFrameFileWriter() override;

// Create an instance of the video frame file writer.
// |output_folder| specifies the folder video frames will be written to.
// |output_format| specifies the output file format.
// |output_limit| limits the max number of files that can be written.
static std::unique_ptr<VideoFrameFileWriter> Create(
const base::FilePath& output_folder,
OutputFormat output_format = OutputFormat::kPNG);
OutputFormat output_format = OutputFormat::kPNG,
size_t output_limit = std::numeric_limits<size_t>::max());

// Interface VideoFrameProcessor
void ProcessVideoFrame(scoped_refptr<const VideoFrame> video_frame,
Expand All @@ -46,7 +51,8 @@ class VideoFrameFileWriter : public VideoFrameProcessor {

private:
VideoFrameFileWriter(const base::FilePath& output_folder,
OutputFormat output_format);
OutputFormat output_format,
size_t output_limit);

// Initialize the video frame file writer.
bool Initialize();
Expand All @@ -66,12 +72,16 @@ class VideoFrameFileWriter : public VideoFrameProcessor {
const base::FilePath output_folder_;
// Output format of the frames.
const OutputFormat output_format_;
// The maximum number of frames that can be written.
const size_t output_limit_;

// The video frame mapper used to gain access to the raw video frame memory.
std::unique_ptr<VideoFrameMapper> video_frame_mapper_;

// The number of frames currently queued for writing.
size_t num_frames_writing_ GUARDED_BY(frame_writer_lock_);
// The number of frames currently written or queued to be written.
size_t num_frames_writes_requested_ = 0u;

// Thread on which video frame writing is done.
base::Thread frame_writer_thread_;
Expand Down
16 changes: 13 additions & 3 deletions media/gpu/test/video_frame_validator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ namespace test {
// static
std::unique_ptr<VideoFrameValidator> VideoFrameValidator::Create(
const std::vector<std::string>& expected_frame_checksums,
const VideoPixelFormat validation_format) {
const VideoPixelFormat validation_format,
std::unique_ptr<VideoFrameProcessor> corrupt_frame_processor) {
auto video_frame_validator = base::WrapUnique(
new VideoFrameValidator(expected_frame_checksums, validation_format));
new VideoFrameValidator(expected_frame_checksums, validation_format,
std::move(corrupt_frame_processor)));
if (!video_frame_validator->Initialize()) {
LOG(ERROR) << "Failed to initialize VideoFrameValidator.";
return nullptr;
Expand All @@ -36,9 +38,11 @@ std::unique_ptr<VideoFrameValidator> VideoFrameValidator::Create(

VideoFrameValidator::VideoFrameValidator(
std::vector<std::string> expected_frame_checksums,
VideoPixelFormat validation_format)
VideoPixelFormat validation_format,
std::unique_ptr<VideoFrameProcessor> corrupt_frame_processor)
: expected_frame_checksums_(std::move(expected_frame_checksums)),
validation_format_(validation_format),
corrupt_frame_processor_(std::move(corrupt_frame_processor)),
num_frames_validating_(0),
frame_validator_thread_("FrameValidatorThread"),
frame_validator_cv_(&frame_validator_lock_) {
Expand Down Expand Up @@ -97,6 +101,9 @@ bool VideoFrameValidator::WaitUntilDone() {
frame_validator_cv_.Wait();
}

if (corrupt_frame_processor_ && !corrupt_frame_processor_->WaitUntilDone())
return false;

if (mismatched_frames_.size() > 0u) {
LOG(ERROR) << mismatched_frames_.size() << " frames failed to validate.";
return false;
Expand Down Expand Up @@ -148,6 +155,9 @@ void VideoFrameValidator::ProcessVideoFrameTask(
if (computed_md5 != expected_md5) {
mismatched_frames_.push_back(
MismatchedFrameInfo{frame_index, computed_md5, expected_md5});
// Perform additional processing on the corrupt video frame if requested.
if (corrupt_frame_processor_)
corrupt_frame_processor_->ProcessVideoFrame(video_frame, frame_index);
}
}

Expand Down
18 changes: 15 additions & 3 deletions media/gpu/test/video_frame_validator.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,15 @@ class VideoFrameValidator : public VideoFrameProcessor {
// Create an instance of the video frame validator. The calculated checksums
// will be compared to the values in |expected_frame_checksums|. If no
// checksums are provided only checksum calculation will be done.
// |validation_format| specifies the pixel format used when calculating the
// checksum. Pixel format conversion will be performed if required. The
// |corrupt_frame_processor| is an optional video frame processor that will be
// called on each frame that fails validation. Ownership of the corrupt frame
// processor will be transferred to the frame validator.
static std::unique_ptr<VideoFrameValidator> Create(
const std::vector<std::string>& expected_frame_checksums,
const VideoPixelFormat validation_format = PIXEL_FORMAT_I420);
const VideoPixelFormat validation_format = PIXEL_FORMAT_I420,
std::unique_ptr<VideoFrameProcessor> corrupt_frame_processor = nullptr);

~VideoFrameValidator() override;

Expand All @@ -71,8 +77,10 @@ class VideoFrameValidator : public VideoFrameProcessor {
bool WaitUntilDone() override;

private:
VideoFrameValidator(std::vector<std::string> expected_frame_checksums,
VideoPixelFormat validation_format);
VideoFrameValidator(
std::vector<std::string> expected_frame_checksums,
VideoPixelFormat validation_format,
std::unique_ptr<VideoFrameProcessor> corrupt_frame_processor);

// Start the frame validation thread.
bool Initialize();
Expand All @@ -98,6 +106,10 @@ class VideoFrameValidator : public VideoFrameProcessor {
// VideoPixelFormat the VideoFrame will be converted to for validation.
const VideoPixelFormat validation_format_;

// An optional video frame processor that all corrupted frames will be
// forwarded to. This can be used to e.g. write corrupted frames to disk.
const std::unique_ptr<VideoFrameProcessor> corrupt_frame_processor_;

// The number of frames currently queued for validation.
size_t num_frames_validating_ GUARDED_BY(frame_validator_lock_);

Expand Down
13 changes: 7 additions & 6 deletions media/gpu/test/video_player/video_player_test_environment.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ VideoPlayerTestEnvironment* VideoPlayerTestEnvironment::Create(
const base::FilePath& video_path,
const base::FilePath& video_metadata_path,
bool enable_validator,
bool output_frames,
FrameOutputMode frame_output_mode,
const base::FilePath& output_folder,
bool use_vd) {
auto video = std::make_unique<media::test::Video>(
Expand All @@ -34,18 +34,19 @@ VideoPlayerTestEnvironment* VideoPlayerTestEnvironment::Create(
}

return new VideoPlayerTestEnvironment(std::move(video), enable_validator,
output_frames, output_folder, use_vd);
frame_output_mode, output_folder,
use_vd);
}

VideoPlayerTestEnvironment::VideoPlayerTestEnvironment(
std::unique_ptr<media::test::Video> video,
bool enable_validator,
bool output_frames,
FrameOutputMode frame_output_mode,
const base::FilePath& output_folder,
bool use_vd)
: video_(std::move(video)),
enable_validator_(enable_validator),
output_frames_(output_frames),
frame_output_mode_(frame_output_mode),
output_folder_(output_folder),
use_vd_(use_vd) {}

Expand Down Expand Up @@ -81,8 +82,8 @@ bool VideoPlayerTestEnvironment::IsValidatorEnabled() const {
return enable_validator_;
}

bool VideoPlayerTestEnvironment::IsFramesOutputEnabled() const {
return output_frames_;
FrameOutputMode VideoPlayerTestEnvironment::GetFrameOutputMode() const {
return frame_output_mode_;
}

const base::FilePath& VideoPlayerTestEnvironment::OutputFolder() const {
Expand Down
20 changes: 15 additions & 5 deletions media/gpu/test/video_player/video_player_test_environment.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ namespace test {

class Video;

// The frame output mode allows controlling which video frames are written to
// disk. Writing frames will greatly slow down the test and generate a lot of
// test artifacts, so be careful when configuring other modes than kNone in
// automated testing.
enum class FrameOutputMode {
kNone, // Don't output any frames.
kCorrupt, // Only output corrupt frames.
kAll // Output all frames.
};

// Test environment for video decode tests. Performs setup and teardown once for
// the entire test run.
class VideoPlayerTestEnvironment : public VideoTestEnvironment {
Expand All @@ -23,7 +33,7 @@ class VideoPlayerTestEnvironment : public VideoTestEnvironment {
const base::FilePath& video_path,
const base::FilePath& video_metadata_path,
bool enable_validator,
bool output_frames,
FrameOutputMode frame_output_mode,
const base::FilePath& output_folder,
bool use_vd);
~VideoPlayerTestEnvironment() override;
Expand All @@ -35,8 +45,8 @@ class VideoPlayerTestEnvironment : public VideoTestEnvironment {
const media::test::Video* Video() const;
// Check whether frame validation is enabled.
bool IsValidatorEnabled() const;
// Check whether outputting frames is enabled.
bool IsFramesOutputEnabled() const;
// Get the frame output mode.
FrameOutputMode GetFrameOutputMode() const;
// Get the output folder.
const base::FilePath& OutputFolder() const;
// Check whether we should use VD-based video decoders instead of VDA-based.
Expand All @@ -47,13 +57,13 @@ class VideoPlayerTestEnvironment : public VideoTestEnvironment {
private:
VideoPlayerTestEnvironment(std::unique_ptr<media::test::Video> video,
bool enable_validator,
bool output_frames,
FrameOutputMode frame_output_mode,
const base::FilePath& output_folder,
bool use_vd);

const std::unique_ptr<media::test::Video> video_;
const bool enable_validator_;
const bool output_frames_;
const FrameOutputMode frame_output_mode_;
const base::FilePath output_folder_;
const bool use_vd_;
// TODO(dstaessens): Remove this once all allocate-only platforms reached EOL.
Expand Down
5 changes: 3 additions & 2 deletions media/gpu/video_decode_accelerator_perf_tests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -422,8 +422,9 @@ int main(int argc, char** argv) {
// Set up our test environment.
media::test::VideoPlayerTestEnvironment* test_environment =
media::test::VideoPlayerTestEnvironment::Create(
video_path, video_metadata_path, false, false,
base::FilePath(output_folder), use_vd);
video_path, video_metadata_path, false,
media::test::FrameOutputMode::kAll, base::FilePath(output_folder),
use_vd);
if (!test_environment)
return EXIT_FAILURE;

Expand Down
Loading

0 comments on commit d404124

Please sign in to comment.