Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
* [FFmpeg-devel] [PATCH] {cbs,vulkan}_vp9: Fix regression for vulkan_vp9 (PR #20209)
@ 2025-08-11  1:18 bcheng
  0 siblings, 0 replies; only message in thread
From: bcheng @ 2025-08-11  1:18 UTC (permalink / raw)
  To: ffmpeg-devel

PR #20209 opened by bcheng
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20209
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20209.patch

The previous change 26a2a76346 broke Vulkan decoding because the `VP9RawFrameHeader`s can no longer be updated.

I reworked vulkan_vp9 to use the existing parsed header in `VP9BitstreamHeader` for the segmentation and loop filter deltas (the only "stateful" values we need). The follow-up commit drops the now unused fields from the `CodedBitstreamVP9Context`.



From 1f9750f3a74e40d14a87e68c95e0d7cfd648a592 Mon Sep 17 00:00:00 2001
From: Benjamin Cheng <ben@bcheng.me>
Date: Sun, 10 Aug 2025 21:06:18 -0400
Subject: [PATCH 1/2] vulkan_vp9: Read values from VP9BitstreamHeader

The stateful values for loop filter and segmentation already exist, and
are parsed in VP9BitstreamHeader. This also preps for removal of the
previously added (in c0bf1382a) fields to CodedBitstreamVP9Context.

Fixes: 26a2a76346 ("cbs_vp9: Fix VP9 passthrough")
---
 libavcodec/vulkan_vp9.c | 32 +++++++++++++++++---------------
 1 file changed, 17 insertions(+), 15 deletions(-)

diff --git a/libavcodec/vulkan_vp9.c b/libavcodec/vulkan_vp9.c
index f8ce73dc90..0f7448ebb6 100644
--- a/libavcodec/vulkan_vp9.c
+++ b/libavcodec/vulkan_vp9.c
@@ -182,15 +182,14 @@ static int vk_vp9_start_frame(AVCodecContext          *avctx,
         .update_mode_delta = 0x0,
     };
 
-    for (int i = 0; i < 2; i++)
-        ap->loop_filter.update_mode_delta |= pic->frame_header->update_mode_delta[i];
-
     for (int i = 0; i < STD_VIDEO_VP9_MAX_REF_FRAMES; i++) {
-        ap->loop_filter.loop_filter_ref_deltas[i] = pic->frame_header->loop_filter_ref_deltas[i];
+        ap->loop_filter.loop_filter_ref_deltas[i] = s->h.lf_delta.ref[i]; /* Use stateful value */
         ap->loop_filter.update_ref_delta |= pic->frame_header->update_ref_delta[i];
     }
-    for (int i = 0; i < STD_VIDEO_VP9_LOOP_FILTER_ADJUSTMENTS; i++)
-        ap->loop_filter.loop_filter_mode_deltas[i] = pic->frame_header->loop_filter_mode_deltas[i];
+    for (int i = 0; i < STD_VIDEO_VP9_LOOP_FILTER_ADJUSTMENTS; i++) {
+        ap->loop_filter.loop_filter_mode_deltas[i] = s->h.lf_delta.mode[i]; /* Use stateful value */
+        ap->loop_filter.update_mode_delta |= pic->frame_header->update_mode_delta[i];
+    }
 
     ap->segmentation = (StdVideoVP9Segmentation) {
         .flags = (StdVideoVP9SegmentationFlags) {
@@ -201,18 +200,21 @@ static int vk_vp9_start_frame(AVCodecContext          *avctx,
         },
     };
 
+    /* Use the stateful value for segmentation also */
     for (int i = 0; i < STD_VIDEO_VP9_MAX_SEGMENTATION_TREE_PROBS; i++)
-        ap->segmentation.segmentation_tree_probs[i] = pic->frame_header->segmentation_tree_probs[i];
+        ap->segmentation.segmentation_tree_probs[i] = s->h.segmentation.prob[i];
     for (int i = 0; i < STD_VIDEO_VP9_MAX_SEGMENTATION_PRED_PROB; i++)
-        ap->segmentation.segmentation_pred_prob[i] = pic->frame_header->segmentation_pred_prob[i];
+        ap->segmentation.segmentation_pred_prob[i] = s->h.segmentation.pred_prob[i];
     for (int i = 0; i < STD_VIDEO_VP9_MAX_SEGMENTS; i++) {
-        ap->segmentation.FeatureEnabled[i] = 0x0;
-        for (int j = 0; j < STD_VIDEO_VP9_SEG_LVL_MAX; j++) {
-            ap->segmentation.FeatureEnabled[i] |= pic->frame_header->feature_enabled[i][j] << j;
-            ap->segmentation.FeatureData[i][j] = pic->frame_header->feature_sign[i][j] ?
-                                                 -pic->frame_header->feature_value[i][j] :
-                                                 +pic->frame_header->feature_value[i][j];
-        }
+        ap->segmentation.FeatureEnabled[i] =
+            (s->h.segmentation.feat[i].q_enabled    << 0) |
+            (s->h.segmentation.feat[i].lf_enabled   << 1) |
+            (s->h.segmentation.feat[i].ref_enabled  << 2) |
+            (s->h.segmentation.feat[i].skip_enabled << 3);
+        ap->segmentation.FeatureData[i][0] = s->h.segmentation.feat[i].q_val;
+        ap->segmentation.FeatureData[i][1] = s->h.segmentation.feat[i].lf_val;
+        ap->segmentation.FeatureData[i][2] = s->h.segmentation.feat[i].ref_val;
+        /* FeatureData[i][3] is for skip, which does not have a value */
     }
 
     ap->color_config = (StdVideoVP9ColorConfig) {
-- 
2.49.1


From 597ce26e0e51d861d3cb28f10a5288c497925f25 Mon Sep 17 00:00:00 2001
From: Benjamin Cheng <ben@bcheng.me>
Date: Sun, 10 Aug 2025 21:10:44 -0400
Subject: [PATCH 2/2] cbs_vp9: Drop unused fields from CBS context

These were previously added for vulkan_vp9 but are since no longer
required.

Fixes: 26a2a76346 ("cbs_vp9: Fix VP9 passthrough")
---
 libavcodec/cbs_vp9.h                 |  8 -----
 libavcodec/cbs_vp9_syntax_template.c | 54 ----------------------------
 2 files changed, 62 deletions(-)

diff --git a/libavcodec/cbs_vp9.h b/libavcodec/cbs_vp9.h
index 588765b873..af15eb4bac 100644
--- a/libavcodec/cbs_vp9.h
+++ b/libavcodec/cbs_vp9.h
@@ -206,14 +206,6 @@ typedef struct CodedBitstreamVP9Context {
     uint8_t subsampling_y;
     int bit_depth;
 
-    int8_t loop_filter_ref_deltas[VP9_MAX_REF_FRAMES];
-    int8_t loop_filter_mode_deltas[2];
-    uint8_t segmentation_tree_probs[7];
-    uint8_t segmentation_pred_prob[3];
-    uint8_t feature_enabled[VP9_MAX_SEGMENTS][VP9_SEG_LVL_MAX];
-    uint8_t feature_value[VP9_MAX_SEGMENTS][VP9_SEG_LVL_MAX];
-    uint8_t feature_sign[VP9_MAX_SEGMENTS][VP9_SEG_LVL_MAX];
-
     VP9ReferenceFrameState ref[VP9_NUM_REF_FRAMES];
 } CodedBitstreamVP9Context;
 
diff --git a/libavcodec/cbs_vp9_syntax_template.c b/libavcodec/cbs_vp9_syntax_template.c
index 9d01debb6d..2945165bcb 100644
--- a/libavcodec/cbs_vp9_syntax_template.c
+++ b/libavcodec/cbs_vp9_syntax_template.c
@@ -374,60 +374,6 @@ static int FUNC(uncompressed_header)(CodedBitstreamContext *ctx, RWContext *rw,
         }
     }
 
-    // Update top-level loop filter and segmentation state with changes
-    // from this frame.
-    if (current->frame_type == VP9_KEY_FRAME ||
-        current->intra_only                  ||
-        current->error_resilient_mode) {
-        // setup_past_independence() - fill with the initial values.
-
-        vp9->loop_filter_ref_deltas[VP9_INTRA_FRAME]  = 1;
-        vp9->loop_filter_ref_deltas[VP9_LAST_FRAME]   = 0;
-        vp9->loop_filter_ref_deltas[VP9_GOLDEN_FRAME] = -1;
-        vp9->loop_filter_ref_deltas[VP9_ALTREF_FRAME] = -1;
-
-        vp9->loop_filter_mode_deltas[0] = 0;
-        vp9->loop_filter_mode_deltas[1] = 0;
-
-        memset(vp9->feature_enabled, 0, sizeof(vp9->feature_enabled));
-        memset(vp9->feature_value,   0, sizeof(vp9->feature_value));
-        memset(vp9->feature_sign,    0, sizeof(vp9->feature_sign));
-
-    } else {
-        // Modify previous state based on updates in this frame.
-
-        if (current->loop_filter_delta_update) {
-            for (i = 0; i < 4; i++) {
-                if (current->update_ref_delta[i])
-                    vp9->loop_filter_ref_deltas[i] =
-                        current->loop_filter_ref_deltas[i];
-            }
-            for (i = 0; i < 2; i++) {
-                if (current->update_mode_delta[i])
-                    vp9->loop_filter_mode_deltas[i] =
-                        current->loop_filter_mode_deltas[i];
-            }
-        }
-
-        if (current->segmentation_update_data) {
-            memcpy(vp9->feature_enabled, current->feature_enabled,
-                   sizeof(vp9->feature_enabled));
-            memcpy(vp9->feature_value,   current->feature_value,
-                   sizeof(vp9->feature_value));
-            memcpy(vp9->feature_sign,    current->feature_sign,
-                   sizeof(vp9->feature_sign));
-
-            if (current->segmentation_update_map) {
-                memcpy(vp9->segmentation_tree_probs,
-                       current->segmentation_tree_probs,
-                       sizeof(vp9->segmentation_tree_probs));
-                memcpy(vp9->segmentation_pred_prob,
-                       current->segmentation_pred_prob,
-                       sizeof(vp9->segmentation_pred_prob));
-            }
-        }
-    }
-
     av_log(ctx->log_ctx, AV_LOG_DEBUG, "Frame:  size %dx%d  "
            "subsample %dx%d  bit_depth %d  tiles %dx%d.\n",
            vp9->frame_width, vp9->frame_height,
-- 
2.49.1

_______________________________________________
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".

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2025-08-11  1:18 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-08-11  1:18 [FFmpeg-devel] [PATCH] {cbs,vulkan}_vp9: Fix regression for vulkan_vp9 (PR #20209) bcheng

Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
		ffmpegdev@gitmailbox.com
	public-inbox-index ffmpegdev

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git