aboutsummaryrefslogtreecommitdiffstats
path: root/libavcodec/vvc/refs.c
diff options
context:
space:
mode:
authorNuo Mi <nuomi2021@gmail.com>2024-05-19 21:27:43 +0800
committerNuo Mi <nuomi2021@gmail.com>2024-05-21 20:20:25 +0800
commit77acd0a0dd93698a705fd440686994ac0fb1a6a3 (patch)
tree79942a8ad36169e2dcd26b80339a945eb5dfc720 /libavcodec/vvc/refs.c
parentdeda59a9964ff02a27d490a8d93f30e60c18b312 (diff)
downloadffmpeg-77acd0a0dd93698a705fd440686994ac0fb1a6a3.tar.gz
avcodec/vvcdec: inter, wait reference with a different resolution
For RPR, the current frame may reference a frame with a different resolution. Therefore, we need to consider frame scaling when we wait for reference pixels.
Diffstat (limited to 'libavcodec/vvc/refs.c')
-rw-r--r--libavcodec/vvc/refs.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/libavcodec/vvc/refs.c b/libavcodec/vvc/refs.c
index 954db4a8c8..fb42963034 100644
--- a/libavcodec/vvc/refs.c
+++ b/libavcodec/vvc/refs.c
@@ -114,10 +114,12 @@ static FrameProgress *alloc_progress(void)
static VVCFrame *alloc_frame(VVCContext *s, VVCFrameContext *fc)
{
+ const VVCSPS *sps = fc->ps.sps;
const VVCPPS *pps = fc->ps.pps;
for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
int ret;
VVCFrame *frame = &fc->DPB[i];
+ VVCWindow *win = &frame->scaling_win;
if (frame->frame->buf[0])
continue;
@@ -144,6 +146,13 @@ static VVCFrame *alloc_frame(VVCContext *s, VVCFrameContext *fc)
for (int j = 0; j < frame->ctb_count; j++)
frame->rpl_tab[j] = frame->rpl;
+ win->left_offset = pps->r->pps_scaling_win_left_offset << sps->hshift[CHROMA];
+ win->right_offset = pps->r->pps_scaling_win_right_offset << sps->hshift[CHROMA];
+ win->top_offset = pps->r->pps_scaling_win_top_offset << sps->vshift[CHROMA];
+ win->bottom_offset = pps->r->pps_scaling_win_bottom_offset << sps->vshift[CHROMA];
+ frame->ref_width = pps->r->pps_pic_width_in_luma_samples - win->left_offset - win->right_offset;
+ frame->ref_height = pps->r->pps_pic_height_in_luma_samples - win->bottom_offset - win->top_offset;
+
frame->progress = alloc_progress();
if (!frame->progress)
goto fail;
@@ -353,6 +362,24 @@ static VVCFrame *generate_missing_ref(VVCContext *s, VVCFrameContext *fc, int po
return frame;
}
+#define CHECK_MAX(d) (frame->ref_##d * frame->sps->r->sps_pic_##d##_max_in_luma_samples >= ref->ref_##d * (frame->pps->r->pps_pic_##d##_in_luma_samples - max))
+#define CHECK_SAMPLES(d) (frame->pps->r->pps_pic_##d##_in_luma_samples == ref->pps->r->pps_pic_##d##_in_luma_samples)
+static int check_candidate_ref(const VVCFrame *frame, const VVCRefPic *refp)
+{
+ const VVCFrame *ref = refp->ref;
+
+ if (refp->is_scaled) {
+ const int max = FFMAX(8, frame->sps->min_cb_size_y);
+ return frame->ref_width * 2 >= ref->ref_width &&
+ frame->ref_height * 2 >= ref->ref_height &&
+ frame->ref_width <= ref->ref_width * 8 &&
+ frame->ref_height <= ref->ref_height * 8 &&
+ CHECK_MAX(width) && CHECK_MAX(height);
+ }
+ return CHECK_SAMPLES(width) && CHECK_SAMPLES(height);
+}
+
+#define RPR_SCALE(f) (((ref->f << 14) + (fc->ref->f >> 1)) / fc->ref->f)
/* add a reference with the given poc to the list and mark it as used in DPB */
static int add_candidate_ref(VVCContext *s, VVCFrameContext *fc, RefPicList *list,
int poc, int ref_flag, uint8_t use_msb)
@@ -372,6 +399,18 @@ static int add_candidate_ref(VVCContext *s, VVCFrameContext *fc, RefPicList *lis
refp->poc = poc;
refp->ref = ref;
refp->is_lt = ref_flag & VVC_FRAME_FLAG_LONG_REF;
+ refp->is_scaled = ref->sps->r->sps_num_subpics_minus1 != fc->ref->sps->r->sps_num_subpics_minus1||
+ memcmp(&ref->scaling_win, &fc->ref->scaling_win, sizeof(ref->scaling_win)) ||
+ ref->pps->r->pps_pic_width_in_luma_samples != fc->ref->pps->r->pps_pic_width_in_luma_samples ||
+ ref->pps->r->pps_pic_height_in_luma_samples != fc->ref->pps->r->pps_pic_height_in_luma_samples;
+
+ if (!check_candidate_ref(fc->ref, refp))
+ return AVERROR_INVALIDDATA;
+
+ if (refp->is_scaled) {
+ refp->scale[0] = RPR_SCALE(ref_width);
+ refp->scale[1] = RPR_SCALE(ref_height);
+ }
list->nb_refs++;
mark_ref(ref, ref_flag);