]> git.sesse.net Git - ffmpeg/commitdiff
avcodec/cbs_av1: infer segmentation parameters from reference frames
authorJames Almer <jamrial@gmail.com>
Tue, 20 Oct 2020 21:20:24 +0000 (18:20 -0300)
committerJames Almer <jamrial@gmail.com>
Wed, 28 Oct 2020 14:26:25 +0000 (11:26 -0300)
Partially implements setup_past_independence() and load_previous().
These ensures they are always set, even if the values were not coded
in the input bitstream and will not be coded in the output bitstream.

Reviewed-by: Mark Thompson <sw@jkqxz.net>
Signed-off-by: James Almer <jamrial@gmail.com>
libavcodec/cbs_av1.h
libavcodec/cbs_av1_syntax_template.c

index 97aeee979566f0802957741d7324560b1ba90eeb..a2d78e736f0ac677eeb011457b5311af9a991d9c 100644 (file)
@@ -416,6 +416,8 @@ typedef struct AV1ReferenceFrameState {
 
     int8_t  loop_filter_ref_deltas[AV1_TOTAL_REFS_PER_FRAME];
     int8_t  loop_filter_mode_deltas[2];
+    uint8_t feature_enabled[AV1_MAX_SEGMENTS][AV1_SEG_LVL_MAX];
+    int16_t feature_value[AV1_MAX_SEGMENTS][AV1_SEG_LVL_MAX];
 } AV1ReferenceFrameState;
 
 typedef struct CodedBitstreamAV1Context {
index 137da5a860fbf969c8133f0d9dee70e7c3124424..f351b1de244b1b42e901601dc366d8ba7f8cfeee 100644 (file)
@@ -743,8 +743,11 @@ static int FUNC(quantization_params)(CodedBitstreamContext *ctx, RWContext *rw,
 static int FUNC(segmentation_params)(CodedBitstreamContext *ctx, RWContext *rw,
                                      AV1RawFrameHeader *current)
 {
+    CodedBitstreamAV1Context  *priv = ctx->priv_data;
     static const uint8_t bits[AV1_SEG_LVL_MAX] = { 8, 6, 6, 6, 6, 3, 0, 0 };
     static const uint8_t sign[AV1_SEG_LVL_MAX] = { 1, 1, 1, 1, 1, 0, 0, 0 };
+    static const uint8_t default_feature_enabled[AV1_SEG_LVL_MAX] = { 0 };
+    static const int16_t default_feature_value[AV1_SEG_LVL_MAX] = { 0 };
     int i, j, err;
 
     flag(segmentation_enabled);
@@ -763,9 +766,22 @@ static int FUNC(segmentation_params)(CodedBitstreamContext *ctx, RWContext *rw,
             flag(segmentation_update_data);
         }
 
-        if (current->segmentation_update_data) {
-            for (i = 0; i < AV1_MAX_SEGMENTS; i++) {
-                for (j = 0; j < AV1_SEG_LVL_MAX; j++) {
+        for (i = 0; i < AV1_MAX_SEGMENTS; i++) {
+            const uint8_t *ref_feature_enabled;
+            const int16_t *ref_feature_value;
+
+            if (current->primary_ref_frame == AV1_PRIMARY_REF_NONE) {
+                ref_feature_enabled = default_feature_enabled;
+                ref_feature_value = default_feature_value;
+            } else {
+                ref_feature_enabled =
+                    priv->ref[current->ref_frame_idx[current->primary_ref_frame]].feature_enabled[i];
+                ref_feature_value =
+                    priv->ref[current->ref_frame_idx[current->primary_ref_frame]].feature_value[i];
+            }
+
+            for (j = 0; j < AV1_SEG_LVL_MAX; j++) {
+                if (current->segmentation_update_data) {
                     flags(feature_enabled[i][j], 2, i, j);
 
                     if (current->feature_enabled[i][j] && bits[j] > 0) {
@@ -776,6 +792,9 @@ static int FUNC(segmentation_params)(CodedBitstreamContext *ctx, RWContext *rw,
                     } else {
                         infer(feature_value[i][j], 0);
                     }
+                } else {
+                    infer(feature_enabled[i][j], ref_feature_enabled[j]);
+                    infer(feature_value[i][j], ref_feature_value[j]);
                 }
             }
         }
@@ -1645,6 +1664,10 @@ update_refs:
                    sizeof(current->loop_filter_ref_deltas));
             memcpy(priv->ref[i].loop_filter_mode_deltas, current->loop_filter_mode_deltas,
                    sizeof(current->loop_filter_mode_deltas));
+            memcpy(priv->ref[i].feature_enabled, current->feature_enabled,
+                   sizeof(current->feature_enabled));
+            memcpy(priv->ref[i].feature_value, current->feature_value,
+                   sizeof(current->feature_value));
         }
     }