• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
RTCVideoDecoderTest()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 
SetUp()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_, DoCreateVideoDecodeAccelerator(_, _))
41         .WillRepeatedly(
42              Return(static_cast<media::VideoDecodeAccelerator*>(NULL)));
43     EXPECT_CALL(*mock_gpu_factories_,
44                 DoCreateVideoDecodeAccelerator(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 
TearDown()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 
Decoded(webrtc::I420VideoFrame & decoded_image)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 
Initialize()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 
NotifyResetDone()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 
RunUntilIdle()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::MockGpuVideoAcceleratorFactories> 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 
TEST_F(RTCVideoDecoderTest,CreateReturnsNullOnUnsupportedCodec)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 
TEST_F(RTCVideoDecoderTest,InitDecodeReturnsErrorOnFeedbackMode)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 
TEST_F(RTCVideoDecoderTest,DecodeReturnsErrorWithoutInitDecode)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 
TEST_F(RTCVideoDecoderTest,DecodeReturnsErrorOnIncompleteFrame)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 
TEST_F(RTCVideoDecoderTest,DecodeReturnsErrorOnMissingFrames)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 
TEST_F(RTCVideoDecoderTest,ResetReturnsOk)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 
TEST_F(RTCVideoDecoderTest,ReleaseReturnsOk)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 
TEST_F(RTCVideoDecoderTest,InitDecodeAfterRelease)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 
TEST_F(RTCVideoDecoderTest,VdaThreadStops)168 TEST_F(RTCVideoDecoderTest, VdaThreadStops) { vda_thread_.Stop(); }
169 
TEST_F(RTCVideoDecoderTest,IsBufferAfterReset)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 
TEST_F(RTCVideoDecoderTest,IsFirstBufferAfterReset)195 TEST_F(RTCVideoDecoderTest, IsFirstBufferAfterReset) {
196   EXPECT_TRUE(
197       rtc_decoder_->IsFirstBufferAfterReset(0, RTCVideoDecoder::ID_INVALID));
198   EXPECT_FALSE(
199       rtc_decoder_->IsFirstBufferAfterReset(1, RTCVideoDecoder::ID_INVALID));
200   EXPECT_FALSE(rtc_decoder_->IsFirstBufferAfterReset(0, 0));
201   EXPECT_TRUE(rtc_decoder_->IsFirstBufferAfterReset(1, 0));
202   EXPECT_FALSE(rtc_decoder_->IsFirstBufferAfterReset(2, 0));
203 
204   EXPECT_FALSE(rtc_decoder_->IsFirstBufferAfterReset(RTCVideoDecoder::ID_HALF,
205                                                      RTCVideoDecoder::ID_HALF));
206   EXPECT_TRUE(rtc_decoder_->IsFirstBufferAfterReset(
207       RTCVideoDecoder::ID_HALF + 1, RTCVideoDecoder::ID_HALF));
208   EXPECT_FALSE(rtc_decoder_->IsFirstBufferAfterReset(
209       RTCVideoDecoder::ID_HALF + 2, RTCVideoDecoder::ID_HALF));
210 
211   EXPECT_FALSE(rtc_decoder_->IsFirstBufferAfterReset(RTCVideoDecoder::ID_LAST,
212                                                      RTCVideoDecoder::ID_LAST));
213   EXPECT_TRUE(
214       rtc_decoder_->IsFirstBufferAfterReset(0, RTCVideoDecoder::ID_LAST));
215   EXPECT_FALSE(
216       rtc_decoder_->IsFirstBufferAfterReset(1, RTCVideoDecoder::ID_LAST));
217 }
218 
219 }  // content
220