OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 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.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/gpu_video_decoder.h" |
| 12 #include "media/filters/mock_gpu_video_decoder_factories.h" |
| 13 #include "media/video/mock_video_decode_accelerator.h" |
| 14 #include "testing/gtest/include/gtest/gtest.h" |
| 15 |
| 16 using ::testing::_; |
| 17 using ::testing::Invoke; |
| 18 using ::testing::Return; |
| 19 using ::testing::SaveArg; |
| 20 using ::testing::WithArgs; |
| 21 |
| 22 namespace content { |
| 23 |
| 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_, |
| 41 CreateVideoDecodeAccelerator(media::VP8PROFILE_MAIN, _)) |
| 42 .WillOnce(Return(mock_vda_)); |
| 43 EXPECT_CALL(*mock_gpu_factories_, Abort()).WillRepeatedly(Return()); |
| 44 EXPECT_CALL(*mock_gpu_factories_, CreateSharedMemory(_)) |
| 45 .WillRepeatedly(Return(static_cast<base::SharedMemory*>(NULL))); |
| 46 EXPECT_CALL(*mock_vda_, Destroy()); |
| 47 rtc_decoder_ = RTCVideoDecoder::Create(mock_gpu_factories_); |
| 48 } |
| 49 |
| 50 virtual void TearDown() OVERRIDE { |
| 51 VLOG(2) << "TearDown"; |
| 52 if (vda_thread_.IsRunning()) { |
| 53 RunUntilIdle(); // Wait until all callbascks complete. |
| 54 vda_loop_proxy_->DeleteSoon(FROM_HERE, rtc_decoder_.release()); |
| 55 // Make sure the decoder is released before stopping the thread. |
| 56 RunUntilIdle(); |
| 57 vda_thread_.Stop(); |
| 58 } else { |
| 59 rtc_decoder_.reset(); |
| 60 } |
| 61 } |
| 62 |
| 63 virtual int32_t Decoded(webrtc::I420VideoFrame& decoded_image) OVERRIDE { |
| 64 VLOG(2) << "Decoded"; |
| 65 EXPECT_EQ(vda_loop_proxy_, base::MessageLoopProxy::current()); |
| 66 return WEBRTC_VIDEO_CODEC_OK; |
| 67 } |
| 68 |
| 69 void Initialize() { |
| 70 VLOG(2) << "Initialize"; |
| 71 codec_.codecType = webrtc::kVideoCodecVP8; |
| 72 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->InitDecode(&codec_, 1)); |
| 73 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, |
| 74 rtc_decoder_->RegisterDecodeCompleteCallback(this)); |
| 75 } |
| 76 |
| 77 void NotifyResetDone() { |
| 78 VLOG(2) << "NotifyResetDone"; |
| 79 vda_loop_proxy_->PostTask(FROM_HERE, |
| 80 base::Bind(&RTCVideoDecoder::NotifyResetDone, |
| 81 base::Unretained(rtc_decoder_.get()))); |
| 82 } |
| 83 |
| 84 void RunUntilIdle() { |
| 85 VLOG(2) << "RunUntilIdle"; |
| 86 vda_loop_proxy_->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::MockGpuVideoDecoderFactories> 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::MessageLoopProxy> vda_loop_proxy_; |
| 101 |
| 102 base::Lock lock_; |
| 103 base::WaitableEvent idle_waiter_; |
| 104 }; |
| 105 |
| 106 TEST_F(RTCVideoDecoderTest, InitDecodeReturnsErrorOnFeedbackMode) { |
| 107 codec_.codecType = webrtc::kVideoCodecVP8; |
| 108 codec_.codecSpecific.VP8.feedbackModeOn = true; |
| 109 EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR, rtc_decoder_->InitDecode(&codec_, 1)); |
| 110 } |
| 111 |
| 112 TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorWithoutInitDecode) { |
| 113 webrtc::EncodedImage input_image; |
| 114 EXPECT_EQ(WEBRTC_VIDEO_CODEC_UNINITIALIZED, |
| 115 rtc_decoder_->Decode(input_image, false, NULL, NULL, 0)); |
| 116 } |
| 117 |
| 118 TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnIncompleteFrame) { |
| 119 Initialize(); |
| 120 webrtc::EncodedImage input_image; |
| 121 input_image._completeFrame = false; |
| 122 EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR, |
| 123 rtc_decoder_->Decode(input_image, false, NULL, NULL, 0)); |
| 124 } |
| 125 |
| 126 TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnMissingFrames) { |
| 127 Initialize(); |
| 128 webrtc::EncodedImage input_image; |
| 129 input_image._completeFrame = true; |
| 130 bool missingFrames = true; |
| 131 EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR, |
| 132 rtc_decoder_->Decode(input_image, missingFrames, NULL, NULL, 0)); |
| 133 } |
| 134 |
| 135 TEST_F(RTCVideoDecoderTest, ResetReturnsOk) { |
| 136 Initialize(); |
| 137 EXPECT_CALL(*mock_vda_, Reset()) |
| 138 .WillOnce(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone)); |
| 139 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Reset()); |
| 140 } |
| 141 |
| 142 TEST_F(RTCVideoDecoderTest, ReleaseReturnsOk) { |
| 143 Initialize(); |
| 144 EXPECT_CALL(*mock_vda_, Reset()) |
| 145 .WillOnce(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone)); |
| 146 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Release()); |
| 147 } |
| 148 |
| 149 TEST_F(RTCVideoDecoderTest, VdaThreadStops) { vda_thread_.Stop(); } |
| 150 |
| 151 TEST_F(RTCVideoDecoderTest, IsBufferAfterReset) { |
| 152 EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(0, RTCVideoDecoder::ID_INVALID)); |
| 153 EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST, |
| 154 RTCVideoDecoder::ID_INVALID)); |
| 155 EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_HALF - 2, |
| 156 RTCVideoDecoder::ID_HALF + 2)); |
| 157 EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_HALF + 2, |
| 158 RTCVideoDecoder::ID_HALF - 2)); |
| 159 |
| 160 EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(0, 0)); |
| 161 EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(0, RTCVideoDecoder::ID_LAST)); |
| 162 EXPECT_FALSE( |
| 163 rtc_decoder_->IsBufferAfterReset(0, RTCVideoDecoder::ID_HALF - 2)); |
| 164 EXPECT_TRUE( |
| 165 rtc_decoder_->IsBufferAfterReset(0, RTCVideoDecoder::ID_HALF + 2)); |
| 166 |
| 167 EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST, 0)); |
| 168 EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST, |
| 169 RTCVideoDecoder::ID_HALF - 2)); |
| 170 EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST, |
| 171 RTCVideoDecoder::ID_HALF + 2)); |
| 172 EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST, |
| 173 RTCVideoDecoder::ID_LAST)); |
| 174 } |
| 175 |
| 176 } // content |
OLD | NEW |