This source file includes following definitions.
- is_reset_pending_
- InitializeWithConfig
- Initialize
- EnterPendingInitState
- SatisfyInit
- FrameReady
- ExpectReadResult
- Decode
- ReadOneFrame
- ReadUntilEOS
- EnterPendingReadState
- SatisfyReadAndExpect
- SatisfyRead
- OnDecoderReset
- ExpectResetResult
- ResetAndExpect
- EnterPendingResetState
- SatisfyReset
- Stop
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
#include "base/basictypes.h"
#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "media/base/decoder_buffer.h"
#include "media/base/mock_filters.h"
#include "media/base/test_helpers.h"
#include "media/base/video_frame.h"
#include "media/filters/fake_video_decoder.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace media {
static const int kDecodingDelay = 9;
static const int kTotalBuffers = 12;
static const int kDurationMs = 30;
class FakeVideoDecoderTest : public testing::Test {
 public:
  FakeVideoDecoderTest()
      : decoder_(new FakeVideoDecoder(kDecodingDelay, false)),
        num_input_buffers_(0),
        num_decoded_frames_(0),
        decode_status_(VideoDecoder::kNotEnoughData),
        is_decode_pending_(false),
        is_reset_pending_(false) {}
  virtual ~FakeVideoDecoderTest() {
    Stop();
  }
  void InitializeWithConfig(const VideoDecoderConfig& config) {
    decoder_->Initialize(config, NewExpectedStatusCB(PIPELINE_OK));
    message_loop_.RunUntilIdle();
    current_config_ = config;
  }
  void Initialize() {
    InitializeWithConfig(TestVideoConfig::Normal());
  }
  void EnterPendingInitState() {
    decoder_->HoldNextInit();
    Initialize();
  }
  void SatisfyInit() {
    decoder_->SatisfyInit();
    message_loop_.RunUntilIdle();
  }
  
  void FrameReady(VideoDecoder::Status status,
                  const scoped_refptr<VideoFrame>& frame) {
    DCHECK(is_decode_pending_);
    ASSERT_TRUE(status == VideoDecoder::kOk ||
                status == VideoDecoder::kNotEnoughData);
    is_decode_pending_ = false;
    decode_status_ = status;
    frame_decoded_ = frame;
    if (frame && !frame->end_of_stream())
      num_decoded_frames_++;
  }
  enum CallbackResult {
    PENDING,
    OK,
    NOT_ENOUGH_DATA,
    ABROTED,
    EOS
  };
  void ExpectReadResult(CallbackResult result) {
    switch (result) {
      case PENDING:
        EXPECT_TRUE(is_decode_pending_);
        ASSERT_FALSE(frame_decoded_);
        break;
      case OK:
        EXPECT_FALSE(is_decode_pending_);
        ASSERT_EQ(VideoDecoder::kOk, decode_status_);
        ASSERT_TRUE(frame_decoded_);
        EXPECT_FALSE(frame_decoded_->end_of_stream());
        break;
      case NOT_ENOUGH_DATA:
        EXPECT_FALSE(is_decode_pending_);
        ASSERT_EQ(VideoDecoder::kNotEnoughData, decode_status_);
        ASSERT_FALSE(frame_decoded_);
        break;
      case ABROTED:
        EXPECT_FALSE(is_decode_pending_);
        ASSERT_EQ(VideoDecoder::kOk, decode_status_);
        EXPECT_FALSE(frame_decoded_);
        break;
      case EOS:
        EXPECT_FALSE(is_decode_pending_);
        ASSERT_EQ(VideoDecoder::kOk, decode_status_);
        ASSERT_TRUE(frame_decoded_);
        EXPECT_TRUE(frame_decoded_->end_of_stream());
        break;
    }
  }
  void Decode() {
    scoped_refptr<DecoderBuffer> buffer;
    if (num_input_buffers_ < kTotalBuffers) {
      buffer = CreateFakeVideoBufferForTest(
          current_config_,
          base::TimeDelta::FromMilliseconds(kDurationMs * num_input_buffers_),
          base::TimeDelta::FromMilliseconds(kDurationMs));
      num_input_buffers_++;
    } else {
      buffer = DecoderBuffer::CreateEOSBuffer();
    }
    decode_status_ = VideoDecoder::kDecodeError;
    frame_decoded_ = NULL;
    is_decode_pending_ = true;
    decoder_->Decode(
        buffer,
        base::Bind(&FakeVideoDecoderTest::FrameReady, base::Unretained(this)));
    message_loop_.RunUntilIdle();
  }
  void ReadOneFrame() {
    do {
      Decode();
    } while (decode_status_ == VideoDecoder::kNotEnoughData &&
             !is_decode_pending_);
  }
  void ReadUntilEOS() {
    do {
      ReadOneFrame();
    } while (frame_decoded_ && !frame_decoded_->end_of_stream());
  }
  void EnterPendingReadState() {
    
    ReadOneFrame();
    decoder_->HoldNextDecode();
    ReadOneFrame();
    ExpectReadResult(PENDING);
  }
  void SatisfyReadAndExpect(CallbackResult result) {
    decoder_->SatisfyDecode();
    message_loop_.RunUntilIdle();
    ExpectReadResult(result);
  }
  void SatisfyRead() {
    SatisfyReadAndExpect(OK);
  }
  
