• 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_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 
TearDown()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 
Decoded(webrtc::I420VideoFrame & decoded_image)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 
Initialize()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 
NotifyResetDone()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 
RunUntilIdle()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 
TEST_F(RTCVideoDecoderTest,CreateReturnsNullOnUnsupportedCodec)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 
TEST_F(RTCVideoDecoderTest,InitDecodeReturnsErrorOnFeedbackMode)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 
TEST_F(RTCVideoDecoderTest,DecodeReturnsErrorWithoutInitDecode)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 
TEST_F(RTCVideoDecoderTest,DecodeReturnsErrorOnIncompleteFrame)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 
TEST_F(RTCVideoDecoderTest,DecodeReturnsErrorOnMissingFrames)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 
TEST_F(RTCVideoDecoderTest,ResetReturnsOk)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 
TEST_F(RTCVideoDecoderTest,ReleaseReturnsOk)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 
TEST_F(RTCVideoDecoderTest,InitDecodeAfterRelease)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 
TEST_F(RTCVideoDecoderTest,IsBufferAfterReset)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 
TEST_F(RTCVideoDecoderTest,IsFirstBufferAfterReset)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