Home | History | Annotate | Download | only in media
      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/bind.h"
      6 #include "base/message_loop/message_loop.h"
      7 #include "base/synchronization/waitable_event.h"
      8 #include "base/threading/thread.h"
      9 #include "content/renderer/media/rtc_video_decoder.h"
     10 #include "media/base/gmock_callback_support.h"
     11 #include "media/filters/mock_gpu_video_accelerator_factories.h"
     12 #include "media/video/mock_video_decode_accelerator.h"
     13 #include "testing/gtest/include/gtest/gtest.h"
     14 
     15 using ::testing::_;
     16 using ::testing::Invoke;
     17 using ::testing::Return;
     18 using ::testing::SaveArg;
     19 using ::testing::WithArgs;
     20 
     21 namespace content {
     22 
     23 // TODO(wuchengli): add MockSharedMemroy so more functions can be tested.
     24 class RTCVideoDecoderTest : public ::testing::Test,
     25                             webrtc::DecodedImageCallback {
     26  public:
     27   RTCVideoDecoderTest()
     28       : mock_gpu_factories_(new media::MockGpuVideoAcceleratorFactories),
     29         vda_thread_("vda_thread"),
     30         idle_waiter_(false, false) {
     31     memset(&codec_, 0, sizeof(codec_));
     32   }
     33 
     34   virtual void SetUp() OVERRIDE {
     35     ASSERT_TRUE(vda_thread_.Start());
     36     vda_task_runner_ = vda_thread_.message_loop_proxy();
     37     mock_vda_ = new media::MockVideoDecodeAccelerator;
     38     EXPECT_CALL(*mock_gpu_factories_, GetTaskRunner())
     39         .WillRepeatedly(Return(vda_task_runner_));
     40     EXPECT_CALL(*mock_gpu_factories_, DoCreateVideoDecodeAccelerator())
     41         .WillRepeatedly(Return(mock_vda_));
     42     EXPECT_CALL(*mock_gpu_factories_, CreateSharedMemory(_))
     43         .WillRepeatedly(Return(static_cast<base::SharedMemory*>(NULL)));
     44     EXPECT_CALL(*mock_vda_, Initialize(_, _))
     45         .Times(1)
     46         .WillRepeatedly(Return(true));
     47     EXPECT_CALL(*mock_vda_, Destroy()).Times(1);
     48     rtc_decoder_ =
     49         RTCVideoDecoder::Create(webrtc::kVideoCodecVP8, mock_gpu_factories_);
     50   }
     51 
     52   virtual void TearDown() OVERRIDE {
     53     VLOG(2) << "TearDown";
     54     EXPECT_TRUE(vda_thread_.IsRunning());
     55     RunUntilIdle();  // Wait until all callbascks complete.
     56     vda_task_runner_->DeleteSoon(FROM_HERE, rtc_decoder_.release());
     57     // Make sure the decoder is released before stopping the thread.
     58     RunUntilIdle();
     59     vda_thread_.Stop();
     60   }
     61 
     62   virtual int32_t Decoded(webrtc::I420VideoFrame& decoded_image) OVERRIDE {
     63     VLOG(2) << "Decoded";
     64     EXPECT_EQ(vda_task_runner_, base::MessageLoopProxy::current());
     65     return WEBRTC_VIDEO_CODEC_OK;
     66   }
     67 
     68   void Initialize() {
     69     VLOG(2) << "Initialize";
     70     codec_.codecType = webrtc::kVideoCodecVP8;
     71     EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->InitDecode(&codec_, 1));
     72     EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
     73               rtc_decoder_->RegisterDecodeCompleteCallback(this));
     74   }
     75 
     76   void NotifyResetDone() {
     77     VLOG(2) << "NotifyResetDone";
     78     vda_task_runner_->PostTask(
     79         FROM_HERE,
     80         base::Bind(&RTCVideoDecoder::NotifyResetDone,
     81                    base::Unretained(rtc_decoder_.get())));
     82   }
     83 
     84   void RunUntilIdle() {
     85     VLOG(2) << "RunUntilIdle";
     86     vda_task_runner_->PostTask(FROM_HERE,
     87                                base::Bind(&base::WaitableEvent::Signal,
     88                                           base::Unretained(&idle_waiter_)));
     89     idle_waiter_.Wait();
     90   }
     91 
     92  protected:
     93   scoped_refptr<media::MockGpuVideoAcceleratorFactories> mock_gpu_factories_;
     94   media::MockVideoDecodeAccelerator* mock_vda_;
     95   scoped_ptr<RTCVideoDecoder> rtc_decoder_;
     96   webrtc::VideoCodec codec_;
     97   base::Thread vda_thread_;
     98 
     99  private:
    100   scoped_refptr<base::SingleThreadTaskRunner> vda_task_runner_;
    101 
    102   base::Lock lock_;
    103   base::WaitableEvent idle_waiter_;
    104 };
    105 
    106 TEST_F(RTCVideoDecoderTest, CreateReturnsNullOnUnsupportedCodec) {
    107   scoped_ptr<RTCVideoDecoder> null_rtc_decoder(
    108       RTCVideoDecoder::Create(webrtc::kVideoCodecI420, mock_gpu_factories_));
    109   EXPECT_EQ(NULL, null_rtc_decoder.get());
    110 }
    111 
    112 TEST_F(RTCVideoDecoderTest, InitDecodeReturnsErrorOnFeedbackMode) {
    113   codec_.codecType = webrtc::kVideoCodecVP8;
    114   codec_.codecSpecific.VP8.feedbackModeOn = true;
    115   EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR, rtc_decoder_->InitDecode(&codec_, 1));
    116 }
    117 
    118 TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorWithoutInitDecode) {
    119   webrtc::EncodedImage input_image;
    120   EXPECT_EQ(WEBRTC_VIDEO_CODEC_UNINITIALIZED,
    121             rtc_decoder_->Decode(input_image, false, NULL, NULL, 0));
    122 }
    123 
    124 TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnIncompleteFrame) {
    125   Initialize();
    126   webrtc::EncodedImage input_image;
    127   input_image._completeFrame = false;
    128   EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
    129             rtc_decoder_->Decode(input_image, false, NULL, NULL, 0));
    130 }
    131 
    132 TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnMissingFrames) {
    133   Initialize();
    134   webrtc::EncodedImage input_image;
    135   input_image._completeFrame = true;
    136   bool missingFrames = true;
    137   EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
    138             rtc_decoder_->Decode(input_image, missingFrames, NULL, NULL, 0));
    139 }
    140 
    141 TEST_F(RTCVideoDecoderTest, ResetReturnsOk) {
    142   Initialize();
    143   EXPECT_CALL(*mock_vda_, Reset())
    144       .WillOnce(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone));
    145   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Reset());
    146 }
    147 
    148 TEST_F(RTCVideoDecoderTest, ReleaseReturnsOk) {
    149   Initialize();
    150   EXPECT_CALL(*mock_vda_, Reset())
    151       .WillOnce(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone));
    152   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Release());
    153 }
    154 
    155 TEST_F(RTCVideoDecoderTest, InitDecodeAfterRelease) {
    156   EXPECT_CALL(*mock_vda_, Reset())
    157       .WillRepeatedly(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone));
    158   Initialize();
    159   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Release());
    160   Initialize();
    161   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Release());
    162 }
    163 
    164 TEST_F(RTCVideoDecoderTest, IsBufferAfterReset) {
    165   EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(0, RTCVideoDecoder::ID_INVALID));
    166   EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST,
    167                                                RTCVideoDecoder::ID_INVALID));
    168   EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_HALF - 2,
    169                                                 RTCVideoDecoder::ID_HALF + 2));
    170   EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_HALF + 2,
    171                                                RTCVideoDecoder::ID_HALF - 2));
    172 
    173   EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(0, 0));
    174   EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(0, RTCVideoDecoder::ID_LAST));
    175   EXPECT_FALSE(
    176       rtc_decoder_->IsBufferAfterReset(0, RTCVideoDecoder::ID_HALF - 2));
    177   EXPECT_TRUE(
    178       rtc_decoder_->IsBufferAfterReset(0, RTCVideoDecoder::ID_HALF + 2));
    179 
    180   EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST, 0));
    181   EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST,
    182                                                 RTCVideoDecoder::ID_HALF - 2));
    183   EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST,
    184                                                RTCVideoDecoder::ID_HALF + 2));
    185   EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST,
    186                                                 RTCVideoDecoder::ID_LAST));
    187 }
    188 
    189 TEST_F(RTCVideoDecoderTest, IsFirstBufferAfterReset) {
    190   EXPECT_TRUE(
    191       rtc_decoder_->IsFirstBufferAfterReset(0, RTCVideoDecoder::ID_INVALID));
    192   EXPECT_FALSE(
    193       rtc_decoder_->IsFirstBufferAfterReset(1, RTCVideoDecoder::ID_INVALID));
    194   EXPECT_FALSE(rtc_decoder_->IsFirstBufferAfterReset(0, 0));
    195   EXPECT_TRUE(rtc_decoder_->IsFirstBufferAfterReset(1, 0));
    196   EXPECT_FALSE(rtc_decoder_->IsFirstBufferAfterReset(2, 0));
    197 
    198   EXPECT_FALSE(rtc_decoder_->IsFirstBufferAfterReset(RTCVideoDecoder::ID_HALF,
    199                                                      RTCVideoDecoder::ID_HALF));
    200   EXPECT_TRUE(rtc_decoder_->IsFirstBufferAfterReset(
    201       RTCVideoDecoder::ID_HALF + 1, RTCVideoDecoder::ID_HALF));
    202   EXPECT_FALSE(rtc_decoder_->IsFirstBufferAfterReset(
    203       RTCVideoDecoder::ID_HALF + 2, RTCVideoDecoder::ID_HALF));
    204 
    205   EXPECT_FALSE(rtc_decoder_->IsFirstBufferAfterReset(RTCVideoDecoder::ID_LAST,
    206                                                      RTCVideoDecoder::ID_LAST));
    207   EXPECT_TRUE(
    208       rtc_decoder_->IsFirstBufferAfterReset(0, RTCVideoDecoder::ID_LAST));
    209   EXPECT_FALSE(
    210       rtc_decoder_->IsFirstBufferAfterReset(1, RTCVideoDecoder::ID_LAST));
    211 }
    212 
    213 }  // content
    214