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