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_TRUE(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_TRUE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST, | |
Ami GONE FROM CHROMIUM
2013/07/02 23:36:57
For this and l.160 what does it mean that id X is
wuchengli
2013/07/03 09:09:38
Right. It's a little bit confusing. I changed the
| |
173 RTCVideoDecoder::ID_LAST)); | |
174 } | |
175 | |
176 } // content | |
OLD | NEW |