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