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 
     17 #include "vp9/decoder/vp9_decoder.h"
     18 
     19 #include "vpx/svc_context.h"
     20 #include "vpx/vp8cx.h"
     21 #include "vpx/vpx_encoder.h"
     22 
     23 namespace {
     24 
     25 using libvpx_test::CodecFactory;
     26 using libvpx_test::Decoder;
     27 using libvpx_test::DxDataIterator;
     28 using libvpx_test::VP9CodecFactory;
     29 
     30 class SvcTest : public ::testing::Test {
     31  protected:
     32   static const uint32_t kWidth = 352;
     33   static const uint32_t kHeight = 288;
     34 
     35   SvcTest()
     36       : codec_iface_(0), test_file_name_("hantro_collage_w352h288.yuv"),
     37         codec_initialized_(false), decoder_(0) {
     38     memset(&svc_, 0, sizeof(svc_));
     39     memset(&codec_, 0, sizeof(codec_));
     40     memset(&codec_enc_, 0, sizeof(codec_enc_));
     41   }
     42 
     43   virtual ~SvcTest() {}
     44 
     45   virtual void SetUp() {
     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 = vpx_codec_dec_cfg_t();
     62     VP9CodecFactory codec_factory;
     63     decoder_ = codec_factory.CreateDecoder(dec_cfg, 0);
     64 
     65     tile_columns_ = 0;
     66     tile_rows_ = 0;
     67   }
     68 
     69   virtual void TearDown() {
     70     ReleaseEncoder();
     71     delete (decoder_);
     72   }
     73 
     74   void InitializeEncoder() {
     75     const vpx_codec_err_t res =
     76         vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
     77     EXPECT_EQ(VPX_CODEC_OK, res);
     78     vpx_codec_control(&codec_, VP8E_SET_CPUUSED, 4);  // Make the test faster
     79     vpx_codec_control(&codec_, VP9E_SET_TILE_COLUMNS, tile_columns_);
     80     vpx_codec_control(&codec_, VP9E_SET_TILE_ROWS, tile_rows_);
     81     codec_initialized_ = true;
     82   }
     83 
     84   void ReleaseEncoder() {
     85     vpx_svc_release(&svc_);
     86     if (codec_initialized_) vpx_codec_destroy(&codec_);
     87     codec_initialized_ = false;
     88   }
     89 
     90   void GetStatsData(std::string *const stats_buf) {
     91     vpx_codec_iter_t iter = NULL;
     92     const vpx_codec_cx_pkt_t *cx_pkt;
     93 
     94     while ((cx_pkt = vpx_codec_get_cx_data(&codec_, &iter)) != NULL) {
     95       if (cx_pkt->kind == VPX_CODEC_STATS_PKT) {
     96         EXPECT_GT(cx_pkt->data.twopass_stats.sz, 0U);
     97         ASSERT_TRUE(cx_pkt->data.twopass_stats.buf != NULL);
     98         stats_buf->append(static_cast<char *>(cx_pkt->data.twopass_stats.buf),
     99                           cx_pkt->data.twopass_stats.sz);
    100       }
    101     }
    102   }
    103 
    104   void Pass1EncodeNFrames(const int n, const int layers,
    105                           std::string *const stats_buf) {
    106     vpx_codec_err_t res;
    107 
    108     ASSERT_GT(n, 0);
    109     ASSERT_GT(layers, 0);
    110     svc_.spatial_layers = layers;
    111     codec_enc_.g_pass = VPX_RC_FIRST_PASS;
    112     InitializeEncoder();
    113 
    114     libvpx_test::I420VideoSource video(
    115         test_file_name_, codec_enc_.g_w, codec_enc_.g_h,
    116         codec_enc_.g_timebase.den, codec_enc_.g_timebase.num, 0, 30);
    117     video.Begin();
    118 
    119     for (int i = 0; i < n; ++i) {
    120       res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
    121                            video.duration(), VPX_DL_GOOD_QUALITY);
    122       ASSERT_EQ(VPX_CODEC_OK, res);
    123       GetStatsData(stats_buf);
    124       video.Next();
    125     }
    126 
    127     // Flush encoder and test EOS packet.
    128     res = vpx_svc_encode(&svc_, &codec_, NULL, video.pts(), video.duration(),
    129                          VPX_DL_GOOD_QUALITY);
    130     ASSERT_EQ(VPX_CODEC_OK, res);
    131     GetStatsData(stats_buf);
    132 
    133     ReleaseEncoder();
    134   }
    135 
    136   void StoreFrames(const size_t max_frame_received,
    137                    struct vpx_fixed_buf *const outputs,
    138                    size_t *const frame_received) {
    139     vpx_codec_iter_t iter = NULL;
    140     const vpx_codec_cx_pkt_t *cx_pkt;
    141 
    142     while ((cx_pkt = vpx_codec_get_cx_data(&codec_, &iter)) != NULL) {
    143       if (cx_pkt->kind == VPX_CODEC_CX_FRAME_PKT) {
    144         const size_t frame_size = cx_pkt->data.frame.sz;
    145 
    146         EXPECT_GT(frame_size, 0U);
    147         ASSERT_TRUE(cx_pkt->data.frame.buf != NULL);
    148         ASSERT_LT(*frame_received, max_frame_received);
    149 
    150         if (*frame_received == 0)
    151           EXPECT_EQ(1, !!(cx_pkt->data.frame.flags & VPX_FRAME_IS_KEY));
    152 
    153         outputs[*frame_received].buf = malloc(frame_size + 16);
    154         ASSERT_TRUE(outputs[*frame_received].buf != NULL);
    155         memcpy(outputs[*frame_received].buf, cx_pkt->data.frame.buf,
    156                frame_size);
    157         outputs[*frame_received].sz = frame_size;
    158         ++(*frame_received);
    159       }
    160     }
    161   }
    162 
    163   void Pass2EncodeNFrames(std::string *const stats_buf, const int n,
    164                           const int layers,
    165                           struct vpx_fixed_buf *const outputs) {
    166     vpx_codec_err_t res;
    167     size_t frame_received = 0;
    168 
    169     ASSERT_TRUE(outputs != NULL);
    170     ASSERT_GT(n, 0);
    171     ASSERT_GT(layers, 0);
    172     svc_.spatial_layers = layers;
    173     codec_enc_.rc_target_bitrate = 500;
    174     if (codec_enc_.g_pass == VPX_RC_LAST_PASS) {
    175       ASSERT_TRUE(stats_buf != NULL);
    176       ASSERT_GT(stats_buf->size(), 0U);
    177       codec_enc_.rc_twopass_stats_in.buf = &(*stats_buf)[0];
    178       codec_enc_.rc_twopass_stats_in.sz = stats_buf->size();
    179     }
    180     InitializeEncoder();
    181 
    182     libvpx_test::I420VideoSource video(
    183         test_file_name_, codec_enc_.g_w, codec_enc_.g_h,
    184         codec_enc_.g_timebase.den, codec_enc_.g_timebase.num, 0, 30);
    185     video.Begin();
    186 
    187     for (int i = 0; i < n; ++i) {
    188       res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
    189                            video.duration(), VPX_DL_GOOD_QUALITY);
    190       ASSERT_EQ(VPX_CODEC_OK, res);
    191       StoreFrames(n, outputs, &frame_received);
    192       video.Next();
    193     }
    194 
    195     // Flush encoder.
    196     res = vpx_svc_encode(&svc_, &codec_, NULL, 0, video.duration(),
    197                          VPX_DL_GOOD_QUALITY);
    198     EXPECT_EQ(VPX_CODEC_OK, res);
    199     StoreFrames(n, outputs, &frame_received);
    200 
    201     EXPECT_EQ(frame_received, static_cast<size_t>(n));
    202 
    203     ReleaseEncoder();
    204   }
    205 
    206   void DecodeNFrames(const struct vpx_fixed_buf *const inputs, const int n) {
    207     int decoded_frames = 0;
    208     int received_frames = 0;
    209 
    210     ASSERT_TRUE(inputs != NULL);
    211     ASSERT_GT(n, 0);
    212 
    213     for (int i = 0; i < n; ++i) {
    214       ASSERT_TRUE(inputs[i].buf != NULL);
    215       ASSERT_GT(inputs[i].sz, 0U);
    216       const vpx_codec_err_t res_dec = decoder_->DecodeFrame(
    217           static_cast<const uint8_t *>(inputs[i].buf), inputs[i].sz);
    218       ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError();
    219       ++decoded_frames;
    220 
    221       DxDataIterator dec_iter = decoder_->GetDxData();
    222       while (dec_iter.Next() != NULL) {
    223         ++received_frames;
    224       }
    225     }
    226     EXPECT_EQ(decoded_frames, n);
    227     EXPECT_EQ(received_frames, n);
    228   }
    229 
    230   void DropEnhancementLayers(struct vpx_fixed_buf *const inputs,
    231                              const int num_super_frames,
    232                              const int remained_spatial_layers) {
    233     ASSERT_TRUE(inputs != NULL);
    234     ASSERT_GT(num_super_frames, 0);
    235     ASSERT_GT(remained_spatial_layers, 0);
    236 
    237     for (int i = 0; i < num_super_frames; ++i) {
    238       uint32_t frame_sizes[8] = { 0 };
    239       int frame_count = 0;
    240       int frames_found = 0;
    241       int frame;
    242       ASSERT_TRUE(inputs[i].buf != NULL);
    243       ASSERT_GT(inputs[i].sz, 0U);
    244 
    245       vpx_codec_err_t res = vp9_parse_superframe_index(
    246           static_cast<const uint8_t *>(inputs[i].buf), inputs[i].sz,
    247           frame_sizes, &frame_count, NULL, NULL);
    248       ASSERT_EQ(VPX_CODEC_OK, res);
    249 
    250       if (frame_count == 0) {
    251         // There's no super frame but only a single frame.
    252         ASSERT_EQ(1, remained_spatial_layers);
    253       } else {
    254         // Found a super frame.
    255         uint8_t *frame_data = static_cast<uint8_t *>(inputs[i].buf);
    256         uint8_t *frame_start = frame_data;
    257         for (frame = 0; frame < frame_count; ++frame) {
    258           // Looking for a visible frame.
    259           if (frame_data[0] & 0x02) {
    260             ++frames_found;
    261             if (frames_found == remained_spatial_layers) break;
    262           }
    263           frame_data += frame_sizes[frame];
    264         }
    265         ASSERT_LT(frame, frame_count)
    266             << "Couldn't find a visible frame. "
    267             << "remained_spatial_layers: " << remained_spatial_layers
    268             << "    super_frame: " << i;
    269         if (frame == frame_count - 1) continue;
    270 
    271         frame_data += frame_sizes[frame];
    272 
    273         // We need to add one more frame for multiple frame contexts.
    274         uint8_t marker =
    275             static_cast<const uint8_t *>(inputs[i].buf)[inputs[i].sz - 1];
    276         const uint32_t mag = ((marker >> 3) & 0x3) + 1;
    277         const size_t index_sz = 2 + mag * frame_count;
    278         const size_t new_index_sz = 2 + mag * (frame + 1);
    279         marker &= 0x0f8;
    280         marker |= frame;
    281 
    282         // Copy existing frame sizes.
    283         memmove(frame_data + 1, frame_start + inputs[i].sz - index_sz + 1,
    284                 new_index_sz - 2);
    285         // New marker.
    286         frame_data[0] = marker;
    287         frame_data += (mag * (frame + 1) + 1);
    288 
    289         *frame_data++ = marker;
    290         inputs[i].sz = frame_data - frame_start;
    291       }
    292     }
    293   }
    294 
    295   void FreeBitstreamBuffers(struct vpx_fixed_buf *const inputs, const int n) {
    296     ASSERT_TRUE(inputs != NULL);
    297     ASSERT_GT(n, 0);
    298 
    299     for (int i = 0; i < n; ++i) {
    300       free(inputs[i].buf);
    301       inputs[i].buf = NULL;
    302       inputs[i].sz = 0;
    303     }
    304   }
    305 
    306   SvcContext svc_;
    307   vpx_codec_ctx_t codec_;
    308   struct vpx_codec_enc_cfg codec_enc_;
    309   vpx_codec_iface_t *codec_iface_;
    310   std::string test_file_name_;
    311   bool codec_initialized_;
    312   Decoder *decoder_;
    313   int tile_columns_;
    314   int tile_rows_;
    315 };
    316 
    317 TEST_F(SvcTest, SvcInit) {
    318   // test missing parameters
    319   vpx_codec_err_t res = vpx_svc_init(NULL, &codec_, codec_iface_, &codec_enc_);
    320   EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
    321   res = vpx_svc_init(&svc_, NULL, codec_iface_, &codec_enc_);
    322   EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
    323   res = vpx_svc_init(&svc_, &codec_, NULL, &codec_enc_);
    324   EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
    325 
    326   res = vpx_svc_init(&svc_, &codec_, codec_iface_, NULL);
    327   EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
    328 
    329   svc_.spatial_layers = 6;  // too many layers
    330   res = vpx_svc_init(&svc_, &codec_, codec_iface_, &codec_enc_);
    331   EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
    332 
    333   svc_.spatial_layers = 0;  // use default layers
    334   InitializeEncoder();
    335   EXPECT_EQ(VPX_SS_DEFAULT_LAYERS, svc_.spatial_layers);
    336 }
    337 
    338 TEST_F(SvcTest, InitTwoLayers) {
    339   svc_.spatial_layers = 2;
    340   InitializeEncoder();
    341 }
    342 
    343 TEST_F(SvcTest, InvalidOptions) {
    344   vpx_codec_err_t res = vpx_svc_set_options(&svc_, NULL);
    345   EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
    346 
    347   res = vpx_svc_set_options(&svc_, "not-an-option=1");
    348   EXPECT_EQ(VPX_CODEC_OK, res);
    349   res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
    350   EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
    351 }
    352 
    353 TEST_F(SvcTest, SetLayersOption) {
    354   vpx_codec_err_t res = vpx_svc_set_options(&svc_, "spatial-layers=3");
    355   EXPECT_EQ(VPX_CODEC_OK, res);
    356   InitializeEncoder();
    357   EXPECT_EQ(3, svc_.spatial_layers);
    358 }
    359 
    360 TEST_F(SvcTest, SetMultipleOptions) {
    361   vpx_codec_err_t res =
    362       vpx_svc_set_options(&svc_, "spatial-layers=2 scale-factors=1/3,2/3");
    363   EXPECT_EQ(VPX_CODEC_OK, res);
    364   InitializeEncoder();
    365   EXPECT_EQ(2, svc_.spatial_layers);
    366 }
    367 
    368 TEST_F(SvcTest, SetScaleFactorsOption) {
    369   svc_.spatial_layers = 2;
    370   vpx_codec_err_t res =
    371       vpx_svc_set_options(&svc_, "scale-factors=not-scale-factors");
    372   EXPECT_EQ(VPX_CODEC_OK, res);
    373   res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
    374   EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
    375 
    376   res = vpx_svc_set_options(&svc_, "scale-factors=1/3, 3*3");
    377   EXPECT_EQ(VPX_CODEC_OK, res);
    378   res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
    379   EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
    380 
    381   res = vpx_svc_set_options(&svc_, "scale-factors=1/3");
    382   EXPECT_EQ(VPX_CODEC_OK, res);
    383   res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
    384   EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
    385 
    386   res = vpx_svc_set_options(&svc_, "scale-factors=1/3,2/3");
    387   EXPECT_EQ(VPX_CODEC_OK, res);
    388   InitializeEncoder();
    389 }
    390 
    391 TEST_F(SvcTest, SetQuantizersOption) {
    392   svc_.spatial_layers = 2;
    393   vpx_codec_err_t res = vpx_svc_set_options(&svc_, "max-quantizers=nothing");
    394   EXPECT_EQ(VPX_CODEC_OK, res);
    395   res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
    396   EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
    397 
    398   res = vpx_svc_set_options(&svc_, "min-quantizers=nothing");
    399   EXPECT_EQ(VPX_CODEC_OK, res);
    400   res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
    401   EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
    402 
    403   res = vpx_svc_set_options(&svc_, "max-quantizers=40");
    404   EXPECT_EQ(VPX_CODEC_OK, res);
    405   res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
    406   EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
    407 
    408   res = vpx_svc_set_options(&svc_, "min-quantizers=40");
    409   EXPECT_EQ(VPX_CODEC_OK, res);
    410   res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
    411   EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
    412 
    413   res = vpx_svc_set_options(&svc_, "max-quantizers=30,30 min-quantizers=40,40");
    414   EXPECT_EQ(VPX_CODEC_OK, res);
    415   res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
    416   EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
    417 
    418   res = vpx_svc_set_options(&svc_, "max-quantizers=40,40 min-quantizers=30,30");
    419   InitializeEncoder();
    420 }
    421 
    422 TEST_F(SvcTest, SetAutoAltRefOption) {
    423   svc_.spatial_layers = 5;
    424   vpx_codec_err_t res = vpx_svc_set_options(&svc_, "auto-alt-refs=none");
    425   EXPECT_EQ(VPX_CODEC_OK, res);
    426   res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
    427   EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
    428 
    429   res = vpx_svc_set_options(&svc_, "auto-alt-refs=1,1,1,1,0");
    430   EXPECT_EQ(VPX_CODEC_OK, res);
    431   res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
    432   EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
    433 
    434   vpx_svc_set_options(&svc_, "auto-alt-refs=0,1,1,1,0");
    435   InitializeEncoder();
    436 }
    437 
    438 // Test that decoder can handle an SVC frame as the first frame in a sequence.
    439 TEST_F(SvcTest, OnePassEncodeOneFrame) {
    440   codec_enc_.g_pass = VPX_RC_ONE_PASS;
    441   vpx_fixed_buf output = vpx_fixed_buf();
    442   Pass2EncodeNFrames(NULL, 1, 2, &output);
    443   DecodeNFrames(&output, 1);
    444   FreeBitstreamBuffers(&output, 1);
    445 }
    446 
    447 TEST_F(SvcTest, OnePassEncodeThreeFrames) {
    448   codec_enc_.g_pass = VPX_RC_ONE_PASS;
    449   codec_enc_.g_lag_in_frames = 0;
    450   vpx_fixed_buf outputs[3];
    451   memset(&outputs[0], 0, sizeof(outputs));
    452   Pass2EncodeNFrames(NULL, 3, 2, &outputs[0]);
    453   DecodeNFrames(&outputs[0], 3);
    454   FreeBitstreamBuffers(&outputs[0], 3);
    455 }
    456 
    457 TEST_F(SvcTest, TwoPassEncode10Frames) {
    458   // First pass encode
    459   std::string stats_buf;
    460   Pass1EncodeNFrames(10, 2, &stats_buf);
    461 
    462   // Second pass encode
    463   codec_enc_.g_pass = VPX_RC_LAST_PASS;
    464   vpx_fixed_buf outputs[10];
    465   memset(&outputs[0], 0, sizeof(outputs));
    466   Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]);
    467   DecodeNFrames(&outputs[0], 10);
    468   FreeBitstreamBuffers(&outputs[0], 10);
    469 }
    470 
    471 TEST_F(SvcTest, TwoPassEncode20FramesWithAltRef) {
    472   // First pass encode
    473   std::string stats_buf;
    474   Pass1EncodeNFrames(20, 2, &stats_buf);
    475 
    476   // Second pass encode
    477   codec_enc_.g_pass = VPX_RC_LAST_PASS;
    478   vpx_svc_set_options(&svc_, "auto-alt-refs=1,1");
    479   vpx_fixed_buf outputs[20];
    480   memset(&outputs[0], 0, sizeof(outputs));
    481   Pass2EncodeNFrames(&stats_buf, 20, 2, &outputs[0]);
    482   DecodeNFrames(&outputs[0], 20);
    483   FreeBitstreamBuffers(&outputs[0], 20);
    484 }
    485 
    486 TEST_F(SvcTest, TwoPassEncode2SpatialLayersDecodeBaseLayerOnly) {
    487   // First pass encode
    488   std::string stats_buf;
    489   Pass1EncodeNFrames(10, 2, &stats_buf);
    490 
    491   // Second pass encode
    492   codec_enc_.g_pass = VPX_RC_LAST_PASS;
    493   vpx_svc_set_options(&svc_, "auto-alt-refs=1,1");
    494   vpx_fixed_buf outputs[10];
    495   memset(&outputs[0], 0, sizeof(outputs));
    496   Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]);
    497   DropEnhancementLayers(&outputs[0], 10, 1);
    498   DecodeNFrames(&outputs[0], 10);
    499   FreeBitstreamBuffers(&outputs[0], 10);
    500 }
    501 
    502 TEST_F(SvcTest, TwoPassEncode5SpatialLayersDecode54321Layers) {
    503   // First pass encode
    504   std::string stats_buf;
    505   Pass1EncodeNFrames(10, 5, &stats_buf);
    506 
    507   // Second pass encode
    508   codec_enc_.g_pass = VPX_RC_LAST_PASS;
    509   vpx_svc_set_options(&svc_, "auto-alt-refs=0,1,1,1,0");
    510   vpx_fixed_buf outputs[10];
    511   memset(&outputs[0], 0, sizeof(outputs));
    512   Pass2EncodeNFrames(&stats_buf, 10, 5, &outputs[0]);
    513 
    514   DecodeNFrames(&outputs[0], 10);
    515   DropEnhancementLayers(&outputs[0], 10, 4);
    516   DecodeNFrames(&outputs[0], 10);
    517   DropEnhancementLayers(&outputs[0], 10, 3);
    518   DecodeNFrames(&outputs[0], 10);
    519   DropEnhancementLayers(&outputs[0], 10, 2);
    520   DecodeNFrames(&outputs[0], 10);
    521   DropEnhancementLayers(&outputs[0], 10, 1);
    522   DecodeNFrames(&outputs[0], 10);
    523 
    524   FreeBitstreamBuffers(&outputs[0], 10);
    525 }
    526 
    527 TEST_F(SvcTest, TwoPassEncode2SNRLayers) {
    528   // First pass encode
    529   std::string stats_buf;
    530   vpx_svc_set_options(&svc_, "scale-factors=1/1,1/1");
    531   Pass1EncodeNFrames(20, 2, &stats_buf);
    532 
    533   // Second pass encode
    534   codec_enc_.g_pass = VPX_RC_LAST_PASS;
    535   vpx_svc_set_options(&svc_, "auto-alt-refs=1,1 scale-factors=1/1,1/1");
    536   vpx_fixed_buf outputs[20];
    537   memset(&outputs[0], 0, sizeof(outputs));
    538   Pass2EncodeNFrames(&stats_buf, 20, 2, &outputs[0]);
    539   DecodeNFrames(&outputs[0], 20);
    540   FreeBitstreamBuffers(&outputs[0], 20);
    541 }
    542 
    543 TEST_F(SvcTest, TwoPassEncode3SNRLayersDecode321Layers) {
    544   // First pass encode
    545   std::string stats_buf;
    546   vpx_svc_set_options(&svc_, "scale-factors=1/1,1/1,1/1");
    547   Pass1EncodeNFrames(20, 3, &stats_buf);
    548 
    549   // Second pass encode
    550   codec_enc_.g_pass = VPX_RC_LAST_PASS;
    551   vpx_svc_set_options(&svc_, "auto-alt-refs=1,1,1 scale-factors=1/1,1/1,1/1");
    552   vpx_fixed_buf outputs[20];
    553   memset(&outputs[0], 0, sizeof(outputs));
    554   Pass2EncodeNFrames(&stats_buf, 20, 3, &outputs[0]);
    555   DecodeNFrames(&outputs[0], 20);
    556   DropEnhancementLayers(&outputs[0], 20, 2);
    557   DecodeNFrames(&outputs[0], 20);
    558   DropEnhancementLayers(&outputs[0], 20, 1);
    559   DecodeNFrames(&outputs[0], 20);
    560 
    561   FreeBitstreamBuffers(&outputs[0], 20);
    562 }
    563 
    564 TEST_F(SvcTest, SetMultipleFrameContextsOption) {
    565   svc_.spatial_layers = 5;
    566   vpx_codec_err_t res = vpx_svc_set_options(&svc_, "multi-frame-contexts=1");
    567   EXPECT_EQ(VPX_CODEC_OK, res);
    568   res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
    569   EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
    570 
    571   svc_.spatial_layers = 2;
    572   res = vpx_svc_set_options(&svc_, "multi-frame-contexts=1");
    573   InitializeEncoder();
    574 }
    575 
    576 TEST_F(SvcTest, TwoPassEncode2SpatialLayersWithMultipleFrameContexts) {
    577   // First pass encode
    578   std::string stats_buf;
    579   Pass1EncodeNFrames(10, 2, &stats_buf);
    580 
    581   // Second pass encode
    582   codec_enc_.g_pass = VPX_RC_LAST_PASS;
    583   codec_enc_.g_error_resilient = 0;
    584   vpx_svc_set_options(&svc_, "auto-alt-refs=1,1 multi-frame-contexts=1");
    585   vpx_fixed_buf outputs[10];
    586   memset(&outputs[0], 0, sizeof(outputs));
    587   Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]);
    588   DecodeNFrames(&outputs[0], 10);
    589   FreeBitstreamBuffers(&outputs[0], 10);
    590 }
    591 
    592 TEST_F(SvcTest,
    593        TwoPassEncode2SpatialLayersWithMultipleFrameContextsDecodeBaselayer) {
    594   // First pass encode
    595   std::string stats_buf;
    596   Pass1EncodeNFrames(10, 2, &stats_buf);
    597 
    598   // Second pass encode
    599   codec_enc_.g_pass = VPX_RC_LAST_PASS;
    600   codec_enc_.g_error_resilient = 0;
    601   vpx_svc_set_options(&svc_, "auto-alt-refs=1,1 multi-frame-contexts=1");
    602   vpx_fixed_buf outputs[10];
    603   memset(&outputs[0], 0, sizeof(outputs));
    604   Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]);
    605   DropEnhancementLayers(&outputs[0], 10, 1);
    606   DecodeNFrames(&outputs[0], 10);
    607   FreeBitstreamBuffers(&outputs[0], 10);
    608 }
    609 
    610 TEST_F(SvcTest, TwoPassEncode2SNRLayersWithMultipleFrameContexts) {
    611   // First pass encode
    612   std::string stats_buf;
    613   vpx_svc_set_options(&svc_, "scale-factors=1/1,1/1");
    614   Pass1EncodeNFrames(10, 2, &stats_buf);
    615 
    616   // Second pass encode
    617   codec_enc_.g_pass = VPX_RC_LAST_PASS;
    618   codec_enc_.g_error_resilient = 0;
    619   vpx_svc_set_options(&svc_,
    620                       "auto-alt-refs=1,1 scale-factors=1/1,1/1 "
    621                       "multi-frame-contexts=1");
    622   vpx_fixed_buf outputs[10];
    623   memset(&outputs[0], 0, sizeof(outputs));
    624   Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]);
    625   DecodeNFrames(&outputs[0], 10);
    626   FreeBitstreamBuffers(&outputs[0], 10);
    627 }
    628 
    629 TEST_F(SvcTest,
    630        TwoPassEncode3SNRLayersWithMultipleFrameContextsDecode321Layer) {
    631   // First pass encode
    632   std::string stats_buf;
    633   vpx_svc_set_options(&svc_, "scale-factors=1/1,1/1,1/1");
    634   Pass1EncodeNFrames(10, 3, &stats_buf);
    635 
    636   // Second pass encode
    637   codec_enc_.g_pass = VPX_RC_LAST_PASS;
    638   codec_enc_.g_error_resilient = 0;
    639   vpx_svc_set_options(&svc_,
    640                       "auto-alt-refs=1,1,1 scale-factors=1/1,1/1,1/1 "
    641                       "multi-frame-contexts=1");
    642   vpx_fixed_buf outputs[10];
    643   memset(&outputs[0], 0, sizeof(outputs));
    644   Pass2EncodeNFrames(&stats_buf, 10, 3, &outputs[0]);
    645 
    646   DecodeNFrames(&outputs[0], 10);
    647   DropEnhancementLayers(&outputs[0], 10, 2);
    648   DecodeNFrames(&outputs[0], 10);
    649   DropEnhancementLayers(&outputs[0], 10, 1);
    650   DecodeNFrames(&outputs[0], 10);
    651 
    652   FreeBitstreamBuffers(&outputs[0], 10);
    653 }
    654 
    655 TEST_F(SvcTest, TwoPassEncode2TemporalLayers) {
    656   // First pass encode
    657   std::string stats_buf;
    658   vpx_svc_set_options(&svc_, "scale-factors=1/1");
    659   svc_.temporal_layers = 2;
    660   Pass1EncodeNFrames(10, 1, &stats_buf);
    661 
    662   // Second pass encode
    663   codec_enc_.g_pass = VPX_RC_LAST_PASS;
    664   svc_.temporal_layers = 2;
    665   vpx_svc_set_options(&svc_, "auto-alt-refs=1 scale-factors=1/1");
    666   vpx_fixed_buf outputs[10];
    667   memset(&outputs[0], 0, sizeof(outputs));
    668   Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]);
    669   DecodeNFrames(&outputs[0], 10);
    670   FreeBitstreamBuffers(&outputs[0], 10);
    671 }
    672 
    673 TEST_F(SvcTest, TwoPassEncode2TemporalLayersWithMultipleFrameContexts) {
    674   // First pass encode
    675   std::string stats_buf;
    676   vpx_svc_set_options(&svc_, "scale-factors=1/1");
    677   svc_.temporal_layers = 2;
    678   Pass1EncodeNFrames(10, 1, &stats_buf);
    679 
    680   // Second pass encode
    681   codec_enc_.g_pass = VPX_RC_LAST_PASS;
    682   svc_.temporal_layers = 2;
    683   codec_enc_.g_error_resilient = 0;
    684   vpx_svc_set_options(&svc_,
    685                       "auto-alt-refs=1 scale-factors=1/1 "
    686                       "multi-frame-contexts=1");
    687   vpx_fixed_buf outputs[10];
    688   memset(&outputs[0], 0, sizeof(outputs));
    689   Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]);
    690   DecodeNFrames(&outputs[0], 10);
    691   FreeBitstreamBuffers(&outputs[0], 10);
    692 }
    693 
    694 TEST_F(SvcTest, TwoPassEncode2TemporalLayersDecodeBaseLayer) {
    695   // First pass encode
    696   std::string stats_buf;
    697   vpx_svc_set_options(&svc_, "scale-factors=1/1");
    698   svc_.temporal_layers = 2;
    699   Pass1EncodeNFrames(10, 1, &stats_buf);
    700 
    701   // Second pass encode
    702   codec_enc_.g_pass = VPX_RC_LAST_PASS;
    703   svc_.temporal_layers = 2;
    704   vpx_svc_set_options(&svc_, "auto-alt-refs=1 scale-factors=1/1");
    705   vpx_fixed_buf outputs[10];
    706   memset(&outputs[0], 0, sizeof(outputs));
    707   Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]);
    708 
    709   vpx_fixed_buf base_layer[5];
    710   for (int i = 0; i < 5; ++i) base_layer[i] = outputs[i * 2];
    711 
    712   DecodeNFrames(&base_layer[0], 5);
    713   FreeBitstreamBuffers(&outputs[0], 10);
    714 }
    715 
    716 TEST_F(SvcTest,
    717        TwoPassEncode2TemporalLayersWithMultipleFrameContextsDecodeBaseLayer) {
    718   // First pass encode
    719   std::string stats_buf;
    720   vpx_svc_set_options(&svc_, "scale-factors=1/1");
    721   svc_.temporal_layers = 2;
    722   Pass1EncodeNFrames(10, 1, &stats_buf);
    723 
    724   // Second pass encode
    725   codec_enc_.g_pass = VPX_RC_LAST_PASS;
    726   svc_.temporal_layers = 2;
    727   codec_enc_.g_error_resilient = 0;
    728   vpx_svc_set_options(&svc_,
    729                       "auto-alt-refs=1 scale-factors=1/1 "
    730                       "multi-frame-contexts=1");
    731   vpx_fixed_buf outputs[10];
    732   memset(&outputs[0], 0, sizeof(outputs));
    733   Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]);
    734 
    735   vpx_fixed_buf base_layer[5];
    736   for (int i = 0; i < 5; ++i) base_layer[i] = outputs[i * 2];
    737 
    738   DecodeNFrames(&base_layer[0], 5);
    739   FreeBitstreamBuffers(&outputs[0], 10);
    740 }
    741 
    742 TEST_F(SvcTest, TwoPassEncode2TemporalLayersWithTiles) {
    743   // First pass encode
    744   std::string stats_buf;
    745   vpx_svc_set_options(&svc_, "scale-factors=1/1");
    746   svc_.temporal_layers = 2;
    747   Pass1EncodeNFrames(10, 1, &stats_buf);
    748 
    749   // Second pass encode
    750   codec_enc_.g_pass = VPX_RC_LAST_PASS;
    751   svc_.temporal_layers = 2;
    752   vpx_svc_set_options(&svc_, "auto-alt-refs=1 scale-factors=1/1");
    753   codec_enc_.g_w = 704;
    754   codec_enc_.g_h = 144;
    755   tile_columns_ = 1;
    756   tile_rows_ = 1;
    757   vpx_fixed_buf outputs[10];
    758   memset(&outputs[0], 0, sizeof(outputs));
    759   Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]);
    760   DecodeNFrames(&outputs[0], 10);
    761   FreeBitstreamBuffers(&outputs[0], 10);
    762 }
    763 
    764 TEST_F(SvcTest, TwoPassEncode2TemporalLayersWithMultipleFrameContextsAndTiles) {
    765   // First pass encode
    766   std::string stats_buf;
    767   vpx_svc_set_options(&svc_, "scale-factors=1/1");
    768   svc_.temporal_layers = 2;
    769   Pass1EncodeNFrames(10, 1, &stats_buf);
    770 
    771   // Second pass encode
    772   codec_enc_.g_pass = VPX_RC_LAST_PASS;
    773   svc_.temporal_layers = 2;
    774   codec_enc_.g_error_resilient = 0;
    775   codec_enc_.g_w = 704;
    776   codec_enc_.g_h = 144;
    777   tile_columns_ = 1;
    778   tile_rows_ = 1;
    779   vpx_svc_set_options(&svc_,
    780                       "auto-alt-refs=1 scale-factors=1/1 "
    781                       "multi-frame-contexts=1");
    782   vpx_fixed_buf outputs[10];
    783   memset(&outputs[0], 0, sizeof(outputs));
    784   Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]);
    785   DecodeNFrames(&outputs[0], 10);
    786   FreeBitstreamBuffers(&outputs[0], 10);
    787 }
    788 
    789 }  // namespace
    790