OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2013 The WebM project authors. All Rights Reserved. | 2 * Copyright (c) 2013 The WebM project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
49 nframes_ = 0; | 49 nframes_ = 0; |
50 mismatch_psnr_ = 0.0; | 50 mismatch_psnr_ = 0.0; |
51 mismatch_nframes_ = 0; | 51 mismatch_nframes_ = 0; |
52 } | 52 } |
53 | 53 |
54 virtual void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) { | 54 virtual void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) { |
55 psnr_ += pkt->data.psnr.psnr[0]; | 55 psnr_ += pkt->data.psnr.psnr[0]; |
56 nframes_++; | 56 nframes_++; |
57 } | 57 } |
58 | 58 |
59 virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video) { | 59 // |
| 60 // Frame flags and layer id for temporal layers. |
| 61 // For two layers, test pattern is: |
| 62 // 1 3 |
| 63 // 0 2 ..... |
| 64 // LAST is updated on base/layer 0, GOLDEN updated on layer 1. |
| 65 int SetFrameFlags(int frame_num, int num_temp_layers) { |
| 66 int frame_flags = 0; |
| 67 if (num_temp_layers == 2) { |
| 68 if (frame_num % 2 == 0) { |
| 69 // Layer 0: predict from L and ARF, update L. |
| 70 frame_flags = VP8_EFLAG_NO_REF_GF | |
| 71 VP8_EFLAG_NO_UPD_GF | |
| 72 VP8_EFLAG_NO_UPD_ARF; |
| 73 } else { |
| 74 // Layer 1: predict from L, GF, and ARF, and update GF. |
| 75 frame_flags = VP8_EFLAG_NO_UPD_ARF | |
| 76 VP8_EFLAG_NO_UPD_LAST; |
| 77 } |
| 78 } |
| 79 return frame_flags; |
| 80 } |
| 81 |
| 82 virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video, |
| 83 ::libvpx_test::Encoder *encoder) { |
60 frame_flags_ &= ~(VP8_EFLAG_NO_UPD_LAST | | 84 frame_flags_ &= ~(VP8_EFLAG_NO_UPD_LAST | |
61 VP8_EFLAG_NO_UPD_GF | | 85 VP8_EFLAG_NO_UPD_GF | |
62 VP8_EFLAG_NO_UPD_ARF); | 86 VP8_EFLAG_NO_UPD_ARF); |
63 if (droppable_nframes_ > 0 && | 87 // For temporal layer case. |
64 (cfg_.g_pass == VPX_RC_LAST_PASS || cfg_.g_pass == VPX_RC_ONE_PASS)) { | 88 if (cfg_.ts_number_layers > 1) { |
| 89 frame_flags_ = SetFrameFlags(video->frame(), cfg_.ts_number_layers); |
65 for (unsigned int i = 0; i < droppable_nframes_; ++i) { | 90 for (unsigned int i = 0; i < droppable_nframes_; ++i) { |
66 if (droppable_frames_[i] == video->frame()) { | 91 if (droppable_frames_[i] == video->frame()) { |
67 std::cout << " Encoding droppable frame: " | 92 std::cout << "Encoding droppable frame: " |
68 << droppable_frames_[i] << "\n"; | 93 << droppable_frames_[i] << "\n"; |
69 frame_flags_ |= (VP8_EFLAG_NO_UPD_LAST | | |
70 VP8_EFLAG_NO_UPD_GF | | |
71 VP8_EFLAG_NO_UPD_ARF); | |
72 return; | |
73 } | 94 } |
74 } | 95 } |
| 96 } else { |
| 97 if (droppable_nframes_ > 0 && |
| 98 (cfg_.g_pass == VPX_RC_LAST_PASS || cfg_.g_pass == VPX_RC_ONE_PASS)) { |
| 99 for (unsigned int i = 0; i < droppable_nframes_; ++i) { |
| 100 if (droppable_frames_[i] == video->frame()) { |
| 101 std::cout << "Encoding droppable frame: " |
| 102 << droppable_frames_[i] << "\n"; |
| 103 frame_flags_ |= (VP8_EFLAG_NO_UPD_LAST | |
| 104 VP8_EFLAG_NO_UPD_GF | |
| 105 VP8_EFLAG_NO_UPD_ARF); |
| 106 return; |
| 107 } |
| 108 } |
| 109 } |
75 } | 110 } |
76 } | 111 } |
77 | 112 |
78 double GetAveragePsnr() const { | 113 double GetAveragePsnr() const { |
79 if (nframes_) | 114 if (nframes_) |
80 return psnr_ / nframes_; | 115 return psnr_ / nframes_; |
81 return 0.0; | 116 return 0.0; |
82 } | 117 } |
83 | 118 |
84 double GetAverageMismatchPsnr() const { | 119 double GetAverageMismatchPsnr() const { |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
229 // Note the Average Mismatch PSNR is the average of the PSNR between | 264 // Note the Average Mismatch PSNR is the average of the PSNR between |
230 // decoded frame and encoder's version of the same frame for all frames | 265 // decoded frame and encoder's version of the same frame for all frames |
231 // with mismatch. | 266 // with mismatch. |
232 const double psnr_resilience_mismatch = GetAverageMismatchPsnr(); | 267 const double psnr_resilience_mismatch = GetAverageMismatchPsnr(); |
233 std::cout << " Mismatch PSNR: " | 268 std::cout << " Mismatch PSNR: " |
234 << psnr_resilience_mismatch << "\n"; | 269 << psnr_resilience_mismatch << "\n"; |
235 EXPECT_GT(psnr_resilience_mismatch, 20.0); | 270 EXPECT_GT(psnr_resilience_mismatch, 20.0); |
236 #endif | 271 #endif |
237 } | 272 } |
238 | 273 |
| 274 // Check for successful decoding and no encoder/decoder mismatch |
| 275 // if we lose (i.e., drop before decoding) the enhancement layer frames for a |
| 276 // two layer temporal pattern. The base layer does not predict from the top |
| 277 // layer, so successful decoding is expected. |
| 278 TEST_P(ErrorResilienceTestLarge, 2LayersDropEnhancement) { |
| 279 const vpx_rational timebase = { 33333333, 1000000000 }; |
| 280 cfg_.g_timebase = timebase; |
| 281 cfg_.rc_target_bitrate = 500; |
| 282 cfg_.g_lag_in_frames = 0; |
| 283 |
| 284 cfg_.rc_end_usage = VPX_CBR; |
| 285 // 2 Temporal layers, no spatial layers, CBR mode. |
| 286 cfg_.ss_number_layers = 1; |
| 287 cfg_.ts_number_layers = 2; |
| 288 cfg_.ts_rate_decimator[0] = 2; |
| 289 cfg_.ts_rate_decimator[1] = 1; |
| 290 cfg_.ts_periodicity = 2; |
| 291 cfg_.ts_target_bitrate[0] = 60 * cfg_.rc_target_bitrate / 100; |
| 292 cfg_.ts_target_bitrate[1] = cfg_.rc_target_bitrate; |
| 293 |
| 294 init_flags_ = VPX_CODEC_USE_PSNR; |
| 295 |
| 296 libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, |
| 297 timebase.den, timebase.num, 0, 40); |
| 298 |
| 299 // Error resilient mode ON. |
| 300 cfg_.g_error_resilient = 1; |
| 301 cfg_.kf_mode = VPX_KF_DISABLED; |
| 302 |
| 303 // The odd frames are the enhancement layer for 2 layer pattern, so set |
| 304 // those frames as droppable. Drop the last 7 frames. |
| 305 unsigned int num_droppable_frames = 7; |
| 306 unsigned int droppable_frame_list[] = {27, 29, 31, 33, 35, 37, 39}; |
| 307 SetDroppableFrames(num_droppable_frames, droppable_frame_list); |
| 308 SetErrorFrames(num_droppable_frames, droppable_frame_list); |
| 309 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); |
| 310 // Test that no mismatches have been found |
| 311 std::cout << " Mismatch frames: " |
| 312 << GetMismatchFrames() << "\n"; |
| 313 EXPECT_EQ(GetMismatchFrames(), (unsigned int) 0); |
| 314 |
| 315 // Reset previously set of error/droppable frames. |
| 316 Reset(); |
| 317 } |
| 318 |
239 VP8_INSTANTIATE_TEST_CASE(ErrorResilienceTestLarge, ONE_PASS_TEST_MODES); | 319 VP8_INSTANTIATE_TEST_CASE(ErrorResilienceTestLarge, ONE_PASS_TEST_MODES); |
240 VP9_INSTANTIATE_TEST_CASE(ErrorResilienceTestLarge, ONE_PASS_TEST_MODES); | 320 VP9_INSTANTIATE_TEST_CASE(ErrorResilienceTestLarge, ONE_PASS_TEST_MODES); |
241 | 321 |
242 } // namespace | 322 } // namespace |
OLD | NEW |