Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(99)

Side by Side Diff: content/renderer/media/rtc_video_decoder_factory_tv_unittest.cc

Issue 14247018: Implement WebRTC in Chrome for TV (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed Dongwon and Yuncheol's comments Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 "base/threading/thread.h"
8 #include "content/renderer/media/rtc_video_decoder_factory_tv.h"
9 #include "media/base/decoder_buffer.h"
10 #include "media/base/video_decoder_config.h"
11 #include "testing/gmock/include/gmock/gmock.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "third_party/webrtc/modules/video_coding/codecs/interface/mock/mock_vid eo_codec_interface.h"
14 #include "ui/gfx/rect.h"
15
16 using ::testing::_;
17 using ::testing::Return;
18
19 namespace content {
20
21 class RTCVideoDecoderFactoryTvTest : public ::testing::Test {
22 public:
23 RTCVideoDecoderFactoryTvTest()
24 : factory_(new RTCVideoDecoderFactoryTv),
25 decoder_(NULL),
26 is_demuxer_acquired_(false),
27 video_stream_(NULL),
28 size_(1280, 720),
29 input_image_(&data_, sizeof(data_), sizeof(data_)),
30 data_('a'),
31 read_event_(false, false),
32 decoder_thread_("Test decoeder thread"),
acolwell GONE FROM CHROMIUM 2013/05/14 18:17:47 nit:s/decoeder/decoder
wonsik 2013/05/20 14:02:24 Done.
33 decoder_thread_event_(false, false) {}
34
35 void ReadCallback(media::DemuxerStream::Status status,
36 const scoped_refptr<media::DecoderBuffer>& decoder_buffer) {
37 switch (status) {
38 case media::DemuxerStream::kOk:
39 EXPECT_TRUE(decoder_buffer);
40 break;
41 case media::DemuxerStream::kConfigChanged:
42 case media::DemuxerStream::kAborted:
43 EXPECT_FALSE(decoder_buffer);
44 break;
45 }
46 last_decoder_buffer_ = decoder_buffer;
47 read_event_.Signal();
48 }
49
50 void ExpectEqualsAndSignal(int32_t expected, int32_t actual) {
51 EXPECT_EQ(expected, actual);
52 decoder_thread_event_.Signal();
53 }
54
55 void ExpectNotEqualsAndSignal(int32_t unexpected, int32_t actual) {
56 EXPECT_NE(unexpected, actual);
57 decoder_thread_event_.Signal();
58 }
59
60 protected:
61 virtual void SetUp() OVERRIDE {
62 memset(&codec_, 0, sizeof(codec_));
acolwell GONE FROM CHROMIUM 2013/05/14 18:17:47 I think you can just move all the logic in this me
wonsik 2013/05/20 14:02:24 Done.
63 message_loop_proxy_ = base::MessageLoopProxy::current();
64 input_image_._frameType = webrtc::kKeyFrame;
65 input_image_._encodedWidth = size_.width();
66 input_image_._encodedHeight = size_.height();
67 input_image_._completeFrame = true;
68 decoder_thread_.Start();
69 }
70
71 virtual void TearDown() OVERRIDE {
72 if (is_demuxer_acquired_) {
acolwell GONE FROM CHROMIUM 2013/05/14 18:17:47 I believe you can move all of the logic in this me
wonsik 2013/05/20 14:02:24 Done.
73 factory_->ReleaseDemuxer();
74 is_demuxer_acquired_ = false;
75 }
76 if (decoder_) {
77 factory_->DestroyVideoDecoder(decoder_);
78 decoder_ = NULL;
79 }
80
81 decoder_thread_.Stop();
82 }
83
84 base::Callback<void(int32_t)> BindExpectEquals(int32_t expected) {
85 return base::Bind(&RTCVideoDecoderFactoryTvTest::ExpectEqualsAndSignal,
86 base::Unretained(this),
87 expected);
88 }
89
90 base::Callback<void(int32_t)> BindExpectNotEquals(int32_t unexpected) {
91 return base::Bind(&RTCVideoDecoderFactoryTvTest::ExpectNotEqualsAndSignal,
92 base::Unretained(this),
93 unexpected);
94 }
95
96 base::Callback<int32_t(void)> BindInitDecode(const webrtc::VideoCodec* codec,
97 int32_t num_cores) {
98 return base::Bind(&webrtc::VideoDecoder::InitDecode,
99 base::Unretained(decoder_),
100 codec,
101 num_cores);
102 }
103
104 base::Callback<int32_t(void)> BindDecode(
105 const webrtc::EncodedImage& input_image,
106 bool missing_frames,
107 const webrtc::RTPFragmentationHeader* fragmentation,
108 const webrtc::CodecSpecificInfo* info = NULL,
109 int64_t render_time_ms = -1) {
110 return base::Bind(&webrtc::VideoDecoder::Decode,
111 base::Unretained(decoder_),
112 input_image,
113 missing_frames,
114 fragmentation,
115 info,
116 render_time_ms);
117 }
118
119 void CreateDecoderAndAcquireDemuxer() {
120 decoder_ = factory_->CreateVideoDecoder(webrtc::kVideoCodecVP8);
121 ASSERT_TRUE(decoder_);
122 ASSERT_TRUE(factory_->AcquireDemuxer());
123 is_demuxer_acquired_ = true;
124 }
125
126 void InitDecode() {
127 codec_.codecType = webrtc::kVideoCodecVP8;
128 codec_.width = size_.width();
129 codec_.height = size_.height();
130 base::PostTaskAndReplyWithResult(decoder_thread_.message_loop_proxy(),
131 FROM_HERE,
132 BindInitDecode(&codec_, 1),
133 BindExpectEquals(WEBRTC_VIDEO_CODEC_OK));
134 decoder_thread_event_.Wait();
135 base::PostTaskAndReplyWithResult(
136 decoder_thread_.message_loop_proxy(),
137 FROM_HERE,
138 base::Bind(&webrtc::VideoDecoder::RegisterDecodeCompleteCallback,
139 base::Unretained(decoder_),
140 &decode_complete_callback_),
141 BindExpectEquals(WEBRTC_VIDEO_CODEC_OK));
142 decoder_thread_event_.Wait();
143 }
144
145 void GetVideoStream() {
146 video_stream_ = factory_->GetStream(media::DemuxerStream::VIDEO);
147 ASSERT_TRUE(video_stream_);
148 EXPECT_EQ(media::kCodecVP8, video_stream_->video_decoder_config().codec());
149 EXPECT_EQ(size_, video_stream_->video_decoder_config().coded_size());
150 EXPECT_EQ(gfx::Rect(size_),
151 video_stream_->video_decoder_config().visible_rect());
152 EXPECT_EQ(size_, video_stream_->video_decoder_config().natural_size());
153 }
154
155 void PostDecodeAndWait(int32_t expected,
156 const webrtc::EncodedImage& input_image,
157 bool missing_frames,
158 const webrtc::RTPFragmentationHeader* fragmentation,
159 const webrtc::CodecSpecificInfo* info = NULL,
160 int64_t render_time_ms = -1) {
161 base::PostTaskAndReplyWithResult(
162 decoder_thread_.message_loop_proxy(),
163 FROM_HERE,
164 BindDecode(
165 input_image, missing_frames, fragmentation, info, render_time_ms),
166 BindExpectEquals(expected));
167 decoder_thread_event_.Wait();
168 }
169
170 RTCVideoDecoderFactoryTv* factory_;
171 webrtc::VideoDecoder* decoder_;
172 bool is_demuxer_acquired_;
173 base::MessageLoopProxy* message_loop_proxy_;
174 media::DemuxerStream* video_stream_;
175 webrtc::VideoCodec codec_;
176 gfx::Size size_;
177 webrtc::EncodedImage input_image_;
178 unsigned char data_;
179 webrtc::MockDecodedImageCallback decode_complete_callback_;
180 base::WaitableEvent read_event_;
181 base::Thread decoder_thread_;
182 base::WaitableEvent decoder_thread_event_;
183 scoped_refptr<media::DecoderBuffer> last_decoder_buffer_;
184 };
185
186 TEST_F(RTCVideoDecoderFactoryTvTest, CreateAndDestroyDecoder) {
187 // Only VP8 decoder is supported.
188 ASSERT_FALSE(factory_->CreateVideoDecoder(webrtc::kVideoCodecI420));
189 decoder_ = factory_->CreateVideoDecoder(webrtc::kVideoCodecVP8);
190 ASSERT_TRUE(decoder_);
191 // Only one decoder at a time will be created.
192 ASSERT_FALSE(factory_->CreateVideoDecoder(webrtc::kVideoCodecVP8));
193 factory_->DestroyVideoDecoder(decoder_);
194 }
195
196 TEST_F(RTCVideoDecoderFactoryTvTest, AcquireDemuxerAfterCreateDecoder) {
197 decoder_ = factory_->CreateVideoDecoder(webrtc::kVideoCodecVP8);
198 ASSERT_TRUE(decoder_);
199 ASSERT_TRUE(factory_->AcquireDemuxer());
200 is_demuxer_acquired_ = true;
201 // Demuxer can be acquired only once.
202 ASSERT_FALSE(factory_->AcquireDemuxer());
203 }
204
205 TEST_F(RTCVideoDecoderFactoryTvTest, AcquireDemuxerBeforeCreateDecoder) {
206 ASSERT_TRUE(factory_->AcquireDemuxer());
207 is_demuxer_acquired_ = true;
208 decoder_ = factory_->CreateVideoDecoder(webrtc::kVideoCodecVP8);
209 ASSERT_TRUE(decoder_);
210 }
211
212 TEST_F(RTCVideoDecoderFactoryTvTest, InitDecodeReturnsErrorOnNonVP8Codec) {
213 CreateDecoderAndAcquireDemuxer();
214 codec_.codecType = webrtc::kVideoCodecI420;
215 base::PostTaskAndReplyWithResult(decoder_thread_.message_loop_proxy(),
216 FROM_HERE,
217 BindInitDecode(&codec_, 1),
218 BindExpectNotEquals(WEBRTC_VIDEO_CODEC_OK));
219 decoder_thread_event_.Wait();
220 }
221
222 TEST_F(RTCVideoDecoderFactoryTvTest, InitDecodeReturnsErrorOnFeedbackMode) {
223 CreateDecoderAndAcquireDemuxer();
224 codec_.codecType = webrtc::kVideoCodecVP8;
225 codec_.codecSpecific.VP8.feedbackModeOn = true;
226 base::PostTaskAndReplyWithResult(decoder_thread_.message_loop_proxy(),
227 FROM_HERE,
228 BindInitDecode(&codec_, 1),
229 BindExpectNotEquals(WEBRTC_VIDEO_CODEC_OK));
230 decoder_thread_event_.Wait();
231 }
232
233 TEST_F(RTCVideoDecoderFactoryTvTest, DecodeReturnsErrorBeforeInitDecode) {
234 CreateDecoderAndAcquireDemuxer();
235 PostDecodeAndWait(
236 WEBRTC_VIDEO_CODEC_UNINITIALIZED, input_image_, false, NULL, NULL, 0);
237 }
238
239 TEST_F(RTCVideoDecoderFactoryTvTest, DecodeReturnsErrorOnDamagedBitstream) {
240 CreateDecoderAndAcquireDemuxer();
241 InitDecode();
242 input_image_._completeFrame = false;
243 PostDecodeAndWait(
244 WEBRTC_VIDEO_CODEC_ERROR, input_image_, false, NULL, NULL, 0);
245 }
246
247 TEST_F(RTCVideoDecoderFactoryTvTest, DecodeReturnsErrorOnMissingFrames) {
248 CreateDecoderAndAcquireDemuxer();
249 InitDecode();
250 PostDecodeAndWait(
251 WEBRTC_VIDEO_CODEC_ERROR, input_image_, true, NULL, NULL, 0);
252 }
253
254 TEST_F(RTCVideoDecoderFactoryTvTest, GetNonVideoStreamFails) {
255 CreateDecoderAndAcquireDemuxer();
256 InitDecode();
257 EXPECT_FALSE(factory_->GetStream(media::DemuxerStream::AUDIO));
258 EXPECT_FALSE(factory_->GetStream(media::DemuxerStream::UNKNOWN));
259 }
260
261 TEST_F(RTCVideoDecoderFactoryTvTest, GetVideoStreamSucceeds) {
262 CreateDecoderAndAcquireDemuxer();
263 InitDecode();
264 GetVideoStream();
265 }
266
267 TEST_F(RTCVideoDecoderFactoryTvTest, DecodeReturnsErrorOnNonKeyFrameAtFirst) {
268 CreateDecoderAndAcquireDemuxer();
269 InitDecode();
270 GetVideoStream();
271 input_image_._frameType = webrtc::kDeltaFrame;
272 PostDecodeAndWait(
273 WEBRTC_VIDEO_CODEC_ERROR, input_image_, false, NULL, NULL, 0);
274 }
275
276 TEST_F(RTCVideoDecoderFactoryTvTest, DecodeUpdatesVideoSizeOnKeyFrame) {
277 CreateDecoderAndAcquireDemuxer();
278 InitDecode();
279 GetVideoStream();
280 gfx::Size new_size(320, 240);
281 input_image_._encodedWidth = new_size.width();
282 input_image_._encodedHeight = new_size.height();
283 PostDecodeAndWait(WEBRTC_VIDEO_CODEC_OK, input_image_, false, NULL, NULL, 0);
284 EXPECT_EQ(new_size, video_stream_->video_decoder_config().coded_size());
285 EXPECT_EQ(gfx::Rect(new_size),
286 video_stream_->video_decoder_config().visible_rect());
287 EXPECT_EQ(new_size, video_stream_->video_decoder_config().natural_size());
288 }
289
290 TEST_F(RTCVideoDecoderFactoryTvTest, DecodeAdjustsTimestampFromZero) {
291 CreateDecoderAndAcquireDemuxer();
292 InitDecode();
293 GetVideoStream();
294 PostDecodeAndWait(
295 WEBRTC_VIDEO_CODEC_OK, input_image_, false, NULL, NULL, 10000);
296 video_stream_->Read(base::Bind(&RTCVideoDecoderFactoryTvTest::ReadCallback,
297 base::Unretained(this)));
298 read_event_.Wait();
299 EXPECT_EQ(base::TimeDelta::FromMilliseconds(0),
300 last_decoder_buffer_->GetTimestamp());
301 PostDecodeAndWait(
302 WEBRTC_VIDEO_CODEC_OK, input_image_, false, NULL, NULL, 10033);
303 video_stream_->Read(base::Bind(&RTCVideoDecoderFactoryTvTest::ReadCallback,
304 base::Unretained(this)));
305 read_event_.Wait();
306 EXPECT_EQ(base::TimeDelta::FromMilliseconds(33),
307 last_decoder_buffer_->GetTimestamp());
308 }
309
310 TEST_F(RTCVideoDecoderFactoryTvTest, DecodePassesDataCorrectly) {
311 CreateDecoderAndAcquireDemuxer();
312 InitDecode();
313 GetVideoStream();
314 video_stream_->Read(base::Bind(&RTCVideoDecoderFactoryTvTest::ReadCallback,
315 base::Unretained(this)));
316 PostDecodeAndWait(WEBRTC_VIDEO_CODEC_OK, input_image_, false, NULL, NULL, 0);
317 read_event_.Wait();
318 EXPECT_EQ(static_cast<int>(sizeof(data_)),
319 last_decoder_buffer_->GetDataSize());
320 EXPECT_EQ(data_, last_decoder_buffer_->GetData()[0]);
321 }
322
323 TEST_F(RTCVideoDecoderFactoryTvTest, NextReadTriggersDecodeCompleteCallback) {
324 EXPECT_CALL(decode_complete_callback_, Decoded(_))
325 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
326
327 CreateDecoderAndAcquireDemuxer();
328 InitDecode();
329 GetVideoStream();
330 video_stream_->Read(base::Bind(&RTCVideoDecoderFactoryTvTest::ReadCallback,
331 base::Unretained(this)));
332 PostDecodeAndWait(WEBRTC_VIDEO_CODEC_OK, input_image_, false, NULL, NULL, 0);
333 read_event_.Wait();
334 video_stream_->Read(base::Bind(&RTCVideoDecoderFactoryTvTest::ReadCallback,
335 base::Unretained(this)));
336 }
337
338 TEST_F(RTCVideoDecoderFactoryTvTest, ResetReturnsOk) {
339 CreateDecoderAndAcquireDemuxer();
340 InitDecode();
341 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder_->Reset());
342 }
343
344 TEST_F(RTCVideoDecoderFactoryTvTest, ReleaseReturnsOk) {
345 CreateDecoderAndAcquireDemuxer();
346 InitDecode();
347 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder_->Release());
348 }
349
350 } // content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698