OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2012 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 "content/renderer/media/rtc_video_decoder.h" | |
6 | |
7 #include <deque> | |
8 | |
9 #include "base/bind.h" | |
10 #include "base/memory/singleton.h" | |
11 #include "base/message_loop.h" | |
12 #include "base/string_util.h" | |
13 #include "media/base/data_buffer.h" | |
14 #include "media/base/limits.h" | |
15 #include "media/base/mock_filters.h" | |
16 #include "media/base/test_helpers.h" | |
17 #include "media/base/video_frame.h" | |
18 #include "testing/gtest/include/gtest/gtest.h" | |
19 #include "third_party/libjingle/source/talk/media/base/videoframe.h" | |
20 | |
21 using ::testing::_; | |
22 using ::testing::AnyNumber; | |
23 using ::testing::DoAll; | |
24 using ::testing::Message; | |
25 using ::testing::Return; | |
26 using ::testing::ReturnNull; | |
27 using ::testing::SetArgumentPointee; | |
28 using ::testing::StrictMock; | |
29 using ::testing::WithArg; | |
30 using ::testing::Invoke; | |
31 using media::MockStatisticsCB; | |
32 using media::MockVideoRenderer; | |
33 using media::NewExpectedClosure; | |
34 using media::NewExpectedStatusCB; | |
35 using media::PipelineStatistics; | |
36 using media::PIPELINE_OK; | |
37 using media::StatisticsCB; | |
38 | |
39 namespace content { | |
40 namespace { | |
41 | |
42 class NullVideoFrame : public cricket::VideoFrame { | |
43 public: | |
44 NullVideoFrame() {} | |
45 virtual ~NullVideoFrame() {} | |
46 | |
47 virtual bool Reset(uint32 fourcc, int w, int h, int dw, int dh, | |
48 uint8 *sample, size_t sample_size, | |
49 size_t pixel_width, size_t pixel_height, | |
50 int64 elapsed_time, int64 time_stamp, int rotation) | |
51 OVERRIDE { | |
52 return true; | |
53 } | |
54 | |
55 virtual size_t GetWidth() const OVERRIDE { return 0; } | |
56 virtual size_t GetHeight() const OVERRIDE { return 0; } | |
57 virtual const uint8 *GetYPlane() const OVERRIDE { return NULL; } | |
58 virtual const uint8 *GetUPlane() const OVERRIDE { return NULL; } | |
59 virtual const uint8 *GetVPlane() const OVERRIDE { return NULL; } | |
60 virtual uint8 *GetYPlane() OVERRIDE { return NULL; } | |
61 virtual uint8 *GetUPlane() OVERRIDE { return NULL; } | |
62 virtual uint8 *GetVPlane() OVERRIDE { return NULL; } | |
63 virtual int32 GetYPitch() const OVERRIDE { return 0; } | |
64 virtual int32 GetUPitch() const OVERRIDE { return 0; } | |
65 virtual int32 GetVPitch() const OVERRIDE { return 0; } | |
66 | |
67 virtual size_t GetPixelWidth() const OVERRIDE { return 1; } | |
68 virtual size_t GetPixelHeight() const OVERRIDE { return 1; } | |
69 virtual int64 GetElapsedTime() const OVERRIDE { return 0; } | |
70 virtual int64 GetTimeStamp() const OVERRIDE { return 0; } | |
71 virtual void SetElapsedTime(int64 elapsed_time) OVERRIDE {} | |
72 virtual void SetTimeStamp(int64 time_stamp) OVERRIDE {} | |
73 | |
74 virtual int GetRotation() const OVERRIDE { return 0; } | |
75 | |
76 virtual VideoFrame *Copy() const OVERRIDE { return NULL; } | |
77 | |
78 virtual bool MakeExclusive() OVERRIDE { return true; } | |
79 | |
80 virtual size_t CopyToBuffer(uint8 *buffer, size_t size) const OVERRIDE { | |
81 return 0; | |
82 } | |
83 | |
84 virtual size_t ConvertToRgbBuffer(uint32 to_fourcc, uint8 *buffer, | |
85 size_t size, | |
86 int stride_rgb) const OVERRIDE { | |
87 return 0; | |
88 } | |
89 | |
90 virtual void StretchToPlanes(uint8 *y, uint8 *u, uint8 *v, | |
91 int32 pitchY, int32 pitchU, int32 pitchV, | |
92 size_t width, size_t height, | |
93 bool interpolate, bool crop) const OVERRIDE { | |
94 } | |
95 | |
96 virtual size_t StretchToBuffer(size_t w, size_t h, uint8 *buffer, size_t size, | |
97 bool interpolate, bool crop) const OVERRIDE { | |
98 return 0; | |
99 } | |
100 | |
101 virtual void StretchToFrame(VideoFrame *target, bool interpolate, | |
102 bool crop) const OVERRIDE { | |
103 } | |
104 | |
105 virtual VideoFrame *Stretch(size_t w, size_t h, bool interpolate, | |
106 bool crop) const OVERRIDE { | |
107 return NULL; | |
108 } | |
109 | |
110 protected: | |
111 virtual VideoFrame* CreateEmptyFrame(int w, int h, | |
112 size_t pixel_width, size_t pixel_height, | |
113 int64 elapsed_time, | |
114 int64 time_stamp) const OVERRIDE { | |
115 return NULL; | |
116 } | |
117 }; | |
118 | |
119 class MockVideoTrack : public webrtc::VideoTrackInterface { | |
120 public: | |
121 static MockVideoTrack* Create() { | |
122 return new talk_base::RefCountedObject<MockVideoTrack>(); | |
123 } | |
124 | |
125 virtual std::string kind() const OVERRIDE { | |
126 NOTIMPLEMENTED(); | |
127 return ""; | |
128 } | |
129 virtual std::string id() const OVERRIDE { | |
130 NOTIMPLEMENTED(); | |
131 return ""; | |
132 } | |
133 virtual bool enabled() const OVERRIDE { | |
134 NOTIMPLEMENTED(); | |
135 return false; | |
136 } | |
137 virtual TrackState state() const OVERRIDE { | |
138 NOTIMPLEMENTED(); | |
139 return kEnded; | |
140 } | |
141 virtual bool set_enabled(bool enable) OVERRIDE { | |
142 NOTIMPLEMENTED(); | |
143 return false; | |
144 } | |
145 virtual bool set_state(TrackState new_state) OVERRIDE { | |
146 NOTIMPLEMENTED(); | |
147 return false; | |
148 } | |
149 virtual void RegisterObserver(webrtc::ObserverInterface* observer) OVERRIDE { | |
150 NOTIMPLEMENTED(); | |
151 } | |
152 virtual void UnregisterObserver( | |
153 webrtc::ObserverInterface* observer) OVERRIDE { | |
154 NOTIMPLEMENTED(); | |
155 } | |
156 virtual webrtc::VideoSourceInterface* GetSource() const OVERRIDE { | |
157 NOTIMPLEMENTED(); | |
158 return NULL; | |
159 } | |
160 MOCK_METHOD1(AddRenderer, void(webrtc::VideoRendererInterface* renderer)); | |
161 MOCK_METHOD1(RemoveRenderer, void(webrtc::VideoRendererInterface* renderer)); | |
162 | |
163 virtual cricket::VideoRenderer* FrameInput() OVERRIDE { | |
164 NOTIMPLEMENTED(); | |
165 return NULL; | |
166 } | |
167 | |
168 protected: | |
169 MockVideoTrack() {} | |
170 ~MockVideoTrack() {} | |
171 }; | |
172 | |
173 } // namespace | |
174 | |
175 class RTCVideoDecoderTest : public testing::Test { | |
Ami GONE FROM CHROMIUM
2013/02/26 23:16:55
I guess now'd be a good time to inspect the test c
wuchengli
2013/02/27 01:45:41
I'm not familiar with svn. How to get the latest s
wuchengli
2013/02/27 02:28:43
So the revision is 180591. Right?
I forgot to say
| |
176 protected: | |
177 static const int kWidth; | |
178 static const int kHeight; | |
179 static const PipelineStatistics kStatistics; | |
180 | |
181 RTCVideoDecoderTest() { | |
182 } | |
183 | |
184 virtual ~RTCVideoDecoderTest() { | |
185 } | |
186 | |
187 virtual void SetUp() OVERRIDE { | |
188 video_track_ = MockVideoTrack::Create(); | |
189 decoder_ = new RTCVideoDecoder(message_loop_.message_loop_proxy(), | |
190 message_loop_.message_loop_proxy(), | |
191 video_track_); | |
192 read_cb_ = base::Bind(&RTCVideoDecoderTest::FrameReady, | |
193 base::Unretained(this)); | |
194 | |
195 DCHECK(decoder_); | |
196 | |
197 EXPECT_CALL(statistics_cb_, OnStatistics(_)) | |
198 .Times(AnyNumber()); | |
199 } | |
200 | |
201 virtual void TearDown() OVERRIDE { | |
202 if (decoder_->state_ == RTCVideoDecoder::kStopped) | |
203 return; | |
204 Stop(); | |
205 } | |
206 | |
207 void InitializeDecoderSuccessfully() { | |
208 EXPECT_CALL(*video_track_, AddRenderer(decoder_.get())); | |
209 // Test successful initialization. | |
210 decoder_->Initialize( | |
211 NULL, NewExpectedStatusCB(PIPELINE_OK), NewStatisticsCB()); | |
212 message_loop_.RunUntilIdle(); | |
213 } | |
214 | |
215 void Stop() { | |
216 EXPECT_CALL(*video_track_, RemoveRenderer(decoder_.get())); | |
217 decoder_->Stop(media::NewExpectedClosure()); | |
218 | |
219 message_loop_.RunUntilIdle(); | |
220 EXPECT_EQ(RTCVideoDecoder::kStopped, decoder_->state_); | |
221 } | |
222 | |
223 StatisticsCB NewStatisticsCB() { | |
224 return base::Bind(&MockStatisticsCB::OnStatistics, | |
225 base::Unretained(&statistics_cb_)); | |
226 } | |
227 | |
228 void RenderFrame() { | |
229 NullVideoFrame video_frame; | |
230 decoder_->RenderFrame(&video_frame); | |
231 } | |
232 | |
233 MOCK_METHOD2(FrameReady, void(media::VideoDecoder::Status status, | |
234 const scoped_refptr<media::VideoFrame>&)); | |
235 | |
236 // Fixture members. | |
237 scoped_refptr<MockVideoTrack> video_track_; | |
238 scoped_refptr<RTCVideoDecoder> decoder_; | |
239 MockStatisticsCB statistics_cb_; | |
240 MessageLoop message_loop_; | |
241 media::VideoDecoder::ReadCB read_cb_; | |
242 | |
243 private: | |
244 DISALLOW_COPY_AND_ASSIGN(RTCVideoDecoderTest); | |
245 }; | |
246 | |
247 const int RTCVideoDecoderTest::kWidth = 640; | |
248 const int RTCVideoDecoderTest::kHeight = 480; | |
249 const PipelineStatistics RTCVideoDecoderTest::kStatistics; | |
250 | |
251 MATCHER_P2(HasSize, width, height, "") { | |
252 EXPECT_EQ(arg->coded_size().width(), width); | |
253 EXPECT_EQ(arg->coded_size().height(), height); | |
254 EXPECT_EQ(arg->visible_rect().x(), 0); | |
255 EXPECT_EQ(arg->visible_rect().y(), 0); | |
256 EXPECT_EQ(arg->visible_rect().width(), width); | |
257 EXPECT_EQ(arg->visible_rect().height(), height); | |
258 EXPECT_EQ(arg->natural_size().width(), width); | |
259 EXPECT_EQ(arg->natural_size().height(), height); | |
260 return (arg->coded_size().width() == width) && | |
261 (arg->coded_size().height() == height) && | |
262 (arg->visible_rect().x() == 0) && | |
263 (arg->visible_rect().y() == 0) && | |
264 (arg->visible_rect().width() == width) && | |
265 (arg->visible_rect().height() == height) && | |
266 (arg->natural_size().width() == width) && | |
267 (arg->natural_size().height() == height); | |
268 } | |
269 | |
270 TEST_F(RTCVideoDecoderTest, Initialize_Successful) { | |
271 InitializeDecoderSuccessfully(); | |
272 | |
273 EXPECT_CALL(*this, FrameReady(media::VideoDecoder::kOk, | |
274 HasSize(kWidth, kHeight))); | |
275 decoder_->Read(read_cb_); | |
276 RenderFrame(); | |
277 } | |
278 | |
279 TEST_F(RTCVideoDecoderTest, DoReset) { | |
280 InitializeDecoderSuccessfully(); | |
281 | |
282 EXPECT_CALL(*this, FrameReady(media::VideoDecoder::kOk, | |
283 scoped_refptr<media::VideoFrame>())); | |
284 decoder_->Read(read_cb_); | |
285 decoder_->Reset(media::NewExpectedClosure()); | |
286 | |
287 message_loop_.RunUntilIdle(); | |
288 EXPECT_EQ(RTCVideoDecoder::kNormal, decoder_->state_); | |
289 } | |
290 | |
291 TEST_F(RTCVideoDecoderTest, DoRenderFrame) { | |
292 InitializeDecoderSuccessfully(); | |
293 | |
294 for (size_t i = 0; i < media::limits::kMaxVideoFrames; ++i) | |
295 RenderFrame(); | |
296 | |
297 message_loop_.RunUntilIdle(); | |
298 EXPECT_EQ(RTCVideoDecoder::kNormal, decoder_->state_); | |
299 } | |
300 | |
301 TEST_F(RTCVideoDecoderTest, DoSetSize) { | |
302 InitializeDecoderSuccessfully(); | |
303 | |
304 EXPECT_CALL(*this, FrameReady(media::VideoDecoder::kOk, | |
305 HasSize(kWidth, kHeight))); | |
306 decoder_->Read(read_cb_); | |
307 RenderFrame(); | |
308 message_loop_.RunUntilIdle(); | |
309 | |
310 int new_width = kWidth * 2; | |
311 int new_height = kHeight * 2; | |
312 decoder_->SetSize(new_width, new_height); | |
313 | |
314 EXPECT_CALL(*this, FrameReady(media::VideoDecoder::kOk, | |
315 HasSize(new_width, new_height))); | |
316 decoder_->Read(read_cb_); | |
317 RenderFrame(); | |
318 message_loop_.RunUntilIdle(); | |
319 } | |
320 | |
321 TEST_F(RTCVideoDecoderTest, ReadAndShutdown) { | |
322 // Test all the Read requests can be fullfilled (which is needed in order to | |
323 // teardown the pipeline) even when there's no input frame. | |
324 InitializeDecoderSuccessfully(); | |
325 | |
326 EXPECT_CALL(*this, FrameReady(media::VideoDecoder::kOk, | |
327 scoped_refptr<media::VideoFrame>())); | |
328 decoder_->Read(read_cb_); | |
329 Stop(); | |
330 | |
331 // Any read after stopping should be immediately satisfied. | |
332 EXPECT_CALL(*this, FrameReady(media::VideoDecoder::kOk, | |
333 scoped_refptr<media::VideoFrame>())); | |
334 decoder_->Read(read_cb_); | |
335 message_loop_.RunUntilIdle(); | |
336 } | |
337 | |
338 } // namespace content | |
OLD | NEW |