When the current subpicture has sps_subpic_treated_as_pic_flag equal to 1, motion vectors are cropped such that they cannot point to other subpictures. This was accounted for in the prediction logic, but not in pred_get_y, which is used by the scheduling logic to determine which parts of the reference pictures must have been reconstructed before inter prediction of a subsequent frame may begin. Consequently, where a motion vector pointed to a location significantly above the current subpicture, there was the possibility of a race condition. Patch fixes this by cropping the motion vector to the current subpicture in pred_get_y.
Signed-off-by: Frank Plowman <p...@frankplowman.com> --- Changes since v1: * Also clip max_y to the subpic_bottom, in order to prevent adding unecessary dependencies. max_y is also clipped to the picture bottom where it wasn't before. This doesn't make any difference to the function of the code as is, but this was only previously unnecessary due to a detail of how y-coordinates are mapped to CTU rows. To aid comprehensibility, the MV is now clipped to both the top and bottom edges of the picture. * Rename subpic_t to subpic_top to avoid clashing with conventions for type names. --- libavcodec/vvc/ctu.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/libavcodec/vvc/ctu.c b/libavcodec/vvc/ctu.c index f80bce637c..b82dece0dd 100644 --- a/libavcodec/vvc/ctu.c +++ b/libavcodec/vvc/ctu.c @@ -2393,23 +2393,34 @@ static int has_inter_luma(const CodingUnit *cu) return cu->pred_mode != MODE_INTRA && cu->pred_mode != MODE_PLT && cu->tree_type != DUAL_TREE_CHROMA; } -static int pred_get_y(const int y0, const Mv *mv, const int height) +static int pred_get_y(const VVCLocalContext *lc, const int y0, const Mv *mv, const int height, const VVCFrame *src_frame) { - return FFMAX(0, y0 + (mv->y >> 4) + height); + const VVCSPS *sps = src_frame->sps; + const VVCPPS *pps = src_frame->pps; + const int pic_height = pps->height; + const int subpic_idx = lc->sc->sh.r->curr_subpic_idx; + const int subpic_top = pps->subpic_y[subpic_idx]; + const int subpic_bottom = subpic_top + pps->subpic_height[subpic_idx] - 1; + const int subpic_treated_as_pic = sps->r->sps_subpic_treated_as_pic_flag[subpic_idx]; + const int lower_bound = subpic_treated_as_pic ? subpic_top : 0; + const int upper_bound = subpic_treated_as_pic ? subpic_bottom : pic_height; + return av_clip(y0 + (mv->y >> 4) + height, lower_bound, upper_bound); } -static void cu_get_max_y(const CodingUnit *cu, int max_y[2][VVC_MAX_REF_ENTRIES], const VVCFrameContext *fc) +static void cu_get_max_y(const VVCLocalContext *lc, const CodingUnit *cu, int max_y[2][VVC_MAX_REF_ENTRIES]) { + const VVCFrameContext *fc = lc->fc; const PredictionUnit *pu = &cu->pu; if (pu->merge_gpm_flag) { for (int i = 0; i < FF_ARRAY_ELEMS(pu->gpm_mv); i++) { - const MvField *mvf = pu->gpm_mv + i; - const int lx = mvf->pred_flag - PF_L0; - const int idx = mvf->ref_idx[lx]; - const int y = pred_get_y(cu->y0, mvf->mv + lx, cu->cb_height); + const MvField *mvf = pu->gpm_mv + i; + const int lx = mvf->pred_flag - PF_L0; + const int idx = mvf->ref_idx[lx]; + const VVCRefPic *refp = lc->sc->rpl[lx].refs + idx; + const int y = pred_get_y(lc, cu->y0, mvf->mv + lx, cu->cb_height, refp->ref); - max_y[lx][idx] = FFMAX(max_y[lx][idx], y); + max_y[lx][idx] = FFMAX(max_y[lx][idx], y); } } else { const MotionInfo *mi = &pu->mi; @@ -2424,8 +2435,9 @@ static void cu_get_max_y(const CodingUnit *cu, int max_y[2][VVC_MAX_REF_ENTRIES] for (int lx = 0; lx < 2; lx++) { const PredFlag mask = 1 << lx; if (mvf->pred_flag & mask) { - const int idx = mvf->ref_idx[lx]; - const int y = pred_get_y(y0, mvf->mv + lx, sbh); + const int idx = mvf->ref_idx[lx]; + const VVCRefPic *refp = lc->sc->rpl[lx].refs + idx; + int y = pred_get_y(lc, y0, mvf->mv + lx, sbh, refp->ref); max_y[lx][idx] = FFMAX(max_y[lx][idx], y + max_dmvr_off); } @@ -2452,7 +2464,7 @@ static void ctu_get_pred(VVCLocalContext *lc, const int rs) while (cu) { if (has_inter_luma(cu)) { - cu_get_max_y(cu, ctu->max_y, fc); + cu_get_max_y(lc, cu, ctu->max_y); ctu->has_dmvr |= cu->pu.dmvr_flag; } cu = cu->next; -- 2.47.0 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".