diff options
author | yuli@chromium.org <yuli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-01 18:22:02 +0000 |
---|---|---|
committer | yuli@chromium.org <yuli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-01 18:22:02 +0000 |
commit | 6c37fa59b3eb9c888b9d32d0f7765626bc093cde (patch) | |
tree | 0fa2ad82e9de3e441f89526356ab2056557a7aea /content/common/gpu/media | |
parent | e61b6d83c90d26fd82edace55599139e0adfde8e (diff) | |
download | chromium_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.h | 8 | ||||
-rw-r--r-- | content/common/gpu/media/rendering_helper_gl.cc | 51 | ||||
-rw-r--r-- | content/common/gpu/media/rendering_helper_mac.mm | 19 | ||||
-rw-r--r-- | content/common/gpu/media/video_decode_accelerator_unittest.cc | 186 |
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) { ¬es)); 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)); |