Home | History | Annotate | Download | only in test
      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 
     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 
     42   virtual ~SvcTest() {}
     43 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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.
    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 
    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 
    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 
    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 
    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