1 /*
2 * Copyright (c) 2013 The WebM project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include <string>
12 #include "third_party/googletest/src/include/gtest/gtest.h"
13 #include "test/codec_factory.h"
14 #include "test/decode_test_driver.h"
15 #include "test/i420_video_source.h"
16 #include "vpx/svc_context.h"
17 #include "vpx/vp8cx.h"
18 #include "vpx/vpx_encoder.h"
19
20 namespace {
21
22 using libvpx_test::CodecFactory;
23 using libvpx_test::Decoder;
24 using libvpx_test::VP9CodecFactory;
25
26 class SvcTest : public ::testing::Test {
27 protected:
28 static const uint32_t kWidth = 352;
29 static const uint32_t kHeight = 288;
30
SvcTest()31 SvcTest()
32 : codec_iface_(0),
33 test_file_name_("hantro_collage_w352h288.yuv"),
34 stats_file_name_("hantro_collage_w352h288.stat"),
35 codec_initialized_(false),
36 decoder_(0) {
37 memset(&svc_, 0, sizeof(svc_));
38 memset(&codec_, 0, sizeof(codec_));
39 memset(&codec_enc_, 0, sizeof(codec_enc_));
40 }
41
~SvcTest()42 virtual ~SvcTest() {}
43
SetUp()44 virtual void SetUp() {
45 svc_.encoding_mode = INTER_LAYER_PREDICTION_IP;
46 svc_.log_level = SVC_LOG_DEBUG;
47 svc_.log_print = 0;
48
49 codec_iface_ = vpx_codec_vp9_cx();
50 const vpx_codec_err_t res =
51 vpx_codec_enc_config_default(codec_iface_, &codec_enc_, 0);
52 EXPECT_EQ(VPX_CODEC_OK, res);
53
54 codec_enc_.g_w = kWidth;
55 codec_enc_.g_h = kHeight;
56 codec_enc_.g_timebase.num = 1;
57 codec_enc_.g_timebase.den = 60;
58 codec_enc_.kf_min_dist = 100;
59 codec_enc_.kf_max_dist = 100;
60
61 vpx_codec_dec_cfg_t dec_cfg = {0};
62 VP9CodecFactory codec_factory;
63 decoder_ = codec_factory.CreateDecoder(dec_cfg, 0);
64 }
65
TearDown()66 virtual void TearDown() {
67 vpx_svc_release(&svc_);
68 delete(decoder_);
69 if (codec_initialized_) vpx_codec_destroy(&codec_);
70 }
71
72 SvcContext svc_;
73 vpx_codec_ctx_t codec_;
74 struct vpx_codec_enc_cfg codec_enc_;
75 vpx_codec_iface_t *codec_iface_;
76 std::string test_file_name_;
77 std::string stats_file_name_;
78 bool codec_initialized_;
79 Decoder *decoder_;
80 };
81
TEST_F(SvcTest,SvcInit)82 TEST_F(SvcTest, SvcInit) {
83 // test missing parameters
84 vpx_codec_err_t res = vpx_svc_init(NULL, &codec_, codec_iface_, &codec_enc_);
85 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
86 res = vpx_svc_init(&svc_, NULL, codec_iface_, &codec_enc_);
87 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
88 res = vpx_svc_init(&svc_, &codec_, NULL, &codec_enc_);
89 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
90
91 res = vpx_svc_init(&svc_, &codec_, codec_iface_, NULL);
92 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
93
94 svc_.spatial_layers = 6; // too many layers
95 res = vpx_svc_init(&svc_, &codec_, codec_iface_, &codec_enc_);
96 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
97
98 svc_.spatial_layers = 0; // use default layers
99 res = vpx_svc_init(&svc_, &codec_, codec_iface_, &codec_enc_);
100 EXPECT_EQ(VPX_CODEC_OK, res);
101 codec_initialized_ = true;
102 EXPECT_EQ(VPX_SS_DEFAULT_LAYERS, svc_.spatial_layers);
103 }
104
TEST_F(SvcTest,InitTwoLayers)105 TEST_F(SvcTest, InitTwoLayers) {
106 svc_.spatial_layers = 2;
107 vpx_svc_set_scale_factors(&svc_, "4/16,16*16"); // invalid scale values
108 vpx_codec_err_t res = vpx_svc_init(&svc_, &codec_, codec_iface_, &codec_enc_);
109 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
110
111 vpx_svc_set_scale_factors(&svc_, "4/16,16/16"); // valid scale values
112 res = vpx_svc_init(&svc_, &codec_, codec_iface_, &codec_enc_);
113 EXPECT_EQ(VPX_CODEC_OK, res);
114 codec_initialized_ = true;
115 }
116
TEST_F(SvcTest,InvalidOptions)117 TEST_F(SvcTest, InvalidOptions) {
118 vpx_codec_err_t res = vpx_svc_set_options(&svc_, NULL);
119 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
120
121 res = vpx_svc_set_options(&svc_, "not-an-option=1");
122 EXPECT_EQ(VPX_CODEC_OK, res);
123 res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
124 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
125 }
126
TEST_F(SvcTest,SetLayersOption)127 TEST_F(SvcTest, SetLayersOption) {
128 vpx_codec_err_t res = vpx_svc_set_options(&svc_, "layers=3");
129 EXPECT_EQ(VPX_CODEC_OK, res);
130 res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
131 EXPECT_EQ(VPX_CODEC_OK, res);
132 codec_initialized_ = true;
133 EXPECT_EQ(3, svc_.spatial_layers);
134 }
135
TEST_F(SvcTest,SetEncodingMode)136 TEST_F(SvcTest, SetEncodingMode) {
137 vpx_codec_err_t res = vpx_svc_set_options(&svc_, "encoding-mode=alt-ip");
138 EXPECT_EQ(VPX_CODEC_OK, res);
139 res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
140 EXPECT_EQ(VPX_CODEC_OK, res);
141 codec_initialized_ = true;
142 EXPECT_EQ(ALT_INTER_LAYER_PREDICTION_IP, svc_.encoding_mode);
143 }
144
TEST_F(SvcTest,SetMultipleOptions)145 TEST_F(SvcTest, SetMultipleOptions) {
146 vpx_codec_err_t res = vpx_svc_set_options(&svc_, "layers=2 encoding-mode=ip");
147 res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
148 EXPECT_EQ(VPX_CODEC_OK, res);
149 codec_initialized_ = true;
150 EXPECT_EQ(2, svc_.spatial_layers);
151 EXPECT_EQ(INTER_LAYER_PREDICTION_IP, svc_.encoding_mode);
152 }
153
TEST_F(SvcTest,SetScaleFactorsOption)154 TEST_F(SvcTest, SetScaleFactorsOption) {
155 svc_.spatial_layers = 2;
156 vpx_codec_err_t res =
157 vpx_svc_set_options(&svc_, "scale-factors=not-scale-factors");
158 EXPECT_EQ(VPX_CODEC_OK, res);
159 res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
160 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
161
162 res = vpx_svc_set_options(&svc_, "scale-factors=1/3,2/3");
163 EXPECT_EQ(VPX_CODEC_OK, res);
164 res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
165 EXPECT_EQ(VPX_CODEC_OK, res);
166 codec_initialized_ = true;
167 }
168
TEST_F(SvcTest,SetQuantizersOption)169 TEST_F(SvcTest, SetQuantizersOption) {
170 svc_.spatial_layers = 2;
171 vpx_codec_err_t res = vpx_svc_set_options(&svc_, "quantizers=not-quantizers");
172 EXPECT_EQ(VPX_CODEC_OK, res);
173 res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
174 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
175
176 vpx_svc_set_options(&svc_, "quantizers=40,45");
177 res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
178 EXPECT_EQ(VPX_CODEC_OK, res);
179 codec_initialized_ = true;
180 }
181
TEST_F(SvcTest,SetKeyFrameQuantizersOption)182 TEST_F(SvcTest, SetKeyFrameQuantizersOption) {
183 svc_.spatial_layers = 2;
184 vpx_codec_err_t res = vpx_svc_set_options(&svc_,
185 "quantizers-keyframe=not-quantizers");
186 EXPECT_EQ(VPX_CODEC_OK, res);
187 res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
188 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
189
190 vpx_svc_set_options(&svc_, "quantizers-keyframe=40,45");
191 res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
192 EXPECT_EQ(VPX_CODEC_OK, res);
193 codec_initialized_ = true;
194 }
195
TEST_F(SvcTest,SetQuantizers)196 TEST_F(SvcTest, SetQuantizers) {
197 vpx_codec_err_t res = vpx_svc_set_quantizers(NULL, "40,30", 0);
198 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
199
200 res = vpx_svc_set_quantizers(&svc_, NULL, 0);
201 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
202
203 svc_.spatial_layers = 2;
204 res = vpx_svc_set_quantizers(&svc_, "40", 0);
205 EXPECT_EQ(VPX_CODEC_OK, res);
206 res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
207 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
208
209 res = vpx_svc_set_quantizers(&svc_, "40,30", 0);
210 EXPECT_EQ(VPX_CODEC_OK, res);
211 res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
212 EXPECT_EQ(VPX_CODEC_OK, res);
213 codec_initialized_ = true;
214 }
215
TEST_F(SvcTest,SetKeyFrameQuantizers)216 TEST_F(SvcTest, SetKeyFrameQuantizers) {
217 vpx_codec_err_t res = vpx_svc_set_quantizers(NULL, "40,31", 1);
218 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
219
220 res = vpx_svc_set_quantizers(&svc_, NULL, 1);
221 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
222
223 res = vpx_svc_set_quantizers(&svc_, "40,30", 1);
224 EXPECT_EQ(VPX_CODEC_OK, res);
225 res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
226 EXPECT_EQ(VPX_CODEC_OK, res);
227 codec_initialized_ = true;
228 }
229
TEST_F(SvcTest,SetScaleFactors)230 TEST_F(SvcTest, SetScaleFactors) {
231 vpx_codec_err_t res = vpx_svc_set_scale_factors(NULL, "4/16,16/16");
232 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
233
234 res = vpx_svc_set_scale_factors(&svc_, NULL);
235 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
236
237 svc_.spatial_layers = 2;
238 res = vpx_svc_set_scale_factors(&svc_, "4/16");
239 EXPECT_EQ(VPX_CODEC_OK, res);
240 res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
241 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
242
243 res = vpx_svc_set_scale_factors(&svc_, "4/16,16/16");
244 EXPECT_EQ(VPX_CODEC_OK, res);
245 res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
246 EXPECT_EQ(VPX_CODEC_OK, res);
247 codec_initialized_ = true;
248 }
249
250 // Test that decoder can handle an SVC frame as the first frame in a sequence.
TEST_F(SvcTest,FirstFrameHasLayers)251 TEST_F(SvcTest, FirstFrameHasLayers) {
252 svc_.spatial_layers = 2;
253 vpx_svc_set_scale_factors(&svc_, "4/16,16/16");
254 vpx_svc_set_quantizers(&svc_, "40,30", 0);
255
256 vpx_codec_err_t res =
257 vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
258 EXPECT_EQ(VPX_CODEC_OK, res);
259 codec_initialized_ = true;
260
261 libvpx_test::I420VideoSource video(test_file_name_, kWidth, kHeight,
262 codec_enc_.g_timebase.den,
263 codec_enc_.g_timebase.num, 0, 30);
264 video.Begin();
265
266 res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
267 video.duration(), VPX_DL_GOOD_QUALITY);
268 EXPECT_EQ(VPX_CODEC_OK, res);
269
270 const vpx_codec_err_t res_dec = decoder_->DecodeFrame(
271 static_cast<const uint8_t *>(vpx_svc_get_buffer(&svc_)),
272 vpx_svc_get_frame_size(&svc_));
273
274 // this test fails with a decoder error
275 ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError();
276 }
277
TEST_F(SvcTest,EncodeThreeFrames)278 TEST_F(SvcTest, EncodeThreeFrames) {
279 svc_.spatial_layers = 2;
280 vpx_svc_set_scale_factors(&svc_, "4/16,16/16");
281 vpx_svc_set_quantizers(&svc_, "40,30", 0);
282
283 vpx_codec_err_t res =
284 vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
285 ASSERT_EQ(VPX_CODEC_OK, res);
286 codec_initialized_ = true;
287
288 libvpx_test::I420VideoSource video(test_file_name_, kWidth, kHeight,
289 codec_enc_.g_timebase.den,
290 codec_enc_.g_timebase.num, 0, 30);
291 // FRAME 0
292 video.Begin();
293 // This frame is a keyframe.
294 res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
295 video.duration(), VPX_DL_GOOD_QUALITY);
296 ASSERT_EQ(VPX_CODEC_OK, res);
297 EXPECT_EQ(1, vpx_svc_is_keyframe(&svc_));
298
299 vpx_codec_err_t res_dec = decoder_->DecodeFrame(
300 static_cast<const uint8_t *>(vpx_svc_get_buffer(&svc_)),
301 vpx_svc_get_frame_size(&svc_));
302 ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError();
303
304 // FRAME 1
305 video.Next();
306 // This is a P-frame.
307 res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
308 video.duration(), VPX_DL_GOOD_QUALITY);
309 ASSERT_EQ(VPX_CODEC_OK, res);
310 EXPECT_EQ(0, vpx_svc_is_keyframe(&svc_));
311
312 res_dec = decoder_->DecodeFrame(
313 static_cast<const uint8_t *>(vpx_svc_get_buffer(&svc_)),
314 vpx_svc_get_frame_size(&svc_));
315 ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError();
316
317 // FRAME 2
318 video.Next();
319 // This is a P-frame.
320 res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
321 video.duration(), VPX_DL_GOOD_QUALITY);
322 ASSERT_EQ(VPX_CODEC_OK, res);
323 EXPECT_EQ(0, vpx_svc_is_keyframe(&svc_));
324
325 res_dec = decoder_->DecodeFrame(
326 static_cast<const uint8_t *>(vpx_svc_get_buffer(&svc_)),
327 vpx_svc_get_frame_size(&svc_));
328 ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError();
329 }
330
TEST_F(SvcTest,GetLayerResolution)331 TEST_F(SvcTest, GetLayerResolution) {
332 svc_.spatial_layers = 2;
333 vpx_svc_set_scale_factors(&svc_, "4/16,8/16");
334 vpx_svc_set_quantizers(&svc_, "40,30", 0);
335
336 vpx_codec_err_t res =
337 vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
338 EXPECT_EQ(VPX_CODEC_OK, res);
339 codec_initialized_ = true;
340
341 // ensure that requested layer is a valid layer
342 uint32_t layer_width, layer_height;
343 res = vpx_svc_get_layer_resolution(&svc_, svc_.spatial_layers,
344 &layer_width, &layer_height);
345 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
346
347 res = vpx_svc_get_layer_resolution(NULL, 0, &layer_width, &layer_height);
348 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
349
350 res = vpx_svc_get_layer_resolution(&svc_, 0, NULL, &layer_height);
351 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
352
353 res = vpx_svc_get_layer_resolution(&svc_, 0, &layer_width, NULL);
354 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
355
356 res = vpx_svc_get_layer_resolution(&svc_, 0, &layer_width, &layer_height);
357 EXPECT_EQ(VPX_CODEC_OK, res);
358 EXPECT_EQ(kWidth * 4 / 16, layer_width);
359 EXPECT_EQ(kHeight * 4 / 16, layer_height);
360
361 res = vpx_svc_get_layer_resolution(&svc_, 1, &layer_width, &layer_height);
362 EXPECT_EQ(VPX_CODEC_OK, res);
363 EXPECT_EQ(kWidth * 8 / 16, layer_width);
364 EXPECT_EQ(kHeight * 8 / 16, layer_height);
365 }
366
TEST_F(SvcTest,FirstPassEncode)367 TEST_F(SvcTest, FirstPassEncode) {
368 svc_.spatial_layers = 2;
369 codec_enc_.g_pass = VPX_RC_FIRST_PASS;
370 vpx_svc_set_scale_factors(&svc_, "4/16,16/16");
371 vpx_svc_set_quantizers(&svc_, "40,30", 0);
372
373 vpx_codec_err_t res =
374 vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
375 ASSERT_EQ(VPX_CODEC_OK, res);
376 codec_initialized_ = true;
377
378 libvpx_test::I420VideoSource video(test_file_name_, kWidth, kHeight,
379 codec_enc_.g_timebase.den,
380 codec_enc_.g_timebase.num, 0, 30);
381 // FRAME 0
382 video.Begin();
383 res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
384 video.duration(), VPX_DL_GOOD_QUALITY);
385 ASSERT_EQ(VPX_CODEC_OK, res);
386 EXPECT_GT(vpx_svc_get_rc_stats_buffer_size(&svc_), 0U);
387
388 // FRAME 1
389 video.Next();
390 res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
391 video.duration(), VPX_DL_GOOD_QUALITY);
392 ASSERT_EQ(VPX_CODEC_OK, res);
393 EXPECT_GT(vpx_svc_get_rc_stats_buffer_size(&svc_), 0U);
394
395 // Flush encoder and test EOS packet
396 res = vpx_svc_encode(&svc_, &codec_, NULL, video.pts(),
397 video.duration(), VPX_DL_GOOD_QUALITY);
398 ASSERT_EQ(VPX_CODEC_OK, res);
399 EXPECT_GT(vpx_svc_get_rc_stats_buffer_size(&svc_), 0U);
400 }
401
TEST_F(SvcTest,SecondPassEncode)402 TEST_F(SvcTest, SecondPassEncode) {
403 svc_.spatial_layers = 2;
404 codec_enc_.g_pass = VPX_RC_LAST_PASS;
405
406 FILE *const stats_file = libvpx_test::OpenTestDataFile(stats_file_name_);
407 ASSERT_TRUE(stats_file != NULL) << "Stats file open failed. Filename: "
408 << stats_file;
409
410 struct vpx_fixed_buf stats_buf;
411 fseek(stats_file, 0, SEEK_END);
412 stats_buf.sz = static_cast<size_t>(ftell(stats_file));
413 fseek(stats_file, 0, SEEK_SET);
414
415 stats_buf.buf = malloc(stats_buf.sz);
416 ASSERT_TRUE(stats_buf.buf != NULL);
417 const size_t bytes_read = fread(stats_buf.buf, 1, stats_buf.sz, stats_file);
418 ASSERT_EQ(bytes_read, stats_buf.sz);
419 fclose(stats_file);
420 codec_enc_.rc_twopass_stats_in = stats_buf;
421
422 vpx_codec_err_t res =
423 vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
424 ASSERT_EQ(VPX_CODEC_OK, res);
425 codec_initialized_ = true;
426
427 libvpx_test::I420VideoSource video(test_file_name_, kWidth, kHeight,
428 codec_enc_.g_timebase.den,
429 codec_enc_.g_timebase.num, 0, 30);
430 // FRAME 0
431 video.Begin();
432 // This frame is a keyframe.
433 res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
434 video.duration(), VPX_DL_GOOD_QUALITY);
435 ASSERT_EQ(VPX_CODEC_OK, res);
436 EXPECT_EQ(1, vpx_svc_is_keyframe(&svc_));
437
438 vpx_codec_err_t res_dec = decoder_->DecodeFrame(
439 static_cast<const uint8_t *>(vpx_svc_get_buffer(&svc_)),
440 vpx_svc_get_frame_size(&svc_));
441 ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError();
442
443 // FRAME 1
444 video.Next();
445 // This is a P-frame.
446 res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
447 video.duration(), VPX_DL_GOOD_QUALITY);
448 ASSERT_EQ(VPX_CODEC_OK, res);
449 EXPECT_EQ(0, vpx_svc_is_keyframe(&svc_));
450
451 res_dec = decoder_->DecodeFrame(
452 static_cast<const uint8_t *>(vpx_svc_get_buffer(&svc_)),
453 vpx_svc_get_frame_size(&svc_));
454 ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError();
455
456 // FRAME 2
457 video.Next();
458 // This is a P-frame.
459 res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
460 video.duration(), VPX_DL_GOOD_QUALITY);
461 ASSERT_EQ(VPX_CODEC_OK, res);
462 EXPECT_EQ(0, vpx_svc_is_keyframe(&svc_));
463
464 res_dec = decoder_->DecodeFrame(
465 static_cast<const uint8_t *>(vpx_svc_get_buffer(&svc_)),
466 vpx_svc_get_frame_size(&svc_));
467 ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError();
468
469 free(stats_buf.buf);
470 }
471
472 } // namespace
473