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/synchronization/waitable_event.h" | |
6 #include "base/task_runner_util.h" | |
7 #include "content/renderer/media/mock_media_stream_dependency_factory.h" | |
8 #include "content/renderer/media/rtc_video_decoder_bridge_tv.h" | |
9 #include "media/base/decoder_buffer.h" | |
10 #include "testing/gmock/include/gmock/gmock.h" | |
11 #include "testing/gtest/include/gtest/gtest.h" | |
12 #include "third_party/webrtc/modules/video_coding/codecs/interface/mock/mock_vid eo_codec_interface.h" | |
13 | |
14 using ::testing::_; | |
15 using ::testing::Return; | |
16 | |
17 namespace content { | |
18 | |
19 class RTCVideoDecoderBridgeTvTest : public ::testing::Test { | |
20 public: | |
21 RTCVideoDecoderBridgeTvTest() | |
22 : bridge_(RTCVideoDecoderBridgeTv::Get()), | |
23 demuxer_(NULL), | |
24 video_stream_(NULL), | |
25 size_(1280, 720), | |
26 input_image_(&data_, sizeof(data_), sizeof(data_)), | |
27 data_('a'), | |
28 read_event_(false, false), | |
29 decoder_thread_("Test decoeder thread"), | |
30 decoder_thread_event_(false, false) {} | |
31 | |
32 void ReadCallback(media::DemuxerStream::Status status, | |
Ami GONE FROM CHROMIUM
2013/05/08 20:26:44
intentionally ignoring |status|?
wonsik
2013/05/14 12:53:57
Added some sanity checks.
| |
33 const scoped_refptr<media::DecoderBuffer>& decoder_buffer) { | |
34 last_decoder_buffer_ = decoder_buffer; | |
35 read_event_.Signal(); | |
36 } | |
37 | |
38 void ExpectEqualsAndSignal(int32_t expected_result, int32_t actual_result) { | |
Ami GONE FROM CHROMIUM
2013/05/08 20:26:44
s/_result//g
Ami GONE FROM CHROMIUM
2013/05/08 20:26:44
s/_t//g
wonsik
2013/05/14 12:53:57
Done.
wonsik
2013/05/14 12:53:57
Well they are from the definition of webrtc::Video
| |
39 EXPECT_EQ(expected_result, actual_result); | |
40 decoder_thread_event_.Signal(); | |
41 } | |
42 | |
43 void ExpectNotEqualsAndSignal(int32_t unexpected_result, | |
44 int32_t actual_result) { | |
45 EXPECT_NE(unexpected_result, actual_result); | |
46 decoder_thread_event_.Signal(); | |
47 } | |
48 | |
49 protected: | |
50 virtual void SetUp() OVERRIDE { | |
51 memset(&codec_, 0, sizeof(codec_)); | |
52 message_loop_proxy_ = base::MessageLoopProxy::current(); | |
53 input_image_._frameType = webrtc::kKeyFrame; | |
54 input_image_._encodedWidth = size_.width(); | |
55 input_image_._encodedHeight = size_.height(); | |
56 input_image_._completeFrame = true; | |
57 decoder_thread_.Start(); | |
58 } | |
59 | |
60 virtual void TearDown() OVERRIDE { | |
61 if (demuxer_) { | |
62 bridge_->ReleaseOwnership(&owner_factory_); | |
63 bridge_->DestroyDemuxer(demuxer_); | |
64 } | |
65 decoder_thread_.Stop(); | |
66 } | |
67 | |
68 base::Callback<void(int32_t)> BindExpectEquals( | |
69 int32_t expected_result) { | |
70 return base::Bind(&RTCVideoDecoderBridgeTvTest::ExpectEqualsAndSignal, | |
71 base::Unretained(this), | |
72 expected_result); | |
73 } | |
74 | |
75 base::Callback<void(int32_t)> BindExpectNotEquals( | |
76 int32_t unexpected_result) { | |
77 return base::Bind(&RTCVideoDecoderBridgeTvTest::ExpectNotEqualsAndSignal, | |
78 base::Unretained(this), | |
79 unexpected_result); | |
80 } | |
81 | |
82 base::Callback<int32_t(void)> BindInitDecode( | |
83 const webrtc::VideoCodec* codec, | |
84 int32_t num_cores) { | |
85 return base::Bind(&RTCVideoDecoderBridgeTv::InitDecode, | |
86 base::Unretained(bridge_), | |
87 codec, | |
88 num_cores); | |
89 } | |
90 | |
91 base::Callback<int32_t(void)> BindDecode( | |
92 const webrtc::EncodedImage& input_image, | |
93 bool missing_frames, | |
94 const webrtc::RTPFragmentationHeader* fragmentation, | |
95 const webrtc::CodecSpecificInfo* info = NULL, | |
96 int64_t render_time_ms = -1) { | |
97 return base::Bind(&RTCVideoDecoderBridgeTv::Decode, | |
98 base::Unretained(bridge_), | |
99 input_image, | |
100 missing_frames, | |
101 fragmentation, | |
102 info, | |
103 render_time_ms); | |
104 } | |
105 | |
106 void AcquireOwnershipAndCreateDemuxer() { | |
107 bridge_->AcquireOwnership(&owner_factory_); | |
Ami GONE FROM CHROMIUM
2013/05/08 20:26:44
What if this fails?
(I'd say CHECK the return valu
wonsik
2013/05/14 12:53:57
Done.
| |
108 demuxer_ = bridge_->CreateDemuxer(&owner_factory_, message_loop_proxy_); | |
109 } | |
110 | |
111 void InitDecode() { | |
112 codec_.codecType = webrtc::kVideoCodecVP8; | |
113 codec_.width = size_.width(); | |
114 codec_.height = size_.height(); | |
115 base::PostTaskAndReplyWithResult( | |
116 decoder_thread_.message_loop_proxy(), | |
117 FROM_HERE, | |
118 BindInitDecode(&codec_, 1), | |
119 BindExpectEquals(WEBRTC_VIDEO_CODEC_OK)); | |
120 decoder_thread_event_.Wait(); | |
Ami GONE FROM CHROMIUM
2013/05/08 20:26:44
here and elsewhere, if expectations have already f
wonsik
2013/05/14 12:53:57
Done.
| |
121 base::PostTaskAndReplyWithResult( | |
122 decoder_thread_.message_loop_proxy(), | |
123 FROM_HERE, | |
124 base::Bind(&RTCVideoDecoderBridgeTv::RegisterDecodeCompleteCallback, | |
125 base::Unretained(bridge_), | |
126 &decode_complete_callback_), | |
127 BindExpectEquals(WEBRTC_VIDEO_CODEC_OK)); | |
128 decoder_thread_event_.Wait(); | |
129 } | |
130 | |
131 void GetVideoStream() { | |
132 video_stream_ = demuxer_->GetStream(media::DemuxerStream::VIDEO); | |
133 EXPECT_NE(static_cast<media::DemuxerStream*>(NULL), video_stream_); | |
134 EXPECT_EQ(media::kCodecVP8, video_stream_->video_decoder_config().codec()); | |
135 EXPECT_EQ(size_, video_stream_->video_decoder_config().coded_size()); | |
136 EXPECT_EQ(gfx::Rect(size_), | |
137 video_stream_->video_decoder_config().visible_rect()); | |
138 EXPECT_EQ(size_, video_stream_->video_decoder_config().natural_size()); | |
Ami GONE FROM CHROMIUM
2013/05/08 20:26:44
This would be a fantastic place to test support fo
| |
139 } | |
140 | |
141 void PostDecodeAndWait(int32_t expected_result, | |
142 const webrtc::EncodedImage& input_image, | |
143 bool missing_frames, | |
144 const webrtc::RTPFragmentationHeader* fragmentation, | |
145 const webrtc::CodecSpecificInfo* info = NULL, | |
146 int64_t render_time_ms = -1) { | |
147 base::PostTaskAndReplyWithResult( | |
148 decoder_thread_.message_loop_proxy(), | |
149 FROM_HERE, | |
150 BindDecode( | |
151 input_image, missing_frames, fragmentation, info, render_time_ms), | |
152 BindExpectEquals(expected_result)); | |
153 decoder_thread_event_.Wait(); | |
154 } | |
155 | |
156 RTCVideoDecoderBridgeTv* bridge_; | |
157 MockMediaStreamDependencyFactory owner_factory_; | |
158 MockMediaStreamDependencyFactory non_owner_factory_; | |
159 base::MessageLoopProxy* message_loop_proxy_; | |
160 media::Demuxer* demuxer_; | |
161 media::DemuxerStream* video_stream_; | |
162 webrtc::VideoCodec codec_; | |
163 gfx::Size size_; | |
164 webrtc::EncodedImage input_image_; | |
165 unsigned char data_; | |
166 webrtc::MockDecodedImageCallback decode_complete_callback_; | |
167 base::WaitableEvent read_event_; | |
168 base::Thread decoder_thread_; | |
169 base::WaitableEvent decoder_thread_event_; | |
170 scoped_refptr<media::DecoderBuffer> last_decoder_buffer_; | |
171 }; | |
172 | |
173 TEST_F(RTCVideoDecoderBridgeTvTest, AcquireAndReleaseOwnership) { | |
174 EXPECT_TRUE(bridge_->AcquireOwnership(&owner_factory_)); | |
175 EXPECT_FALSE(bridge_->AcquireOwnership(&non_owner_factory_)); | |
176 bridge_->ReleaseOwnership(&owner_factory_); | |
177 } | |
178 | |
179 TEST_F(RTCVideoDecoderBridgeTvTest, CreateDemuxerAfterAcquireOwnership) { | |
180 EXPECT_TRUE(bridge_->AcquireOwnership(&owner_factory_)); | |
181 EXPECT_EQ(static_cast<media::Demuxer*>(NULL), | |
Ami GONE FROM CHROMIUM
2013/05/08 20:26:44
FWIW, here and elsewhere, instead of static_cast<L
wonsik
2013/05/14 12:53:57
Done.
| |
182 bridge_->CreateDemuxer(&non_owner_factory_, message_loop_proxy_)); | |
183 demuxer_ = bridge_->CreateDemuxer(&owner_factory_, message_loop_proxy_); | |
184 EXPECT_NE(static_cast<media::Demuxer*>(NULL), demuxer_); | |
185 } | |
186 | |
187 TEST_F(RTCVideoDecoderBridgeTvTest, CreateDemuxerBeforeAcquireOwnership) { | |
188 RTCVideoDecoderBridgeTv* bridge_ = RTCVideoDecoderBridgeTv::Get(); | |
189 demuxer_ = bridge_->CreateDemuxer(&owner_factory_, message_loop_proxy_); | |
190 EXPECT_NE(static_cast<media::Demuxer*>(NULL), demuxer_); | |
191 EXPECT_EQ(static_cast<media::Demuxer*>(NULL), | |
192 bridge_->CreateDemuxer(&non_owner_factory_, message_loop_proxy_)); | |
193 EXPECT_FALSE(bridge_->AcquireOwnership(&non_owner_factory_)); | |
194 EXPECT_TRUE(bridge_->AcquireOwnership(&owner_factory_)); | |
Ami GONE FROM CHROMIUM
2013/05/08 20:26:44
here and elsewhere, always release.
Since you're u
wonsik
2013/05/14 12:53:57
Done --- we're no longer using a singleton, and Te
| |
195 } | |
196 | |
197 TEST_F(RTCVideoDecoderBridgeTvTest, InitDecodeReturnsErrorOnNonVP8Codec) { | |
198 AcquireOwnershipAndCreateDemuxer(); | |
199 codec_.codecType = webrtc::kVideoCodecI420; | |
200 base::PostTaskAndReplyWithResult( | |
201 decoder_thread_.message_loop_proxy(), | |
202 FROM_HERE, | |
203 BindInitDecode(&codec_, 1), | |
204 BindExpectNotEquals(WEBRTC_VIDEO_CODEC_OK)); | |
205 decoder_thread_event_.Wait(); | |
206 } | |
207 | |
208 TEST_F(RTCVideoDecoderBridgeTvTest, InitDecodeReturnsErrorOnFeedbackMode) { | |
209 AcquireOwnershipAndCreateDemuxer(); | |
210 codec_.codecType = webrtc::kVideoCodecVP8; | |
211 codec_.codecSpecific.VP8.feedbackModeOn = true; | |
212 base::PostTaskAndReplyWithResult( | |
213 decoder_thread_.message_loop_proxy(), | |
214 FROM_HERE, | |
215 BindInitDecode(&codec_, 1), | |
216 BindExpectNotEquals(WEBRTC_VIDEO_CODEC_OK)); | |
217 decoder_thread_event_.Wait(); | |
218 } | |
219 | |
220 TEST_F(RTCVideoDecoderBridgeTvTest, DecodeReturnsErrorBeforeInitDecode) { | |
221 AcquireOwnershipAndCreateDemuxer(); | |
222 PostDecodeAndWait( | |
223 WEBRTC_VIDEO_CODEC_UNINITIALIZED, input_image_, false, NULL, NULL, 0); | |
224 } | |
225 | |
226 TEST_F(RTCVideoDecoderBridgeTvTest, DecodeReturnsErrorOnDamagedBitstream) { | |
227 AcquireOwnershipAndCreateDemuxer(); | |
228 InitDecode(); | |
229 input_image_._completeFrame = false; | |
230 PostDecodeAndWait( | |
231 WEBRTC_VIDEO_CODEC_ERROR, input_image_, false, NULL, NULL, 0); | |
232 } | |
233 | |
234 TEST_F(RTCVideoDecoderBridgeTvTest, DecodeReturnsErrorOnMissingFrames) { | |
235 AcquireOwnershipAndCreateDemuxer(); | |
236 InitDecode(); | |
237 PostDecodeAndWait( | |
238 WEBRTC_VIDEO_CODEC_ERROR, input_image_, true, NULL, NULL, 0); | |
239 } | |
240 | |
241 TEST_F(RTCVideoDecoderBridgeTvTest, GetNonVideoStreamFails) { | |
242 AcquireOwnershipAndCreateDemuxer(); | |
243 InitDecode(); | |
244 EXPECT_EQ(static_cast<media::DemuxerStream*>(NULL), | |
245 demuxer_->GetStream(media::DemuxerStream::AUDIO)); | |
246 EXPECT_EQ(static_cast<media::DemuxerStream*>(NULL), | |
247 demuxer_->GetStream(media::DemuxerStream::UNKNOWN)); | |
248 } | |
249 | |
250 TEST_F(RTCVideoDecoderBridgeTvTest, GetVideoStreamSucceeds) { | |
251 AcquireOwnershipAndCreateDemuxer(); | |
252 InitDecode(); | |
253 GetVideoStream(); | |
254 } | |
255 | |
256 TEST_F(RTCVideoDecoderBridgeTvTest, DecodeReturnsErrorOnNonKeyFrameAtFirst) { | |
257 AcquireOwnershipAndCreateDemuxer(); | |
258 InitDecode(); | |
259 GetVideoStream(); | |
260 input_image_._frameType = webrtc::kDeltaFrame; | |
261 PostDecodeAndWait( | |
262 WEBRTC_VIDEO_CODEC_ERROR, input_image_, false, NULL, NULL, 0); | |
263 } | |
264 | |
265 TEST_F(RTCVideoDecoderBridgeTvTest, DecodeUpdatesVideoSizeOnKeyFrame) { | |
266 AcquireOwnershipAndCreateDemuxer(); | |
267 InitDecode(); | |
268 GetVideoStream(); | |
269 gfx::Size new_size(320, 240); | |
270 input_image_._encodedWidth = new_size.width(); | |
271 input_image_._encodedHeight = new_size.height(); | |
272 PostDecodeAndWait( | |
273 WEBRTC_VIDEO_CODEC_OK, input_image_, false, NULL, NULL, 0); | |
274 EXPECT_EQ(new_size, video_stream_->video_decoder_config().coded_size()); | |
275 EXPECT_EQ(gfx::Rect(new_size), | |
276 video_stream_->video_decoder_config().visible_rect()); | |
277 EXPECT_EQ(new_size, video_stream_->video_decoder_config().natural_size()); | |
278 } | |
279 | |
280 TEST_F(RTCVideoDecoderBridgeTvTest, DecodeAdjustsTimestampFromZero) { | |
281 AcquireOwnershipAndCreateDemuxer(); | |
282 InitDecode(); | |
283 GetVideoStream(); | |
284 PostDecodeAndWait( | |
285 WEBRTC_VIDEO_CODEC_OK, input_image_, false, NULL, NULL, 10000); | |
286 video_stream_->Read(base::Bind(&RTCVideoDecoderBridgeTvTest::ReadCallback, | |
287 base::Unretained(this))); | |
288 read_event_.Wait(); | |
289 EXPECT_EQ(base::TimeDelta::FromMilliseconds(0), | |
290 last_decoder_buffer_->GetTimestamp()); | |
291 PostDecodeAndWait( | |
292 WEBRTC_VIDEO_CODEC_OK, input_image_, false, NULL, NULL, 10033); | |
293 video_stream_->Read(base::Bind(&RTCVideoDecoderBridgeTvTest::ReadCallback, | |
294 base::Unretained(this))); | |
295 read_event_.Wait(); | |
296 EXPECT_EQ(base::TimeDelta::FromMilliseconds(33), | |
297 last_decoder_buffer_->GetTimestamp()); | |
298 } | |
299 | |
300 TEST_F(RTCVideoDecoderBridgeTvTest, DecodePassesDataCorrectly) { | |
301 AcquireOwnershipAndCreateDemuxer(); | |
302 InitDecode(); | |
303 GetVideoStream(); | |
304 video_stream_->Read(base::Bind(&RTCVideoDecoderBridgeTvTest::ReadCallback, | |
305 base::Unretained(this))); | |
306 PostDecodeAndWait( | |
307 WEBRTC_VIDEO_CODEC_OK, input_image_, false, NULL, NULL, 0); | |
308 read_event_.Wait(); | |
309 EXPECT_EQ(static_cast<int>(sizeof(data_)), | |
310 last_decoder_buffer_->GetDataSize()); | |
311 EXPECT_EQ(data_, last_decoder_buffer_->GetData()[0]); | |
312 } | |
313 | |
314 TEST_F(RTCVideoDecoderBridgeTvTest, NextReadTriggersDecodeCompleteCallback) { | |
315 EXPECT_CALL(decode_complete_callback_, Decoded(_)) | |
316 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK)); | |
317 | |
318 AcquireOwnershipAndCreateDemuxer(); | |
319 InitDecode(); | |
320 GetVideoStream(); | |
321 video_stream_->Read(base::Bind(&RTCVideoDecoderBridgeTvTest::ReadCallback, | |
322 base::Unretained(this))); | |
323 PostDecodeAndWait( | |
324 WEBRTC_VIDEO_CODEC_OK, input_image_, false, NULL, NULL, 0); | |
325 read_event_.Wait(); | |
326 video_stream_->Read(base::Bind(&RTCVideoDecoderBridgeTvTest::ReadCallback, | |
327 base::Unretained(this))); | |
328 } | |
329 | |
330 TEST_F(RTCVideoDecoderBridgeTvTest, ResetReturnsOk) { | |
331 AcquireOwnershipAndCreateDemuxer(); | |
332 InitDecode(); | |
333 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, bridge_->Reset()); | |
334 } | |
335 | |
336 TEST_F(RTCVideoDecoderBridgeTvTest, ReleaseReturnsOk) { | |
337 AcquireOwnershipAndCreateDemuxer(); | |
338 InitDecode(); | |
339 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, bridge_->Release()); | |
340 } | |
341 | |
342 } // content | |
OLD | NEW |