  void OnDecoderReset() {
    DCHECK(is_reset_pending_);
    is_reset_pending_ = false;
  }
  void ExpectResetResult(CallbackResult result) {
    switch (result) {
      case PENDING:
        EXPECT_TRUE(is_reset_pending_);
        break;
      case OK:
        EXPECT_FALSE(is_reset_pending_);
        break;
      default:
        NOTREACHED();
    }
  }
  void ResetAndExpect(CallbackResult result) {
    is_reset_pending_ = true;
    decoder_->Reset(base::Bind(&FakeVideoDecoderTest::OnDecoderReset,
                               base::Unretained(this)));
    message_loop_.RunUntilIdle();
    ExpectResetResult(result);
  }
  void EnterPendingResetState() {
    decoder_->HoldNextReset();
    ResetAndExpect(PENDING);
  }
  void SatisfyReset() {
    decoder_->SatisfyReset();
    message_loop_.RunUntilIdle();
    ExpectResetResult(OK);
  }
  void Stop() {
    decoder_->Stop();
    message_loop_.RunUntilIdle();
    
    DCHECK(!is_decode_pending_);
    DCHECK(!is_reset_pending_);
  }
  base::MessageLoop message_loop_;
  VideoDecoderConfig current_config_;
  scoped_ptr<FakeVideoDecoder> decoder_;
  int num_input_buffers_;
  int num_decoded_frames_;
  
  VideoDecoder::Status decode_status_;
  scoped_refptr<VideoFrame> frame_decoded_;
  bool is_decode_pending_;
  bool is_reset_pending_;
 private:
  DISALLOW_COPY_AND_ASSIGN(FakeVideoDecoderTest);
};
TEST_F(FakeVideoDecoderTest, Initialize) {
  Initialize();
}
TEST_F(FakeVideoDecoderTest, Read_AllFrames) {
  Initialize();
  ReadUntilEOS();
  EXPECT_EQ(kTotalBuffers, num_decoded_frames_);
}
TEST_F(FakeVideoDecoderTest, Read_DecodingDelay) {
  Initialize();
  while (num_input_buffers_ < kTotalBuffers) {
    ReadOneFrame();
    EXPECT_EQ(num_input_buffers_, num_decoded_frames_ + kDecodingDelay);
  }
}
TEST_F(FakeVideoDecoderTest, Read_ZeroDelay) {
  decoder_.reset(new FakeVideoDecoder(0, false));
  Initialize();
  while (num_input_buffers_ < kTotalBuffers) {
    ReadOneFrame();
    EXPECT_EQ(num_input_buffers_, num_decoded_frames_);
  }
}
TEST_F(FakeVideoDecoderTest, Read_Pending_NotEnoughData) {
  Initialize();
  decoder_->HoldNextDecode();
  ReadOneFrame();
  ExpectReadResult(PENDING);
  SatisfyReadAndExpect(NOT_ENOUGH_DATA);
}
TEST_F(FakeVideoDecoderTest, Read_Pending_OK) {
  Initialize();
  ReadOneFrame();
  EnterPendingReadState();
  SatisfyReadAndExpect(OK);
}
TEST_F(FakeVideoDecoderTest, Reinitialize) {
  Initialize();
  ReadOneFrame();
  InitializeWithConfig(TestVideoConfig::Large());
  ReadOneFrame();
}
TEST_F(FakeVideoDecoderTest, Reinitialize_FrameDropped) {
  Initialize();
  ReadOneFrame();
  Initialize();
  ReadUntilEOS();
  EXPECT_LT(num_decoded_frames_, kTotalBuffers);
}
TEST_F(FakeVideoDecoderTest, Reset) {
  Initialize();
  ReadOneFrame();
  ResetAndExpect(OK);
}
TEST_F(FakeVideoDecoderTest, Reset_DuringPendingRead) {
  Initialize();
  EnterPendingReadState();
  ResetAndExpect(PENDING);
  SatisfyRead();
}
TEST_F(FakeVideoDecoderTest, Reset_Pending) {
  Initialize();
  EnterPendingResetState();
  SatisfyReset();
}
TEST_F(FakeVideoDecoderTest, Reset_PendingDuringPendingRead) {
  Initialize();
  EnterPendingReadState();
  EnterPendingResetState();
  SatisfyRead();
  SatisfyReset();
}
TEST_F(FakeVideoDecoderTest, Stop) {
  Initialize();
  ReadOneFrame();
  ExpectReadResult(OK);
  Stop();
}
TEST_F(FakeVideoDecoderTest, Stop_DuringPendingInitialization) {
  EnterPendingInitState();
  Stop();
}
TEST_F(FakeVideoDecoderTest, Stop_DuringPendingRead) {
  Initialize();
  EnterPendingReadState();
  Stop();
}
TEST_F(FakeVideoDecoderTest, Stop_DuringPendingReset) {
  Initialize();
  EnterPendingResetState();
  Stop();
}
TEST_F(FakeVideoDecoderTest, Stop_DuringPendingReadAndPendingReset) {
  Initialize();
  EnterPendingReadState();
  EnterPendingResetState();
  Stop();
}
TEST_F(FakeVideoDecoderTest, GetDecodeOutput) {
  decoder_.reset(new FakeVideoDecoder(kDecodingDelay, true));
  Initialize();
  while (num_input_buffers_ < kTotalBuffers) {
    ReadOneFrame();
    while (decoder_->GetDecodeOutput())
      ++num_decoded_frames_;
    EXPECT_EQ(num_input_buffers_, num_decoded_frames_);
  }
}
}