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 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
209 double fps, | 209 double fps, |
210 ReusePictureCB reuse_picture_cb); | 210 ReusePictureCB reuse_picture_cb); |
211 virtual ~ThrottlingVDAClient(); | 211 virtual ~ThrottlingVDAClient(); |
212 | 212 |
213 // VideoDecodeAccelerator::Client implementation | 213 // VideoDecodeAccelerator::Client implementation |
214 virtual void ProvidePictureBuffers(uint32 requested_num_of_buffers, | 214 virtual void ProvidePictureBuffers(uint32 requested_num_of_buffers, |
215 const gfx::Size& dimensions, | 215 const gfx::Size& dimensions, |
216 uint32 texture_target) OVERRIDE; | 216 uint32 texture_target) OVERRIDE; |
217 virtual void DismissPictureBuffer(int32 picture_buffer_id) OVERRIDE; | 217 virtual void DismissPictureBuffer(int32 picture_buffer_id) OVERRIDE; |
218 virtual void PictureReady(const media::Picture& picture) OVERRIDE; | 218 virtual void PictureReady(const media::Picture& picture) OVERRIDE; |
219 virtual void NotifyInitializeDone() OVERRIDE; | |
220 virtual void NotifyEndOfBitstreamBuffer(int32 bitstream_buffer_id) OVERRIDE; | 219 virtual void NotifyEndOfBitstreamBuffer(int32 bitstream_buffer_id) OVERRIDE; |
221 virtual void NotifyFlushDone() OVERRIDE; | 220 virtual void NotifyFlushDone() OVERRIDE; |
222 virtual void NotifyResetDone() OVERRIDE; | 221 virtual void NotifyResetDone() OVERRIDE; |
223 virtual void NotifyError(VideoDecodeAccelerator::Error error) OVERRIDE; | 222 virtual void NotifyError(VideoDecodeAccelerator::Error error) OVERRIDE; |
224 | 223 |
225 int num_decoded_frames() { return num_decoded_frames_; } | 224 int num_decoded_frames() { return num_decoded_frames_; } |
226 | 225 |
227 private: | 226 private: |
228 | 227 |
229 void CallClientPictureReady(int version); | 228 void CallClientPictureReady(int version); |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
305 if (!pending_pictures_.empty()) { | 304 if (!pending_pictures_.empty()) { |
306 base::MessageLoop::current()->PostDelayedTask( | 305 base::MessageLoop::current()->PostDelayedTask( |
307 FROM_HERE, | 306 FROM_HERE, |
308 base::Bind(&ThrottlingVDAClient::CallClientPictureReady, | 307 base::Bind(&ThrottlingVDAClient::CallClientPictureReady, |
309 AsWeakPtr(), | 308 AsWeakPtr(), |
310 stream_version_), | 309 stream_version_), |
311 next_frame_delivered_time_ - base::TimeTicks::Now()); | 310 next_frame_delivered_time_ - base::TimeTicks::Now()); |
312 } | 311 } |
313 } | 312 } |
314 | 313 |
315 void ThrottlingVDAClient::NotifyInitializeDone() { | |
316 client_->NotifyInitializeDone(); | |
317 } | |
318 | |
319 void ThrottlingVDAClient::NotifyEndOfBitstreamBuffer( | 314 void ThrottlingVDAClient::NotifyEndOfBitstreamBuffer( |
320 int32 bitstream_buffer_id) { | 315 int32 bitstream_buffer_id) { |
321 client_->NotifyEndOfBitstreamBuffer(bitstream_buffer_id); | 316 client_->NotifyEndOfBitstreamBuffer(bitstream_buffer_id); |
322 } | 317 } |
323 | 318 |
324 void ThrottlingVDAClient::NotifyFlushDone() { | 319 void ThrottlingVDAClient::NotifyFlushDone() { |
325 if (!pending_pictures_.empty()) { | 320 if (!pending_pictures_.empty()) { |
326 base::MessageLoop::current()->PostDelayedTask( | 321 base::MessageLoop::current()->PostDelayedTask( |
327 FROM_HERE, | 322 FROM_HERE, |
328 base::Bind(&ThrottlingVDAClient::NotifyFlushDone, | 323 base::Bind(&ThrottlingVDAClient::NotifyFlushDone, |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
390 void CreateAndStartDecoder(); | 385 void CreateAndStartDecoder(); |
391 | 386 |
392 // VideoDecodeAccelerator::Client implementation. | 387 // VideoDecodeAccelerator::Client implementation. |
393 // The heart of the Client. | 388 // The heart of the Client. |
394 virtual void ProvidePictureBuffers(uint32 requested_num_of_buffers, | 389 virtual void ProvidePictureBuffers(uint32 requested_num_of_buffers, |
395 const gfx::Size& dimensions, | 390 const gfx::Size& dimensions, |
396 uint32 texture_target) OVERRIDE; | 391 uint32 texture_target) OVERRIDE; |
397 virtual void DismissPictureBuffer(int32 picture_buffer_id) OVERRIDE; | 392 virtual void DismissPictureBuffer(int32 picture_buffer_id) OVERRIDE; |
398 virtual void PictureReady(const media::Picture& picture) OVERRIDE; | 393 virtual void PictureReady(const media::Picture& picture) OVERRIDE; |
399 // Simple state changes. | 394 // Simple state changes. |
400 virtual void NotifyInitializeDone() OVERRIDE; | |
401 virtual void NotifyEndOfBitstreamBuffer(int32 bitstream_buffer_id) OVERRIDE; | 395 virtual void NotifyEndOfBitstreamBuffer(int32 bitstream_buffer_id) OVERRIDE; |
402 virtual void NotifyFlushDone() OVERRIDE; | 396 virtual void NotifyFlushDone() OVERRIDE; |
403 virtual void NotifyResetDone() OVERRIDE; | 397 virtual void NotifyResetDone() OVERRIDE; |
404 virtual void NotifyError(VideoDecodeAccelerator::Error error) OVERRIDE; | 398 virtual void NotifyError(VideoDecodeAccelerator::Error error) OVERRIDE; |
405 | 399 |
406 void OutputFrameDeliveryTimes(base::File* output); | 400 void OutputFrameDeliveryTimes(base::File* output); |
407 | 401 |
408 void NotifyFrameDropped(int32 picture_buffer_id); | 402 void NotifyFrameDropped(int32 picture_buffer_id); |
409 | 403 |
410 // Simple getters for inspecting the state of the Client. | 404 // Simple getters for inspecting the state of the Client. |
411 int num_done_bitstream_buffers() { return num_done_bitstream_buffers_; } | 405 int num_done_bitstream_buffers() { return num_done_bitstream_buffers_; } |
412 int num_skipped_fragments() { return num_skipped_fragments_; } | 406 int num_skipped_fragments() { return num_skipped_fragments_; } |
413 int num_queued_fragments() { return num_queued_fragments_; } | 407 int num_queued_fragments() { return num_queued_fragments_; } |
414 int num_decoded_frames(); | 408 int num_decoded_frames(); |
415 double frames_per_second(); | 409 double frames_per_second(); |
416 // Return the median of the decode time in milliseconds. | 410 // Return the median of the decode time in milliseconds. |
417 int decode_time_median(); | 411 int decode_time_median(); |
418 bool decoder_deleted() { return !decoder_.get(); } | 412 bool decoder_deleted() { return !decoder_.get(); } |
419 | 413 |
420 private: | 414 private: |
421 typedef std::map<int, media::PictureBuffer*> PictureBufferById; | 415 typedef std::map<int, media::PictureBuffer*> PictureBufferById; |
422 | 416 |
423 void SetState(ClientState new_state); | 417 void SetState(ClientState new_state); |
| 418 void FinishInitialization(); |
424 | 419 |
425 // Delete the associated decoder helper. | 420 // Delete the associated decoder helper. |
426 void DeleteDecoder(); | 421 void DeleteDecoder(); |
427 | 422 |
428 // Compute & return the first encoded bytes (including a start frame) to send | 423 // Compute & return the first encoded bytes (including a start frame) to send |
429 // to the decoder, starting at |start_pos| and returning one fragment. Skips | 424 // to the decoder, starting at |start_pos| and returning one fragment. Skips |
430 // to the first decodable position. | 425 // to the first decodable position. |
431 std::string GetBytesForFirstFragment(size_t start_pos, size_t* end_pos); | 426 std::string GetBytesForFirstFragment(size_t start_pos, size_t* end_pos); |
432 // Compute & return the encoded bytes of next fragment to send to the decoder | 427 // Compute & return the encoded bytes of next fragment to send to the decoder |
433 // (based on |start_pos|). | 428 // (based on |start_pos|). |
434 std::string GetBytesForNextFragment(size_t start_pos, size_t* end_pos); | 429 std::string GetBytesForNextFragment(size_t start_pos, size_t* end_pos); |
435 // Helpers for GetBytesForNextFragment above. | 430 // Helpers for GetBytesForNextFragment above. |
436 void GetBytesForNextNALU(size_t start_pos, size_t* end_pos); // For h.264. | 431 void GetBytesForNextNALU(size_t start_pos, size_t* end_pos); // For h.264. |
437 std::string GetBytesForNextFrame( | 432 std::string GetBytesForNextFrame( |
438 size_t start_pos, size_t* end_pos); // For VP8. | 433 size_t start_pos, size_t* end_pos); // For VP8. |
439 | 434 |
440 // Request decode of the next fragment in the encoded data. | 435 // Request decode of the next fragment in the encoded data. |
441 void DecodeNextFragment(); | 436 void DecodeNextFragment(); |
442 | 437 |
443 RenderingHelper* rendering_helper_; | 438 RenderingHelper* rendering_helper_; |
444 int rendering_window_id_; | 439 int rendering_window_id_; |
445 std::string encoded_data_; | 440 std::string encoded_data_; |
446 const int num_in_flight_decodes_; | 441 const int num_in_flight_decodes_; |
447 int outstanding_decodes_; | 442 int outstanding_decodes_; |
448 size_t encoded_data_next_pos_to_decode_; | 443 size_t encoded_data_next_pos_to_decode_; |
449 int next_bitstream_buffer_id_; | 444 int next_bitstream_buffer_id_; |
450 ClientStateNotification<ClientState>* note_; | 445 ClientStateNotification<ClientState>* note_; |
451 scoped_ptr<VideoDecodeAccelerator> decoder_; | 446 scoped_ptr<VideoDecodeAccelerator> decoder_; |
| 447 scoped_ptr<base::WeakPtrFactory<VideoDecodeAccelerator> > |
| 448 weak_decoder_factory_; |
452 std::set<int> outstanding_texture_ids_; | 449 std::set<int> outstanding_texture_ids_; |
453 int remaining_play_throughs_; | 450 int remaining_play_throughs_; |
454 int reset_after_frame_num_; | 451 int reset_after_frame_num_; |
455 int delete_decoder_state_; | 452 int delete_decoder_state_; |
456 ClientState state_; | 453 ClientState state_; |
457 int num_skipped_fragments_; | 454 int num_skipped_fragments_; |
458 int num_queued_fragments_; | 455 int num_queued_fragments_; |
459 int num_decoded_frames_; | 456 int num_decoded_frames_; |
460 int num_done_bitstream_buffers_; | 457 int num_done_bitstream_buffers_; |
461 PictureBufferById picture_buffers_by_id_; | 458 PictureBufferById picture_buffers_by_id_; |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
569 device.Pass(), | 566 device.Pass(), |
570 base::MessageLoopProxy::current())); | 567 base::MessageLoopProxy::current())); |
571 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) | 568 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) |
572 CHECK_EQ(gfx::kGLImplementationDesktopGL, gfx::GetGLImplementation()) | 569 CHECK_EQ(gfx::kGLImplementationDesktopGL, gfx::GetGLImplementation()) |
573 << "Hardware video decode does not work with OSMesa"; | 570 << "Hardware video decode does not work with OSMesa"; |
574 decoder_.reset(new VaapiVideoDecodeAccelerator( | 571 decoder_.reset(new VaapiVideoDecodeAccelerator( |
575 static_cast<Display*>(rendering_helper_->GetGLDisplay()), | 572 static_cast<Display*>(rendering_helper_->GetGLDisplay()), |
576 base::Bind(&DoNothingReturnTrue))); | 573 base::Bind(&DoNothingReturnTrue))); |
577 #endif // OS_WIN | 574 #endif // OS_WIN |
578 CHECK(decoder_.get()); | 575 CHECK(decoder_.get()); |
| 576 weak_decoder_factory_.reset( |
| 577 new base::WeakPtrFactory<VideoDecodeAccelerator>(decoder_.get())); |
579 SetState(CS_DECODER_SET); | 578 SetState(CS_DECODER_SET); |
580 if (decoder_deleted()) | 579 if (decoder_deleted()) |
581 return; | 580 return; |
582 | 581 |
583 CHECK(decoder_->Initialize(profile_, client)); | 582 CHECK(decoder_->Initialize(profile_, client)); |
| 583 FinishInitialization(); |
584 } | 584 } |
585 | 585 |
586 void GLRenderingVDAClient::ProvidePictureBuffers( | 586 void GLRenderingVDAClient::ProvidePictureBuffers( |
587 uint32 requested_num_of_buffers, | 587 uint32 requested_num_of_buffers, |
588 const gfx::Size& dimensions, | 588 const gfx::Size& dimensions, |
589 uint32 texture_target) { | 589 uint32 texture_target) { |
590 if (decoder_deleted()) | 590 if (decoder_deleted()) |
591 return; | 591 return; |
592 std::vector<media::PictureBuffer> buffers; | 592 std::vector<media::PictureBuffer> buffers; |
593 | 593 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
653 CHECK(picture_buffer); | 653 CHECK(picture_buffer); |
654 if (!suppress_rendering_) { | 654 if (!suppress_rendering_) { |
655 rendering_helper_->RenderTexture(texture_target_, | 655 rendering_helper_->RenderTexture(texture_target_, |
656 picture_buffer->texture_id()); | 656 picture_buffer->texture_id()); |
657 } | 657 } |
658 | 658 |
659 if (num_decoded_frames() > delay_reuse_after_frame_num_) { | 659 if (num_decoded_frames() > delay_reuse_after_frame_num_) { |
660 base::MessageLoop::current()->PostDelayedTask( | 660 base::MessageLoop::current()->PostDelayedTask( |
661 FROM_HERE, | 661 FROM_HERE, |
662 base::Bind(&VideoDecodeAccelerator::ReusePictureBuffer, | 662 base::Bind(&VideoDecodeAccelerator::ReusePictureBuffer, |
663 decoder_->AsWeakPtr(), | 663 weak_decoder_factory_->GetWeakPtr(), |
664 picture.picture_buffer_id()), | 664 picture.picture_buffer_id()), |
665 kReuseDelay); | 665 kReuseDelay); |
666 } else { | 666 } else { |
667 decoder_->ReusePictureBuffer(picture.picture_buffer_id()); | 667 decoder_->ReusePictureBuffer(picture.picture_buffer_id()); |
668 } | 668 } |
669 } | 669 } |
670 | 670 |
671 void GLRenderingVDAClient::NotifyInitializeDone() { | |
672 SetState(CS_INITIALIZED); | |
673 initialize_done_ticks_ = base::TimeTicks::Now(); | |
674 | |
675 if (reset_after_frame_num_ == START_OF_STREAM_RESET) { | |
676 reset_after_frame_num_ = MID_STREAM_RESET; | |
677 decoder_->Reset(); | |
678 return; | |
679 } | |
680 | |
681 for (int i = 0; i < num_in_flight_decodes_; ++i) | |
682 DecodeNextFragment(); | |
683 DCHECK_EQ(outstanding_decodes_, num_in_flight_decodes_); | |
684 } | |
685 | |
686 void GLRenderingVDAClient::NotifyEndOfBitstreamBuffer( | 671 void GLRenderingVDAClient::NotifyEndOfBitstreamBuffer( |
687 int32 bitstream_buffer_id) { | 672 int32 bitstream_buffer_id) { |
688 // TODO(fischman): this test currently relies on this notification to make | 673 // TODO(fischman): this test currently relies on this notification to make |
689 // forward progress during a Reset(). But the VDA::Reset() API doesn't | 674 // forward progress during a Reset(). But the VDA::Reset() API doesn't |
690 // guarantee this, so stop relying on it (and remove the notifications from | 675 // guarantee this, so stop relying on it (and remove the notifications from |
691 // VaapiVideoDecodeAccelerator::FinishReset()). | 676 // VaapiVideoDecodeAccelerator::FinishReset()). |
692 ++num_done_bitstream_buffers_; | 677 ++num_done_bitstream_buffers_; |
693 --outstanding_decodes_; | 678 --outstanding_decodes_; |
694 if (decode_calls_per_second_ == 0) | 679 if (decode_calls_per_second_ == 0) |
695 DecodeNextFragment(); | 680 DecodeNextFragment(); |
(...skipping 21 matching lines...) Expand all Loading... |
717 return; | 702 return; |
718 } else if (reset_after_frame_num_ == START_OF_STREAM_RESET) { | 703 } else if (reset_after_frame_num_ == START_OF_STREAM_RESET) { |
719 reset_after_frame_num_ = END_OF_STREAM_RESET; | 704 reset_after_frame_num_ = END_OF_STREAM_RESET; |
720 for (int i = 0; i < num_in_flight_decodes_; ++i) | 705 for (int i = 0; i < num_in_flight_decodes_; ++i) |
721 DecodeNextFragment(); | 706 DecodeNextFragment(); |
722 return; | 707 return; |
723 } | 708 } |
724 | 709 |
725 if (remaining_play_throughs_) { | 710 if (remaining_play_throughs_) { |
726 encoded_data_next_pos_to_decode_ = 0; | 711 encoded_data_next_pos_to_decode_ = 0; |
727 NotifyInitializeDone(); | 712 FinishInitialization(); |
728 return; | 713 return; |
729 } | 714 } |
730 | 715 |
731 SetState(CS_RESET); | 716 SetState(CS_RESET); |
732 if (!decoder_deleted()) | 717 if (!decoder_deleted()) |
733 DeleteDecoder(); | 718 DeleteDecoder(); |
734 } | 719 } |
735 | 720 |
736 void GLRenderingVDAClient::NotifyError(VideoDecodeAccelerator::Error error) { | 721 void GLRenderingVDAClient::NotifyError(VideoDecodeAccelerator::Error error) { |
737 SetState(CS_ERROR); | 722 SetState(CS_ERROR); |
(...skipping 24 matching lines...) Expand all Loading... |
762 | 747 |
763 void GLRenderingVDAClient::SetState(ClientState new_state) { | 748 void GLRenderingVDAClient::SetState(ClientState new_state) { |
764 note_->Notify(new_state); | 749 note_->Notify(new_state); |
765 state_ = new_state; | 750 state_ = new_state; |
766 if (!remaining_play_throughs_ && new_state == delete_decoder_state_) { | 751 if (!remaining_play_throughs_ && new_state == delete_decoder_state_) { |
767 CHECK(!decoder_deleted()); | 752 CHECK(!decoder_deleted()); |
768 DeleteDecoder(); | 753 DeleteDecoder(); |
769 } | 754 } |
770 } | 755 } |
771 | 756 |
| 757 void GLRenderingVDAClient::FinishInitialization() { |
| 758 SetState(CS_INITIALIZED); |
| 759 initialize_done_ticks_ = base::TimeTicks::Now(); |
| 760 |
| 761 if (reset_after_frame_num_ == START_OF_STREAM_RESET) { |
| 762 reset_after_frame_num_ = MID_STREAM_RESET; |
| 763 decoder_->Reset(); |
| 764 return; |
| 765 } |
| 766 |
| 767 for (int i = 0; i < num_in_flight_decodes_; ++i) |
| 768 DecodeNextFragment(); |
| 769 DCHECK_EQ(outstanding_decodes_, num_in_flight_decodes_); |
| 770 } |
| 771 |
772 void GLRenderingVDAClient::DeleteDecoder() { | 772 void GLRenderingVDAClient::DeleteDecoder() { |
773 if (decoder_deleted()) | 773 if (decoder_deleted()) |
774 return; | 774 return; |
| 775 weak_decoder_factory_.reset(); |
775 decoder_.release()->Destroy(); | 776 decoder_.release()->Destroy(); |
776 STLClearObject(&encoded_data_); | 777 STLClearObject(&encoded_data_); |
777 for (std::set<int>::iterator it = outstanding_texture_ids_.begin(); | 778 for (std::set<int>::iterator it = outstanding_texture_ids_.begin(); |
778 it != outstanding_texture_ids_.end(); ++it) { | 779 it != outstanding_texture_ids_.end(); ++it) { |
779 rendering_helper_->DeleteTexture(*it); | 780 rendering_helper_->DeleteTexture(*it); |
780 } | 781 } |
781 outstanding_texture_ids_.clear(); | 782 outstanding_texture_ids_.clear(); |
782 // Cascade through the rest of the states to simplify test code below. | 783 // Cascade through the rest of the states to simplify test code below. |
783 for (int i = state_ + 1; i < CS_MAX; ++i) | 784 for (int i = state_ + 1; i < CS_MAX; ++i) |
784 SetState(static_cast<ClientState>(i)); | 785 SetState(static_cast<ClientState>(i)); |
(...skipping 784 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1569 } | 1570 } |
1570 if (it->first == "v" || it->first == "vmodule") | 1571 if (it->first == "v" || it->first == "vmodule") |
1571 continue; | 1572 continue; |
1572 LOG(FATAL) << "Unexpected switch: " << it->first << ":" << it->second; | 1573 LOG(FATAL) << "Unexpected switch: " << it->first << ":" << it->second; |
1573 } | 1574 } |
1574 | 1575 |
1575 base::ShadowingAtExitManager at_exit_manager; | 1576 base::ShadowingAtExitManager at_exit_manager; |
1576 | 1577 |
1577 return RUN_ALL_TESTS(); | 1578 return RUN_ALL_TESTS(); |
1578 } | 1579 } |
OLD | NEW |