[FFmpeg-devel] [PATCH] lavc/vvc: Use pps->{width, height} over sps->{width, height}

post at frankplowman.com post at frankplowman.com
Thu Feb 15 13:54:24 EET 2024


From: Frank Plowman <post at frankplowman.com>

The PPS should be used instead of the SPS to get the current picture's
dimensions.  Using the SPS can cause issues if the resolution changes
mid-sequence.  In particular, it was leading to invalid memory accesses
if the resolution decreased.

Patch replaces sps->{width,height} with pps->{width,height}.  It also
removes sps->{width,height}, as these are no longer used anywhere.

Fixes crash when decoding DVB V&V test sequence
VVC_HDR_UHDTV1_ClosedGOP_Max3840x2160_50fps_HLG10_res_change_without_RPR

Signed-off-by: Frank Plowman <post at frankplowman.com>
---
 libavcodec/vvc/vvc_ctu.c    |  4 ++--
 libavcodec/vvc/vvc_ctu.h    |  2 +-
 libavcodec/vvc/vvc_filter.c | 48 ++++++++++++++++++-------------------
 libavcodec/vvc/vvc_mvs.c    |  4 ++--
 libavcodec/vvc/vvc_ps.c     |  3 ---
 libavcodec/vvc/vvc_ps.h     |  2 --
 libavcodec/vvc/vvc_refs.c   |  5 ++--
 7 files changed, 32 insertions(+), 36 deletions(-)

