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