OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2013 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/message_loop.h" |
| 8 #include "media/base/decoder_buffer.h" |
| 9 #include "media/base/mock_filters.h" |
| 10 #include "media/base/test_helpers.h" |
| 11 #include "media/base/video_frame.h" |
| 12 #include "media/filters/fake_demuxer_stream.h" |
| 13 #include "media/filters/fake_video_decoder.h" |
| 14 #include "testing/gtest/include/gtest/gtest.h" |
| 15 |
| 16 namespace media { |
| 17 |
| 18 static const int kDecodingDelay = 9; |
| 19 static const int kNumConfigs = 3; |
| 20 static const int kNumBuffersInOneConfig = 9; |
| 21 static const int kNumInputBuffers = kNumConfigs * kNumBuffersInOneConfig; |
| 22 |
| 23 class FakeVideoDecoderTest : public testing::Test { |
| 24 public: |
| 25 FakeVideoDecoderTest() |
| 26 : decoder_(new FakeVideoDecoder(kDecodingDelay)), |
| 27 demuxer_stream_( |
| 28 new FakeDemuxerStream(kNumConfigs, kNumBuffersInOneConfig, false)), |
| 29 num_decoded_frames_(0), |
| 30 is_read_pending_(false), |
| 31 is_reset_pending_(false), |
| 32 is_stop_pending_(false) {} |
| 33 |
| 34 virtual ~FakeVideoDecoderTest() { |
| 35 StopAndExpect(OK); |
| 36 } |
| 37 |
| 38 void Initialize() { |
| 39 decoder_->Initialize(demuxer_stream_.get(), |
| 40 NewExpectedStatusCB(PIPELINE_OK), |
| 41 base::Bind(&MockStatisticsCB::OnStatistics, |
| 42 base::Unretained(&statistics_cb_))); |
| 43 message_loop_.RunUntilIdle(); |
| 44 } |
| 45 |
| 46 // Callback for VideoDecoder::Read(). |
| 47 void FrameReady(VideoDecoder::Status status, |
| 48 const scoped_refptr<VideoFrame>& frame) { |
| 49 DCHECK(is_read_pending_); |
| 50 ASSERT_EQ(VideoDecoder::kOk, status); |
| 51 |
| 52 is_read_pending_ = false; |
| 53 frame_read_ = frame; |
| 54 |
| 55 if (frame && !frame->IsEndOfStream()) |
| 56 num_decoded_frames_++; |
| 57 } |
| 58 |
| 59 enum CallbackResult { |
| 60 PENDING, |
| 61 OK, |
| 62 ABROTED, |
| 63 EOS |
| 64 }; |
| 65 |
| 66 void ExpectReadResult(CallbackResult result) { |
| 67 switch (result) { |
| 68 case PENDING: |
| 69 EXPECT_TRUE(is_read_pending_); |
| 70 ASSERT_FALSE(frame_read_); |
| 71 break; |
| 72 case OK: |
| 73 EXPECT_FALSE(is_read_pending_); |
| 74 ASSERT_TRUE(frame_read_); |
| 75 EXPECT_FALSE(frame_read_->IsEndOfStream()); |
| 76 break; |
| 77 case ABROTED: |
| 78 EXPECT_FALSE(is_read_pending_); |
| 79 EXPECT_FALSE(frame_read_); |
| 80 break; |
| 81 case EOS: |
| 82 EXPECT_FALSE(is_read_pending_); |
| 83 ASSERT_TRUE(frame_read_); |
| 84 EXPECT_TRUE(frame_read_->IsEndOfStream()); |
| 85 break; |
| 86 } |
| 87 } |
| 88 |
| 89 void ReadOneFrame() { |
| 90 frame_read_ = NULL; |
| 91 is_read_pending_ = true; |
| 92 decoder_->Read( |
| 93 base::Bind(&FakeVideoDecoderTest::FrameReady, base::Unretained(this))); |
| 94 message_loop_.RunUntilIdle(); |
| 95 } |
| 96 |
| 97 void ReadUntilEOS() { |
| 98 do { |
| 99 ReadOneFrame(); |
| 100 } while (frame_read_ && !frame_read_->IsEndOfStream()); |
| 101 } |
| 102 |
| 103 void EnterPendingReadState() { |
| 104 decoder_->HoldNextRead(); |
| 105 ReadOneFrame(); |
| 106 ExpectReadResult(PENDING); |
| 107 } |
| 108 |
| 109 void SatisfyRead() { |
| 110 decoder_->SatisfyRead(); |
| 111 message_loop_.RunUntilIdle(); |
| 112 ExpectReadResult(OK); |
| 113 } |
| 114 |
| 115 // Callback for VideoDecoder::Reset(). |
| 116 void OnDecoderReset() { |
| 117 DCHECK(is_reset_pending_); |
| 118 is_reset_pending_ = false; |
| 119 } |
| 120 |
| 121 void ExpectResetResult(CallbackResult result) { |
| 122 switch (result) { |
| 123 case PENDING: |
| 124 EXPECT_TRUE(is_reset_pending_); |
| 125 break; |
| 126 case OK: |
| 127 EXPECT_FALSE(is_reset_pending_); |
| 128 break; |
| 129 default: |
| 130 NOTREACHED(); |
| 131 } |
| 132 } |
| 133 |
| 134 void ResetAndExpect(CallbackResult result) { |
| 135 is_reset_pending_ = true; |
| 136 decoder_->Reset(base::Bind(&FakeVideoDecoderTest::OnDecoderReset, |
| 137 base::Unretained(this))); |
| 138 message_loop_.RunUntilIdle(); |
| 139 ExpectResetResult(result); |
| 140 } |
| 141 |
| 142 void EnterPendingResetState() { |
| 143 decoder_->HoldNextReset(); |
| 144 ResetAndExpect(PENDING); |
| 145 } |
| 146 |
| 147 void SatisfyReset() { |
| 148 decoder_->SatisfyReset(); |
| 149 message_loop_.RunUntilIdle(); |
| 150 ExpectResetResult(OK); |
| 151 } |
| 152 |
| 153 // Callback for VideoDecoder::Stop(). |
| 154 void OnDecoderStopped() { |
| 155 DCHECK(is_stop_pending_); |
| 156 is_stop_pending_ = false; |
| 157 } |
| 158 |
| 159 void ExpectStopResult(CallbackResult result) { |
| 160 switch (result) { |
| 161 case PENDING: |
| 162 EXPECT_TRUE(is_stop_pending_); |
| 163 break; |
| 164 case OK: |
| 165 EXPECT_FALSE(is_stop_pending_); |
| 166 break; |
| 167 default: |
| 168 NOTREACHED(); |
| 169 } |
| 170 } |
| 171 |
| 172 void StopAndExpect(CallbackResult result) { |
| 173 is_stop_pending_ = true; |
| 174 decoder_->Stop(base::Bind(&FakeVideoDecoderTest::OnDecoderStopped, |
| 175 base::Unretained(this))); |
| 176 message_loop_.RunUntilIdle(); |
| 177 ExpectStopResult(result); |
| 178 } |
| 179 |
| 180 void EnterPendingStopState() { |
| 181 decoder_->HoldNextStop(); |
| 182 StopAndExpect(PENDING); |
| 183 } |
| 184 |
| 185 void SatisfyStop() { |
| 186 decoder_->SatisfyStop(); |
| 187 message_loop_.RunUntilIdle(); |
| 188 ExpectStopResult(OK); |
| 189 } |
| 190 |
| 191 // Callback for DemuxerStream::Read so that we can skip frames to trigger a |
| 192 // config change. |
| 193 void BufferReady(bool* config_changed, |
| 194 DemuxerStream::Status status, |
| 195 const scoped_refptr<DecoderBuffer>& buffer) { |
| 196 if (status == DemuxerStream::kConfigChanged) |
| 197 *config_changed = true; |
| 198 } |
| 199 |
| 200 void ChangeConfig() { |
| 201 bool config_changed = false; |
| 202 while (!config_changed) { |
| 203 demuxer_stream_->Read(base::Bind(&FakeVideoDecoderTest::BufferReady, |
| 204 base::Unretained(this), |
| 205 &config_changed)); |
| 206 message_loop_.RunUntilIdle(); |
| 207 } |
| 208 } |
| 209 |
| 210 void EnterPendingDemuxerReadState() { |
| 211 demuxer_stream_->HoldNextRead(); |
| 212 ReadOneFrame(); |
| 213 } |
| 214 |
| 215 void SatisfyDemuxerRead() { |
| 216 demuxer_stream_->SatisfyRead(); |
| 217 message_loop_.RunUntilIdle(); |
| 218 } |
| 219 |
| 220 void AbortDemuxerRead() { |
| 221 demuxer_stream_->Reset(); |
| 222 message_loop_.RunUntilIdle(); |
| 223 } |
| 224 |
| 225 base::MessageLoop message_loop_; |
| 226 scoped_ptr<FakeVideoDecoder> decoder_; |
| 227 scoped_ptr<FakeDemuxerStream> demuxer_stream_; |
| 228 MockStatisticsCB statistics_cb_; |
| 229 int num_decoded_frames_; |
| 230 |
| 231 // Callback result/status. |
| 232 scoped_refptr<VideoFrame> frame_read_; |
| 233 bool is_read_pending_; |
| 234 bool is_reset_pending_; |
| 235 bool is_stop_pending_; |
| 236 |
| 237 private: |
| 238 DISALLOW_COPY_AND_ASSIGN(FakeVideoDecoderTest); |
| 239 }; |
| 240 |
| 241 TEST_F(FakeVideoDecoderTest, Initialize) { |
| 242 Initialize(); |
| 243 } |
| 244 |
| 245 TEST_F(FakeVideoDecoderTest, Read_AllFrames) { |
| 246 Initialize(); |
| 247 ReadUntilEOS(); |
| 248 EXPECT_EQ(kNumInputBuffers, num_decoded_frames_); |
| 249 } |
| 250 |
| 251 TEST_F(FakeVideoDecoderTest, Read_AbortedDemuxerRead) { |
| 252 Initialize(); |
| 253 demuxer_stream_->HoldNextRead(); |
| 254 ReadOneFrame(); |
| 255 AbortDemuxerRead(); |
| 256 ExpectReadResult(ABROTED); |
| 257 } |
| 258 |
| 259 TEST_F(FakeVideoDecoderTest, Read_DecodingDelay) { |
| 260 Initialize(); |
| 261 |
| 262 while (demuxer_stream_->num_buffers_returned() < kNumInputBuffers) { |
| 263 ReadOneFrame(); |
| 264 EXPECT_EQ(demuxer_stream_->num_buffers_returned(), |
| 265 num_decoded_frames_ + kDecodingDelay); |
| 266 } |
| 267 } |
| 268 |
| 269 TEST_F(FakeVideoDecoderTest, Read_ZeroDelay) { |
| 270 decoder_.reset(new FakeVideoDecoder(0)); |
| 271 Initialize(); |
| 272 |
| 273 while (demuxer_stream_->num_buffers_returned() < kNumInputBuffers) { |
| 274 ReadOneFrame(); |
| 275 EXPECT_EQ(demuxer_stream_->num_buffers_returned(), num_decoded_frames_); |
| 276 } |
| 277 } |
| 278 |
| 279 TEST_F(FakeVideoDecoderTest, Read_Pending) { |
| 280 Initialize(); |
| 281 EnterPendingReadState(); |
| 282 SatisfyRead(); |
| 283 } |
| 284 |
| 285 TEST_F(FakeVideoDecoderTest, Reinitialize) { |
| 286 Initialize(); |
| 287 VideoDecoderConfig old_config = demuxer_stream_->video_decoder_config(); |
| 288 ChangeConfig(); |
| 289 VideoDecoderConfig new_config = demuxer_stream_->video_decoder_config(); |
| 290 EXPECT_FALSE(new_config.Matches(old_config)); |
| 291 Initialize(); |
| 292 } |
| 293 |
| 294 // Reinitializing the decoder during the middle of the decoding process can |
| 295 // cause dropped frames. |
| 296 TEST_F(FakeVideoDecoderTest, Reinitialize_FrameDropped) { |
| 297 Initialize(); |
| 298 ReadOneFrame(); |
| 299 Initialize(); |
| 300 ReadUntilEOS(); |
| 301 EXPECT_LT(num_decoded_frames_, kNumInputBuffers); |
| 302 } |
| 303 |
| 304 TEST_F(FakeVideoDecoderTest, Reset) { |
| 305 Initialize(); |
| 306 ReadOneFrame(); |
| 307 ResetAndExpect(OK); |
| 308 } |
| 309 |
| 310 TEST_F(FakeVideoDecoderTest, Reset_DuringPendingDemuxerRead) { |
| 311 Initialize(); |
| 312 EnterPendingDemuxerReadState(); |
| 313 ResetAndExpect(PENDING); |
| 314 SatisfyDemuxerRead(); |
| 315 ExpectReadResult(ABROTED); |
| 316 } |
| 317 |
| 318 TEST_F(FakeVideoDecoderTest, Reset_DuringPendingDemuxerRead_Aborted) { |
| 319 Initialize(); |
| 320 EnterPendingDemuxerReadState(); |
| 321 ResetAndExpect(PENDING); |
| 322 AbortDemuxerRead(); |
| 323 ExpectReadResult(ABROTED); |
| 324 } |
| 325 |
| 326 TEST_F(FakeVideoDecoderTest, Reset_DuringPendingRead) { |
| 327 Initialize(); |
| 328 EnterPendingReadState(); |
| 329 ResetAndExpect(PENDING); |
| 330 SatisfyRead(); |
| 331 } |
| 332 |
| 333 TEST_F(FakeVideoDecoderTest, Reset_Pending) { |
| 334 Initialize(); |
| 335 EnterPendingResetState(); |
| 336 SatisfyReset(); |
| 337 } |
| 338 |
| 339 TEST_F(FakeVideoDecoderTest, Reset_PendingDuringPendingRead) { |
| 340 Initialize(); |
| 341 EnterPendingReadState(); |
| 342 EnterPendingResetState(); |
| 343 SatisfyRead(); |
| 344 SatisfyReset(); |
| 345 } |
| 346 |
| 347 TEST_F(FakeVideoDecoderTest, Stop) { |
| 348 Initialize(); |
| 349 ReadOneFrame(); |
| 350 ExpectReadResult(OK); |
| 351 StopAndExpect(OK); |
| 352 } |
| 353 |
| 354 TEST_F(FakeVideoDecoderTest, Stop_DuringPendingDemuxerRead) { |
| 355 Initialize(); |
| 356 EnterPendingDemuxerReadState(); |
| 357 StopAndExpect(PENDING); |
| 358 SatisfyDemuxerRead(); |
| 359 ExpectReadResult(ABROTED); |
| 360 } |
| 361 |
| 362 TEST_F(FakeVideoDecoderTest, Stop_DuringPendingDemuxerRead_Aborted) { |
| 363 Initialize(); |
| 364 EnterPendingDemuxerReadState(); |
| 365 ResetAndExpect(PENDING); |
| 366 StopAndExpect(PENDING); |
| 367 SatisfyDemuxerRead(); |
| 368 ExpectReadResult(ABROTED); |
| 369 ExpectResetResult(OK); |
| 370 ExpectStopResult(OK); |
| 371 } |
| 372 |
| 373 TEST_F(FakeVideoDecoderTest, Stop_DuringPendingRead) { |
| 374 Initialize(); |
| 375 EnterPendingReadState(); |
| 376 StopAndExpect(PENDING); |
| 377 SatisfyRead(); |
| 378 ExpectStopResult(OK); |
| 379 } |
| 380 |
| 381 TEST_F(FakeVideoDecoderTest, Stop_DuringPendingReset) { |
| 382 Initialize(); |
| 383 EnterPendingResetState(); |
| 384 StopAndExpect(PENDING); |
| 385 SatisfyReset(); |
| 386 ExpectStopResult(OK); |
| 387 } |
| 388 |
| 389 TEST_F(FakeVideoDecoderTest, Stop_DuringPendingReadAndPendingReset) { |
| 390 Initialize(); |
| 391 EnterPendingReadState(); |
| 392 EnterPendingResetState(); |
| 393 StopAndExpect(PENDING); |
| 394 SatisfyRead(); |
| 395 SatisfyReset(); |
| 396 ExpectStopResult(OK); |
| 397 } |
| 398 |
| 399 TEST_F(FakeVideoDecoderTest, Stop_Pending) { |
| 400 Initialize(); |
| 401 decoder_->HoldNextStop(); |
| 402 StopAndExpect(PENDING); |
| 403 decoder_->SatisfyStop(); |
| 404 message_loop_.RunUntilIdle(); |
| 405 ExpectStopResult(OK); |
| 406 } |
| 407 |
| 408 TEST_F(FakeVideoDecoderTest, Stop_PendingDuringPendingRead) { |
| 409 Initialize(); |
| 410 EnterPendingReadState(); |
| 411 EnterPendingStopState(); |
| 412 SatisfyRead(); |
| 413 SatisfyStop(); |
| 414 } |
| 415 |
| 416 TEST_F(FakeVideoDecoderTest, Stop_PendingDuringPendingReset) { |
| 417 Initialize(); |
| 418 EnterPendingResetState(); |
| 419 EnterPendingStopState(); |
| 420 SatisfyReset(); |
| 421 SatisfyStop(); |
| 422 } |
| 423 |
| 424 TEST_F(FakeVideoDecoderTest, Stop_PendingDuringPendingReadAndPendingReset) { |
| 425 Initialize(); |
| 426 EnterPendingReadState(); |
| 427 EnterPendingResetState(); |
| 428 EnterPendingStopState(); |
| 429 SatisfyRead(); |
| 430 SatisfyReset(); |
| 431 SatisfyStop(); |
| 432 } |
| 433 |
| 434 } // namespace media |
OLD | NEW |