PR #22873 opened by Diego de Souza (ddesouza)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22873
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22873.patch

Both paths unconditionally rounded coded dimensions to even via
(dim + 1) & ~1. This is required for 4:2:0 and 4:2:2 (chroma
subsampling requires even-aligned surfaces) but incorrect for
monochrome and 4:4:4, which have no chroma subsampling. As a result,
AV1 monochrome clips with odd dimensions (e.g., 1273x713) were output
as 1274x714, causing CRC mismatches vs. reference decoders.

In cuviddec.c: cuinfo.ulTargetWidth/Height still receives the
even-aligned value for internal NVDEC surface allocation, but
avctx->width/height are only updated to the rounded value for 420/422.
For monochrome/444, the original display dimensions are preserved; the
cuMemcpy2D copy crops to avctx->width/height naturally.

In nvdec.c: frames_ctx->width/height are conditionally rounded only
for 420/422. Monochrome/444 uses avctx->coded_width/coded_height
unchanged, matching the dimensions set by the software codec layer.


From a7d2ce39859fd041ee749408333b65525c39e4f6 Mon Sep 17 00:00:00 2001
From: Diego de Souza <[email protected]>
Date: Tue, 21 Apr 2026 17:31:49 +0200
Subject: [PATCH 1/2] avcodec/cuviddec: fix dimension rounding for
 monochrome/444 formats

Both paths unconditionally rounded display dimensions to even via
(dim + 1) & ~1. This is required for 4:2:0 and 4:2:2 (chroma
subsampling requires even-aligned surfaces) but incorrect for
monochrome and 4:4:4. AV1 monochrome clips with odd dimensions
(e.g. 1273x713) were output as 1274x714.

cuinfo.ulTargetWidth/Height still receives the even-aligned value
for internal NVDEC surface allocation. avctx->width/height are only
updated to the rounded value for 420/422; for monochrome/444 the
original display dimensions are preserved and the cuMemcpy2D copy
crops naturally.

Patch by: Aniket Dhok <[email protected]>
Signed-off-by: Diego de Souza <[email protected]>
---
 libavcodec/cuviddec.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/libavcodec/cuviddec.c b/libavcodec/cuviddec.c
index fa1494cad4..62c2bfb7ff 100644
--- a/libavcodec/cuviddec.c
+++ b/libavcodec/cuviddec.c
@@ -164,9 +164,17 @@ static int CUDAAPI cuvid_handle_video_sequence(void 
*opaque, CUVIDEOFORMAT* form
         avctx->height = cuinfo.display_area.bottom - cuinfo.display_area.top;
     }
 
-    // target width/height need to be multiples of two
-    cuinfo.ulTargetWidth = avctx->width = (avctx->width + 1) & ~1;
-    cuinfo.ulTargetHeight = avctx->height = (avctx->height + 1) & ~1;
+    // NVDEC target dimensions must be even-aligned for internal surface 
allocation.
+    // For chroma-subsampled formats (420/422), the output dimensions must 
also be
+    // even. For monochrome/444, keep the original output dimensions and only
+    // even-align the NVDEC target — the frame copy will crop to avctx 
dimensions.
+    cuinfo.ulTargetWidth  = (avctx->width + 1) & ~1;
+    cuinfo.ulTargetHeight = (avctx->height + 1) & ~1;
+    if (format->chroma_format == cudaVideoChromaFormat_420 ||
+        format->chroma_format == cudaVideoChromaFormat_422) {
+        avctx->width  = cuinfo.ulTargetWidth;
+        avctx->height = cuinfo.ulTargetHeight;
+    }
 
     // aspect ratio conversion, 1:1, depends on scaled resolution
     cuinfo.target_rect.left = 0;
-- 
2.52.0


From 382a2ae8c6b929ed070a2741f08541e0a38cc6e6 Mon Sep 17 00:00:00 2001
From: Diego de Souza <[email protected]>
Date: Tue, 21 Apr 2026 17:34:49 +0200
Subject: [PATCH 2/2] avcodec/nvdec: fix dimension rounding for monochrome/444
 formats

frames_ctx->width/height were unconditionally rounded to even, causing
odd-dimension monochrome/444 clips to be reported with incorrect
surface pool dimensions. Round only for 4:2:0 and 4:2:2; for
monochrome/444 use avctx->coded_width/coded_height unchanged,
matching the dimensions set by the software codec layer.

Patch by: Aniket Dhok <[email protected]>
Signed-off-by: Diego de Souza <[email protected]>
---
 libavcodec/nvdec.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/libavcodec/nvdec.c b/libavcodec/nvdec.c
index 911fc336c7..e64ee7a9d6 100644
--- a/libavcodec/nvdec.c
+++ b/libavcodec/nvdec.c
@@ -732,8 +732,18 @@ int ff_nvdec_frame_params(AVCodecContext *avctx,
     chroma_444 = supports_444 && cuvid_chroma_format == 
cudaVideoChromaFormat_444;
 
     frames_ctx->format            = AV_PIX_FMT_CUDA;
-    frames_ctx->width             = (avctx->coded_width + 1) & ~1;
-    frames_ctx->height            = (avctx->coded_height + 1) & ~1;
+    // NVDEC target dimensions must be even-aligned for internal surface 
allocation.
+    // For chroma-subsampled formats (420/422), the output dimensions must 
also be
+    // even. For monochrome/444, keep the original output dimensions and only
+    // even-align the NVDEC target — the frame copy will crop to avctx 
dimensions.
+    if (cuvid_chroma_format == cudaVideoChromaFormat_420 ||
+        cuvid_chroma_format == cudaVideoChromaFormat_422) {
+        frames_ctx->width         = (avctx->coded_width  + 1) & ~1;
+        frames_ctx->height        = (avctx->coded_height + 1) & ~1;
+    } else {
+        frames_ctx->width         = avctx->coded_width;
+        frames_ctx->height        = avctx->coded_height;
+    }
     /*
      * We add two extra frames to the pool to account for deinterlacing filters
      * holding onto their frames.
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to