Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <stdint.h> | 5 #include <stdint.h> |
| 6 #include <string.h> | 6 #include <string.h> |
| 7 | 7 |
| 8 #include "base/bind.h" | 8 #include "base/bind.h" |
| 9 #include "base/location.h" | 9 #include "base/location.h" |
| 10 #include "base/single_thread_task_runner.h" | 10 #include "base/single_thread_task_runner.h" |
| 11 #include "base/synchronization/waitable_event.h" | 11 #include "base/synchronization/waitable_event.h" |
| 12 #include "base/thread_task_runner_handle.h" | 12 #include "base/thread_task_runner_handle.h" |
| 13 #include "base/threading/thread.h" | 13 #include "base/threading/thread.h" |
| 14 #include "content/renderer/media/rtc_video_decoder.h" | 14 #include "content/renderer/media/rtc_video_decoder.h" |
| 15 #include "media/base/gmock_callback_support.h" | 15 #include "media/base/gmock_callback_support.h" |
| 16 #include "media/renderers/mock_gpu_video_accelerator_factories.h" | 16 #include "media/renderers/mock_gpu_video_accelerator_factories.h" |
| 17 #include "media/video/mock_video_decode_accelerator.h" | 17 #include "media/video/mock_video_decode_accelerator.h" |
| 18 #include "testing/gtest/include/gtest/gtest.h" | 18 #include "testing/gtest/include/gtest/gtest.h" |
| 19 | 19 |
| 20 using ::testing::_; | 20 using ::testing::_; |
| 21 using ::testing::Invoke; | 21 using ::testing::Invoke; |
| 22 using ::testing::Return; | 22 using ::testing::Return; |
| 23 using ::testing::SaveArg; | 23 using ::testing::SaveArg; |
| 24 using ::testing::Values; | |
| 24 using ::testing::WithArgs; | 25 using ::testing::WithArgs; |
| 25 | 26 |
| 26 namespace content { | 27 namespace content { |
| 27 | 28 |
| 29 namespace { | |
| 30 | |
| 31 static const int kMinResolutionWidth = 16; | |
| 32 static const int kMinResolutionHeight = 16; | |
| 33 static const int kMaxResolutionWidth = 1920; | |
| 34 static const int kMaxResolutionHeight = 1088; | |
| 35 | |
| 36 } // namespace | |
| 37 | |
| 28 // TODO(wuchengli): add MockSharedMemroy so more functions can be tested. | 38 // TODO(wuchengli): add MockSharedMemroy so more functions can be tested. |
|
mcasas
2016/03/23 18:29:57
nit: s/MockSharedMemroy/MockSharedMemory/
emircan
2016/03/25 02:33:31
Done.
| |
| 29 class RTCVideoDecoderTest : public ::testing::Test, | 39 class RTCVideoDecoderTest |
| 30 webrtc::DecodedImageCallback { | 40 : public ::testing::TestWithParam<webrtc::VideoCodecType>, |
| 41 webrtc::DecodedImageCallback { | |
| 31 public: | 42 public: |
| 32 RTCVideoDecoderTest() | 43 RTCVideoDecoderTest() |
| 33 : mock_gpu_factories_( | 44 : mock_gpu_factories_( |
| 34 new media::MockGpuVideoAcceleratorFactories(nullptr)), | 45 new media::MockGpuVideoAcceleratorFactories(nullptr)), |
| 35 vda_thread_("vda_thread"), | 46 vda_thread_("vda_thread"), |
| 36 idle_waiter_(false, false) { | 47 idle_waiter_(false, false) { |
| 37 memset(&codec_, 0, sizeof(codec_)); | 48 memset(&codec_, 0, sizeof(codec_)); |
| 38 } | 49 } |
| 39 | 50 |
| 40 void SetUp() override { | 51 void SetUp() override { |
| 41 ASSERT_TRUE(vda_thread_.Start()); | 52 ASSERT_TRUE(vda_thread_.Start()); |
| 42 vda_task_runner_ = vda_thread_.task_runner(); | 53 vda_task_runner_ = vda_thread_.task_runner(); |
| 43 mock_vda_ = new media::MockVideoDecodeAccelerator; | 54 mock_vda_ = new media::MockVideoDecodeAccelerator; |
| 44 | 55 |
| 45 media::VideoDecodeAccelerator::SupportedProfile supported_profile; | 56 media::VideoDecodeAccelerator::SupportedProfile supported_profile; |
| 46 supported_profile.min_resolution.SetSize(16, 16); | 57 supported_profile.min_resolution.SetSize(kMinResolutionWidth, |
| 47 supported_profile.max_resolution.SetSize(1920, 1088); | 58 kMinResolutionHeight); |
| 59 supported_profile.max_resolution.SetSize(kMaxResolutionWidth, | |
| 60 kMaxResolutionHeight); | |
| 48 supported_profile.profile = media::H264PROFILE_MAIN; | 61 supported_profile.profile = media::H264PROFILE_MAIN; |
| 49 capabilities_.supported_profiles.push_back(supported_profile); | 62 capabilities_.supported_profiles.push_back(supported_profile); |
| 50 supported_profile.profile = media::VP8PROFILE_ANY; | 63 supported_profile.profile = media::VP8PROFILE_ANY; |
| 51 capabilities_.supported_profiles.push_back(supported_profile); | 64 capabilities_.supported_profiles.push_back(supported_profile); |
| 52 | 65 |
| 53 EXPECT_CALL(*mock_gpu_factories_.get(), GetTaskRunner()) | 66 EXPECT_CALL(*mock_gpu_factories_.get(), GetTaskRunner()) |
| 54 .WillRepeatedly(Return(vda_task_runner_)); | 67 .WillRepeatedly(Return(vda_task_runner_)); |
| 55 EXPECT_CALL(*mock_gpu_factories_.get(), | 68 EXPECT_CALL(*mock_gpu_factories_.get(), |
| 56 GetVideoDecodeAcceleratorCapabilities()) | 69 GetVideoDecodeAcceleratorCapabilities()) |
| 57 .WillRepeatedly(Return(capabilities_)); | 70 .WillRepeatedly(Return(capabilities_)); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 94 } | 107 } |
| 95 | 108 |
| 96 void NotifyResetDone() { | 109 void NotifyResetDone() { |
| 97 DVLOG(2) << "NotifyResetDone"; | 110 DVLOG(2) << "NotifyResetDone"; |
| 98 vda_task_runner_->PostTask( | 111 vda_task_runner_->PostTask( |
| 99 FROM_HERE, | 112 FROM_HERE, |
| 100 base::Bind(&RTCVideoDecoder::NotifyResetDone, | 113 base::Bind(&RTCVideoDecoder::NotifyResetDone, |
| 101 base::Unretained(rtc_decoder_.get()))); | 114 base::Unretained(rtc_decoder_.get()))); |
| 102 } | 115 } |
| 103 | 116 |
| 117 void NotifyError(media::VideoDecodeAccelerator::Error error) { | |
| 118 DVLOG(2) << "NotifyError"; | |
| 119 vda_task_runner_->PostTask( | |
| 120 FROM_HERE, | |
| 121 base::Bind(&RTCVideoDecoder::NotifyError, | |
| 122 base::Unretained(rtc_decoder_.get()), error)); | |
| 123 } | |
| 124 | |
| 104 void RunUntilIdle() { | 125 void RunUntilIdle() { |
| 105 DVLOG(2) << "RunUntilIdle"; | 126 DVLOG(2) << "RunUntilIdle"; |
| 106 vda_task_runner_->PostTask(FROM_HERE, | 127 vda_task_runner_->PostTask(FROM_HERE, |
| 107 base::Bind(&base::WaitableEvent::Signal, | 128 base::Bind(&base::WaitableEvent::Signal, |
| 108 base::Unretained(&idle_waiter_))); | 129 base::Unretained(&idle_waiter_))); |
| 109 idle_waiter_.Wait(); | 130 idle_waiter_.Wait(); |
| 110 } | 131 } |
| 111 | 132 |
| 133 void SetUpResetVDA() { | |
| 134 mock_reset_vda_ = new media::MockVideoDecodeAccelerator; | |
| 135 EXPECT_CALL(*mock_gpu_factories_.get(), DoCreateVideoDecodeAccelerator()) | |
| 136 .WillRepeatedly(Return(mock_reset_vda_)); | |
| 137 EXPECT_CALL(*mock_reset_vda_, Initialize(_, _)) | |
| 138 .Times(1) | |
| 139 .WillRepeatedly(Return(true)); | |
| 140 EXPECT_CALL(*mock_reset_vda_, Destroy()).Times(1); | |
| 141 } | |
| 142 | |
| 112 protected: | 143 protected: |
| 113 scoped_ptr<media::MockGpuVideoAcceleratorFactories> mock_gpu_factories_; | 144 scoped_ptr<media::MockGpuVideoAcceleratorFactories> mock_gpu_factories_; |
| 114 media::MockVideoDecodeAccelerator* mock_vda_; | 145 media::MockVideoDecodeAccelerator* mock_vda_; |
| 146 media::MockVideoDecodeAccelerator* mock_reset_vda_; | |
|
mcasas
2016/03/23 18:29:57
s/mock_reset_vda_/mock_vda_after_reset_/ ?
emircan
2016/03/25 02:33:31
Done.
| |
| 115 scoped_ptr<RTCVideoDecoder> rtc_decoder_; | 147 scoped_ptr<RTCVideoDecoder> rtc_decoder_; |
| 116 webrtc::VideoCodec codec_; | 148 webrtc::VideoCodec codec_; |
| 117 base::Thread vda_thread_; | 149 base::Thread vda_thread_; |
| 118 media::VideoDecodeAccelerator::Capabilities capabilities_; | 150 media::VideoDecodeAccelerator::Capabilities capabilities_; |
| 119 | 151 |
| 120 private: | 152 private: |
| 121 scoped_refptr<base::SingleThreadTaskRunner> vda_task_runner_; | 153 scoped_refptr<base::SingleThreadTaskRunner> vda_task_runner_; |
| 122 | 154 |
| 123 base::Lock lock_; | 155 base::Lock lock_; |
| 124 base::WaitableEvent idle_waiter_; | 156 base::WaitableEvent idle_waiter_; |
| 125 }; | 157 }; |
| 126 | 158 |
| 127 TEST_F(RTCVideoDecoderTest, CreateReturnsNullOnUnsupportedCodec) { | 159 TEST_F(RTCVideoDecoderTest, CreateReturnsNullOnUnsupportedCodec) { |
| 128 CreateDecoder(webrtc::kVideoCodecVP8); | 160 CreateDecoder(webrtc::kVideoCodecVP8); |
| 129 scoped_ptr<RTCVideoDecoder> null_rtc_decoder(RTCVideoDecoder::Create( | 161 scoped_ptr<RTCVideoDecoder> null_rtc_decoder(RTCVideoDecoder::Create( |
| 130 webrtc::kVideoCodecI420, mock_gpu_factories_.get())); | 162 webrtc::kVideoCodecI420, mock_gpu_factories_.get())); |
| 131 EXPECT_EQ(NULL, null_rtc_decoder.get()); | 163 EXPECT_EQ(NULL, null_rtc_decoder.get()); |
| 132 } | 164 } |
| 133 | 165 |
| 134 TEST_F(RTCVideoDecoderTest, CreateAndInitSucceedsForH264Codec) { | 166 TEST_P(RTCVideoDecoderTest, CreateAndInitSucceeds) { |
| 135 CreateDecoder(webrtc::kVideoCodecH264); | 167 const webrtc::VideoCodecType codec_type = GetParam(); |
| 168 CreateDecoder(codec_type); | |
| 136 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->InitDecode(&codec_, 1)); | 169 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->InitDecode(&codec_, 1)); |
| 137 } | 170 } |
| 138 | 171 |
| 139 TEST_F(RTCVideoDecoderTest, InitDecodeReturnsErrorOnFeedbackMode) { | 172 TEST_F(RTCVideoDecoderTest, InitDecodeReturnsErrorOnFeedbackMode) { |
| 140 CreateDecoder(webrtc::kVideoCodecVP8); | 173 CreateDecoder(webrtc::kVideoCodecVP8); |
| 141 codec_.codecSpecific.VP8.feedbackModeOn = true; | 174 codec_.codecSpecific.VP8.feedbackModeOn = true; |
| 142 EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR, rtc_decoder_->InitDecode(&codec_, 1)); | 175 EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR, rtc_decoder_->InitDecode(&codec_, 1)); |
| 143 } | 176 } |
| 144 | 177 |
| 145 TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorWithoutInitDecode) { | 178 TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorWithoutInitDecode) { |
| 146 CreateDecoder(webrtc::kVideoCodecVP8); | 179 CreateDecoder(webrtc::kVideoCodecVP8); |
| 147 webrtc::EncodedImage input_image; | 180 webrtc::EncodedImage input_image; |
| 148 EXPECT_EQ(WEBRTC_VIDEO_CODEC_UNINITIALIZED, | 181 EXPECT_EQ(WEBRTC_VIDEO_CODEC_UNINITIALIZED, |
| 149 rtc_decoder_->Decode(input_image, false, NULL, NULL, 0)); | 182 rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0)); |
| 150 } | 183 } |
| 151 | 184 |
| 152 TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnIncompleteFrame) { | 185 TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnIncompleteFrame) { |
| 153 CreateDecoder(webrtc::kVideoCodecVP8); | 186 CreateDecoder(webrtc::kVideoCodecVP8); |
| 154 Initialize(); | 187 Initialize(); |
| 155 webrtc::EncodedImage input_image; | 188 webrtc::EncodedImage input_image; |
| 156 input_image._completeFrame = false; | 189 input_image._completeFrame = false; |
| 157 EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR, | 190 EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR, |
| 158 rtc_decoder_->Decode(input_image, false, NULL, NULL, 0)); | 191 rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0)); |
| 159 } | 192 } |
| 160 | 193 |
| 161 TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnMissingFrames) { | 194 TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnMissingFrames) { |
| 162 CreateDecoder(webrtc::kVideoCodecVP8); | 195 CreateDecoder(webrtc::kVideoCodecVP8); |
| 163 Initialize(); | 196 Initialize(); |
| 164 webrtc::EncodedImage input_image; | 197 webrtc::EncodedImage input_image; |
| 165 input_image._completeFrame = true; | 198 input_image._completeFrame = true; |
| 166 bool missingFrames = true; | 199 bool missingFrames = true; |
| 167 EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR, | 200 EXPECT_EQ( |
| 168 rtc_decoder_->Decode(input_image, missingFrames, NULL, NULL, 0)); | 201 WEBRTC_VIDEO_CODEC_ERROR, |
| 202 rtc_decoder_->Decode(input_image, missingFrames, nullptr, nullptr, 0)); | |
| 169 } | 203 } |
| 170 | 204 |
| 171 TEST_F(RTCVideoDecoderTest, ReleaseReturnsOk) { | 205 TEST_F(RTCVideoDecoderTest, ReleaseReturnsOk) { |
| 172 CreateDecoder(webrtc::kVideoCodecVP8); | 206 CreateDecoder(webrtc::kVideoCodecVP8); |
| 173 Initialize(); | 207 Initialize(); |
| 174 EXPECT_CALL(*mock_vda_, Reset()) | 208 EXPECT_CALL(*mock_vda_, Reset()) |
| 175 .WillOnce(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone)); | 209 .WillOnce(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone)); |
| 176 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Release()); | 210 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Release()); |
| 177 } | 211 } |
| 178 | 212 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 230 RTCVideoDecoder::ID_HALF + 2, RTCVideoDecoder::ID_HALF)); | 264 RTCVideoDecoder::ID_HALF + 2, RTCVideoDecoder::ID_HALF)); |
| 231 | 265 |
| 232 EXPECT_FALSE(rtc_decoder_->IsFirstBufferAfterReset(RTCVideoDecoder::ID_LAST, | 266 EXPECT_FALSE(rtc_decoder_->IsFirstBufferAfterReset(RTCVideoDecoder::ID_LAST, |
| 233 RTCVideoDecoder::ID_LAST)); | 267 RTCVideoDecoder::ID_LAST)); |
| 234 EXPECT_TRUE( | 268 EXPECT_TRUE( |
| 235 rtc_decoder_->IsFirstBufferAfterReset(0, RTCVideoDecoder::ID_LAST)); | 269 rtc_decoder_->IsFirstBufferAfterReset(0, RTCVideoDecoder::ID_LAST)); |
| 236 EXPECT_FALSE( | 270 EXPECT_FALSE( |
| 237 rtc_decoder_->IsFirstBufferAfterReset(1, RTCVideoDecoder::ID_LAST)); | 271 rtc_decoder_->IsFirstBufferAfterReset(1, RTCVideoDecoder::ID_LAST)); |
| 238 } | 272 } |
| 239 | 273 |
| 274 | |
| 275 TEST_P(RTCVideoDecoderTest, DecodeResetsAfterError) { | |
| 276 const webrtc::VideoCodecType codec_type = GetParam(); | |
| 277 CreateDecoder(codec_type); | |
| 278 Initialize(); | |
| 279 | |
| 280 webrtc::EncodedImage input_image; | |
| 281 input_image._completeFrame = true; | |
| 282 input_image._encodedWidth = kMinResolutionWidth; | |
| 283 input_image._encodedHeight = kMaxResolutionHeight; | |
| 284 input_image._frameType = webrtc::kVideoFrameDelta; | |
| 285 EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR, | |
| 286 rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0)); | |
| 287 RunUntilIdle(); | |
| 288 | |
| 289 // Notify the decoder about a platform error. | |
| 290 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); | |
| 291 RunUntilIdle(); | |
| 292 | |
| 293 // Expect decode call to reset decoder, and set up a new VDA to track it. | |
| 294 SetUpResetVDA(); | |
| 295 EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR, | |
| 296 rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0)); | |
| 297 } | |
| 298 | |
| 299 INSTANTIATE_TEST_CASE_P(CodecProfiles, | |
| 300 RTCVideoDecoderTest, | |
| 301 Values(webrtc::kVideoCodecVP8, | |
| 302 webrtc::kVideoCodecH264)); | |
| 303 | |
| 240 } // content | 304 } // content |
| OLD | NEW |