summaryrefslogtreecommitdiffstats
path: root/content/common/gpu/media
diff options
context:
space:
mode:
authoryuli@chromium.org <yuli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-01 18:22:02 +0000
committeryuli@chromium.org <yuli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-01 18:22:02 +0000
commit6c37fa59b3eb9c888b9d32d0f7765626bc093cde (patch)
tree0fa2ad82e9de3e441f89526356ab2056557a7aea /content/common/gpu/media
parente61b6d83c90d26fd82edace55599139e0adfde8e (diff)
downloadchromium_src-6c37fa59b3eb9c888b9d32d0f7765626bc093cde.zip
chromium_src-6c37fa59b3eb9c888b9d32d0f7765626bc093cde.tar.gz
chromium_src-6c37fa59b3eb9c888b9d32d0f7765626bc093cde.tar.bz2
Support multiple test streams as input for VDA tests.
Extend the existing flags and functions to take multiple streams as test input. BUG=chrome-os-partner:17620 Review URL: https://chromiumcodereview.appspot.com/12334102 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@185553 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/common/gpu/media')
-rw-r--r--content/common/gpu/media/rendering_helper.h8
-rw-r--r--content/common/gpu/media/rendering_helper_gl.cc51
-rw-r--r--content/common/gpu/media/rendering_helper_mac.mm19
-rw-r--r--content/common/gpu/media/video_decode_accelerator_unittest.cc186
4 files changed, 153 insertions, 111 deletions
diff --git a/content/common/gpu/media/rendering_helper.h b/content/common/gpu/media/rendering_helper.h
index 94a4299..3a883c4 100644
--- a/content/common/gpu/media/rendering_helper.h
+++ b/content/common/gpu/media/rendering_helper.h
@@ -5,7 +5,10 @@
#ifndef CONTENT_COMMON_GPU_MEDIA_RENDERING_HELPER_H_
#define CONTENT_COMMON_GPU_MEDIA_RENDERING_HELPER_H_
+#include <vector>
+
#include "base/basictypes.h"
+#include "ui/gfx/size.h"
namespace base {
class WaitableEvent;
@@ -27,11 +30,10 @@ class RenderingHelper {
RenderingHelper() {}
virtual ~RenderingHelper() {}
- // Create the window and render context.
+ // Create the render context and windows by the specified dimensions.
virtual void Initialize(bool suppress_swap_to_display,
int num_windows,
- int width,
- int height,
+ const std::vector<gfx::Size>& dimensions,
base::WaitableEvent* done) = 0;
// Undo the effects of Initialize() and signal |*done|.
diff --git a/content/common/gpu/media/rendering_helper_gl.cc b/content/common/gpu/media/rendering_helper_gl.cc
index 80c2d52..6ea4bed 100644
--- a/content/common/gpu/media/rendering_helper_gl.cc
+++ b/content/common/gpu/media/rendering_helper_gl.cc
@@ -97,8 +97,7 @@ class RenderingHelperGL : public RenderingHelper {
// Implement RenderingHelper.
virtual void Initialize(bool suppress_swap_to_display,
int num_windows,
- int width,
- int height,
+ const std::vector<gfx::Size>& dimensions,
base::WaitableEvent* done) OVERRIDE;
virtual void UnInitialize(base::WaitableEvent* done) OVERRIDE;
virtual void CreateTexture(int window_id,
@@ -121,8 +120,7 @@ class RenderingHelperGL : public RenderingHelper {
MessageLoop* message_loop_;
- int width_;
- int height_;
+ std::vector<gfx::Size> dimensions_;
bool suppress_swap_to_display_;
NativeContextType gl_context_;
@@ -169,7 +167,7 @@ RenderingHelperGL::RenderingHelperGL() {
}
RenderingHelperGL::~RenderingHelperGL() {
- CHECK_EQ(width_, 0) << "Must call UnInitialize before dtor.";
+ CHECK_EQ(dimensions_.size(), 0U) << "Must call UnInitialize before dtor.";
Clear();
}
@@ -193,14 +191,14 @@ void RenderingHelperGL::MakeCurrent(int window_id) {
#endif
}
-void RenderingHelperGL::Initialize(bool suppress_swap_to_display,
- int num_windows,
- int width,
- int height,
- base::WaitableEvent* done) {
- // Use width_ != 0 as a proxy for the class having already been
+void RenderingHelperGL::Initialize(
+ bool suppress_swap_to_display,
+ int num_windows,
+ const std::vector<gfx::Size>& dimensions,
+ base::WaitableEvent* done) {
+ // Use dimensions_.size() != 0 as a proxy for the class having already been
// Initialize()'d, and UnInitialize() before continuing.
- if (width_) {
+ if (dimensions_.size()) {
base::WaitableEvent done(false, false);
UnInitialize(&done);
done.Wait();
@@ -209,10 +207,9 @@ void RenderingHelperGL::Initialize(bool suppress_swap_to_display,
scoped_refptr<GLContextStubWithExtensions> stub_context(
new GLContextStubWithExtensions());
suppress_swap_to_display_ = suppress_swap_to_display;
- CHECK_GT(width, 0);
- CHECK_GT(height, 0);
- width_ = width;
- height_ = height;
+
+ CHECK_GT(dimensions.size(), 0U);
+ dimensions_ = dimensions;
message_loop_ = MessageLoop::current();
CHECK_GT(num_windows, 0);
@@ -282,6 +279,11 @@ void RenderingHelperGL::Initialize(bool suppress_swap_to_display,
// Per-window/surface X11 & EGL initialization.
for (int i = 0; i < num_windows; ++i) {
// Arrange X windows whimsically, with some padding.
+ int j = i % dimensions_.size();
+ int width = dimensions_[j].width();
+ int height = dimensions_[j].height();
+ CHECK_GT(width, 0);
+ CHECK_GT(height, 0);
int top_left_x = (width + 20) * (i % 4);
int top_left_y = (height + 12) * (i % 3);
@@ -289,7 +291,7 @@ void RenderingHelperGL::Initialize(bool suppress_swap_to_display,
NativeWindowType window =
CreateWindowEx(0, L"Static", L"VideoDecodeAcceleratorTest",
WS_OVERLAPPEDWINDOW | WS_VISIBLE, top_left_x,
- top_left_y, width_, height_, NULL, NULL, NULL,
+ top_left_y, width, height, NULL, NULL, NULL,
NULL);
CHECK(window != NULL);
windows_.push_back(window);
@@ -307,7 +309,7 @@ void RenderingHelperGL::Initialize(bool suppress_swap_to_display,
NativeWindowType window = XCreateWindow(
x_display_, DefaultRootWindow(x_display_),
- top_left_x, top_left_y, width_, height_,
+ top_left_x, top_left_y, width, height,
0 /* border width */,
depth, CopyFromParent /* class */, CopyFromParent /* visual */,
(CWBackPixel | CWOverrideRedirect), &window_attributes);
@@ -412,9 +414,9 @@ void RenderingHelperGL::UnInitialize(base::WaitableEvent* done) {
}
void RenderingHelperGL::CreateTexture(int window_id,
- uint32 texture_target,
- uint32* texture_id,
- base::WaitableEvent* done) {
+ uint32 texture_target,
+ uint32* texture_id,
+ base::WaitableEvent* done) {
if (MessageLoop::current() != message_loop_) {
message_loop_->PostTask(
FROM_HERE,
@@ -426,7 +428,9 @@ void RenderingHelperGL::CreateTexture(int window_id,
MakeCurrent(window_id);
glGenTextures(1, texture_id);
glBindTexture(GL_TEXTURE_2D, *texture_id);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, GL_RGBA,
+ int dimensions_id = window_id % dimensions_.size();
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dimensions_[dimensions_id].width(),
+ dimensions_[dimensions_id].height(), 0, GL_RGBA,
GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -477,8 +481,7 @@ void* RenderingHelperGL::GetGLDisplay() {
void RenderingHelperGL::Clear() {
suppress_swap_to_display_ = false;
- width_ = 0;
- height_ = 0;
+ dimensions_.clear();
texture_id_to_surface_index_.clear();
message_loop_ = NULL;
gl_context_ = NULL;
diff --git a/content/common/gpu/media/rendering_helper_mac.mm b/content/common/gpu/media/rendering_helper_mac.mm
index 1a58646..a315791 100644
--- a/content/common/gpu/media/rendering_helper_mac.mm
+++ b/content/common/gpu/media/rendering_helper_mac.mm
@@ -87,8 +87,7 @@ class RenderingHelperMac : public RenderingHelper {
// Implement RenderingHelper.
virtual void Initialize(bool suppress_swap_to_display,
int num_windows,
- int width,
- int height,
+ const std::vector<gfx::Size>& dimensions,
base::WaitableEvent* done) OVERRIDE;
virtual void UnInitialize(base::WaitableEvent* done) OVERRIDE;
virtual void CreateTexture(int window_id,
@@ -133,11 +132,11 @@ RenderingHelperMac::~RenderingHelperMac() {
CHECK_EQ(width_, 0) << "Must call UnInitialize before dtor.";
}
-void RenderingHelperMac::Initialize(bool suppress_swap_to_display,
- int num_windows,
- int width,
- int height,
- base::WaitableEvent* done) {
+void RenderingHelperMac::Initialize(
+ bool suppress_swap_to_display,
+ int num_windows,
+ const std::vector<gfx::Size>& dimensions,
+ base::WaitableEvent* done) {
// Use width_ != 0 as a proxy for the class having already been
// Initialize()'d, and UnInitialize() before continuing.
if (width_) {
@@ -150,8 +149,10 @@ void RenderingHelperMac::Initialize(bool suppress_swap_to_display,
// only supports a single instance only one window should be created.
CHECK_EQ(num_windows, 1);
- width_ = width;
- height_ = height;
+ // There should be only one window dimension as only one window is created.
+ CHECK_EQ(dimensions.size(), 1U);
+ width_ = dimensions[0].width();
+ height_ = dimensions[0].height();
suppress_swap_to_display_ = suppress_swap_to_display;
message_loop_ = MessageLoop::current();
diff --git a/content/common/gpu/media/video_decode_accelerator_unittest.cc b/content/common/gpu/media/video_decode_accelerator_unittest.cc
index 8e6a71d..dd6c137 100644
--- a/content/common/gpu/media/video_decode_accelerator_unittest.cc
+++ b/content/common/gpu/media/video_decode_accelerator_unittest.cc
@@ -63,7 +63,11 @@ namespace content {
namespace {
// Values optionally filled in from flags; see main() below.
-// The syntax of this variable is:
+// The syntax of multiple test videos is:
+// test-video1;test-video2;test-video3
+// where only the first video is required and other optional videos would be
+// decoded by concurrent decoders.
+// The syntax of each test-video is:
// filename:width:height:numframes:numfragments:minFPSwithRender:minFPSnoRender
// where only the first field is required. Value details:
// - |filename| must be an h264 Annex B (NAL) stream or an IVF VP8 stream.
@@ -79,47 +83,81 @@ namespace {
const base::FilePath::CharType* test_video_data =
FILE_PATH_LITERAL("test-25fps_high.h264:1280:720:250:252:50:100:4");
#else
-// TODO(fischman): figure out how to support multiple test videos per run (needs
-// to refactor where ParseTestVideoData is called). For now just make it easy
-// to replace which file is used by commenting/uncommenting these lines:
const base::FilePath::CharType* test_video_data =
// FILE_PATH_LITERAL("test-25fps.vp8:320:240:250:250:50:175:11");
FILE_PATH_LITERAL("test-25fps.h264:320:240:250:258:50:175:1");
#endif
-// Parse |data| into its constituent parts and set the various output fields
-// accordingly. CHECK-fails on unexpected or missing required data.
-// Unspecified optional fields are set to -1.
-void ParseTestVideoData(base::FilePath::StringType data,
- base::FilePath::StringType* file_name,
- int* width, int* height,
- int* num_frames,
- int* num_fragments,
- int* min_fps_render,
- int* min_fps_no_render,
- int* profile) {
- std::vector<base::FilePath::StringType> elements;
- base::SplitString(data, ':', &elements);
- CHECK_GE(elements.size(), 1U) << data;
- CHECK_LE(elements.size(), 8U) << data;
- *file_name = elements[0];
- *width = *height = *num_frames = *num_fragments = -1;
- *min_fps_render = *min_fps_no_render = -1;
- *profile = -1;
- if (!elements[1].empty())
- CHECK(base::StringToInt(elements[1], width));
- if (!elements[2].empty())
- CHECK(base::StringToInt(elements[2], height));
- if (!elements[3].empty())
- CHECK(base::StringToInt(elements[3], num_frames));
- if (!elements[4].empty())
- CHECK(base::StringToInt(elements[4], num_fragments));
- if (!elements[5].empty())
- CHECK(base::StringToInt(elements[5], min_fps_render));
- if (!elements[6].empty())
- CHECK(base::StringToInt(elements[6], min_fps_no_render));
- if (!elements[7].empty())
- CHECK(base::StringToInt(elements[7], profile));
+struct TestVideoFile {
+ explicit TestVideoFile(base::FilePath::StringType file_name)
+ : file_name(file_name),
+ width(-1),
+ height(-1),
+ num_frames(-1),
+ num_fragments(-1),
+ min_fps_render(-1),
+ min_fps_no_render(-1),
+ profile(-1) {
+ }
+
+ base::FilePath::StringType file_name;
+ int width;
+ int height;
+ int num_frames;
+ int num_fragments;
+ int min_fps_render;
+ int min_fps_no_render;
+ int profile;
+ std::string data_str;
+};
+
+// Parse |data| into its constituent parts, set the various output fields
+// accordingly, and read in video stream. CHECK-fails on unexpected or
+// missing required data. Unspecified optional fields are set to -1.
+void ParseAndReadTestVideoData(base::FilePath::StringType data,
+ size_t num_concurrent_decoders,
+ int reset_after_frame_num,
+ std::vector<TestVideoFile*>* test_video_files) {
+ std::vector<base::FilePath::StringType> entries;
+ base::SplitString(data, ';', &entries);
+ CHECK_GE(entries.size(), 1U) << data;
+ for (size_t index = 0; index < entries.size(); ++index) {
+ std::vector<base::FilePath::StringType> fields;
+ base::SplitString(entries[index], ':', &fields);
+ CHECK_GE(fields.size(), 1U) << entries[index];
+ CHECK_LE(fields.size(), 8U) << entries[index];
+ TestVideoFile* video_file = new TestVideoFile(fields[0]);
+ if (!fields[1].empty())
+ CHECK(base::StringToInt(fields[1], &video_file->width));
+ if (!fields[2].empty())
+ CHECK(base::StringToInt(fields[2], &video_file->height));
+ if (!fields[3].empty()) {
+ CHECK(base::StringToInt(fields[3], &video_file->num_frames));
+ // If we reset mid-stream and start playback over, account for frames
+ // that are decoded twice in our expectations.
+ if (video_file->num_frames > 0 && reset_after_frame_num >= 0)
+ video_file->num_frames += reset_after_frame_num;
+ }
+ if (!fields[4].empty())
+ CHECK(base::StringToInt(fields[4], &video_file->num_fragments));
+ if (!fields[5].empty()) {
+ CHECK(base::StringToInt(fields[5], &video_file->min_fps_render));
+ video_file->min_fps_render /= num_concurrent_decoders;
+ }
+ if (!fields[6].empty()) {
+ CHECK(base::StringToInt(fields[6], &video_file->min_fps_no_render));
+ video_file->min_fps_no_render /= num_concurrent_decoders;
+ }
+ if (!fields[7].empty())
+ CHECK(base::StringToInt(fields[7], &video_file->profile));
+
+ // Read in the video data.
+ base::FilePath filepath(video_file->file_name);
+ CHECK(file_util::ReadFileToString(filepath, &video_file->data_str))
+ << "test_video_file: " << filepath.MaybeAsASCII();
+
+ test_video_files->push_back(video_file);
+ }
}
// State of the GLRenderingVDAClient below. Order matters here as the test
@@ -200,17 +238,17 @@ class GLRenderingVDAClient : public VideoDecodeAccelerator::Client {
// Both |reset_after_frame_num| & |delete_decoder_state| apply only to the
// last play-through (governed by |num_play_throughs|).
GLRenderingVDAClient(RenderingHelper* rendering_helper,
- int rendering_window_id,
- ClientStateNotification* note,
- const std::string& encoded_data,
- int num_fragments_per_decode,
- int num_in_flight_decodes,
- int num_play_throughs,
- int reset_after_frame_num,
- int delete_decoder_state,
- int frame_width,
- int frame_height,
- int profile);
+ int rendering_window_id,
+ ClientStateNotification* note,
+ const std::string& encoded_data,
+ int num_fragments_per_decode,
+ int num_in_flight_decodes,
+ int num_play_throughs,
+ int reset_after_frame_num,
+ int delete_decoder_state,
+ int frame_width,
+ int frame_height,
+ int profile);
virtual ~GLRenderingVDAClient();
void CreateDecoder();
@@ -694,19 +732,9 @@ TEST_P(VideoDecodeAcceleratorTest, TestSimpleDecode) {
const int reset_after_frame_num = GetParam().e;
const int delete_decoder_state = GetParam().f;
- base::FilePath::StringType test_video_file;
- int frame_width, frame_height;
- int num_frames, num_fragments, min_fps_render, min_fps_no_render, profile;
- ParseTestVideoData(test_video_data, &test_video_file, &frame_width,
- &frame_height, &num_frames, &num_fragments,
- &min_fps_render, &min_fps_no_render, &profile);
- min_fps_render /= num_concurrent_decoders;
- min_fps_no_render /= num_concurrent_decoders;
-
- // If we reset mid-stream and start playback over, account for frames that are
- // decoded twice in our expectations.
- if (num_frames > 0 && reset_after_frame_num >= 0)
- num_frames += reset_after_frame_num;
+ std::vector<TestVideoFile*> test_video_files;
+ ParseAndReadTestVideoData(test_video_data, num_concurrent_decoders,
+ reset_after_frame_num, &test_video_files);
// Suppress GL swapping in all but a few tests, to cut down overall test
// runtime.
@@ -715,12 +743,6 @@ TEST_P(VideoDecodeAcceleratorTest, TestSimpleDecode) {
std::vector<ClientStateNotification*> notes(num_concurrent_decoders, NULL);
std::vector<GLRenderingVDAClient*> clients(num_concurrent_decoders, NULL);
- // Read in the video data.
- std::string data_str;
- CHECK(file_util::ReadFileToString(base::FilePath(test_video_file),
- &data_str))
- << "test_video_file: " << base::FilePath(test_video_file).MaybeAsASCII();
-
// Initialize the rendering helper.
base::Thread rendering_thread("GLRenderingVDAClientThread");
base::Thread::Options options;
@@ -735,22 +757,30 @@ TEST_P(VideoDecodeAcceleratorTest, TestSimpleDecode) {
scoped_ptr<RenderingHelper> rendering_helper(RenderingHelper::Create());
base::WaitableEvent done(false, false);
+ std::vector<gfx::Size> frame_dimensions;
+ for (size_t index = 0; index < test_video_files.size(); ++index) {
+ frame_dimensions.push_back(gfx::Size(
+ test_video_files[index]->width, test_video_files[index]->height));
+ }
rendering_thread.message_loop()->PostTask(
FROM_HERE,
base::Bind(&RenderingHelper::Initialize,
base::Unretained(rendering_helper.get()),
suppress_swap_to_display, num_concurrent_decoders,
- frame_width, frame_height, &done));
+ frame_dimensions, &done));
done.Wait();
// First kick off all the decoders.
for (size_t index = 0; index < num_concurrent_decoders; ++index) {
+ TestVideoFile* video_file =
+ test_video_files[index % test_video_files.size()];
ClientStateNotification* note = new ClientStateNotification();
notes[index] = note;
GLRenderingVDAClient* client = new GLRenderingVDAClient(
- rendering_helper.get(), index, note, data_str, num_fragments_per_decode,
- num_in_flight_decodes, num_play_throughs, reset_after_frame_num,
- delete_decoder_state, frame_width, frame_height, profile);
+ rendering_helper.get(), index, note, video_file->data_str,
+ num_fragments_per_decode, num_in_flight_decodes, num_play_throughs,
+ reset_after_frame_num, delete_decoder_state, video_file->width,
+ video_file->height, video_file->profile);
clients[index] = client;
rendering_thread.message_loop()->PostTask(
@@ -807,17 +837,19 @@ TEST_P(VideoDecodeAcceleratorTest, TestSimpleDecode) {
if (delete_decoder_state < CS_FLUSHED)
continue;
GLRenderingVDAClient* client = clients[i];
- if (num_frames > 0)
- EXPECT_EQ(client->num_decoded_frames(), num_frames);
+ TestVideoFile* video_file = test_video_files[i % test_video_files.size()];
+ if (video_file->num_frames > 0)
+ EXPECT_EQ(client->num_decoded_frames(), video_file->num_frames);
if (reset_after_frame_num < 0) {
- EXPECT_EQ(num_fragments, client->num_skipped_fragments() +
+ EXPECT_EQ(video_file->num_fragments, client->num_skipped_fragments() +
client->num_queued_fragments());
EXPECT_EQ(client->num_done_bitstream_buffers(),
ceil(static_cast<double>(client->num_queued_fragments()) /
num_fragments_per_decode));
}
LOG(INFO) << "Decoder " << i << " fps: " << client->frames_per_second();
- int min_fps = suppress_swap_to_display ? min_fps_no_render : min_fps_render;
+ int min_fps = suppress_swap_to_display ?
+ video_file->min_fps_no_render : video_file->min_fps_render;
if (min_fps > 0)
EXPECT_GT(client->frames_per_second(), min_fps);
}
@@ -832,6 +864,10 @@ TEST_P(VideoDecodeAcceleratorTest, TestSimpleDecode) {
&notes));
rendering_thread.message_loop()->PostTask(
FROM_HERE,
+ base::Bind(&STLDeleteElements<std::vector<TestVideoFile*> >,
+ &test_video_files));
+ rendering_thread.message_loop()->PostTask(
+ FROM_HERE,
base::Bind(&RenderingHelper::UnInitialize,
base::Unretained(rendering_helper.get()),
&done));