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 3 // found in the LICENSE file. 4 5 #include "base/basictypes.h" 6 #include "base/bind.h" 7 #include "base/memory/scoped_ptr.h" 8 #include "base/message_loop/message_loop.h" 9 #include "media/base/decoder_buffer.h" 10 #include "media/base/demuxer_stream.h" 11 #include "media/filters/fake_demuxer_stream.h" 12 #include "testing/gtest/include/gtest/gtest.h" 13 14 namespace media { 15 16 static const int kNumBuffersInOneConfig = 9; 17 static const int kNumBuffersToReadFirst = 5; 18 static const int kNumConfigs = 3; 19 COMPILE_ASSERT(kNumBuffersToReadFirst < kNumBuffersInOneConfig, 20 do_not_read_too_many_buffers); 21 COMPILE_ASSERT(kNumConfigs > 0, need_multiple_configs_to_trigger_config_change); 22 23 class FakeDemuxerStreamTest : public testing::Test { 24 public: 25 FakeDemuxerStreamTest() 26 : status_(DemuxerStream::kAborted), 27 read_pending_(false) {} 28 virtual ~FakeDemuxerStreamTest() {} 29 30 void BufferReady(DemuxerStream::Status status, 31 const scoped_refptr<DecoderBuffer>& buffer) { 32 DCHECK(read_pending_); 33 read_pending_ = false; 34 status_ = status; 35 buffer_ = buffer; 36 } 37 38 enum ReadResult { 39 OK, 40 ABORTED, 41 CONFIG_CHANGED, 42 EOS, 43 PENDING 44 }; 45 46 void EnterNormalReadState() { 47 stream_.reset( 48 new FakeDemuxerStream(kNumConfigs, kNumBuffersInOneConfig, false)); 49 for (int i = 0; i < kNumBuffersToReadFirst; ++i) 50 ReadAndExpect(OK); 51 } 52 53 void EnterBeforeEOSState() { 54 stream_.reset(new FakeDemuxerStream(1, kNumBuffersInOneConfig, false)); 55 for (int i = 0; i < kNumBuffersInOneConfig; ++i) 56 ReadAndExpect(OK); 57 } 58 59 void ExpectReadResult(ReadResult result) { 60 switch (result) { 61 case OK: 62 EXPECT_FALSE(read_pending_); 63 EXPECT_EQ(DemuxerStream::kOk, status_); 64 ASSERT_TRUE(buffer_.get()); 65 EXPECT_FALSE(buffer_->end_of_stream()); 66 break; 67 68 case ABORTED: 69 EXPECT_FALSE(read_pending_); 70 EXPECT_EQ(DemuxerStream::kAborted, status_); 71 EXPECT_FALSE(buffer_.get()); 72 break; 73 74 case CONFIG_CHANGED: 75 EXPECT_FALSE(read_pending_); 76 EXPECT_EQ(DemuxerStream::kConfigChanged, status_); 77 EXPECT_FALSE(buffer_.get()); 78 break; 79 80 case EOS: 81 EXPECT_FALSE(read_pending_); 82 EXPECT_EQ(DemuxerStream::kOk, status_); 83 ASSERT_TRUE(buffer_.get()); 84 EXPECT_TRUE(buffer_->end_of_stream()); 85 break; 86 87 case PENDING: 88 EXPECT_TRUE(read_pending_); 89 break; 90 } 91 } 92 93 void ReadAndExpect(ReadResult result) { 94 EXPECT_FALSE(read_pending_); 95 read_pending_ = true; 96 stream_->Read(base::Bind(&FakeDemuxerStreamTest::BufferReady, 97 base::Unretained(this))); 98 message_loop_.RunUntilIdle(); 99 ExpectReadResult(result); 100 } 101 102 void ReadUntilPending() { 103 while (1) { 104 read_pending_ = true; 105 stream_->Read(base::Bind(&FakeDemuxerStreamTest::BufferReady, 106 base::Unretained(this))); 107 message_loop_.RunUntilIdle(); 108 if (read_pending_) 109 break; 110 } 111 } 112 113 void SatisfyReadAndExpect(ReadResult result) { 114 EXPECT_TRUE(read_pending_); 115 stream_->SatisfyRead(); 116 message_loop_.RunUntilIdle(); 117 ExpectReadResult(result); 118 } 119 120 void Reset() { 121 bool had_read_pending = read_pending_; 122 stream_->Reset(); 123 message_loop_.RunUntilIdle(); 124 125 EXPECT_FALSE(read_pending_); 126 if (had_read_pending) 127 ExpectReadResult(ABORTED); 128 } 129 130 void TestRead(int num_configs, 131 int num_buffers_in_one_config, 132 bool is_encrypted) { 133 stream_.reset(new FakeDemuxerStream( 134 num_configs, num_buffers_in_one_config, is_encrypted)); 135 136 int num_buffers_received = 0; 137 138 const VideoDecoderConfig& config = stream_->video_decoder_config(); 139 EXPECT_TRUE(config.IsValidConfig()); 140 EXPECT_EQ(is_encrypted, config.is_encrypted()); 141 142 for (int i = 0; i < num_configs; ++i) { 143 for (int j = 0; j < num_buffers_in_one_config; ++j) { 144 ReadAndExpect(OK); 145 num_buffers_received++; 146 EXPECT_EQ(num_buffers_received, stream_->num_buffers_returned()); 147 } 148 149 if (i == num_configs - 1) 150 ReadAndExpect(EOS); 151 else 152 ReadAndExpect(CONFIG_CHANGED); 153 } 154 155 // Will always get EOS after we hit EOS. 156 ReadAndExpect(EOS); 157 158 EXPECT_EQ(num_configs * num_buffers_in_one_config, num_buffers_received); 159 } 160 161 base::MessageLoop message_loop_; 162 scoped_ptr<FakeDemuxerStream> stream_; 163 164 DemuxerStream::Status status_; 165 scoped_refptr<DecoderBuffer> buffer_; 166 bool read_pending_; 167 int num_buffers_received_; 168 169 private: 170 DISALLOW_COPY_AND_ASSIGN(FakeDemuxerStreamTest); 171 }; 172 173 TEST_F(FakeDemuxerStreamTest, Read_OneConfig) { 174 TestRead(1, 5, false); 175 } 176 177 TEST_F(FakeDemuxerStreamTest, Read_MultipleConfigs) { 178 TestRead(3, 5, false); 179 } 180 181 TEST_F(FakeDemuxerStreamTest, Read_OneBufferPerConfig) { 182 TestRead(3, 1, false); 183 } 184 185 TEST_F(FakeDemuxerStreamTest, Read_Encrypted) { 186 TestRead(6, 3, true); 187 } 188 189 TEST_F(FakeDemuxerStreamTest, HoldRead_Normal) { 190 EnterNormalReadState(); 191 stream_->HoldNextRead(); 192 ReadAndExpect(PENDING); 193 SatisfyReadAndExpect(OK); 194 } 195 196 TEST_F(FakeDemuxerStreamTest, HoldRead_BeforeConfigChanged) { 197 EnterNormalReadState(); 198 stream_->HoldNextConfigChangeRead(); 199 ReadUntilPending(); 200 SatisfyReadAndExpect(CONFIG_CHANGED); 201 } 202 203 TEST_F(FakeDemuxerStreamTest, HoldRead_BeforeEOS) { 204 EnterBeforeEOSState(); 205 stream_->HoldNextRead(); 206 ReadAndExpect(PENDING); 207 SatisfyReadAndExpect(EOS); 208 } 209 210 TEST_F(FakeDemuxerStreamTest, Reset_Normal) { 211 EnterNormalReadState(); 212 Reset(); 213 ReadAndExpect(OK); 214 } 215 216 TEST_F(FakeDemuxerStreamTest, Reset_AfterHoldRead) { 217 EnterNormalReadState(); 218 stream_->HoldNextRead(); 219 Reset(); 220 ReadAndExpect(OK); 221 } 222 223 TEST_F(FakeDemuxerStreamTest, Reset_DuringPendingRead) { 224 EnterNormalReadState(); 225 stream_->HoldNextRead(); 226 ReadAndExpect(PENDING); 227 Reset(); 228 ReadAndExpect(OK); 229 } 230 231 TEST_F(FakeDemuxerStreamTest, Reset_BeforeConfigChanged) { 232 EnterNormalReadState(); 233 stream_->HoldNextConfigChangeRead(); 234 ReadUntilPending(); 235 Reset(); 236 ReadAndExpect(CONFIG_CHANGED); 237 } 238 239 TEST_F(FakeDemuxerStreamTest, Reset_BeforeEOS) { 240 EnterBeforeEOSState(); 241 stream_->HoldNextRead(); 242 ReadAndExpect(PENDING); 243 Reset(); 244 ReadAndExpect(EOS); 245 } 246 247 } // namespace media 248