From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTPS id 6F4494C883 for ; Sun, 9 Feb 2025 15:45:37 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id E3CE868BCCC; Sun, 9 Feb 2025 17:45:23 +0200 (EET) Received: from sender2-op-o11.zoho.eu (sender2-op-o11.zoho.eu [136.143.171.11]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 2DB8568B64B for ; Sun, 9 Feb 2025 17:45:16 +0200 (EET) ARC-Seal: i=1; a=rsa-sha256; t=1739115913; cv=none; d=zohomail.eu; s=zohoarc; b=Mmq+o8rbnrCjd3tf9Vqhso7VUZauDiEiHNl/L7EYDELhpNhis6zVd3KLgKRmgKckrPmeVAqyoR4uJcDcCuE0U1/9Ecw9ogsp/s8hXhCHh9V4GgZLwl6T8UUvbP0qCZd1vFF+xbMXVFK/IXXzg5qSoGWUV8mWmJzTSekOld7nrMY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.eu; s=zohoarc; t=1739115913; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=9hrifaJJInCkf1YA0qB5OVFe3Q/KzoL4L/+0ji77O7I=; b=GEQZVdtNCZEk05JTM+E6em/dKGLk2kylyseyMiMUvVuveusTaBnGyUaD6P7UdjL7d3n3peRvGw5ZxBv3WOO89ZHq+krs71wUJzoMHdo1ejMLkf1d2Br3RUvZM6fS2pXFDe1bUJX3nkQLsBaT/87cRcotcuBPgkfn0B80b+IdL7E= ARC-Authentication-Results: i=1; mx.zohomail.eu; dkim=pass header.i=frankplowman.com; spf=pass smtp.mailfrom=post@frankplowman.com; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1739115913; s=zmail; d=frankplowman.com; i=post@frankplowman.com; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-ID:In-Reply-To:References:MIME-Version:Content-Transfer-Encoding:Message-Id:Reply-To; bh=9hrifaJJInCkf1YA0qB5OVFe3Q/KzoL4L/+0ji77O7I=; b=Lf7NmqPMNvqecEG6h9Cu1riwLnKQoof/0Jc7WSG4o6wd+viXs/2XzxduelXLeZAi lLs4kvOs2yHlUNgRbB7Vm+C3hdBLpwXCbwblN+sAZ1pFOy//rN8iw6HlFmEv6VFO1qK iT0peRMXjmiPeYeyQcdUnZO3qr3fps5wMnBPLIBE= Received: by mx.zoho.eu with SMTPS id 1739115911734845.031058164711; Sun, 9 Feb 2025 16:45:11 +0100 (CET) From: Frank Plowman To: ffmpeg-devel@ffmpeg.org Date: Sun, 9 Feb 2025 15:43:17 +0000 Message-ID: <20250209154505.69704-2-post@frankplowman.com> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20250209154505.69704-1-post@frankplowman.com> References: <20250209154505.69704-1-post@frankplowman.com> MIME-Version: 1.0 X-ZohoMailClient: External Subject: [FFmpeg-devel] [PATCH 2/2] lavc/vvc: Ensure subpictures don't overlap X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Frank Plowman , nuomi2021@gmail.com Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Archived-At: List-Archive: List-Post: This is essentially a re-implementation of https://patchwork.ffmpeg.org/project/ffmpeg/patch/20241005223955.54158-1-post@frankplowman.com/ That patch was not applied last time. Instead we opted to identify issues which could be caused by invalid subpicture layouts and remedy those issues where they manifest, either through error detection or code hardening. This was primarily implemented in the set https://patchwork.ffmpeg.org/project/ffmpeg/list/?series=13381. This has worked to some degree, however issues with subpicture layouts continue to crop up from the fuzzer and I've fixed a number of bugs related to subpicture layouts since then. I think it's best to return to the initial plan and simply check if the subpicture layout is valid initially. This implementation is also lighter than the first time -- by doing a bit more logic in pps_subpic_less_than_one_tile_slice, we are able to store a tile_in_subpic map rather than a ctu_in_subpic map. This reduces the size of the map to the point it becomes possible to allocate it on the stack. Similar to 8bd66a8c9587af61c7b46558be3c4ee317c1af5a, the layout is also validated in the slice map construction code, rather than in the CBS, which avoids duplicating some logic. Signed-off-by: Frank Plowman --- libavcodec/vvc/ps.c | 52 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/libavcodec/vvc/ps.c b/libavcodec/vvc/ps.c index 9480540e03..9af5e1250b 100644 --- a/libavcodec/vvc/ps.c +++ b/libavcodec/vvc/ps.c @@ -401,25 +401,47 @@ static void subpic_tiles(int *tile_x, int *tile_y, int *tile_x_end, int *tile_y_ (*tile_y_end)++; } -static void pps_subpic_less_than_one_tile_slice(VVCPPS *pps, const VVCSPS *sps, const int i, const int tx, const int ty, int *off) +static int pps_subpic_less_than_one_tile_slice(VVCPPS *pps, const VVCSPS *sps, const int i, const int tx, const int ty, int *off, bool *tile_in_subpic) { + const int subpic_right = sps->r->sps_subpic_ctu_top_left_x[i] + sps->r->sps_subpic_width_minus1[i]; + const int subpic_bottom = sps->r->sps_subpic_ctu_top_left_y[i] + sps->r->sps_subpic_height_minus1[i]; + const int tile_right = pps->col_bd[tx] + pps->r->col_width_val[tx] - 1; + const int tile_bottom = pps->row_bd[ty] + pps->r->row_height_val[ty] - 1; + const bool is_final_subpic_in_tile = subpic_right == tile_right && subpic_bottom == tile_bottom; + + if (is_final_subpic_in_tile) { + const size_t tile_idx = ty * VVC_MAX_TILE_COLUMNS + tx; + if (tile_in_subpic[tile_idx]) + return AVERROR_INVALIDDATA; + tile_in_subpic[tile_idx] = true; + } + pps->num_ctus_in_slice[i] = pps_add_ctus(pps, off, sps->r->sps_subpic_ctu_top_left_x[i], sps->r->sps_subpic_ctu_top_left_y[i], sps->r->sps_subpic_width_minus1[i] + 1, sps->r->sps_subpic_height_minus1[i] + 1); + + return 0; } -static void pps_subpic_one_or_more_tiles_slice(VVCPPS *pps, const int tile_x, const int tile_y, const int x_end, const int y_end, const int i, int *off) +static int pps_subpic_one_or_more_tiles_slice(VVCPPS *pps, const int tile_x, const int tile_y, const int x_end, const int y_end, + const int i, int *off, bool *tile_in_subpic) { for (int ty = tile_y; ty < y_end; ty++) { for (int tx = tile_x; tx < x_end; tx++) { + const size_t tile_idx = ty * VVC_MAX_TILE_COLUMNS + tx; + if (tile_in_subpic[tile_idx]) + return AVERROR_INVALIDDATA; + tile_in_subpic[tile_idx] = true; + pps->num_ctus_in_slice[i] += pps_add_ctus(pps, off, pps->col_bd[tx], pps->row_bd[ty], pps->r->col_width_val[tx], pps->r->row_height_val[ty]); } } + return 0; } -static void pps_subpic_slice(VVCPPS *pps, const VVCSPS *sps, const int i, int *off) +static int pps_subpic_slice(VVCPPS *pps, const VVCSPS *sps, const int i, int *off, bool *tile_in_subpic) { int tx, ty, x_end, y_end; @@ -428,19 +450,30 @@ static void pps_subpic_slice(VVCPPS *pps, const VVCSPS *sps, const int i, int *o subpic_tiles(&tx, &ty, &x_end, &y_end, sps, pps, i); if (ty + 1 == y_end && sps->r->sps_subpic_height_minus1[i] + 1 < pps->r->row_height_val[ty]) - pps_subpic_less_than_one_tile_slice(pps, sps, i, tx, ty, off); + return pps_subpic_less_than_one_tile_slice(pps, sps, i, tx, ty, off, tile_in_subpic); else - pps_subpic_one_or_more_tiles_slice(pps, tx, ty, x_end, y_end, i, off); + return pps_subpic_one_or_more_tiles_slice(pps, tx, ty, x_end, y_end, i, off, tile_in_subpic); } -static void pps_single_slice_per_subpic(VVCPPS *pps, const VVCSPS *sps, int *off) +static int pps_single_slice_per_subpic(VVCPPS *pps, const VVCSPS *sps, int *off) { if (!sps->r->sps_subpic_info_present_flag) { pps_single_slice_picture(pps, off); } else { - for (int i = 0; i < pps->r->pps_num_slices_in_pic_minus1 + 1; i++) - pps_subpic_slice(pps, sps, i, off); + bool tile_in_subpic[VVC_MAX_TILES_PER_AU] = {0}; + for (int i = 0; i < pps->r->pps_num_slices_in_pic_minus1 + 1; i++) { + const int ret = pps_subpic_slice(pps, sps, i, off, tile_in_subpic); + if (ret < 0) + return ret; + } + + // We only use tile_in_subpic to check that the subpictures don't overlap + // here; we don't use tile_in_subpic to check that the subpictures cover + // every tile. It is possible to avoid doing this work here because the + // covering property of subpictures is already guaranteed by the mechanisms + // which check every CTU belongs to a slice. } + return 0; } static int pps_one_tile_slices(VVCPPS *pps, const int tile_idx, int i, int *off) @@ -491,8 +524,7 @@ static int pps_rect_slice(VVCPPS *pps, const VVCSPS *sps) int tile_idx = 0, off = 0; if (r->pps_single_slice_per_subpic_flag) { - pps_single_slice_per_subpic(pps, sps, &off); - return 0; + return pps_single_slice_per_subpic(pps, sps, &off); } for (int i = 0; i < r->pps_num_slices_in_pic_minus1 + 1; i++) { -- 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-request@ffmpeg.org with subject "unsubscribe".