Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(290)

Side by Side Diff: content/common/gpu/media/video_decode_accelerator_unittest.cc

Issue 19151002: Add switches: "target_fps" and "disable_rendering" to video_decode_accelerator_unittest. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: address review comment Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
(...skipping 12 matching lines...) Expand all
23 // gtest uses as struct names (inside a namespace). This means that 23 // 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. 24 // #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 25 // This is http://code.google.com/p/googletest/issues/detail?id=371
26 #include "testing/gtest/include/gtest/gtest.h" 26 #include "testing/gtest/include/gtest/gtest.h"
27 27
28 #include "base/at_exit.h" 28 #include "base/at_exit.h"
29 #include "base/bind.h" 29 #include "base/bind.h"
30 #include "base/command_line.h" 30 #include "base/command_line.h"
31 #include "base/file_util.h" 31 #include "base/file_util.h"
32 #include "base/format_macros.h" 32 #include "base/format_macros.h"
33 #include "base/md5.h" 33 #include "base/md5.h"
Ami GONE FROM CHROMIUM 2013/08/02 00:33:22 Please don't rebase while there are outstanding co
Owen Lin 2013/08/02 05:38:19 I see. Sorry for the inconvenience.
34 #include "base/platform_file.h" 34 #include "base/platform_file.h"
35 #include "base/process_util.h" 35 #include "base/process_util.h"
36 #include "base/stl_util.h" 36 #include "base/stl_util.h"
37 #include "base/strings/string_number_conversions.h" 37 #include "base/strings/string_number_conversions.h"
38 #include "base/strings/string_split.h" 38 #include "base/strings/string_split.h"
39 #include "base/strings/stringize_macros.h" 39 #include "base/strings/stringize_macros.h"
40 #include "base/strings/stringprintf.h" 40 #include "base/strings/stringprintf.h"
41 #include "base/strings/utf_string_conversions.h" 41 #include "base/strings/utf_string_conversions.h"
42 #include "base/synchronization/condition_variable.h" 42 #include "base/synchronization/condition_variable.h"
43 #include "base/synchronization/lock.h" 43 #include "base/synchronization/lock.h"
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 // - |profile| is the media::VideoCodecProfile set during Initialization. 83 // - |profile| is the media::VideoCodecProfile set during Initialization.
84 // An empty value for a numeric field means "ignore". 84 // An empty value for a numeric field means "ignore".
85 const base::FilePath::CharType* test_video_data = 85 const base::FilePath::CharType* test_video_data =
86 // FILE_PATH_LITERAL("test-25fps.vp8:320:240:250:250:50:175:11"); 86 // FILE_PATH_LITERAL("test-25fps.vp8:320:240:250:250:50:175:11");
87 FILE_PATH_LITERAL("test-25fps.h264:320:240:250:258:50:175:1"); 87 FILE_PATH_LITERAL("test-25fps.h264:320:240:250:258:50:175:1");
88 88
89 // The path of the frame delivery time log. We can enable the log and specify 89 // The path of the frame delivery time log. We can enable the log and specify
90 // the filename by the "--frame_delivery_log" switch. 90 // the filename by the "--frame_delivery_log" switch.
91 const base::FilePath::CharType* frame_delivery_log = NULL; 91 const base::FilePath::CharType* frame_delivery_log = NULL;
92 92
93 // The value is set by the switch "--rendering_fps".
94 double rendering_fps = 0;
Ami GONE FROM CHROMIUM 2013/08/02 00:33:22 global vars should be prefixed with g_ to avoid co
Owen Lin 2013/08/02 05:38:19 Done.
95
96 // Disable rendering, the value is set by the switch "--disable_rendering".
97 bool disable_rendering = false;
98
93 // Magic constants for differentiating the reasons for NotifyResetDone being 99 // Magic constants for differentiating the reasons for NotifyResetDone being
94 // called. 100 // called.
95 enum ResetPoint { 101 enum ResetPoint {
96 MID_STREAM_RESET = -2, 102 MID_STREAM_RESET = -2,
97 END_OF_STREAM_RESET = -1 103 END_OF_STREAM_RESET = -1
98 }; 104 };
99 105
100 const int kMaxResetAfterFrameNum = 100; 106 const int kMaxResetAfterFrameNum = 100;
101 const int kMaxFramesToDelayReuse = 64; 107 const int kMaxFramesToDelayReuse = 64;
102 const int kReuseDelayMs = 1000; 108 const base::TimeDelta kReuseDelay = base::TimeDelta::FromSeconds(1);
109 const base::TimeDelta kFrameDelayTolerance =
110 base::TimeDelta::FromMilliseconds(1);
103 111
104 struct TestVideoFile { 112 struct TestVideoFile {
105 explicit TestVideoFile(base::FilePath::StringType file_name) 113 explicit TestVideoFile(base::FilePath::StringType file_name)
106 : file_name(file_name), 114 : file_name(file_name),
107 width(-1), 115 width(-1),
108 height(-1), 116 height(-1),
109 num_frames(-1), 117 num_frames(-1),
110 num_fragments(-1), 118 num_fragments(-1),
111 min_fps_render(-1), 119 min_fps_render(-1),
112 min_fps_no_render(-1), 120 min_fps_no_render(-1),
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 } 221 }
214 222
215 // State of the GLRenderingVDAClient below. Order matters here as the test 223 // State of the GLRenderingVDAClient below. Order matters here as the test
216 // makes assumptions about it. 224 // makes assumptions about it.
217 enum ClientState { 225 enum ClientState {
218 CS_CREATED = 0, 226 CS_CREATED = 0,
219 CS_DECODER_SET = 1, 227 CS_DECODER_SET = 1,
220 CS_INITIALIZED = 2, 228 CS_INITIALIZED = 2,
221 CS_FLUSHING = 3, 229 CS_FLUSHING = 3,
222 CS_FLUSHED = 4, 230 CS_FLUSHED = 4,
223 CS_DONE = 5, 231 CS_RESETTING = 5,
224 CS_RESETTING = 6, 232 CS_RESET = 6,
225 CS_RESET = 7, 233 CS_ERROR = 7,
226 CS_ERROR = 8, 234 CS_DESTROYED = 8,
227 CS_DESTROYED = 9,
228 CS_MAX, // Must be last entry. 235 CS_MAX, // Must be last entry.
229 }; 236 };
230 237
231 // Helper class allowing one thread to wait on a notification from another. 238 // Helper class allowing one thread to wait on a notification from another.
232 // If notifications come in faster than they are Wait()'d for, they are 239 // If notifications come in faster than they are Wait()'d for, they are
233 // accumulated (so exactly as many Wait() calls will unblock as Notify() calls 240 // accumulated (so exactly as many Wait() calls will unblock as Notify() calls
234 // were made, regardless of order). 241 // were made, regardless of order).
235 class ClientStateNotification { 242 class ClientStateNotification {
236 public: 243 public:
237 ClientStateNotification(); 244 ClientStateNotification();
(...skipping 21 matching lines...) Expand all
259 266
260 ClientState ClientStateNotification::Wait() { 267 ClientState ClientStateNotification::Wait() {
261 base::AutoLock auto_lock(lock_); 268 base::AutoLock auto_lock(lock_);
262 while (pending_states_for_notification_.empty()) 269 while (pending_states_for_notification_.empty())
263 cv_.Wait(); 270 cv_.Wait();
264 ClientState ret = pending_states_for_notification_.front(); 271 ClientState ret = pending_states_for_notification_.front();
265 pending_states_for_notification_.pop(); 272 pending_states_for_notification_.pop();
266 return ret; 273 return ret;
267 } 274 }
268 275
276 // A wrapper client that throttles the PictureReady callbacks to a given rate.
277 // It may drops or queues frame to deliver them on time.
278 class ThrottlingVDAClient : public VideoDecodeAccelerator::Client,
279 public base::SupportsWeakPtr<ThrottlingVDAClient> {
280 public:
281 // Callback invoked whan the picture is dropped and should be reused for
282 // the decoder again.
283 typedef base::Callback<void(int32 picture_buffer_id)> ReusePictureCB;
284
285 ThrottlingVDAClient(VideoDecodeAccelerator::Client* client,
286 double fps,
287 ReusePictureCB reuse_picture_cb);
288 virtual ~ThrottlingVDAClient();
289
290 // VideoDecodeAccelerator::Client implementation
291 virtual void ProvidePictureBuffers(uint32 requested_num_of_buffers,
292 const gfx::Size& dimensions,
293 uint32 texture_target) OVERRIDE;
294 virtual void DismissPictureBuffer(int32 picture_buffer_id) OVERRIDE;
295 virtual void PictureReady(const media::Picture& picture) OVERRIDE;
296 virtual void NotifyInitializeDone() OVERRIDE;
297 virtual void NotifyEndOfBitstreamBuffer(int32 bitstream_buffer_id) OVERRIDE;
298 virtual void NotifyFlushDone() OVERRIDE;
299 virtual void NotifyResetDone() OVERRIDE;
300 virtual void NotifyError(VideoDecodeAccelerator::Error error) OVERRIDE;
301
302 int num_decoded_frames() { return num_decoded_frames_; }
303
304 private:
305
306 void CallClientPictureReady(int version);
307
308 VideoDecodeAccelerator::Client* client_;
309 ReusePictureCB reuse_picture_cb_;
310 base::TimeTicks next_frame_delivered_time_;
311 base::TimeDelta frame_duration_;
312
313 int num_decoded_frames_;
314 int stream_version_;
315 std::deque<media::Picture> pending_pictures_;
316
317 DISALLOW_IMPLICIT_CONSTRUCTORS(ThrottlingVDAClient);
318 };
319
320 ThrottlingVDAClient::ThrottlingVDAClient(
321 VideoDecodeAccelerator::Client* client,
322 double fps,
323 ReusePictureCB reuse_picture_cb)
324 : client_(client),
325 reuse_picture_cb_(reuse_picture_cb),
326 num_decoded_frames_(0),
327 stream_version_(0) {
328 CHECK(client_);
329 CHECK_GT(fps, 0);
330 frame_duration_ = base::TimeDelta::FromSeconds(1) / fps;
331 }
332
333 ThrottlingVDAClient::~ThrottlingVDAClient() {}
334
335 void ThrottlingVDAClient::ProvidePictureBuffers(
336 uint32 requested_num_of_buffers,
337 const gfx::Size& dimensions,
338 uint32 texture_target) {
339 client_->ProvidePictureBuffers(requested_num_of_buffers,
340 dimensions,
341 texture_target);
342 }
343
344 void ThrottlingVDAClient::DismissPictureBuffer(int32 picture_buffer_id) {
345 client_->DismissPictureBuffer(picture_buffer_id);
346 }
347
348 void ThrottlingVDAClient::PictureReady(const media::Picture& picture) {
349 ++num_decoded_frames_;
350
351 if (pending_pictures_.empty()) {
352 base::TimeDelta delay = next_frame_delivered_time_.is_null()
353 ? base::TimeDelta()
354 : next_frame_delivered_time_ - base::TimeTicks::Now();
355 base::MessageLoop::current()->PostDelayedTask(
356 FROM_HERE,
357 base::Bind(&ThrottlingVDAClient::CallClientPictureReady,
358 AsWeakPtr(),
359 stream_version_),
360 delay);
361 }
362 pending_pictures_.push_back(picture);
363 }
364
365 void ThrottlingVDAClient::CallClientPictureReady(int version) {
366 // Just return if we have reset the decoder
367 if (version != stream_version_)
368 return;
369
370 base::TimeTicks now = base::TimeTicks::Now();
371
372 if (next_frame_delivered_time_.is_null())
373 next_frame_delivered_time_ = now;
374
375 if (next_frame_delivered_time_ + kFrameDelayTolerance < now) {
Ami GONE FROM CHROMIUM 2013/08/02 00:33:22 Shouldn't kFrameDelayTolerance always be equal to
Owen Lin 2013/08/02 05:38:19 Good point. Thanks.
376 // Too late, drop the frame
377 reuse_picture_cb_.Run(pending_pictures_.front().picture_buffer_id());
378 } else {
379 client_->PictureReady(pending_pictures_.front());
380 }
381
382 pending_pictures_.pop_front();
383 next_frame_delivered_time_ += frame_duration_;
384 if (!pending_pictures_.empty()) {
385 base::MessageLoop::current()->PostDelayedTask(
386 FROM_HERE,
387 base::Bind(&ThrottlingVDAClient::CallClientPictureReady,
388 AsWeakPtr(),
389 stream_version_),
390 next_frame_delivered_time_ - base::TimeTicks::Now());
391 }
392 }
393
394 void ThrottlingVDAClient::NotifyInitializeDone() {
395 client_->NotifyInitializeDone();
396 }
397
398 void ThrottlingVDAClient::NotifyEndOfBitstreamBuffer(
399 int32 bitstream_buffer_id) {
400 client_->NotifyEndOfBitstreamBuffer(bitstream_buffer_id);
401 }
402
403 void ThrottlingVDAClient::NotifyFlushDone() {
404 if (!pending_pictures_.empty()) {
405 base::MessageLoop::current()->PostDelayedTask(
406 FROM_HERE,
407 base::Bind(&ThrottlingVDAClient::NotifyFlushDone,
408 base::Unretained(this)),
409 next_frame_delivered_time_ - base::TimeTicks::Now());
410 return;
411 }
412 client_->NotifyFlushDone();
413 }
414
415 void ThrottlingVDAClient::NotifyResetDone() {
416 ++stream_version_;
417 while (!pending_pictures_.empty()) {
418 reuse_picture_cb_.Run(pending_pictures_.front().picture_buffer_id());
Ami GONE FROM CHROMIUM 2013/08/02 00:33:22 indent is off here and elsewhere. why not give [gi
Owen Lin 2013/08/02 05:38:19 Done. I tried "git cl format" but it changed the c
419 pending_pictures_.pop_front();
420 }
421 next_frame_delivered_time_ = base::TimeTicks();
422 client_->NotifyResetDone();
423 }
424
425 void ThrottlingVDAClient::NotifyError(VideoDecodeAccelerator::Error error) {
426 client_->NotifyError(error);
427 }
428
269 // Client that can accept callbacks from a VideoDecodeAccelerator and is used by 429 // Client that can accept callbacks from a VideoDecodeAccelerator and is used by
270 // the TESTs below. 430 // the TESTs below.
271 class GLRenderingVDAClient : public VideoDecodeAccelerator::Client { 431 class GLRenderingVDAClient : public VideoDecodeAccelerator::Client {
272 public: 432 public:
273 // Doesn't take ownership of |rendering_helper| or |note|, which must outlive 433 // Doesn't take ownership of |rendering_helper| or |note|, which must outlive
274 // |*this|. 434 // |*this|.
275 // |num_fragments_per_decode| counts NALUs for h264 and frames for VP8. 435 // |num_fragments_per_decode| counts NALUs for h264 and frames for VP8.
276 // |num_play_throughs| indicates how many times to play through the video. 436 // |num_play_throughs| indicates how many times to play through the video.
277 // |reset_after_frame_num| can be a frame number >=0 indicating a mid-stream 437 // |reset_after_frame_num| can be a frame number >=0 indicating a mid-stream
278 // Reset() should be done after that frame number is delivered, or 438 // Reset() should be done after that frame number is delivered, or
279 // END_OF_STREAM_RESET to indicate no mid-stream Reset(). 439 // END_OF_STREAM_RESET to indicate no mid-stream Reset().
280 // |delete_decoder_state| indicates when the underlying decoder should be 440 // |delete_decoder_state| indicates when the underlying decoder should be
281 // Destroy()'d and deleted and can take values: N<0: delete after -N Decode() 441 // Destroy()'d and deleted and can take values: N<0: delete after -N Decode()
282 // calls have been made, N>=0 means interpret as ClientState. 442 // calls have been made, N>=0 means interpret as ClientState.
283 // Both |reset_after_frame_num| & |delete_decoder_state| apply only to the 443 // Both |reset_after_frame_num| & |delete_decoder_state| apply only to the
284 // last play-through (governed by |num_play_throughs|). 444 // last play-through (governed by |num_play_throughs|).
445 // |rendering_fps| indicates the target rendering fps. 0 means no target fps
446 // and it would render as fast as possible.
447 // |suppress_rendering| indicates GL rendering is suppressed or not.
285 // After |delay_reuse_after_frame_num| frame has been delivered, the client 448 // After |delay_reuse_after_frame_num| frame has been delivered, the client
286 // will start delaying the call to ReusePictureBuffer() for kReuseDelayMs. 449 // will start delaying the call to ReusePictureBuffer() for kReuseDelay.
287 GLRenderingVDAClient(RenderingHelper* rendering_helper, 450 GLRenderingVDAClient(RenderingHelper* rendering_helper,
288 int rendering_window_id, 451 int rendering_window_id,
289 ClientStateNotification* note, 452 ClientStateNotification* note,
290 const std::string& encoded_data, 453 const std::string& encoded_data,
291 int num_fragments_per_decode, 454 int num_fragments_per_decode,
292 int num_in_flight_decodes, 455 int num_in_flight_decodes,
293 int num_play_throughs, 456 int num_play_throughs,
294 int reset_after_frame_num, 457 int reset_after_frame_num,
295 int delete_decoder_state, 458 int delete_decoder_state,
296 int frame_width, 459 int frame_width,
297 int frame_height, 460 int frame_height,
298 int profile, 461 int profile,
462 double rendering_fps,
299 bool suppress_rendering, 463 bool suppress_rendering,
300 int delay_reuse_after_frame_num); 464 int delay_reuse_after_frame_num);
301 virtual ~GLRenderingVDAClient(); 465 virtual ~GLRenderingVDAClient();
302 void CreateDecoder(); 466 void CreateDecoder();
303 467
304 // VideoDecodeAccelerator::Client implementation. 468 // VideoDecodeAccelerator::Client implementation.
305 // The heart of the Client. 469 // The heart of the Client.
306 virtual void ProvidePictureBuffers(uint32 requested_num_of_buffers, 470 virtual void ProvidePictureBuffers(uint32 requested_num_of_buffers,
307 const gfx::Size& dimensions, 471 const gfx::Size& dimensions,
308 uint32 texture_target) OVERRIDE; 472 uint32 texture_target) OVERRIDE;
309 virtual void DismissPictureBuffer(int32 picture_buffer_id) OVERRIDE; 473 virtual void DismissPictureBuffer(int32 picture_buffer_id) OVERRIDE;
310 virtual void PictureReady(const media::Picture& picture) OVERRIDE; 474 virtual void PictureReady(const media::Picture& picture) OVERRIDE;
311 // Simple state changes. 475 // Simple state changes.
312 virtual void NotifyInitializeDone() OVERRIDE; 476 virtual void NotifyInitializeDone() OVERRIDE;
313 virtual void NotifyEndOfBitstreamBuffer(int32 bitstream_buffer_id) OVERRIDE; 477 virtual void NotifyEndOfBitstreamBuffer(int32 bitstream_buffer_id) OVERRIDE;
314 virtual void NotifyFlushDone() OVERRIDE; 478 virtual void NotifyFlushDone() OVERRIDE;
315 virtual void NotifyResetDone() OVERRIDE; 479 virtual void NotifyResetDone() OVERRIDE;
316 virtual void NotifyError(VideoDecodeAccelerator::Error error) OVERRIDE; 480 virtual void NotifyError(VideoDecodeAccelerator::Error error) OVERRIDE;
317 481
318 void OutputFrameDeliveryTimes(base::PlatformFile output); 482 void OutputFrameDeliveryTimes(base::PlatformFile output);
319 483
484 void NotifyFrameDropped(int32 picture_buffer_id);
485
320 // Simple getters for inspecting the state of the Client. 486 // Simple getters for inspecting the state of the Client.
321 int num_done_bitstream_buffers() { return num_done_bitstream_buffers_; } 487 int num_done_bitstream_buffers() { return num_done_bitstream_buffers_; }
322 int num_skipped_fragments() { return num_skipped_fragments_; } 488 int num_skipped_fragments() { return num_skipped_fragments_; }
323 int num_queued_fragments() { return num_queued_fragments_; } 489 int num_queued_fragments() { return num_queued_fragments_; }
324 int num_decoded_frames() { return num_decoded_frames_; } 490 int num_decoded_frames() { return num_decoded_frames_; }
325 double frames_per_second(); 491 double frames_per_second();
326 bool decoder_deleted() { return !decoder_.get(); } 492 bool decoder_deleted() { return !decoder_.get(); }
327 493
328 private: 494 private:
329 typedef std::map<int, media::PictureBuffer*> PictureBufferById; 495 typedef std::map<int, media::PictureBuffer*> PictureBufferById;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
366 int num_skipped_fragments_; 532 int num_skipped_fragments_;
367 int num_queued_fragments_; 533 int num_queued_fragments_;
368 int num_decoded_frames_; 534 int num_decoded_frames_;
369 int num_done_bitstream_buffers_; 535 int num_done_bitstream_buffers_;
370 PictureBufferById picture_buffers_by_id_; 536 PictureBufferById picture_buffers_by_id_;
371 base::TimeTicks initialize_done_ticks_; 537 base::TimeTicks initialize_done_ticks_;
372 int profile_; 538 int profile_;
373 bool suppress_rendering_; 539 bool suppress_rendering_;
374 std::vector<base::TimeTicks> frame_delivery_times_; 540 std::vector<base::TimeTicks> frame_delivery_times_;
375 int delay_reuse_after_frame_num_; 541 int delay_reuse_after_frame_num_;
542 scoped_ptr<ThrottlingVDAClient> throttling_client_;
543
544 DISALLOW_IMPLICIT_CONSTRUCTORS(GLRenderingVDAClient);
376 }; 545 };
377 546
378 GLRenderingVDAClient::GLRenderingVDAClient( 547 GLRenderingVDAClient::GLRenderingVDAClient(
379 RenderingHelper* rendering_helper, 548 RenderingHelper* rendering_helper,
380 int rendering_window_id, 549 int rendering_window_id,
381 ClientStateNotification* note, 550 ClientStateNotification* note,
382 const std::string& encoded_data, 551 const std::string& encoded_data,
383 int num_fragments_per_decode, 552 int num_fragments_per_decode,
384 int num_in_flight_decodes, 553 int num_in_flight_decodes,
385 int num_play_throughs, 554 int num_play_throughs,
386 int reset_after_frame_num, 555 int reset_after_frame_num,
387 int delete_decoder_state, 556 int delete_decoder_state,
388 int frame_width, 557 int frame_width,
389 int frame_height, 558 int frame_height,
390 int profile, 559 int profile,
560 double rendering_fps,
391 bool suppress_rendering, 561 bool suppress_rendering,
392 int delay_reuse_after_frame_num) 562 int delay_reuse_after_frame_num)
393 : rendering_helper_(rendering_helper), 563 : rendering_helper_(rendering_helper),
394 rendering_window_id_(rendering_window_id), 564 rendering_window_id_(rendering_window_id),
395 encoded_data_(encoded_data), 565 encoded_data_(encoded_data),
396 num_fragments_per_decode_(num_fragments_per_decode), 566 num_fragments_per_decode_(num_fragments_per_decode),
397 num_in_flight_decodes_(num_in_flight_decodes), outstanding_decodes_(0), 567 num_in_flight_decodes_(num_in_flight_decodes), outstanding_decodes_(0),
398 encoded_data_next_pos_to_decode_(0), next_bitstream_buffer_id_(0), 568 encoded_data_next_pos_to_decode_(0), next_bitstream_buffer_id_(0),
399 note_(note), 569 note_(note),
400 remaining_play_throughs_(num_play_throughs), 570 remaining_play_throughs_(num_play_throughs),
401 reset_after_frame_num_(reset_after_frame_num), 571 reset_after_frame_num_(reset_after_frame_num),
402 delete_decoder_state_(delete_decoder_state), 572 delete_decoder_state_(delete_decoder_state),
403 state_(CS_CREATED), 573 state_(CS_CREATED),
404 num_skipped_fragments_(0), num_queued_fragments_(0), 574 num_skipped_fragments_(0), num_queued_fragments_(0),
405 num_decoded_frames_(0), num_done_bitstream_buffers_(0), 575 num_decoded_frames_(0), num_done_bitstream_buffers_(0),
406 profile_(profile), 576 profile_(profile),
407 suppress_rendering_(suppress_rendering), 577 suppress_rendering_(suppress_rendering),
408 delay_reuse_after_frame_num_(delay_reuse_after_frame_num) { 578 delay_reuse_after_frame_num_(delay_reuse_after_frame_num) {
409 CHECK_GT(num_fragments_per_decode, 0); 579 CHECK_GT(num_fragments_per_decode, 0);
410 CHECK_GT(num_in_flight_decodes, 0); 580 CHECK_GT(num_in_flight_decodes, 0);
411 CHECK_GT(num_play_throughs, 0); 581 CHECK_GT(num_play_throughs, 0);
582 CHECK_GE(rendering_fps, 0);
583 if (rendering_fps > 0)
584 throttling_client_.reset(new ThrottlingVDAClient(
585 this,
586 rendering_fps,
587 base::Bind(&GLRenderingVDAClient::NotifyFrameDropped,
588 base::Unretained(this))));
412 } 589 }
413 590
414 GLRenderingVDAClient::~GLRenderingVDAClient() { 591 GLRenderingVDAClient::~GLRenderingVDAClient() {
415 DeleteDecoder(); // Clean up in case of expected error. 592 DeleteDecoder(); // Clean up in case of expected error.
416 CHECK(decoder_deleted()); 593 CHECK(decoder_deleted());
417 STLDeleteValues(&picture_buffers_by_id_); 594 STLDeleteValues(&picture_buffers_by_id_);
418 SetState(CS_DESTROYED); 595 SetState(CS_DESTROYED);
419 } 596 }
420 597
421 static bool DoNothingReturnTrue() { return true; } 598 static bool DoNothingReturnTrue() { return true; }
422 599
423 void GLRenderingVDAClient::CreateDecoder() { 600 void GLRenderingVDAClient::CreateDecoder() {
424 CHECK(decoder_deleted()); 601 CHECK(decoder_deleted());
425 CHECK(!decoder_.get()); 602 CHECK(!decoder_.get());
603
604 VideoDecodeAccelerator::Client* client = this;
605 if (throttling_client_)
606 client = throttling_client_.get();
426 #if defined(OS_WIN) 607 #if defined(OS_WIN)
427 decoder_.reset(new DXVAVideoDecodeAccelerator( 608 decoder_.reset(new DXVAVideoDecodeAccelerator(
428 this, base::Bind(&DoNothingReturnTrue))); 609 client, base::Bind(&DoNothingReturnTrue)));
429 #elif defined(OS_CHROMEOS) 610 #elif defined(OS_CHROMEOS)
430 #if defined(ARCH_CPU_ARMEL) 611 #if defined(ARCH_CPU_ARMEL)
431 decoder_.reset( 612 decoder_.reset(
432 new ExynosVideoDecodeAccelerator( 613 new ExynosVideoDecodeAccelerator(
433 static_cast<EGLDisplay>(rendering_helper_->GetGLDisplay()), 614 static_cast<EGLDisplay>(rendering_helper_->GetGLDisplay()),
434 static_cast<EGLContext>(rendering_helper_->GetGLContext()), 615 static_cast<EGLContext>(rendering_helper_->GetGLContext()),
435 this, base::Bind(&DoNothingReturnTrue))); 616 client, base::Bind(&DoNothingReturnTrue)));
436 #elif defined(ARCH_CPU_X86_FAMILY) 617 #elif defined(ARCH_CPU_X86_FAMILY)
437 decoder_.reset(new VaapiVideoDecodeAccelerator( 618 decoder_.reset(new VaapiVideoDecodeAccelerator(
438 static_cast<Display*>(rendering_helper_->GetGLDisplay()), 619 static_cast<Display*>(rendering_helper_->GetGLDisplay()),
439 static_cast<GLXContext>(rendering_helper_->GetGLContext()), 620 static_cast<GLXContext>(rendering_helper_->GetGLContext()),
440 this, base::Bind(&DoNothingReturnTrue))); 621 client, base::Bind(&DoNothingReturnTrue)));
441 #endif // ARCH_CPU_ARMEL 622 #endif // ARCH_CPU_ARMEL
442 #endif // OS_WIN 623 #endif // OS_WIN
443 CHECK(decoder_.get()); 624 CHECK(decoder_.get());
444 SetState(CS_DECODER_SET); 625 SetState(CS_DECODER_SET);
445 if (decoder_deleted()) 626 if (decoder_deleted())
446 return; 627 return;
447 628
448 // Configure the decoder. 629 // Configure the decoder.
449 media::VideoCodecProfile profile = media::H264PROFILE_BASELINE; 630 media::VideoCodecProfile profile = media::H264PROFILE_BASELINE;
450 if (profile_ != -1) 631 if (profile_ != -1)
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
485 delete it->second; 666 delete it->second;
486 picture_buffers_by_id_.erase(it); 667 picture_buffers_by_id_.erase(it);
487 } 668 }
488 669
489 void GLRenderingVDAClient::PictureReady(const media::Picture& picture) { 670 void GLRenderingVDAClient::PictureReady(const media::Picture& picture) {
490 // We shouldn't be getting pictures delivered after Reset has completed. 671 // We shouldn't be getting pictures delivered after Reset has completed.
491 CHECK_LT(state_, CS_RESET); 672 CHECK_LT(state_, CS_RESET);
492 673
493 if (decoder_deleted()) 674 if (decoder_deleted())
494 return; 675 return;
676
495 frame_delivery_times_.push_back(base::TimeTicks::Now()); 677 frame_delivery_times_.push_back(base::TimeTicks::Now());
496 678
497 CHECK_LE(picture.bitstream_buffer_id(), next_bitstream_buffer_id_); 679 CHECK_LE(picture.bitstream_buffer_id(), next_bitstream_buffer_id_);
498 ++num_decoded_frames_; 680 ++num_decoded_frames_;
499 681
500 // Mid-stream reset applies only to the last play-through per constructor 682 // Mid-stream reset applies only to the last play-through per constructor
501 // comment. 683 // comment.
502 if (remaining_play_throughs_ == 1 && 684 if (remaining_play_throughs_ == 1 &&
503 reset_after_frame_num_ == num_decoded_frames_) { 685 reset_after_frame_num_ == num_decoded_frames_) {
504 reset_after_frame_num_ = MID_STREAM_RESET; 686 reset_after_frame_num_ = MID_STREAM_RESET;
505 decoder_->Reset(); 687 decoder_->Reset();
506 // Re-start decoding from the beginning of the stream to avoid needing to 688 // Re-start decoding from the beginning of the stream to avoid needing to
507 // know how to find I-frames and so on in this test. 689 // know how to find I-frames and so on in this test.
508 encoded_data_next_pos_to_decode_ = 0; 690 encoded_data_next_pos_to_decode_ = 0;
509 } 691 }
510 692
511 media::PictureBuffer* picture_buffer = 693 media::PictureBuffer* picture_buffer =
512 picture_buffers_by_id_[picture.picture_buffer_id()]; 694 picture_buffers_by_id_[picture.picture_buffer_id()];
513 CHECK(picture_buffer); 695 CHECK(picture_buffer);
514 if (!suppress_rendering_) { 696 if (!suppress_rendering_) {
515 rendering_helper_->RenderTexture(picture_buffer->texture_id()); 697 rendering_helper_->RenderTexture(picture_buffer->texture_id());
516 } 698 }
517 699
518 if (num_decoded_frames_ > delay_reuse_after_frame_num_) { 700 if (num_decoded_frames_ > delay_reuse_after_frame_num_) {
519 base::MessageLoop::current()->PostDelayedTask(FROM_HERE, base::Bind( 701 base::MessageLoop::current()->PostDelayedTask(FROM_HERE, base::Bind(
520 &VideoDecodeAccelerator::ReusePictureBuffer, 702 &VideoDecodeAccelerator::ReusePictureBuffer,
521 decoder_->AsWeakPtr(), picture.picture_buffer_id()), 703 decoder_->AsWeakPtr(), picture.picture_buffer_id()),
522 base::TimeDelta::FromMilliseconds(kReuseDelayMs)); 704 kReuseDelay);
523 } else { 705 } else {
524 decoder_->ReusePictureBuffer(picture.picture_buffer_id()); 706 decoder_->ReusePictureBuffer(picture.picture_buffer_id());
525 } 707 }
526 } 708 }
527 709
528 void GLRenderingVDAClient::NotifyInitializeDone() { 710 void GLRenderingVDAClient::NotifyInitializeDone() {
529 SetState(CS_INITIALIZED); 711 SetState(CS_INITIALIZED);
530 initialize_done_ticks_ = base::TimeTicks::Now(); 712 initialize_done_ticks_ = base::TimeTicks::Now();
531 for (int i = 0; i < num_in_flight_decodes_; ++i) 713 for (int i = 0; i < num_in_flight_decodes_; ++i)
532 DecodeNextFragments(); 714 DecodeNextFragments();
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
588 base::TimeTicks t0 = initialize_done_ticks_; 770 base::TimeTicks t0 = initialize_done_ticks_;
589 for (size_t i = 0; i < frame_delivery_times_.size(); ++i) { 771 for (size_t i = 0; i < frame_delivery_times_.size(); ++i) {
590 s = base::StringPrintf("frame %04" PRIuS ": %" PRId64 " us\n", 772 s = base::StringPrintf("frame %04" PRIuS ": %" PRId64 " us\n",
591 i, 773 i,
592 (frame_delivery_times_[i] - t0).InMicroseconds()); 774 (frame_delivery_times_[i] - t0).InMicroseconds());
593 t0 = frame_delivery_times_[i]; 775 t0 = frame_delivery_times_[i];
594 base::WritePlatformFileAtCurrentPos(output, s.data(), s.length()); 776 base::WritePlatformFileAtCurrentPos(output, s.data(), s.length());
595 } 777 }
596 } 778 }
597 779
780 void GLRenderingVDAClient::NotifyFrameDropped(int32 picture_buffer_id) {
781 decoder_->ReusePictureBuffer(picture_buffer_id);
782 }
783
598 static bool LookingAtNAL(const std::string& encoded, size_t pos) { 784 static bool LookingAtNAL(const std::string& encoded, size_t pos) {
599 return encoded[pos] == 0 && encoded[pos + 1] == 0 && 785 return encoded[pos] == 0 && encoded[pos + 1] == 0 &&
600 encoded[pos + 2] == 0 && encoded[pos + 3] == 1; 786 encoded[pos + 2] == 0 && encoded[pos + 3] == 1;
601 } 787 }
602 788
603 void GLRenderingVDAClient::SetState(ClientState new_state) { 789 void GLRenderingVDAClient::SetState(ClientState new_state) {
604 note_->Notify(new_state); 790 note_->Notify(new_state);
605 state_ = new_state; 791 state_ = new_state;
606 if (!remaining_play_throughs_ && new_state == delete_decoder_state_) { 792 if (!remaining_play_throughs_ && new_state == delete_decoder_state_) {
607 CHECK(!decoder_deleted()); 793 CHECK(!decoder_deleted());
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
777 } 963 }
778 964
779 // We assert a minimal number of concurrent decoders we expect to succeed. 965 // We assert a minimal number of concurrent decoders we expect to succeed.
780 // Different platforms can support more concurrent decoders, so we don't assert 966 // Different platforms can support more concurrent decoders, so we don't assert
781 // failure above this. 967 // failure above this.
782 enum { kMinSupportedNumConcurrentDecoders = 3 }; 968 enum { kMinSupportedNumConcurrentDecoders = 3 };
783 969
784 // Test the most straightforward case possible: data is decoded from a single 970 // Test the most straightforward case possible: data is decoded from a single
785 // chunk and rendered to the screen. 971 // chunk and rendered to the screen.
786 TEST_P(VideoDecodeAcceleratorTest, TestSimpleDecode) { 972 TEST_P(VideoDecodeAcceleratorTest, TestSimpleDecode) {
787 // Can be useful for debugging VLOGs from OVDA.
788 // logging::SetMinLogLevel(-1);
789
790 // Required for Thread to work. Not used otherwise. 973 // Required for Thread to work. Not used otherwise.
791 base::ShadowingAtExitManager at_exit_manager; 974 base::ShadowingAtExitManager at_exit_manager;
792 975
793 const int num_fragments_per_decode = GetParam().a; 976 const int num_fragments_per_decode = GetParam().a;
794 const size_t num_concurrent_decoders = GetParam().b; 977 const size_t num_concurrent_decoders = GetParam().b;
795 const size_t num_in_flight_decodes = GetParam().c; 978 const size_t num_in_flight_decodes = GetParam().c;
796 const int num_play_throughs = GetParam().d; 979 const int num_play_throughs = GetParam().d;
797 const int reset_point = GetParam().e; 980 const int reset_point = GetParam().e;
798 const int delete_decoder_state = GetParam().f; 981 const int delete_decoder_state = GetParam().f;
799 bool test_reuse_delay = GetParam().g; 982 bool test_reuse_delay = GetParam().g;
800 const bool render_as_thumbnails = GetParam().h; 983 const bool render_as_thumbnails = GetParam().h;
801 984
802 std::vector<TestVideoFile*> test_video_files; 985 std::vector<TestVideoFile*> test_video_files;
803 ParseAndReadTestVideoData(test_video_data, num_concurrent_decoders, 986 ParseAndReadTestVideoData(test_video_data, num_concurrent_decoders,
804 reset_point, &test_video_files); 987 reset_point, &test_video_files);
805 988
806 // Suppress GL rendering when we are logging the frame delivery time and a 989 // Suppress GL rendering for all tests when the "--disable_rendering" is set.
807 // few other tests, to cut down overall test runtime. 990 // Otherwise, suppress rendering in all but a few tests, to cut down overall
991 // test runtime.
808 const bool suppress_rendering = num_fragments_per_decode > 1 || 992 const bool suppress_rendering = num_fragments_per_decode > 1 ||
809 frame_delivery_log != NULL; 993 content::disable_rendering;
810 994
811 std::vector<ClientStateNotification*> notes(num_concurrent_decoders, NULL); 995 std::vector<ClientStateNotification*> notes(num_concurrent_decoders, NULL);
812 std::vector<GLRenderingVDAClient*> clients(num_concurrent_decoders, NULL); 996 std::vector<GLRenderingVDAClient*> clients(num_concurrent_decoders, NULL);
813 997
814 // Initialize the rendering helper. 998 // Initialize the rendering helper.
815 base::Thread rendering_thread("GLRenderingVDAClientThread"); 999 base::Thread rendering_thread("GLRenderingVDAClientThread");
816 base::Thread::Options options; 1000 base::Thread::Options options;
817 options.message_loop_type = base::MessageLoop::TYPE_DEFAULT; 1001 options.message_loop_type = base::MessageLoop::TYPE_DEFAULT;
818 #if defined(OS_WIN) 1002 #if defined(OS_WIN)
819 // For windows the decoding thread initializes the media foundation decoder 1003 // For windows the decoding thread initializes the media foundation decoder
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
864 if (test_reuse_delay && 1048 if (test_reuse_delay &&
865 kMaxFramesToDelayReuse * 2 < video_file->num_frames) { 1049 kMaxFramesToDelayReuse * 2 < video_file->num_frames) {
866 delay_after_frame_num = video_file->num_frames - kMaxFramesToDelayReuse; 1050 delay_after_frame_num = video_file->num_frames - kMaxFramesToDelayReuse;
867 } 1051 }
868 1052
869 GLRenderingVDAClient* client = new GLRenderingVDAClient( 1053 GLRenderingVDAClient* client = new GLRenderingVDAClient(
870 rendering_helper.get(), index, note, video_file->data_str, 1054 rendering_helper.get(), index, note, video_file->data_str,
871 num_fragments_per_decode, num_in_flight_decodes, num_play_throughs, 1055 num_fragments_per_decode, num_in_flight_decodes, num_play_throughs,
872 video_file->reset_after_frame_num, delete_decoder_state, 1056 video_file->reset_after_frame_num, delete_decoder_state,
873 video_file->width, video_file->height, video_file->profile, 1057 video_file->width, video_file->height, video_file->profile,
874 suppress_rendering, delay_after_frame_num); 1058 rendering_fps, suppress_rendering, delay_after_frame_num);
875 clients[index] = client; 1059 clients[index] = client;
876 1060
877 rendering_thread.message_loop()->PostTask( 1061 rendering_thread.message_loop()->PostTask(
878 FROM_HERE, 1062 FROM_HERE,
879 base::Bind(&GLRenderingVDAClient::CreateDecoder, 1063 base::Bind(&GLRenderingVDAClient::CreateDecoder,
880 base::Unretained(client))); 1064 base::Unretained(client)));
881 1065
882 ASSERT_EQ(note->Wait(), CS_DECODER_SET); 1066 ASSERT_EQ(note->Wait(), CS_DECODER_SET);
883 } 1067 }
884 // Then wait for all the decodes to finish. 1068 // Then wait for all the decodes to finish.
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
1133 for (CommandLine::SwitchMap::const_iterator it = switches.begin(); 1317 for (CommandLine::SwitchMap::const_iterator it = switches.begin();
1134 it != switches.end(); ++it) { 1318 it != switches.end(); ++it) {
1135 if (it->first == "test_video_data") { 1319 if (it->first == "test_video_data") {
1136 content::test_video_data = it->second.c_str(); 1320 content::test_video_data = it->second.c_str();
1137 continue; 1321 continue;
1138 } 1322 }
1139 if (it->first == "frame_delivery_log") { 1323 if (it->first == "frame_delivery_log") {
1140 content::frame_delivery_log = it->second.c_str(); 1324 content::frame_delivery_log = it->second.c_str();
1141 continue; 1325 continue;
1142 } 1326 }
1327 if (it->first == "rendering_fps") {
1328 CHECK(base::StringToDouble(it->second, &content::rendering_fps));
1329 continue;
1330 }
1331 if (it->first == "disable_rendering") {
1332 content::disable_rendering = true;
1333 continue;
1334 }
1143 if (it->first == "v" || it->first == "vmodule") 1335 if (it->first == "v" || it->first == "vmodule")
1144 continue; 1336 continue;
1145 LOG(FATAL) << "Unexpected switch: " << it->first << ":" << it->second; 1337 LOG(FATAL) << "Unexpected switch: " << it->first << ":" << it->second;
1146 } 1338 }
1147 1339
1148 base::ShadowingAtExitManager at_exit_manager; 1340 base::ShadowingAtExitManager at_exit_manager;
1149 1341
1150 #if defined(OS_WIN) 1342 #if defined(OS_WIN)
1151 content::DXVAVideoDecodeAccelerator::PreSandboxInitialization(); 1343 content::DXVAVideoDecodeAccelerator::PreSandboxInitialization();
1152 #elif defined(OS_CHROMEOS) 1344 #elif defined(OS_CHROMEOS)
1153 #if defined(ARCH_CPU_ARMEL) 1345 #if defined(ARCH_CPU_ARMEL)
1154 content::ExynosVideoDecodeAccelerator::PreSandboxInitialization(); 1346 content::ExynosVideoDecodeAccelerator::PreSandboxInitialization();
1155 #elif defined(ARCH_CPU_X86_FAMILY) 1347 #elif defined(ARCH_CPU_X86_FAMILY)
1156 content::VaapiWrapper::PreSandboxInitialization(); 1348 content::VaapiWrapper::PreSandboxInitialization();
1157 #endif // ARCH_CPU_ARMEL 1349 #endif // ARCH_CPU_ARMEL
1158 #endif // OS_CHROMEOS 1350 #endif // OS_CHROMEOS
1159 1351
1160 return RUN_ALL_TESTS(); 1352 return RUN_ALL_TESTS();
1161 } 1353 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698