/* * Copyright (c) 2013 The WebM project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree.
*/
// // Frame flags and layer id for temporal layers. // For two layers, test pattern is: // 1 3 // 0 2 ..... // LAST is updated on base/layer 0, GOLDEN updated on layer 1. // Non-zero pattern_switch parameter means pattern will switch to // not using LAST for frame_num >= pattern_switch. int SetFrameFlags(int frame_num, int num_temp_layers, int pattern_switch) { int frame_flags = 0; if (num_temp_layers == 2) { if (frame_num % 2 == 0) { if (frame_num < pattern_switch || pattern_switch == 0) { // Layer 0: predict from LAST and ARF, update LAST.
frame_flags =
VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
} else { // Layer 0: predict from GF and ARF, update GF.
frame_flags = VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_UPD_LAST |
VP8_EFLAG_NO_UPD_ARF;
}
} else { if (frame_num < pattern_switch || pattern_switch == 0) { // Layer 1: predict from L, GF, and ARF, update GF.
frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
} else { // Layer 1: predict from GF and ARF, update GF.
frame_flags = VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_UPD_LAST |
VP8_EFLAG_NO_UPD_ARF;
}
}
} return frame_flags;
}
void PreEncodeFrameHook(libvpx_test::VideoSource *video) override {
frame_flags_ &=
~(VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF); // For temporal layer case. if (cfg_.ts_number_layers > 1) {
frame_flags_ =
SetFrameFlags(video->frame(), cfg_.ts_number_layers, pattern_switch_); for (unsignedint i = 0; i < droppable_nframes_; ++i) { if (droppable_frames_[i] == video->frame()) {
std::cout << "Encoding droppable frame: " << droppable_frames_[i]
<< "\n";
}
}
} else { if (droppable_nframes_ > 0 &&
(cfg_.g_pass == VPX_RC_LAST_PASS || cfg_.g_pass == VPX_RC_ONE_PASS)) { for (unsignedint i = 0; i < droppable_nframes_; ++i) { if (droppable_frames_[i] == video->frame()) {
std::cout << "Encoding droppable frame: " << droppable_frames_[i]
<< "\n";
frame_flags_ |= (VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF |
VP8_EFLAG_NO_UPD_ARF); return;
}
}
}
}
}
// Test that turning on error resilient mode hurts by 10% at most. if (psnr_resilience_off > 0.0) { constdouble psnr_ratio = psnr_resilience_on / psnr_resilience_off;
EXPECT_GE(psnr_ratio, 0.9);
EXPECT_LE(psnr_ratio, 1.1);
} #endif// CONFIG_REALTIME_ONLY
}
// Check for successful decoding and no encoder/decoder mismatch // if we lose (i.e., drop before decoding) a set of droppable // frames (i.e., frames that don't update any reference buffers). // Check both isolated and consecutive loss.
TEST_P(ErrorResilienceTestLarge, DropFramesWithoutRecovery) { const vpx_rational timebase = { 33333333, 1000000000 };
cfg_.g_timebase = timebase;
cfg_.rc_target_bitrate = 500; // FIXME(debargha): Fix this to work for any lag. // Currently this test only works for lag = 0
cfg_.g_lag_in_frames = 0;
// Set an arbitrary set of error frames same as droppable frames. // In addition to isolated loss/drop, add a long consecutive series // (of size 9) of dropped frames. unsignedint num_droppable_frames = 11; unsignedint droppable_frame_list[] = { 5, 16, 22, 23, 24, 25,
26, 27, 28, 29, 30 };
SetDroppableFrames(num_droppable_frames, droppable_frame_list);
SetErrorFrames(num_droppable_frames, droppable_frame_list);
ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); // Test that no mismatches have been found
std::cout << " Mismatch frames: " << GetMismatchFrames() << "\n";
EXPECT_EQ(GetMismatchFrames(), (unsignedint)0);
// Reset previously set of error/droppable frames.
Reset();
#if 0 // TODO(jkoleszar): This test is disabled for the time being as too // sensitive. It's not clear how to set a reasonable threshold for // this behavior.
// Now set an arbitrary set of error frames that are non-droppable unsignedint num_error_frames = 3; unsignedint error_frame_list[] = {3, 10, 20};
SetErrorFrames(num_error_frames, error_frame_list);
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
// Test that dropping an arbitrary set of inter frames does not hurt too much // Note the Average Mismatch PSNR is the average of the PSNR between // decoded frame and encoder's version of the same frame for all frames // with mismatch. constdouble psnr_resilience_mismatch = GetAverageMismatchPsnr();
std::cout << " Mismatch PSNR: "
<< psnr_resilience_mismatch << "\n";
EXPECT_GT(psnr_resilience_mismatch, 20.0); #endif
}
// Check for successful decoding and no encoder/decoder mismatch // if we lose (i.e., drop before decoding) the enhancement layer frames for a // two layer temporal pattern. The base layer does not predict from the top // layer, so successful decoding is expected.
TEST_P(ErrorResilienceTestLarge, 2LayersDropEnhancement) { // This test doesn't run if SVC is not supported. if (!svc_support_) return;
// The odd frames are the enhancement layer for 2 layer pattern, so set // those frames as droppable. Drop the last 7 frames. unsignedint num_droppable_frames = 7; unsignedint droppable_frame_list[] = { 27, 29, 31, 33, 35, 37, 39 };
SetDroppableFrames(num_droppable_frames, droppable_frame_list);
SetErrorFrames(num_droppable_frames, droppable_frame_list);
ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); // Test that no mismatches have been found
std::cout << " Mismatch frames: " << GetMismatchFrames() << "\n";
EXPECT_EQ(GetMismatchFrames(), (unsignedint)0);
// Reset previously set of error/droppable frames.
Reset();
}
// Check for successful decoding and no encoder/decoder mismatch // for a two layer temporal pattern, where at some point in the // sequence, the LAST ref is not used anymore.
TEST_P(ErrorResilienceTestLarge, 2LayersNoRefLast) { // This test doesn't run if SVC is not supported. if (!svc_support_) return;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); // Test that no mismatches have been found
std::cout << " Mismatch frames: " << GetMismatchFrames() << "\n";
EXPECT_EQ(GetMismatchFrames(), (unsignedint)0);
// Reset previously set of error/droppable frames.
Reset();
}
class ErrorResilienceTestLargeCodecControls
: public ::libvpx_test::EncoderTest, public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> { protected:
ErrorResilienceTestLargeCodecControls()
: EncoderTest(GET_PARAM(0)), encoding_mode_(GET_PARAM(1)) {
Reset();
}
void FramePktHook(const vpx_codec_cx_pkt_t *pkt) override { // Time since last timestamp = duration.
vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_; if (duration > 1) { // Update counter for total number of frames (#frames input to encoder). // Needed for setting the proper layer_id below.
tot_frame_number_ += static_cast<int>(duration - 1);
} int layer = SetLayerId(tot_frame_number_, cfg_.ts_number_layers); const size_t frame_size_in_bits = pkt->data.frame.sz * 8; // Update the total encoded bits. For temporal layers, update the cumulative // encoded bits per layer. for (int i = layer; i < static_cast<int>(cfg_.ts_number_layers); ++i) {
bits_total_[i] += frame_size_in_bits;
} // Update the most recent pts.
last_pts_ = pkt->data.frame.pts;
++tot_frame_number_;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.