diff --git a/libavcodec/vvc/vvc_ctu.c b/libavcodec/vvc/vvc_ctu.c
index d166b16a19..36f98f5f2b 100644
--- a/libavcodec/vvc/vvc_ctu.c
+++ b/libavcodec/vvc/vvc_ctu.c
@@ -2415,8 +2415,8 @@ void ff_vvc_decode_neighbour(VVCLocalContext *lc, const int x_ctb, const int y_c
     VVCFrameContext *fc = lc->fc;
     const int ctb_size         = fc->ps.sps->ctb_size_y;
 
-    lc->end_of_tiles_x = fc->ps.sps->width;
-    lc->end_of_tiles_y = fc->ps.sps->height;
+    lc->end_of_tiles_x = fc->ps.pps->width;
+    lc->end_of_tiles_y = fc->ps.pps->height;
     if (fc->ps.pps->ctb_to_col_bd[rx] != fc->ps.pps->ctb_to_col_bd[rx + 1])
         lc->end_of_tiles_x = FFMIN(x_ctb + ctb_size, lc->end_of_tiles_x);
     if (fc->ps.pps->ctb_to_row_bd[ry] != fc->ps.pps->ctb_to_row_bd[ry + 1])
diff --git a/libavcodec/vvc/vvc_ctu.h b/libavcodec/vvc/vvc_ctu.h
index 91b4ed14a1..ab3fac626d 100644
--- a/libavcodec/vvc/vvc_ctu.h
+++ b/libavcodec/vvc/vvc_ctu.h
@@ -85,7 +85,7 @@
 /**
  * Value of the luma sample at position (x, y) in the 2D array tab.
  */
-#define SAMPLE(tab, x, y) ((tab)[(y) * s->sps->width + (x)])
+#define SAMPLE(tab, x, y) ((tab)[(y) * s->pps->width + (x)])
 #define SAMPLE_CTB(tab, x, y) ((tab)[(y) * min_cb_width + (x)])
 #define CTB(tab, x, y) ((tab)[(y) * fc->ps.pps->ctb_width + (x)])
 
diff --git a/libavcodec/vvc/vvc_filter.c b/libavcodec/vvc/vvc_filter.c
index cebc02fd9f..df77e443f6 100644
--- a/libavcodec/vvc/vvc_filter.c
+++ b/libavcodec/vvc/vvc_filter.c
@@ -102,8 +102,8 @@ static void copy_ctb_to_hv(VVCFrameContext *fc, const uint8_t *src,
     const int c_idx, const int x_ctb, const int y_ctb, const int top)
 {
     const int ps = fc->ps.sps->pixel_shift;
-    const int w  = fc->ps.sps->width >> fc->ps.sps->hshift[c_idx];
-    const int h  = fc->ps.sps->height >> fc->ps.sps->vshift[c_idx];
+    const int w  = fc->ps.pps->width >> fc->ps.sps->hshift[c_idx];
+    const int h  = fc->ps.pps->height >> fc->ps.sps->vshift[c_idx];
 
     if (top) {
         /* top */
@@ -133,8 +133,8 @@ static void sao_copy_ctb_to_hv(VVCLocalContext *lc, const int rx, const int ry,
         const ptrdiff_t src_stride = fc->frame->linesize[c_idx];
         const int ctb_size_h       = ctb_size_y >> fc->ps.sps->hshift[c_idx];
         const int ctb_size_v       = ctb_size_y >> fc->ps.sps->vshift[c_idx];
-        const int width            = FFMIN(ctb_size_h, (fc->ps.sps->width  >> fc->ps.sps->hshift[c_idx]) - x);
-        const int height           = FFMIN(ctb_size_v, (fc->ps.sps->height >> fc->ps.sps->vshift[c_idx]) - y);
+        const int width            = FFMIN(ctb_size_h, (fc->ps.pps->width  >> fc->ps.sps->hshift[c_idx]) - x);
+        const int height           = FFMIN(ctb_size_v, (fc->ps.pps->height >> fc->ps.sps->vshift[c_idx]) - y);
         const uint8_t *src          = &fc->frame->data[c_idx][y * src_stride + (x << fc->ps.sps->pixel_shift)];
         copy_ctb_to_hv(fc, src, src_stride, x, y, width, height, c_idx, rx, ry, top);
     }
@@ -216,8 +216,8 @@ void ff_vvc_sao_filter(VVCLocalContext *lc, int x, int y)
         ptrdiff_t src_stride = fc->frame->linesize[c_idx];
         int ctb_size_h = ctb_size_y >> fc->ps.sps->hshift[c_idx];
         int ctb_size_v = ctb_size_y >> fc->ps.sps->vshift[c_idx];
-        int width    = FFMIN(ctb_size_h, (fc->ps.sps->width  >> fc->ps.sps->hshift[c_idx]) - x0);
-        int height   = FFMIN(ctb_size_v, (fc->ps.sps->height >> fc->ps.sps->vshift[c_idx]) - y0);
+        int width    = FFMIN(ctb_size_h, (fc->ps.pps->width  >> fc->ps.sps->hshift[c_idx]) - x0);
+        int height   = FFMIN(ctb_size_v, (fc->ps.pps->height >> fc->ps.sps->vshift[c_idx]) - y0);
         int tab      = sao_tab[(FFALIGN(width, 8) >> 3) - 1];
         uint8_t *src = &fc->frame->data[c_idx][y0 * src_stride + (x0 << fc->ps.sps->pixel_shift)];
         ptrdiff_t dst_stride;
@@ -230,8 +230,8 @@ void ff_vvc_sao_filter(VVCLocalContext *lc, int x, int y)
             break;
         case SAO_EDGE:
         {
-            const int w = fc->ps.sps->width >> fc->ps.sps->hshift[c_idx];
-            const int h = fc->ps.sps->height >> fc->ps.sps->vshift[c_idx];
+            const int w = fc->ps.pps->width >> fc->ps.sps->hshift[c_idx];
+            const int h = fc->ps.pps->height >> fc->ps.sps->vshift[c_idx];
             const int sh = fc->ps.sps->pixel_shift;
 
             dst_stride = 2*MAX_PB_SIZE + AV_INPUT_BUFFER_PADDING_SIZE;
@@ -880,11 +880,11 @@ void ff_vvc_deblock_vertical(const VVCLocalContext *lc, int x0, int y0)
     vvc_deblock_bs(lc, x0, y0, 1);
 
     x_end = x0 + ctb_size;
-    if (x_end > fc->ps.sps->width)
-        x_end = fc->ps.sps->width;
+    if (x_end > fc->ps.pps->width)
+        x_end = fc->ps.pps->width;
     y_end = y0 + ctb_size;
-    if (y_end > fc->ps.sps->height)
-        y_end = fc->ps.sps->height;
+    if (y_end > fc->ps.pps->height)
+        y_end = fc->ps.pps->height;
 
     for (int c_idx = 0; c_idx < c_end; c_idx++) {
         const int hs          = sps->hshift[c_idx];
@@ -950,11 +950,11 @@ void ff_vvc_deblock_horizontal(const VVCLocalContext *lc, int x0, int y0)
     vvc_deblock_bs(lc, x0, y0, 0);
 
     x_end = x0 + ctb_size;
-    if (x_end > fc->ps.sps->width)
-        x_end = fc->ps.sps->width;
+    if (x_end > fc->ps.pps->width)
+        x_end = fc->ps.pps->width;
     y_end = y0 + ctb_size;
-    if (y_end > fc->ps.sps->height)
-        y_end = fc->ps.sps->height;
+    if (y_end > fc->ps.pps->height)
+        y_end = fc->ps.pps->height;
 
     for (int c_idx = 0; c_idx < c_end; c_idx++) {
         const int hs          = sps->hshift[c_idx];
@@ -1050,8 +1050,8 @@ static void alf_copy_ctb_to_hv(VVCFrameContext *fc, const uint8_t *src, const pt
     const int x, const int y, const int width, const int height, const int x_ctb, const int y_ctb, const int c_idx)
 {
     const int ps            = fc->ps.sps->pixel_shift;
-    const int w             = fc->ps.sps->width >> fc->ps.sps->hshift[c_idx];
-    const int h             = fc->ps.sps->height >> fc->ps.sps->vshift[c_idx];
+    const int w             = fc->ps.pps->width >> fc->ps.sps->hshift[c_idx];
+    const int h             = fc->ps.pps->height >> fc->ps.sps->vshift[c_idx];
     const int border_pixels = (c_idx == 0) ? ALF_BORDER_LUMA : ALF_BORDER_CHROMA;
     const int offset_h[]    = { 0, height - border_pixels };
     const int offset_v[]    = { 0, width  - border_pixels };
@@ -1107,8 +1107,8 @@ static void alf_prepare_buffer(VVCFrameContext *fc, uint8_t *_dst, const uint8_t
     const int c_idx, const int *edges)
 {
     const int ps = fc->ps.sps->pixel_shift;
-    const int w = fc->ps.sps->width >> fc->ps.sps->hshift[c_idx];
-    const int h = fc->ps.sps->height >> fc->ps.sps->vshift[c_idx];
+    const int w = fc->ps.pps->width >> fc->ps.sps->hshift[c_idx];
+    const int h = fc->ps.pps->height >> fc->ps.sps->vshift[c_idx];
     const int border_pixels = c_idx == 0 ? ALF_BORDER_LUMA : ALF_BORDER_CHROMA;
     uint8_t *dst, *src;
 
@@ -1241,8 +1241,8 @@ void ff_vvc_alf_copy_ctu_to_hv(VVCLocalContext* lc, const int x0, const int y0)
         const int vs     = fc->ps.sps->vshift[c_idx];
         const int x      = x0 >> hs;
         const int y      = y0 >> vs;
-        const int width  = FFMIN(fc->ps.sps->width - x0, ctb_size_y) >> hs;
-        const int height = FFMIN(fc->ps.sps->height - y0, ctb_size_y) >> vs;
+        const int width  = FFMIN(fc->ps.pps->width - x0, ctb_size_y) >> hs;
+        const int height = FFMIN(fc->ps.pps->height - y0, ctb_size_y) >> vs;
 
         const int src_stride = fc->frame->linesize[c_idx];
         uint8_t* src = &fc->frame->data[c_idx][y * src_stride + (x << ps)];
@@ -1286,8 +1286,8 @@ void ff_vvc_alf_filter(VVCLocalContext *lc, const int x0, const int y0)
         const int ctb_size_v = ctb_size_y >> vs;
         const int x = x0 >> hs;
         const int y = y0 >> vs;
-        const int pic_width = fc->ps.sps->width >> hs;
-        const int pic_height = fc->ps.sps->height >> vs;
+        const int pic_width = fc->ps.pps->width >> hs;
+        const int pic_height = fc->ps.pps->height >> vs;
         const int width  = FFMIN(pic_width  - x, ctb_size_h);
         const int height = FFMIN(pic_height - y, ctb_size_v);
         const int src_stride = fc->frame->linesize[c_idx];
diff --git a/libavcodec/vvc/vvc_mvs.c b/libavcodec/vvc/vvc_mvs.c
index 668730dbbf..2ed05ad2a4 100644
--- a/libavcodec/vvc/vvc_mvs.c
+++ b/libavcodec/vvc/vvc_mvs.c
@@ -226,8 +226,8 @@ static int temporal_luma_motion_vector(const VVCLocalContext *lc,
 
     if (tab_mvf &&
         (cu->y0 >> sps->ctb_log2_size_y) == (y >> sps->ctb_log2_size_y) &&
-        y < fc->ps.sps->height &&
-        x < fc->ps.sps->width) {
+        y < fc->ps.pps->height &&
+        x < fc->ps.pps->width) {
         x                 &= ~7;
         y                 &= ~7;
         temp_col           = TAB_MVF(x, y);
diff --git a/libavcodec/vvc/vvc_ps.c b/libavcodec/vvc/vvc_ps.c
index 62ad389e97..affab8c5fc 100644
--- a/libavcodec/vvc/vvc_ps.c
+++ b/libavcodec/vvc/vvc_ps.c
@@ -177,9 +177,6 @@ static int sps_derive(VVCSPS *sps, void *log_ctx)
     int ret;
     const H266RawSPS *r = sps->r;
 
-    sps->width  = r->sps_pic_width_max_in_luma_samples;
-    sps->height = r->sps_pic_height_max_in_luma_samples;
-
     ret = sps_bit_depth(sps, log_ctx);
     if (ret < 0)
         return ret;
diff --git a/libavcodec/vvc/vvc_ps.h b/libavcodec/vvc/vvc_ps.h
index ede4e74009..3d3aa061f5 100644
--- a/libavcodec/vvc/vvc_ps.h
+++ b/libavcodec/vvc/vvc_ps.h
@@ -59,8 +59,6 @@ typedef struct VVCSPS {
     const H266RawSPS *r;                                            ///< RefStruct reference
 
     //derived values
-    uint16_t    width;
-    uint16_t    height;
     uint8_t     hshift[VVC_MAX_SAMPLE_ARRAYS];
     uint8_t     vshift[VVC_MAX_SAMPLE_ARRAYS];
     uint32_t    max_pic_order_cnt_lsb;                             ///< MaxPicOrderCntLsb
diff --git a/libavcodec/vvc/vvc_refs.c b/libavcodec/vvc/vvc_refs.c
index e1895d1cca..99f2dcf3ec 100644
--- a/libavcodec/vvc/vvc_refs.c
+++ b/libavcodec/vvc/vvc_refs.c
@@ -316,6 +316,7 @@ static void mark_ref(VVCFrame *frame, int flag)
 static VVCFrame *generate_missing_ref(VVCContext *s, VVCFrameContext *fc, int poc)
 {
     const VVCSPS *sps = fc->ps.sps;
+    const VVCPPS *pps = fc->ps.pps;
     VVCFrame *frame;
 
     frame = alloc_frame(s, fc);
@@ -329,10 +330,10 @@ static VVCFrame *generate_missing_ref(VVCContext *s, VVCFrameContext *fc, int po
                        frame->frame->buf[i]->size);
         } else {
             for (int i = 0; frame->frame->data[i]; i++)
-                for (int y = 0; y < (sps->height >> sps->vshift[i]); y++) {
+                for (int y = 0; y < (pps->height >> sps->vshift[i]); y++) {
                     uint8_t *dst = frame->frame->data[i] + y * frame->frame->linesize[i];
                     AV_WN16(dst, 1 << (sps->bit_depth - 1));
-                    av_memcpy_backptr(dst + 2, 2, 2*(sps->width >> sps->hshift[i]) - 2);
+                    av_memcpy_backptr(dst + 2, 2, 2*(pps->width >> sps->hshift[i]) - 2);
                 }
         }
     }
-- 
2.43.0



More information about the ffmpeg-devel mailing list