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

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

Issue 7467037: Made Destroy() followup more aggressive to test for races. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 9 years, 5 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 | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « content/common/gpu/gpu_messages.h ('k') | content/renderer/pepper_platform_video_decoder_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698