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 18namespace { 19 20class DatarateTestLarge : public ::libvpx_test::EncoderTest, 21 public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> { 22 public: 23 DatarateTestLarge() : EncoderTest(GET_PARAM(0)) {} 24 25 virtual ~DatarateTestLarge() {} 26 27 protected: 28 virtual void SetUp() { 29 InitializeConfig(); 30 SetMode(GET_PARAM(1)); 31 ResetModel(); 32 } 33 34 virtual void ResetModel() { 35 last_pts_ = 0; 36 bits_in_buffer_model_ = cfg_.rc_target_bitrate * cfg_.rc_buf_initial_sz; 37 frame_number_ = 0; 38 first_drop_ = 0; 39 bits_total_ = 0; 40 duration_ = 0.0; 41 } 42 43 virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video, 44 ::libvpx_test::Encoder *encoder) { 45 if (video->frame() == 1) { 46 encoder->Control(VP8E_SET_NOISE_SENSITIVITY, denoiser_on_); 47 } 48 const vpx_rational_t tb = video->timebase(); 49 timebase_ = static_cast<double>(tb.num) / tb.den; 50 duration_ = 0; 51 } 52 53 virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) { 54 // Time since last timestamp = duration. 55 vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_; 56 57 // TODO(jimbankoski): Remove these lines when the issue: 58 // http://code.google.com/p/webm/issues/detail?id=496 is fixed. 59 // For now the codec assumes buffer starts at starting buffer rate 60 // plus one frame's time. 61 if (last_pts_ == 0) 62 duration = 1; 63 64 // Add to the buffer the bits we'd expect from a constant bitrate server. 65 bits_in_buffer_model_ += static_cast<int64_t>( 66 duration * timebase_ * cfg_.rc_target_bitrate * 1000); 67 68 /* Test the buffer model here before subtracting the frame. Do so because 69 * the way the leaky bucket model works in libvpx is to allow the buffer to 70 * empty - and then stop showing frames until we've got enough bits to 71 * show one. As noted in comment below (issue 495), this does not currently 72 * apply to key frames. For now exclude key frames in condition below. */ 73 const bool key_frame = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) 74 ? true: false; 75 if (!key_frame) { 76 ASSERT_GE(bits_in_buffer_model_, 0) << "Buffer Underrun at frame " 77 << pkt->data.frame.pts; 78 } 79 80 const size_t frame_size_in_bits = pkt->data.frame.sz * 8; 81 82 // Subtract from the buffer the bits associated with a played back frame. 83 bits_in_buffer_model_ -= frame_size_in_bits; 84 85 // Update the running total of bits for end of test datarate checks. 86 bits_total_ += frame_size_in_bits; 87 88 // If first drop not set and we have a drop set it to this time. 89 if (!first_drop_ && duration > 1) 90 first_drop_ = last_pts_ + 1; 91 92 // Update the most recent pts. 93 last_pts_ = pkt->data.frame.pts; 94 95 // We update this so that we can calculate the datarate minus the last 96 // frame encoded in the file. 97 bits_in_last_frame_ = frame_size_in_bits; 98 99 ++frame_number_; 100 } 101 102 virtual void EndPassHook(void) { 103 if (bits_total_) { 104 const double file_size_in_kb = bits_total_ / 1000.; // bits per kilobit 105 106 duration_ = (last_pts_ + 1) * timebase_; 107 108 // Effective file datarate includes the time spent prebuffering. 109 effective_datarate_ = (bits_total_ - bits_in_last_frame_) / 1000.0 110 / (cfg_.rc_buf_initial_sz / 1000.0 + duration_); 111 112 file_datarate_ = file_size_in_kb / duration_; 113 } 114 } 115 116 vpx_codec_pts_t last_pts_; 117 int64_t bits_in_buffer_model_; 118 double timebase_; 119 int frame_number_; 120 vpx_codec_pts_t first_drop_; 121 int64_t bits_total_; 122 double duration_; 123 double file_datarate_; 124 double effective_datarate_; 125 size_t bits_in_last_frame_; 126 int denoiser_on_; 127}; 128 129#if CONFIG_TEMPORAL_DENOISING 130// Check basic datarate targeting, for a single bitrate, but loop over the 131// various denoiser settings. 132TEST_P(DatarateTestLarge, DenoiserLevels) { 133 cfg_.rc_buf_initial_sz = 500; 134 cfg_.rc_dropframe_thresh = 1; 135 cfg_.rc_max_quantizer = 56; 136 cfg_.rc_end_usage = VPX_CBR; 137 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 138 30, 1, 0, 140); 139 for (int j = 1; j < 5; ++j) { 140 // Run over the denoiser levels. 141 // For the temporal denoiser (#if CONFIG_TEMPORAL_DENOISING) the level j 142 // refers to the 4 denoiser modes: denoiserYonly, denoiserOnYUV, 143 // denoiserOnAggressive, and denoiserOnAdaptive. 144 // For the spatial denoiser (if !CONFIG_TEMPORAL_DENOISING), the level j 145 // refers to the blur thresholds: 20, 40, 60 80. 146 // The j = 0 case (denoiser off) is covered in the tests below. 147 denoiser_on_ = j; 148 cfg_.rc_target_bitrate = 300; 149 ResetModel(); 150 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 151 ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95) 152 << " The datarate for the file exceeds the target!"; 153 154 ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.3) 155 << " The datarate for the file missed the target!"; 156 } 157} 158#endif // CONFIG_TEMPORAL_DENOISING 159 160TEST_P(DatarateTestLarge, BasicBufferModel) { 161 denoiser_on_ = 0; 162 cfg_.rc_buf_initial_sz = 500; 163 cfg_.rc_dropframe_thresh = 1; 164 cfg_.rc_max_quantizer = 56; 165 cfg_.rc_end_usage = VPX_CBR; 166 // 2 pass cbr datarate control has a bug hidden by the small # of 167 // frames selected in this encode. The problem is that even if the buffer is 168 // negative we produce a keyframe on a cutscene. Ignoring datarate 169 // constraints 170 // TODO(jimbankoski): ( Fix when issue 171 // http://code.google.com/p/webm/issues/detail?id=495 is addressed. ) 172 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 173 30, 1, 0, 140); 174 175 // There is an issue for low bitrates in real-time mode, where the 176 // effective_datarate slightly overshoots the target bitrate. 177 // This is same the issue as noted about (#495). 178 // TODO(jimbankoski/marpan): Update test to run for lower bitrates (< 100), 179 // when the issue is resolved. 180 for (int i = 100; i < 800; i += 200) { 181 cfg_.rc_target_bitrate = i; 182 ResetModel(); 183 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 184 ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95) 185 << " The datarate for the file exceeds the target!"; 186 187 ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.3) 188 << " The datarate for the file missed the target!"; 189 } 190} 191 192TEST_P(DatarateTestLarge, ChangingDropFrameThresh) { 193 denoiser_on_ = 0; 194 cfg_.rc_buf_initial_sz = 500; 195 cfg_.rc_max_quantizer = 36; 196 cfg_.rc_end_usage = VPX_CBR; 197 cfg_.rc_target_bitrate = 200; 198 cfg_.kf_mode = VPX_KF_DISABLED; 199 200 const int frame_count = 40; 201 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 202 30, 1, 0, frame_count); 203 204 // Here we check that the first dropped frame gets earlier and earlier 205 // as the drop frame threshold is increased. 206 207 const int kDropFrameThreshTestStep = 30; 208 vpx_codec_pts_t last_drop = frame_count; 209 for (int i = 1; i < 91; i += kDropFrameThreshTestStep) { 210 cfg_.rc_dropframe_thresh = i; 211 ResetModel(); 212 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 213 ASSERT_LE(first_drop_, last_drop) 214 << " The first dropped frame for drop_thresh " << i 215 << " > first dropped frame for drop_thresh " 216 << i - kDropFrameThreshTestStep; 217 last_drop = first_drop_; 218 } 219} 220 221class DatarateTestVP9Large : public ::libvpx_test::EncoderTest, 222 public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> { 223 public: 224 DatarateTestVP9Large() : EncoderTest(GET_PARAM(0)) {} 225 226 protected: 227 virtual ~DatarateTestVP9Large() {} 228 229 virtual void SetUp() { 230 InitializeConfig(); 231 SetMode(GET_PARAM(1)); 232 set_cpu_used_ = GET_PARAM(2); 233 ResetModel(); 234 } 235 236 virtual void ResetModel() { 237 last_pts_ = 0; 238 bits_in_buffer_model_ = cfg_.rc_target_bitrate * cfg_.rc_buf_initial_sz; 239 frame_number_ = 0; 240 tot_frame_number_ = 0; 241 first_drop_ = 0; 242 num_drops_ = 0; 243 // Denoiser is off by default. 244 denoiser_on_ = 0; 245 // For testing up to 3 layers. 246 for (int i = 0; i < 3; ++i) { 247 bits_total_[i] = 0; 248 } 249 } 250 251 // 252 // Frame flags and layer id for temporal layers. 253 // 254 255 // For two layers, test pattern is: 256 // 1 3 257 // 0 2 ..... 258 // For three layers, test pattern is: 259 // 1 3 5 7 260 // 2 6 261 // 0 4 .... 262 // LAST is always update on base/layer 0, GOLDEN is updated on layer 1. 263 // For this 3 layer example, the 2nd enhancement layer (layer 2) does not 264 // update any reference frames. 265 int SetFrameFlags(int frame_num, int num_temp_layers) { 266 int frame_flags = 0; 267 if (num_temp_layers == 2) { 268 if (frame_num % 2 == 0) { 269 // Layer 0: predict from L and ARF, update L. 270 frame_flags = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | 271 VP8_EFLAG_NO_UPD_ARF; 272 } else { 273 // Layer 1: predict from L, G and ARF, and update G. 274 frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST | 275 VP8_EFLAG_NO_UPD_ENTROPY; 276 } 277 } else if (num_temp_layers == 3) { 278 if (frame_num % 4 == 0) { 279 // Layer 0: predict from L and ARF; update L. 280 frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | 281 VP8_EFLAG_NO_REF_GF; 282 } else if ((frame_num - 2) % 4 == 0) { 283 // Layer 1: predict from L, G, ARF; update G. 284 frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST; 285 } else if ((frame_num - 1) % 2 == 0) { 286 // Layer 2: predict from L, G, ARF; update none. 287 frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | 288 VP8_EFLAG_NO_UPD_LAST; 289 } 290 } 291 return frame_flags; 292 } 293 294 int SetLayerId(int frame_num, int num_temp_layers) { 295 int layer_id = 0; 296 if (num_temp_layers == 2) { 297 if (frame_num % 2 == 0) { 298 layer_id = 0; 299 } else { 300 layer_id = 1; 301 } 302 } else if (num_temp_layers == 3) { 303 if (frame_num % 4 == 0) { 304 layer_id = 0; 305 } else if ((frame_num - 2) % 4 == 0) { 306 layer_id = 1; 307 } else if ((frame_num - 1) % 2 == 0) { 308 layer_id = 2; 309 } 310 } 311 return layer_id; 312 } 313 314 virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video, 315 ::libvpx_test::Encoder *encoder) { 316 if (video->frame() == 1) { 317 encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_); 318 encoder->Control(VP9E_SET_NOISE_SENSITIVITY, denoiser_on_); 319 } 320 if (cfg_.ts_number_layers > 1) { 321 if (video->frame() == 1) { 322 encoder->Control(VP9E_SET_SVC, 1); 323 } 324 vpx_svc_layer_id_t layer_id = {0, 0}; 325 layer_id.spatial_layer_id = 0; 326 frame_flags_ = SetFrameFlags(video->frame(), cfg_.ts_number_layers); 327 layer_id.temporal_layer_id = SetLayerId(video->frame(), 328 cfg_.ts_number_layers); 329 if (video->frame() > 0) { 330 encoder->Control(VP9E_SET_SVC_LAYER_ID, &layer_id); 331 } 332 } 333 const vpx_rational_t tb = video->timebase(); 334 timebase_ = static_cast<double>(tb.num) / tb.den; 335 duration_ = 0; 336 } 337 338 339 virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) { 340 // Time since last timestamp = duration. 341 vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_; 342 343 if (duration > 1) { 344 // If first drop not set and we have a drop set it to this time. 345 if (!first_drop_) 346 first_drop_ = last_pts_ + 1; 347 // Update the number of frame drops. 348 num_drops_ += static_cast<int>(duration - 1); 349 // Update counter for total number of frames (#frames input to encoder). 350 // Needed for setting the proper layer_id below. 351 tot_frame_number_ += static_cast<int>(duration - 1); 352 } 353 354 int layer = SetLayerId(tot_frame_number_, cfg_.ts_number_layers); 355 356 // Add to the buffer the bits we'd expect from a constant bitrate server. 357 bits_in_buffer_model_ += static_cast<int64_t>( 358 duration * timebase_ * cfg_.rc_target_bitrate * 1000); 359 360 // Buffer should not go negative. 361 ASSERT_GE(bits_in_buffer_model_, 0) << "Buffer Underrun at frame " 362 << pkt->data.frame.pts; 363 364 const size_t frame_size_in_bits = pkt->data.frame.sz * 8; 365 366 // Update the total encoded bits. For temporal layers, update the cumulative 367 // encoded bits per layer. 368 for (int i = layer; i < static_cast<int>(cfg_.ts_number_layers); ++i) { 369 bits_total_[i] += frame_size_in_bits; 370 } 371 372 // Update the most recent pts. 373 last_pts_ = pkt->data.frame.pts; 374 ++frame_number_; 375 ++tot_frame_number_; 376 } 377 378 virtual void EndPassHook(void) { 379 for (int layer = 0; layer < static_cast<int>(cfg_.ts_number_layers); 380 ++layer) { 381 duration_ = (last_pts_ + 1) * timebase_; 382 if (bits_total_[layer]) { 383 // Effective file datarate: 384 effective_datarate_[layer] = (bits_total_[layer] / 1000.0) / duration_; 385 } 386 } 387 } 388 389 vpx_codec_pts_t last_pts_; 390 double timebase_; 391 int frame_number_; // Counter for number of non-dropped/encoded frames. 392 int tot_frame_number_; // Counter for total number of input frames. 393 int64_t bits_total_[3]; 394 double duration_; 395 double effective_datarate_[3]; 396 int set_cpu_used_; 397 int64_t bits_in_buffer_model_; 398 vpx_codec_pts_t first_drop_; 399 int num_drops_; 400 int denoiser_on_; 401}; 402 403// Check basic rate targeting, 404TEST_P(DatarateTestVP9Large, BasicRateTargeting) { 405 cfg_.rc_buf_initial_sz = 500; 406 cfg_.rc_buf_optimal_sz = 500; 407 cfg_.rc_buf_sz = 1000; 408 cfg_.rc_dropframe_thresh = 1; 409 cfg_.rc_min_quantizer = 0; 410 cfg_.rc_max_quantizer = 63; 411 cfg_.rc_end_usage = VPX_CBR; 412 cfg_.g_lag_in_frames = 0; 413 414 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 415 30, 1, 0, 140); 416 for (int i = 150; i < 800; i += 200) { 417 cfg_.rc_target_bitrate = i; 418 ResetModel(); 419 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 420 ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85) 421 << " The datarate for the file is lower than target by too much!"; 422 ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15) 423 << " The datarate for the file is greater than target by too much!"; 424 } 425} 426 427// Check basic rate targeting, 428TEST_P(DatarateTestVP9Large, BasicRateTargeting444) { 429 ::libvpx_test::Y4mVideoSource video("rush_hour_444.y4m", 0, 140); 430 431 cfg_.g_profile = 1; 432 cfg_.g_timebase = video.timebase(); 433 434 cfg_.rc_buf_initial_sz = 500; 435 cfg_.rc_buf_optimal_sz = 500; 436 cfg_.rc_buf_sz = 1000; 437 cfg_.rc_dropframe_thresh = 1; 438 cfg_.rc_min_quantizer = 0; 439 cfg_.rc_max_quantizer = 63; 440 cfg_.rc_end_usage = VPX_CBR; 441 442 for (int i = 250; i < 900; i += 200) { 443 cfg_.rc_target_bitrate = i; 444 ResetModel(); 445 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 446 ASSERT_GE(static_cast<double>(cfg_.rc_target_bitrate), 447 effective_datarate_[0] * 0.85) 448 << " The datarate for the file exceeds the target by too much!"; 449 ASSERT_LE(static_cast<double>(cfg_.rc_target_bitrate), 450 effective_datarate_[0] * 1.15) 451 << " The datarate for the file missed the target!" 452 << cfg_.rc_target_bitrate << " "<< effective_datarate_; 453 } 454} 455 456// Check that (1) the first dropped frame gets earlier and earlier 457// as the drop frame threshold is increased, and (2) that the total number of 458// frame drops does not decrease as we increase frame drop threshold. 459// Use a lower qp-max to force some frame drops. 460TEST_P(DatarateTestVP9Large, ChangingDropFrameThresh) { 461 cfg_.rc_buf_initial_sz = 500; 462 cfg_.rc_buf_optimal_sz = 500; 463 cfg_.rc_buf_sz = 1000; 464 cfg_.rc_undershoot_pct = 20; 465 cfg_.rc_undershoot_pct = 20; 466 cfg_.rc_dropframe_thresh = 10; 467 cfg_.rc_min_quantizer = 0; 468 cfg_.rc_max_quantizer = 50; 469 cfg_.rc_end_usage = VPX_CBR; 470 cfg_.rc_target_bitrate = 200; 471 cfg_.g_lag_in_frames = 0; 472 473 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 474 30, 1, 0, 140); 475 476 const int kDropFrameThreshTestStep = 30; 477 vpx_codec_pts_t last_drop = 140; 478 int last_num_drops = 0; 479 for (int i = 10; i < 100; i += kDropFrameThreshTestStep) { 480 cfg_.rc_dropframe_thresh = i; 481 ResetModel(); 482 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 483 ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85) 484 << " The datarate for the file is lower than target by too much!"; 485 ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15) 486 << " The datarate for the file is greater than target by too much!"; 487 ASSERT_LE(first_drop_, last_drop) 488 << " The first dropped frame for drop_thresh " << i 489 << " > first dropped frame for drop_thresh " 490 << i - kDropFrameThreshTestStep; 491 ASSERT_GE(num_drops_, last_num_drops) 492 << " The number of dropped frames for drop_thresh " << i 493 << " < number of dropped frames for drop_thresh " 494 << i - kDropFrameThreshTestStep; 495 last_drop = first_drop_; 496 last_num_drops = num_drops_; 497 } 498} 499 500// Check basic rate targeting for 2 temporal layers. 501TEST_P(DatarateTestVP9Large, BasicRateTargeting2TemporalLayers) { 502 cfg_.rc_buf_initial_sz = 500; 503 cfg_.rc_buf_optimal_sz = 500; 504 cfg_.rc_buf_sz = 1000; 505 cfg_.rc_dropframe_thresh = 1; 506 cfg_.rc_min_quantizer = 0; 507 cfg_.rc_max_quantizer = 63; 508 cfg_.rc_end_usage = VPX_CBR; 509 cfg_.g_lag_in_frames = 0; 510 511 // 2 Temporal layers, no spatial layers: Framerate decimation (2, 1). 512 cfg_.ss_number_layers = 1; 513 cfg_.ts_number_layers = 2; 514 cfg_.ts_rate_decimator[0] = 2; 515 cfg_.ts_rate_decimator[1] = 1; 516 517 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 518 30, 1, 0, 200); 519 for (int i = 200; i <= 800; i += 200) { 520 cfg_.rc_target_bitrate = i; 521 ResetModel(); 522 // 60-40 bitrate allocation for 2 temporal layers. 523 cfg_.ts_target_bitrate[0] = 60 * cfg_.rc_target_bitrate / 100; 524 cfg_.ts_target_bitrate[1] = cfg_.rc_target_bitrate; 525 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 526 for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) { 527 ASSERT_GE(effective_datarate_[j], cfg_.ts_target_bitrate[j] * 0.85) 528 << " The datarate for the file is lower than target by too much, " 529 "for layer: " << j; 530 ASSERT_LE(effective_datarate_[j], cfg_.ts_target_bitrate[j] * 1.15) 531 << " The datarate for the file is greater than target by too much, " 532 "for layer: " << j; 533 } 534 } 535} 536 537// Check basic rate targeting for 3 temporal layers. 538TEST_P(DatarateTestVP9Large, BasicRateTargeting3TemporalLayers) { 539 cfg_.rc_buf_initial_sz = 500; 540 cfg_.rc_buf_optimal_sz = 500; 541 cfg_.rc_buf_sz = 1000; 542 cfg_.rc_dropframe_thresh = 1; 543 cfg_.rc_min_quantizer = 0; 544 cfg_.rc_max_quantizer = 63; 545 cfg_.rc_end_usage = VPX_CBR; 546 cfg_.g_lag_in_frames = 0; 547 548 // 3 Temporal layers, no spatial layers: Framerate decimation (4, 2, 1). 549 cfg_.ss_number_layers = 1; 550 cfg_.ts_number_layers = 3; 551 cfg_.ts_rate_decimator[0] = 4; 552 cfg_.ts_rate_decimator[1] = 2; 553 cfg_.ts_rate_decimator[2] = 1; 554 555 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 556 30, 1, 0, 200); 557 for (int i = 200; i <= 800; i += 200) { 558 cfg_.rc_target_bitrate = i; 559 ResetModel(); 560 // 40-20-40 bitrate allocation for 3 temporal layers. 561 cfg_.ts_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100; 562 cfg_.ts_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100; 563 cfg_.ts_target_bitrate[2] = cfg_.rc_target_bitrate; 564 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 565 for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) { 566 // TODO(yaowu): Work out more stable rc control strategy and 567 // Adjust the thresholds to be tighter than .75. 568 ASSERT_GE(effective_datarate_[j], cfg_.ts_target_bitrate[j] * 0.75) 569 << " The datarate for the file is lower than target by too much, " 570 "for layer: " << j; 571 // TODO(yaowu): Work out more stable rc control strategy and 572 // Adjust the thresholds to be tighter than 1.25. 573 ASSERT_LE(effective_datarate_[j], cfg_.ts_target_bitrate[j] * 1.25) 574 << " The datarate for the file is greater than target by too much, " 575 "for layer: " << j; 576 } 577 } 578} 579 580// Check basic rate targeting for 3 temporal layers, with frame dropping. 581// Only for one (low) bitrate with lower max_quantizer, and somewhat higher 582// frame drop threshold, to force frame dropping. 583TEST_P(DatarateTestVP9Large, BasicRateTargeting3TemporalLayersFrameDropping) { 584 cfg_.rc_buf_initial_sz = 500; 585 cfg_.rc_buf_optimal_sz = 500; 586 cfg_.rc_buf_sz = 1000; 587 // Set frame drop threshold and rc_max_quantizer to force some frame drops. 588 cfg_.rc_dropframe_thresh = 20; 589 cfg_.rc_max_quantizer = 45; 590 cfg_.rc_min_quantizer = 0; 591 cfg_.rc_end_usage = VPX_CBR; 592 cfg_.g_lag_in_frames = 0; 593 594 // 3 Temporal layers, no spatial layers: Framerate decimation (4, 2, 1). 595 cfg_.ss_number_layers = 1; 596 cfg_.ts_number_layers = 3; 597 cfg_.ts_rate_decimator[0] = 4; 598 cfg_.ts_rate_decimator[1] = 2; 599 cfg_.ts_rate_decimator[2] = 1; 600 601 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 602 30, 1, 0, 200); 603 cfg_.rc_target_bitrate = 200; 604 ResetModel(); 605 // 40-20-40 bitrate allocation for 3 temporal layers. 606 cfg_.ts_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100; 607 cfg_.ts_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100; 608 cfg_.ts_target_bitrate[2] = cfg_.rc_target_bitrate; 609 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 610 for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) { 611 ASSERT_GE(effective_datarate_[j], cfg_.ts_target_bitrate[j] * 0.85) 612 << " The datarate for the file is lower than target by too much, " 613 "for layer: " << j; 614 ASSERT_LE(effective_datarate_[j], cfg_.ts_target_bitrate[j] * 1.15) 615 << " The datarate for the file is greater than target by too much, " 616 "for layer: " << j; 617 // Expect some frame drops in this test: for this 200 frames test, 618 // expect at least 10% and not more than 60% drops. 619 ASSERT_GE(num_drops_, 20); 620 ASSERT_LE(num_drops_, 130); 621 } 622} 623 624#if CONFIG_VP9_TEMPORAL_DENOISING 625// Check basic datarate targeting, for a single bitrate, when denoiser is on. 626TEST_P(DatarateTestVP9Large, DenoiserLevels) { 627 cfg_.rc_buf_initial_sz = 500; 628 cfg_.rc_buf_optimal_sz = 500; 629 cfg_.rc_buf_sz = 1000; 630 cfg_.rc_dropframe_thresh = 1; 631 cfg_.rc_min_quantizer = 2; 632 cfg_.rc_max_quantizer = 56; 633 cfg_.rc_end_usage = VPX_CBR; 634 cfg_.g_lag_in_frames = 0; 635 636 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 637 30, 1, 0, 140); 638 639 // For the temporal denoiser (#if CONFIG_VP9_TEMPORAL_DENOISING), 640 // there is only one denoiser mode: denoiserYonly(which is 1), 641 // but may add more modes in the future. 642 cfg_.rc_target_bitrate = 300; 643 ResetModel(); 644 // Turn on the denoiser. 645 denoiser_on_ = 1; 646 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 647 ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85) 648 << " The datarate for the file is lower than target by too much!"; 649 ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15) 650 << " The datarate for the file is greater than target by too much!"; 651} 652#endif // CONFIG_VP9_TEMPORAL_DENOISING 653 654VP8_INSTANTIATE_TEST_CASE(DatarateTestLarge, ALL_TEST_MODES); 655VP9_INSTANTIATE_TEST_CASE(DatarateTestVP9Large, 656 ::testing::Values(::libvpx_test::kOnePassGood, 657 ::libvpx_test::kRealTime), 658 ::testing::Range(2, 7)); 659} // namespace 660