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
SvcTest()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
~SvcTest()43 virtual ~SvcTest() {}
44
SetUp()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
TearDown()69 virtual void TearDown() {
70 ReleaseEncoder();
71 delete (decoder_);
72 }
73
InitializeEncoder()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
ReleaseEncoder()84 void ReleaseEncoder() {
85 vpx_svc_release(&svc_);
86 if (codec_initialized_) vpx_codec_destroy(&codec_);
87 codec_initialized_ = false;
88 }
89
GetStatsData(std::string * const stats_buf)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
Pass1EncodeNFrames(const int n,const int layers,std::string * const stats_buf)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
StoreFrames(const size_t max_frame_received,struct vpx_fixed_buf * const outputs,size_t * const frame_received)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
Pass2EncodeNFrames(std::string * const stats_buf,const int n,const int layers,struct vpx_fixed_buf * const outputs)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
DecodeNFrames(const struct vpx_fixed_buf * const inputs,const int n)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
DropEnhancementLayers(struct vpx_fixed_buf * const inputs,const int num_super_frames,const int remained_spatial_layers)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
FreeBitstreamBuffers(struct vpx_fixed_buf * const inputs,const int n)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
TEST_F(SvcTest,SvcInit)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
TEST_F(SvcTest,InitTwoLayers)338 TEST_F(SvcTest, InitTwoLayers) {
339 svc_.spatial_layers = 2;
340 InitializeEncoder();
341 }
342
TEST_F(SvcTest,InvalidOptions)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
TEST_F(SvcTest,SetLayersOption)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
TEST_F(SvcTest,SetMultipleOptions)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
TEST_F(SvcTest,SetScaleFactorsOption)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
TEST_F(SvcTest,SetQuantizersOption)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
TEST_F(SvcTest,SetAutoAltRefOption)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.
TEST_F(SvcTest,OnePassEncodeOneFrame)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
TEST_F(SvcTest,OnePassEncodeThreeFrames)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
TEST_F(SvcTest,TwoPassEncode10Frames)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
TEST_F(SvcTest,TwoPassEncode20FramesWithAltRef)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
TEST_F(SvcTest,TwoPassEncode2SpatialLayersDecodeBaseLayerOnly)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
TEST_F(SvcTest,TwoPassEncode5SpatialLayersDecode54321Layers)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
TEST_F(SvcTest,TwoPassEncode2SNRLayers)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
TEST_F(SvcTest,TwoPassEncode3SNRLayersDecode321Layers)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
TEST_F(SvcTest,SetMultipleFrameContextsOption)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
TEST_F(SvcTest,TwoPassEncode2SpatialLayersWithMultipleFrameContexts)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
TEST_F(SvcTest,TwoPassEncode2SpatialLayersWithMultipleFrameContextsDecodeBaselayer)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
TEST_F(SvcTest,TwoPassEncode2SNRLayersWithMultipleFrameContexts)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
TEST_F(SvcTest,TwoPassEncode3SNRLayersWithMultipleFrameContextsDecode321Layer)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
TEST_F(SvcTest,TwoPassEncode2TemporalLayers)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
TEST_F(SvcTest,TwoPassEncode2TemporalLayersWithMultipleFrameContexts)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
TEST_F(SvcTest,TwoPassEncode2TemporalLayersDecodeBaseLayer)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
TEST_F(SvcTest,TwoPassEncode2TemporalLayersWithMultipleFrameContextsDecodeBaseLayer)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
TEST_F(SvcTest,TwoPassEncode2TemporalLayersWithTiles)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
TEST_F(SvcTest,TwoPassEncode2TemporalLayersWithMultipleFrameContextsAndTiles)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