CWG-F311: Call qm_params after segmentation_params

Note: The functions mentioned in the commit message are all syntax
structures in the draft AV2 spec.

Move the last part of quantization_params() to a new syntax structure
qm_params(). In uncompressed_header(), call qm_params() after
segmentation_params(). This allows qm_params() to check the
segmentation_enabled variable.

Related to https://gitlab.com/AOMediaCodec/avm/-/issues/761.

Experiment macro: CONFIG_F311_QM_PARAMS

Test:
```
test_libaom --gtest_filter=*FrameMultiQmatrixTest*
test_libaom --gtest_filter=*QMTest*
```

STATS_CHANGED
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c
index ac76c8d..1773302 100644
--- a/av1/decoder/decodeframe.c
+++ b/av1/decoder/decodeframe.c
@@ -3596,12 +3596,28 @@
     quant_params->v_dc_delta_q = 0;
     quant_params->v_ac_delta_q = 0;
   }
+}
+
+static AOM_INLINE void setup_qm_params(CommonQuantParams *quant_params,
+#if CONFIG_F311_QM_PARAMS
+                                       bool segmentation_enabled,
+#endif  // CONFIG_F311_QM_PARAMS
+                                       int num_planes, bool separate_uv_delta_q,
+                                       struct aom_read_bit_buffer *rb) {
   quant_params->using_qmatrix = aom_rb_read_bit(rb);
 #if CONFIG_QM_DEBUG
   printf("[DEC-FRM] using_qmatrix: %d\n", quant_params->using_qmatrix);
 #endif
   if (quant_params->using_qmatrix) {
+#if CONFIG_F311_QM_PARAMS
+    if (segmentation_enabled) {
+      quant_params->pic_qm_num = aom_rb_read_literal(rb, 2) + 1;
+    } else {
+      quant_params->pic_qm_num = 1;
+    }
+#else
     quant_params->pic_qm_num = aom_rb_read_literal(rb, 2) + 1;
+#endif  // CONFIG_F311_QM_PARAMS
 #if CONFIG_QM_DEBUG
     printf("[DEC-FRM] pic_qm_num: %d\n", quant_params->pic_qm_num);
 #endif
@@ -3618,7 +3634,7 @@
           quant_params->qm_v[i] = quant_params->qm_y[i];
         } else {
           quant_params->qm_u[i] = aom_rb_read_literal(rb, QM_LEVEL_BITS);
-          if (!seq_params->separate_uv_delta_q) {
+          if (!separate_uv_delta_q) {
             quant_params->qm_v[i] = quant_params->qm_u[i];
           } else {
             quant_params->qm_v[i] = aom_rb_read_literal(rb, QM_LEVEL_BITS);
@@ -8369,6 +8385,10 @@
 
   CommonQuantParams *const quant_params = &cm->quant_params;
   setup_quantization(quant_params, av1_num_planes(cm), &cm->seq_params, rb);
+#if !CONFIG_F311_QM_PARAMS
+  setup_qm_params(quant_params, av1_num_planes(cm),
+                  cm->seq_params.separate_uv_delta_q, rb);
+#endif  // !CONFIG_F311_QM_PARAMS
   cm->cur_frame->base_qindex = quant_params->base_qindex;
   cm->cur_frame->u_ac_delta_q = quant_params->u_ac_delta_q;
   cm->cur_frame->v_ac_delta_q = quant_params->v_ac_delta_q;
@@ -8391,6 +8411,11 @@
 
   setup_segmentation(cm, rb);
 
+#if CONFIG_F311_QM_PARAMS
+  setup_qm_params(quant_params, cm->seg.enabled, av1_num_planes(cm),
+                  cm->seq_params.separate_uv_delta_q, rb);
+#endif  // CONFIG_F311_QM_PARAMS
+
   cm->delta_q_info.delta_q_res = 1;
   cm->delta_q_info.delta_lf_res = 1;
   cm->delta_q_info.delta_lf_present_flag = 0;
@@ -8413,12 +8438,14 @@
 
   xd->cur_frame_force_integer_mv = features->cur_frame_force_integer_mv;
 
+#if !CONFIG_F311_QM_PARAMS
   if (!cm->seg.enabled && quant_params->using_qmatrix &&
       quant_params->qm_index_bits > 0) {
     aom_internal_error(&cm->error, AOM_CODEC_CORRUPT_FRAME,
                        "The frame does not use segmentation but uses "
                        "per-segment quantizer matrices");
   }
+#endif  // !CONFIG_F311_QM_PARAMS
 #if CONFIG_EXT_SEG
   const int max_seg_num =
       cm->seg.enable_ext_seg ? MAX_SEGMENTS : MAX_SEGMENTS_8;
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index 1965ddd..71e4cb4 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -4761,12 +4761,29 @@
     assert(quant_params->u_ac_delta_q == 0);
     assert(quant_params->v_ac_delta_q == 0);
   }
+}
+
+static AOM_INLINE void encode_qm_params(AV1_COMMON *cm,
+                                        struct aom_write_bit_buffer *wb) {
+  const CommonQuantParams *quant_params = &cm->quant_params;
   aom_wb_write_bit(wb, quant_params->using_qmatrix);
   if (quant_params->using_qmatrix) {
+#if CONFIG_F311_QM_PARAMS
+    if (cm->seg.enabled) {
+      aom_wb_write_literal(wb, quant_params->pic_qm_num - 1, 2);
+    } else if (quant_params->pic_qm_num > 1) {
+      aom_internal_error(&cm->error, AOM_CODEC_ERROR,
+                         "The frame does not use segmentation but uses "
+                         "per-segment quantizer matrices");
+    }
+#else
     aom_wb_write_literal(wb, quant_params->pic_qm_num - 1, 2);
+#endif  // CONFIG_F311_QM_PARAMS
 #if CONFIG_QM_DEBUG
     printf("[ENC-FRM] pic_qm_num: %d\n", quant_params->pic_qm_num);
 #endif
+    const int num_planes = av1_num_planes(cm);
+    bool separate_uv_delta_q = cm->seq_params.separate_uv_delta_q;
     for (uint8_t i = 0; i < quant_params->pic_qm_num; i++) {
       aom_wb_write_literal(wb, quant_params->qm_y[i], QM_LEVEL_BITS);
       if (num_planes > 1) {
@@ -4799,6 +4816,7 @@
     }
   }
 }
+
 #if CONFIG_BRU
 static AOM_INLINE void encode_bru_active_info(AV1_COMP *cpi,
                                               struct aom_write_bit_buffer *wb) {
@@ -4815,6 +4833,7 @@
   return;
 }
 #endif  // CONFIG_BRU
+
 static AOM_INLINE void encode_segmentation(AV1_COMMON *cm, MACROBLOCKD *xd,
                                            struct aom_write_bit_buffer *wb) {
   int i, j;
@@ -6599,7 +6618,13 @@
   write_tile_info(cm, saved_wb, wb);
 
   encode_quantization(quant_params, av1_num_planes(cm), &cm->seq_params, wb);
+#if !CONFIG_F311_QM_PARAMS
+  encode_qm_params(cm, wb);
+#endif  // !CONFIG_F311_QM_PARAMS
   encode_segmentation(cm, xd, wb);
+#if CONFIG_F311_QM_PARAMS
+  encode_qm_params(cm, wb);
+#endif  // CONFIG_F311_QM_PARAMS
 
   const DeltaQInfo *const delta_q_info = &cm->delta_q_info;
   if (delta_q_info->delta_q_present_flag) assert(quant_params->base_qindex > 0);
@@ -6624,11 +6649,13 @@
 
   if (quant_params->using_qmatrix) {
     const struct segmentation *seg = &cm->seg;
+#if !CONFIG_F311_QM_PARAMS
     if (!seg->enabled && quant_params->qm_index_bits > 0) {
       aom_internal_error(&cm->error, AOM_CODEC_ERROR,
                          "The frame does not use segmentation but uses "
                          "per-segment quantizer matrices");
     }
+#endif  // !CONFIG_F311_QM_PARAMS
 #if CONFIG_EXT_SEG
     const int max_seg_num = seg->enable_ext_seg ? MAX_SEGMENTS : MAX_SEGMENTS_8;
 #else   // CONFIG_EXT_SEG
diff --git a/build/cmake/aom_config_defaults.cmake b/build/cmake/aom_config_defaults.cmake
index 1b6de09..dc21ea8 100644
--- a/build/cmake/aom_config_defaults.cmake
+++ b/build/cmake/aom_config_defaults.cmake
@@ -434,6 +434,11 @@
   1
   "Alignment of ref picture to be integer multiples of 8 for loop filter and inter prediction"
 )
+set_aom_config_var(
+  CONFIG_F311_QM_PARAMS
+  1
+  "Call qm_params() after segmentation_params() in uncompressed_header(), CWG-F311."
+)
 set_aom_config_var(CONFIG_GDF 1 "Enable guided detail filter.")
 set_aom_config_var(CONFIG_GDF_IMPROVEMENT 1
                    "Enable guided detail filter improvement.")