1 /* 2 * Copyright (c) 2013 The WebM project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "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 17 namespace { 18 19 const int kMaxErrorFrames = 12; 20 const int kMaxDroppableFrames = 12; 21 22 class ErrorResilienceTestLarge 23 : public ::libvpx_test::EncoderTest, 24 public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, bool> { 25 protected: 26 ErrorResilienceTestLarge() 27 : EncoderTest(GET_PARAM(0)), svc_support_(GET_PARAM(2)), psnr_(0.0), 28 nframes_(0), mismatch_psnr_(0.0), mismatch_nframes_(0), 29 encoding_mode_(GET_PARAM(1)) { 30 Reset(); 31 } 32 33 virtual ~ErrorResilienceTestLarge() {} 34 35 void Reset() { 36 error_nframes_ = 0; 37 droppable_nframes_ = 0; 38 pattern_switch_ = 0; 39 } 40 41 virtual void SetUp() { 42 InitializeConfig(); 43 SetMode(encoding_mode_); 44 } 45 46 virtual void BeginPassHook(unsigned int /*pass*/) { 47 psnr_ = 0.0; 48 nframes_ = 0; 49 mismatch_psnr_ = 0.0; 50 mismatch_nframes_ = 0; 51 } 52 53 virtual void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) { 54 psnr_ += pkt->data.psnr.psnr[0]; 55 nframes_++; 56 } 57 58 // 59 // Frame flags and layer id for temporal layers. 60 // For two layers, test pattern is: 61 // 1 3 62 // 0 2 ..... 63 // LAST is updated on base/layer 0, GOLDEN updated on layer 1. 64 // Non-zero pattern_switch parameter means pattern will switch to 65 // not using LAST for frame_num >= pattern_switch. 66 int SetFrameFlags(int frame_num, int num_temp_layers, int pattern_switch) { 67 int frame_flags = 0; 68 if (num_temp_layers == 2) { 69 if (frame_num % 2 == 0) { 70 if (frame_num < pattern_switch || pattern_switch == 0) { 71 // Layer 0: predict from LAST and ARF, update LAST. 72 frame_flags = 73 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; 74 } else { 75 // Layer 0: predict from GF and ARF, update GF. 76 frame_flags = VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_UPD_LAST | 77 VP8_EFLAG_NO_UPD_ARF; 78 } 79 } else { 80 if (frame_num < pattern_switch || pattern_switch == 0) { 81 // Layer 1: predict from L, GF, and ARF, update GF. 82 frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST; 83 } else { 84 // Layer 1: predict from GF and ARF, update GF. 85 frame_flags = VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_UPD_LAST | 86 VP8_EFLAG_NO_UPD_ARF; 87 } 88 } 89 } 90 return frame_flags; 91 } 92 93 virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video) { 94 frame_flags_ &= 95 ~(VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF); 96 // For temporal layer case. 97 if (cfg_.ts_number_layers > 1) { 98 frame_flags_ = 99 SetFrameFlags(video->frame(), cfg_.ts_number_layers, pattern_switch_); 100 for (unsigned int i = 0; i < droppable_nframes_; ++i) { 101 if (droppable_frames_[i] == video->frame()) { 102 std::cout << "Encoding droppable frame: " << droppable_frames_[i] 103 << "\n"; 104 } 105 } 106 } else { 107 if (droppable_nframes_ > 0 && 108 (cfg_.g_pass == VPX_RC_LAST_PASS || cfg_.g_pass == VPX_RC_ONE_PASS)) { 109 for (unsigned int i = 0; i < droppable_nframes_; ++i) { 110 if (droppable_frames_[i] == video->frame()) { 111 std::cout << "Encoding droppable frame: " << droppable_frames_[i] 112 << "\n"; 113 frame_flags_ |= (VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF | 114 VP8_EFLAG_NO_UPD_ARF); 115 return; 116 } 117 } 118 } 119 } 120 } 121 122 double GetAveragePsnr() const { 123 if (nframes_) return psnr_ / nframes_; 124 return 0.0; 125 } 126 127 double GetAverageMismatchPsnr() const { 128 if (mismatch_nframes_) return mismatch_psnr_ / mismatch_nframes_; 129 return 0.0; 130 } 131 132 virtual bool DoDecode() const { 133 if (error_nframes_ > 0 && 134 (cfg_.g_pass == VPX_RC_LAST_PASS || cfg_.g_pass == VPX_RC_ONE_PASS)) { 135 for (unsigned int i = 0; i < error_nframes_; ++i) { 136 if (error_frames_[i] == nframes_ - 1) { 137 std::cout << " Skipping decoding frame: " 138 << error_frames_[i] << "\n"; 139 return 0; 140 } 141 } 142 } 143 return 1; 144 } 145 146 virtual void MismatchHook(const vpx_image_t *img1, const vpx_image_t *img2) { 147 double mismatch_psnr = compute_psnr(img1, img2); 148 mismatch_psnr_ += mismatch_psnr; 149 ++mismatch_nframes_; 150 // std::cout << "Mismatch frame psnr: " << mismatch_psnr << "\n"; 151 } 152 153 void SetErrorFrames(int num, unsigned int *list) { 154 if (num > kMaxErrorFrames) { 155 num = kMaxErrorFrames; 156 } else if (num < 0) { 157 num = 0; 158 } 159 error_nframes_ = num; 160 for (unsigned int i = 0; i < error_nframes_; ++i) { 161 error_frames_[i] = list[i]; 162 } 163 } 164 165 void SetDroppableFrames(int num, unsigned int *list) { 166 if (num > kMaxDroppableFrames) { 167 num = kMaxDroppableFrames; 168 } else if (num < 0) { 169 num = 0; 170 } 171 droppable_nframes_ = num; 172 for (unsigned int i = 0; i < droppable_nframes_; ++i) { 173 droppable_frames_[i] = list[i]; 174 } 175 } 176 177 unsigned int GetMismatchFrames() { return mismatch_nframes_; } 178 179 void SetPatternSwitch(int frame_switch) { pattern_switch_ = frame_switch; } 180 181 bool svc_support_; 182 183 private: 184 double psnr_; 185 unsigned int nframes_; 186 unsigned int error_nframes_; 187 unsigned int droppable_nframes_; 188 unsigned int pattern_switch_; 189 double mismatch_psnr_; 190 unsigned int mismatch_nframes_; 191 unsigned int error_frames_[kMaxErrorFrames]; 192 unsigned int droppable_frames_[kMaxDroppableFrames]; 193 libvpx_test::TestMode encoding_mode_; 194 }; 195 196 TEST_P(ErrorResilienceTestLarge, OnVersusOff) { 197 const vpx_rational timebase = { 33333333, 1000000000 }; 198 cfg_.g_timebase = timebase; 199 cfg_.rc_target_bitrate = 2000; 200 cfg_.g_lag_in_frames = 10; 201 202 init_flags_ = VPX_CODEC_USE_PSNR; 203 204 libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 205 timebase.den, timebase.num, 0, 30); 206 207 // Error resilient mode OFF. 208 cfg_.g_error_resilient = 0; 209 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 210 const double psnr_resilience_off = GetAveragePsnr(); 211 EXPECT_GT(psnr_resilience_off, 25.0); 212 213 // Error resilient mode ON. 214 cfg_.g_error_resilient = 1; 215 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 216 const double psnr_resilience_on = GetAveragePsnr(); 217 EXPECT_GT(psnr_resilience_on, 25.0); 218 219 // Test that turning on error resilient mode hurts by 10% at most. 220 if (psnr_resilience_off > 0.0) { 221 const double psnr_ratio = psnr_resilience_on / psnr_resilience_off; 222 EXPECT_GE(psnr_ratio, 0.9); 223 EXPECT_LE(psnr_ratio, 1.1); 224 } 225 } 226 227 // Check for successful decoding and no encoder/decoder mismatch 228 // if we lose (i.e., drop before decoding) a set of droppable 229 // frames (i.e., frames that don't update any reference buffers). 230 // Check both isolated and consecutive loss. 231 TEST_P(ErrorResilienceTestLarge, DropFramesWithoutRecovery) { 232 const vpx_rational timebase = { 33333333, 1000000000 }; 233 cfg_.g_timebase = timebase; 234 cfg_.rc_target_bitrate = 500; 235 // FIXME(debargha): Fix this to work for any lag. 236 // Currently this test only works for lag = 0 237 cfg_.g_lag_in_frames = 0; 238 239 init_flags_ = VPX_CODEC_USE_PSNR; 240 241 libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 242 timebase.den, timebase.num, 0, 40); 243 244 // Error resilient mode ON. 245 cfg_.g_error_resilient = 1; 246 cfg_.kf_mode = VPX_KF_DISABLED; 247 248 // Set an arbitrary set of error frames same as droppable frames. 249 // In addition to isolated loss/drop, add a long consecutive series 250 // (of size 9) of dropped frames. 251 unsigned int num_droppable_frames = 11; 252 unsigned int droppable_frame_list[] = { 5, 16, 22, 23, 24, 25, 253 26, 27, 28, 29, 30 }; 254 SetDroppableFrames(num_droppable_frames, droppable_frame_list); 255 SetErrorFrames(num_droppable_frames, droppable_frame_list); 256 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 257 // Test that no mismatches have been found 258 std::cout << " Mismatch frames: " << GetMismatchFrames() << "\n"; 259 EXPECT_EQ(GetMismatchFrames(), (unsigned int)0); 260 261 // Reset previously set of error/droppable frames. 262 Reset(); 263 264 #if 0 265 // TODO(jkoleszar): This test is disabled for the time being as too 266 // sensitive. It's not clear how to set a reasonable threshold for 267 // this behavior. 268 269 // Now set an arbitrary set of error frames that are non-droppable 270 unsigned int num_error_frames = 3; 271 unsigned int error_frame_list[] = {3, 10, 20}; 272 SetErrorFrames(num_error_frames, error_frame_list); 273 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 274 275 // Test that dropping an arbitrary set of inter frames does not hurt too much 276 // Note the Average Mismatch PSNR is the average of the PSNR between 277 // decoded frame and encoder's version of the same frame for all frames 278 // with mismatch. 279 const double psnr_resilience_mismatch = GetAverageMismatchPsnr(); 280 std::cout << " Mismatch PSNR: " 281 << psnr_resilience_mismatch << "\n"; 282 EXPECT_GT(psnr_resilience_mismatch, 20.0); 283 #endif 284 } 285 286 // Check for successful decoding and no encoder/decoder mismatch 287 // if we lose (i.e., drop before decoding) the enhancement layer frames for a 288 // two layer temporal pattern. The base layer does not predict from the top 289 // layer, so successful decoding is expected. 290 TEST_P(ErrorResilienceTestLarge, 2LayersDropEnhancement) { 291 // This test doesn't run if SVC is not supported. 292 if (!svc_support_) return; 293 294 const vpx_rational timebase = { 33333333, 1000000000 }; 295 cfg_.g_timebase = timebase; 296 cfg_.rc_target_bitrate = 500; 297 cfg_.g_lag_in_frames = 0; 298 299 cfg_.rc_end_usage = VPX_CBR; 300 // 2 Temporal layers, no spatial layers, CBR mode. 301 cfg_.ss_number_layers = 1; 302 cfg_.ts_number_layers = 2; 303 cfg_.ts_rate_decimator[0] = 2; 304 cfg_.ts_rate_decimator[1] = 1; 305 cfg_.ts_periodicity = 2; 306 cfg_.ts_target_bitrate[0] = 60 * cfg_.rc_target_bitrate / 100; 307 cfg_.ts_target_bitrate[1] = cfg_.rc_target_bitrate; 308 309 init_flags_ = VPX_CODEC_USE_PSNR; 310 311 libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 312 timebase.den, timebase.num, 0, 40); 313 314 // Error resilient mode ON. 315 cfg_.g_error_resilient = 1; 316 cfg_.kf_mode = VPX_KF_DISABLED; 317 SetPatternSwitch(0); 318 319 // The odd frames are the enhancement layer for 2 layer pattern, so set 320 // those frames as droppable. Drop the last 7 frames. 321 unsigned int num_droppable_frames = 7; 322 unsigned int droppable_frame_list[] = { 27, 29, 31, 33, 35, 37, 39 }; 323 SetDroppableFrames(num_droppable_frames, droppable_frame_list); 324 SetErrorFrames(num_droppable_frames, droppable_frame_list); 325 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 326 // Test that no mismatches have been found 327 std::cout << " Mismatch frames: " << GetMismatchFrames() << "\n"; 328 EXPECT_EQ(GetMismatchFrames(), (unsigned int)0); 329 330 // Reset previously set of error/droppable frames. 331 Reset(); 332 } 333 334 // Check for successful decoding and no encoder/decoder mismatch 335 // for a two layer temporal pattern, where at some point in the 336 // sequence, the LAST ref is not used anymore. 337 TEST_P(ErrorResilienceTestLarge, 2LayersNoRefLast) { 338 // This test doesn't run if SVC is not supported. 339 if (!svc_support_) return; 340 341 const vpx_rational timebase = { 33333333, 1000000000 }; 342 cfg_.g_timebase = timebase; 343 cfg_.rc_target_bitrate = 500; 344 cfg_.g_lag_in_frames = 0; 345 346 cfg_.rc_end_usage = VPX_CBR; 347 // 2 Temporal layers, no spatial layers, CBR mode. 348 cfg_.ss_number_layers = 1; 349 cfg_.ts_number_layers = 2; 350 cfg_.ts_rate_decimator[0] = 2; 351 cfg_.ts_rate_decimator[1] = 1; 352 cfg_.ts_periodicity = 2; 353 cfg_.ts_target_bitrate[0] = 60 * cfg_.rc_target_bitrate / 100; 354 cfg_.ts_target_bitrate[1] = cfg_.rc_target_bitrate; 355 356 init_flags_ = VPX_CODEC_USE_PSNR; 357 358 libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 359 timebase.den, timebase.num, 0, 100); 360 361 // Error resilient mode ON. 362 cfg_.g_error_resilient = 1; 363 cfg_.kf_mode = VPX_KF_DISABLED; 364 SetPatternSwitch(60); 365 366 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 367 // Test that no mismatches have been found 368 std::cout << " Mismatch frames: " << GetMismatchFrames() << "\n"; 369 EXPECT_EQ(GetMismatchFrames(), (unsigned int)0); 370 371 // Reset previously set of error/droppable frames. 372 Reset(); 373 } 374 375 class ErrorResilienceTestLargeCodecControls 376 : public ::libvpx_test::EncoderTest, 377 public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> { 378 protected: 379 ErrorResilienceTestLargeCodecControls() 380 : EncoderTest(GET_PARAM(0)), encoding_mode_(GET_PARAM(1)) { 381 Reset(); 382 } 383 384 virtual ~ErrorResilienceTestLargeCodecControls() {} 385 386 void Reset() { 387 last_pts_ = 0; 388 tot_frame_number_ = 0; 389 // For testing up to 3 layers. 390 for (int i = 0; i < 3; ++i) { 391 bits_total_[i] = 0; 392 } 393 duration_ = 0.0; 394 } 395 396 virtual void SetUp() { 397 InitializeConfig(); 398 SetMode(encoding_mode_); 399 } 400 401 // 402 // Frame flags and layer id for temporal layers. 403 // 404 405 // For two layers, test pattern is: 406 // 1 3 407 // 0 2 ..... 408 // For three layers, test pattern is: 409 // 1 3 5 7 410 // 2 6 411 // 0 4 .... 412 // LAST is always update on base/layer 0, GOLDEN is updated on layer 1, 413 // and ALTREF is updated on top layer for 3 layer pattern. 414 int SetFrameFlags(int frame_num, int num_temp_layers) { 415 int frame_flags = 0; 416 if (num_temp_layers == 2) { 417 if (frame_num % 2 == 0) { 418 // Layer 0: predict from L and ARF, update L. 419 frame_flags = 420 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; 421 } else { 422 // Layer 1: predict from L, G and ARF, and update G. 423 frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST | 424 VP8_EFLAG_NO_UPD_ENTROPY; 425 } 426 } else if (num_temp_layers == 3) { 427 if (frame_num % 4 == 0) { 428 // Layer 0: predict from L, update L. 429 frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | 430 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF; 431 } else if ((frame_num - 2) % 4 == 0) { 432 // Layer 1: predict from L, G, update G. 433 frame_flags = 434 VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_REF_ARF; 435 } else if ((frame_num - 1) % 2 == 0) { 436 // Layer 2: predict from L, G, ARF; update ARG. 437 frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST; 438 } 439 } 440 return frame_flags; 441 } 442 443 int SetLayerId(int frame_num, int num_temp_layers) { 444 int layer_id = 0; 445 if (num_temp_layers == 2) { 446 if (frame_num % 2 == 0) { 447 layer_id = 0; 448 } else { 449 layer_id = 1; 450 } 451 } else if (num_temp_layers == 3) { 452 if (frame_num % 4 == 0) { 453 layer_id = 0; 454 } else if ((frame_num - 2) % 4 == 0) { 455 layer_id = 1; 456 } else if ((frame_num - 1) % 2 == 0) { 457 layer_id = 2; 458 } 459 } 460 return layer_id; 461 } 462 463 virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video, 464 libvpx_test::Encoder *encoder) { 465 if (cfg_.ts_number_layers > 1) { 466 int layer_id = SetLayerId(video->frame(), cfg_.ts_number_layers); 467 int frame_flags = SetFrameFlags(video->frame(), cfg_.ts_number_layers); 468 if (video->frame() > 0) { 469 encoder->Control(VP8E_SET_TEMPORAL_LAYER_ID, layer_id); 470 encoder->Control(VP8E_SET_FRAME_FLAGS, frame_flags); 471 } 472 const vpx_rational_t tb = video->timebase(); 473 timebase_ = static_cast<double>(tb.num) / tb.den; 474 duration_ = 0; 475 return; 476 } 477 } 478 479 virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) { 480 // Time since last timestamp = duration. 481 vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_; 482 if (duration > 1) { 483 // Update counter for total number of frames (#frames input to encoder). 484 // Needed for setting the proper layer_id below. 485 tot_frame_number_ += static_cast<int>(duration - 1); 486 } 487 int layer = SetLayerId(tot_frame_number_, cfg_.ts_number_layers); 488 const size_t frame_size_in_bits = pkt->data.frame.sz * 8; 489 // Update the total encoded bits. For temporal layers, update the cumulative 490 // encoded bits per layer. 491 for (int i = layer; i < static_cast<int>(cfg_.ts_number_layers); ++i) { 492 bits_total_[i] += frame_size_in_bits; 493 } 494 // Update the most recent pts. 495 last_pts_ = pkt->data.frame.pts; 496 ++tot_frame_number_; 497 } 498 499 virtual void EndPassHook(void) { 500 duration_ = (last_pts_ + 1) * timebase_; 501 if (cfg_.ts_number_layers > 1) { 502 for (int layer = 0; layer < static_cast<int>(cfg_.ts_number_layers); 503 ++layer) { 504 if (bits_total_[layer]) { 505 // Effective file datarate: 506 effective_datarate_[layer] = 507 (bits_total_[layer] / 1000.0) / duration_; 508 } 509 } 510 } 511 } 512 513 double effective_datarate_[3]; 514 515 private: 516 libvpx_test::TestMode encoding_mode_; 517 vpx_codec_pts_t last_pts_; 518 double timebase_; 519 int64_t bits_total_[3]; 520 double duration_; 521 int tot_frame_number_; 522 }; 523 524 // Check two codec controls used for: 525 // (1) for setting temporal layer id, and (2) for settings encoder flags. 526 // This test invokes those controls for each frame, and verifies encoder/decoder 527 // mismatch and basic rate control response. 528 // TODO(marpan): Maybe move this test to datarate_test.cc. 529 TEST_P(ErrorResilienceTestLargeCodecControls, CodecControl3TemporalLayers) { 530 cfg_.rc_buf_initial_sz = 500; 531 cfg_.rc_buf_optimal_sz = 500; 532 cfg_.rc_buf_sz = 1000; 533 cfg_.rc_dropframe_thresh = 1; 534 cfg_.rc_min_quantizer = 2; 535 cfg_.rc_max_quantizer = 56; 536 cfg_.rc_end_usage = VPX_CBR; 537 cfg_.rc_dropframe_thresh = 1; 538 cfg_.g_lag_in_frames = 0; 539 cfg_.kf_mode = VPX_KF_DISABLED; 540 cfg_.g_error_resilient = 1; 541 542 // 3 Temporal layers. Framerate decimation (4, 2, 1). 543 cfg_.ts_number_layers = 3; 544 cfg_.ts_rate_decimator[0] = 4; 545 cfg_.ts_rate_decimator[1] = 2; 546 cfg_.ts_rate_decimator[2] = 1; 547 cfg_.ts_periodicity = 4; 548 cfg_.ts_layer_id[0] = 0; 549 cfg_.ts_layer_id[1] = 2; 550 cfg_.ts_layer_id[2] = 1; 551 cfg_.ts_layer_id[3] = 2; 552 553 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 554 30, 1, 0, 200); 555 for (int i = 200; i <= 800; i += 200) { 556 cfg_.rc_target_bitrate = i; 557 Reset(); 558 // 40-20-40 bitrate allocation for 3 temporal layers. 559 cfg_.ts_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100; 560 cfg_.ts_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100; 561 cfg_.ts_target_bitrate[2] = cfg_.rc_target_bitrate; 562 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 563 for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) { 564 ASSERT_GE(effective_datarate_[j], cfg_.ts_target_bitrate[j] * 0.75) 565 << " The datarate for the file is lower than target by too much, " 566 "for layer: " 567 << j; 568 ASSERT_LE(effective_datarate_[j], cfg_.ts_target_bitrate[j] * 1.25) 569 << " The datarate for the file is greater than target by too much, " 570 "for layer: " 571 << j; 572 } 573 } 574 } 575 576 VP8_INSTANTIATE_TEST_CASE(ErrorResilienceTestLarge, ONE_PASS_TEST_MODES, 577 ::testing::Values(true)); 578 VP8_INSTANTIATE_TEST_CASE(ErrorResilienceTestLargeCodecControls, 579 ONE_PASS_TEST_MODES); 580 VP9_INSTANTIATE_TEST_CASE(ErrorResilienceTestLarge, ONE_PASS_TEST_MODES, 581 ::testing::Values(true)); 582 } // namespace 583