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