OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 // | 4 // |
5 // The bulk of this file is support code; sorry about that. Here's an overview | 5 // The bulk of this file is support code; sorry about that. Here's an overview |
6 // to hopefully help readers of this code: | 6 // to hopefully help readers of this code: |
7 // - RenderingHelper is charged with interacting with X11/{EGL/GLES2,GLX/GL} or | 7 // - RenderingHelper is charged with interacting with X11/{EGL/GLES2,GLX/GL} or |
8 // Win/EGL. | 8 // Win/EGL. |
9 // - ClientState is an enum for the state of the decode client used by the test. | 9 // - ClientState is an enum for the state of the decode client used by the test. |
10 // - ClientStateNotification is a barrier abstraction that allows the test code | 10 // - ClientStateNotification is a barrier abstraction that allows the test code |
11 // to be written sequentially and wait for the decode client to see certain | 11 // to be written sequentially and wait for the decode client to see certain |
12 // state transitions. | 12 // state transitions. |
13 // - GLRenderingVDAClient is a VideoDecodeAccelerator::Client implementation | 13 // - GLRenderingVDAClient is a VideoDecodeAccelerator::Client implementation |
14 // - Finally actual TEST cases are at the bottom of this file, using the above | 14 // - Finally actual TEST cases are at the bottom of this file, using the above |
15 // infrastructure. | 15 // infrastructure. |
16 | 16 |
17 #include <fcntl.h> | 17 #include <fcntl.h> |
18 #include <sys/stat.h> | 18 #include <sys/stat.h> |
19 #include <sys/types.h> | 19 #include <sys/types.h> |
20 #include <algorithm> | |
20 #include <deque> | 21 #include <deque> |
22 #include <map> | |
21 | 23 |
22 // Include gtest.h out of order because <X11/X.h> #define's Bool & None, which | 24 // Include gtest.h out of order because <X11/X.h> #define's Bool & None, which |
23 // gtest uses as struct names (inside a namespace). This means that | 25 // gtest uses as struct names (inside a namespace). This means that |
24 // #include'ing gtest after anything that pulls in X.h fails to compile. | 26 // #include'ing gtest after anything that pulls in X.h fails to compile. |
25 // This is http://code.google.com/p/googletest/issues/detail?id=371 | 27 // This is http://code.google.com/p/googletest/issues/detail?id=371 |
26 #include "testing/gtest/include/gtest/gtest.h" | 28 #include "testing/gtest/include/gtest/gtest.h" |
27 | 29 |
28 #include "base/at_exit.h" | 30 #include "base/at_exit.h" |
29 #include "base/bind.h" | 31 #include "base/bind.h" |
30 #include "base/command_line.h" | 32 #include "base/command_line.h" |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
82 // - |minFPSwithRender| and |minFPSnoRender| are minimum frames/second speeds | 84 // - |minFPSwithRender| and |minFPSnoRender| are minimum frames/second speeds |
83 // expected to be achieved with and without rendering to the screen, resp. | 85 // expected to be achieved with and without rendering to the screen, resp. |
84 // (the latter tests just decode speed). | 86 // (the latter tests just decode speed). |
85 // - |profile| is the media::VideoCodecProfile set during Initialization. | 87 // - |profile| is the media::VideoCodecProfile set during Initialization. |
86 // An empty value for a numeric field means "ignore". | 88 // An empty value for a numeric field means "ignore". |
87 const base::FilePath::CharType* g_test_video_data = | 89 const base::FilePath::CharType* g_test_video_data = |
88 // FILE_PATH_LITERAL("test-25fps.vp8:320:240:250:250:50:175:11"); | 90 // FILE_PATH_LITERAL("test-25fps.vp8:320:240:250:250:50:175:11"); |
89 FILE_PATH_LITERAL("test-25fps.h264:320:240:250:258:50:175:1"); | 91 FILE_PATH_LITERAL("test-25fps.h264:320:240:250:258:50:175:1"); |
90 | 92 |
91 // The path of the frame delivery time log. We can enable the log and specify | 93 // The path of the frame delivery time log. We can enable the log and specify |
92 // the filename by the "--frame_delivery_log" switch. | 94 // the filename by the "--frame_delivery_log" or "--output_log" switch. |
Ami GONE FROM CHROMIUM
2013/11/04 18:26:51
If the log is for more general purposes than just
wuchengli
2013/11/05 06:24:15
Done.
| |
93 const base::FilePath::CharType* g_frame_delivery_log = NULL; | 95 const base::FilePath::CharType* g_output_log = NULL; |
94 | 96 |
95 // The value is set by the switch "--rendering_fps". | 97 // The value is set by the switch "--rendering_fps". |
96 double g_rendering_fps = 0; | 98 double g_rendering_fps = 0; |
97 | 99 |
98 // Disable rendering, the value is set by the switch "--disable_rendering". | 100 // Disable rendering, the value is set by the switch "--disable_rendering". |
99 bool g_disable_rendering = false; | 101 bool g_disable_rendering = false; |
100 | 102 |
101 // Magic constants for differentiating the reasons for NotifyResetDone being | 103 // Magic constants for differentiating the reasons for NotifyResetDone being |
102 // called. | 104 // called. |
103 enum ResetPoint { | 105 enum ResetPoint { |
104 START_OF_STREAM_RESET = -3, | 106 START_OF_STREAM_RESET = -3, |
105 MID_STREAM_RESET = -2, | 107 MID_STREAM_RESET = -2, |
106 END_OF_STREAM_RESET = -1 | 108 END_OF_STREAM_RESET = -1 |
107 }; | 109 }; |
108 | 110 |
109 const int kMaxResetAfterFrameNum = 100; | 111 const int kMaxResetAfterFrameNum = 100; |
110 const int kMaxFramesToDelayReuse = 64; | 112 const int kMaxFramesToDelayReuse = 64; |
111 const base::TimeDelta kReuseDelay = base::TimeDelta::FromSeconds(1); | 113 const base::TimeDelta kReuseDelay = base::TimeDelta::FromSeconds(1); |
114 // Simulate WebRTC and call VDA::Decode in 30FPS. | |
115 const int kWebRtcDecodeFps = 30; | |
112 | 116 |
113 struct TestVideoFile { | 117 struct TestVideoFile { |
114 explicit TestVideoFile(base::FilePath::StringType file_name) | 118 explicit TestVideoFile(base::FilePath::StringType file_name) |
115 : file_name(file_name), | 119 : file_name(file_name), |
116 width(-1), | 120 width(-1), |
117 height(-1), | 121 height(-1), |
118 num_frames(-1), | 122 num_frames(-1), |
119 num_fragments(-1), | 123 num_fragments(-1), |
120 min_fps_render(-1), | 124 min_fps_render(-1), |
121 min_fps_no_render(-1), | 125 min_fps_no_render(-1), |
(...skipping 14 matching lines...) Expand all Loading... | |
136 }; | 140 }; |
137 | 141 |
138 // Presumed minimal display size. | 142 // Presumed minimal display size. |
139 // We subtract one pixel from the width because some ARM chromebooks do not | 143 // We subtract one pixel from the width because some ARM chromebooks do not |
140 // support two fullscreen app running at the same time. See crbug.com/270064. | 144 // support two fullscreen app running at the same time. See crbug.com/270064. |
141 const gfx::Size kThumbnailsDisplaySize(1366 - 1, 768); | 145 const gfx::Size kThumbnailsDisplaySize(1366 - 1, 768); |
142 const gfx::Size kThumbnailsPageSize(1600, 1200); | 146 const gfx::Size kThumbnailsPageSize(1600, 1200); |
143 const gfx::Size kThumbnailSize(160, 120); | 147 const gfx::Size kThumbnailSize(160, 120); |
144 const int kMD5StringLength = 32; | 148 const int kMD5StringLength = 32; |
145 | 149 |
146 // Parse |data| into its constituent parts, set the various output fields | |
147 // accordingly, and read in video stream. CHECK-fails on unexpected or | |
148 // missing required data. Unspecified optional fields are set to -1. | |
149 void ParseAndReadTestVideoData(base::FilePath::StringType data, | |
150 size_t num_concurrent_decoders, | |
151 int reset_point, | |
152 std::vector<TestVideoFile*>* test_video_files) { | |
153 std::vector<base::FilePath::StringType> entries; | |
154 base::SplitString(data, ';', &entries); | |
155 CHECK_GE(entries.size(), 1U) << data; | |
156 for (size_t index = 0; index < entries.size(); ++index) { | |
157 std::vector<base::FilePath::StringType> fields; | |
158 base::SplitString(entries[index], ':', &fields); | |
159 CHECK_GE(fields.size(), 1U) << entries[index]; | |
160 CHECK_LE(fields.size(), 8U) << entries[index]; | |
161 TestVideoFile* video_file = new TestVideoFile(fields[0]); | |
162 if (!fields[1].empty()) | |
163 CHECK(base::StringToInt(fields[1], &video_file->width)); | |
164 if (!fields[2].empty()) | |
165 CHECK(base::StringToInt(fields[2], &video_file->height)); | |
166 if (!fields[3].empty()) { | |
167 CHECK(base::StringToInt(fields[3], &video_file->num_frames)); | |
168 // If we reset mid-stream and start playback over, account for frames | |
169 // that are decoded twice in our expectations. | |
170 if (video_file->num_frames > 0 && reset_point == MID_STREAM_RESET) { | |
171 // Reset should not go beyond the last frame; reset after the first | |
172 // frame for short videos. | |
173 video_file->reset_after_frame_num = kMaxResetAfterFrameNum; | |
174 if (video_file->num_frames <= kMaxResetAfterFrameNum) | |
175 video_file->reset_after_frame_num = 1; | |
176 video_file->num_frames += video_file->reset_after_frame_num; | |
177 } else { | |
178 video_file->reset_after_frame_num = reset_point; | |
179 } | |
180 } | |
181 if (!fields[4].empty()) | |
182 CHECK(base::StringToInt(fields[4], &video_file->num_fragments)); | |
183 if (!fields[5].empty()) { | |
184 CHECK(base::StringToInt(fields[5], &video_file->min_fps_render)); | |
185 video_file->min_fps_render /= num_concurrent_decoders; | |
186 } | |
187 if (!fields[6].empty()) { | |
188 CHECK(base::StringToInt(fields[6], &video_file->min_fps_no_render)); | |
189 video_file->min_fps_no_render /= num_concurrent_decoders; | |
190 } | |
191 if (!fields[7].empty()) | |
192 CHECK(base::StringToInt(fields[7], &video_file->profile)); | |
193 | |
194 // Read in the video data. | |
195 base::FilePath filepath(video_file->file_name); | |
196 CHECK(base::ReadFileToString(filepath, &video_file->data_str)) | |
197 << "test_video_file: " << filepath.MaybeAsASCII(); | |
198 | |
199 test_video_files->push_back(video_file); | |
200 } | |
201 } | |
202 | |
203 // Read in golden MD5s for the thumbnailed rendering of this video | 150 // Read in golden MD5s for the thumbnailed rendering of this video |
204 void ReadGoldenThumbnailMD5s(const TestVideoFile* video_file, | 151 void ReadGoldenThumbnailMD5s(const TestVideoFile* video_file, |
205 std::vector<std::string>* md5_strings) { | 152 std::vector<std::string>* md5_strings) { |
206 base::FilePath filepath(video_file->file_name); | 153 base::FilePath filepath(video_file->file_name); |
207 filepath = filepath.AddExtension(FILE_PATH_LITERAL(".md5")); | 154 filepath = filepath.AddExtension(FILE_PATH_LITERAL(".md5")); |
208 std::string all_md5s; | 155 std::string all_md5s; |
209 base::ReadFileToString(filepath, &all_md5s); | 156 base::ReadFileToString(filepath, &all_md5s); |
210 base::SplitString(all_md5s, '\n', md5_strings); | 157 base::SplitString(all_md5s, '\n', md5_strings); |
211 // Check these are legitimate MD5s. | 158 // Check these are legitimate MD5s. |
212 for (std::vector<std::string>::iterator md5_string = md5_strings->begin(); | 159 for (std::vector<std::string>::iterator md5_string = md5_strings->begin(); |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
406 // |delete_decoder_state| indicates when the underlying decoder should be | 353 // |delete_decoder_state| indicates when the underlying decoder should be |
407 // Destroy()'d and deleted and can take values: N<0: delete after -N Decode() | 354 // Destroy()'d and deleted and can take values: N<0: delete after -N Decode() |
408 // calls have been made, N>=0 means interpret as ClientState. | 355 // calls have been made, N>=0 means interpret as ClientState. |
409 // Both |reset_after_frame_num| & |delete_decoder_state| apply only to the | 356 // Both |reset_after_frame_num| & |delete_decoder_state| apply only to the |
410 // last play-through (governed by |num_play_throughs|). | 357 // last play-through (governed by |num_play_throughs|). |
411 // |rendering_fps| indicates the target rendering fps. 0 means no target fps | 358 // |rendering_fps| indicates the target rendering fps. 0 means no target fps |
412 // and it would render as fast as possible. | 359 // and it would render as fast as possible. |
413 // |suppress_rendering| indicates GL rendering is suppressed or not. | 360 // |suppress_rendering| indicates GL rendering is suppressed or not. |
414 // After |delay_reuse_after_frame_num| frame has been delivered, the client | 361 // After |delay_reuse_after_frame_num| frame has been delivered, the client |
415 // will start delaying the call to ReusePictureBuffer() for kReuseDelay. | 362 // will start delaying the call to ReusePictureBuffer() for kReuseDelay. |
363 // |decode_fps| is the number of VDA::Decode calls per second. | |
Ami GONE FROM CHROMIUM
2013/11/04 18:26:51
does this imply num_in_flight_decodes is always 1
Ami GONE FROM CHROMIUM
2013/11/04 18:26:51
decode_calls_per_second would be a clearer name, a
wuchengli
2013/11/05 06:24:15
Done.
wuchengli
2013/11/05 06:24:15
Yes. num_in_flight_decodes is always 1 in this cas
| |
416 GLRenderingVDAClient(RenderingHelper* rendering_helper, | 364 GLRenderingVDAClient(RenderingHelper* rendering_helper, |
417 int rendering_window_id, | 365 int rendering_window_id, |
418 ClientStateNotification<ClientState>* note, | 366 ClientStateNotification<ClientState>* note, |
419 const std::string& encoded_data, | 367 const std::string& encoded_data, |
420 int num_in_flight_decodes, | 368 int num_in_flight_decodes, |
421 int num_play_throughs, | 369 int num_play_throughs, |
422 int reset_after_frame_num, | 370 int reset_after_frame_num, |
423 int delete_decoder_state, | 371 int delete_decoder_state, |
424 int frame_width, | 372 int frame_width, |
425 int frame_height, | 373 int frame_height, |
426 int profile, | 374 int profile, |
427 double rendering_fps, | 375 double rendering_fps, |
428 bool suppress_rendering, | 376 bool suppress_rendering, |
429 int delay_reuse_after_frame_num); | 377 int delay_reuse_after_frame_num, |
378 int decode_fps); | |
430 virtual ~GLRenderingVDAClient(); | 379 virtual ~GLRenderingVDAClient(); |
431 void CreateDecoder(); | 380 void CreateAndStartDecoder(); |
432 | 381 |
433 // VideoDecodeAccelerator::Client implementation. | 382 // VideoDecodeAccelerator::Client implementation. |
434 // The heart of the Client. | 383 // The heart of the Client. |
435 virtual void ProvidePictureBuffers(uint32 requested_num_of_buffers, | 384 virtual void ProvidePictureBuffers(uint32 requested_num_of_buffers, |
436 const gfx::Size& dimensions, | 385 const gfx::Size& dimensions, |
437 uint32 texture_target) OVERRIDE; | 386 uint32 texture_target) OVERRIDE; |
438 virtual void DismissPictureBuffer(int32 picture_buffer_id) OVERRIDE; | 387 virtual void DismissPictureBuffer(int32 picture_buffer_id) OVERRIDE; |
439 virtual void PictureReady(const media::Picture& picture) OVERRIDE; | 388 virtual void PictureReady(const media::Picture& picture) OVERRIDE; |
440 // Simple state changes. | 389 // Simple state changes. |
441 virtual void NotifyInitializeDone() OVERRIDE; | 390 virtual void NotifyInitializeDone() OVERRIDE; |
442 virtual void NotifyEndOfBitstreamBuffer(int32 bitstream_buffer_id) OVERRIDE; | 391 virtual void NotifyEndOfBitstreamBuffer(int32 bitstream_buffer_id) OVERRIDE; |
443 virtual void NotifyFlushDone() OVERRIDE; | 392 virtual void NotifyFlushDone() OVERRIDE; |
444 virtual void NotifyResetDone() OVERRIDE; | 393 virtual void NotifyResetDone() OVERRIDE; |
445 virtual void NotifyError(VideoDecodeAccelerator::Error error) OVERRIDE; | 394 virtual void NotifyError(VideoDecodeAccelerator::Error error) OVERRIDE; |
446 | 395 |
447 void OutputFrameDeliveryTimes(base::PlatformFile output); | 396 void OutputFrameDeliveryTimes(base::PlatformFile output); |
448 | 397 |
449 void NotifyFrameDropped(int32 picture_buffer_id); | 398 void NotifyFrameDropped(int32 picture_buffer_id); |
450 | 399 |
451 // Simple getters for inspecting the state of the Client. | 400 // Simple getters for inspecting the state of the Client. |
452 int num_done_bitstream_buffers() { return num_done_bitstream_buffers_; } | 401 int num_done_bitstream_buffers() { return num_done_bitstream_buffers_; } |
453 int num_skipped_fragments() { return num_skipped_fragments_; } | 402 int num_skipped_fragments() { return num_skipped_fragments_; } |
454 int num_queued_fragments() { return num_queued_fragments_; } | 403 int num_queued_fragments() { return num_queued_fragments_; } |
455 int num_decoded_frames(); | 404 int num_decoded_frames(); |
456 double frames_per_second(); | 405 double frames_per_second(); |
406 // Returns the median of the decode time in milli-seconds. | |
407 int decode_time_median(); | |
457 bool decoder_deleted() { return !decoder_.get(); } | 408 bool decoder_deleted() { return !decoder_.get(); } |
458 | 409 |
459 private: | 410 private: |
460 typedef std::map<int, media::PictureBuffer*> PictureBufferById; | 411 typedef std::map<int, media::PictureBuffer*> PictureBufferById; |
461 | 412 |
462 void SetState(ClientState new_state); | 413 void SetState(ClientState new_state); |
463 | 414 |
464 // Delete the associated decoder helper. | 415 // Delete the associated decoder helper. |
465 void DeleteDecoder(); | 416 void DeleteDecoder(); |
466 | 417 |
(...skipping 30 matching lines...) Expand all Loading... | |
497 int num_queued_fragments_; | 448 int num_queued_fragments_; |
498 int num_decoded_frames_; | 449 int num_decoded_frames_; |
499 int num_done_bitstream_buffers_; | 450 int num_done_bitstream_buffers_; |
500 PictureBufferById picture_buffers_by_id_; | 451 PictureBufferById picture_buffers_by_id_; |
501 base::TimeTicks initialize_done_ticks_; | 452 base::TimeTicks initialize_done_ticks_; |
502 int profile_; | 453 int profile_; |
503 bool suppress_rendering_; | 454 bool suppress_rendering_; |
504 std::vector<base::TimeTicks> frame_delivery_times_; | 455 std::vector<base::TimeTicks> frame_delivery_times_; |
505 int delay_reuse_after_frame_num_; | 456 int delay_reuse_after_frame_num_; |
506 scoped_ptr<ThrottlingVDAClient> throttling_client_; | 457 scoped_ptr<ThrottlingVDAClient> throttling_client_; |
458 // A map from bitstream buffer id to the decode start time of the buffer. | |
459 std::map<int, base::TimeTicks> decode_start_time_; | |
460 // The decode time of all decoded frames. | |
461 std::vector<base::TimeDelta> decode_time_; | |
462 // The number of VDA::Decode calls per second. This is to simulate webrtc. | |
463 int decode_fps_; | |
507 | 464 |
508 DISALLOW_IMPLICIT_CONSTRUCTORS(GLRenderingVDAClient); | 465 DISALLOW_IMPLICIT_CONSTRUCTORS(GLRenderingVDAClient); |
509 }; | 466 }; |
510 | 467 |
511 GLRenderingVDAClient::GLRenderingVDAClient( | 468 GLRenderingVDAClient::GLRenderingVDAClient( |
512 RenderingHelper* rendering_helper, | 469 RenderingHelper* rendering_helper, |
513 int rendering_window_id, | 470 int rendering_window_id, |
514 ClientStateNotification<ClientState>* note, | 471 ClientStateNotification<ClientState>* note, |
515 const std::string& encoded_data, | 472 const std::string& encoded_data, |
516 int num_in_flight_decodes, | 473 int num_in_flight_decodes, |
517 int num_play_throughs, | 474 int num_play_throughs, |
518 int reset_after_frame_num, | 475 int reset_after_frame_num, |
519 int delete_decoder_state, | 476 int delete_decoder_state, |
520 int frame_width, | 477 int frame_width, |
521 int frame_height, | 478 int frame_height, |
522 int profile, | 479 int profile, |
523 double rendering_fps, | 480 double rendering_fps, |
524 bool suppress_rendering, | 481 bool suppress_rendering, |
525 int delay_reuse_after_frame_num) | 482 int delay_reuse_after_frame_num, |
483 int decode_fps) | |
526 : rendering_helper_(rendering_helper), | 484 : rendering_helper_(rendering_helper), |
527 rendering_window_id_(rendering_window_id), | 485 rendering_window_id_(rendering_window_id), |
528 encoded_data_(encoded_data), | 486 encoded_data_(encoded_data), |
529 num_in_flight_decodes_(num_in_flight_decodes), | 487 num_in_flight_decodes_(num_in_flight_decodes), |
530 outstanding_decodes_(0), | 488 outstanding_decodes_(0), |
531 encoded_data_next_pos_to_decode_(0), | 489 encoded_data_next_pos_to_decode_(0), |
532 next_bitstream_buffer_id_(0), | 490 next_bitstream_buffer_id_(0), |
533 note_(note), | 491 note_(note), |
534 remaining_play_throughs_(num_play_throughs), | 492 remaining_play_throughs_(num_play_throughs), |
535 reset_after_frame_num_(reset_after_frame_num), | 493 reset_after_frame_num_(reset_after_frame_num), |
536 delete_decoder_state_(delete_decoder_state), | 494 delete_decoder_state_(delete_decoder_state), |
537 state_(CS_CREATED), | 495 state_(CS_CREATED), |
538 num_skipped_fragments_(0), | 496 num_skipped_fragments_(0), |
539 num_queued_fragments_(0), | 497 num_queued_fragments_(0), |
540 num_decoded_frames_(0), | 498 num_decoded_frames_(0), |
541 num_done_bitstream_buffers_(0), | 499 num_done_bitstream_buffers_(0), |
542 profile_(profile), | 500 profile_(profile), |
543 suppress_rendering_(suppress_rendering), | 501 suppress_rendering_(suppress_rendering), |
544 delay_reuse_after_frame_num_(delay_reuse_after_frame_num) { | 502 delay_reuse_after_frame_num_(delay_reuse_after_frame_num), |
503 decode_fps_(decode_fps) { | |
545 CHECK_GT(num_in_flight_decodes, 0); | 504 CHECK_GT(num_in_flight_decodes, 0); |
546 CHECK_GT(num_play_throughs, 0); | 505 CHECK_GT(num_play_throughs, 0); |
547 CHECK_GE(rendering_fps, 0); | 506 CHECK_GE(rendering_fps, 0); |
507 // |num_in_flight_decodes_| is not supported when decode fps > 0. | |
508 if (decode_fps_ > 0) | |
509 CHECK_EQ(1, num_in_flight_decodes_); | |
548 if (rendering_fps > 0) | 510 if (rendering_fps > 0) |
549 throttling_client_.reset(new ThrottlingVDAClient( | 511 throttling_client_.reset(new ThrottlingVDAClient( |
550 this, | 512 this, |
551 rendering_fps, | 513 rendering_fps, |
552 base::Bind(&GLRenderingVDAClient::NotifyFrameDropped, | 514 base::Bind(&GLRenderingVDAClient::NotifyFrameDropped, |
553 base::Unretained(this)))); | 515 base::Unretained(this)))); |
554 } | 516 } |
555 | 517 |
556 GLRenderingVDAClient::~GLRenderingVDAClient() { | 518 GLRenderingVDAClient::~GLRenderingVDAClient() { |
557 DeleteDecoder(); // Clean up in case of expected error. | 519 DeleteDecoder(); // Clean up in case of expected error. |
558 CHECK(decoder_deleted()); | 520 CHECK(decoder_deleted()); |
559 STLDeleteValues(&picture_buffers_by_id_); | 521 STLDeleteValues(&picture_buffers_by_id_); |
560 SetState(CS_DESTROYED); | 522 SetState(CS_DESTROYED); |
561 } | 523 } |
562 | 524 |
563 static bool DoNothingReturnTrue() { return true; } | 525 static bool DoNothingReturnTrue() { return true; } |
564 | 526 |
565 void GLRenderingVDAClient::CreateDecoder() { | 527 void GLRenderingVDAClient::CreateAndStartDecoder() { |
566 CHECK(decoder_deleted()); | 528 CHECK(decoder_deleted()); |
567 CHECK(!decoder_.get()); | 529 CHECK(!decoder_.get()); |
568 | 530 |
569 VideoDecodeAccelerator::Client* client = this; | 531 VideoDecodeAccelerator::Client* client = this; |
570 base::WeakPtr<VideoDecodeAccelerator::Client> weak_client = AsWeakPtr(); | 532 base::WeakPtr<VideoDecodeAccelerator::Client> weak_client = AsWeakPtr(); |
571 if (throttling_client_) { | 533 if (throttling_client_) { |
572 client = throttling_client_.get(); | 534 client = throttling_client_.get(); |
573 weak_client = throttling_client_->AsWeakPtr(); | 535 weak_client = throttling_client_->AsWeakPtr(); |
574 } | 536 } |
575 #if defined(OS_WIN) | 537 #if defined(OS_WIN) |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
638 picture_buffers_by_id_.erase(it); | 600 picture_buffers_by_id_.erase(it); |
639 } | 601 } |
640 | 602 |
641 void GLRenderingVDAClient::PictureReady(const media::Picture& picture) { | 603 void GLRenderingVDAClient::PictureReady(const media::Picture& picture) { |
642 // We shouldn't be getting pictures delivered after Reset has completed. | 604 // We shouldn't be getting pictures delivered after Reset has completed. |
643 CHECK_LT(state_, CS_RESET); | 605 CHECK_LT(state_, CS_RESET); |
644 | 606 |
645 if (decoder_deleted()) | 607 if (decoder_deleted()) |
646 return; | 608 return; |
647 | 609 |
648 frame_delivery_times_.push_back(base::TimeTicks::Now()); | 610 base::TimeTicks now = base::TimeTicks::Now(); |
611 frame_delivery_times_.push_back(now); | |
612 // Save the decode time of this picture. | |
613 std::map<int, base::TimeTicks>::iterator it | |
614 = decode_start_time_.find(picture.bitstream_buffer_id()); | |
615 ASSERT_NE(decode_start_time_.end(), it); | |
616 decode_time_.push_back(now - it->second); | |
617 decode_start_time_.erase(it); | |
649 | 618 |
650 CHECK_LE(picture.bitstream_buffer_id(), next_bitstream_buffer_id_); | 619 CHECK_LE(picture.bitstream_buffer_id(), next_bitstream_buffer_id_); |
651 ++num_decoded_frames_; | 620 ++num_decoded_frames_; |
652 | 621 |
653 // Mid-stream reset applies only to the last play-through per constructor | 622 // Mid-stream reset applies only to the last play-through per constructor |
654 // comment. | 623 // comment. |
655 if (remaining_play_throughs_ == 1 && | 624 if (remaining_play_throughs_ == 1 && |
656 reset_after_frame_num_ == num_decoded_frames()) { | 625 reset_after_frame_num_ == num_decoded_frames()) { |
657 reset_after_frame_num_ = MID_STREAM_RESET; | 626 reset_after_frame_num_ = MID_STREAM_RESET; |
658 decoder_->Reset(); | 627 decoder_->Reset(); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
695 } | 664 } |
696 | 665 |
697 void GLRenderingVDAClient::NotifyEndOfBitstreamBuffer( | 666 void GLRenderingVDAClient::NotifyEndOfBitstreamBuffer( |
698 int32 bitstream_buffer_id) { | 667 int32 bitstream_buffer_id) { |
699 // TODO(fischman): this test currently relies on this notification to make | 668 // TODO(fischman): this test currently relies on this notification to make |
700 // forward progress during a Reset(). But the VDA::Reset() API doesn't | 669 // forward progress during a Reset(). But the VDA::Reset() API doesn't |
701 // guarantee this, so stop relying on it (and remove the notifications from | 670 // guarantee this, so stop relying on it (and remove the notifications from |
702 // VaapiVideoDecodeAccelerator::FinishReset()). | 671 // VaapiVideoDecodeAccelerator::FinishReset()). |
703 ++num_done_bitstream_buffers_; | 672 ++num_done_bitstream_buffers_; |
704 --outstanding_decodes_; | 673 --outstanding_decodes_; |
705 DecodeNextFragment(); | 674 if (decode_fps_ == 0) |
675 DecodeNextFragment(); | |
706 } | 676 } |
707 | 677 |
708 void GLRenderingVDAClient::NotifyFlushDone() { | 678 void GLRenderingVDAClient::NotifyFlushDone() { |
709 if (decoder_deleted()) | 679 if (decoder_deleted()) |
710 return; | 680 return; |
711 SetState(CS_FLUSHED); | 681 SetState(CS_FLUSHED); |
712 --remaining_play_throughs_; | 682 --remaining_play_throughs_; |
713 DCHECK_GE(remaining_play_throughs_, 0); | 683 DCHECK_GE(remaining_play_throughs_, 0); |
714 if (decoder_deleted()) | 684 if (decoder_deleted()) |
715 return; | 685 return; |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
877 | 847 |
878 // Populate the shared memory buffer w/ the fragment, duplicate its handle, | 848 // Populate the shared memory buffer w/ the fragment, duplicate its handle, |
879 // and hand it off to the decoder. | 849 // and hand it off to the decoder. |
880 base::SharedMemory shm; | 850 base::SharedMemory shm; |
881 CHECK(shm.CreateAndMapAnonymous(next_fragment_size)); | 851 CHECK(shm.CreateAndMapAnonymous(next_fragment_size)); |
882 memcpy(shm.memory(), next_fragment_bytes.data(), next_fragment_size); | 852 memcpy(shm.memory(), next_fragment_bytes.data(), next_fragment_size); |
883 base::SharedMemoryHandle dup_handle; | 853 base::SharedMemoryHandle dup_handle; |
884 CHECK(shm.ShareToProcess(base::Process::Current().handle(), &dup_handle)); | 854 CHECK(shm.ShareToProcess(base::Process::Current().handle(), &dup_handle)); |
885 media::BitstreamBuffer bitstream_buffer( | 855 media::BitstreamBuffer bitstream_buffer( |
886 next_bitstream_buffer_id_, dup_handle, next_fragment_size); | 856 next_bitstream_buffer_id_, dup_handle, next_fragment_size); |
857 decode_start_time_[next_bitstream_buffer_id_] = base::TimeTicks::Now(); | |
887 // Mask against 30 bits, to avoid (undefined) wraparound on signed integer. | 858 // Mask against 30 bits, to avoid (undefined) wraparound on signed integer. |
888 next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & 0x3FFFFFFF; | 859 next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & 0x3FFFFFFF; |
889 decoder_->Decode(bitstream_buffer); | 860 decoder_->Decode(bitstream_buffer); |
890 ++outstanding_decodes_; | 861 ++outstanding_decodes_; |
891 encoded_data_next_pos_to_decode_ = end_pos; | 862 encoded_data_next_pos_to_decode_ = end_pos; |
892 | 863 |
893 if (!remaining_play_throughs_ && | 864 if (!remaining_play_throughs_ && |
894 -delete_decoder_state_ == next_bitstream_buffer_id_) { | 865 -delete_decoder_state_ == next_bitstream_buffer_id_) { |
895 DeleteDecoder(); | 866 DeleteDecoder(); |
896 } | 867 } |
868 | |
869 if (decode_fps_ > 0) { | |
870 base::MessageLoop::current()->PostDelayedTask( | |
871 FROM_HERE, | |
872 base::Bind(&GLRenderingVDAClient::DecodeNextFragment, AsWeakPtr()), | |
873 base::TimeDelta::FromSeconds(1) / decode_fps_); | |
874 } | |
897 } | 875 } |
898 | 876 |
899 int GLRenderingVDAClient::num_decoded_frames() { | 877 int GLRenderingVDAClient::num_decoded_frames() { |
900 return throttling_client_ ? throttling_client_->num_decoded_frames() | 878 return throttling_client_ ? throttling_client_->num_decoded_frames() |
901 : num_decoded_frames_; | 879 : num_decoded_frames_; |
902 } | 880 } |
903 | 881 |
904 double GLRenderingVDAClient::frames_per_second() { | 882 double GLRenderingVDAClient::frames_per_second() { |
905 base::TimeDelta delta = frame_delivery_times_.back() - initialize_done_ticks_; | 883 base::TimeDelta delta = frame_delivery_times_.back() - initialize_done_ticks_; |
906 if (delta.InSecondsF() == 0) | 884 if (delta.InSecondsF() == 0) |
907 return 0; | 885 return 0; |
908 return num_decoded_frames() / delta.InSecondsF(); | 886 return num_decoded_frames() / delta.InSecondsF(); |
909 } | 887 } |
910 | 888 |
889 int GLRenderingVDAClient::decode_time_median() { | |
890 if (decode_time_.size() == 0) | |
891 return 0; | |
892 std::sort(decode_time_.begin(), decode_time_.end()); | |
893 int index = decode_time_.size() / 2; | |
894 if (decode_time_.size() % 2 != 0) | |
895 return decode_time_[index].InMilliseconds(); | |
896 | |
897 return (decode_time_[index] + decode_time_[index - 1]).InMilliseconds() / 2; | |
898 } | |
899 | |
900 class VideoDecodeAcceleratorTest : public ::testing::Test { | |
901 protected: | |
902 VideoDecodeAcceleratorTest(); | |
903 virtual void SetUp(); | |
904 virtual void TearDown(); | |
905 | |
906 // Parse |data| into its constituent parts, set the various output fields | |
907 // accordingly, and read in video stream. CHECK-fails on unexpected or | |
908 // missing required data. Unspecified optional fields are set to -1. | |
909 void ParseAndReadTestVideoData(base::FilePath::StringType data, | |
910 std::vector<TestVideoFile*>* test_video_files); | |
911 void UpdateVideoFileParam(const std::vector<TestVideoFile*>& test_video_files, | |
Ami GONE FROM CHROMIUM
2013/11/04 18:26:51
doco unclear methods
wuchengli
2013/11/05 06:24:15
Done.
| |
912 size_t num_concurrent_decoders, | |
913 int reset_point); | |
914 void InitializeRenderingHelper(const RenderingHelperParams& helper_params); | |
915 void CreateAndStartDecoder(GLRenderingVDAClient* client, | |
916 ClientStateNotification<ClientState>* note); | |
917 void WaitUntilDecodeFinish(ClientStateNotification<ClientState>* note); | |
918 void WaitUntilIdle(); | |
919 void OutputLogFile(const base::FilePath::CharType* log_path, | |
920 const std::string& content); | |
921 | |
922 std::vector<TestVideoFile*> test_video_files_; | |
923 RenderingHelper rendering_helper_; | |
924 scoped_refptr<base::MessageLoopProxy> rendering_loop_proxy_; | |
925 | |
926 private: | |
927 base::Thread rendering_thread_; | |
928 // Required for Thread to work. Not used otherwise. | |
929 base::ShadowingAtExitManager at_exit_manager_; | |
930 | |
931 DISALLOW_COPY_AND_ASSIGN(VideoDecodeAcceleratorTest); | |
932 }; | |
933 | |
934 VideoDecodeAcceleratorTest::VideoDecodeAcceleratorTest() | |
935 : rendering_thread_("GLRenderingVDAClientThread") {} | |
936 | |
937 void VideoDecodeAcceleratorTest::SetUp() { | |
938 ParseAndReadTestVideoData(g_test_video_data, &test_video_files_); | |
939 | |
940 // Initialize the rendering helper. | |
941 base::Thread::Options options; | |
942 options.message_loop_type = base::MessageLoop::TYPE_DEFAULT; | |
943 #if defined(OS_WIN) | |
944 // For windows the decoding thread initializes the media foundation decoder | |
945 // which uses COM. We need the thread to be a UI thread. | |
946 options.message_loop_type = base::MessageLoop::TYPE_UI; | |
947 #endif // OS_WIN | |
948 | |
949 rendering_thread_.StartWithOptions(options); | |
950 rendering_loop_proxy_ = rendering_thread_.message_loop_proxy(); | |
951 } | |
952 | |
953 void VideoDecodeAcceleratorTest::TearDown() { | |
954 rendering_loop_proxy_->PostTask( | |
955 FROM_HERE, | |
956 base::Bind(&STLDeleteElements<std::vector<TestVideoFile*> >, | |
957 &test_video_files_)); | |
958 | |
959 base::WaitableEvent done(false, false); | |
960 rendering_loop_proxy_->PostTask( | |
961 FROM_HERE, | |
962 base::Bind(&RenderingHelper::UnInitialize, | |
963 base::Unretained(&rendering_helper_), | |
964 &done)); | |
965 done.Wait(); | |
966 | |
967 rendering_thread_.Stop(); | |
968 } | |
969 | |
970 void VideoDecodeAcceleratorTest::ParseAndReadTestVideoData( | |
971 base::FilePath::StringType data, | |
972 std::vector<TestVideoFile*>* test_video_files) { | |
973 std::vector<base::FilePath::StringType> entries; | |
974 base::SplitString(data, ';', &entries); | |
975 CHECK_GE(entries.size(), 1U) << data; | |
976 for (size_t index = 0; index < entries.size(); ++index) { | |
977 std::vector<base::FilePath::StringType> fields; | |
978 base::SplitString(entries[index], ':', &fields); | |
979 CHECK_GE(fields.size(), 1U) << entries[index]; | |
980 CHECK_LE(fields.size(), 8U) << entries[index]; | |
981 TestVideoFile* video_file = new TestVideoFile(fields[0]); | |
982 if (!fields[1].empty()) | |
983 CHECK(base::StringToInt(fields[1], &video_file->width)); | |
984 if (!fields[2].empty()) | |
985 CHECK(base::StringToInt(fields[2], &video_file->height)); | |
986 if (!fields[3].empty()) | |
987 CHECK(base::StringToInt(fields[3], &video_file->num_frames)); | |
988 if (!fields[4].empty()) | |
989 CHECK(base::StringToInt(fields[4], &video_file->num_fragments)); | |
990 if (!fields[5].empty()) | |
991 CHECK(base::StringToInt(fields[5], &video_file->min_fps_render)); | |
992 if (!fields[6].empty()) | |
993 CHECK(base::StringToInt(fields[6], &video_file->min_fps_no_render)); | |
994 if (!fields[7].empty()) | |
995 CHECK(base::StringToInt(fields[7], &video_file->profile)); | |
996 | |
997 // Read in the video data. | |
998 base::FilePath filepath(video_file->file_name); | |
999 CHECK(base::ReadFileToString(filepath, &video_file->data_str)) | |
1000 << "test_video_file: " << filepath.MaybeAsASCII(); | |
1001 | |
1002 test_video_files->push_back(video_file); | |
1003 } | |
1004 } | |
1005 | |
1006 void VideoDecodeAcceleratorTest::UpdateVideoFileParam( | |
1007 const std::vector<TestVideoFile*>& test_video_files, | |
1008 size_t num_concurrent_decoders, | |
1009 int reset_point) { | |
1010 for (size_t i = 0; i < test_video_files.size(); i++) { | |
1011 TestVideoFile* video_file = test_video_files[i]; | |
1012 if (video_file->num_frames > 0 && reset_point == MID_STREAM_RESET) { | |
1013 // Reset should not go beyond the last frame; reset after the first | |
1014 // frame for short videos. | |
1015 video_file->reset_after_frame_num = kMaxResetAfterFrameNum; | |
1016 if (video_file->num_frames <= kMaxResetAfterFrameNum) | |
1017 video_file->reset_after_frame_num = 1; | |
1018 video_file->num_frames += video_file->reset_after_frame_num; | |
1019 } | |
1020 if (video_file->min_fps_render != -1) | |
1021 video_file->min_fps_render /= num_concurrent_decoders; | |
1022 if (video_file->min_fps_no_render != -1) | |
1023 video_file->min_fps_no_render /= num_concurrent_decoders; | |
1024 } | |
1025 } | |
1026 | |
1027 void VideoDecodeAcceleratorTest::InitializeRenderingHelper( | |
1028 const RenderingHelperParams& helper_params) { | |
1029 base::WaitableEvent done(false, false); | |
1030 rendering_loop_proxy_->PostTask( | |
1031 FROM_HERE, | |
1032 base::Bind(&RenderingHelper::Initialize, | |
1033 base::Unretained(&rendering_helper_), | |
1034 helper_params, | |
1035 &done)); | |
1036 done.Wait(); | |
1037 } | |
1038 | |
1039 void VideoDecodeAcceleratorTest::CreateAndStartDecoder( | |
1040 GLRenderingVDAClient* client, | |
1041 ClientStateNotification<ClientState>* note) { | |
1042 rendering_loop_proxy_->PostTask( | |
1043 FROM_HERE, | |
1044 base::Bind(&GLRenderingVDAClient::CreateAndStartDecoder, | |
1045 base::Unretained(client))); | |
1046 ASSERT_EQ(note->Wait(), CS_DECODER_SET); | |
1047 } | |
1048 | |
1049 void VideoDecodeAcceleratorTest::WaitUntilDecodeFinish( | |
1050 ClientStateNotification<ClientState>* note) { | |
1051 for (int i = 0; i < CS_MAX; i++) { | |
1052 if (note->Wait() == CS_DESTROYED) | |
1053 break; | |
1054 } | |
1055 } | |
1056 | |
1057 void VideoDecodeAcceleratorTest::WaitUntilIdle() { | |
1058 base::WaitableEvent done(false, false); | |
1059 rendering_loop_proxy_->PostTask( | |
1060 FROM_HERE, | |
1061 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&done))); | |
1062 done.Wait(); | |
1063 } | |
1064 | |
1065 void VideoDecodeAcceleratorTest::OutputLogFile( | |
1066 const base::FilePath::CharType* log_path, | |
1067 const std::string& content) { | |
1068 base::PlatformFile file = base::CreatePlatformFile( | |
1069 base::FilePath(log_path), | |
1070 base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_WRITE, | |
1071 NULL, | |
1072 NULL); | |
1073 base::WritePlatformFileAtCurrentPos(file, content.data(), content.length()); | |
1074 base::ClosePlatformFile(file); | |
1075 } | |
1076 | |
911 // Test parameters: | 1077 // Test parameters: |
912 // - Number of concurrent decoders. | 1078 // - Number of concurrent decoders. |
913 // - Number of concurrent in-flight Decode() calls per decoder. | 1079 // - Number of concurrent in-flight Decode() calls per decoder. |
914 // - Number of play-throughs. | 1080 // - Number of play-throughs. |
915 // - reset_after_frame_num: see GLRenderingVDAClient ctor. | 1081 // - reset_after_frame_num: see GLRenderingVDAClient ctor. |
916 // - delete_decoder_phase: see GLRenderingVDAClient ctor. | 1082 // - delete_decoder_phase: see GLRenderingVDAClient ctor. |
917 // - whether to test slow rendering by delaying ReusePictureBuffer(). | 1083 // - whether to test slow rendering by delaying ReusePictureBuffer(). |
918 // - whether the video frames are rendered as thumbnails. | 1084 // - whether the video frames are rendered as thumbnails. |
919 class VideoDecodeAcceleratorTest | 1085 class VideoDecodeAcceleratorParamTest |
920 : public ::testing::TestWithParam< | 1086 : public VideoDecodeAcceleratorTest, |
921 Tuple7<int, int, int, ResetPoint, ClientState, bool, bool> > { | 1087 public ::testing::WithParamInterface< |
1088 Tuple7<int, int, int, ResetPoint, ClientState, bool, bool> > { | |
922 }; | 1089 }; |
923 | 1090 |
924 // Helper so that gtest failures emit a more readable version of the tuple than | 1091 // Helper so that gtest failures emit a more readable version of the tuple than |
925 // its byte representation. | 1092 // its byte representation. |
926 ::std::ostream& operator<<( | 1093 ::std::ostream& operator<<( |
927 ::std::ostream& os, | 1094 ::std::ostream& os, |
928 const Tuple7<int, int, int, ResetPoint, ClientState, bool, bool>& t) { | 1095 const Tuple7<int, int, int, ResetPoint, ClientState, bool, bool>& t) { |
929 return os << t.a << ", " << t.b << ", " << t.c << ", " << t.d << ", " << t.e | 1096 return os << t.a << ", " << t.b << ", " << t.c << ", " << t.d << ", " << t.e |
930 << ", " << t.f << ", " << t.g; | 1097 << ", " << t.f << ", " << t.g; |
931 } | 1098 } |
(...skipping 11 matching lines...) Expand all Loading... | |
943 << ", instead of " << expected_state; | 1110 << ", instead of " << expected_state; |
944 } | 1111 } |
945 | 1112 |
946 // We assert a minimal number of concurrent decoders we expect to succeed. | 1113 // We assert a minimal number of concurrent decoders we expect to succeed. |
947 // Different platforms can support more concurrent decoders, so we don't assert | 1114 // Different platforms can support more concurrent decoders, so we don't assert |
948 // failure above this. | 1115 // failure above this. |
949 enum { kMinSupportedNumConcurrentDecoders = 3 }; | 1116 enum { kMinSupportedNumConcurrentDecoders = 3 }; |
950 | 1117 |
951 // Test the most straightforward case possible: data is decoded from a single | 1118 // Test the most straightforward case possible: data is decoded from a single |
952 // chunk and rendered to the screen. | 1119 // chunk and rendered to the screen. |
953 TEST_P(VideoDecodeAcceleratorTest, TestSimpleDecode) { | 1120 TEST_P(VideoDecodeAcceleratorParamTest, TestSimpleDecode) { |
954 // Required for Thread to work. Not used otherwise. | |
955 base::ShadowingAtExitManager at_exit_manager; | |
956 | |
957 const size_t num_concurrent_decoders = GetParam().a; | 1121 const size_t num_concurrent_decoders = GetParam().a; |
958 const size_t num_in_flight_decodes = GetParam().b; | 1122 const size_t num_in_flight_decodes = GetParam().b; |
959 const int num_play_throughs = GetParam().c; | 1123 const int num_play_throughs = GetParam().c; |
960 const int reset_point = GetParam().d; | 1124 const int reset_point = GetParam().d; |
961 const int delete_decoder_state = GetParam().e; | 1125 const int delete_decoder_state = GetParam().e; |
962 bool test_reuse_delay = GetParam().f; | 1126 bool test_reuse_delay = GetParam().f; |
963 const bool render_as_thumbnails = GetParam().g; | 1127 const bool render_as_thumbnails = GetParam().g; |
964 | 1128 |
965 std::vector<TestVideoFile*> test_video_files; | 1129 UpdateVideoFileParam(test_video_files_, num_concurrent_decoders, reset_point); |
966 ParseAndReadTestVideoData(g_test_video_data, | |
967 num_concurrent_decoders, | |
968 reset_point, | |
969 &test_video_files); | |
970 | 1130 |
971 // Suppress GL rendering for all tests when the "--disable_rendering" is set. | 1131 // Suppress GL rendering for all tests when the "--disable_rendering" is set. |
972 const bool suppress_rendering = g_disable_rendering; | 1132 const bool suppress_rendering = g_disable_rendering; |
973 | 1133 |
974 std::vector<ClientStateNotification<ClientState>*> | 1134 std::vector<ClientStateNotification<ClientState>*> |
975 notes(num_concurrent_decoders, NULL); | 1135 notes(num_concurrent_decoders, NULL); |
976 std::vector<GLRenderingVDAClient*> clients(num_concurrent_decoders, NULL); | 1136 std::vector<GLRenderingVDAClient*> clients(num_concurrent_decoders, NULL); |
977 | 1137 |
978 // Initialize the rendering helper. | |
979 base::Thread rendering_thread("GLRenderingVDAClientThread"); | |
980 base::Thread::Options options; | |
981 options.message_loop_type = base::MessageLoop::TYPE_DEFAULT; | |
982 #if defined(OS_WIN) | |
983 // For windows the decoding thread initializes the media foundation decoder | |
984 // which uses COM. We need the thread to be a UI thread. | |
985 options.message_loop_type = base::MessageLoop::TYPE_UI; | |
986 #endif // OS_WIN | |
987 | |
988 rendering_thread.StartWithOptions(options); | |
989 RenderingHelper rendering_helper; | |
990 | |
991 base::WaitableEvent done(false, false); | |
992 RenderingHelperParams helper_params; | 1138 RenderingHelperParams helper_params; |
993 helper_params.num_windows = num_concurrent_decoders; | 1139 helper_params.num_windows = num_concurrent_decoders; |
994 helper_params.render_as_thumbnails = render_as_thumbnails; | 1140 helper_params.render_as_thumbnails = render_as_thumbnails; |
995 if (render_as_thumbnails) { | 1141 if (render_as_thumbnails) { |
996 // Only one decoder is supported with thumbnail rendering | 1142 // Only one decoder is supported with thumbnail rendering |
997 CHECK_EQ(num_concurrent_decoders, 1U); | 1143 CHECK_EQ(num_concurrent_decoders, 1U); |
998 gfx::Size frame_size(test_video_files[0]->width, | 1144 gfx::Size frame_size(test_video_files_[0]->width, |
999 test_video_files[0]->height); | 1145 test_video_files_[0]->height); |
1000 helper_params.frame_dimensions.push_back(frame_size); | 1146 helper_params.frame_dimensions.push_back(frame_size); |
1001 helper_params.window_dimensions.push_back(kThumbnailsDisplaySize); | 1147 helper_params.window_dimensions.push_back(kThumbnailsDisplaySize); |
1002 helper_params.thumbnails_page_size = kThumbnailsPageSize; | 1148 helper_params.thumbnails_page_size = kThumbnailsPageSize; |
1003 helper_params.thumbnail_size = kThumbnailSize; | 1149 helper_params.thumbnail_size = kThumbnailSize; |
1004 } else { | 1150 } else { |
1005 for (size_t index = 0; index < test_video_files.size(); ++index) { | 1151 for (size_t index = 0; index < test_video_files_.size(); ++index) { |
1006 gfx::Size frame_size(test_video_files[index]->width, | 1152 gfx::Size frame_size(test_video_files_[index]->width, |
1007 test_video_files[index]->height); | 1153 test_video_files_[index]->height); |
1008 helper_params.frame_dimensions.push_back(frame_size); | 1154 helper_params.frame_dimensions.push_back(frame_size); |
1009 helper_params.window_dimensions.push_back(frame_size); | 1155 helper_params.window_dimensions.push_back(frame_size); |
1010 } | 1156 } |
1011 } | 1157 } |
1012 rendering_thread.message_loop()->PostTask( | 1158 InitializeRenderingHelper(helper_params); |
1013 FROM_HERE, | |
1014 base::Bind(&RenderingHelper::Initialize, | |
1015 base::Unretained(&rendering_helper), | |
1016 helper_params, | |
1017 &done)); | |
1018 done.Wait(); | |
1019 | 1159 |
1020 // First kick off all the decoders. | 1160 // First kick off all the decoders. |
1021 for (size_t index = 0; index < num_concurrent_decoders; ++index) { | 1161 for (size_t index = 0; index < num_concurrent_decoders; ++index) { |
1022 TestVideoFile* video_file = | 1162 TestVideoFile* video_file = |
1023 test_video_files[index % test_video_files.size()]; | 1163 test_video_files_[index % test_video_files_.size()]; |
1024 ClientStateNotification<ClientState>* note = | 1164 ClientStateNotification<ClientState>* note = |
1025 new ClientStateNotification<ClientState>(); | 1165 new ClientStateNotification<ClientState>(); |
1026 notes[index] = note; | 1166 notes[index] = note; |
1027 | 1167 |
1028 int delay_after_frame_num = std::numeric_limits<int>::max(); | 1168 int delay_after_frame_num = std::numeric_limits<int>::max(); |
1029 if (test_reuse_delay && | 1169 if (test_reuse_delay && |
1030 kMaxFramesToDelayReuse * 2 < video_file->num_frames) { | 1170 kMaxFramesToDelayReuse * 2 < video_file->num_frames) { |
1031 delay_after_frame_num = video_file->num_frames - kMaxFramesToDelayReuse; | 1171 delay_after_frame_num = video_file->num_frames - kMaxFramesToDelayReuse; |
1032 } | 1172 } |
1033 | 1173 |
1034 GLRenderingVDAClient* client = | 1174 GLRenderingVDAClient* client = |
1035 new GLRenderingVDAClient(&rendering_helper, | 1175 new GLRenderingVDAClient(&rendering_helper_, |
1036 index, | 1176 index, |
1037 note, | 1177 note, |
1038 video_file->data_str, | 1178 video_file->data_str, |
1039 num_in_flight_decodes, | 1179 num_in_flight_decodes, |
1040 num_play_throughs, | 1180 num_play_throughs, |
1041 video_file->reset_after_frame_num, | 1181 video_file->reset_after_frame_num, |
1042 delete_decoder_state, | 1182 delete_decoder_state, |
1043 video_file->width, | 1183 video_file->width, |
1044 video_file->height, | 1184 video_file->height, |
1045 video_file->profile, | 1185 video_file->profile, |
1046 g_rendering_fps, | 1186 g_rendering_fps, |
1047 suppress_rendering, | 1187 suppress_rendering, |
1048 delay_after_frame_num); | 1188 delay_after_frame_num, |
1189 0); | |
1049 clients[index] = client; | 1190 clients[index] = client; |
1050 | 1191 |
1051 rendering_thread.message_loop()->PostTask( | 1192 CreateAndStartDecoder(client, note); |
1052 FROM_HERE, | |
1053 base::Bind(&GLRenderingVDAClient::CreateDecoder, | |
1054 base::Unretained(client))); | |
1055 | |
1056 ASSERT_EQ(note->Wait(), CS_DECODER_SET); | |
1057 } | 1193 } |
1058 // Then wait for all the decodes to finish. | 1194 // Then wait for all the decodes to finish. |
1059 // Only check performance & correctness later if we play through only once. | 1195 // Only check performance & correctness later if we play through only once. |
1060 bool skip_performance_and_correctness_checks = num_play_throughs > 1; | 1196 bool skip_performance_and_correctness_checks = num_play_throughs > 1; |
1061 for (size_t i = 0; i < num_concurrent_decoders; ++i) { | 1197 for (size_t i = 0; i < num_concurrent_decoders; ++i) { |
1062 ClientStateNotification<ClientState>* note = notes[i]; | 1198 ClientStateNotification<ClientState>* note = notes[i]; |
1063 ClientState state = note->Wait(); | 1199 ClientState state = note->Wait(); |
1064 if (state != CS_INITIALIZED) { | 1200 if (state != CS_INITIALIZED) { |
1065 skip_performance_and_correctness_checks = true; | 1201 skip_performance_and_correctness_checks = true; |
1066 // We expect initialization to fail only when more than the supported | 1202 // We expect initialization to fail only when more than the supported |
(...skipping 28 matching lines...) Expand all Loading... | |
1095 AssertWaitForStateOrDeleted(note, clients[i], CS_DESTROYED)); | 1231 AssertWaitForStateOrDeleted(note, clients[i], CS_DESTROYED)); |
1096 } | 1232 } |
1097 // Finally assert that decoding went as expected. | 1233 // Finally assert that decoding went as expected. |
1098 for (size_t i = 0; i < num_concurrent_decoders && | 1234 for (size_t i = 0; i < num_concurrent_decoders && |
1099 !skip_performance_and_correctness_checks; ++i) { | 1235 !skip_performance_and_correctness_checks; ++i) { |
1100 // We can only make performance/correctness assertions if the decoder was | 1236 // We can only make performance/correctness assertions if the decoder was |
1101 // allowed to finish. | 1237 // allowed to finish. |
1102 if (delete_decoder_state < CS_FLUSHED) | 1238 if (delete_decoder_state < CS_FLUSHED) |
1103 continue; | 1239 continue; |
1104 GLRenderingVDAClient* client = clients[i]; | 1240 GLRenderingVDAClient* client = clients[i]; |
1105 TestVideoFile* video_file = test_video_files[i % test_video_files.size()]; | 1241 TestVideoFile* video_file = test_video_files_[i % test_video_files_.size()]; |
1106 if (video_file->num_frames > 0) { | 1242 if (video_file->num_frames > 0) { |
1107 // Expect the decoded frames may be more than the video frames as frames | 1243 // Expect the decoded frames may be more than the video frames as frames |
1108 // could still be returned until resetting done. | 1244 // could still be returned until resetting done. |
1109 if (video_file->reset_after_frame_num > 0) | 1245 if (video_file->reset_after_frame_num > 0) |
1110 EXPECT_GE(client->num_decoded_frames(), video_file->num_frames); | 1246 EXPECT_GE(client->num_decoded_frames(), video_file->num_frames); |
1111 else | 1247 else |
1112 EXPECT_EQ(client->num_decoded_frames(), video_file->num_frames); | 1248 EXPECT_EQ(client->num_decoded_frames(), video_file->num_frames); |
1113 } | 1249 } |
1114 if (reset_point == END_OF_STREAM_RESET) { | 1250 if (reset_point == END_OF_STREAM_RESET) { |
1115 EXPECT_EQ(video_file->num_fragments, client->num_skipped_fragments() + | 1251 EXPECT_EQ(video_file->num_fragments, client->num_skipped_fragments() + |
1116 client->num_queued_fragments()); | 1252 client->num_queued_fragments()); |
1117 EXPECT_EQ(client->num_done_bitstream_buffers(), | 1253 EXPECT_EQ(client->num_done_bitstream_buffers(), |
1118 client->num_queued_fragments()); | 1254 client->num_queued_fragments()); |
1119 } | 1255 } |
1120 LOG(INFO) << "Decoder " << i << " fps: " << client->frames_per_second(); | 1256 LOG(INFO) << "Decoder " << i << " fps: " << client->frames_per_second(); |
1121 if (!render_as_thumbnails) { | 1257 if (!render_as_thumbnails) { |
1122 int min_fps = suppress_rendering ? | 1258 int min_fps = suppress_rendering ? |
1123 video_file->min_fps_no_render : video_file->min_fps_render; | 1259 video_file->min_fps_no_render : video_file->min_fps_render; |
1124 if (min_fps > 0 && !test_reuse_delay) | 1260 if (min_fps > 0 && !test_reuse_delay) |
1125 EXPECT_GT(client->frames_per_second(), min_fps); | 1261 EXPECT_GT(client->frames_per_second(), min_fps); |
1126 } | 1262 } |
1127 } | 1263 } |
1128 | 1264 |
1129 if (render_as_thumbnails) { | 1265 if (render_as_thumbnails) { |
1130 std::vector<unsigned char> rgb; | 1266 std::vector<unsigned char> rgb; |
1131 bool alpha_solid; | 1267 bool alpha_solid; |
1132 rendering_thread.message_loop()->PostTask( | 1268 base::WaitableEvent done(false, false); |
1269 rendering_loop_proxy_->PostTask( | |
1133 FROM_HERE, | 1270 FROM_HERE, |
1134 base::Bind(&RenderingHelper::GetThumbnailsAsRGB, | 1271 base::Bind(&RenderingHelper::GetThumbnailsAsRGB, |
1135 base::Unretained(&rendering_helper), | 1272 base::Unretained(&rendering_helper_), |
1136 &rgb, &alpha_solid, &done)); | 1273 &rgb, &alpha_solid, &done)); |
1137 done.Wait(); | 1274 done.Wait(); |
1138 | 1275 |
1139 std::vector<std::string> golden_md5s; | 1276 std::vector<std::string> golden_md5s; |
1140 std::string md5_string = base::MD5String( | 1277 std::string md5_string = base::MD5String( |
1141 base::StringPiece(reinterpret_cast<char*>(&rgb[0]), rgb.size())); | 1278 base::StringPiece(reinterpret_cast<char*>(&rgb[0]), rgb.size())); |
1142 ReadGoldenThumbnailMD5s(test_video_files[0], &golden_md5s); | 1279 ReadGoldenThumbnailMD5s(test_video_files_[0], &golden_md5s); |
1143 std::vector<std::string>::iterator match = | 1280 std::vector<std::string>::iterator match = |
1144 find(golden_md5s.begin(), golden_md5s.end(), md5_string); | 1281 find(golden_md5s.begin(), golden_md5s.end(), md5_string); |
1145 if (match == golden_md5s.end()) { | 1282 if (match == golden_md5s.end()) { |
1146 // Convert raw RGB into PNG for export. | 1283 // Convert raw RGB into PNG for export. |
1147 std::vector<unsigned char> png; | 1284 std::vector<unsigned char> png; |
1148 gfx::PNGCodec::Encode(&rgb[0], | 1285 gfx::PNGCodec::Encode(&rgb[0], |
1149 gfx::PNGCodec::FORMAT_RGB, | 1286 gfx::PNGCodec::FORMAT_RGB, |
1150 kThumbnailsPageSize, | 1287 kThumbnailsPageSize, |
1151 kThumbnailsPageSize.width() * 3, | 1288 kThumbnailsPageSize.width() * 3, |
1152 true, | 1289 true, |
1153 std::vector<gfx::PNGCodec::Comment>(), | 1290 std::vector<gfx::PNGCodec::Comment>(), |
1154 &png); | 1291 &png); |
1155 | 1292 |
1156 LOG(ERROR) << "Unknown thumbnails MD5: " << md5_string; | 1293 LOG(ERROR) << "Unknown thumbnails MD5: " << md5_string; |
1157 | 1294 |
1158 base::FilePath filepath(test_video_files[0]->file_name); | 1295 base::FilePath filepath(test_video_files_[0]->file_name); |
1159 filepath = filepath.AddExtension(FILE_PATH_LITERAL(".bad_thumbnails")); | 1296 filepath = filepath.AddExtension(FILE_PATH_LITERAL(".bad_thumbnails")); |
1160 filepath = filepath.AddExtension(FILE_PATH_LITERAL(".png")); | 1297 filepath = filepath.AddExtension(FILE_PATH_LITERAL(".png")); |
1161 int num_bytes = file_util::WriteFile(filepath, | 1298 int num_bytes = file_util::WriteFile(filepath, |
1162 reinterpret_cast<char*>(&png[0]), | 1299 reinterpret_cast<char*>(&png[0]), |
1163 png.size()); | 1300 png.size()); |
1164 ASSERT_EQ(num_bytes, static_cast<int>(png.size())); | 1301 ASSERT_EQ(num_bytes, static_cast<int>(png.size())); |
1165 } | 1302 } |
1166 ASSERT_NE(match, golden_md5s.end()); | 1303 ASSERT_NE(match, golden_md5s.end()); |
1167 EXPECT_EQ(alpha_solid, true) << "RGBA frame had incorrect alpha"; | 1304 EXPECT_EQ(alpha_solid, true) << "RGBA frame had incorrect alpha"; |
1168 } | 1305 } |
1169 | 1306 |
1170 // Output the frame delivery time to file | 1307 // Output the frame delivery time to file |
1171 // We can only make performance/correctness assertions if the decoder was | 1308 // We can only make performance/correctness assertions if the decoder was |
1172 // allowed to finish. | 1309 // allowed to finish. |
1173 if (g_frame_delivery_log != NULL && delete_decoder_state >= CS_FLUSHED) { | 1310 if (g_output_log != NULL && delete_decoder_state >= CS_FLUSHED) { |
1174 base::PlatformFile output_file = base::CreatePlatformFile( | 1311 base::PlatformFile output_file = base::CreatePlatformFile( |
1175 base::FilePath(g_frame_delivery_log), | 1312 base::FilePath(g_output_log), |
1176 base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_WRITE, | 1313 base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_WRITE, |
1177 NULL, | 1314 NULL, |
1178 NULL); | 1315 NULL); |
1179 for (size_t i = 0; i < num_concurrent_decoders; ++i) { | 1316 for (size_t i = 0; i < num_concurrent_decoders; ++i) { |
1180 clients[i]->OutputFrameDeliveryTimes(output_file); | 1317 clients[i]->OutputFrameDeliveryTimes(output_file); |
1181 } | 1318 } |
1182 base::ClosePlatformFile(output_file); | 1319 base::ClosePlatformFile(output_file); |
1183 } | 1320 } |
1184 | 1321 |
1185 rendering_thread.message_loop()->PostTask( | 1322 rendering_loop_proxy_->PostTask( |
1186 FROM_HERE, | 1323 FROM_HERE, |
1187 base::Bind(&STLDeleteElements<std::vector<GLRenderingVDAClient*> >, | 1324 base::Bind(&STLDeleteElements<std::vector<GLRenderingVDAClient*> >, |
1188 &clients)); | 1325 &clients)); |
1189 rendering_thread.message_loop()->PostTask( | 1326 rendering_loop_proxy_->PostTask( |
1190 FROM_HERE, | 1327 FROM_HERE, |
1191 base::Bind(&STLDeleteElements< | 1328 base::Bind(&STLDeleteElements< |
1192 std::vector<ClientStateNotification<ClientState>*> >, | 1329 std::vector<ClientStateNotification<ClientState>*> >, |
1193 ¬es)); | 1330 ¬es)); |
1194 rendering_thread.message_loop()->PostTask( | 1331 WaitUntilIdle(); |
1195 FROM_HERE, | |
1196 base::Bind(&STLDeleteElements<std::vector<TestVideoFile*> >, | |
1197 &test_video_files)); | |
1198 rendering_thread.message_loop()->PostTask( | |
1199 FROM_HERE, | |
1200 base::Bind(&RenderingHelper::UnInitialize, | |
1201 base::Unretained(&rendering_helper), | |
1202 &done)); | |
1203 done.Wait(); | |
1204 rendering_thread.Stop(); | |
1205 }; | 1332 }; |
1206 | 1333 |
1207 // Test that replay after EOS works fine. | 1334 // Test that replay after EOS works fine. |
1208 INSTANTIATE_TEST_CASE_P( | 1335 INSTANTIATE_TEST_CASE_P( |
1209 ReplayAfterEOS, VideoDecodeAcceleratorTest, | 1336 ReplayAfterEOS, VideoDecodeAcceleratorParamTest, |
1210 ::testing::Values( | 1337 ::testing::Values( |
1211 MakeTuple(1, 1, 4, END_OF_STREAM_RESET, CS_RESET, false, false))); | 1338 MakeTuple(1, 1, 4, END_OF_STREAM_RESET, CS_RESET, false, false))); |
1212 | 1339 |
1213 // This hangs on Exynos, preventing further testing and wasting test machine | 1340 // This hangs on Exynos, preventing further testing and wasting test machine |
1214 // time. | 1341 // time. |
1215 // TODO(ihf): Enable again once http://crbug.com/269754 is fixed. | 1342 // TODO(ihf): Enable again once http://crbug.com/269754 is fixed. |
1216 #if defined(ARCH_CPU_X86_FAMILY) | 1343 #if defined(ARCH_CPU_X86_FAMILY) |
1217 // Test that Reset() before the first Decode() works fine. | 1344 // Test that Reset() before the first Decode() works fine. |
1218 INSTANTIATE_TEST_CASE_P( | 1345 INSTANTIATE_TEST_CASE_P( |
1219 ResetBeforeDecode, VideoDecodeAcceleratorTest, | 1346 ResetBeforeDecode, VideoDecodeAcceleratorParamTest, |
1220 ::testing::Values( | 1347 ::testing::Values( |
1221 MakeTuple(1, 1, 1, START_OF_STREAM_RESET, CS_RESET, false, false))); | 1348 MakeTuple(1, 1, 1, START_OF_STREAM_RESET, CS_RESET, false, false))); |
1222 #endif // ARCH_CPU_X86_FAMILY | 1349 #endif // ARCH_CPU_X86_FAMILY |
1223 | 1350 |
1224 // Test that Reset() mid-stream works fine and doesn't affect decoding even when | 1351 // Test that Reset() mid-stream works fine and doesn't affect decoding even when |
1225 // Decode() calls are made during the reset. | 1352 // Decode() calls are made during the reset. |
1226 INSTANTIATE_TEST_CASE_P( | 1353 INSTANTIATE_TEST_CASE_P( |
1227 MidStreamReset, VideoDecodeAcceleratorTest, | 1354 MidStreamReset, VideoDecodeAcceleratorParamTest, |
1228 ::testing::Values( | 1355 ::testing::Values( |
1229 MakeTuple(1, 1, 1, MID_STREAM_RESET, CS_RESET, false, false))); | 1356 MakeTuple(1, 1, 1, MID_STREAM_RESET, CS_RESET, false, false))); |
1230 | 1357 |
1231 INSTANTIATE_TEST_CASE_P( | 1358 INSTANTIATE_TEST_CASE_P( |
1232 SlowRendering, VideoDecodeAcceleratorTest, | 1359 SlowRendering, VideoDecodeAcceleratorParamTest, |
1233 ::testing::Values( | 1360 ::testing::Values( |
1234 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_RESET, true, false))); | 1361 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_RESET, true, false))); |
1235 | 1362 |
1236 // Test that Destroy() mid-stream works fine (primarily this is testing that no | 1363 // Test that Destroy() mid-stream works fine (primarily this is testing that no |
1237 // crashes occur). | 1364 // crashes occur). |
1238 INSTANTIATE_TEST_CASE_P( | 1365 INSTANTIATE_TEST_CASE_P( |
1239 TearDownTiming, VideoDecodeAcceleratorTest, | 1366 TearDownTiming, VideoDecodeAcceleratorParamTest, |
1240 ::testing::Values( | 1367 ::testing::Values( |
1241 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_DECODER_SET, false, false), | 1368 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_DECODER_SET, false, false), |
1242 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_INITIALIZED, false, false), | 1369 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_INITIALIZED, false, false), |
1243 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_FLUSHING, false, false), | 1370 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_FLUSHING, false, false), |
1244 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_FLUSHED, false, false), | 1371 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_FLUSHED, false, false), |
1245 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_RESETTING, false, false), | 1372 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_RESETTING, false, false), |
1246 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false, false), | 1373 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false, false), |
1247 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, | 1374 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, |
1248 static_cast<ClientState>(-1), false, false), | 1375 static_cast<ClientState>(-1), false, false), |
1249 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, | 1376 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, |
1250 static_cast<ClientState>(-10), false, false), | 1377 static_cast<ClientState>(-10), false, false), |
1251 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, | 1378 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, |
1252 static_cast<ClientState>(-100), false, false))); | 1379 static_cast<ClientState>(-100), false, false))); |
1253 | 1380 |
1254 // Test that decoding various variation works with multiple in-flight decodes. | 1381 // Test that decoding various variation works with multiple in-flight decodes. |
1255 INSTANTIATE_TEST_CASE_P( | 1382 INSTANTIATE_TEST_CASE_P( |
1256 DecodeVariations, VideoDecodeAcceleratorTest, | 1383 DecodeVariations, VideoDecodeAcceleratorParamTest, |
1257 ::testing::Values( | 1384 ::testing::Values( |
1258 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false, false), | 1385 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false, false), |
1259 MakeTuple(1, 10, 1, END_OF_STREAM_RESET, CS_RESET, false, false), | 1386 MakeTuple(1, 10, 1, END_OF_STREAM_RESET, CS_RESET, false, false), |
1260 // Tests queuing. | 1387 // Tests queuing. |
1261 MakeTuple(1, 15, 1, END_OF_STREAM_RESET, CS_RESET, false, false))); | 1388 MakeTuple(1, 15, 1, END_OF_STREAM_RESET, CS_RESET, false, false))); |
1262 | 1389 |
1263 // Find out how many concurrent decoders can go before we exhaust system | 1390 // Find out how many concurrent decoders can go before we exhaust system |
1264 // resources. | 1391 // resources. |
1265 INSTANTIATE_TEST_CASE_P( | 1392 INSTANTIATE_TEST_CASE_P( |
1266 ResourceExhaustion, VideoDecodeAcceleratorTest, | 1393 ResourceExhaustion, VideoDecodeAcceleratorParamTest, |
1267 ::testing::Values( | 1394 ::testing::Values( |
1268 // +0 hack below to promote enum to int. | 1395 // +0 hack below to promote enum to int. |
1269 MakeTuple(kMinSupportedNumConcurrentDecoders + 0, 1, 1, | 1396 MakeTuple(kMinSupportedNumConcurrentDecoders + 0, 1, 1, |
1270 END_OF_STREAM_RESET, CS_RESET, false, false), | 1397 END_OF_STREAM_RESET, CS_RESET, false, false), |
1271 MakeTuple(kMinSupportedNumConcurrentDecoders + 1, 1, 1, | 1398 MakeTuple(kMinSupportedNumConcurrentDecoders + 1, 1, 1, |
1272 END_OF_STREAM_RESET, CS_RESET, false, false))); | 1399 END_OF_STREAM_RESET, CS_RESET, false, false))); |
1273 | 1400 |
1274 // Thumbnailing test | 1401 // Thumbnailing test |
1275 INSTANTIATE_TEST_CASE_P( | 1402 INSTANTIATE_TEST_CASE_P( |
1276 Thumbnail, VideoDecodeAcceleratorTest, | 1403 Thumbnail, VideoDecodeAcceleratorParamTest, |
1277 ::testing::Values( | 1404 ::testing::Values( |
1278 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false, true))); | 1405 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false, true))); |
1279 | 1406 |
1407 // Measures the median of the decode time when VDA::Decode is called in 30FPS. | |
1408 TEST_F(VideoDecodeAcceleratorTest, TestDecodeTimeMedian) { | |
1409 RenderingHelperParams helper_params; | |
1410 gfx::Size frame_size(test_video_files_[0]->width, | |
1411 test_video_files_[0]->height); | |
1412 helper_params.frame_dimensions.push_back(frame_size); | |
1413 helper_params.window_dimensions.push_back(frame_size); | |
1414 InitializeRenderingHelper(helper_params); | |
1415 | |
1416 ClientStateNotification<ClientState>* note = | |
1417 new ClientStateNotification<ClientState>(); | |
1418 GLRenderingVDAClient* client = | |
1419 new GLRenderingVDAClient(&rendering_helper_, | |
1420 0, | |
1421 note, | |
1422 test_video_files_[0]->data_str, | |
1423 1, | |
1424 1, | |
1425 test_video_files_[0]->reset_after_frame_num, | |
1426 CS_RESET, | |
1427 test_video_files_[0]->width, | |
1428 test_video_files_[0]->height, | |
1429 test_video_files_[0]->profile, | |
1430 g_rendering_fps, | |
1431 true, | |
1432 std::numeric_limits<int>::max(), | |
1433 kWebRtcDecodeFps); | |
1434 CreateAndStartDecoder(client, note); | |
1435 WaitUntilDecodeFinish(note); | |
1436 | |
1437 int decode_time_median = client->decode_time_median(); | |
1438 std::string output_string = | |
1439 base::StringPrintf("Decode time median: %d ms", decode_time_median); | |
1440 LOG(INFO) << output_string; | |
1441 ASSERT_GT(decode_time_median, 0); | |
1442 | |
1443 if (g_output_log != NULL) | |
1444 OutputLogFile(g_output_log, output_string); | |
1445 | |
1446 rendering_loop_proxy_->DeleteSoon(FROM_HERE, client); | |
1447 rendering_loop_proxy_->DeleteSoon(FROM_HERE, note); | |
1448 WaitUntilIdle(); | |
1449 }; | |
1450 | |
1280 // TODO(fischman, vrk): add more tests! In particular: | 1451 // TODO(fischman, vrk): add more tests! In particular: |
1281 // - Test life-cycle: Seek/Stop/Pause/Play for a single decoder. | 1452 // - Test life-cycle: Seek/Stop/Pause/Play for a single decoder. |
1282 // - Test alternate configurations | 1453 // - Test alternate configurations |
1283 // - Test failure conditions. | 1454 // - Test failure conditions. |
1284 // - Test frame size changes mid-stream | 1455 // - Test frame size changes mid-stream |
1285 | 1456 |
1286 } // namespace | 1457 } // namespace |
1287 } // namespace content | 1458 } // namespace content |
1288 | 1459 |
1289 int main(int argc, char **argv) { | 1460 int main(int argc, char **argv) { |
(...skipping 10 matching lines...) Expand all Loading... | |
1300 CommandLine* cmd_line = CommandLine::ForCurrentProcess(); | 1471 CommandLine* cmd_line = CommandLine::ForCurrentProcess(); |
1301 DCHECK(cmd_line); | 1472 DCHECK(cmd_line); |
1302 | 1473 |
1303 CommandLine::SwitchMap switches = cmd_line->GetSwitches(); | 1474 CommandLine::SwitchMap switches = cmd_line->GetSwitches(); |
1304 for (CommandLine::SwitchMap::const_iterator it = switches.begin(); | 1475 for (CommandLine::SwitchMap::const_iterator it = switches.begin(); |
1305 it != switches.end(); ++it) { | 1476 it != switches.end(); ++it) { |
1306 if (it->first == "test_video_data") { | 1477 if (it->first == "test_video_data") { |
1307 content::g_test_video_data = it->second.c_str(); | 1478 content::g_test_video_data = it->second.c_str(); |
1308 continue; | 1479 continue; |
1309 } | 1480 } |
1481 // TODO(wuchengli): remove this after CrOS test changes to output_log. | |
1310 if (it->first == "frame_delivery_log") { | 1482 if (it->first == "frame_delivery_log") { |
1311 content::g_frame_delivery_log = it->second.c_str(); | 1483 content::g_output_log = it->second.c_str(); |
1484 continue; | |
1485 } | |
1486 if (it->first == "output_log") { | |
1487 content::g_output_log = it->second.c_str(); | |
1312 continue; | 1488 continue; |
1313 } | 1489 } |
1314 if (it->first == "rendering_fps") { | 1490 if (it->first == "rendering_fps") { |
1315 // On Windows, CommandLine::StringType is wstring. We need to convert | 1491 // On Windows, CommandLine::StringType is wstring. We need to convert |
1316 // it to std::string first | 1492 // it to std::string first |
1317 std::string input(it->second.begin(), it->second.end()); | 1493 std::string input(it->second.begin(), it->second.end()); |
1318 CHECK(base::StringToDouble(input, &content::g_rendering_fps)); | 1494 CHECK(base::StringToDouble(input, &content::g_rendering_fps)); |
1319 continue; | 1495 continue; |
1320 } | 1496 } |
1321 if (it->first == "disable_rendering") { | 1497 if (it->first == "disable_rendering") { |
(...skipping 12 matching lines...) Expand all Loading... | |
1334 #elif defined(OS_CHROMEOS) | 1510 #elif defined(OS_CHROMEOS) |
1335 #if defined(ARCH_CPU_ARMEL) | 1511 #if defined(ARCH_CPU_ARMEL) |
1336 content::ExynosVideoDecodeAccelerator::PreSandboxInitialization(); | 1512 content::ExynosVideoDecodeAccelerator::PreSandboxInitialization(); |
1337 #elif defined(ARCH_CPU_X86_FAMILY) | 1513 #elif defined(ARCH_CPU_X86_FAMILY) |
1338 content::VaapiWrapper::PreSandboxInitialization(); | 1514 content::VaapiWrapper::PreSandboxInitialization(); |
1339 #endif // ARCH_CPU_ARMEL | 1515 #endif // ARCH_CPU_ARMEL |
1340 #endif // OS_CHROMEOS | 1516 #endif // OS_CHROMEOS |
1341 | 1517 |
1342 return RUN_ALL_TESTS(); | 1518 return RUN_ALL_TESTS(); |
1343 } | 1519 } |
OLD | NEW |