Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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, and GLES2. | 7 // - RenderingHelper is charged with interacting with X11, EGL, and GLES2. |
| 8 // - ClientState is an enum for the state of the decode client used by the test. | 8 // - ClientState is an enum for the state of the decode client used by the test. |
| 9 // - ClientStateNotification is a barrier abstraction that allows the test code | 9 // - ClientStateNotification is a barrier abstraction that allows the test code |
| 10 // to be written sequentially and wait for the decode client to see certain | 10 // to be written sequentially and wait for the decode client to see certain |
| (...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 438 | 438 |
| 439 // Client that can accept callbacks from a VideoDecodeAccelerator and is used by | 439 // Client that can accept callbacks from a VideoDecodeAccelerator and is used by |
| 440 // the TESTs below. | 440 // the TESTs below. |
| 441 class EglRenderingVDAClient : public VideoDecodeAccelerator::Client { | 441 class EglRenderingVDAClient : public VideoDecodeAccelerator::Client { |
| 442 public: | 442 public: |
| 443 // Doesn't take ownership of |note| or |encoded_data|, which must outlive | 443 // Doesn't take ownership of |note| or |encoded_data|, which must outlive |
| 444 // |*this|. | 444 // |*this|. |
| 445 EglRenderingVDAClient(RenderingHelper* rendering_helper, | 445 EglRenderingVDAClient(RenderingHelper* rendering_helper, |
| 446 int rendering_window_id, | 446 int rendering_window_id, |
| 447 ClientStateNotification* note, | 447 ClientStateNotification* note, |
| 448 std::string* encoded_data, | 448 const std::string& encoded_data, |
| 449 int num_NALUs_per_decode, | 449 int num_NALUs_per_decode, |
| 450 int delete_decoder_state); | 450 int delete_decoder_state); |
| 451 virtual ~EglRenderingVDAClient(); | 451 virtual ~EglRenderingVDAClient(); |
| 452 void CreateDecoder(); | 452 void CreateDecoder(); |
| 453 | 453 |
| 454 // VideoDecodeAccelerator::Client implementation. | 454 // VideoDecodeAccelerator::Client implementation. |
| 455 // The heart of the Client. | 455 // The heart of the Client. |
| 456 virtual void ProvidePictureBuffers( | 456 virtual void ProvidePictureBuffers( |
| 457 uint32 requested_num_of_buffers, | 457 uint32 requested_num_of_buffers, |
| 458 const gfx::Size& dimensions); | 458 const gfx::Size& dimensions); |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 485 | 485 |
| 486 // Compute & return in |*end_pos| the end position for the next batch of NALUs | 486 // Compute & return in |*end_pos| the end position for the next batch of NALUs |
| 487 // to ship to the decoder (based on |start_pos| & |num_NALUs_per_decode_|). | 487 // to ship to the decoder (based on |start_pos| & |num_NALUs_per_decode_|). |
| 488 void GetRangeForNextNALUs(size_t start_pos, size_t* end_pos); | 488 void GetRangeForNextNALUs(size_t start_pos, size_t* end_pos); |
| 489 | 489 |
| 490 // Request decode of the next batch of NALUs in the encoded data. | 490 // Request decode of the next batch of NALUs in the encoded data. |
| 491 void DecodeNextNALUs(); | 491 void DecodeNextNALUs(); |
| 492 | 492 |
| 493 RenderingHelper* rendering_helper_; | 493 RenderingHelper* rendering_helper_; |
| 494 int rendering_window_id_; | 494 int rendering_window_id_; |
| 495 const std::string* encoded_data_; | 495 std::string encoded_data_; |
| 496 const int num_NALUs_per_decode_; | 496 const int num_NALUs_per_decode_; |
| 497 size_t encoded_data_next_pos_to_decode_; | 497 size_t encoded_data_next_pos_to_decode_; |
| 498 int next_bitstream_buffer_id_; | 498 int next_bitstream_buffer_id_; |
| 499 ClientStateNotification* note_; | 499 ClientStateNotification* note_; |
| 500 scoped_refptr<OmxVideoDecodeAccelerator> decoder_; | 500 scoped_refptr<OmxVideoDecodeAccelerator> decoder_; |
| 501 std::set<int> outstanding_texture_ids_; | |
| 501 int delete_decoder_state_; | 502 int delete_decoder_state_; |
| 502 ClientState state_; | 503 ClientState state_; |
| 503 int num_decoded_frames_; | 504 int num_decoded_frames_; |
| 504 int num_done_bitstream_buffers_; | 505 int num_done_bitstream_buffers_; |
| 505 PictureBufferById picture_buffers_by_id_; | 506 PictureBufferById picture_buffers_by_id_; |
| 506 base::TimeTicks initialize_done_ticks_; | 507 base::TimeTicks initialize_done_ticks_; |
| 507 base::TimeTicks last_frame_delivered_ticks_; | 508 base::TimeTicks last_frame_delivered_ticks_; |
| 508 }; | 509 }; |
| 509 | 510 |
| 510 EglRenderingVDAClient::EglRenderingVDAClient(RenderingHelper* rendering_helper, | 511 EglRenderingVDAClient::EglRenderingVDAClient(RenderingHelper* rendering_helper, |
| 511 int rendering_window_id, | 512 int rendering_window_id, |
| 512 ClientStateNotification* note, | 513 ClientStateNotification* note, |
| 513 std::string* encoded_data, | 514 const std::string& encoded_data, |
| 514 int num_NALUs_per_decode, | 515 int num_NALUs_per_decode, |
| 515 int delete_decoder_state) | 516 int delete_decoder_state) |
| 516 : rendering_helper_(rendering_helper), | 517 : rendering_helper_(rendering_helper), |
| 517 rendering_window_id_(rendering_window_id), | 518 rendering_window_id_(rendering_window_id), |
| 518 encoded_data_(encoded_data), num_NALUs_per_decode_(num_NALUs_per_decode), | 519 encoded_data_(encoded_data), num_NALUs_per_decode_(num_NALUs_per_decode), |
| 519 encoded_data_next_pos_to_decode_(0), next_bitstream_buffer_id_(0), | 520 encoded_data_next_pos_to_decode_(0), next_bitstream_buffer_id_(0), |
| 520 note_(note), delete_decoder_state_(delete_decoder_state), | 521 note_(note), delete_decoder_state_(delete_decoder_state), |
| 521 state_(CS_CREATED), | 522 state_(CS_CREATED), |
| 522 num_decoded_frames_(0), num_done_bitstream_buffers_(0) { | 523 num_decoded_frames_(0), num_done_bitstream_buffers_(0) { |
| 523 CHECK_GT(num_NALUs_per_decode, 0); | 524 CHECK_GT(num_NALUs_per_decode, 0); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 555 if (decoder_deleted()) | 556 if (decoder_deleted()) |
| 556 return; | 557 return; |
| 557 std::vector<media::PictureBuffer> buffers; | 558 std::vector<media::PictureBuffer> buffers; |
| 558 | 559 |
| 559 for (uint32 i = 0; i < requested_num_of_buffers; ++i) { | 560 for (uint32 i = 0; i < requested_num_of_buffers; ++i) { |
| 560 uint32 id = picture_buffers_by_id_.size(); | 561 uint32 id = picture_buffers_by_id_.size(); |
| 561 GLuint texture_id; | 562 GLuint texture_id; |
| 562 base::WaitableEvent done(false, false); | 563 base::WaitableEvent done(false, false); |
| 563 rendering_helper_->CreateTexture(rendering_window_id_, &texture_id, &done); | 564 rendering_helper_->CreateTexture(rendering_window_id_, &texture_id, &done); |
| 564 done.Wait(); | 565 done.Wait(); |
| 566 bool inserted = outstanding_texture_ids_.insert(texture_id).second; | |
| 567 DCHECK(inserted); | |
|
vrk (LEFT CHROMIUM)
2011/07/26 17:33:20
nit: change DCHECK to CHECK here and elsewhere.
Ami GONE FROM CHROMIUM
2011/07/26 18:05:09
Done.
| |
| 565 media::PictureBuffer* buffer = | 568 media::PictureBuffer* buffer = |
| 566 new media::PictureBuffer(id, dimensions, texture_id); | 569 new media::PictureBuffer(id, dimensions, texture_id); |
| 567 CHECK(picture_buffers_by_id_.insert(std::make_pair(id, buffer)).second); | 570 CHECK(picture_buffers_by_id_.insert(std::make_pair(id, buffer)).second); |
| 568 buffers.push_back(*buffer); | 571 buffers.push_back(*buffer); |
| 569 } | 572 } |
| 570 decoder_->AssignPictureBuffers(buffers); | 573 decoder_->AssignPictureBuffers(buffers); |
| 571 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR); | 574 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR); |
| 572 CHECK_EQ(static_cast<int>(eglGetError()), EGL_SUCCESS); | 575 CHECK_EQ(static_cast<int>(eglGetError()), EGL_SUCCESS); |
| 573 } | 576 } |
| 574 | 577 |
| 575 void EglRenderingVDAClient::DismissPictureBuffer(int32 picture_buffer_id) { | 578 void EglRenderingVDAClient::DismissPictureBuffer(int32 picture_buffer_id) { |
| 576 PictureBufferById::iterator it = | 579 PictureBufferById::iterator it = |
| 577 picture_buffers_by_id_.find(picture_buffer_id); | 580 picture_buffers_by_id_.find(picture_buffer_id); |
| 578 DCHECK(it != picture_buffers_by_id_.end()); | 581 DCHECK(it != picture_buffers_by_id_.end()); |
| 582 int removed = outstanding_texture_ids_.erase(it->second->texture_id()); | |
| 583 DCHECK_EQ(removed, 1); | |
| 579 rendering_helper_->DeleteTexture(it->second->texture_id()); | 584 rendering_helper_->DeleteTexture(it->second->texture_id()); |
| 580 delete it->second; | 585 delete it->second; |
| 581 picture_buffers_by_id_.erase(it); | 586 picture_buffers_by_id_.erase(it); |
| 582 } | 587 } |
| 583 | 588 |
| 584 void EglRenderingVDAClient::PictureReady(const media::Picture& picture) { | 589 void EglRenderingVDAClient::PictureReady(const media::Picture& picture) { |
| 585 // We shouldn't be getting pictures delivered after Reset has completed. | 590 // We shouldn't be getting pictures delivered after Reset has completed. |
| 586 DCHECK_LT(state_, CS_RESET); | 591 DCHECK_LT(state_, CS_RESET); |
| 587 | 592 |
| 588 if (decoder_deleted()) | 593 if (decoder_deleted()) |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 655 CHECK(!decoder_deleted()); | 660 CHECK(!decoder_deleted()); |
| 656 DeleteDecoder(); | 661 DeleteDecoder(); |
| 657 } | 662 } |
| 658 } | 663 } |
| 659 | 664 |
| 660 void EglRenderingVDAClient::DeleteDecoder() { | 665 void EglRenderingVDAClient::DeleteDecoder() { |
| 661 if (decoder_deleted()) | 666 if (decoder_deleted()) |
| 662 return; | 667 return; |
| 663 decoder_->Destroy(); | 668 decoder_->Destroy(); |
| 664 decoder_ = NULL; | 669 decoder_ = NULL; |
| 670 STLClearObject(&encoded_data_); | |
| 671 for (std::set<int>::iterator it = outstanding_texture_ids_.begin(); | |
| 672 it != outstanding_texture_ids_.end(); ++it) { | |
| 673 rendering_helper_->DeleteTexture(*it); | |
| 674 } | |
| 675 outstanding_texture_ids_.clear(); | |
| 665 // Cascade through the rest of the states to simplify test code below. | 676 // Cascade through the rest of the states to simplify test code below. |
| 666 for (int i = state_ + 1; i < CS_MAX; ++i) | 677 for (int i = state_ + 1; i < CS_MAX; ++i) |
| 667 SetState(static_cast<ClientState>(i)); | 678 SetState(static_cast<ClientState>(i)); |
| 668 } | 679 } |
| 669 | 680 |
| 670 void EglRenderingVDAClient::GetRangeForNextNALUs( | 681 void EglRenderingVDAClient::GetRangeForNextNALUs( |
| 671 size_t start_pos, size_t* end_pos) { | 682 size_t start_pos, size_t* end_pos) { |
| 672 *end_pos = start_pos; | 683 *end_pos = start_pos; |
| 673 CHECK(LookingAtNAL(*encoded_data_, start_pos)); | 684 CHECK(LookingAtNAL(encoded_data_, start_pos)); |
| 674 for (int i = 0; i < num_NALUs_per_decode_; ++i) { | 685 for (int i = 0; i < num_NALUs_per_decode_; ++i) { |
| 675 *end_pos += 4; | 686 *end_pos += 4; |
| 676 while (*end_pos + 3 < encoded_data_->size() && | 687 while (*end_pos + 3 < encoded_data_.size() && |
| 677 !LookingAtNAL(*encoded_data_, *end_pos)) { | 688 !LookingAtNAL(encoded_data_, *end_pos)) { |
| 678 ++*end_pos; | 689 ++*end_pos; |
| 679 } | 690 } |
| 680 if (*end_pos + 3 >= encoded_data_->size()) { | 691 if (*end_pos + 3 >= encoded_data_.size()) { |
| 681 *end_pos = encoded_data_->size(); | 692 *end_pos = encoded_data_.size(); |
| 682 return; | 693 return; |
| 683 } | 694 } |
| 684 } | 695 } |
| 685 } | 696 } |
| 686 | 697 |
| 687 void EglRenderingVDAClient::DecodeNextNALUs() { | 698 void EglRenderingVDAClient::DecodeNextNALUs() { |
| 688 if (decoder_deleted()) | 699 if (decoder_deleted()) |
| 689 return; | 700 return; |
| 690 if (encoded_data_next_pos_to_decode_ == encoded_data_->size()) { | 701 if (encoded_data_next_pos_to_decode_ == encoded_data_.size()) { |
| 691 decoder_->Flush(); | 702 decoder_->Flush(); |
| 692 return; | 703 return; |
| 693 } | 704 } |
| 694 size_t start_pos = encoded_data_next_pos_to_decode_; | 705 size_t start_pos = encoded_data_next_pos_to_decode_; |
| 695 size_t end_pos; | 706 size_t end_pos; |
| 696 GetRangeForNextNALUs(start_pos, &end_pos); | 707 GetRangeForNextNALUs(start_pos, &end_pos); |
| 697 | 708 |
| 698 // Populate the shared memory buffer w/ the NALU, duplicate its handle, and | 709 // Populate the shared memory buffer w/ the NALU, duplicate its handle, and |
| 699 // hand it off to the decoder. | 710 // hand it off to the decoder. |
| 700 base::SharedMemory shm; | 711 base::SharedMemory shm; |
| 701 CHECK(shm.CreateAndMapAnonymous(end_pos - start_pos)) | 712 CHECK(shm.CreateAndMapAnonymous(end_pos - start_pos)) |
| 702 << start_pos << ", " << end_pos; | 713 << start_pos << ", " << end_pos; |
| 703 memcpy(shm.memory(), encoded_data_->data() + start_pos, end_pos - start_pos); | 714 memcpy(shm.memory(), encoded_data_.data() + start_pos, end_pos - start_pos); |
| 704 base::SharedMemoryHandle dup_handle; | 715 base::SharedMemoryHandle dup_handle; |
| 705 CHECK(shm.ShareToProcess(base::Process::Current().handle(), &dup_handle)); | 716 CHECK(shm.ShareToProcess(base::Process::Current().handle(), &dup_handle)); |
| 706 media::BitstreamBuffer bitstream_buffer( | 717 media::BitstreamBuffer bitstream_buffer( |
| 707 next_bitstream_buffer_id_++, dup_handle, end_pos - start_pos); | 718 next_bitstream_buffer_id_++, dup_handle, end_pos - start_pos); |
| 708 decoder_->Decode(bitstream_buffer); | 719 decoder_->Decode(bitstream_buffer); |
| 709 encoded_data_next_pos_to_decode_ = end_pos; | 720 encoded_data_next_pos_to_decode_ = end_pos; |
| 710 | 721 |
| 711 if (-delete_decoder_state_ == next_bitstream_buffer_id_) | 722 if (-delete_decoder_state_ == next_bitstream_buffer_id_) |
| 712 DeleteDecoder(); | 723 DeleteDecoder(); |
| 713 } | 724 } |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 790 suppress_swap_to_display, num_concurrent_decoders, | 801 suppress_swap_to_display, num_concurrent_decoders, |
| 791 frame_width, frame_height, &done)); | 802 frame_width, frame_height, &done)); |
| 792 done.Wait(); | 803 done.Wait(); |
| 793 | 804 |
| 794 // First kick off all the decoders. | 805 // First kick off all the decoders. |
| 795 for (size_t index = 0; index < num_concurrent_decoders; ++index) { | 806 for (size_t index = 0; index < num_concurrent_decoders; ++index) { |
| 796 ClientStateNotification* note = new ClientStateNotification(); | 807 ClientStateNotification* note = new ClientStateNotification(); |
| 797 notes[index] = note; | 808 notes[index] = note; |
| 798 EglRenderingVDAClient* client = new EglRenderingVDAClient( | 809 EglRenderingVDAClient* client = new EglRenderingVDAClient( |
| 799 &rendering_helper, index, | 810 &rendering_helper, index, |
| 800 note, &data_str, num_NALUs_per_decode, | 811 note, data_str, num_NALUs_per_decode, |
| 801 delete_decoder_state); | 812 delete_decoder_state); |
| 802 clients[index] = client; | 813 clients[index] = client; |
| 803 | 814 |
| 804 rendering_thread.message_loop()->PostTask( | 815 rendering_thread.message_loop()->PostTask( |
| 805 FROM_HERE, | 816 FROM_HERE, |
| 806 base::Bind(&EglRenderingVDAClient::CreateDecoder, | 817 base::Bind(&EglRenderingVDAClient::CreateDecoder, |
| 807 base::Unretained(client))); | 818 base::Unretained(client))); |
| 808 | 819 |
| 809 ASSERT_EQ(note->Wait(), CS_DECODER_SET); | 820 ASSERT_EQ(note->Wait(), CS_DECODER_SET); |
| 810 } | 821 } |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 919 it != switches.end(); ++it) { | 930 it != switches.end(); ++it) { |
| 920 if (it->first == "test_video_data") { | 931 if (it->first == "test_video_data") { |
| 921 test_video_data = it->second.c_str(); | 932 test_video_data = it->second.c_str(); |
| 922 continue; | 933 continue; |
| 923 } | 934 } |
| 924 LOG(FATAL) << "Unexpected switch: " << it->first << ":" << it->second; | 935 LOG(FATAL) << "Unexpected switch: " << it->first << ":" << it->second; |
| 925 } | 936 } |
| 926 | 937 |
| 927 return RUN_ALL_TESTS(); | 938 return RUN_ALL_TESTS(); |
| 928 } | 939 } |
| OLD | NEW |