1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chromecast/media/cma/base/mock_frame_consumer.h" 6 7 #include "base/bind.h" 8 #include "base/location.h" 9 #include "base/message_loop/message_loop_proxy.h" 10 #include "base/time/time.h" 11 #include "chromecast/media/cma/base/coded_frame_provider.h" 12 #include "chromecast/media/cma/base/decoder_buffer_base.h" 13 #include "chromecast/media/cma/base/frame_generator_for_test.h" 14 #include "media/base/video_decoder_config.h" 15 #include "testing/gtest/include/gtest/gtest.h" 16 17 namespace chromecast { 18 namespace media { 19 20 MockFrameConsumer::MockFrameConsumer( 21 CodedFrameProvider* coded_frame_provider) 22 : coded_frame_provider_(coded_frame_provider), 23 pattern_idx_(0), 24 last_read_aborted_by_flush_(false) { 25 } 26 27 MockFrameConsumer::~MockFrameConsumer() { 28 } 29 30 void MockFrameConsumer::Configure( 31 const std::vector<bool>& delayed_task_pattern, 32 bool last_read_aborted_by_flush, 33 scoped_ptr<FrameGeneratorForTest> frame_generator) { 34 delayed_task_pattern_ = delayed_task_pattern; 35 last_read_aborted_by_flush_ = last_read_aborted_by_flush; 36 frame_generator_.reset(frame_generator.release()); 37 } 38 39 void MockFrameConsumer::Start(const base::Closure& done_cb) { 40 done_cb_ = done_cb; 41 42 pattern_idx_ = 0; 43 44 base::MessageLoopProxy::current()->PostTask( 45 FROM_HERE, 46 base::Bind(&MockFrameConsumer::ReadFrame, base::Unretained(this))); 47 } 48 49 void MockFrameConsumer::ReadFrame() { 50 // Once all the frames have been read, flush the frame provider. 51 if (frame_generator_->RemainingFrameCount() == 0 && 52 !last_read_aborted_by_flush_) { 53 coded_frame_provider_->Flush( 54 base::Bind(&MockFrameConsumer::OnFlushCompleted, 55 base::Unretained(this))); 56 return; 57 } 58 59 coded_frame_provider_->Read( 60 base::Bind(&MockFrameConsumer::OnNewFrame, 61 base::Unretained(this))); 62 63 // The last read is right away aborted by a Flush. 64 if (frame_generator_->RemainingFrameCount() == 0 && 65 last_read_aborted_by_flush_) { 66 coded_frame_provider_->Flush( 67 base::Bind(&MockFrameConsumer::OnFlushCompleted, 68 base::Unretained(this))); 69 return; 70 } 71 } 72 73 void MockFrameConsumer::OnNewFrame( 74 const scoped_refptr<DecoderBufferBase>& buffer, 75 const ::media::AudioDecoderConfig& audio_config, 76 const ::media::VideoDecoderConfig& video_config) { 77 bool ref_has_config = frame_generator_->HasDecoderConfig(); 78 scoped_refptr<DecoderBufferBase> ref_buffer = frame_generator_->Generate(); 79 80 ASSERT_TRUE(buffer.get()); 81 ASSERT_TRUE(ref_buffer.get()); 82 83 EXPECT_EQ(video_config.IsValidConfig(), ref_has_config); 84 85 EXPECT_EQ(buffer->end_of_stream(), ref_buffer->end_of_stream()); 86 if (!ref_buffer->end_of_stream()) { 87 EXPECT_EQ(buffer->timestamp(), ref_buffer->timestamp()); 88 ASSERT_EQ(buffer->data_size(), ref_buffer->data_size()); 89 for (size_t k = 0; k < ref_buffer->data_size(); k++) 90 EXPECT_EQ(buffer->data()[k], ref_buffer->data()[k]); 91 } 92 93 bool delayed = delayed_task_pattern_[pattern_idx_]; 94 pattern_idx_ = (pattern_idx_ + 1) % delayed_task_pattern_.size(); 95 96 if (delayed) { 97 base::MessageLoopProxy::current()->PostDelayedTask( 98 FROM_HERE, 99 base::Bind(&MockFrameConsumer::ReadFrame, 100 base::Unretained(this)), 101 base::TimeDelta::FromMilliseconds(1)); 102 } else { 103 base::MessageLoopProxy::current()->PostTask( 104 FROM_HERE, 105 base::Bind(&MockFrameConsumer::ReadFrame, 106 base::Unretained(this))); 107 } 108 } 109 110 void MockFrameConsumer::OnFlushCompleted() { 111 EXPECT_EQ(frame_generator_->RemainingFrameCount(), 0); 112 done_cb_.Run(); 113 } 114 115 } // namespace media 116 } // namespace chromecast 117