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