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
23namespace {
24
25using libvpx_test::CodecFactory;
26using libvpx_test::Decoder;
27using libvpx_test::DxDataIterator;
28using libvpx_test::VP9CodecFactory;
29
30class 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
317TEST_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
338TEST_F(SvcTest, InitTwoLayers) {
339  svc_.spatial_layers = 2;
340  InitializeEncoder();
341}
342
343TEST_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
353TEST_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
360TEST_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
368TEST_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
391TEST_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
422TEST_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.
439TEST_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
447TEST_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
457TEST_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
471TEST_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
486TEST_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
502TEST_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
527TEST_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
543TEST_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
564TEST_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
576TEST_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
592TEST_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
610TEST_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
629TEST_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
655TEST_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
673TEST_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
694TEST_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
716TEST_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
742TEST_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
764TEST_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