1// Copyright 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/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_video_decoder.h" 13#include "testing/gtest/include/gtest/gtest.h" 14 15namespace media { 16 17static const int kTotalBuffers = 12; 18static const int kDurationMs = 30; 19 20struct FakeVideoDecoderTestParams { 21 FakeVideoDecoderTestParams(int decoding_delay, int max_decode_requests) 22 : decoding_delay(decoding_delay), 23 max_decode_requests(max_decode_requests) {} 24 int decoding_delay; 25 int max_decode_requests; 26}; 27 28class FakeVideoDecoderTest 29 : public testing::Test, 30 public testing::WithParamInterface<FakeVideoDecoderTestParams> { 31 public: 32 FakeVideoDecoderTest() 33 : decoder_(new FakeVideoDecoder(GetParam().decoding_delay, 34 GetParam().max_decode_requests)), 35 num_input_buffers_(0), 36 num_decoded_frames_(0), 37 last_decode_status_(VideoDecoder::kOk), 38 pending_decode_requests_(0), 39 is_reset_pending_(false) {} 40 41 virtual ~FakeVideoDecoderTest() { 42 Destroy(); 43 } 44 45 void InitializeWithConfig(const VideoDecoderConfig& config) { 46 decoder_->Initialize( 47 config, false, NewExpectedStatusCB(PIPELINE_OK), 48 base::Bind(&FakeVideoDecoderTest::FrameReady, base::Unretained(this))); 49 message_loop_.RunUntilIdle(); 50 current_config_ = config; 51 } 52 53 void Initialize() { 54 InitializeWithConfig(TestVideoConfig::Normal()); 55 } 56 57 void EnterPendingInitState() { 58 decoder_->HoldNextInit(); 59 Initialize(); 60 } 61 62 void SatisfyInit() { 63 decoder_->SatisfyInit(); 64 message_loop_.RunUntilIdle(); 65 } 66 67 // Callback for VideoDecoder::Decode(). 68 void DecodeDone(VideoDecoder::Status status) { 69 DCHECK_GT(pending_decode_requests_, 0); 70 --pending_decode_requests_; 71 last_decode_status_ = status; 72 } 73 74 void FrameReady(const scoped_refptr<VideoFrame>& frame) { 75 DCHECK(!frame->end_of_stream()); 76 last_decoded_frame_ = frame; 77 num_decoded_frames_++; 78 } 79 80 enum CallbackResult { 81 PENDING, 82 OK, 83 NOT_ENOUGH_DATA, 84 ABORTED 85 }; 86 87 void ExpectReadResult(CallbackResult result) { 88 switch (result) { 89 case PENDING: 90 EXPECT_GT(pending_decode_requests_, 0); 91 break; 92 case OK: 93 EXPECT_EQ(0, pending_decode_requests_); 94 ASSERT_EQ(VideoDecoder::kOk, last_decode_status_); 95 ASSERT_TRUE(last_decoded_frame_.get()); 96 break; 97 case NOT_ENOUGH_DATA: 98 EXPECT_EQ(0, pending_decode_requests_); 99 ASSERT_EQ(VideoDecoder::kOk, last_decode_status_); 100 ASSERT_FALSE(last_decoded_frame_.get()); 101 break; 102 case ABORTED: 103 EXPECT_EQ(0, pending_decode_requests_); 104 ASSERT_EQ(VideoDecoder::kAborted, last_decode_status_); 105 EXPECT_FALSE(last_decoded_frame_.get()); 106 break; 107 } 108 } 109 110 void Decode() { 111 scoped_refptr<DecoderBuffer> buffer; 112 113 if (num_input_buffers_ < kTotalBuffers) { 114 buffer = CreateFakeVideoBufferForTest( 115 current_config_, 116 base::TimeDelta::FromMilliseconds(kDurationMs * num_input_buffers_), 117 base::TimeDelta::FromMilliseconds(kDurationMs)); 118 } else { 119 buffer = DecoderBuffer::CreateEOSBuffer(); 120 } 121 122 ++num_input_buffers_; 123 ++pending_decode_requests_; 124 125 decoder_->Decode( 126 buffer, 127 base::Bind(&FakeVideoDecoderTest::DecodeDone, base::Unretained(this))); 128 message_loop_.RunUntilIdle(); 129 } 130 131 void ReadOneFrame() { 132 last_decoded_frame_ = NULL; 133 do { 134 Decode(); 135 } while (!last_decoded_frame_.get() && pending_decode_requests_ == 0); 136 } 137 138 void ReadAllFrames() { 139 do { 140 Decode(); 141 } while (num_input_buffers_ <= kTotalBuffers); // All input buffers + EOS. 142 } 143 144 void EnterPendingReadState() { 145 // Pass the initial NOT_ENOUGH_DATA stage. 146 ReadOneFrame(); 147 decoder_->HoldDecode(); 148 ReadOneFrame(); 149 ExpectReadResult(PENDING); 150 } 151 152 void SatisfyDecodeAndExpect(CallbackResult result) { 153 decoder_->SatisfyDecode(); 154 message_loop_.RunUntilIdle(); 155 ExpectReadResult(result); 156 } 157 158 void SatisfyRead() { 159 SatisfyDecodeAndExpect(OK); 160 } 161 162 // Callback for VideoDecoder::Reset(). 163 void OnDecoderReset() { 164 DCHECK(is_reset_pending_); 165 is_reset_pending_ = false; 166 } 167 168 void ExpectResetResult(CallbackResult result) { 169 switch (result) { 170 case PENDING: 171 EXPECT_TRUE(is_reset_pending_); 172 break; 173 case OK: 174 EXPECT_FALSE(is_reset_pending_); 175 break; 176 default: 177 NOTREACHED(); 178 } 179 } 180 181 void ResetAndExpect(CallbackResult result) { 182 is_reset_pending_ = true; 183 decoder_->Reset(base::Bind(&FakeVideoDecoderTest::OnDecoderReset, 184 base::Unretained(this))); 185 message_loop_.RunUntilIdle(); 186 ExpectResetResult(result); 187 } 188 189 void EnterPendingResetState() { 190 decoder_->HoldNextReset(); 191 ResetAndExpect(PENDING); 192 } 193 194 void SatisfyReset() { 195 decoder_->SatisfyReset(); 196 message_loop_.RunUntilIdle(); 197 ExpectResetResult(OK); 198 } 199 200 void Destroy() { 201 decoder_.reset(); 202 message_loop_.RunUntilIdle(); 203 204 // All pending callbacks must have been fired. 205 DCHECK_EQ(pending_decode_requests_, 0); 206 DCHECK(!is_reset_pending_); 207 } 208 209 base::MessageLoop message_loop_; 210 VideoDecoderConfig current_config_; 211 212 scoped_ptr<FakeVideoDecoder> decoder_; 213 214 int num_input_buffers_; 215 int num_decoded_frames_; 216 217 // Callback result/status. 218 VideoDecoder::Status last_decode_status_; 219 scoped_refptr<VideoFrame> last_decoded_frame_; 220 int pending_decode_requests_; 221 bool is_reset_pending_; 222 223 private: 224 DISALLOW_COPY_AND_ASSIGN(FakeVideoDecoderTest); 225}; 226 227INSTANTIATE_TEST_CASE_P(NoParallelDecode, 228 FakeVideoDecoderTest, 229 ::testing::Values(FakeVideoDecoderTestParams(9, 1), 230 FakeVideoDecoderTestParams(0, 1))); 231INSTANTIATE_TEST_CASE_P(ParallelDecode, 232 FakeVideoDecoderTest, 233 ::testing::Values(FakeVideoDecoderTestParams(9, 3), 234 FakeVideoDecoderTestParams(0, 3))); 235 236TEST_P(FakeVideoDecoderTest, Initialize) { 237 Initialize(); 238} 239 240TEST_P(FakeVideoDecoderTest, Read_AllFrames) { 241 Initialize(); 242 ReadAllFrames(); 243 EXPECT_EQ(kTotalBuffers, num_decoded_frames_); 244} 245 246TEST_P(FakeVideoDecoderTest, Read_DecodingDelay) { 247 Initialize(); 248 249 while (num_input_buffers_ < kTotalBuffers) { 250 ReadOneFrame(); 251 EXPECT_EQ(num_input_buffers_, 252 num_decoded_frames_ + GetParam().decoding_delay); 253 } 254} 255 256TEST_P(FakeVideoDecoderTest, Read_ZeroDelay) { 257 decoder_.reset(new FakeVideoDecoder(0, 1)); 258 Initialize(); 259 260 while (num_input_buffers_ < kTotalBuffers) { 261 ReadOneFrame(); 262 EXPECT_EQ(num_input_buffers_, num_decoded_frames_); 263 } 264} 265 266TEST_P(FakeVideoDecoderTest, Read_Pending_NotEnoughData) { 267 if (GetParam().decoding_delay < 1) 268 return; 269 270 Initialize(); 271 decoder_->HoldDecode(); 272 ReadOneFrame(); 273 ExpectReadResult(PENDING); 274 SatisfyDecodeAndExpect(NOT_ENOUGH_DATA); 275 276 // Verify that FrameReady() hasn't been called. 277 EXPECT_FALSE(last_decoded_frame_.get()); 278} 279 280TEST_P(FakeVideoDecoderTest, Read_Pending_OK) { 281 Initialize(); 282 EnterPendingReadState(); 283 SatisfyDecodeAndExpect(OK); 284} 285 286TEST_P(FakeVideoDecoderTest, Read_Parallel) { 287 if (GetParam().max_decode_requests < 2) 288 return; 289 290 Initialize(); 291 decoder_->HoldDecode(); 292 for (int i = 0; i < GetParam().max_decode_requests; ++i) { 293 ReadOneFrame(); 294 ExpectReadResult(PENDING); 295 } 296 EXPECT_EQ(GetParam().max_decode_requests, pending_decode_requests_); 297 SatisfyDecodeAndExpect( 298 GetParam().max_decode_requests > GetParam().decoding_delay 299 ? OK 300 : NOT_ENOUGH_DATA); 301} 302 303TEST_P(FakeVideoDecoderTest, ReadWithHold_DecodingDelay) { 304 Initialize(); 305 306 // Hold all decodes and satisfy one decode at a time. 307 decoder_->HoldDecode(); 308 int num_decodes_satisfied = 0; 309 while (num_decoded_frames_ == 0) { 310 while (pending_decode_requests_ < decoder_->GetMaxDecodeRequests()) 311 Decode(); 312 decoder_->SatisfySingleDecode(); 313 ++num_decodes_satisfied; 314 message_loop_.RunUntilIdle(); 315 } 316 317 DCHECK_EQ(num_decoded_frames_, 1); 318 DCHECK_EQ(num_decodes_satisfied, GetParam().decoding_delay + 1); 319} 320 321TEST_P(FakeVideoDecoderTest, Reinitialize) { 322 Initialize(); 323 ReadOneFrame(); 324 InitializeWithConfig(TestVideoConfig::Large()); 325 ReadOneFrame(); 326} 327 328// Reinitializing the decoder during the middle of the decoding process can 329// cause dropped frames. 330TEST_P(FakeVideoDecoderTest, Reinitialize_FrameDropped) { 331 if (GetParam().decoding_delay < 1) 332 return; 333 334 Initialize(); 335 ReadOneFrame(); 336 Initialize(); 337 ReadAllFrames(); 338 EXPECT_LT(num_decoded_frames_, kTotalBuffers); 339} 340 341TEST_P(FakeVideoDecoderTest, Reset) { 342 Initialize(); 343 ReadOneFrame(); 344 ResetAndExpect(OK); 345} 346 347TEST_P(FakeVideoDecoderTest, Reset_DuringPendingRead) { 348 Initialize(); 349 EnterPendingReadState(); 350 ResetAndExpect(PENDING); 351 SatisfyDecodeAndExpect(ABORTED); 352} 353 354TEST_P(FakeVideoDecoderTest, Reset_Pending) { 355 Initialize(); 356 EnterPendingResetState(); 357 SatisfyReset(); 358} 359 360TEST_P(FakeVideoDecoderTest, Reset_PendingDuringPendingRead) { 361 Initialize(); 362 EnterPendingReadState(); 363 EnterPendingResetState(); 364 SatisfyDecodeAndExpect(ABORTED); 365 SatisfyReset(); 366} 367 368TEST_P(FakeVideoDecoderTest, Destroy) { 369 Initialize(); 370 ReadOneFrame(); 371 ExpectReadResult(OK); 372 Destroy(); 373} 374 375TEST_P(FakeVideoDecoderTest, Destroy_DuringPendingInitialization) { 376 EnterPendingInitState(); 377 Destroy(); 378} 379 380TEST_P(FakeVideoDecoderTest, Destroy_DuringPendingRead) { 381 Initialize(); 382 EnterPendingReadState(); 383 Destroy(); 384} 385 386TEST_P(FakeVideoDecoderTest, Destroy_DuringPendingReset) { 387 Initialize(); 388 EnterPendingResetState(); 389 Destroy(); 390} 391 392TEST_P(FakeVideoDecoderTest, Destroy_DuringPendingReadAndPendingReset) { 393 Initialize(); 394 EnterPendingReadState(); 395 EnterPendingResetState(); 396 Destroy(); 397} 398 399} // namespace media 400