• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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