From patchwork Sat Oct 5 22:39:42 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frank Plowman X-Patchwork-Id: 52083 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a59:938f:0:b0:48e:c0f8:d0de with SMTP id z15csp1699703vqg; Sun, 6 Oct 2024 21:56:05 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCUvpBuB4ZG7aV+WKBSRliuZfOUallCg9eMF4NWzFgCVMurAKWhx6Bk5ZMJGikmpOPktGszA6CcJqtuFfawwRa95@gmail.com X-Google-Smtp-Source: AGHT+IGTkMuGXUs614WRNJwAo7lzKHaKcMUe1FlZWppEwki75DECaensW4ss9Oapw7fVg0buXWbX X-Received: by 2002:a05:6512:2803:b0:539:9fb4:802f with SMTP id 2adb3069b0e04-539ab858c13mr5101889e87.22.1728276965676; Sun, 06 Oct 2024 21:56:05 -0700 (PDT) Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id 2adb3069b0e04-539b001fd69si1658655e87.500.2024.10.06.21.56.04; Sun, 06 Oct 2024 21:56:05 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@frankplowman.com header.s=zmail header.b=KzJDvF9i; arc=fail (body hash mismatch); spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id B692268D788; Sun, 6 Oct 2024 01:40:09 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from sender-op-o11.zoho.eu (sender-op-o11.zoho.eu [136.143.169.11]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id BC27A68D788 for ; Sun, 6 Oct 2024 01:40:02 +0300 (EEST) ARC-Seal: i=1; a=rsa-sha256; t=1728168000; cv=none; d=zohomail.eu; s=zohoarc; b=V5QTekHKqKtq9y7pU/i8vLF5OTFQECtJfLl595LaSiny5cArbe8RSsrp9RR14utmTw9TCiPYofeLZpCVY/hpTFI6QA/6m9yEgtU4QPORUVJMo4KPLsEQpXGhGSlqsgO79ytoHZZHdrvCVtmjoxfhAOWcD2DhD5tm3cu4b/gK7Hk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.eu; s=zohoarc; t=1728168000; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:MIME-Version:Message-ID:Subject:Subject:To:To:Message-Id:Reply-To; bh=vxLqjIXm4X7xWKWwdBTiTLTW49ykPzQCfYSqhMHNs5w=; b=NsUgWz2bBkcNTwtSYBsfzzDwHew9rTsIL3odt9jqyTfM+kUxo/1Ybb9Jkay8miau6FnaniPcxKGOEot/9X/BYFVKU2artLL7NIevtdL0MfHu1hzgpYnf4+mKcguyVlrP80hrGfLecHqKMakwQnHtc8CHsdjiWwIJqyw0jI7D9X4= 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=1728168000; s=zmail; d=frankplowman.com; i=post@frankplowman.com; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-ID:MIME-Version:Content-Transfer-Encoding:Message-Id:Reply-To; bh=vxLqjIXm4X7xWKWwdBTiTLTW49ykPzQCfYSqhMHNs5w=; b=KzJDvF9ixrFirzN/SxSHKD9qzYSFW0HGnEYjULLDHbcsVOp3WmnUTlOND4TNrECg Z0zEGLVDCifyQ40LgRrNWAttEnYWCZJbRLCdnvk6zsISVuReePBWaGr+2VDXc40af5y edWlMUa89t/e271UiD4gkLEoNpiPEzEn9ycH1BkU= Received: by mx.zoho.eu with SMTPS id 1728167998682425.4486745955571; Sun, 6 Oct 2024 00:39:58 +0200 (CEST) From: Frank Plowman To: ffmpeg-devel@ffmpeg.org Date: Sat, 5 Oct 2024 15:39:42 -0700 Message-ID: <20241005223955.54158-1-post@frankplowman.com> X-Mailer: git-send-email 2.46.2 MIME-Version: 1.0 X-ZohoMailClient: External Subject: [FFmpeg-devel] [PATCH] lavc/vvc: Validate subpartitioning structure 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 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: ggTJNB15wBNf H.266 (V3) section 6.3.3 dictates that the division of the picture into subpictures must be exhaustive and mutually exclusive, i.e. that each CTU "belongs to" one and only one subpicture. In most cases this is guaranteed by the syntax, but in the case sps_subpic_same_size_flag=0, we must check this is true ourselves. Signed-off-by: Frank Plowman --- libavcodec/cbs_h266_syntax_template.c | 46 +++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/libavcodec/cbs_h266_syntax_template.c b/libavcodec/cbs_h266_syntax_template.c index b4165b43b3..822ee26f46 100644 --- a/libavcodec/cbs_h266_syntax_template.c +++ b/libavcodec/cbs_h266_syntax_template.c @@ -1191,7 +1191,7 @@ static int FUNC(sps)(CodedBitstreamContext *ctx, RWContext *rw, win_left_edge_ctus > current->sps_subpic_ctu_top_left_x[i] ? win_left_edge_ctus - current->sps_subpic_ctu_top_left_x[i] : 0, - MAX_UINT_BITS(wlen), 1, i); + tmp_width_val - current->sps_subpic_ctu_top_left_x[i] - 1, 1, i); } else { infer(sps_subpic_width_minus1[i], tmp_width_val - @@ -1208,7 +1208,7 @@ static int FUNC(sps)(CodedBitstreamContext *ctx, RWContext *rw, win_top_edge_ctus > current->sps_subpic_ctu_top_left_y[i] ? win_top_edge_ctus - current->sps_subpic_ctu_top_left_y[i] : 0, - MAX_UINT_BITS(hlen), 1, i); + tmp_height_val - current->sps_subpic_ctu_top_left_y[i] - 1, 1, i); } else { infer(sps_subpic_height_minus1[i], tmp_height_val - @@ -1242,6 +1242,48 @@ static int FUNC(sps)(CodedBitstreamContext *ctx, RWContext *rw, infer(sps_loop_filter_across_subpic_enabled_flag[i], 0); } } + // If the subpic partitioning structure is signalled explicitly, + // validate it constitutes an exhaustive and mutually exclusive + // coverage of the picture, per 6.3.3. If the partitioning is not + // provided explicitly, then it is ensured by the syntax and we need + // not check. + if (!current->sps_subpic_same_size_flag) { + char *ctu_in_subpic = av_mallocz(tmp_width_val * tmp_height_val); + if (!ctu_in_subpic) + return AVERROR(ENOMEM); + for (i = 0; i <= current->sps_num_subpics_minus1; i++) { + const unsigned x0 = current->sps_subpic_ctu_top_left_x[i]; + const unsigned y0 = current->sps_subpic_ctu_top_left_y[i]; + const unsigned w = current->sps_subpic_width_minus1[i] + 1; + const unsigned h = current->sps_subpic_height_minus1[i] + 1; + av_assert0(x0 + w - 1 < tmp_width_val); + av_assert0(y0 + h - 1 < tmp_height_val); + for (unsigned x = x0; x < x0 + w; x++) { + for (unsigned y = y0; y < y0 + h; y++) { + const unsigned idx = y * tmp_width_val + x; + if (ctu_in_subpic[idx]) { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "Subpictures overlap.\n"); + av_freep(&ctu_in_subpic); + return AVERROR_INVALIDDATA; + } + ctu_in_subpic[idx] = 1; + } + } + } + for (unsigned x = 0; x < tmp_width_val; x++) { + for (unsigned y = 0; y < tmp_height_val; y++) { + const unsigned idx = y * tmp_width_val + x; + if (!ctu_in_subpic[idx]) { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "Subpictures do not cover the entire picture.\n"); + av_freep(&ctu_in_subpic); + return AVERROR_INVALIDDATA; + } + } + } + av_freep(&ctu_in_subpic); + } } else { infer(sps_subpic_ctu_top_left_x[0], 0); infer(sps_subpic_ctu_top_left_y[0], 0);