Chromium Code Reviews| 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 |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 81 // - |profile| is the media::VideoCodecProfile set during Initialization. | 81 // - |profile| is the media::VideoCodecProfile set during Initialization. |
| 82 // An empty value for a numeric field means "ignore". | 82 // An empty value for a numeric field means "ignore". |
| 83 const base::FilePath::CharType* test_video_data = | 83 const base::FilePath::CharType* test_video_data = |
| 84 // FILE_PATH_LITERAL("test-25fps.vp8:320:240:250:250:50:175:11"); | 84 // FILE_PATH_LITERAL("test-25fps.vp8:320:240:250:250:50:175:11"); |
| 85 FILE_PATH_LITERAL("test-25fps.h264:320:240:250:258:50:175:1"); | 85 FILE_PATH_LITERAL("test-25fps.h264:320:240:250:258:50:175:1"); |
| 86 | 86 |
| 87 // The path of the frame delivery time log. We can enable the log and specify | 87 // The path of the frame delivery time log. We can enable the log and specify |
| 88 // the filename by the "--frame_delivery_log" switch. | 88 // the filename by the "--frame_delivery_log" switch. |
| 89 const base::FilePath::CharType* frame_delivery_log = NULL; | 89 const base::FilePath::CharType* frame_delivery_log = NULL; |
| 90 | 90 |
| 91 // The value is set by the switch "--target_fps". | |
| 92 float target_fps = 0; | |
|
Ami GONE FROM CHROMIUM
2013/07/15 18:54:14
"target_fps" is too vague IMO.
IIUC you want it to
Owen Lin
2013/07/16 10:46:54
Done.
| |
| 93 | |
| 94 // Disable rendering, the value is set by the switch "--disable_rendering". | |
| 95 bool disable_rendering = false; | |
| 96 | |
| 91 // Magic constants for differentiating the reasons for NotifyResetDone being | 97 // Magic constants for differentiating the reasons for NotifyResetDone being |
| 92 // called. | 98 // called. |
| 93 enum ResetPoint { | 99 enum ResetPoint { |
| 94 MID_STREAM_RESET = -2, | 100 MID_STREAM_RESET = -2, |
| 95 END_OF_STREAM_RESET = -1 | 101 END_OF_STREAM_RESET = -1 |
| 96 }; | 102 }; |
| 97 | 103 |
| 98 const int kMaxResetAfterFrameNum = 100; | 104 const int kMaxResetAfterFrameNum = 100; |
| 99 const int kMaxFramesToDelayReuse = 64; | 105 const int kMaxFramesToDelayReuse = 64; |
| 100 const int kReuseDelayMs = 1000; | 106 const int kReuseDelayMs = 1000; |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 180 } | 186 } |
| 181 | 187 |
| 182 // State of the GLRenderingVDAClient below. Order matters here as the test | 188 // State of the GLRenderingVDAClient below. Order matters here as the test |
| 183 // makes assumptions about it. | 189 // makes assumptions about it. |
| 184 enum ClientState { | 190 enum ClientState { |
| 185 CS_CREATED = 0, | 191 CS_CREATED = 0, |
| 186 CS_DECODER_SET = 1, | 192 CS_DECODER_SET = 1, |
| 187 CS_INITIALIZED = 2, | 193 CS_INITIALIZED = 2, |
| 188 CS_FLUSHING = 3, | 194 CS_FLUSHING = 3, |
| 189 CS_FLUSHED = 4, | 195 CS_FLUSHED = 4, |
| 190 CS_DONE = 5, | 196 CS_COMPLETE_RENDERING = 5, |
|
Pawel Osciak
2013/07/15 08:07:06
I'd call this RENDERED or RENDERING_DONE. IMHO thi
Ami GONE FROM CHROMIUM
2013/07/15 18:54:14
I think none of these names is good enough to use
Owen Lin
2013/07/16 10:46:54
Are you suggesting removing this state ? My intent
Owen Lin
2013/07/16 10:46:54
Done.
| |
| 191 CS_RESETTING = 6, | 197 CS_RESETTING = 6, |
| 192 CS_RESET = 7, | 198 CS_RESET = 7, |
| 193 CS_ERROR = 8, | 199 CS_ERROR = 8, |
| 194 CS_DESTROYED = 9, | 200 CS_DESTROYED = 9, |
| 195 CS_MAX, // Must be last entry. | 201 CS_MAX, // Must be last entry. |
| 196 }; | 202 }; |
| 197 | 203 |
| 198 // Helper class allowing one thread to wait on a notification from another. | 204 // Helper class allowing one thread to wait on a notification from another. |
| 199 // If notifications come in faster than they are Wait()'d for, they are | 205 // If notifications come in faster than they are Wait()'d for, they are |
| 200 // accumulated (so exactly as many Wait() calls will unblock as Notify() calls | 206 // accumulated (so exactly as many Wait() calls will unblock as Notify() calls |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 256 ClientStateNotification* note, | 262 ClientStateNotification* note, |
| 257 const std::string& encoded_data, | 263 const std::string& encoded_data, |
| 258 int num_fragments_per_decode, | 264 int num_fragments_per_decode, |
| 259 int num_in_flight_decodes, | 265 int num_in_flight_decodes, |
| 260 int num_play_throughs, | 266 int num_play_throughs, |
| 261 int reset_after_frame_num, | 267 int reset_after_frame_num, |
| 262 int delete_decoder_state, | 268 int delete_decoder_state, |
| 263 int frame_width, | 269 int frame_width, |
| 264 int frame_height, | 270 int frame_height, |
| 265 int profile, | 271 int profile, |
| 272 float target_fps, | |
|
Pawel Osciak
2013/07/15 08:07:06
Add doc above?
Owen Lin
2013/07/16 10:46:54
Done.
| |
| 266 bool suppress_rendering, | 273 bool suppress_rendering, |
| 267 int delay_reuse_after_frame_num); | 274 int delay_reuse_after_frame_num); |
| 268 virtual ~GLRenderingVDAClient(); | 275 virtual ~GLRenderingVDAClient(); |
| 269 void CreateDecoder(); | 276 void CreateDecoder(); |
| 270 | 277 |
| 271 // VideoDecodeAccelerator::Client implementation. | 278 // VideoDecodeAccelerator::Client implementation. |
| 272 // The heart of the Client. | 279 // The heart of the Client. |
| 273 virtual void ProvidePictureBuffers(uint32 requested_num_of_buffers, | 280 virtual void ProvidePictureBuffers(uint32 requested_num_of_buffers, |
| 274 const gfx::Size& dimensions, | 281 const gfx::Size& dimensions, |
| 275 uint32 texture_target) OVERRIDE; | 282 uint32 texture_target) OVERRIDE; |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 289 int num_skipped_fragments() { return num_skipped_fragments_; } | 296 int num_skipped_fragments() { return num_skipped_fragments_; } |
| 290 int num_queued_fragments() { return num_queued_fragments_; } | 297 int num_queued_fragments() { return num_queued_fragments_; } |
| 291 int num_decoded_frames() { return num_decoded_frames_; } | 298 int num_decoded_frames() { return num_decoded_frames_; } |
| 292 double frames_per_second(); | 299 double frames_per_second(); |
| 293 bool decoder_deleted() { return !decoder_.get(); } | 300 bool decoder_deleted() { return !decoder_.get(); } |
| 294 | 301 |
| 295 private: | 302 private: |
| 296 typedef std::map<int, media::PictureBuffer*> PictureBufferById; | 303 typedef std::map<int, media::PictureBuffer*> PictureBufferById; |
| 297 | 304 |
| 298 void SetState(ClientState new_state); | 305 void SetState(ClientState new_state); |
| 306 void RenderPicture(const media::Picture& picture); | |
| 299 | 307 |
| 300 // Delete the associated OMX decoder helper. | 308 // Delete the associated OMX decoder helper. |
| 301 void DeleteDecoder(); | 309 void DeleteDecoder(); |
| 302 | 310 |
| 303 // Compute & return the first encoded bytes (including a start frame) to send | 311 // Compute & return the first encoded bytes (including a start frame) to send |
| 304 // to the decoder, starting at |start_pos| and returning | 312 // to the decoder, starting at |start_pos| and returning |
| 305 // |num_fragments_per_decode| units. Skips to the first decodable position. | 313 // |num_fragments_per_decode| units. Skips to the first decodable position. |
| 306 std::string GetBytesForFirstFragments(size_t start_pos, size_t* end_pos); | 314 std::string GetBytesForFirstFragments(size_t start_pos, size_t* end_pos); |
| 307 // Compute & return the next encoded bytes to send to the decoder (based on | 315 // Compute & return the next encoded bytes to send to the decoder (based on |
| 308 // |start_pos| & |num_fragments_per_decode_|). | 316 // |start_pos| & |num_fragments_per_decode_|). |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 333 int num_skipped_fragments_; | 341 int num_skipped_fragments_; |
| 334 int num_queued_fragments_; | 342 int num_queued_fragments_; |
| 335 int num_decoded_frames_; | 343 int num_decoded_frames_; |
| 336 int num_done_bitstream_buffers_; | 344 int num_done_bitstream_buffers_; |
| 337 PictureBufferById picture_buffers_by_id_; | 345 PictureBufferById picture_buffers_by_id_; |
| 338 base::TimeTicks initialize_done_ticks_; | 346 base::TimeTicks initialize_done_ticks_; |
| 339 int profile_; | 347 int profile_; |
| 340 bool suppress_rendering_; | 348 bool suppress_rendering_; |
| 341 std::vector<base::TimeTicks> frame_delivery_times_; | 349 std::vector<base::TimeTicks> frame_delivery_times_; |
| 342 int delay_reuse_after_frame_num_; | 350 int delay_reuse_after_frame_num_; |
| 351 base::TimeTicks next_frame_delivered_time_; | |
| 352 base::TimeDelta frame_interval_; | |
|
Ami GONE FROM CHROMIUM
2013/07/15 18:54:14
s/interval/duration/
Owen Lin
2013/07/16 10:46:54
Done.
| |
| 353 int pending_rendering_; | |
| 343 }; | 354 }; |
| 344 | 355 |
| 345 GLRenderingVDAClient::GLRenderingVDAClient( | 356 GLRenderingVDAClient::GLRenderingVDAClient( |
| 346 RenderingHelper* rendering_helper, | 357 RenderingHelper* rendering_helper, |
| 347 int rendering_window_id, | 358 int rendering_window_id, |
| 348 ClientStateNotification* note, | 359 ClientStateNotification* note, |
| 349 const std::string& encoded_data, | 360 const std::string& encoded_data, |
| 350 int num_fragments_per_decode, | 361 int num_fragments_per_decode, |
| 351 int num_in_flight_decodes, | 362 int num_in_flight_decodes, |
| 352 int num_play_throughs, | 363 int num_play_throughs, |
| 353 int reset_after_frame_num, | 364 int reset_after_frame_num, |
| 354 int delete_decoder_state, | 365 int delete_decoder_state, |
| 355 int frame_width, | 366 int frame_width, |
| 356 int frame_height, | 367 int frame_height, |
| 357 int profile, | 368 int profile, |
| 369 float target_fps, | |
| 358 bool suppress_rendering, | 370 bool suppress_rendering, |
| 359 int delay_reuse_after_frame_num) | 371 int delay_reuse_after_frame_num) |
| 360 : rendering_helper_(rendering_helper), | 372 : rendering_helper_(rendering_helper), |
| 361 rendering_window_id_(rendering_window_id), | 373 rendering_window_id_(rendering_window_id), |
| 362 encoded_data_(encoded_data), | 374 encoded_data_(encoded_data), |
| 363 num_fragments_per_decode_(num_fragments_per_decode), | 375 num_fragments_per_decode_(num_fragments_per_decode), |
| 364 num_in_flight_decodes_(num_in_flight_decodes), outstanding_decodes_(0), | 376 num_in_flight_decodes_(num_in_flight_decodes), outstanding_decodes_(0), |
| 365 encoded_data_next_pos_to_decode_(0), next_bitstream_buffer_id_(0), | 377 encoded_data_next_pos_to_decode_(0), next_bitstream_buffer_id_(0), |
| 366 note_(note), | 378 note_(note), |
| 367 remaining_play_throughs_(num_play_throughs), | 379 remaining_play_throughs_(num_play_throughs), |
| 368 reset_after_frame_num_(reset_after_frame_num), | 380 reset_after_frame_num_(reset_after_frame_num), |
| 369 delete_decoder_state_(delete_decoder_state), | 381 delete_decoder_state_(delete_decoder_state), |
| 370 state_(CS_CREATED), | 382 state_(CS_CREATED), |
| 371 num_skipped_fragments_(0), num_queued_fragments_(0), | 383 num_skipped_fragments_(0), num_queued_fragments_(0), |
| 372 num_decoded_frames_(0), num_done_bitstream_buffers_(0), | 384 num_decoded_frames_(0), num_done_bitstream_buffers_(0), |
| 373 profile_(profile), | 385 profile_(profile), |
| 374 suppress_rendering_(suppress_rendering), | 386 suppress_rendering_(suppress_rendering), |
| 375 delay_reuse_after_frame_num_(delay_reuse_after_frame_num) { | 387 delay_reuse_after_frame_num_(delay_reuse_after_frame_num) { |
| 376 CHECK_GT(num_fragments_per_decode, 0); | 388 CHECK_GT(num_fragments_per_decode, 0); |
| 377 CHECK_GT(num_in_flight_decodes, 0); | 389 CHECK_GT(num_in_flight_decodes, 0); |
| 378 CHECK_GT(num_play_throughs, 0); | 390 CHECK_GT(num_play_throughs, 0); |
| 391 CHECK_GE(target_fps, 0); | |
| 392 if (target_fps > 0) | |
| 393 frame_interval_ = base::TimeDelta::FromSeconds(1) / target_fps; | |
| 379 } | 394 } |
| 380 | 395 |
| 381 GLRenderingVDAClient::~GLRenderingVDAClient() { | 396 GLRenderingVDAClient::~GLRenderingVDAClient() { |
| 382 DeleteDecoder(); // Clean up in case of expected error. | 397 DeleteDecoder(); // Clean up in case of expected error. |
| 383 CHECK(decoder_deleted()); | 398 CHECK(decoder_deleted()); |
| 384 STLDeleteValues(&picture_buffers_by_id_); | 399 STLDeleteValues(&picture_buffers_by_id_); |
| 385 SetState(CS_DESTROYED); | 400 SetState(CS_DESTROYED); |
| 386 } | 401 } |
| 387 | 402 |
| 388 static bool DoNothingReturnTrue() { return true; } | 403 static bool DoNothingReturnTrue() { return true; } |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 452 delete it->second; | 467 delete it->second; |
| 453 picture_buffers_by_id_.erase(it); | 468 picture_buffers_by_id_.erase(it); |
| 454 } | 469 } |
| 455 | 470 |
| 456 void GLRenderingVDAClient::PictureReady(const media::Picture& picture) { | 471 void GLRenderingVDAClient::PictureReady(const media::Picture& picture) { |
| 457 // We shouldn't be getting pictures delivered after Reset has completed. | 472 // We shouldn't be getting pictures delivered after Reset has completed. |
| 458 CHECK_LT(state_, CS_RESET); | 473 CHECK_LT(state_, CS_RESET); |
| 459 | 474 |
| 460 if (decoder_deleted()) | 475 if (decoder_deleted()) |
| 461 return; | 476 return; |
| 462 frame_delivery_times_.push_back(base::TimeTicks::Now()); | |
| 463 | |
| 464 CHECK_LE(picture.bitstream_buffer_id(), next_bitstream_buffer_id_); | |
| 465 ++num_decoded_frames_; | |
| 466 | 477 |
| 467 // Mid-stream reset applies only to the last play-through per constructor | 478 // Mid-stream reset applies only to the last play-through per constructor |
| 468 // comment. | 479 // comment. |
| 469 if (remaining_play_throughs_ == 1 && | 480 if (remaining_play_throughs_ == 1 && |
| 470 reset_after_frame_num_ == num_decoded_frames_) { | 481 reset_after_frame_num_ == num_decoded_frames_) { |
| 471 reset_after_frame_num_ = MID_STREAM_RESET; | 482 reset_after_frame_num_ = MID_STREAM_RESET; |
| 472 decoder_->Reset(); | 483 decoder_->Reset(); |
| 473 // Re-start decoding from the beginning of the stream to avoid needing to | 484 // Re-start decoding from the beginning of the stream to avoid needing to |
| 474 // know how to find I-frames and so on in this test. | 485 // know how to find I-frames and so on in this test. |
| 475 encoded_data_next_pos_to_decode_ = 0; | 486 encoded_data_next_pos_to_decode_ = 0; |
| 476 } | 487 } |
| 477 | 488 |
| 489 base::TimeTicks now = base::TimeTicks::Now(); | |
| 490 | |
| 491 // Play immediately if it is the first frame or there is no target_fps | |
| 492 if (num_decoded_frames_ == 0 || frame_interval_ == base::TimeDelta()) | |
| 493 next_frame_delivered_time_ = now; | |
| 494 | |
| 495 CHECK_LE(picture.bitstream_buffer_id(), next_bitstream_buffer_id_); | |
| 496 ++num_decoded_frames_; | |
| 497 | |
| 498 while (next_frame_delivered_time_ < now) { | |
| 499 // frame dropped | |
|
Pawel Osciak
2013/07/15 08:07:06
Actually, there might be more than one frame dropp
Owen Lin
2013/07/16 10:46:54
Done.
| |
| 500 next_frame_delivered_time_ += frame_interval_; | |
| 501 } | |
| 502 | |
| 503 base::MessageLoop::current()->PostDelayedTask( | |
| 504 FROM_HERE, | |
| 505 base::Bind(&GLRenderingVDAClient::RenderPicture, | |
| 506 base::Unretained(this), | |
| 507 picture), | |
| 508 next_frame_delivered_time_ - now); | |
| 509 next_frame_delivered_time_ += frame_interval_; | |
| 510 ++pending_rendering_; | |
|
Pawel Osciak
2013/07/15 08:07:06
There is a chance that when you loop in l.498, nex
Owen Lin
2013/07/16 10:46:54
Hi, I don't really get it. When we exit the loop i
| |
| 511 } | |
| 512 | |
| 513 void GLRenderingVDAClient::RenderPicture(const media::Picture& picture) { | |
| 514 if (decoder_deleted()) | |
| 515 return; | |
| 516 frame_delivery_times_.push_back(base::TimeTicks::Now()); | |
| 517 | |
|
Pawel Osciak
2013/07/15 08:07:06
This is render time, not frame delivery time, whic
Owen Lin
2013/07/16 10:46:54
You're right. It just makes it simple to write the
| |
| 478 media::PictureBuffer* picture_buffer = | 518 media::PictureBuffer* picture_buffer = |
| 479 picture_buffers_by_id_[picture.picture_buffer_id()]; | 519 picture_buffers_by_id_[picture.picture_buffer_id()]; |
| 480 CHECK(picture_buffer); | 520 CHECK(picture_buffer); |
| 481 if (!suppress_rendering_) { | 521 if (!suppress_rendering_) { |
| 482 rendering_helper_->RenderTexture(picture_buffer->texture_id()); | 522 rendering_helper_->RenderTexture(picture_buffer->texture_id()); |
| 483 } | 523 } |
| 484 | |
| 485 if (num_decoded_frames_ > delay_reuse_after_frame_num_) { | 524 if (num_decoded_frames_ > delay_reuse_after_frame_num_) { |
| 486 base::MessageLoop::current()->PostDelayedTask(FROM_HERE, base::Bind( | 525 base::MessageLoop::current()->PostDelayedTask(FROM_HERE, base::Bind( |
| 487 &VideoDecodeAccelerator::ReusePictureBuffer, | 526 &VideoDecodeAccelerator::ReusePictureBuffer, |
| 488 base::Unretained(decoder_.get()), picture.picture_buffer_id()), | 527 base::Unretained(decoder_.get()), picture.picture_buffer_id()), |
| 489 base::TimeDelta::FromMilliseconds(kReuseDelayMs)); | 528 base::TimeDelta::FromMilliseconds(kReuseDelayMs)); |
| 490 } else { | 529 } else { |
| 491 decoder_->ReusePictureBuffer(picture.picture_buffer_id()); | 530 decoder_->ReusePictureBuffer(picture.picture_buffer_id()); |
| 492 } | 531 } |
| 532 if (--pending_rendering_ == 0 && state_ == CS_FLUSHED) { | |
| 533 SetState(CS_COMPLETE_RENDERING); | |
| 534 decoder_->Reset(); | |
| 535 SetState(CS_RESETTING); | |
| 536 } | |
| 493 } | 537 } |
| 494 | 538 |
| 495 void GLRenderingVDAClient::NotifyInitializeDone() { | 539 void GLRenderingVDAClient::NotifyInitializeDone() { |
| 496 SetState(CS_INITIALIZED); | 540 SetState(CS_INITIALIZED); |
| 497 initialize_done_ticks_ = base::TimeTicks::Now(); | 541 initialize_done_ticks_ = base::TimeTicks::Now(); |
| 498 for (int i = 0; i < num_in_flight_decodes_; ++i) | 542 for (int i = 0; i < num_in_flight_decodes_; ++i) |
| 499 DecodeNextFragments(); | 543 DecodeNextFragments(); |
| 500 DCHECK_EQ(outstanding_decodes_, num_in_flight_decodes_); | 544 DCHECK_EQ(outstanding_decodes_, num_in_flight_decodes_); |
| 501 } | 545 } |
| 502 | 546 |
| 503 void GLRenderingVDAClient::NotifyEndOfBitstreamBuffer( | 547 void GLRenderingVDAClient::NotifyEndOfBitstreamBuffer( |
| 504 int32 bitstream_buffer_id) { | 548 int32 bitstream_buffer_id) { |
| 505 // TODO(fischman): this test currently relies on this notification to make | 549 // TODO(fischman): this test currently relies on this notification to make |
| 506 // forward progress during a Reset(). But the VDA::Reset() API doesn't | 550 // forward progress during a Reset(). But the VDA::Reset() API doesn't |
| 507 // guarantee this, so stop relying on it (and remove the notifications from | 551 // guarantee this, so stop relying on it (and remove the notifications from |
| 508 // VaapiVideoDecodeAccelerator::FinishReset()). | 552 // VaapiVideoDecodeAccelerator::FinishReset()). |
| 509 ++num_done_bitstream_buffers_; | 553 ++num_done_bitstream_buffers_; |
| 510 --outstanding_decodes_; | 554 --outstanding_decodes_; |
| 511 DecodeNextFragments(); | 555 DecodeNextFragments(); |
| 512 } | 556 } |
| 513 | 557 |
| 514 void GLRenderingVDAClient::NotifyFlushDone() { | 558 void GLRenderingVDAClient::NotifyFlushDone() { |
| 515 if (decoder_deleted()) | 559 if (decoder_deleted()) |
| 516 return; | 560 return; |
| 517 SetState(CS_FLUSHED); | 561 SetState(CS_FLUSHED); |
| 518 --remaining_play_throughs_; | 562 --remaining_play_throughs_; |
| 519 DCHECK_GE(remaining_play_throughs_, 0); | 563 DCHECK_GE(remaining_play_throughs_, 0); |
| 520 if (decoder_deleted()) | 564 if (decoder_deleted()) |
| 521 return; | 565 return; |
| 522 decoder_->Reset(); | 566 if (pending_rendering_ == 0) { |
|
Ami GONE FROM CHROMIUM
2013/07/15 18:54:14
Why do none of the other notifications test for th
Owen Lin
2013/07/16 10:46:54
I don't get it. Can you be more specific ?
Do you
| |
| 523 SetState(CS_RESETTING); | 567 SetState(CS_COMPLETE_RENDERING); |
| 568 decoder_->Reset(); | |
| 569 SetState(CS_RESETTING); | |
|
Ami GONE FROM CHROMIUM
2013/07/15 18:54:14
Duplicating this block here and at l.532 is a code
Owen Lin
2013/07/16 10:46:54
Do you suggest me the following:
if (pending_rend
| |
| 570 } | |
| 524 } | 571 } |
| 525 | 572 |
| 526 void GLRenderingVDAClient::NotifyResetDone() { | 573 void GLRenderingVDAClient::NotifyResetDone() { |
| 527 if (decoder_deleted()) | 574 if (decoder_deleted()) |
| 528 return; | 575 return; |
| 529 | 576 |
| 530 if (reset_after_frame_num_ == MID_STREAM_RESET) { | 577 if (reset_after_frame_num_ == MID_STREAM_RESET) { |
| 531 reset_after_frame_num_ = END_OF_STREAM_RESET; | 578 reset_after_frame_num_ = END_OF_STREAM_RESET; |
| 532 DecodeNextFragments(); | 579 DecodeNextFragments(); |
| 533 return; | 580 return; |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 718 // - whether to test slow rendering by delaying ReusePictureBuffer(). | 765 // - whether to test slow rendering by delaying ReusePictureBuffer(). |
| 719 class VideoDecodeAcceleratorTest | 766 class VideoDecodeAcceleratorTest |
| 720 : public ::testing::TestWithParam< | 767 : public ::testing::TestWithParam< |
| 721 Tuple7<int, int, int, int, ResetPoint, ClientState, bool> > { | 768 Tuple7<int, int, int, int, ResetPoint, ClientState, bool> > { |
| 722 }; | 769 }; |
| 723 | 770 |
| 724 // Helper so that gtest failures emit a more readable version of the tuple than | 771 // Helper so that gtest failures emit a more readable version of the tuple than |
| 725 // its byte representation. | 772 // its byte representation. |
| 726 ::std::ostream& operator<<( | 773 ::std::ostream& operator<<( |
| 727 ::std::ostream& os, | 774 ::std::ostream& os, |
| 728 const Tuple6<int, int, int, int, ResetPoint, ClientState>& t) { | 775 const Tuple7<int, int, int, int, ResetPoint, ClientState, bool>& t) { |
| 729 return os << t.a << ", " << t.b << ", " << t.c << ", " << t.d << ", " << t.e | 776 return os << t.a << ", " << t.b << ", " << t.c << ", " << t.d << ", " << t.e |
| 730 << ", " << t.f; | 777 << ", " << t.f << ", " << t.g; |
| 731 } | 778 } |
| 732 | 779 |
| 733 // Wait for |note| to report a state and if it's not |expected_state| then | 780 // Wait for |note| to report a state and if it's not |expected_state| then |
| 734 // assert |client| has deleted its decoder. | 781 // assert |client| has deleted its decoder. |
| 735 static void AssertWaitForStateOrDeleted(ClientStateNotification* note, | 782 static void AssertWaitForStateOrDeleted(ClientStateNotification* note, |
| 736 GLRenderingVDAClient* client, | 783 GLRenderingVDAClient* client, |
| 737 ClientState expected_state) { | 784 ClientState expected_state) { |
| 738 ClientState state = note->Wait(); | 785 ClientState state = note->Wait(); |
| 739 if (state == expected_state) return; | 786 if (state == expected_state) return; |
| 740 ASSERT_TRUE(client->decoder_deleted()) | 787 ASSERT_TRUE(client->decoder_deleted()) |
| 741 << "Decoder not deleted but Wait() returned " << state | 788 << "Decoder not deleted but Wait() returned " << state |
| 742 << ", instead of " << expected_state; | 789 << ", instead of " << expected_state; |
| 743 } | 790 } |
| 744 | 791 |
| 745 // We assert a minimal number of concurrent decoders we expect to succeed. | 792 // We assert a minimal number of concurrent decoders we expect to succeed. |
| 746 // Different platforms can support more concurrent decoders, so we don't assert | 793 // Different platforms can support more concurrent decoders, so we don't assert |
| 747 // failure above this. | 794 // failure above this. |
| 748 enum { kMinSupportedNumConcurrentDecoders = 3 }; | 795 enum { kMinSupportedNumConcurrentDecoders = 3 }; |
| 749 | 796 |
| 750 // Test the most straightforward case possible: data is decoded from a single | 797 // Test the most straightforward case possible: data is decoded from a single |
| 751 // chunk and rendered to the screen. | 798 // chunk and rendered to the screen. |
| 752 TEST_P(VideoDecodeAcceleratorTest, TestSimpleDecode) { | 799 TEST_P(VideoDecodeAcceleratorTest, TestSimpleDecode) { |
| 753 // Can be useful for debugging VLOGs from OVDA. | |
| 754 // logging::SetMinLogLevel(-1); | |
| 755 | |
| 756 // Required for Thread to work. Not used otherwise. | 800 // Required for Thread to work. Not used otherwise. |
| 757 base::ShadowingAtExitManager at_exit_manager; | 801 base::ShadowingAtExitManager at_exit_manager; |
| 758 | 802 |
| 759 const int num_fragments_per_decode = GetParam().a; | 803 const int num_fragments_per_decode = GetParam().a; |
| 760 const size_t num_concurrent_decoders = GetParam().b; | 804 const size_t num_concurrent_decoders = GetParam().b; |
| 761 const size_t num_in_flight_decodes = GetParam().c; | 805 const size_t num_in_flight_decodes = GetParam().c; |
| 762 const int num_play_throughs = GetParam().d; | 806 const int num_play_throughs = GetParam().d; |
| 763 const int reset_point = GetParam().e; | 807 const int reset_point = GetParam().e; |
| 764 const int delete_decoder_state = GetParam().f; | 808 const int delete_decoder_state = GetParam().f; |
| 765 bool test_reuse_delay = GetParam().g; | 809 bool test_reuse_delay = GetParam().g; |
| 766 | 810 |
| 767 std::vector<TestVideoFile*> test_video_files; | 811 std::vector<TestVideoFile*> test_video_files; |
| 768 ParseAndReadTestVideoData(test_video_data, num_concurrent_decoders, | 812 ParseAndReadTestVideoData(test_video_data, num_concurrent_decoders, |
| 769 reset_point, &test_video_files); | 813 reset_point, &test_video_files); |
| 770 | 814 |
| 771 // Suppress GL rendering when we are logging the frame delivery time and a | 815 // Suppress GL rendering when we are logging the frame delivery time and a |
| 772 // few other tests, to cut down overall test runtime. | 816 // few other tests, to cut down overall test runtime. |
| 773 const bool suppress_rendering = num_fragments_per_decode > 1 || | 817 const bool suppress_rendering = num_fragments_per_decode > 1 || |
| 774 frame_delivery_log != NULL; | 818 content::disable_rendering; |
| 775 | 819 |
| 776 std::vector<ClientStateNotification*> notes(num_concurrent_decoders, NULL); | 820 std::vector<ClientStateNotification*> notes(num_concurrent_decoders, NULL); |
| 777 std::vector<GLRenderingVDAClient*> clients(num_concurrent_decoders, NULL); | 821 std::vector<GLRenderingVDAClient*> clients(num_concurrent_decoders, NULL); |
| 778 | 822 |
| 779 // Initialize the rendering helper. | 823 // Initialize the rendering helper. |
| 780 base::Thread rendering_thread("GLRenderingVDAClientThread"); | 824 base::Thread rendering_thread("GLRenderingVDAClientThread"); |
| 781 base::Thread::Options options; | 825 base::Thread::Options options; |
| 782 options.message_loop_type = base::MessageLoop::TYPE_DEFAULT; | 826 options.message_loop_type = base::MessageLoop::TYPE_DEFAULT; |
| 783 #if defined(OS_WIN) | 827 #if defined(OS_WIN) |
| 784 // For windows the decoding thread initializes the media foundation decoder | 828 // For windows the decoding thread initializes the media foundation decoder |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 814 if (test_reuse_delay && | 858 if (test_reuse_delay && |
| 815 kMaxFramesToDelayReuse * 2 < video_file->num_frames) { | 859 kMaxFramesToDelayReuse * 2 < video_file->num_frames) { |
| 816 delay_after_frame_num = video_file->num_frames - kMaxFramesToDelayReuse; | 860 delay_after_frame_num = video_file->num_frames - kMaxFramesToDelayReuse; |
| 817 } | 861 } |
| 818 | 862 |
| 819 GLRenderingVDAClient* client = new GLRenderingVDAClient( | 863 GLRenderingVDAClient* client = new GLRenderingVDAClient( |
| 820 rendering_helper.get(), index, note, video_file->data_str, | 864 rendering_helper.get(), index, note, video_file->data_str, |
| 821 num_fragments_per_decode, num_in_flight_decodes, num_play_throughs, | 865 num_fragments_per_decode, num_in_flight_decodes, num_play_throughs, |
| 822 video_file->reset_after_frame_num, delete_decoder_state, | 866 video_file->reset_after_frame_num, delete_decoder_state, |
| 823 video_file->width, video_file->height, video_file->profile, | 867 video_file->width, video_file->height, video_file->profile, |
| 824 suppress_rendering, delay_after_frame_num); | 868 target_fps, suppress_rendering, delay_after_frame_num); |
| 825 clients[index] = client; | 869 clients[index] = client; |
| 826 | 870 |
| 827 rendering_thread.message_loop()->PostTask( | 871 rendering_thread.message_loop()->PostTask( |
| 828 FROM_HERE, | 872 FROM_HERE, |
| 829 base::Bind(&GLRenderingVDAClient::CreateDecoder, | 873 base::Bind(&GLRenderingVDAClient::CreateDecoder, |
| 830 base::Unretained(client))); | 874 base::Unretained(client))); |
| 831 | 875 |
| 832 ASSERT_EQ(note->Wait(), CS_DECODER_SET); | 876 ASSERT_EQ(note->Wait(), CS_DECODER_SET); |
| 833 } | 877 } |
| 834 // Then wait for all the decodes to finish. | 878 // Then wait for all the decodes to finish. |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 853 if (n > 0) { | 897 if (n > 0) { |
| 854 ASSERT_NO_FATAL_FAILURE( | 898 ASSERT_NO_FATAL_FAILURE( |
| 855 AssertWaitForStateOrDeleted(note, clients[i], CS_INITIALIZED)); | 899 AssertWaitForStateOrDeleted(note, clients[i], CS_INITIALIZED)); |
| 856 } | 900 } |
| 857 // InitializeDone kicks off decoding inside the client, so we just need to | 901 // InitializeDone kicks off decoding inside the client, so we just need to |
| 858 // wait for Flush. | 902 // wait for Flush. |
| 859 ASSERT_NO_FATAL_FAILURE( | 903 ASSERT_NO_FATAL_FAILURE( |
| 860 AssertWaitForStateOrDeleted(note, clients[i], CS_FLUSHING)); | 904 AssertWaitForStateOrDeleted(note, clients[i], CS_FLUSHING)); |
| 861 ASSERT_NO_FATAL_FAILURE( | 905 ASSERT_NO_FATAL_FAILURE( |
| 862 AssertWaitForStateOrDeleted(note, clients[i], CS_FLUSHED)); | 906 AssertWaitForStateOrDeleted(note, clients[i], CS_FLUSHED)); |
| 863 // FlushDone requests Reset(). | 907 ASSERT_NO_FATAL_FAILURE( |
| 908 AssertWaitForStateOrDeleted(note, clients[i], CS_COMPLETE_RENDERING)); | |
| 864 ASSERT_NO_FATAL_FAILURE( | 909 ASSERT_NO_FATAL_FAILURE( |
| 865 AssertWaitForStateOrDeleted(note, clients[i], CS_RESETTING)); | 910 AssertWaitForStateOrDeleted(note, clients[i], CS_RESETTING)); |
| 866 } | 911 } |
| 867 ASSERT_NO_FATAL_FAILURE( | 912 ASSERT_NO_FATAL_FAILURE( |
| 868 AssertWaitForStateOrDeleted(note, clients[i], CS_RESET)); | 913 AssertWaitForStateOrDeleted(note, clients[i], CS_RESET)); |
| 914 | |
| 869 // ResetDone requests Destroy(). | 915 // ResetDone requests Destroy(). |
| 870 ASSERT_NO_FATAL_FAILURE( | 916 ASSERT_NO_FATAL_FAILURE( |
| 871 AssertWaitForStateOrDeleted(note, clients[i], CS_DESTROYED)); | 917 AssertWaitForStateOrDeleted(note, clients[i], CS_DESTROYED)); |
| 872 } | 918 } |
| 873 // Finally assert that decoding went as expected. | 919 // Finally assert that decoding went as expected. |
| 874 for (size_t i = 0; i < num_concurrent_decoders && | 920 for (size_t i = 0; i < num_concurrent_decoders && |
| 875 !skip_performance_and_correctness_checks; ++i) { | 921 !skip_performance_and_correctness_checks; ++i) { |
| 876 // We can only make performance/correctness assertions if the decoder was | 922 // We can only make performance/correctness assertions if the decoder was |
| 877 // allowed to finish. | 923 // allowed to finish. |
| 878 if (delete_decoder_state < CS_FLUSHED) | 924 if (delete_decoder_state < CS_FLUSHED) |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1032 for (CommandLine::SwitchMap::const_iterator it = switches.begin(); | 1078 for (CommandLine::SwitchMap::const_iterator it = switches.begin(); |
| 1033 it != switches.end(); ++it) { | 1079 it != switches.end(); ++it) { |
| 1034 if (it->first == "test_video_data") { | 1080 if (it->first == "test_video_data") { |
| 1035 content::test_video_data = it->second.c_str(); | 1081 content::test_video_data = it->second.c_str(); |
| 1036 continue; | 1082 continue; |
| 1037 } | 1083 } |
| 1038 if (it->first == "frame_delivery_log") { | 1084 if (it->first == "frame_delivery_log") { |
| 1039 content::frame_delivery_log = it->second.c_str(); | 1085 content::frame_delivery_log = it->second.c_str(); |
| 1040 continue; | 1086 continue; |
| 1041 } | 1087 } |
| 1088 if (it->first == "target_fps") { | |
| 1089 double input_value = 0; | |
| 1090 CHECK(base::StringToDouble(it->second, &input_value)); | |
| 1091 content::target_fps = static_cast<float>(input_value); | |
|
Ami GONE FROM CHROMIUM
2013/07/15 18:54:14
why not just use double instead of float and avoid
Owen Lin
2013/07/16 10:46:54
Done.
| |
| 1092 continue; | |
| 1093 } | |
| 1094 if (it->first == "disable_rendering") { | |
| 1095 content::disable_rendering = true; | |
| 1096 continue; | |
| 1097 } | |
| 1042 if (it->first == "v" || it->first == "vmodule") | 1098 if (it->first == "v" || it->first == "vmodule") |
| 1043 continue; | 1099 continue; |
| 1044 LOG(FATAL) << "Unexpected switch: " << it->first << ":" << it->second; | 1100 LOG(FATAL) << "Unexpected switch: " << it->first << ":" << it->second; |
| 1045 } | 1101 } |
| 1046 | 1102 |
| 1047 base::ShadowingAtExitManager at_exit_manager; | 1103 base::ShadowingAtExitManager at_exit_manager; |
| 1048 | 1104 |
| 1049 #if defined(OS_WIN) | 1105 #if defined(OS_WIN) |
| 1050 content::DXVAVideoDecodeAccelerator::PreSandboxInitialization(); | 1106 content::DXVAVideoDecodeAccelerator::PreSandboxInitialization(); |
| 1051 #elif defined(OS_CHROMEOS) | 1107 #elif defined(OS_CHROMEOS) |
| 1052 #if defined(ARCH_CPU_ARMEL) | 1108 #if defined(ARCH_CPU_ARMEL) |
| 1053 content::ExynosVideoDecodeAccelerator::PreSandboxInitialization(); | 1109 content::ExynosVideoDecodeAccelerator::PreSandboxInitialization(); |
| 1054 #elif defined(ARCH_CPU_X86_FAMILY) | 1110 #elif defined(ARCH_CPU_X86_FAMILY) |
| 1055 content::VaapiWrapper::PreSandboxInitialization(); | 1111 content::VaapiWrapper::PreSandboxInitialization(); |
| 1056 #endif // ARCH_CPU_ARMEL | 1112 #endif // ARCH_CPU_ARMEL |
| 1057 #endif // OS_CHROMEOS | 1113 #endif // OS_CHROMEOS |
| 1058 | 1114 |
| 1059 return RUN_ALL_TESTS(); | 1115 return RUN_ALL_TESTS(); |
| 1060 } | 1116 } |
| OLD | NEW |