1 /* 2 * Copyright (c) 2012 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 #include "./vpx_config.h" 11 #include "third_party/googletest/src/include/gtest/gtest.h" 12 #include "test/codec_factory.h" 13 #include "test/encode_test_driver.h" 14 #include "test/i420_video_source.h" 15 #include "test/util.h" 16 #include "test/y4m_video_source.h" 17 #include "vpx/vpx_codec.h" 18 19 namespace { 20 21 class DatarateTestLarge 22 : public ::libvpx_test::EncoderTest, 23 public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> { 24 public: 25 DatarateTestLarge() : EncoderTest(GET_PARAM(0)) {} 26 27 virtual ~DatarateTestLarge() {} 28 29 protected: 30 virtual void SetUp() { 31 InitializeConfig(); 32 SetMode(GET_PARAM(1)); 33 set_cpu_used_ = GET_PARAM(2); 34 ResetModel(); 35 } 36 37 virtual void ResetModel() { 38 last_pts_ = 0; 39 bits_in_buffer_model_ = cfg_.rc_target_bitrate * cfg_.rc_buf_initial_sz; 40 frame_number_ = 0; 41 first_drop_ = 0; 42 bits_total_ = 0; 43 duration_ = 0.0; 44 denoiser_offon_test_ = 0; 45 denoiser_offon_period_ = -1; 46 gf_boost_ = 0; 47 use_roi_ = 0; 48 } 49 50 virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video, 51 ::libvpx_test::Encoder *encoder) { 52 if (video->frame() == 0) { 53 encoder->Control(VP8E_SET_NOISE_SENSITIVITY, denoiser_on_); 54 encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_); 55 encoder->Control(VP8E_SET_GF_CBR_BOOST_PCT, gf_boost_); 56 } 57 58 #if CONFIG_VP8_ENCODER 59 if (use_roi_ == 1) { 60 encoder->Control(VP8E_SET_ROI_MAP, &roi_); 61 } 62 #endif 63 64 if (denoiser_offon_test_) { 65 ASSERT_GT(denoiser_offon_period_, 0) 66 << "denoiser_offon_period_ is not positive."; 67 if ((video->frame() + 1) % denoiser_offon_period_ == 0) { 68 // Flip denoiser_on_ periodically 69 denoiser_on_ ^= 1; 70 } 71 encoder->Control(VP8E_SET_NOISE_SENSITIVITY, denoiser_on_); 72 } 73 74 const vpx_rational_t tb = video->timebase(); 75 timebase_ = static_cast<double>(tb.num) / tb.den; 76 duration_ = 0; 77 } 78 79 virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) { 80 // Time since last timestamp = duration. 81 vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_; 82 83 // TODO(jimbankoski): Remove these lines when the issue: 84 // http://code.google.com/p/webm/issues/detail?id=496 is fixed. 85 // For now the codec assumes buffer starts at starting buffer rate 86 // plus one frame's time. 87 if (last_pts_ == 0) duration = 1; 88 89 // Add to the buffer the bits we'd expect from a constant bitrate server. 90 bits_in_buffer_model_ += static_cast<int64_t>( 91 duration * timebase_ * cfg_.rc_target_bitrate * 1000); 92 93 /* Test the buffer model here before subtracting the frame. Do so because 94 * the way the leaky bucket model works in libvpx is to allow the buffer to 95 * empty - and then stop showing frames until we've got enough bits to 96 * show one. As noted in comment below (issue 495), this does not currently 97 * apply to key frames. For now exclude key frames in condition below. */ 98 const bool key_frame = 99 (pkt->data.frame.flags & VPX_FRAME_IS_KEY) ? true : false; 100 if (!key_frame) { 101 ASSERT_GE(bits_in_buffer_model_, 0) 102 << "Buffer Underrun at frame " << pkt->data.frame.pts; 103 } 104 105 const int64_t frame_size_in_bits = pkt->data.frame.sz * 8; 106 107 // Subtract from the buffer the bits associated with a played back frame. 108 bits_in_buffer_model_ -= frame_size_in_bits; 109 110 // Update the running total of bits for end of test datarate checks. 111 bits_total_ += frame_size_in_bits; 112 113 // If first drop not set and we have a drop set it to this time. 114 if (!first_drop_ && duration > 1) first_drop_ = last_pts_ + 1; 115 116 // Update the most recent pts. 117 last_pts_ = pkt->data.frame.pts; 118 119 // We update this so that we can calculate the datarate minus the last 120 // frame encoded in the file. 121 bits_in_last_frame_ = frame_size_in_bits; 122 123 ++frame_number_; 124 } 125 126 virtual void EndPassHook(void) { 127 if (bits_total_) { 128 const double file_size_in_kb = bits_total_ / 1000.; // bits per kilobit 129 130 duration_ = (last_pts_ + 1) * timebase_; 131 132 // Effective file datarate includes the time spent prebuffering. 133 effective_datarate_ = (bits_total_ - bits_in_last_frame_) / 1000.0 / 134 (cfg_.rc_buf_initial_sz / 1000.0 + duration_); 135 136 file_datarate_ = file_size_in_kb / duration_; 137 } 138 } 139 140 vpx_codec_pts_t last_pts_; 141 int64_t bits_in_buffer_model_; 142 double timebase_; 143 int frame_number_; 144 vpx_codec_pts_t first_drop_; 145 int64_t bits_total_; 146 double duration_; 147 double file_datarate_; 148 double effective_datarate_; 149 int64_t bits_in_last_frame_; 150 int denoiser_on_; 151 int denoiser_offon_test_; 152 int denoiser_offon_period_; 153 int set_cpu_used_; 154 int gf_boost_; 155 int use_roi_; 156 vpx_roi_map_t roi_; 157 }; 158 159 #if CONFIG_TEMPORAL_DENOISING 160 // Check basic datarate targeting, for a single bitrate, but loop over the 161 // various denoiser settings. 162 TEST_P(DatarateTestLarge, DenoiserLevels) { 163 cfg_.rc_buf_initial_sz = 500; 164 cfg_.rc_dropframe_thresh = 1; 165 cfg_.rc_max_quantizer = 56; 166 cfg_.rc_end_usage = VPX_CBR; 167 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 168 30, 1, 0, 140); 169 for (int j = 1; j < 5; ++j) { 170 // Run over the denoiser levels. 171 // For the temporal denoiser (#if CONFIG_TEMPORAL_DENOISING) the level j 172 // refers to the 4 denoiser modes: denoiserYonly, denoiserOnYUV, 173 // denoiserOnAggressive, and denoiserOnAdaptive. 174 denoiser_on_ = j; 175 cfg_.rc_target_bitrate = 300; 176 ResetModel(); 177 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 178 ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95) 179 << " The datarate for the file exceeds the target!"; 180 181 ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4) 182 << " The datarate for the file missed the target!"; 183 } 184 } 185 186 // Check basic datarate targeting, for a single bitrate, when denoiser is off 187 // and on. 188 TEST_P(DatarateTestLarge, DenoiserOffOn) { 189 cfg_.rc_buf_initial_sz = 500; 190 cfg_.rc_dropframe_thresh = 1; 191 cfg_.rc_max_quantizer = 56; 192 cfg_.rc_end_usage = VPX_CBR; 193 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 194 30, 1, 0, 299); 195 cfg_.rc_target_bitrate = 300; 196 ResetModel(); 197 // The denoiser is off by default. 198 denoiser_on_ = 0; 199 // Set the offon test flag. 200 denoiser_offon_test_ = 1; 201 denoiser_offon_period_ = 100; 202 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 203 ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95) 204 << " The datarate for the file exceeds the target!"; 205 ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4) 206 << " The datarate for the file missed the target!"; 207 } 208 #endif // CONFIG_TEMPORAL_DENOISING 209 210 TEST_P(DatarateTestLarge, BasicBufferModel) { 211 denoiser_on_ = 0; 212 cfg_.rc_buf_initial_sz = 500; 213 cfg_.rc_dropframe_thresh = 1; 214 cfg_.rc_max_quantizer = 56; 215 cfg_.rc_end_usage = VPX_CBR; 216 // 2 pass cbr datarate control has a bug hidden by the small # of 217 // frames selected in this encode. The problem is that even if the buffer is 218 // negative we produce a keyframe on a cutscene. Ignoring datarate 219 // constraints 220 // TODO(jimbankoski): ( Fix when issue 221 // http://code.google.com/p/webm/issues/detail?id=495 is addressed. ) 222 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 223 30, 1, 0, 140); 224 225 // There is an issue for low bitrates in real-time mode, where the 226 // effective_datarate slightly overshoots the target bitrate. 227 // This is same the issue as noted about (#495). 228 // TODO(jimbankoski/marpan): Update test to run for lower bitrates (< 100), 229 // when the issue is resolved. 230 for (int i = 100; i < 800; i += 200) { 231 cfg_.rc_target_bitrate = i; 232 ResetModel(); 233 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 234 ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95) 235 << " The datarate for the file exceeds the target!"; 236 ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4) 237 << " The datarate for the file missed the target!"; 238 } 239 } 240 241 TEST_P(DatarateTestLarge, ChangingDropFrameThresh) { 242 denoiser_on_ = 0; 243 cfg_.rc_buf_initial_sz = 500; 244 cfg_.rc_max_quantizer = 36; 245 cfg_.rc_end_usage = VPX_CBR; 246 cfg_.rc_target_bitrate = 200; 247 cfg_.kf_mode = VPX_KF_DISABLED; 248 249 const int frame_count = 40; 250 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 251 30, 1, 0, frame_count); 252 253 // Here we check that the first dropped frame gets earlier and earlier 254 // as the drop frame threshold is increased. 255 256 const int kDropFrameThreshTestStep = 30; 257 vpx_codec_pts_t last_drop = frame_count; 258 for (int i = 1; i < 91; i += kDropFrameThreshTestStep) { 259 cfg_.rc_dropframe_thresh = i; 260 ResetModel(); 261 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 262 ASSERT_LE(first_drop_, last_drop) 263 << " The first dropped frame for drop_thresh " << i 264 << " > first dropped frame for drop_thresh " 265 << i - kDropFrameThreshTestStep; 266 last_drop = first_drop_; 267 } 268 } 269 270 TEST_P(DatarateTestLarge, DropFramesMultiThreads) { 271 denoiser_on_ = 0; 272 cfg_.rc_buf_initial_sz = 500; 273 cfg_.rc_dropframe_thresh = 30; 274 cfg_.rc_max_quantizer = 56; 275 cfg_.rc_end_usage = VPX_CBR; 276 cfg_.g_threads = 2; 277 278 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 279 30, 1, 0, 140); 280 cfg_.rc_target_bitrate = 200; 281 ResetModel(); 282 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 283 ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95) 284 << " The datarate for the file exceeds the target!"; 285 286 ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4) 287 << " The datarate for the file missed the target!"; 288 } 289 290 class DatarateTestRealTime : public DatarateTestLarge { 291 public: 292 virtual ~DatarateTestRealTime() {} 293 }; 294 295 #if CONFIG_TEMPORAL_DENOISING 296 // Check basic datarate targeting, for a single bitrate, but loop over the 297 // various denoiser settings. 298 TEST_P(DatarateTestRealTime, DenoiserLevels) { 299 cfg_.rc_buf_initial_sz = 500; 300 cfg_.rc_dropframe_thresh = 1; 301 cfg_.rc_max_quantizer = 56; 302 cfg_.rc_end_usage = VPX_CBR; 303 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 304 30, 1, 0, 140); 305 for (int j = 1; j < 5; ++j) { 306 // Run over the denoiser levels. 307 // For the temporal denoiser (#if CONFIG_TEMPORAL_DENOISING) the level j 308 // refers to the 4 denoiser modes: denoiserYonly, denoiserOnYUV, 309 // denoiserOnAggressive, and denoiserOnAdaptive. 310 denoiser_on_ = j; 311 cfg_.rc_target_bitrate = 300; 312 ResetModel(); 313 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 314 ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95) 315 << " The datarate for the file exceeds the target!"; 316 ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4) 317 << " The datarate for the file missed the target!"; 318 } 319 } 320 321 // Check basic datarate targeting, for a single bitrate, when denoiser is off 322 // and on. 323 TEST_P(DatarateTestRealTime, DenoiserOffOn) { 324 cfg_.rc_buf_initial_sz = 500; 325 cfg_.rc_dropframe_thresh = 1; 326 cfg_.rc_max_quantizer = 56; 327 cfg_.rc_end_usage = VPX_CBR; 328 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 329 30, 1, 0, 299); 330 cfg_.rc_target_bitrate = 300; 331 ResetModel(); 332 // The denoiser is off by default. 333 denoiser_on_ = 0; 334 // Set the offon test flag. 335 denoiser_offon_test_ = 1; 336 denoiser_offon_period_ = 100; 337 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 338 ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95) 339 << " The datarate for the file exceeds the target!"; 340 ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4) 341 << " The datarate for the file missed the target!"; 342 } 343 #endif // CONFIG_TEMPORAL_DENOISING 344 345 TEST_P(DatarateTestRealTime, BasicBufferModel) { 346 denoiser_on_ = 0; 347 cfg_.rc_buf_initial_sz = 500; 348 cfg_.rc_dropframe_thresh = 1; 349 cfg_.rc_max_quantizer = 56; 350 cfg_.rc_end_usage = VPX_CBR; 351 // 2 pass cbr datarate control has a bug hidden by the small # of 352 // frames selected in this encode. The problem is that even if the buffer is 353 // negative we produce a keyframe on a cutscene, ignoring datarate 354 // constraints 355 // TODO(jimbankoski): Fix when issue 356 // http://bugs.chromium.org/p/webm/issues/detail?id=495 is addressed. 357 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 358 30, 1, 0, 140); 359 360 // There is an issue for low bitrates in real-time mode, where the 361 // effective_datarate slightly overshoots the target bitrate. 362 // This is same the issue as noted above (#495). 363 // TODO(jimbankoski/marpan): Update test to run for lower bitrates (< 100), 364 // when the issue is resolved. 365 for (int i = 100; i <= 700; i += 200) { 366 cfg_.rc_target_bitrate = i; 367 ResetModel(); 368 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 369 ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95) 370 << " The datarate for the file exceeds the target!"; 371 ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4) 372 << " The datarate for the file missed the target!"; 373 } 374 } 375 376 TEST_P(DatarateTestRealTime, ChangingDropFrameThresh) { 377 denoiser_on_ = 0; 378 cfg_.rc_buf_initial_sz = 500; 379 cfg_.rc_max_quantizer = 36; 380 cfg_.rc_end_usage = VPX_CBR; 381 cfg_.rc_target_bitrate = 200; 382 cfg_.kf_mode = VPX_KF_DISABLED; 383 384 const int frame_count = 40; 385 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 386 30, 1, 0, frame_count); 387 388 // Check that the first dropped frame gets earlier and earlier 389 // as the drop frame threshold is increased. 390 391 const int kDropFrameThreshTestStep = 30; 392 vpx_codec_pts_t last_drop = frame_count; 393 for (int i = 1; i < 91; i += kDropFrameThreshTestStep) { 394 cfg_.rc_dropframe_thresh = i; 395 ResetModel(); 396 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 397 ASSERT_LE(first_drop_, last_drop) 398 << " The first dropped frame for drop_thresh " << i 399 << " > first dropped frame for drop_thresh " 400 << i - kDropFrameThreshTestStep; 401 last_drop = first_drop_; 402 } 403 } 404 405 TEST_P(DatarateTestRealTime, DropFramesMultiThreads) { 406 denoiser_on_ = 0; 407 cfg_.rc_buf_initial_sz = 500; 408 cfg_.rc_dropframe_thresh = 30; 409 cfg_.rc_max_quantizer = 56; 410 cfg_.rc_end_usage = VPX_CBR; 411 // Encode using multiple threads. 412 cfg_.g_threads = 2; 413 414 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 415 30, 1, 0, 140); 416 cfg_.rc_target_bitrate = 200; 417 ResetModel(); 418 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 419 ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95) 420 << " The datarate for the file exceeds the target!"; 421 422 ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4) 423 << " The datarate for the file missed the target!"; 424 } 425 426 TEST_P(DatarateTestRealTime, RegionOfInterest) { 427 denoiser_on_ = 0; 428 cfg_.rc_buf_initial_sz = 500; 429 cfg_.rc_dropframe_thresh = 0; 430 cfg_.rc_max_quantizer = 56; 431 cfg_.rc_end_usage = VPX_CBR; 432 // Encode using multiple threads. 433 cfg_.g_threads = 2; 434 435 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 436 30, 1, 0, 300); 437 cfg_.rc_target_bitrate = 450; 438 cfg_.g_w = 352; 439 cfg_.g_h = 288; 440 441 ResetModel(); 442 443 // Set ROI parameters 444 use_roi_ = 1; 445 memset(&roi_, 0, sizeof(roi_)); 446 447 roi_.rows = (cfg_.g_h + 15) / 16; 448 roi_.cols = (cfg_.g_w + 15) / 16; 449 450 roi_.delta_q[0] = 0; 451 roi_.delta_q[1] = -20; 452 roi_.delta_q[2] = 0; 453 roi_.delta_q[3] = 0; 454 455 roi_.delta_lf[0] = 0; 456 roi_.delta_lf[1] = -20; 457 roi_.delta_lf[2] = 0; 458 roi_.delta_lf[3] = 0; 459 460 roi_.static_threshold[0] = 0; 461 roi_.static_threshold[1] = 1000; 462 roi_.static_threshold[2] = 0; 463 roi_.static_threshold[3] = 0; 464 465 // Use 2 states: 1 is center square, 0 is the rest. 466 roi_.roi_map = 467 (uint8_t *)calloc(roi_.rows * roi_.cols, sizeof(*roi_.roi_map)); 468 for (unsigned int i = 0; i < roi_.rows; ++i) { 469 for (unsigned int j = 0; j < roi_.cols; ++j) { 470 if (i > (roi_.rows >> 2) && i < ((roi_.rows * 3) >> 2) && 471 j > (roi_.cols >> 2) && j < ((roi_.cols * 3) >> 2)) { 472 roi_.roi_map[i * roi_.cols + j] = 1; 473 } 474 } 475 } 476 477 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 478 ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95) 479 << " The datarate for the file exceeds the target!"; 480 481 ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4) 482 << " The datarate for the file missed the target!"; 483 484 free(roi_.roi_map); 485 } 486 487 TEST_P(DatarateTestRealTime, GFBoost) { 488 denoiser_on_ = 0; 489 cfg_.rc_buf_initial_sz = 500; 490 cfg_.rc_dropframe_thresh = 0; 491 cfg_.rc_max_quantizer = 56; 492 cfg_.rc_end_usage = VPX_CBR; 493 cfg_.g_error_resilient = 0; 494 495 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 496 30, 1, 0, 300); 497 cfg_.rc_target_bitrate = 300; 498 ResetModel(); 499 // Apply a gf boost. 500 gf_boost_ = 50; 501 502 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 503 ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95) 504 << " The datarate for the file exceeds the target!"; 505 506 ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4) 507 << " The datarate for the file missed the target!"; 508 } 509 510 class DatarateTestVP9Large 511 : public ::libvpx_test::EncoderTest, 512 public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> { 513 public: 514 DatarateTestVP9Large() : EncoderTest(GET_PARAM(0)) {} 515 516 protected: 517 virtual ~DatarateTestVP9Large() {} 518 519 virtual void SetUp() { 520 InitializeConfig(); 521 SetMode(GET_PARAM(1)); 522 set_cpu_used_ = GET_PARAM(2); 523 ResetModel(); 524 } 525 526 virtual void ResetModel() { 527 last_pts_ = 0; 528 bits_in_buffer_model_ = cfg_.rc_target_bitrate * cfg_.rc_buf_initial_sz; 529 frame_number_ = 0; 530 tot_frame_number_ = 0; 531 first_drop_ = 0; 532 num_drops_ = 0; 533 // Denoiser is off by default. 534 denoiser_on_ = 0; 535 // For testing up to 3 layers. 536 for (int i = 0; i < 3; ++i) { 537 bits_total_[i] = 0; 538 } 539 denoiser_offon_test_ = 0; 540 denoiser_offon_period_ = -1; 541 frame_parallel_decoding_mode_ = 1; 542 } 543 544 // 545 // Frame flags and layer id for temporal layers. 546 // 547 548 // For two layers, test pattern is: 549 // 1 3 550 // 0 2 ..... 551 // For three layers, test pattern is: 552 // 1 3 5 7 553 // 2 6 554 // 0 4 .... 555 // LAST is always update on base/layer 0, GOLDEN is updated on layer 1. 556 // For this 3 layer example, the 2nd enhancement layer (layer 2) updates 557 // the altref frame. 558 int SetFrameFlags(int frame_num, int num_temp_layers) { 559 int frame_flags = 0; 560 if (num_temp_layers == 2) { 561 if (frame_num % 2 == 0) { 562 // Layer 0: predict from L and ARF, update L. 563 frame_flags = 564 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; 565 } else { 566 // Layer 1: predict from L, G and ARF, and update G. 567 frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST | 568 VP8_EFLAG_NO_UPD_ENTROPY; 569 } 570 } else if (num_temp_layers == 3) { 571 if (frame_num % 4 == 0) { 572 // Layer 0: predict from L and ARF; update L. 573 frame_flags = 574 VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF; 575 } else if ((frame_num - 2) % 4 == 0) { 576 // Layer 1: predict from L, G, ARF; update G. 577 frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST; 578 } else if ((frame_num - 1) % 2 == 0) { 579 // Layer 2: predict from L, G, ARF; update ARF. 580 frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST; 581 } 582 } 583 return frame_flags; 584 } 585 586 int SetLayerId(int frame_num, int num_temp_layers) { 587 int layer_id = 0; 588 if (num_temp_layers == 2) { 589 if (frame_num % 2 == 0) { 590 layer_id = 0; 591 } else { 592 layer_id = 1; 593 } 594 } else if (num_temp_layers == 3) { 595 if (frame_num % 4 == 0) { 596 layer_id = 0; 597 } else if ((frame_num - 2) % 4 == 0) { 598 layer_id = 1; 599 } else if ((frame_num - 1) % 2 == 0) { 600 layer_id = 2; 601 } 602 } 603 return layer_id; 604 } 605 606 virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video, 607 ::libvpx_test::Encoder *encoder) { 608 if (video->frame() == 0) encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_); 609 610 if (denoiser_offon_test_) { 611 ASSERT_GT(denoiser_offon_period_, 0) 612 << "denoiser_offon_period_ is not positive."; 613 if ((video->frame() + 1) % denoiser_offon_period_ == 0) { 614 // Flip denoiser_on_ periodically 615 denoiser_on_ ^= 1; 616 } 617 } 618 619 encoder->Control(VP9E_SET_NOISE_SENSITIVITY, denoiser_on_); 620 encoder->Control(VP9E_SET_TILE_COLUMNS, (cfg_.g_threads >> 1)); 621 encoder->Control(VP9E_SET_FRAME_PARALLEL_DECODING, 622 frame_parallel_decoding_mode_); 623 624 if (cfg_.ts_number_layers > 1) { 625 if (video->frame() == 0) { 626 encoder->Control(VP9E_SET_SVC, 1); 627 } 628 vpx_svc_layer_id_t layer_id; 629 layer_id.spatial_layer_id = 0; 630 frame_flags_ = SetFrameFlags(video->frame(), cfg_.ts_number_layers); 631 layer_id.temporal_layer_id = 632 SetLayerId(video->frame(), cfg_.ts_number_layers); 633 encoder->Control(VP9E_SET_SVC_LAYER_ID, &layer_id); 634 } 635 const vpx_rational_t tb = video->timebase(); 636 timebase_ = static_cast<double>(tb.num) / tb.den; 637 duration_ = 0; 638 } 639 640 virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) { 641 // Time since last timestamp = duration. 642 vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_; 643 644 if (duration > 1) { 645 // If first drop not set and we have a drop set it to this time. 646 if (!first_drop_) first_drop_ = last_pts_ + 1; 647 // Update the number of frame drops. 648 num_drops_ += static_cast<int>(duration - 1); 649 // Update counter for total number of frames (#frames input to encoder). 650 // Needed for setting the proper layer_id below. 651 tot_frame_number_ += static_cast<int>(duration - 1); 652 } 653 654 int layer = SetLayerId(tot_frame_number_, cfg_.ts_number_layers); 655 656 // Add to the buffer the bits we'd expect from a constant bitrate server. 657 bits_in_buffer_model_ += static_cast<int64_t>( 658 duration * timebase_ * cfg_.rc_target_bitrate * 1000); 659 660 // Buffer should not go negative. 661 ASSERT_GE(bits_in_buffer_model_, 0) 662 << "Buffer Underrun at frame " << pkt->data.frame.pts; 663 664 const size_t frame_size_in_bits = pkt->data.frame.sz * 8; 665 666 // Update the total encoded bits. For temporal layers, update the cumulative 667 // encoded bits per layer. 668 for (int i = layer; i < static_cast<int>(cfg_.ts_number_layers); ++i) { 669 bits_total_[i] += frame_size_in_bits; 670 } 671 672 // Update the most recent pts. 673 last_pts_ = pkt->data.frame.pts; 674 ++frame_number_; 675 ++tot_frame_number_; 676 } 677 678 virtual void EndPassHook(void) { 679 for (int layer = 0; layer < static_cast<int>(cfg_.ts_number_layers); 680 ++layer) { 681 duration_ = (last_pts_ + 1) * timebase_; 682 if (bits_total_[layer]) { 683 // Effective file datarate: 684 effective_datarate_[layer] = (bits_total_[layer] / 1000.0) / duration_; 685 } 686 } 687 } 688 689 vpx_codec_pts_t last_pts_; 690 double timebase_; 691 int frame_number_; // Counter for number of non-dropped/encoded frames. 692 int tot_frame_number_; // Counter for total number of input frames. 693 int64_t bits_total_[3]; 694 double duration_; 695 double effective_datarate_[3]; 696 int set_cpu_used_; 697 int64_t bits_in_buffer_model_; 698 vpx_codec_pts_t first_drop_; 699 int num_drops_; 700 int denoiser_on_; 701 int denoiser_offon_test_; 702 int denoiser_offon_period_; 703 int frame_parallel_decoding_mode_; 704 }; 705 706 // Check basic rate targeting for VBR mode with 0 lag. 707 TEST_P(DatarateTestVP9Large, BasicRateTargetingVBRLagZero) { 708 cfg_.rc_min_quantizer = 0; 709 cfg_.rc_max_quantizer = 63; 710 cfg_.g_error_resilient = 0; 711 cfg_.rc_end_usage = VPX_VBR; 712 cfg_.g_lag_in_frames = 0; 713 714 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 715 30, 1, 0, 300); 716 for (int i = 400; i <= 800; i += 400) { 717 cfg_.rc_target_bitrate = i; 718 ResetModel(); 719 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 720 ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.75) 721 << " The datarate for the file is lower than target by too much!"; 722 ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.30) 723 << " The datarate for the file is greater than target by too much!"; 724 } 725 } 726 727 // Check basic rate targeting for VBR mode with non-zero lag. 728 TEST_P(DatarateTestVP9Large, BasicRateTargetingVBRLagNonZero) { 729 cfg_.rc_min_quantizer = 0; 730 cfg_.rc_max_quantizer = 63; 731 cfg_.g_error_resilient = 0; 732 cfg_.rc_end_usage = VPX_VBR; 733 // For non-zero lag, rate control will work (be within bounds) for 734 // real-time mode. 735 if (deadline_ == VPX_DL_REALTIME) { 736 cfg_.g_lag_in_frames = 15; 737 } else { 738 cfg_.g_lag_in_frames = 0; 739 } 740 741 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 742 30, 1, 0, 300); 743 for (int i = 400; i <= 800; i += 400) { 744 cfg_.rc_target_bitrate = i; 745 ResetModel(); 746 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 747 ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.75) 748 << " The datarate for the file is lower than target by too much!"; 749 ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.30) 750 << " The datarate for the file is greater than target by too much!"; 751 } 752 } 753 754 // Check basic rate targeting for VBR mode with non-zero lag, with 755 // frame_parallel_decoding_mode off. This enables the adapt_coeff/mode/mv probs 756 // since error_resilience is off. 757 TEST_P(DatarateTestVP9Large, BasicRateTargetingVBRLagNonZeroFrameParDecOff) { 758 cfg_.rc_min_quantizer = 0; 759 cfg_.rc_max_quantizer = 63; 760 cfg_.g_error_resilient = 0; 761 cfg_.rc_end_usage = VPX_VBR; 762 // For non-zero lag, rate control will work (be within bounds) for 763 // real-time mode. 764 if (deadline_ == VPX_DL_REALTIME) { 765 cfg_.g_lag_in_frames = 15; 766 } else { 767 cfg_.g_lag_in_frames = 0; 768 } 769 770 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 771 30, 1, 0, 300); 772 for (int i = 400; i <= 800; i += 400) { 773 cfg_.rc_target_bitrate = i; 774 ResetModel(); 775 frame_parallel_decoding_mode_ = 0; 776 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 777 ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.75) 778 << " The datarate for the file is lower than target by too much!"; 779 ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.30) 780 << " The datarate for the file is greater than target by too much!"; 781 } 782 } 783 784 // Check basic rate targeting for CBR mode. 785 TEST_P(DatarateTestVP9Large, BasicRateTargeting) { 786 cfg_.rc_buf_initial_sz = 500; 787 cfg_.rc_buf_optimal_sz = 500; 788 cfg_.rc_buf_sz = 1000; 789 cfg_.rc_dropframe_thresh = 1; 790 cfg_.rc_min_quantizer = 0; 791 cfg_.rc_max_quantizer = 63; 792 cfg_.rc_end_usage = VPX_CBR; 793 cfg_.g_lag_in_frames = 0; 794 795 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 796 30, 1, 0, 140); 797 for (int i = 150; i < 800; i += 200) { 798 cfg_.rc_target_bitrate = i; 799 ResetModel(); 800 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 801 ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85) 802 << " The datarate for the file is lower than target by too much!"; 803 ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15) 804 << " The datarate for the file is greater than target by too much!"; 805 } 806 } 807 808 // Check basic rate targeting for CBR mode, with frame_parallel_decoding_mode 809 // off( and error_resilience off). 810 TEST_P(DatarateTestVP9Large, BasicRateTargetingFrameParDecOff) { 811 cfg_.rc_buf_initial_sz = 500; 812 cfg_.rc_buf_optimal_sz = 500; 813 cfg_.rc_buf_sz = 1000; 814 cfg_.rc_dropframe_thresh = 1; 815 cfg_.rc_min_quantizer = 0; 816 cfg_.rc_max_quantizer = 63; 817 cfg_.rc_end_usage = VPX_CBR; 818 cfg_.g_lag_in_frames = 0; 819 cfg_.g_error_resilient = 0; 820 821 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 822 30, 1, 0, 140); 823 for (int i = 150; i < 800; i += 200) { 824 cfg_.rc_target_bitrate = i; 825 ResetModel(); 826 frame_parallel_decoding_mode_ = 0; 827 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 828 ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85) 829 << " The datarate for the file is lower than target by too much!"; 830 ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15) 831 << " The datarate for the file is greater than target by too much!"; 832 } 833 } 834 835 // Check basic rate targeting for CBR mode, with 2 threads and dropped frames. 836 TEST_P(DatarateTestVP9Large, BasicRateTargetingDropFramesMultiThreads) { 837 cfg_.rc_buf_initial_sz = 500; 838 cfg_.rc_buf_optimal_sz = 500; 839 cfg_.rc_buf_sz = 1000; 840 cfg_.rc_dropframe_thresh = 30; 841 cfg_.rc_min_quantizer = 0; 842 cfg_.rc_max_quantizer = 63; 843 cfg_.rc_end_usage = VPX_CBR; 844 cfg_.g_lag_in_frames = 0; 845 // Encode using multiple threads. 846 cfg_.g_threads = 2; 847 848 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 849 30, 1, 0, 140); 850 cfg_.rc_target_bitrate = 200; 851 ResetModel(); 852 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 853 ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85) 854 << " The datarate for the file is lower than target by too much!"; 855 ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15) 856 << " The datarate for the file is greater than target by too much!"; 857 } 858 859 // Check basic rate targeting for CBR. 860 TEST_P(DatarateTestVP9Large, BasicRateTargeting444) { 861 ::libvpx_test::Y4mVideoSource video("rush_hour_444.y4m", 0, 140); 862 863 cfg_.g_profile = 1; 864 cfg_.g_timebase = video.timebase(); 865 866 cfg_.rc_buf_initial_sz = 500; 867 cfg_.rc_buf_optimal_sz = 500; 868 cfg_.rc_buf_sz = 1000; 869 cfg_.rc_dropframe_thresh = 1; 870 cfg_.rc_min_quantizer = 0; 871 cfg_.rc_max_quantizer = 63; 872 cfg_.rc_end_usage = VPX_CBR; 873 874 for (int i = 250; i < 900; i += 200) { 875 cfg_.rc_target_bitrate = i; 876 ResetModel(); 877 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 878 ASSERT_GE(static_cast<double>(cfg_.rc_target_bitrate), 879 effective_datarate_[0] * 0.80) 880 << " The datarate for the file exceeds the target by too much!"; 881 ASSERT_LE(static_cast<double>(cfg_.rc_target_bitrate), 882 effective_datarate_[0] * 1.15) 883 << " The datarate for the file missed the target!" 884 << cfg_.rc_target_bitrate << " " << effective_datarate_; 885 } 886 } 887 888 // Check that (1) the first dropped frame gets earlier and earlier 889 // as the drop frame threshold is increased, and (2) that the total number of 890 // frame drops does not decrease as we increase frame drop threshold. 891 // Use a lower qp-max to force some frame drops. 892 TEST_P(DatarateTestVP9Large, ChangingDropFrameThresh) { 893 cfg_.rc_buf_initial_sz = 500; 894 cfg_.rc_buf_optimal_sz = 500; 895 cfg_.rc_buf_sz = 1000; 896 cfg_.rc_undershoot_pct = 20; 897 cfg_.rc_undershoot_pct = 20; 898 cfg_.rc_dropframe_thresh = 10; 899 cfg_.rc_min_quantizer = 0; 900 cfg_.rc_max_quantizer = 50; 901 cfg_.rc_end_usage = VPX_CBR; 902 cfg_.rc_target_bitrate = 200; 903 cfg_.g_lag_in_frames = 0; 904 // TODO(marpan): Investigate datarate target failures with a smaller keyframe 905 // interval (128). 906 cfg_.kf_max_dist = 9999; 907 908 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 909 30, 1, 0, 140); 910 911 const int kDropFrameThreshTestStep = 30; 912 for (int j = 50; j <= 150; j += 100) { 913 cfg_.rc_target_bitrate = j; 914 vpx_codec_pts_t last_drop = 140; 915 int last_num_drops = 0; 916 for (int i = 10; i < 100; i += kDropFrameThreshTestStep) { 917 cfg_.rc_dropframe_thresh = i; 918 ResetModel(); 919 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 920 ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85) 921 << " The datarate for the file is lower than target by too much!"; 922 ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.25) 923 << " The datarate for the file is greater than target by too much!"; 924 ASSERT_LE(first_drop_, last_drop) 925 << " The first dropped frame for drop_thresh " << i 926 << " > first dropped frame for drop_thresh " 927 << i - kDropFrameThreshTestStep; 928 ASSERT_GE(num_drops_, last_num_drops * 0.85) 929 << " The number of dropped frames for drop_thresh " << i 930 << " < number of dropped frames for drop_thresh " 931 << i - kDropFrameThreshTestStep; 932 last_drop = first_drop_; 933 last_num_drops = num_drops_; 934 } 935 } 936 } 937 938 // Check basic rate targeting for 2 temporal layers. 939 TEST_P(DatarateTestVP9Large, BasicRateTargeting2TemporalLayers) { 940 cfg_.rc_buf_initial_sz = 500; 941 cfg_.rc_buf_optimal_sz = 500; 942 cfg_.rc_buf_sz = 1000; 943 cfg_.rc_dropframe_thresh = 1; 944 cfg_.rc_min_quantizer = 0; 945 cfg_.rc_max_quantizer = 63; 946 cfg_.rc_end_usage = VPX_CBR; 947 cfg_.g_lag_in_frames = 0; 948 949 // 2 Temporal layers, no spatial layers: Framerate decimation (2, 1). 950 cfg_.ss_number_layers = 1; 951 cfg_.ts_number_layers = 2; 952 cfg_.ts_rate_decimator[0] = 2; 953 cfg_.ts_rate_decimator[1] = 1; 954 955 cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS; 956 957 if (deadline_ == VPX_DL_REALTIME) cfg_.g_error_resilient = 1; 958 959 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 960 30, 1, 0, 200); 961 for (int i = 200; i <= 800; i += 200) { 962 cfg_.rc_target_bitrate = i; 963 ResetModel(); 964 // 60-40 bitrate allocation for 2 temporal layers. 965 cfg_.layer_target_bitrate[0] = 60 * cfg_.rc_target_bitrate / 100; 966 cfg_.layer_target_bitrate[1] = cfg_.rc_target_bitrate; 967 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 968 for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) { 969 ASSERT_GE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 0.85) 970 << " The datarate for the file is lower than target by too much, " 971 "for layer: " 972 << j; 973 ASSERT_LE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 1.15) 974 << " The datarate for the file is greater than target by too much, " 975 "for layer: " 976 << j; 977 } 978 } 979 } 980 981 // Check basic rate targeting for 3 temporal layers. 982 TEST_P(DatarateTestVP9Large, BasicRateTargeting3TemporalLayers) { 983 cfg_.rc_buf_initial_sz = 500; 984 cfg_.rc_buf_optimal_sz = 500; 985 cfg_.rc_buf_sz = 1000; 986 cfg_.rc_dropframe_thresh = 1; 987 cfg_.rc_min_quantizer = 0; 988 cfg_.rc_max_quantizer = 63; 989 cfg_.rc_end_usage = VPX_CBR; 990 cfg_.g_lag_in_frames = 0; 991 992 // 3 Temporal layers, no spatial layers: Framerate decimation (4, 2, 1). 993 cfg_.ss_number_layers = 1; 994 cfg_.ts_number_layers = 3; 995 cfg_.ts_rate_decimator[0] = 4; 996 cfg_.ts_rate_decimator[1] = 2; 997 cfg_.ts_rate_decimator[2] = 1; 998 999 cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS; 1000 1001 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 1002 30, 1, 0, 200); 1003 for (int i = 200; i <= 800; i += 200) { 1004 cfg_.rc_target_bitrate = i; 1005 ResetModel(); 1006 // 40-20-40 bitrate allocation for 3 temporal layers. 1007 cfg_.layer_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100; 1008 cfg_.layer_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100; 1009 cfg_.layer_target_bitrate[2] = cfg_.rc_target_bitrate; 1010 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 1011 for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) { 1012 // TODO(yaowu): Work out more stable rc control strategy and 1013 // Adjust the thresholds to be tighter than .75. 1014 ASSERT_GE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 0.75) 1015 << " The datarate for the file is lower than target by too much, " 1016 "for layer: " 1017 << j; 1018 // TODO(yaowu): Work out more stable rc control strategy and 1019 // Adjust the thresholds to be tighter than 1.25. 1020 ASSERT_LE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 1.25) 1021 << " The datarate for the file is greater than target by too much, " 1022 "for layer: " 1023 << j; 1024 } 1025 } 1026 } 1027 1028 // Check basic rate targeting for 3 temporal layers, with frame dropping. 1029 // Only for one (low) bitrate with lower max_quantizer, and somewhat higher 1030 // frame drop threshold, to force frame dropping. 1031 TEST_P(DatarateTestVP9Large, BasicRateTargeting3TemporalLayersFrameDropping) { 1032 cfg_.rc_buf_initial_sz = 500; 1033 cfg_.rc_buf_optimal_sz = 500; 1034 cfg_.rc_buf_sz = 1000; 1035 // Set frame drop threshold and rc_max_quantizer to force some frame drops. 1036 cfg_.rc_dropframe_thresh = 20; 1037 cfg_.rc_max_quantizer = 45; 1038 cfg_.rc_min_quantizer = 0; 1039 cfg_.rc_end_usage = VPX_CBR; 1040 cfg_.g_lag_in_frames = 0; 1041 1042 // 3 Temporal layers, no spatial layers: Framerate decimation (4, 2, 1). 1043 cfg_.ss_number_layers = 1; 1044 cfg_.ts_number_layers = 3; 1045 cfg_.ts_rate_decimator[0] = 4; 1046 cfg_.ts_rate_decimator[1] = 2; 1047 cfg_.ts_rate_decimator[2] = 1; 1048 1049 cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS; 1050 1051 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 1052 30, 1, 0, 200); 1053 cfg_.rc_target_bitrate = 200; 1054 ResetModel(); 1055 // 40-20-40 bitrate allocation for 3 temporal layers. 1056 cfg_.layer_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100; 1057 cfg_.layer_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100; 1058 cfg_.layer_target_bitrate[2] = cfg_.rc_target_bitrate; 1059 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 1060 for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) { 1061 ASSERT_GE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 0.85) 1062 << " The datarate for the file is lower than target by too much, " 1063 "for layer: " 1064 << j; 1065 ASSERT_LE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 1.15) 1066 << " The datarate for the file is greater than target by too much, " 1067 "for layer: " 1068 << j; 1069 // Expect some frame drops in this test: for this 200 frames test, 1070 // expect at least 10% and not more than 60% drops. 1071 ASSERT_GE(num_drops_, 20); 1072 ASSERT_LE(num_drops_, 130); 1073 } 1074 } 1075 1076 #if CONFIG_VP9_TEMPORAL_DENOISING 1077 class DatarateTestVP9LargeDenoiser : public DatarateTestVP9Large { 1078 public: 1079 virtual ~DatarateTestVP9LargeDenoiser() {} 1080 }; 1081 1082 // Check basic datarate targeting, for a single bitrate, when denoiser is on. 1083 TEST_P(DatarateTestVP9LargeDenoiser, LowNoise) { 1084 cfg_.rc_buf_initial_sz = 500; 1085 cfg_.rc_buf_optimal_sz = 500; 1086 cfg_.rc_buf_sz = 1000; 1087 cfg_.rc_dropframe_thresh = 1; 1088 cfg_.rc_min_quantizer = 2; 1089 cfg_.rc_max_quantizer = 56; 1090 cfg_.rc_end_usage = VPX_CBR; 1091 cfg_.g_lag_in_frames = 0; 1092 1093 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 1094 30, 1, 0, 140); 1095 1096 // For the temporal denoiser (#if CONFIG_VP9_TEMPORAL_DENOISING), 1097 // there is only one denoiser mode: denoiserYonly(which is 1), 1098 // but may add more modes in the future. 1099 cfg_.rc_target_bitrate = 300; 1100 ResetModel(); 1101 // Turn on the denoiser. 1102 denoiser_on_ = 1; 1103 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 1104 ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85) 1105 << " The datarate for the file is lower than target by too much!"; 1106 ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15) 1107 << " The datarate for the file is greater than target by too much!"; 1108 } 1109 1110 // Check basic datarate targeting, for a single bitrate, when denoiser is on, 1111 // for clip with high noise level. Use 2 threads. 1112 TEST_P(DatarateTestVP9LargeDenoiser, HighNoise) { 1113 cfg_.rc_buf_initial_sz = 500; 1114 cfg_.rc_buf_optimal_sz = 500; 1115 cfg_.rc_buf_sz = 1000; 1116 cfg_.rc_dropframe_thresh = 1; 1117 cfg_.rc_min_quantizer = 2; 1118 cfg_.rc_max_quantizer = 56; 1119 cfg_.rc_end_usage = VPX_CBR; 1120 cfg_.g_lag_in_frames = 0; 1121 cfg_.g_threads = 2; 1122 1123 ::libvpx_test::Y4mVideoSource video("noisy_clip_640_360.y4m", 0, 200); 1124 1125 // For the temporal denoiser (#if CONFIG_VP9_TEMPORAL_DENOISING), 1126 // there is only one denoiser mode: kDenoiserOnYOnly(which is 1), 1127 // but may add more modes in the future. 1128 cfg_.rc_target_bitrate = 1000; 1129 ResetModel(); 1130 // Turn on the denoiser. 1131 denoiser_on_ = 1; 1132 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 1133 ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85) 1134 << " The datarate for the file is lower than target by too much!"; 1135 ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15) 1136 << " The datarate for the file is greater than target by too much!"; 1137 } 1138 1139 // Check basic datarate targeting, for a single bitrate, when denoiser is on, 1140 // for 1280x720 clip with 4 threads. 1141 TEST_P(DatarateTestVP9LargeDenoiser, 4threads) { 1142 cfg_.rc_buf_initial_sz = 500; 1143 cfg_.rc_buf_optimal_sz = 500; 1144 cfg_.rc_buf_sz = 1000; 1145 cfg_.rc_dropframe_thresh = 1; 1146 cfg_.rc_min_quantizer = 2; 1147 cfg_.rc_max_quantizer = 56; 1148 cfg_.rc_end_usage = VPX_CBR; 1149 cfg_.g_lag_in_frames = 0; 1150 cfg_.g_threads = 4; 1151 1152 ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 300); 1153 1154 // For the temporal denoiser (#if CONFIG_VP9_TEMPORAL_DENOISING), 1155 // there is only one denoiser mode: denoiserYonly(which is 1), 1156 // but may add more modes in the future. 1157 cfg_.rc_target_bitrate = 1000; 1158 ResetModel(); 1159 // Turn on the denoiser. 1160 denoiser_on_ = 1; 1161 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 1162 ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85) 1163 << " The datarate for the file is lower than target by too much!"; 1164 ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.29) 1165 << " The datarate for the file is greater than target by too much!"; 1166 } 1167 1168 // Check basic datarate targeting, for a single bitrate, when denoiser is off 1169 // and on. 1170 TEST_P(DatarateTestVP9LargeDenoiser, DenoiserOffOn) { 1171 cfg_.rc_buf_initial_sz = 500; 1172 cfg_.rc_buf_optimal_sz = 500; 1173 cfg_.rc_buf_sz = 1000; 1174 cfg_.rc_dropframe_thresh = 1; 1175 cfg_.rc_min_quantizer = 2; 1176 cfg_.rc_max_quantizer = 56; 1177 cfg_.rc_end_usage = VPX_CBR; 1178 cfg_.g_lag_in_frames = 0; 1179 1180 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 1181 30, 1, 0, 299); 1182 1183 // For the temporal denoiser (#if CONFIG_VP9_TEMPORAL_DENOISING), 1184 // there is only one denoiser mode: denoiserYonly(which is 1), 1185 // but may add more modes in the future. 1186 cfg_.rc_target_bitrate = 300; 1187 ResetModel(); 1188 // The denoiser is off by default. 1189 denoiser_on_ = 0; 1190 // Set the offon test flag. 1191 denoiser_offon_test_ = 1; 1192 denoiser_offon_period_ = 100; 1193 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 1194 ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85) 1195 << " The datarate for the file is lower than target by too much!"; 1196 ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15) 1197 << " The datarate for the file is greater than target by too much!"; 1198 } 1199 #endif // CONFIG_VP9_TEMPORAL_DENOISING 1200 1201 class DatarateOnePassCbrSvc 1202 : public ::libvpx_test::EncoderTest, 1203 public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> { 1204 public: 1205 DatarateOnePassCbrSvc() : EncoderTest(GET_PARAM(0)) { 1206 memset(&svc_params_, 0, sizeof(svc_params_)); 1207 } 1208 virtual ~DatarateOnePassCbrSvc() {} 1209 1210 protected: 1211 virtual void SetUp() { 1212 InitializeConfig(); 1213 SetMode(GET_PARAM(1)); 1214 speed_setting_ = GET_PARAM(2); 1215 ResetModel(); 1216 } 1217 virtual void ResetModel() { 1218 last_pts_ = 0; 1219 duration_ = 0.0; 1220 mismatch_psnr_ = 0.0; 1221 mismatch_nframes_ = 0; 1222 denoiser_on_ = 0; 1223 tune_content_ = 0; 1224 base_speed_setting_ = 5; 1225 spatial_layer_id_ = 0; 1226 temporal_layer_id_ = 0; 1227 memset(bits_in_buffer_model_, 0, sizeof(bits_in_buffer_model_)); 1228 memset(bits_total_, 0, sizeof(bits_total_)); 1229 memset(layer_target_avg_bandwidth_, 0, sizeof(layer_target_avg_bandwidth_)); 1230 } 1231 virtual void BeginPassHook(unsigned int /*pass*/) {} 1232 virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video, 1233 ::libvpx_test::Encoder *encoder) { 1234 if (video->frame() == 0) { 1235 int i; 1236 for (i = 0; i < VPX_MAX_LAYERS; ++i) { 1237 svc_params_.max_quantizers[i] = 63; 1238 svc_params_.min_quantizers[i] = 0; 1239 } 1240 svc_params_.speed_per_layer[0] = base_speed_setting_; 1241 for (i = 1; i < VPX_SS_MAX_LAYERS; ++i) { 1242 svc_params_.speed_per_layer[i] = speed_setting_; 1243 } 1244 1245 encoder->Control(VP9E_SET_NOISE_SENSITIVITY, denoiser_on_); 1246 encoder->Control(VP9E_SET_SVC, 1); 1247 encoder->Control(VP9E_SET_SVC_PARAMETERS, &svc_params_); 1248 encoder->Control(VP8E_SET_CPUUSED, speed_setting_); 1249 encoder->Control(VP9E_SET_TILE_COLUMNS, 0); 1250 encoder->Control(VP8E_SET_MAX_INTRA_BITRATE_PCT, 300); 1251 encoder->Control(VP9E_SET_TILE_COLUMNS, (cfg_.g_threads >> 1)); 1252 encoder->Control(VP9E_SET_ROW_MT, 1); 1253 encoder->Control(VP8E_SET_STATIC_THRESHOLD, 1); 1254 encoder->Control(VP9E_SET_TUNE_CONTENT, tune_content_); 1255 } 1256 const vpx_rational_t tb = video->timebase(); 1257 timebase_ = static_cast<double>(tb.num) / tb.den; 1258 duration_ = 0; 1259 } 1260 1261 virtual void PostEncodeFrameHook(::libvpx_test::Encoder *encoder) { 1262 vpx_svc_layer_id_t layer_id; 1263 encoder->Control(VP9E_GET_SVC_LAYER_ID, &layer_id); 1264 spatial_layer_id_ = layer_id.spatial_layer_id; 1265 temporal_layer_id_ = layer_id.temporal_layer_id; 1266 // Update buffer with per-layer target frame bandwidth, this is done 1267 // for every frame passed to the encoder (encoded or dropped). 1268 // For temporal layers, update the cumulative buffer level. 1269 for (int sl = 0; sl < number_spatial_layers_; ++sl) { 1270 for (int tl = temporal_layer_id_; tl < number_temporal_layers_; ++tl) { 1271 const int layer = sl * number_temporal_layers_ + tl; 1272 bits_in_buffer_model_[layer] += 1273 static_cast<int64_t>(layer_target_avg_bandwidth_[layer]); 1274 } 1275 } 1276 } 1277 1278 vpx_codec_err_t parse_superframe_index(const uint8_t *data, size_t data_sz, 1279 uint32_t sizes[8], int *count) { 1280 uint8_t marker; 1281 marker = *(data + data_sz - 1); 1282 *count = 0; 1283 if ((marker & 0xe0) == 0xc0) { 1284 const uint32_t frames = (marker & 0x7) + 1; 1285 const uint32_t mag = ((marker >> 3) & 0x3) + 1; 1286 const size_t index_sz = 2 + mag * frames; 1287 // This chunk is marked as having a superframe index but doesn't have 1288 // enough data for it, thus it's an invalid superframe index. 1289 if (data_sz < index_sz) return VPX_CODEC_CORRUPT_FRAME; 1290 { 1291 const uint8_t marker2 = *(data + data_sz - index_sz); 1292 // This chunk is marked as having a superframe index but doesn't have 1293 // the matching marker byte at the front of the index therefore it's an 1294 // invalid chunk. 1295 if (marker != marker2) return VPX_CODEC_CORRUPT_FRAME; 1296 } 1297 { 1298 uint32_t i, j; 1299 const uint8_t *x = &data[data_sz - index_sz + 1]; 1300 for (i = 0; i < frames; ++i) { 1301 uint32_t this_sz = 0; 1302 1303 for (j = 0; j < mag; ++j) this_sz |= (*x++) << (j * 8); 1304 sizes[i] = this_sz; 1305 } 1306 *count = frames; 1307 } 1308 } 1309 return VPX_CODEC_OK; 1310 } 1311 1312 virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) { 1313 uint32_t sizes[8] = { 0 }; 1314 int count = 0; 1315 last_pts_ = pkt->data.frame.pts; 1316 const bool key_frame = 1317 (pkt->data.frame.flags & VPX_FRAME_IS_KEY) ? true : false; 1318 parse_superframe_index(static_cast<const uint8_t *>(pkt->data.frame.buf), 1319 pkt->data.frame.sz, sizes, &count); 1320 ASSERT_EQ(count, number_spatial_layers_); 1321 for (int sl = 0; sl < number_spatial_layers_; ++sl) { 1322 sizes[sl] = sizes[sl] << 3; 1323 // Update the total encoded bits per layer. 1324 // For temporal layers, update the cumulative encoded bits per layer. 1325 for (int tl = temporal_layer_id_; tl < number_temporal_layers_; ++tl) { 1326 const int layer = sl * number_temporal_layers_ + tl; 1327 bits_total_[layer] += static_cast<int64_t>(sizes[sl]); 1328 // Update the per-layer buffer level with the encoded frame size. 1329 bits_in_buffer_model_[layer] -= static_cast<int64_t>(sizes[sl]); 1330 // There should be no buffer underrun, except on the base 1331 // temporal layer, since there may be key frames there. 1332 if (!key_frame && tl > 0) { 1333 ASSERT_GE(bits_in_buffer_model_[layer], 0) 1334 << "Buffer Underrun at frame " << pkt->data.frame.pts; 1335 } 1336 } 1337 } 1338 } 1339 1340 virtual void EndPassHook(void) { 1341 for (int sl = 0; sl < number_spatial_layers_; ++sl) { 1342 for (int tl = 0; tl < number_temporal_layers_; ++tl) { 1343 const int layer = sl * number_temporal_layers_ + tl; 1344 const double file_size_in_kb = bits_total_[layer] / 1000.; 1345 duration_ = (last_pts_ + 1) * timebase_; 1346 file_datarate_[layer] = file_size_in_kb / duration_; 1347 } 1348 } 1349 } 1350 1351 virtual void MismatchHook(const vpx_image_t *img1, const vpx_image_t *img2) { 1352 double mismatch_psnr = compute_psnr(img1, img2); 1353 mismatch_psnr_ += mismatch_psnr; 1354 ++mismatch_nframes_; 1355 } 1356 1357 unsigned int GetMismatchFrames() { return mismatch_nframes_; } 1358 1359 vpx_codec_pts_t last_pts_; 1360 int64_t bits_in_buffer_model_[VPX_MAX_LAYERS]; 1361 double timebase_; 1362 int64_t bits_total_[VPX_MAX_LAYERS]; 1363 double duration_; 1364 double file_datarate_[VPX_MAX_LAYERS]; 1365 size_t bits_in_last_frame_; 1366 vpx_svc_extra_cfg_t svc_params_; 1367 int speed_setting_; 1368 double mismatch_psnr_; 1369 int mismatch_nframes_; 1370 int denoiser_on_; 1371 int tune_content_; 1372 int base_speed_setting_; 1373 int spatial_layer_id_; 1374 int temporal_layer_id_; 1375 int number_spatial_layers_; 1376 int number_temporal_layers_; 1377 int layer_target_avg_bandwidth_[VPX_MAX_LAYERS]; 1378 }; 1379 static void assign_layer_bitrates(vpx_codec_enc_cfg_t *const enc_cfg, 1380 const vpx_svc_extra_cfg_t *svc_params, 1381 int spatial_layers, int temporal_layers, 1382 int temporal_layering_mode, 1383 int *layer_target_avg_bandwidth, 1384 int64_t *bits_in_buffer_model) { 1385 int sl, spatial_layer_target; 1386 float total = 0; 1387 float alloc_ratio[VPX_MAX_LAYERS] = { 0 }; 1388 float framerate = 30.0; 1389 for (sl = 0; sl < spatial_layers; ++sl) { 1390 if (svc_params->scaling_factor_den[sl] > 0) { 1391 alloc_ratio[sl] = (float)(svc_params->scaling_factor_num[sl] * 1.0 / 1392 svc_params->scaling_factor_den[sl]); 1393 total += alloc_ratio[sl]; 1394 } 1395 } 1396 for (sl = 0; sl < spatial_layers; ++sl) { 1397 enc_cfg->ss_target_bitrate[sl] = spatial_layer_target = 1398 (unsigned int)(enc_cfg->rc_target_bitrate * alloc_ratio[sl] / total); 1399 const int index = sl * temporal_layers; 1400 if (temporal_layering_mode == 3) { 1401 enc_cfg->layer_target_bitrate[index] = spatial_layer_target >> 1; 1402 enc_cfg->layer_target_bitrate[index + 1] = 1403 (spatial_layer_target >> 1) + (spatial_layer_target >> 2); 1404 enc_cfg->layer_target_bitrate[index + 2] = spatial_layer_target; 1405 } else if (temporal_layering_mode == 2) { 1406 enc_cfg->layer_target_bitrate[index] = spatial_layer_target * 2 / 3; 1407 enc_cfg->layer_target_bitrate[index + 1] = spatial_layer_target; 1408 } else if (temporal_layering_mode <= 1) { 1409 enc_cfg->layer_target_bitrate[index] = spatial_layer_target; 1410 } 1411 } 1412 for (sl = 0; sl < spatial_layers; ++sl) { 1413 for (int tl = 0; tl < temporal_layers; ++tl) { 1414 const int layer = sl * temporal_layers + tl; 1415 float layer_framerate = framerate; 1416 if (temporal_layers == 2 && tl == 0) layer_framerate = framerate / 2; 1417 if (temporal_layers == 3 && tl == 0) layer_framerate = framerate / 4; 1418 if (temporal_layers == 3 && tl == 1) layer_framerate = framerate / 2; 1419 layer_target_avg_bandwidth[layer] = static_cast<int>( 1420 enc_cfg->layer_target_bitrate[layer] * 1000.0 / layer_framerate); 1421 bits_in_buffer_model[layer] = 1422 enc_cfg->layer_target_bitrate[layer] * enc_cfg->rc_buf_initial_sz; 1423 } 1424 } 1425 } 1426 1427 static void CheckLayerRateTargeting(vpx_codec_enc_cfg_t *const cfg, 1428 int number_spatial_layers, 1429 int number_temporal_layers, 1430 double *file_datarate, 1431 double thresh_overshoot, 1432 double thresh_undershoot) { 1433 for (int sl = 0; sl < number_spatial_layers; ++sl) 1434 for (int tl = 0; tl < number_temporal_layers; ++tl) { 1435 const int layer = sl * number_temporal_layers + tl; 1436 ASSERT_GE(cfg->layer_target_bitrate[layer], 1437 file_datarate[layer] * thresh_overshoot) 1438 << " The datarate for the file exceeds the target by too much!"; 1439 ASSERT_LE(cfg->layer_target_bitrate[layer], 1440 file_datarate[layer] * thresh_undershoot) 1441 << " The datarate for the file is lower than the target by too much!"; 1442 } 1443 } 1444 1445 // Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and 1 1446 // temporal layer, with screen content mode on and same speed setting for all 1447 // layers. 1448 TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SL1TLScreenContent1) { 1449 cfg_.rc_buf_initial_sz = 500; 1450 cfg_.rc_buf_optimal_sz = 500; 1451 cfg_.rc_buf_sz = 1000; 1452 cfg_.rc_min_quantizer = 0; 1453 cfg_.rc_max_quantizer = 63; 1454 cfg_.rc_end_usage = VPX_CBR; 1455 cfg_.g_lag_in_frames = 0; 1456 cfg_.ss_number_layers = 2; 1457 cfg_.ts_number_layers = 1; 1458 cfg_.ts_rate_decimator[0] = 1; 1459 cfg_.g_error_resilient = 1; 1460 cfg_.g_threads = 1; 1461 cfg_.temporal_layering_mode = 0; 1462 svc_params_.scaling_factor_num[0] = 144; 1463 svc_params_.scaling_factor_den[0] = 288; 1464 svc_params_.scaling_factor_num[1] = 288; 1465 svc_params_.scaling_factor_den[1] = 288; 1466 cfg_.rc_dropframe_thresh = 10; 1467 cfg_.kf_max_dist = 9999; 1468 number_spatial_layers_ = cfg_.ss_number_layers; 1469 number_temporal_layers_ = cfg_.ts_number_layers; 1470 ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 60); 1471 cfg_.rc_target_bitrate = 500; 1472 ResetModel(); 1473 tune_content_ = 1; 1474 base_speed_setting_ = speed_setting_; 1475 assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers, 1476 cfg_.ts_number_layers, cfg_.temporal_layering_mode, 1477 layer_target_avg_bandwidth_, bits_in_buffer_model_); 1478 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 1479 CheckLayerRateTargeting(&cfg_, number_spatial_layers_, 1480 number_temporal_layers_, file_datarate_, 0.78, 1.15); 1481 EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames()); 1482 } 1483 1484 // Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and 1485 // 3 temporal layers. Run CIF clip with 1 thread. 1486 TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SL3TL) { 1487 cfg_.rc_buf_initial_sz = 500; 1488 cfg_.rc_buf_optimal_sz = 500; 1489 cfg_.rc_buf_sz = 1000; 1490 cfg_.rc_min_quantizer = 0; 1491 cfg_.rc_max_quantizer = 63; 1492 cfg_.rc_end_usage = VPX_CBR; 1493 cfg_.g_lag_in_frames = 0; 1494 cfg_.ss_number_layers = 2; 1495 cfg_.ts_number_layers = 3; 1496 cfg_.ts_rate_decimator[0] = 4; 1497 cfg_.ts_rate_decimator[1] = 2; 1498 cfg_.ts_rate_decimator[2] = 1; 1499 cfg_.g_error_resilient = 1; 1500 cfg_.g_threads = 1; 1501 cfg_.temporal_layering_mode = 3; 1502 svc_params_.scaling_factor_num[0] = 144; 1503 svc_params_.scaling_factor_den[0] = 288; 1504 svc_params_.scaling_factor_num[1] = 288; 1505 svc_params_.scaling_factor_den[1] = 288; 1506 cfg_.rc_dropframe_thresh = 0; 1507 cfg_.kf_max_dist = 9999; 1508 number_spatial_layers_ = cfg_.ss_number_layers; 1509 number_temporal_layers_ = cfg_.ts_number_layers; 1510 ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1, 1511 0, 400); 1512 // TODO(marpan): Check that effective_datarate for each layer hits the 1513 // layer target_bitrate. 1514 for (int i = 200; i <= 800; i += 200) { 1515 cfg_.rc_target_bitrate = i; 1516 ResetModel(); 1517 assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers, 1518 cfg_.ts_number_layers, cfg_.temporal_layering_mode, 1519 layer_target_avg_bandwidth_, bits_in_buffer_model_); 1520 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 1521 CheckLayerRateTargeting(&cfg_, number_spatial_layers_, 1522 number_temporal_layers_, file_datarate_, 0.78, 1523 1.15); 1524 #if CONFIG_VP9_DECODER 1525 // Number of temporal layers > 1, so half of the frames in this SVC pattern 1526 // will be non-reference frame and hence encoder will avoid loopfilter. 1527 // Since frame dropper is off, we can expect 200 (half of the sequence) 1528 // mismatched frames. 1529 EXPECT_EQ(static_cast<unsigned int>(200), GetMismatchFrames()); 1530 #endif 1531 } 1532 } 1533 1534 // Check basic rate targeting for 1 pass CBR SVC with denoising. 1535 // 2 spatial layers and 3 temporal layer. Run HD clip with 2 threads. 1536 TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SL3TLDenoiserOn) { 1537 cfg_.rc_buf_initial_sz = 500; 1538 cfg_.rc_buf_optimal_sz = 500; 1539 cfg_.rc_buf_sz = 1000; 1540 cfg_.rc_min_quantizer = 0; 1541 cfg_.rc_max_quantizer = 63; 1542 cfg_.rc_end_usage = VPX_CBR; 1543 cfg_.g_lag_in_frames = 0; 1544 cfg_.ss_number_layers = 2; 1545 cfg_.ts_number_layers = 3; 1546 cfg_.ts_rate_decimator[0] = 4; 1547 cfg_.ts_rate_decimator[1] = 2; 1548 cfg_.ts_rate_decimator[2] = 1; 1549 cfg_.g_error_resilient = 1; 1550 cfg_.g_threads = 2; 1551 cfg_.temporal_layering_mode = 3; 1552 svc_params_.scaling_factor_num[0] = 144; 1553 svc_params_.scaling_factor_den[0] = 288; 1554 svc_params_.scaling_factor_num[1] = 288; 1555 svc_params_.scaling_factor_den[1] = 288; 1556 cfg_.rc_dropframe_thresh = 0; 1557 cfg_.kf_max_dist = 9999; 1558 number_spatial_layers_ = cfg_.ss_number_layers; 1559 number_temporal_layers_ = cfg_.ts_number_layers; 1560 ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1, 1561 0, 400); 1562 // TODO(marpan): Check that effective_datarate for each layer hits the 1563 // layer target_bitrate. 1564 // For SVC, noise_sen = 1 means denoising only the top spatial layer 1565 // noise_sen = 2 means denoising the two top spatial layers. 1566 for (int noise_sen = 1; noise_sen <= 2; noise_sen++) { 1567 for (int i = 600; i <= 1000; i += 200) { 1568 cfg_.rc_target_bitrate = i; 1569 ResetModel(); 1570 denoiser_on_ = noise_sen; 1571 assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers, 1572 cfg_.ts_number_layers, cfg_.temporal_layering_mode, 1573 layer_target_avg_bandwidth_, bits_in_buffer_model_); 1574 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 1575 CheckLayerRateTargeting(&cfg_, number_spatial_layers_, 1576 number_temporal_layers_, file_datarate_, 0.78, 1577 1.15); 1578 #if CONFIG_VP9_DECODER 1579 // Number of temporal layers > 1, so half of the frames in this SVC 1580 // pattern 1581 // will be non-reference frame and hence encoder will avoid loopfilter. 1582 // Since frame dropper is off, we can expect 200 (half of the sequence) 1583 // mismatched frames. 1584 EXPECT_EQ(static_cast<unsigned int>(200), GetMismatchFrames()); 1585 #endif 1586 } 1587 } 1588 } 1589 1590 // Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and 3 1591 // temporal layers. Run CIF clip with 1 thread, and few short key frame periods. 1592 TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SL3TLSmallKf) { 1593 cfg_.rc_buf_initial_sz = 500; 1594 cfg_.rc_buf_optimal_sz = 500; 1595 cfg_.rc_buf_sz = 1000; 1596 cfg_.rc_min_quantizer = 0; 1597 cfg_.rc_max_quantizer = 63; 1598 cfg_.rc_end_usage = VPX_CBR; 1599 cfg_.g_lag_in_frames = 0; 1600 cfg_.ss_number_layers = 2; 1601 cfg_.ts_number_layers = 3; 1602 cfg_.ts_rate_decimator[0] = 4; 1603 cfg_.ts_rate_decimator[1] = 2; 1604 cfg_.ts_rate_decimator[2] = 1; 1605 cfg_.g_error_resilient = 1; 1606 cfg_.g_threads = 1; 1607 cfg_.temporal_layering_mode = 3; 1608 svc_params_.scaling_factor_num[0] = 144; 1609 svc_params_.scaling_factor_den[0] = 288; 1610 svc_params_.scaling_factor_num[1] = 288; 1611 svc_params_.scaling_factor_den[1] = 288; 1612 cfg_.rc_dropframe_thresh = 10; 1613 cfg_.rc_target_bitrate = 400; 1614 number_spatial_layers_ = cfg_.ss_number_layers; 1615 number_temporal_layers_ = cfg_.ts_number_layers; 1616 ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1, 1617 0, 400); 1618 // For this 3 temporal layer case, pattern repeats every 4 frames, so choose 1619 // 4 key neighboring key frame periods (so key frame will land on 0-2-1-2). 1620 for (int j = 64; j <= 67; j++) { 1621 cfg_.kf_max_dist = j; 1622 ResetModel(); 1623 assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers, 1624 cfg_.ts_number_layers, cfg_.temporal_layering_mode, 1625 layer_target_avg_bandwidth_, bits_in_buffer_model_); 1626 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 1627 CheckLayerRateTargeting(&cfg_, number_spatial_layers_, 1628 number_temporal_layers_, file_datarate_, 0.78, 1629 1.15); 1630 } 1631 } 1632 1633 // Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and 1634 // 3 temporal layers. Run HD clip with 4 threads. 1635 TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SL3TL4Threads) { 1636 cfg_.rc_buf_initial_sz = 500; 1637 cfg_.rc_buf_optimal_sz = 500; 1638 cfg_.rc_buf_sz = 1000; 1639 cfg_.rc_min_quantizer = 0; 1640 cfg_.rc_max_quantizer = 63; 1641 cfg_.rc_end_usage = VPX_CBR; 1642 cfg_.g_lag_in_frames = 0; 1643 cfg_.ss_number_layers = 2; 1644 cfg_.ts_number_layers = 3; 1645 cfg_.ts_rate_decimator[0] = 4; 1646 cfg_.ts_rate_decimator[1] = 2; 1647 cfg_.ts_rate_decimator[2] = 1; 1648 cfg_.g_error_resilient = 1; 1649 cfg_.g_threads = 4; 1650 cfg_.temporal_layering_mode = 3; 1651 svc_params_.scaling_factor_num[0] = 144; 1652 svc_params_.scaling_factor_den[0] = 288; 1653 svc_params_.scaling_factor_num[1] = 288; 1654 svc_params_.scaling_factor_den[1] = 288; 1655 cfg_.rc_dropframe_thresh = 0; 1656 cfg_.kf_max_dist = 9999; 1657 number_spatial_layers_ = cfg_.ss_number_layers; 1658 number_temporal_layers_ = cfg_.ts_number_layers; 1659 ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 60); 1660 cfg_.rc_target_bitrate = 800; 1661 ResetModel(); 1662 assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers, 1663 cfg_.ts_number_layers, cfg_.temporal_layering_mode, 1664 layer_target_avg_bandwidth_, bits_in_buffer_model_); 1665 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 1666 CheckLayerRateTargeting(&cfg_, number_spatial_layers_, 1667 number_temporal_layers_, file_datarate_, 0.78, 1.15); 1668 #if CONFIG_VP9_DECODER 1669 // Number of temporal layers > 1, so half of the frames in this SVC pattern 1670 // will be non-reference frame and hence encoder will avoid loopfilter. 1671 // Since frame dropper is off, we can expect 30 (half of the sequence) 1672 // mismatched frames. 1673 EXPECT_EQ(static_cast<unsigned int>(30), GetMismatchFrames()); 1674 #endif 1675 } 1676 1677 // Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and 1678 // 3 temporal layers. Run CIF clip with 1 thread. 1679 TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SL3TL) { 1680 cfg_.rc_buf_initial_sz = 500; 1681 cfg_.rc_buf_optimal_sz = 500; 1682 cfg_.rc_buf_sz = 1000; 1683 cfg_.rc_min_quantizer = 0; 1684 cfg_.rc_max_quantizer = 63; 1685 cfg_.rc_end_usage = VPX_CBR; 1686 cfg_.g_lag_in_frames = 0; 1687 cfg_.ss_number_layers = 3; 1688 cfg_.ts_number_layers = 3; 1689 cfg_.ts_rate_decimator[0] = 4; 1690 cfg_.ts_rate_decimator[1] = 2; 1691 cfg_.ts_rate_decimator[2] = 1; 1692 cfg_.g_error_resilient = 1; 1693 cfg_.g_threads = 1; 1694 cfg_.temporal_layering_mode = 3; 1695 svc_params_.scaling_factor_num[0] = 72; 1696 svc_params_.scaling_factor_den[0] = 288; 1697 svc_params_.scaling_factor_num[1] = 144; 1698 svc_params_.scaling_factor_den[1] = 288; 1699 svc_params_.scaling_factor_num[2] = 288; 1700 svc_params_.scaling_factor_den[2] = 288; 1701 cfg_.rc_dropframe_thresh = 0; 1702 cfg_.kf_max_dist = 9999; 1703 number_spatial_layers_ = cfg_.ss_number_layers; 1704 number_temporal_layers_ = cfg_.ts_number_layers; 1705 ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1, 1706 0, 400); 1707 cfg_.rc_target_bitrate = 800; 1708 ResetModel(); 1709 assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers, 1710 cfg_.ts_number_layers, cfg_.temporal_layering_mode, 1711 layer_target_avg_bandwidth_, bits_in_buffer_model_); 1712 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 1713 CheckLayerRateTargeting(&cfg_, number_spatial_layers_, 1714 number_temporal_layers_, file_datarate_, 0.78, 1.15); 1715 #if CONFIG_VP9_DECODER 1716 // Number of temporal layers > 1, so half of the frames in this SVC pattern 1717 // will be non-reference frame and hence encoder will avoid loopfilter. 1718 // Since frame dropper is off, we can expect 200 (half of the sequence) 1719 // mismatched frames. 1720 EXPECT_EQ(static_cast<unsigned int>(200), GetMismatchFrames()); 1721 #endif 1722 } 1723 1724 // Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and 3 1725 // temporal layers. Run CIF clip with 1 thread, and few short key frame periods. 1726 TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SL3TLSmallKf) { 1727 cfg_.rc_buf_initial_sz = 500; 1728 cfg_.rc_buf_optimal_sz = 500; 1729 cfg_.rc_buf_sz = 1000; 1730 cfg_.rc_min_quantizer = 0; 1731 cfg_.rc_max_quantizer = 63; 1732 cfg_.rc_end_usage = VPX_CBR; 1733 cfg_.g_lag_in_frames = 0; 1734 cfg_.ss_number_layers = 3; 1735 cfg_.ts_number_layers = 3; 1736 cfg_.ts_rate_decimator[0] = 4; 1737 cfg_.ts_rate_decimator[1] = 2; 1738 cfg_.ts_rate_decimator[2] = 1; 1739 cfg_.g_error_resilient = 1; 1740 cfg_.g_threads = 1; 1741 cfg_.temporal_layering_mode = 3; 1742 svc_params_.scaling_factor_num[0] = 72; 1743 svc_params_.scaling_factor_den[0] = 288; 1744 svc_params_.scaling_factor_num[1] = 144; 1745 svc_params_.scaling_factor_den[1] = 288; 1746 svc_params_.scaling_factor_num[2] = 288; 1747 svc_params_.scaling_factor_den[2] = 288; 1748 cfg_.rc_dropframe_thresh = 10; 1749 cfg_.rc_target_bitrate = 800; 1750 number_spatial_layers_ = cfg_.ss_number_layers; 1751 number_temporal_layers_ = cfg_.ts_number_layers; 1752 ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1, 1753 0, 400); 1754 // For this 3 temporal layer case, pattern repeats every 4 frames, so choose 1755 // 4 key neighboring key frame periods (so key frame will land on 0-2-1-2). 1756 for (int j = 32; j <= 35; j++) { 1757 cfg_.kf_max_dist = j; 1758 ResetModel(); 1759 assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers, 1760 cfg_.ts_number_layers, cfg_.temporal_layering_mode, 1761 layer_target_avg_bandwidth_, bits_in_buffer_model_); 1762 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 1763 CheckLayerRateTargeting(&cfg_, number_spatial_layers_, 1764 number_temporal_layers_, file_datarate_, 0.78, 1765 1.15); 1766 } 1767 } 1768 1769 // Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and 1770 // 3 temporal layers. Run HD clip with 4 threads. 1771 TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SL3TL4threads) { 1772 cfg_.rc_buf_initial_sz = 500; 1773 cfg_.rc_buf_optimal_sz = 500; 1774 cfg_.rc_buf_sz = 1000; 1775 cfg_.rc_min_quantizer = 0; 1776 cfg_.rc_max_quantizer = 63; 1777 cfg_.rc_end_usage = VPX_CBR; 1778 cfg_.g_lag_in_frames = 0; 1779 cfg_.ss_number_layers = 3; 1780 cfg_.ts_number_layers = 3; 1781 cfg_.ts_rate_decimator[0] = 4; 1782 cfg_.ts_rate_decimator[1] = 2; 1783 cfg_.ts_rate_decimator[2] = 1; 1784 cfg_.g_error_resilient = 1; 1785 cfg_.g_threads = 4; 1786 cfg_.temporal_layering_mode = 3; 1787 svc_params_.scaling_factor_num[0] = 72; 1788 svc_params_.scaling_factor_den[0] = 288; 1789 svc_params_.scaling_factor_num[1] = 144; 1790 svc_params_.scaling_factor_den[1] = 288; 1791 svc_params_.scaling_factor_num[2] = 288; 1792 svc_params_.scaling_factor_den[2] = 288; 1793 cfg_.rc_dropframe_thresh = 0; 1794 cfg_.kf_max_dist = 9999; 1795 number_spatial_layers_ = cfg_.ss_number_layers; 1796 number_temporal_layers_ = cfg_.ts_number_layers; 1797 ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 60); 1798 cfg_.rc_target_bitrate = 800; 1799 ResetModel(); 1800 assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers, 1801 cfg_.ts_number_layers, cfg_.temporal_layering_mode, 1802 layer_target_avg_bandwidth_, bits_in_buffer_model_); 1803 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 1804 CheckLayerRateTargeting(&cfg_, number_spatial_layers_, 1805 number_temporal_layers_, file_datarate_, 0.78, 1.15); 1806 #if CONFIG_VP9_DECODER 1807 // Number of temporal layers > 1, so half of the frames in this SVC pattern 1808 // will be non-reference frame and hence encoder will avoid loopfilter. 1809 // Since frame dropper is off, we can expect 30 (half of the sequence) 1810 // mismatched frames. 1811 EXPECT_EQ(static_cast<unsigned int>(30), GetMismatchFrames()); 1812 #endif 1813 } 1814 1815 // Run SVC encoder for 1 temporal layer, 2 spatial layers, with spatial 1816 // downscale 5x5. 1817 TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SL1TL5x5MultipleRuns) { 1818 cfg_.rc_buf_initial_sz = 500; 1819 cfg_.rc_buf_optimal_sz = 500; 1820 cfg_.rc_buf_sz = 1000; 1821 cfg_.rc_min_quantizer = 0; 1822 cfg_.rc_max_quantizer = 63; 1823 cfg_.rc_end_usage = VPX_CBR; 1824 cfg_.g_lag_in_frames = 0; 1825 cfg_.ss_number_layers = 2; 1826 cfg_.ts_number_layers = 1; 1827 cfg_.ts_rate_decimator[0] = 1; 1828 cfg_.g_error_resilient = 1; 1829 cfg_.g_threads = 3; 1830 cfg_.temporal_layering_mode = 0; 1831 svc_params_.scaling_factor_num[0] = 256; 1832 svc_params_.scaling_factor_den[0] = 1280; 1833 svc_params_.scaling_factor_num[1] = 1280; 1834 svc_params_.scaling_factor_den[1] = 1280; 1835 cfg_.rc_dropframe_thresh = 10; 1836 cfg_.kf_max_dist = 999999; 1837 cfg_.kf_min_dist = 0; 1838 cfg_.ss_target_bitrate[0] = 300; 1839 cfg_.ss_target_bitrate[1] = 1400; 1840 cfg_.layer_target_bitrate[0] = 300; 1841 cfg_.layer_target_bitrate[1] = 1400; 1842 cfg_.rc_target_bitrate = 1700; 1843 number_spatial_layers_ = cfg_.ss_number_layers; 1844 number_temporal_layers_ = cfg_.ts_number_layers; 1845 ResetModel(); 1846 layer_target_avg_bandwidth_[0] = cfg_.layer_target_bitrate[0] * 1000 / 30; 1847 bits_in_buffer_model_[0] = 1848 cfg_.layer_target_bitrate[0] * cfg_.rc_buf_initial_sz; 1849 layer_target_avg_bandwidth_[1] = cfg_.layer_target_bitrate[1] * 1000 / 30; 1850 bits_in_buffer_model_[1] = 1851 cfg_.layer_target_bitrate[1] * cfg_.rc_buf_initial_sz; 1852 ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 60); 1853 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 1854 CheckLayerRateTargeting(&cfg_, number_spatial_layers_, 1855 number_temporal_layers_, file_datarate_, 0.78, 1.15); 1856 EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames()); 1857 } 1858 1859 VP8_INSTANTIATE_TEST_CASE(DatarateTestLarge, ALL_TEST_MODES, 1860 ::testing::Values(0)); 1861 VP8_INSTANTIATE_TEST_CASE(DatarateTestRealTime, 1862 ::testing::Values(::libvpx_test::kRealTime), 1863 ::testing::Values(-6, -12)); 1864 VP9_INSTANTIATE_TEST_CASE(DatarateTestVP9Large, 1865 ::testing::Values(::libvpx_test::kOnePassGood, 1866 ::libvpx_test::kRealTime), 1867 ::testing::Range(2, 9)); 1868 #if CONFIG_VP9_TEMPORAL_DENOISING 1869 VP9_INSTANTIATE_TEST_CASE(DatarateTestVP9LargeDenoiser, 1870 ::testing::Values(::libvpx_test::kRealTime), 1871 ::testing::Range(5, 9)); 1872 #endif 1873 VP9_INSTANTIATE_TEST_CASE(DatarateOnePassCbrSvc, 1874 ::testing::Values(::libvpx_test::kRealTime), 1875 ::testing::Range(5, 9)); 1876 } // namespace 1877