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 const int kNumBuffersInOneConfig = 9; 17 const int kNumBuffersToReadFirst = 5; 18 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 num_buffers_received_(0) {} 29 virtual ~FakeDemuxerStreamTest() {} 30 31 void BufferReady(DemuxerStream::Status status, 32 const scoped_refptr<DecoderBuffer>& buffer) { 33 DCHECK(read_pending_); 34 read_pending_ = false; 35 status_ = status; 36 buffer_ = buffer; 37 if (status == DemuxerStream::kOk && !buffer->end_of_stream()) 38 num_buffers_received_++; 39 } 40 41 enum ReadResult { 42 OK, 43 ABORTED, 44 CONFIG_CHANGED, 45 EOS, 46 PENDING 47 }; 48 49 void EnterNormalReadState() { 50 stream_.reset( 51 new FakeDemuxerStream(kNumConfigs, kNumBuffersInOneConfig, false)); 52 for (int i = 0; i < kNumBuffersToReadFirst; ++i) 53 ReadAndExpect(OK); 54 DCHECK_EQ(kNumBuffersToReadFirst, num_buffers_received_); 55 } 56 57 void EnterBeforeEOSState() { 58 stream_.reset(new FakeDemuxerStream(1, kNumBuffersInOneConfig, false)); 59 for (int i = 0; i < kNumBuffersInOneConfig; ++i) 60 ReadAndExpect(OK); 61 DCHECK_EQ(kNumBuffersInOneConfig, num_buffers_received_); 62 } 63 64 void ExpectReadResult(ReadResult result) { 65 switch (result) { 66 case OK: 67 EXPECT_FALSE(read_pending_); 68 EXPECT_EQ(DemuxerStream::kOk, status_); 69 ASSERT_TRUE(buffer_.get()); 70 EXPECT_FALSE(buffer_->end_of_stream()); 71 break; 72 73 case ABORTED: 74 EXPECT_FALSE(read_pending_); 75 EXPECT_EQ(DemuxerStream::kAborted, status_); 76 EXPECT_FALSE(buffer_.get()); 77 break; 78 79 case CONFIG_CHANGED: 80 EXPECT_TRUE(stream_->SupportsConfigChanges()); 81 EXPECT_FALSE(read_pending_); 82 EXPECT_EQ(DemuxerStream::kConfigChanged, status_); 83 EXPECT_FALSE(buffer_.get()); 84 break; 85 86 case EOS: 87 EXPECT_FALSE(read_pending_); 88 EXPECT_EQ(DemuxerStream::kOk, status_); 89 ASSERT_TRUE(buffer_.get()); 90 EXPECT_TRUE(buffer_->end_of_stream()); 91 break; 92 93 case PENDING: 94 EXPECT_TRUE(read_pending_); 95 break; 96 } 97 } 98 99 void ReadAndExpect(ReadResult result) { 100 EXPECT_FALSE(read_pending_); 101 read_pending_ = true; 102 stream_->Read(base::Bind(&FakeDemuxerStreamTest::BufferReady, 103 base::Unretained(this))); 104 message_loop_.RunUntilIdle(); 105 ExpectReadResult(result); 106 } 107 108 void ReadUntilPending() { 109 while (1) { 110 read_pending_ = true; 111 stream_->Read(base::Bind(&FakeDemuxerStreamTest::BufferReady, 112 base::Unretained(this))); 113 message_loop_.RunUntilIdle(); 114 if (read_pending_) 115 break; 116 } 117 } 118 119 void SatisfyReadAndExpect(ReadResult result) { 120 EXPECT_TRUE(read_pending_); 121 stream_->SatisfyRead(); 122 message_loop_.RunUntilIdle(); 123 ExpectReadResult(result); 124 } 125 126 void Reset() { 127 bool had_read_pending = read_pending_; 128 stream_->Reset(); 129 message_loop_.RunUntilIdle(); 130 131 EXPECT_FALSE(read_pending_); 132 if (had_read_pending) 133 ExpectReadResult(ABORTED); 134 } 135 136 void ReadAllBuffers(int num_configs, int num_buffers_in_one_config) { 137 DCHECK_EQ(0, num_buffers_received_); 138 for (int i = 0; i < num_configs; ++i) { 139 for (int j = 0; j < num_buffers_in_one_config; ++j) { 140 ReadAndExpect(OK); 141 EXPECT_EQ(num_buffers_received_, stream_->num_buffers_returned()); 142 } 143 144 if (i == num_configs - 1) 145 ReadAndExpect(EOS); 146 else 147 ReadAndExpect(CONFIG_CHANGED); 148 } 149 150 // Will always get EOS after we hit EOS. 151 ReadAndExpect(EOS); 152 153 EXPECT_EQ(num_configs * num_buffers_in_one_config, num_buffers_received_); 154 } 155 156 void TestRead(int num_configs, 157 int num_buffers_in_one_config, 158 bool is_encrypted) { 159 stream_.reset(new FakeDemuxerStream( 160 num_configs, num_buffers_in_one_config, is_encrypted)); 161 162 const VideoDecoderConfig& config = stream_->video_decoder_config(); 163 EXPECT_TRUE(config.IsValidConfig()); 164 EXPECT_EQ(is_encrypted, config.is_encrypted()); 165 166 ReadAllBuffers(num_configs, num_buffers_in_one_config); 167 } 168 169 base::MessageLoop message_loop_; 170 scoped_ptr<FakeDemuxerStream> stream_; 171 172 DemuxerStream::Status status_; 173 scoped_refptr<DecoderBuffer> buffer_; 174 bool read_pending_; 175 int num_buffers_received_; 176 177 private: 178 DISALLOW_COPY_AND_ASSIGN(FakeDemuxerStreamTest); 179 }; 180 181 TEST_F(FakeDemuxerStreamTest, Read_OneConfig) { 182 TestRead(1, 5, false); 183 } 184 185 TEST_F(FakeDemuxerStreamTest, Read_MultipleConfigs) { 186 TestRead(3, 5, false); 187 } 188 189 TEST_F(FakeDemuxerStreamTest, Read_OneBufferPerConfig) { 190 TestRead(3, 1, false); 191 } 192 193 TEST_F(FakeDemuxerStreamTest, Read_Encrypted) { 194 TestRead(6, 3, true); 195 } 196 197 TEST_F(FakeDemuxerStreamTest, HoldRead_Normal) { 198 EnterNormalReadState(); 199 stream_->HoldNextRead(); 200 ReadAndExpect(PENDING); 201 SatisfyReadAndExpect(OK); 202 } 203 204 TEST_F(FakeDemuxerStreamTest, HoldRead_BeforeConfigChanged) { 205 EnterNormalReadState(); 206 stream_->HoldNextConfigChangeRead(); 207 ReadUntilPending(); 208 SatisfyReadAndExpect(CONFIG_CHANGED); 209 } 210 211 TEST_F(FakeDemuxerStreamTest, HoldRead_BeforeEOS) { 212 EnterBeforeEOSState(); 213 stream_->HoldNextRead(); 214 ReadAndExpect(PENDING); 215 SatisfyReadAndExpect(EOS); 216 } 217 218 TEST_F(FakeDemuxerStreamTest, Reset_Normal) { 219 EnterNormalReadState(); 220 Reset(); 221 ReadAndExpect(OK); 222 } 223 224 TEST_F(FakeDemuxerStreamTest, Reset_AfterHoldRead) { 225 EnterNormalReadState(); 226 stream_->HoldNextRead(); 227 Reset(); 228 ReadAndExpect(OK); 229 } 230 231 TEST_F(FakeDemuxerStreamTest, Reset_DuringPendingRead) { 232 EnterNormalReadState(); 233 stream_->HoldNextRead(); 234 ReadAndExpect(PENDING); 235 Reset(); 236 ReadAndExpect(OK); 237 } 238 239 TEST_F(FakeDemuxerStreamTest, Reset_BeforeConfigChanged) { 240 EnterNormalReadState(); 241 stream_->HoldNextConfigChangeRead(); 242 ReadUntilPending(); 243 Reset(); 244 ReadAndExpect(CONFIG_CHANGED); 245 } 246 247 TEST_F(FakeDemuxerStreamTest, Reset_BeforeEOS) { 248 EnterBeforeEOSState(); 249 stream_->HoldNextRead(); 250 ReadAndExpect(PENDING); 251 Reset(); 252 ReadAndExpect(EOS); 253 } 254 255 TEST_F(FakeDemuxerStreamTest, NoConfigChanges) { 256 stream_.reset( 257 new FakeDemuxerStream(1, kNumBuffersInOneConfig, false)); 258 EXPECT_FALSE(stream_->SupportsConfigChanges()); 259 for (int i = 0; i < kNumBuffersInOneConfig; ++i) 260 ReadAndExpect(OK); 261 ReadAndExpect(EOS); 262 } 263 264 TEST_F(FakeDemuxerStreamTest, SeekToStart_Normal) { 265 EnterNormalReadState(); 266 stream_->SeekToStart(); 267 num_buffers_received_ = 0; 268 ReadAllBuffers(kNumConfigs, kNumBuffersInOneConfig); 269 } 270 271 TEST_F(FakeDemuxerStreamTest, SeekToStart_BeforeEOS) { 272 EnterBeforeEOSState(); 273 stream_->SeekToStart(); 274 num_buffers_received_ = 0; 275 ReadAllBuffers(1, kNumBuffersInOneConfig); 276 } 277 278 TEST_F(FakeDemuxerStreamTest, SeekToStart_AfterEOS) { 279 TestRead(3, 5, false); 280 stream_->SeekToStart(); 281 num_buffers_received_ = 0; 282 ReadAllBuffers(3, 5); 283 } 284 285 } // namespace media 286