From 8c9445896fa2980196143a44294201e26b786932 Mon Sep 17 00:00:00 2001 From: David Rosca Date: Mon, 12 Feb 2024 20:45:33 +0100 Subject: [PATCH] frontends/va: Separate QP for I/P/B frames For H264/HEVC this needs to calculate init_qp + slice_qp_delta. Reviewed-by: Ruijing Dong Part-of: --- src/gallium/frontends/va/picture_av1_enc.c | 27 ++++++++++++--------- src/gallium/frontends/va/picture_h264_enc.c | 10 +++++--- src/gallium/frontends/va/picture_hevc_enc.c | 22 ++++++++++++++--- src/gallium/include/pipe/p_video_state.h | 3 +++ 4 files changed, 45 insertions(+), 17 deletions(-) diff --git a/src/gallium/frontends/va/picture_av1_enc.c b/src/gallium/frontends/va/picture_av1_enc.c index 3eb119738aa..a669625104b 100644 --- a/src/gallium/frontends/va/picture_av1_enc.c +++ b/src/gallium/frontends/va/picture_av1_enc.c @@ -221,17 +221,6 @@ VAStatus vlVaHandleVAEncPictureParameterBufferTypeAV1(vlVaDriver *drv, vlVaConte PIPE_USAGE_STAGING, coded_buf->size); context->coded_buf = coded_buf; - for (i = 0; i < ARRAY_SIZE(context->desc.av1enc.rc); i++) { - context->desc.av1enc.rc[i].qp = av1->base_qindex ? av1->base_qindex : 60; - /* Distinguishes from the default params set for these values and app specific params passed down */ - context->desc.av1enc.rc[i].app_requested_initial_qp = (av1->base_qindex != 0); - context->desc.av1enc.rc[i].min_qp = av1->min_base_qindex ? av1->min_base_qindex : 1; - context->desc.av1enc.rc[i].max_qp = av1->max_base_qindex ? av1->max_base_qindex : 255; - /* Distinguishes from the default params set for these values and app specific params passed down */ - context->desc.av1enc.rc[i].app_requested_qp_range = - ((context->desc.av1enc.rc[i].max_qp != AV1_MAX_QP_DEFAULT) || (context->desc.av1enc.rc[i].min_qp != AV1_MIN_QP_DEFAULT)); - } - /* these frame types will need to be seen as force type */ switch(av1->picture_flags.bits.frame_type) { @@ -249,6 +238,22 @@ VAStatus vlVaHandleVAEncPictureParameterBufferTypeAV1(vlVaDriver *drv, vlVaConte break; }; + for (i = 0; i < ARRAY_SIZE(context->desc.av1enc.rc); i++) { + unsigned qindex = av1->base_qindex ? av1->base_qindex : 60; + if (context->desc.av1enc.frame_type == PIPE_AV1_ENC_FRAME_TYPE_KEY || + context->desc.av1enc.frame_type == PIPE_AV1_ENC_FRAME_TYPE_INTRA_ONLY) + context->desc.av1enc.rc[i].qp = qindex; + else + context->desc.av1enc.rc[i].qp_inter = qindex; + /* Distinguishes from the default params set for these values and app specific params passed down */ + context->desc.av1enc.rc[i].app_requested_initial_qp = (av1->base_qindex != 0); + context->desc.av1enc.rc[i].min_qp = av1->min_base_qindex ? av1->min_base_qindex : 1; + context->desc.av1enc.rc[i].max_qp = av1->max_base_qindex ? av1->max_base_qindex : 255; + /* Distinguishes from the default params set for these values and app specific params passed down */ + context->desc.av1enc.rc[i].app_requested_qp_range = + ((context->desc.av1enc.rc[i].max_qp != AV1_MAX_QP_DEFAULT) || (context->desc.av1enc.rc[i].min_qp != AV1_MIN_QP_DEFAULT)); + } + if (context->desc.av1enc.frame_type == FRAME_TYPE_KEY_FRAME) context->desc.av1enc.last_key_frame_num = context->desc.av1enc.frame_num; diff --git a/src/gallium/frontends/va/picture_h264_enc.c b/src/gallium/frontends/va/picture_h264_enc.c index b1cd2a94762..e381d4884d6 100644 --- a/src/gallium/frontends/va/picture_h264_enc.c +++ b/src/gallium/frontends/va/picture_h264_enc.c @@ -84,9 +84,7 @@ vlVaHandleVAEncPictureParameterBufferTypeH264(vlVaDriver *drv, vlVaContext *cont context->desc.h264enc.num_slice_descriptors = 0; memset(&context->desc.h264enc.slices_descriptors, 0, sizeof(context->desc.h264enc.slices_descriptors)); - context->desc.h264enc.quant_i_frames = h264->pic_init_qp; - context->desc.h264enc.quant_b_frames = h264->pic_init_qp; - context->desc.h264enc.quant_p_frames = h264->pic_init_qp; + context->desc.h264enc.init_qp = h264->pic_init_qp; context->desc.h264enc.gop_cnt++; if (context->desc.h264enc.gop_cnt == context->desc.h264enc.gop_size) context->desc.h264enc.gop_cnt = 0; @@ -109,6 +107,7 @@ VAStatus vlVaHandleVAEncSliceParameterBufferTypeH264(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) { VAEncSliceParameterBufferH264 *h264; + unsigned slice_qp; h264 = buf->data; memset(&context->desc.h264enc.ref_idx_l0_list, VA_INVALID_ID, sizeof(context->desc.h264enc.ref_idx_l0_list)); @@ -144,12 +143,16 @@ vlVaHandleVAEncSliceParameterBufferTypeH264(vlVaDriver *drv, vlVaContext *contex slice_descriptor.macroblock_address = h264->macroblock_address; slice_descriptor.num_macroblocks = h264->num_macroblocks; + slice_qp = context->desc.h264enc.init_qp + h264->slice_qp_delta; + if ((h264->slice_type == 1) || (h264->slice_type == 6)) { context->desc.h264enc.picture_type = PIPE_H2645_ENC_PICTURE_TYPE_B; slice_descriptor.slice_type = PIPE_H264_SLICE_TYPE_B; + context->desc.h264enc.quant_b_frames = slice_qp; } else if ((h264->slice_type == 0) || (h264->slice_type == 5)) { context->desc.h264enc.picture_type = PIPE_H2645_ENC_PICTURE_TYPE_P; slice_descriptor.slice_type = PIPE_H264_SLICE_TYPE_P; + context->desc.h264enc.quant_p_frames = slice_qp; } else if ((h264->slice_type == 2) || (h264->slice_type == 7)) { if (context->desc.h264enc.picture_type == PIPE_H2645_ENC_PICTURE_TYPE_IDR) { if (slice_descriptor.macroblock_address == 0) { @@ -161,6 +164,7 @@ vlVaHandleVAEncSliceParameterBufferTypeH264(vlVaDriver *drv, vlVaContext *contex context->desc.h264enc.picture_type = PIPE_H2645_ENC_PICTURE_TYPE_I; slice_descriptor.slice_type = PIPE_H264_SLICE_TYPE_I; } + context->desc.h264enc.quant_i_frames = slice_qp; } else { context->desc.h264enc.picture_type = PIPE_H2645_ENC_PICTURE_TYPE_SKIP; } diff --git a/src/gallium/frontends/va/picture_hevc_enc.c b/src/gallium/frontends/va/picture_hevc_enc.c index 871832eb7fe..002c5ff3029 100644 --- a/src/gallium/frontends/va/picture_hevc_enc.c +++ b/src/gallium/frontends/va/picture_hevc_enc.c @@ -63,9 +63,7 @@ vlVaHandleVAEncPictureParameterBufferTypeHEVC(vlVaDriver *drv, vlVaContext *cont context->coded_buf = coded_buf; context->desc.h265enc.pic.log2_parallel_merge_level_minus2 = h265->log2_parallel_merge_level_minus2; context->desc.h265enc.pic.nal_unit_type = h265->nal_unit_type; - context->desc.h265enc.rc.quant_i_frames = h265->pic_init_qp; - context->desc.h265enc.rc.quant_p_frames = h265->pic_init_qp; - context->desc.h265enc.rc.quant_b_frames = h265->pic_init_qp; + context->desc.h265enc.rc.init_qp = h265->pic_init_qp; switch(h265->pic_fields.bits.coding_type) { case 1: @@ -106,6 +104,7 @@ VAStatus vlVaHandleVAEncSliceParameterBufferTypeHEVC(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) { VAEncSliceParameterBufferHEVC *h265; + unsigned slice_qp; h265 = buf->data; memset(&context->desc.h265enc.ref_idx_l0_list, VA_INVALID_ID, sizeof(context->desc.h265enc.ref_idx_l0_list)); @@ -136,6 +135,23 @@ vlVaHandleVAEncSliceParameterBufferTypeHEVC(vlVaDriver *drv, vlVaContext *contex context->desc.h265enc.slice.slice_deblocking_filter_disabled_flag = h265->slice_fields.bits.slice_deblocking_filter_disabled_flag; context->desc.h265enc.slice.slice_loop_filter_across_slices_enabled_flag = h265->slice_fields.bits.slice_loop_filter_across_slices_enabled_flag; + slice_qp = context->desc.h265enc.rc.init_qp + h265->slice_qp_delta; + + switch (context->desc.h265enc.picture_type) { + case PIPE_H2645_ENC_PICTURE_TYPE_I: + case PIPE_H2645_ENC_PICTURE_TYPE_IDR: + context->desc.h265enc.rc.quant_i_frames = slice_qp; + break; + case PIPE_H2645_ENC_PICTURE_TYPE_P: + context->desc.h265enc.rc.quant_p_frames = slice_qp; + break; + case PIPE_H2645_ENC_PICTURE_TYPE_B: + context->desc.h265enc.rc.quant_b_frames = slice_qp; + break; + default: + break; + } + /* Handle the slice control parameters */ struct h265_slice_descriptor slice_descriptor; memset(&slice_descriptor, 0, sizeof(slice_descriptor)); diff --git a/src/gallium/include/pipe/p_video_state.h b/src/gallium/include/pipe/p_video_state.h index 9f225494260..a0319a532a8 100644 --- a/src/gallium/include/pipe/p_video_state.h +++ b/src/gallium/include/pipe/p_video_state.h @@ -631,6 +631,7 @@ struct pipe_h264_enc_picture_desc unsigned intra_idr_period; unsigned ip_period; + unsigned init_qp; unsigned quant_i_frames; unsigned quant_p_frames; unsigned quant_b_frames; @@ -814,6 +815,7 @@ struct pipe_h265_enc_rate_control unsigned peak_bitrate; unsigned frame_rate_num; unsigned frame_rate_den; + unsigned init_qp; unsigned quant_i_frames; unsigned quant_p_frames; unsigned quant_b_frames; @@ -892,6 +894,7 @@ struct pipe_av1_enc_rate_control unsigned enforce_hrd; unsigned max_au_size; unsigned qp; /* Initial QP */ + unsigned qp_inter; unsigned max_qp; unsigned min_qp; bool app_requested_qp_range;