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_decoder_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::MockGpuVideoDecoderFactories),
     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_loop_proxy_ = vda_thread_.message_loop_proxy();
     37     mock_vda_ = new media::MockVideoDecodeAccelerator;
     38     EXPECT_CALL(*mock_gpu_factories_, GetMessageLoop())
     39         .WillRepeatedly(Return(vda_loop_proxy_));
     40     EXPECT_CALL(*mock_gpu_factories_, CreateVideoDecodeAccelerator(_, _))
     41         .WillRepeatedly(
     42              Return(static_cast<media::VideoDecodeAccelerator*>(NULL)));
     43     EXPECT_CALL(*mock_gpu_factories_,
     44                 CreateVideoDecodeAccelerator(media::VP8PROFILE_MAIN, _))
     45         .WillRepeatedly(Return(mock_vda_));
     46     EXPECT_CALL(*mock_gpu_factories_, Abort()).WillRepeatedly(Return());
     47     EXPECT_CALL(*mock_gpu_factories_, CreateSharedMemory(_))
     48         .WillRepeatedly(Return(static_cast<base::SharedMemory*>(NULL)));
     49     EXPECT_CALL(*mock_vda_, Destroy());
     50     rtc_decoder_ =
     51         RTCVideoDecoder::Create(webrtc::kVideoCodecVP8, mock_gpu_factories_);
     52   }
     53 
     54   virtual void TearDown() OVERRIDE {
     55     VLOG(2) << "TearDown";
     56     if (vda_thread_.IsRunning()) {
     57       RunUntilIdle();  // Wait until all callbascks complete.
     58       vda_loop_proxy_->DeleteSoon(FROM_HERE, rtc_decoder_.release());
     59       // Make sure the decoder is released before stopping the thread.
     60       RunUntilIdle();
     61       vda_thread_.Stop();
     62     } else {
     63       rtc_decoder_.reset();
     64     }
     65   }
     66 
     67   virtual int32_t Decoded(webrtc::I420VideoFrame& decoded_image) OVERRIDE {
     68     VLOG(2) << "Decoded";
     69     EXPECT_EQ(vda_loop_proxy_, base::MessageLoopProxy::current());
     70     return WEBRTC_VIDEO_CODEC_OK;
     71   }
     72 
     73   void Initialize() {
     74     VLOG(2) << "Initialize";
     75     codec_.codecType = webrtc::kVideoCodecVP8;
     76     EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->InitDecode(&codec_, 1));
     77     EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
     78               rtc_decoder_->RegisterDecodeCompleteCallback(this));
     79   }
     80 
     81   void NotifyResetDone() {
     82     VLOG(2) << "NotifyResetDone";
     83     vda_loop_proxy_->PostTask(FROM_HERE,
     84                               base::Bind(&RTCVideoDecoder::NotifyResetDone,
     85                                          base::Unretained(rtc_decoder_.get())));
     86   }
     87 
     88   void RunUntilIdle() {
     89     VLOG(2) << "RunUntilIdle";
     90     vda_loop_proxy_->PostTask(FROM_HERE,
     91                               base::Bind(&base::WaitableEvent::Signal,
     92                                          base::Unretained(&idle_waiter_)));
     93     idle_waiter_.Wait();
     94   }
     95 
     96  protected:
     97   scoped_refptr<media::MockGpuVideoDecoderFactories> mock_gpu_factories_;
     98   media::MockVideoDecodeAccelerator* mock_vda_;
     99   scoped_ptr<RTCVideoDecoder> rtc_decoder_;
    100   webrtc::VideoCodec codec_;
    101   base::Thread vda_thread_;
    102 
    103  private:
    104   scoped_refptr<base::MessageLoopProxy> vda_loop_proxy_;
    105 
    106   base::Lock lock_;
    107   base::WaitableEvent idle_waiter_;
    108 };
    109 
    110 TEST_F(RTCVideoDecoderTest, CreateReturnsNullOnUnsupportedCodec) {
    111   scoped_ptr<RTCVideoDecoder> null_rtc_decoder(
    112       RTCVideoDecoder::Create(webrtc::kVideoCodecI420, mock_gpu_factories_));
    113   EXPECT_EQ(NULL, null_rtc_decoder.get());
    114 }
    115 
    116 TEST_F(RTCVideoDecoderTest, InitDecodeReturnsErrorOnFeedbackMode) {
    117   codec_.codecType = webrtc::kVideoCodecVP8;
    118   codec_.codecSpecific.VP8.feedbackModeOn = true;
    119   EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR, rtc_decoder_->InitDecode(&codec_, 1));
    120 }
    121 
    122 TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorWithoutInitDecode) {
    123   webrtc::EncodedImage input_image;
    124   EXPECT_EQ(WEBRTC_VIDEO_CODEC_UNINITIALIZED,
    125             rtc_decoder_->Decode(input_image, false, NULL, NULL, 0));
    126 }
    127 
    128 TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnIncompleteFrame) {
    129   Initialize();
    130   webrtc::EncodedImage input_image;
    131   input_image._completeFrame = false;
    132   EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
    133             rtc_decoder_->Decode(input_image, false, NULL, NULL, 0));
    134 }
    135 
    136 TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnMissingFrames) {
    137   Initialize();
    138   webrtc::EncodedImage input_image;
    139   input_image._completeFrame = true;
    140   bool missingFrames = true;
    141   EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
    142             rtc_decoder_->Decode(input_image, missingFrames, NULL, NULL, 0));
    143 }
    144 
    145 TEST_F(RTCVideoDecoderTest, ResetReturnsOk) {
    146   Initialize();
    147   EXPECT_CALL(*mock_vda_, Reset())
    148       .WillOnce(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone));
    149   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Reset());
    150 }
    151 
    152 TEST_F(RTCVideoDecoderTest, ReleaseReturnsOk) {
    153   Initialize();
    154   EXPECT_CALL(*mock_vda_, Reset())
    155       .WillOnce(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone));
    156   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Release());
    157 }
    158 
    159 TEST_F(RTCVideoDecoderTest, InitDecodeAfterRelease) {
    160   EXPECT_CALL(*mock_vda_, Reset())
    161       .WillRepeatedly(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone));
    162   Initialize();
    163   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Release());
    164   Initialize();
    165   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Release());
    166 }
    167 
    168 TEST_F(RTCVideoDecoderTest, VdaThreadStops) { vda_thread_.Stop(); }
    169 
    170 TEST_F(RTCVideoDecoderTest, IsBufferAfterReset) {
    171   EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(0, RTCVideoDecoder::ID_INVALID));
    172   EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST,
    173                                                RTCVideoDecoder::ID_INVALID));
    174   EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_HALF - 2,
    175                                                 RTCVideoDecoder::ID_HALF + 2));
    176   EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_HALF + 2,
    177                                                RTCVideoDecoder::ID_HALF - 2));
    178 
    179   EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(0, 0));
    180   EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(0, RTCVideoDecoder::ID_LAST));
    181   EXPECT_FALSE(
    182       rtc_decoder_->IsBufferAfterReset(0, RTCVideoDecoder::ID_HALF - 2));
    183   EXPECT_TRUE(
    184       rtc_decoder_->IsBufferAfterReset(0, RTCVideoDecoder::ID_HALF + 2));
    185 
    186   EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST, 0));
    187   EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST,
    188                                                 RTCVideoDecoder::ID_HALF - 2));
    189   EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST,
    190                                                RTCVideoDecoder::ID_HALF + 2));
    191   EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST,
    192                                                 RTCVideoDecoder::ID_LAST));
    193 }
    194 
    195 }  // content
    196