error_resilience_test.cc 20 KB

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