Wrap around current_video_frame and frame_offset We removed resetting of current_video_frame when a keyframe is inserted at decoder. And current_video_frame continues to accumulate, which will overflow eventually, leading to mismatches because of incorrect frame distance computation. It may not be a big issue for encoder, since we still reset current_video_frame to 0 when a keyframe is inserted. And in a typical coding setting, we insert keyframe every 150 frames. So current_video_frame will not overflow. Hence, we wrap the current_video_frame and frame_offset to a small random value at decoder, when they reach a predefined limit FRAME_NUM_LIMIT = INT_MAX - MAX_FRAME_OFFSET - 1. In reality, it is unlikely to code so many frames and thus unable to test. I therefore set FRAME_NUM_LIMIT = 20 and testes the coding result locally with speed 2. It is the same as baseline. Change-Id: I42928a5154319f0faf87251cd57c0094c605cf41
diff --git a/av1/common/enums.h b/av1/common/enums.h index d48d0fd..6d95a84 100644 --- a/av1/common/enums.h +++ b/av1/common/enums.h
@@ -93,6 +93,8 @@ #define DIST_PRECISION (1 << DIST_PRECISION_BITS) // 16 #endif // CONFIG_JNT_COMP +#define FRAME_NUM_LIMIT (INT_MAX - MAX_FRAME_DISTANCE - 1) + // Bitstream profiles indicated by 2-3 bits in the uncompressed header. // 00: Profile 0. 8-bit 4:2:0 only. // 10: Profile 1. 8-bit 4:4:4, 4:2:2, and 4:4:0.
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c index c0dad11..a3a5a88 100644 --- a/av1/decoder/decodeframe.c +++ b/av1/decoder/decodeframe.c
@@ -2608,6 +2608,30 @@ TOTAL_REFS_PER_FRAME * sizeof(WarpedMotionParams)); } +// Copied from av1/encoder/random.h +static INLINE unsigned int lcg_rand16(unsigned int *state) { + *state = (unsigned int)(*state * 1103515245ULL + 12345); + return *state / 65536 % 32768; +} + +// Wrap around to make sure current_video_frame won't surpass a limit +// Such that distance computation could remain correct +static void wrap_around_current_video_frame(AV1Decoder *pbi) { + AV1_COMMON *const cm = &pbi->common; + + if (cm->current_video_frame >= FRAME_NUM_LIMIT) { + // Wrap to a random number in range (MAX_FRAME_DISTANCE, 32768) + static unsigned int seed = 54321; + int new_frame_offset = lcg_rand16(&seed); + new_frame_offset += (MAX_FRAME_DISTANCE + 1); + + // Wrap around for current frame + cm->current_video_frame = new_frame_offset; + cm->frame_offset = new_frame_offset; + cm->cur_frame->cur_frame_offset = cm->frame_offset; + } +} + #if CONFIG_FWD_KF static void show_existing_frame_reset(AV1Decoder *const pbi) { AV1_COMMON *const cm = &pbi->common; @@ -2616,6 +2640,7 @@ assert(cm->show_existing_frame); + wrap_around_current_video_frame(pbi); cm->frame_type = KEY_FRAME; cm->frame_offset = cm->current_video_frame; @@ -2834,6 +2859,7 @@ #endif // CONFIG_FRAME_REFS_SIGNALING if (cm->frame_type == KEY_FRAME) { + wrap_around_current_video_frame(pbi); pbi->refresh_frame_flags = (1 << REF_FRAMES) - 1; for (int i = 0; i < INTER_REFS_PER_FRAME; ++i) {