vp8: Fix to crash in pick_inter.
Added unittest that triggers the crash without this fix. Issue: https://code.google.com/p/webm/issues/detail?id=911 Change-Id: If5208ceb210c821891675fdf3d9951ab83d52ae6
This commit is contained in:
parent
fe3f21099f
commit
2c6d9c574f
@ -37,6 +37,7 @@ class ErrorResilienceTestLarge : public ::libvpx_test::EncoderTest,
|
|||||||
void Reset() {
|
void Reset() {
|
||||||
error_nframes_ = 0;
|
error_nframes_ = 0;
|
||||||
droppable_nframes_ = 0;
|
droppable_nframes_ = 0;
|
||||||
|
pattern_switch_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void SetUp() {
|
virtual void SetUp() {
|
||||||
@ -62,19 +63,37 @@ class ErrorResilienceTestLarge : public ::libvpx_test::EncoderTest,
|
|||||||
// 1 3
|
// 1 3
|
||||||
// 0 2 .....
|
// 0 2 .....
|
||||||
// LAST is updated on base/layer 0, GOLDEN updated on layer 1.
|
// LAST is updated on base/layer 0, GOLDEN updated on layer 1.
|
||||||
int SetFrameFlags(int frame_num, int num_temp_layers) {
|
// 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;
|
int frame_flags = 0;
|
||||||
if (num_temp_layers == 2) {
|
if (num_temp_layers == 2) {
|
||||||
if (frame_num % 2 == 0) {
|
if (frame_num % 2 == 0) {
|
||||||
// Layer 0: predict from L and ARF, update L.
|
if (frame_num < pattern_switch || pattern_switch == 0) {
|
||||||
frame_flags = VP8_EFLAG_NO_REF_GF |
|
// Layer 0: predict from LAST and ARF, update LAST.
|
||||||
VP8_EFLAG_NO_UPD_GF |
|
frame_flags = VP8_EFLAG_NO_REF_GF |
|
||||||
VP8_EFLAG_NO_UPD_ARF;
|
VP8_EFLAG_NO_UPD_GF |
|
||||||
} else {
|
VP8_EFLAG_NO_UPD_ARF;
|
||||||
// Layer 1: predict from L, GF, and ARF, and update GF.
|
} else {
|
||||||
frame_flags = VP8_EFLAG_NO_UPD_ARF |
|
// Layer 0: predict from GF and ARF, update GF.
|
||||||
VP8_EFLAG_NO_UPD_LAST;
|
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;
|
return frame_flags;
|
||||||
}
|
}
|
||||||
@ -86,7 +105,9 @@ class ErrorResilienceTestLarge : public ::libvpx_test::EncoderTest,
|
|||||||
VP8_EFLAG_NO_UPD_ARF);
|
VP8_EFLAG_NO_UPD_ARF);
|
||||||
// For temporal layer case.
|
// For temporal layer case.
|
||||||
if (cfg_.ts_number_layers > 1) {
|
if (cfg_.ts_number_layers > 1) {
|
||||||
frame_flags_ = SetFrameFlags(video->frame(), cfg_.ts_number_layers);
|
frame_flags_ = SetFrameFlags(video->frame(),
|
||||||
|
cfg_.ts_number_layers,
|
||||||
|
pattern_switch_);
|
||||||
for (unsigned int i = 0; i < droppable_nframes_; ++i) {
|
for (unsigned int i = 0; i < droppable_nframes_; ++i) {
|
||||||
if (droppable_frames_[i] == video->frame()) {
|
if (droppable_frames_[i] == video->frame()) {
|
||||||
std::cout << "Encoding droppable frame: "
|
std::cout << "Encoding droppable frame: "
|
||||||
@ -168,11 +189,16 @@ class ErrorResilienceTestLarge : public ::libvpx_test::EncoderTest,
|
|||||||
return mismatch_nframes_;
|
return mismatch_nframes_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetPatternSwitch(int frame_switch) {
|
||||||
|
pattern_switch_ = frame_switch;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double psnr_;
|
double psnr_;
|
||||||
unsigned int nframes_;
|
unsigned int nframes_;
|
||||||
unsigned int error_nframes_;
|
unsigned int error_nframes_;
|
||||||
unsigned int droppable_nframes_;
|
unsigned int droppable_nframes_;
|
||||||
|
unsigned int pattern_switch_;
|
||||||
double mismatch_psnr_;
|
double mismatch_psnr_;
|
||||||
unsigned int mismatch_nframes_;
|
unsigned int mismatch_nframes_;
|
||||||
unsigned int error_frames_[kMaxErrorFrames];
|
unsigned int error_frames_[kMaxErrorFrames];
|
||||||
@ -299,6 +325,7 @@ TEST_P(ErrorResilienceTestLarge, 2LayersDropEnhancement) {
|
|||||||
// Error resilient mode ON.
|
// Error resilient mode ON.
|
||||||
cfg_.g_error_resilient = 1;
|
cfg_.g_error_resilient = 1;
|
||||||
cfg_.kf_mode = VPX_KF_DISABLED;
|
cfg_.kf_mode = VPX_KF_DISABLED;
|
||||||
|
SetPatternSwitch(0);
|
||||||
|
|
||||||
// The odd frames are the enhancement layer for 2 layer pattern, so set
|
// The odd frames are the enhancement layer for 2 layer pattern, so set
|
||||||
// those frames as droppable. Drop the last 7 frames.
|
// those frames as droppable. Drop the last 7 frames.
|
||||||
@ -316,6 +343,45 @@ TEST_P(ErrorResilienceTestLarge, 2LayersDropEnhancement) {
|
|||||||
Reset();
|
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) {
|
||||||
|
const vpx_rational timebase = { 33333333, 1000000000 };
|
||||||
|
cfg_.g_timebase = timebase;
|
||||||
|
cfg_.rc_target_bitrate = 500;
|
||||||
|
cfg_.g_lag_in_frames = 0;
|
||||||
|
|
||||||
|
cfg_.rc_end_usage = VPX_CBR;
|
||||||
|
// 2 Temporal layers, no spatial layers, CBR mode.
|
||||||
|
cfg_.ss_number_layers = 1;
|
||||||
|
cfg_.ts_number_layers = 2;
|
||||||
|
cfg_.ts_rate_decimator[0] = 2;
|
||||||
|
cfg_.ts_rate_decimator[1] = 1;
|
||||||
|
cfg_.ts_periodicity = 2;
|
||||||
|
cfg_.ts_target_bitrate[0] = 60 * cfg_.rc_target_bitrate / 100;
|
||||||
|
cfg_.ts_target_bitrate[1] = cfg_.rc_target_bitrate;
|
||||||
|
|
||||||
|
init_flags_ = VPX_CODEC_USE_PSNR;
|
||||||
|
|
||||||
|
libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
|
||||||
|
timebase.den, timebase.num, 0, 100);
|
||||||
|
|
||||||
|
// Error resilient mode ON.
|
||||||
|
cfg_.g_error_resilient = 1;
|
||||||
|
cfg_.kf_mode = VPX_KF_DISABLED;
|
||||||
|
SetPatternSwitch(60);
|
||||||
|
|
||||||
|
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||||
|
// Test that no mismatches have been found
|
||||||
|
std::cout << " Mismatch frames: "
|
||||||
|
<< GetMismatchFrames() << "\n";
|
||||||
|
EXPECT_EQ(GetMismatchFrames(), (unsigned int) 0);
|
||||||
|
|
||||||
|
// Reset previously set of error/droppable frames.
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
class ErrorResilienceTestLargeCodecControls : public ::libvpx_test::EncoderTest,
|
class ErrorResilienceTestLargeCodecControls : public ::libvpx_test::EncoderTest,
|
||||||
public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
|
public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
|
||||||
protected:
|
protected:
|
||||||
|
@ -753,45 +753,46 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
|
|||||||
int ref_frame_map[4];
|
int ref_frame_map[4];
|
||||||
int sign_bias = 0;
|
int sign_bias = 0;
|
||||||
int dot_artifact_candidate = 0;
|
int dot_artifact_candidate = 0;
|
||||||
// For detecting dot artifact.
|
|
||||||
unsigned char* target = x->src.y_buffer;
|
|
||||||
unsigned char* target_u = x->block[16].src + *x->block[16].base_src;
|
|
||||||
unsigned char* target_v = x->block[20].src + *x->block[20].base_src;
|
|
||||||
int stride = x->src.y_stride;
|
|
||||||
int stride_uv = x->block[16].src_stride;
|
|
||||||
#if CONFIG_TEMPORAL_DENOISING
|
|
||||||
if (cpi->oxcf.noise_sensitivity) {
|
|
||||||
int uv_denoise = (cpi->oxcf.noise_sensitivity >= 2) ? 1 : 0;
|
|
||||||
target =
|
|
||||||
cpi->denoiser.yv12_running_avg[LAST_FRAME].y_buffer + recon_yoffset;
|
|
||||||
stride = cpi->denoiser.yv12_running_avg[LAST_FRAME].y_stride;
|
|
||||||
if (uv_denoise) {
|
|
||||||
target_u =
|
|
||||||
cpi->denoiser.yv12_running_avg[LAST_FRAME].u_buffer + recon_uvoffset;
|
|
||||||
target_v =
|
|
||||||
cpi->denoiser.yv12_running_avg[LAST_FRAME].v_buffer + recon_uvoffset;
|
|
||||||
stride_uv = cpi->denoiser.yv12_running_avg[LAST_FRAME].uv_stride;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
get_predictor_pointers(cpi, plane, recon_yoffset, recon_uvoffset);
|
get_predictor_pointers(cpi, plane, recon_yoffset, recon_uvoffset);
|
||||||
|
|
||||||
dot_artifact_candidate =
|
// If the current frame is using LAST as a reference, check for
|
||||||
check_dot_artifact_candidate(cpi, x,
|
// biasing the mode selection for dot artifacts.
|
||||||
target, stride,
|
if (cpi->ref_frame_flags & VP8_LAST_FRAME) {
|
||||||
plane[LAST_FRAME][0], mb_row, mb_col, 0);
|
unsigned char* target_y = x->src.y_buffer;
|
||||||
// If not found in Y channel, check UV channel.
|
unsigned char* target_u = x->block[16].src + *x->block[16].base_src;
|
||||||
if (!dot_artifact_candidate) {
|
unsigned char* target_v = x->block[20].src + *x->block[20].base_src;
|
||||||
|
int stride = x->src.y_stride;
|
||||||
|
int stride_uv = x->block[16].src_stride;
|
||||||
|
#if CONFIG_TEMPORAL_DENOISING
|
||||||
|
if (cpi->oxcf.noise_sensitivity) {
|
||||||
|
const int uv_denoise = (cpi->oxcf.noise_sensitivity >= 2) ? 1 : 0;
|
||||||
|
target_y =
|
||||||
|
cpi->denoiser.yv12_running_avg[LAST_FRAME].y_buffer + recon_yoffset;
|
||||||
|
stride = cpi->denoiser.yv12_running_avg[LAST_FRAME].y_stride;
|
||||||
|
if (uv_denoise) {
|
||||||
|
target_u =
|
||||||
|
cpi->denoiser.yv12_running_avg[LAST_FRAME].u_buffer +
|
||||||
|
recon_uvoffset;
|
||||||
|
target_v =
|
||||||
|
cpi->denoiser.yv12_running_avg[LAST_FRAME].v_buffer +
|
||||||
|
recon_uvoffset;
|
||||||
|
stride_uv = cpi->denoiser.yv12_running_avg[LAST_FRAME].uv_stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
dot_artifact_candidate =
|
dot_artifact_candidate =
|
||||||
check_dot_artifact_candidate(cpi, x,
|
check_dot_artifact_candidate(cpi, x, target_y, stride,
|
||||||
target_u, stride_uv,
|
plane[LAST_FRAME][0], mb_row, mb_col, 0);
|
||||||
plane[LAST_FRAME][1], mb_row, mb_col, 1);
|
// If not found in Y channel, check UV channel.
|
||||||
if (!dot_artifact_candidate) {
|
if (!dot_artifact_candidate) {
|
||||||
dot_artifact_candidate =
|
dot_artifact_candidate =
|
||||||
check_dot_artifact_candidate(cpi, x,
|
check_dot_artifact_candidate(cpi, x, target_u, stride_uv,
|
||||||
target_v, stride_uv,
|
plane[LAST_FRAME][1], mb_row, mb_col, 1);
|
||||||
plane[LAST_FRAME][2], mb_row, mb_col, 2);
|
if (!dot_artifact_candidate) {
|
||||||
|
dot_artifact_candidate =
|
||||||
|
check_dot_artifact_candidate(cpi, x, target_v, stride_uv,
|
||||||
|
plane[LAST_FRAME][2], mb_row, mb_col, 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user