2 * Copyright (c) 2013 The WebM project authors. All Rights Reserved.
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.
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"
17 #include "vp9/decoder/vp9_decoder.h"
19 #include "vpx/svc_context.h"
20 #include "vpx/vp8cx.h"
21 #include "vpx/vpx_encoder.h"
25 using libvpx_test::CodecFactory;
26 using libvpx_test::Decoder;
27 using libvpx_test::DxDataIterator;
28 using libvpx_test::VP9CodecFactory;
30 class SvcTest : public ::testing::Test {
32 static const uint32_t kWidth = 352;
33 static const uint32_t kHeight = 288;
37 test_file_name_("hantro_collage_w352h288.yuv"),
38 codec_initialized_(false),
40 memset(&svc_, 0, sizeof(svc_));
41 memset(&codec_, 0, sizeof(codec_));
42 memset(&codec_enc_, 0, sizeof(codec_enc_));
47 virtual void SetUp() {
48 svc_.log_level = SVC_LOG_DEBUG;
51 codec_iface_ = vpx_codec_vp9_cx();
52 const vpx_codec_err_t res =
53 vpx_codec_enc_config_default(codec_iface_, &codec_enc_, 0);
54 EXPECT_EQ(VPX_CODEC_OK, res);
56 codec_enc_.g_w = kWidth;
57 codec_enc_.g_h = kHeight;
58 codec_enc_.g_timebase.num = 1;
59 codec_enc_.g_timebase.den = 60;
60 codec_enc_.kf_min_dist = 100;
61 codec_enc_.kf_max_dist = 100;
63 vpx_codec_dec_cfg_t dec_cfg = {0};
64 VP9CodecFactory codec_factory;
65 decoder_ = codec_factory.CreateDecoder(dec_cfg, 0);
68 virtual void TearDown() {
73 void InitializeEncoder() {
74 const vpx_codec_err_t res =
75 vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
76 EXPECT_EQ(VPX_CODEC_OK, res);
77 codec_initialized_ = true;
80 void ReleaseEncoder() {
81 vpx_svc_release(&svc_);
82 if (codec_initialized_) vpx_codec_destroy(&codec_);
83 codec_initialized_ = false;
86 void Pass1EncodeNFrames(const int n, const int layers,
87 std::string *const stats_buf) {
89 size_t stats_size = 0;
90 const char *stats_data = NULL;
94 svc_.spatial_layers = layers;
95 codec_enc_.g_pass = VPX_RC_FIRST_PASS;
98 libvpx_test::I420VideoSource video(test_file_name_, kWidth, kHeight,
99 codec_enc_.g_timebase.den,
100 codec_enc_.g_timebase.num, 0, 30);
103 for (int i = 0; i < n; ++i) {
104 res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
105 video.duration(), VPX_DL_GOOD_QUALITY);
106 ASSERT_EQ(VPX_CODEC_OK, res);
107 stats_size = vpx_svc_get_rc_stats_buffer_size(&svc_);
108 EXPECT_GT(stats_size, 0U);
109 stats_data = vpx_svc_get_rc_stats_buffer(&svc_);
110 ASSERT_TRUE(stats_data != NULL);
111 stats_buf->append(stats_data, stats_size);
115 // Flush encoder and test EOS packet
116 res = vpx_svc_encode(&svc_, &codec_, NULL, video.pts(),
117 video.duration(), VPX_DL_GOOD_QUALITY);
118 stats_size = vpx_svc_get_rc_stats_buffer_size(&svc_);
119 EXPECT_GT(stats_size, 0U);
120 stats_data = vpx_svc_get_rc_stats_buffer(&svc_);
121 ASSERT_TRUE(stats_data != NULL);
122 stats_buf->append(stats_data, stats_size);
127 void StoreFrames(const size_t max_frame_received,
128 struct vpx_fixed_buf *const outputs,
129 size_t *const frame_received) {
131 while ((frame_size = vpx_svc_get_frame_size(&svc_)) > 0) {
132 ASSERT_LT(*frame_received, max_frame_received);
134 if (*frame_received == 0) {
135 EXPECT_EQ(1, vpx_svc_is_keyframe(&svc_));
138 outputs[*frame_received].buf = malloc(frame_size);
139 ASSERT_TRUE(outputs[*frame_received].buf != NULL);
140 memcpy(outputs[*frame_received].buf, vpx_svc_get_buffer(&svc_),
142 outputs[*frame_received].sz = frame_size;
147 void Pass2EncodeNFrames(std::string *const stats_buf,
148 const int n, const int layers,
149 struct vpx_fixed_buf *const outputs) {
151 size_t frame_received = 0;
153 ASSERT_TRUE(outputs != NULL);
155 ASSERT_GT(layers, 0);
156 svc_.spatial_layers = layers;
157 codec_enc_.rc_target_bitrate = 500;
158 if (codec_enc_.g_pass == VPX_RC_LAST_PASS) {
159 ASSERT_TRUE(stats_buf != NULL);
160 ASSERT_GT(stats_buf->size(), 0U);
161 codec_enc_.rc_twopass_stats_in.buf = &(*stats_buf)[0];
162 codec_enc_.rc_twopass_stats_in.sz = stats_buf->size();
166 libvpx_test::I420VideoSource video(test_file_name_, kWidth, kHeight,
167 codec_enc_.g_timebase.den,
168 codec_enc_.g_timebase.num, 0, 30);
171 for (int i = 0; i < n; ++i) {
172 res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
173 video.duration(), VPX_DL_GOOD_QUALITY);
174 ASSERT_EQ(VPX_CODEC_OK, res);
175 StoreFrames(n, outputs, &frame_received);
180 res = vpx_svc_encode(&svc_, &codec_, NULL, 0,
181 video.duration(), VPX_DL_GOOD_QUALITY);
182 EXPECT_EQ(VPX_CODEC_OK, res);
183 StoreFrames(n, outputs, &frame_received);
185 EXPECT_EQ(frame_received, (size_t)n);
190 void DecodeNFrames(const struct vpx_fixed_buf *const inputs, const int n) {
191 int decoded_frames = 0;
192 int received_frames = 0;
194 ASSERT_TRUE(inputs != NULL);
197 for (int i = 0; i < n; ++i) {
198 ASSERT_TRUE(inputs[i].buf != NULL);
199 ASSERT_GT(inputs[i].sz, 0U);
200 const vpx_codec_err_t res_dec =
201 decoder_->DecodeFrame(static_cast<const uint8_t *>(inputs[i].buf),
203 ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError();
206 DxDataIterator dec_iter = decoder_->GetDxData();
207 while (dec_iter.Next()) {
211 EXPECT_EQ(decoded_frames, n);
212 EXPECT_EQ(received_frames, n);
215 void DropEnhancementLayers(struct vpx_fixed_buf *const inputs,
216 const int num_super_frames,
217 const int remained_layers) {
218 ASSERT_TRUE(inputs != NULL);
219 ASSERT_GT(num_super_frames, 0);
220 ASSERT_GT(remained_layers, 0);
222 for (int i = 0; i < num_super_frames; ++i) {
223 uint32_t frame_sizes[8] = {0};
225 int frames_found = 0;
227 ASSERT_TRUE(inputs[i].buf != NULL);
228 ASSERT_GT(inputs[i].sz, 0U);
230 vpx_codec_err_t res =
231 vp9_parse_superframe_index(static_cast<const uint8_t*>(inputs[i].buf),
232 inputs[i].sz, frame_sizes, &frame_count,
234 ASSERT_EQ(VPX_CODEC_OK, res);
236 uint8_t *frame_data = static_cast<uint8_t *>(inputs[i].buf);
237 uint8_t *frame_start = frame_data;
238 for (frame = 0; frame < frame_count; ++frame) {
239 // Looking for a visible frame
240 if (frame_data[0] & 0x02) {
242 if (frames_found == remained_layers)
245 frame_data += frame_sizes[frame];
247 ASSERT_LT(frame, frame_count);
248 if (frame == frame_count - 1)
251 frame_data += frame_sizes[frame];
253 static_cast<const uint8_t *>(inputs[i].buf)[inputs[i].sz - 1];
254 const uint32_t mag = ((marker >> 3) & 0x3) + 1;
255 const size_t index_sz = 2 + mag * frame_count;
256 const size_t new_index_sz = 2 + mag * (frame + 1);
259 frame_data[0] = marker;
260 memcpy(frame_data + 1, frame_start + inputs[i].sz - index_sz + 1,
262 frame_data[new_index_sz - 1] = marker;
263 inputs[i].sz = frame_data - frame_start + new_index_sz;
267 void FreeBitstreamBuffers(struct vpx_fixed_buf *const inputs, const int n) {
268 ASSERT_TRUE(inputs != NULL);
271 for (int i = 0; i < n; ++i) {
273 inputs[i].buf = NULL;
279 vpx_codec_ctx_t codec_;
280 struct vpx_codec_enc_cfg codec_enc_;
281 vpx_codec_iface_t *codec_iface_;
282 std::string test_file_name_;
283 bool codec_initialized_;
287 TEST_F(SvcTest, SvcInit) {
288 // test missing parameters
289 vpx_codec_err_t res = vpx_svc_init(NULL, &codec_, codec_iface_, &codec_enc_);
290 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
291 res = vpx_svc_init(&svc_, NULL, codec_iface_, &codec_enc_);
292 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
293 res = vpx_svc_init(&svc_, &codec_, NULL, &codec_enc_);
294 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
296 res = vpx_svc_init(&svc_, &codec_, codec_iface_, NULL);
297 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
299 svc_.spatial_layers = 6; // too many layers
300 res = vpx_svc_init(&svc_, &codec_, codec_iface_, &codec_enc_);
301 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
303 svc_.spatial_layers = 0; // use default layers
305 EXPECT_EQ(VPX_SS_DEFAULT_LAYERS, svc_.spatial_layers);
308 TEST_F(SvcTest, InitTwoLayers) {
309 svc_.spatial_layers = 2;
310 vpx_svc_set_scale_factors(&svc_, "4/16,16*16"); // invalid scale values
311 vpx_codec_err_t res = vpx_svc_init(&svc_, &codec_, codec_iface_, &codec_enc_);
312 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
314 vpx_svc_set_scale_factors(&svc_, "4/16,16/16"); // valid scale values
318 TEST_F(SvcTest, InvalidOptions) {
319 vpx_codec_err_t res = vpx_svc_set_options(&svc_, NULL);
320 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
322 res = vpx_svc_set_options(&svc_, "not-an-option=1");
323 EXPECT_EQ(VPX_CODEC_OK, res);
324 res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
325 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
328 TEST_F(SvcTest, SetLayersOption) {
329 vpx_codec_err_t res = vpx_svc_set_options(&svc_, "layers=3");
330 EXPECT_EQ(VPX_CODEC_OK, res);
332 EXPECT_EQ(3, svc_.spatial_layers);
335 TEST_F(SvcTest, SetMultipleOptions) {
336 vpx_codec_err_t res =
337 vpx_svc_set_options(&svc_, "layers=2 scale-factors=1/3,2/3");
338 EXPECT_EQ(VPX_CODEC_OK, res);
340 EXPECT_EQ(2, svc_.spatial_layers);
343 TEST_F(SvcTest, SetScaleFactorsOption) {
344 svc_.spatial_layers = 2;
345 vpx_codec_err_t res =
346 vpx_svc_set_options(&svc_, "scale-factors=not-scale-factors");
347 EXPECT_EQ(VPX_CODEC_OK, res);
348 res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
349 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
351 res = vpx_svc_set_options(&svc_, "scale-factors=1/3,2/3");
352 EXPECT_EQ(VPX_CODEC_OK, res);
356 TEST_F(SvcTest, SetQuantizersOption) {
357 svc_.spatial_layers = 2;
358 vpx_codec_err_t res = vpx_svc_set_options(&svc_, "quantizers=not-quantizers");
359 EXPECT_EQ(VPX_CODEC_OK, res);
360 res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
361 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
363 vpx_svc_set_options(&svc_, "quantizers=40,45");
367 TEST_F(SvcTest, SetAutoAltRefOption) {
368 svc_.spatial_layers = 5;
369 vpx_codec_err_t res = vpx_svc_set_options(&svc_, "auto-alt-refs=none");
370 EXPECT_EQ(VPX_CODEC_OK, res);
371 res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
372 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
374 res = vpx_svc_set_options(&svc_, "auto-alt-refs=1,1,1,1,0");
375 EXPECT_EQ(VPX_CODEC_OK, res);
376 res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
377 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
379 vpx_svc_set_options(&svc_, "auto-alt-refs=0,1,1,1,0");
383 TEST_F(SvcTest, SetQuantizers) {
384 vpx_codec_err_t res = vpx_svc_set_quantizers(NULL, "40,30");
385 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
387 res = vpx_svc_set_quantizers(&svc_, NULL);
388 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
390 svc_.spatial_layers = 2;
391 res = vpx_svc_set_quantizers(&svc_, "40");
392 EXPECT_EQ(VPX_CODEC_OK, res);
393 res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
394 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
396 res = vpx_svc_set_quantizers(&svc_, "40,30");
397 EXPECT_EQ(VPX_CODEC_OK, res);
401 TEST_F(SvcTest, SetScaleFactors) {
402 vpx_codec_err_t res = vpx_svc_set_scale_factors(NULL, "4/16,16/16");
403 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
405 res = vpx_svc_set_scale_factors(&svc_, NULL);
406 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
408 svc_.spatial_layers = 2;
409 res = vpx_svc_set_scale_factors(&svc_, "4/16");
410 EXPECT_EQ(VPX_CODEC_OK, res);
411 res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
412 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
414 res = vpx_svc_set_scale_factors(&svc_, "4/16,16/16");
415 EXPECT_EQ(VPX_CODEC_OK, res);
419 // Test that decoder can handle an SVC frame as the first frame in a sequence.
420 TEST_F(SvcTest, OnePassEncodeOneFrame) {
421 codec_enc_.g_pass = VPX_RC_ONE_PASS;
422 vpx_fixed_buf output = {0};
423 Pass2EncodeNFrames(NULL, 1, 2, &output);
424 DecodeNFrames(&output, 1);
425 FreeBitstreamBuffers(&output, 1);
428 TEST_F(SvcTest, OnePassEncodeThreeFrames) {
429 codec_enc_.g_pass = VPX_RC_ONE_PASS;
430 vpx_fixed_buf outputs[3];
431 memset(&outputs[0], 0, sizeof(outputs));
432 Pass2EncodeNFrames(NULL, 3, 2, &outputs[0]);
433 DecodeNFrames(&outputs[0], 3);
434 FreeBitstreamBuffers(&outputs[0], 3);
437 TEST_F(SvcTest, GetLayerResolution) {
438 svc_.spatial_layers = 2;
439 vpx_svc_set_scale_factors(&svc_, "4/16,8/16");
440 vpx_svc_set_quantizers(&svc_, "40,30");
444 // ensure that requested layer is a valid layer
445 uint32_t layer_width, layer_height;
446 vpx_codec_err_t res = vpx_svc_get_layer_resolution(&svc_, svc_.spatial_layers,
447 &layer_width, &layer_height);
448 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
450 res = vpx_svc_get_layer_resolution(NULL, 0, &layer_width, &layer_height);
451 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
453 res = vpx_svc_get_layer_resolution(&svc_, 0, NULL, &layer_height);
454 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
456 res = vpx_svc_get_layer_resolution(&svc_, 0, &layer_width, NULL);
457 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
459 res = vpx_svc_get_layer_resolution(&svc_, 0, &layer_width, &layer_height);
460 EXPECT_EQ(VPX_CODEC_OK, res);
461 EXPECT_EQ(kWidth * 4 / 16, layer_width);
462 EXPECT_EQ(kHeight * 4 / 16, layer_height);
464 res = vpx_svc_get_layer_resolution(&svc_, 1, &layer_width, &layer_height);
465 EXPECT_EQ(VPX_CODEC_OK, res);
466 EXPECT_EQ(kWidth * 8 / 16, layer_width);
467 EXPECT_EQ(kHeight * 8 / 16, layer_height);
470 TEST_F(SvcTest, TwoPassEncode10Frames) {
472 std::string stats_buf;
473 Pass1EncodeNFrames(10, 2, &stats_buf);
475 // Second pass encode
476 codec_enc_.g_pass = VPX_RC_LAST_PASS;
477 vpx_fixed_buf outputs[10];
478 memset(&outputs[0], 0, sizeof(outputs));
479 Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]);
480 DecodeNFrames(&outputs[0], 10);
481 FreeBitstreamBuffers(&outputs[0], 10);
484 TEST_F(SvcTest, TwoPassEncode20FramesWithAltRef) {
486 std::string stats_buf;
487 Pass1EncodeNFrames(20, 2, &stats_buf);
489 // Second pass encode
490 codec_enc_.g_pass = VPX_RC_LAST_PASS;
491 vpx_svc_set_options(&svc_, "auto-alt-refs=1,1");
492 vpx_fixed_buf outputs[20];
493 memset(&outputs[0], 0, sizeof(outputs));
494 Pass2EncodeNFrames(&stats_buf, 20, 2, &outputs[0]);
495 DecodeNFrames(&outputs[0], 20);
496 FreeBitstreamBuffers(&outputs[0], 20);
499 TEST_F(SvcTest, TwoPassEncode2LayersDecodeBaseLayerOnly) {
501 std::string stats_buf;
502 Pass1EncodeNFrames(10, 2, &stats_buf);
504 // Second pass encode
505 codec_enc_.g_pass = VPX_RC_LAST_PASS;
506 vpx_svc_set_options(&svc_, "auto-alt-refs=1,1");
507 vpx_fixed_buf outputs[10];
508 memset(&outputs[0], 0, sizeof(outputs));
509 Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]);
510 DropEnhancementLayers(&outputs[0], 10, 1);
511 DecodeNFrames(&outputs[0], 10);
512 FreeBitstreamBuffers(&outputs[0], 10);
515 TEST_F(SvcTest, TwoPassEncode5LayersDecode54321Layers) {
517 std::string stats_buf;
518 Pass1EncodeNFrames(10, 5, &stats_buf);
520 // Second pass encode
521 codec_enc_.g_pass = VPX_RC_LAST_PASS;
522 vpx_svc_set_options(&svc_, "auto-alt-refs=0,1,1,1,0");
523 vpx_fixed_buf outputs[10];
524 memset(&outputs[0], 0, sizeof(outputs));
525 Pass2EncodeNFrames(&stats_buf, 10, 5, &outputs[0]);
527 DecodeNFrames(&outputs[0], 10);
528 DropEnhancementLayers(&outputs[0], 10, 4);
529 DecodeNFrames(&outputs[0], 10);
530 DropEnhancementLayers(&outputs[0], 10, 3);
531 DecodeNFrames(&outputs[0], 10);
532 DropEnhancementLayers(&outputs[0], 10, 2);
533 DecodeNFrames(&outputs[0], 10);
534 DropEnhancementLayers(&outputs[0], 10, 1);
535 DecodeNFrames(&outputs[0], 10);
537 FreeBitstreamBuffers(&outputs[0], 10);
540 TEST_F(SvcTest, TwoPassEncode2SNRLayers) {
542 std::string stats_buf;
543 vpx_svc_set_options(&svc_, "scale-factors=1/1,1/1");
544 Pass1EncodeNFrames(20, 2, &stats_buf);
546 // Second pass encode
547 codec_enc_.g_pass = VPX_RC_LAST_PASS;
548 vpx_svc_set_options(&svc_,
549 "auto-alt-refs=1,1 scale-factors=1/1,1/1");
550 vpx_fixed_buf outputs[20];
551 memset(&outputs[0], 0, sizeof(outputs));
552 Pass2EncodeNFrames(&stats_buf, 20, 2, &outputs[0]);
553 DecodeNFrames(&outputs[0], 20);
554 FreeBitstreamBuffers(&outputs[0], 20);
557 TEST_F(SvcTest, TwoPassEncode3SNRLayersDecode321Layers) {
559 std::string stats_buf;
560 vpx_svc_set_options(&svc_, "scale-factors=1/1,1/1,1/1");
561 Pass1EncodeNFrames(20, 3, &stats_buf);
563 // Second pass encode
564 codec_enc_.g_pass = VPX_RC_LAST_PASS;
565 vpx_svc_set_options(&svc_,
566 "auto-alt-refs=1,1,1 scale-factors=1/1,1/1,1/1");
567 vpx_fixed_buf outputs[20];
568 memset(&outputs[0], 0, sizeof(outputs));
569 Pass2EncodeNFrames(&stats_buf, 20, 3, &outputs[0]);
570 DecodeNFrames(&outputs[0], 20);
571 DropEnhancementLayers(&outputs[0], 20, 2);
572 DecodeNFrames(&outputs[0], 20);
573 DropEnhancementLayers(&outputs[0], 20, 1);
574 DecodeNFrames(&outputs[0], 20);
576 FreeBitstreamBuffers(&outputs[0], 20);