From 26a2a76346457e33408ca9ef5453b1d14cca2504 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 9 Aug 2025 09:06:13 +0100 Subject: [PATCH] cbs_vp9: Fix VP9 passthrough Don't overwrite the bitstream values when updating the top-level loop filter and segmentation state, instead do the update separately at the end of the frame parsing. This also reverts the change to the passthrough tests which made them have output not matching the input. --- libavcodec/cbs_vp9_syntax_template.c | 87 ++++++++++++------- tests/ref/fate/cbs-vp9-vp90-2-03-deltaq | 2 +- tests/ref/fate/cbs-vp9-vp90-2-05-resize | 2 +- tests/ref/fate/cbs-vp9-vp90-2-06-bilinear | 2 +- tests/ref/fate/cbs-vp9-vp90-2-09-lf_deltas | 2 +- .../cbs-vp9-vp90-2-10-show-existing-frame | 2 +- .../cbs-vp9-vp90-2-10-show-existing-frame2 | 2 +- .../fate/cbs-vp9-vp90-2-segmentation-aq-akiyo | 2 +- .../fate/cbs-vp9-vp90-2-segmentation-sf-akiyo | 2 +- .../ref/fate/cbs-vp9-vp90-2-tiling-pedestrian | 2 +- tests/ref/fate/cbs-vp9-vp91-2-04-yuv440 | 2 +- tests/ref/fate/cbs-vp9-vp91-2-04-yuv444 | 2 +- tests/ref/fate/cbs-vp9-vp92-2-20-10bit-yuv420 | 2 +- tests/ref/fate/cbs-vp9-vp93-2-20-10bit-yuv422 | 2 +- tests/ref/fate/cbs-vp9-vp93-2-20-12bit-yuv444 | 2 +- 15 files changed, 72 insertions(+), 43 deletions(-) diff --git a/libavcodec/cbs_vp9_syntax_template.c b/libavcodec/cbs_vp9_syntax_template.c index 9c4f09eac9..9d01debb6d 100644 --- a/libavcodec/cbs_vp9_syntax_template.c +++ b/libavcodec/cbs_vp9_syntax_template.c @@ -152,7 +152,6 @@ static int FUNC(interpolation_filter)(CodedBitstreamContext *ctx, RWContext *rw, static int FUNC(loop_filter_params)(CodedBitstreamContext *ctx, RWContext *rw, VP9RawFrameHeader *current) { - CodedBitstreamVP9Context *vp9 = ctx->priv_data; int err, i; f(6, loop_filter_level); @@ -160,8 +159,6 @@ static int FUNC(loop_filter_params)(CodedBitstreamContext *ctx, RWContext *rw, f(1, loop_filter_delta_enabled); if (current->loop_filter_delta_enabled) { - memcpy(current->loop_filter_ref_deltas, vp9->loop_filter_ref_deltas, sizeof(vp9->loop_filter_ref_deltas)); - memcpy(current->loop_filter_mode_deltas, vp9->loop_filter_mode_deltas, sizeof(vp9->loop_filter_mode_deltas)); f(1, loop_filter_delta_update); if (current->loop_filter_delta_update) { for (i = 0; i < VP9_MAX_REF_FRAMES; i++) { @@ -174,9 +171,9 @@ static int FUNC(loop_filter_params)(CodedBitstreamContext *ctx, RWContext *rw, if (current->update_mode_delta[i]) ss(6, loop_filter_mode_deltas[i], 1, i); } - memcpy(vp9->loop_filter_ref_deltas, current->loop_filter_ref_deltas, sizeof(vp9->loop_filter_ref_deltas)); - memcpy(vp9->loop_filter_mode_deltas, current->loop_filter_mode_deltas, sizeof(vp9->loop_filter_mode_deltas)); } + } else { + infer(loop_filter_delta_update, 0); } return 0; @@ -201,18 +198,11 @@ static int FUNC(segmentation_params)(CodedBitstreamContext *ctx, RWContext *rw, { static const uint8_t segmentation_feature_bits[VP9_SEG_LVL_MAX] = { 8, 6, 2, 0 }; static const uint8_t segmentation_feature_signed[VP9_SEG_LVL_MAX] = { 1, 1, 0, 0 }; - - CodedBitstreamVP9Context *vp9 = ctx->priv_data; int err, i, j; f(1, segmentation_enabled); if (current->segmentation_enabled) { - memcpy(current->segmentation_tree_probs, vp9->segmentation_tree_probs, sizeof(vp9->segmentation_tree_probs)); - memcpy(current->segmentation_pred_prob, vp9->segmentation_pred_prob, sizeof(vp9->segmentation_pred_prob)); - memcpy(current->feature_enabled, vp9->feature_enabled, sizeof(vp9->feature_enabled)); - memcpy(current->feature_value, vp9->feature_value, sizeof(vp9->feature_value)); - memcpy(current->feature_sign, vp9->feature_sign, sizeof(vp9->feature_sign)); f(1, segmentation_update_map); if (current->segmentation_update_map) { for (i = 0; i < 7; i++) @@ -224,8 +214,6 @@ static int FUNC(segmentation_params)(CodedBitstreamContext *ctx, RWContext *rw, else infer(segmentation_pred_prob[i], 255); } - 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)); } f(1, segmentation_update_data); @@ -248,10 +236,9 @@ static int FUNC(segmentation_params)(CodedBitstreamContext *ctx, RWContext *rw, } } } - 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)); } + } else { + infer(segmentation_update_data, 0); } return 0; @@ -368,18 +355,6 @@ static int FUNC(uncompressed_header)(CodedBitstreamContext *ctx, RWContext *rw, f(2, frame_context_idx); - if (current->frame_type == VP9_KEY_FRAME || current->error_resilient_mode || current->intra_only) { - infer(update_ref_delta[0], 1); - infer(update_ref_delta[1], 0); - infer(update_ref_delta[2], -1); - infer(update_ref_delta[3], -1); - infer(loop_filter_mode_deltas[0], 0); - infer(loop_filter_mode_deltas[1], 0); - memset(vp9->feature_enabled, 0, sizeof(current->feature_enabled)); - memset(vp9->feature_value, 0, sizeof(current->feature_value)); - memset(vp9->feature_sign, 0, sizeof(current->feature_sign)); - } - CHECK(FUNC(loop_filter_params)(ctx, rw, current)); CHECK(FUNC(quantization_params)(ctx, rw, current)); CHECK(FUNC(segmentation_params)(ctx, rw, current)); @@ -399,6 +374,60 @@ 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, diff --git a/tests/ref/fate/cbs-vp9-vp90-2-03-deltaq b/tests/ref/fate/cbs-vp9-vp90-2-03-deltaq index addf9a942a..f621d7a480 100644 --- a/tests/ref/fate/cbs-vp9-vp90-2-03-deltaq +++ b/tests/ref/fate/cbs-vp9-vp90-2-03-deltaq @@ -1 +1 @@ -0f43cdcbdc97ea6651c56540d97610e5 +fe62460fe28202e0666e628afd8602ca diff --git a/tests/ref/fate/cbs-vp9-vp90-2-05-resize b/tests/ref/fate/cbs-vp9-vp90-2-05-resize index 965bbb272e..8f036bba81 100644 --- a/tests/ref/fate/cbs-vp9-vp90-2-05-resize +++ b/tests/ref/fate/cbs-vp9-vp90-2-05-resize @@ -1 +1 @@ -af456bb18c4f5e6fb83c559769ce1b07 +6838422ebb45df353a2bad62b9aff8e9 diff --git a/tests/ref/fate/cbs-vp9-vp90-2-06-bilinear b/tests/ref/fate/cbs-vp9-vp90-2-06-bilinear index ffa375790b..9359e21e40 100644 --- a/tests/ref/fate/cbs-vp9-vp90-2-06-bilinear +++ b/tests/ref/fate/cbs-vp9-vp90-2-06-bilinear @@ -1 +1 @@ -af98321cd43a36f065f8c728e22f2c06 +179e228004c396a301c89f34b6c72f68 diff --git a/tests/ref/fate/cbs-vp9-vp90-2-09-lf_deltas b/tests/ref/fate/cbs-vp9-vp90-2-09-lf_deltas index 313a531945..5b21675c76 100644 --- a/tests/ref/fate/cbs-vp9-vp90-2-09-lf_deltas +++ b/tests/ref/fate/cbs-vp9-vp90-2-09-lf_deltas @@ -1 +1 @@ -8b4ce818cde9621481b6bf7997b544b8 +1d1f0768c547461ae2abef57f0aabc24 diff --git a/tests/ref/fate/cbs-vp9-vp90-2-10-show-existing-frame b/tests/ref/fate/cbs-vp9-vp90-2-10-show-existing-frame index d87d1b7185..19b7a78dd8 100644 --- a/tests/ref/fate/cbs-vp9-vp90-2-10-show-existing-frame +++ b/tests/ref/fate/cbs-vp9-vp90-2-10-show-existing-frame @@ -1 +1 @@ -ea65b698e86322709257caf9038da40a +13fa042ee1b4079c227a5c5c96e2db38 diff --git a/tests/ref/fate/cbs-vp9-vp90-2-10-show-existing-frame2 b/tests/ref/fate/cbs-vp9-vp90-2-10-show-existing-frame2 index fa8d684e42..e7bf2a078d 100644 --- a/tests/ref/fate/cbs-vp9-vp90-2-10-show-existing-frame2 +++ b/tests/ref/fate/cbs-vp9-vp90-2-10-show-existing-frame2 @@ -1 +1 @@ -c1047aeeb593f2f87818d9bd19cb12f2 +2ab7c95e4637fb6a15efd8c0a8d6af98 diff --git a/tests/ref/fate/cbs-vp9-vp90-2-segmentation-aq-akiyo b/tests/ref/fate/cbs-vp9-vp90-2-segmentation-aq-akiyo index f2b03031a4..f30889dbdc 100644 --- a/tests/ref/fate/cbs-vp9-vp90-2-segmentation-aq-akiyo +++ b/tests/ref/fate/cbs-vp9-vp90-2-segmentation-aq-akiyo @@ -1 +1 @@ -cb14fde4f0f99d6e962fb109d3db36ee +b5be66a6a8792f7aac090beb9f3b4555 diff --git a/tests/ref/fate/cbs-vp9-vp90-2-segmentation-sf-akiyo b/tests/ref/fate/cbs-vp9-vp90-2-segmentation-sf-akiyo index a7d074c28c..dca77f2113 100644 --- a/tests/ref/fate/cbs-vp9-vp90-2-segmentation-sf-akiyo +++ b/tests/ref/fate/cbs-vp9-vp90-2-segmentation-sf-akiyo @@ -1 +1 @@ -0f1cfba95edb2446689547fc012f741b +7bde6532fc682bfa3f5170cf9d607865 diff --git a/tests/ref/fate/cbs-vp9-vp90-2-tiling-pedestrian b/tests/ref/fate/cbs-vp9-vp90-2-tiling-pedestrian index d029f01530..0aa3cc8ce6 100644 --- a/tests/ref/fate/cbs-vp9-vp90-2-tiling-pedestrian +++ b/tests/ref/fate/cbs-vp9-vp90-2-tiling-pedestrian @@ -1 +1 @@ -db40458891febf9f007c98e735e02ab9 +1e40e8b48e4682e8b8004b9e0e60a5b6 diff --git a/tests/ref/fate/cbs-vp9-vp91-2-04-yuv440 b/tests/ref/fate/cbs-vp9-vp91-2-04-yuv440 index fe81cc0b39..947e1229eb 100644 --- a/tests/ref/fate/cbs-vp9-vp91-2-04-yuv440 +++ b/tests/ref/fate/cbs-vp9-vp91-2-04-yuv440 @@ -1 +1 @@ -855cffb78a063ad0dfc432ae593974a2 +9bb416c0304a13c4f66c56aef8431cd4 diff --git a/tests/ref/fate/cbs-vp9-vp91-2-04-yuv444 b/tests/ref/fate/cbs-vp9-vp91-2-04-yuv444 index 1b7a1acc6f..bf251138ed 100644 --- a/tests/ref/fate/cbs-vp9-vp91-2-04-yuv444 +++ b/tests/ref/fate/cbs-vp9-vp91-2-04-yuv444 @@ -1 +1 @@ -8f6c44c4098915261e7708ab270877ff +3a7ed001d30f96d4888f5ca16e6263ce diff --git a/tests/ref/fate/cbs-vp9-vp92-2-20-10bit-yuv420 b/tests/ref/fate/cbs-vp9-vp92-2-20-10bit-yuv420 index 23d980ea0f..2cad8b947c 100644 --- a/tests/ref/fate/cbs-vp9-vp92-2-20-10bit-yuv420 +++ b/tests/ref/fate/cbs-vp9-vp92-2-20-10bit-yuv420 @@ -1 +1 @@ -0ed4ec02fd72c0b594d74c5cbd7e252f +7315bb7b55693a87c350b48cd2ee9811 diff --git a/tests/ref/fate/cbs-vp9-vp93-2-20-10bit-yuv422 b/tests/ref/fate/cbs-vp9-vp93-2-20-10bit-yuv422 index 0a77ebbd58..bb1c0f7ea7 100644 --- a/tests/ref/fate/cbs-vp9-vp93-2-20-10bit-yuv422 +++ b/tests/ref/fate/cbs-vp9-vp93-2-20-10bit-yuv422 @@ -1 +1 @@ -1e8d7e1bd62a04bf47270c72a1c55bb7 +1a7b5bf86bf0bbef10c9a1b2c799b276 diff --git a/tests/ref/fate/cbs-vp9-vp93-2-20-12bit-yuv444 b/tests/ref/fate/cbs-vp9-vp93-2-20-12bit-yuv444 index 9705dfeb50..9b7b358d04 100644 --- a/tests/ref/fate/cbs-vp9-vp93-2-20-12bit-yuv444 +++ b/tests/ref/fate/cbs-vp9-vp93-2-20-12bit-yuv444 @@ -1 +1 @@ -c2ca28679265c1c86d4a7ef60cc061ff +9b7a0b7fc081542d9be1074b23054861