From 0b21038c2708458286735f077af69d7053061453 Mon Sep 17 00:00:00 2001 From: Akshata Sahukar Date: Tue, 19 Jan 2021 14:58:00 -0800 Subject: [PATCH] video: driver: Add support to deduce min, max, frame qp values Add support to deduce min, max, frame qp values from client set controls and set the same to video firmware. Change-Id: Id94e781cc0c8afdf0e9e00562bdaea32db04fd74 Signed-off-by: Akshata Sahukar --- driver/platform/waipio/src/msm_vidc_waipio.c | 161 +++++----- driver/vidc/inc/msm_vidc_control.h | 9 + driver/vidc/src/msm_vidc_control.c | 278 +++++++++++++++++- .../uapi/vidc/media/v4l2_vidc_extensions.h | 10 + 4 files changed, 380 insertions(+), 78 deletions(-) diff --git a/driver/platform/waipio/src/msm_vidc_waipio.c b/driver/platform/waipio/src/msm_vidc_waipio.c index fde836d1dd..5144599591 100644 --- a/driver/platform/waipio/src/msm_vidc_waipio.c +++ b/driver/platform/waipio/src/msm_vidc_waipio.c @@ -23,6 +23,10 @@ #define MIN_CHROMA_QP_OFFSET -12 #define MAX_CHROMA_QP_OFFSET 0 #define MAX_BITRATE 220000000 +#define MIN_QP_10BIT -12 +#define MIN_QP_8BIT 0 +#define MAX_QP 51 +#define DEFAULT_QP 20 #define UBWC_CONFIG(mc, ml, hbb, bs1, bs2, bs3, bsp) \ { \ @@ -115,7 +119,18 @@ static struct msm_platform_inst_capability instance_data_waipio[] = { MSM_VIDC_FMT_NV12C, BIT(MSM_VIDC_FMT_NV12) | BIT(MSM_VIDC_FMT_NV21) | BIT(MSM_VIDC_FMT_NV12C), MSM_VIDC_FMT_NV12C}, - {PIX_FMTS, ENC|DEC, HEVC, + {PIX_FMTS, ENC, HEVC, + MSM_VIDC_FMT_NV12, + MSM_VIDC_FMT_TP10C, + BIT(MSM_VIDC_FMT_NV12) | BIT(MSM_VIDC_FMT_NV21) | BIT(MSM_VIDC_FMT_NV12C ) | + BIT(MSM_VIDC_FMT_P010) | BIT(MSM_VIDC_FMT_TP10C), + MSM_VIDC_FMT_NV12C, + 0, 0, + CAP_FLAG_ROOT, + {0}, + {PROFILE, MIN_FRAME_QP, MAX_FRAME_QP, I_FRAME_QP}}, + + {PIX_FMTS, DEC, HEVC, MSM_VIDC_FMT_NV12, MSM_VIDC_FMT_TP10C, BIT(MSM_VIDC_FMT_NV12) | BIT(MSM_VIDC_FMT_NV21) | BIT(MSM_VIDC_FMT_NV12C ) | @@ -294,7 +309,7 @@ static struct msm_platform_inst_capability instance_data_waipio[] = { V4L2_CID_MPEG_VIDEO_BITRATE_MODE, HFI_PROP_RATE_CONTROL, CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, - {0}, {LTR_COUNT, IR_RANDOM, TIME_DELTA_BASED_RC}, + {0}, {LTR_COUNT, IR_RANDOM, TIME_DELTA_BASED_RC, I_FRAME_QP}, msm_vidc_adjust_bitrate_mode, msm_vidc_set_u32_enum}, {LOSSLESS, ENC, HEVC, @@ -441,68 +456,85 @@ static struct msm_platform_inst_capability instance_data_waipio[] = { 0, 1000, 500, 0, V4L2_CID_MPEG_VIDEO_VBV_DELAY}, - // TODO: QP for 10 bits and review QP caps - - {MIN_FRAME_QP, ENC, HEVC, - 0, 51, 1, 20, - V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP, - HFI_PROP_MIN_QP_PACKED, - CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT}, - {MIN_FRAME_QP, ENC, H264, - 0, 51, 1, 20, + MIN_QP_8BIT, MAX_QP, 1, MIN_QP_8BIT, V4L2_CID_MPEG_VIDEO_H264_MIN_QP, HFI_PROP_MIN_QP_PACKED, - CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT}, + CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT, + {0}, {0}, + NULL, msm_vidc_set_min_qp}, + + {MIN_FRAME_QP, ENC, HEVC, + MIN_QP_10BIT, MAX_QP, 1, MIN_QP_10BIT, + V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP, + HFI_PROP_MIN_QP_PACKED, + CAP_FLAG_OUTPUT_PORT, + {PIX_FMTS}, {0}, + msm_vidc_adjust_hevc_min_qp, msm_vidc_set_min_qp}, {I_FRAME_MIN_QP, ENC, H264, - 0, 51, 1, 20, - V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MIN_QP, - HFI_PROP_MIN_QP_PACKED, - CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT}, + MIN_QP_8BIT, MAX_QP, 1, MIN_QP_8BIT, + V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MIN_QP}, + + {I_FRAME_MIN_QP, ENC, HEVC, + MIN_QP_10BIT, MAX_QP, 1, MIN_QP_10BIT, + V4L2_CID_MPEG_VIDC_HEVC_I_FRAME_MIN_QP}, {P_FRAME_MIN_QP, ENC, H264, - 0, 51, 1, 20, - V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MIN_QP, - HFI_PROP_MIN_QP_PACKED, - CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT}, + MIN_QP_8BIT, MAX_QP, 1, MIN_QP_8BIT, + V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MIN_QP}, - // confirm codec - {B_FRAME_MIN_QP, ENC, HEVC|H264, - 0, 51, 1, 20, - V4L2_CID_MPEG_VIDC_B_FRAME_MIN_QP, - HFI_PROP_MIN_QP_PACKED, - CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT}, + {P_FRAME_MIN_QP, ENC, HEVC, + MIN_QP_10BIT, MAX_QP, 1, MIN_QP_10BIT, + V4L2_CID_MPEG_VIDC_HEVC_P_FRAME_MIN_QP}, + + {B_FRAME_MIN_QP, ENC, H264, + MIN_QP_8BIT, MAX_QP, 1, MIN_QP_8BIT, + V4L2_CID_MPEG_VIDC_B_FRAME_MIN_QP}, + + {B_FRAME_MIN_QP, ENC, HEVC, + MIN_QP_10BIT, MAX_QP, 1, MIN_QP_10BIT, + V4L2_CID_MPEG_VIDC_B_FRAME_MIN_QP}, {MAX_FRAME_QP, ENC, H264, - 0, 51, 1, 20, + MIN_QP_8BIT, MAX_QP, 1, MAX_QP, V4L2_CID_MPEG_VIDEO_H264_MAX_QP, HFI_PROP_MAX_QP_PACKED, - CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT}, + CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT, + {0}, {0}, + NULL, msm_vidc_set_min_qp}, {MAX_FRAME_QP, ENC, HEVC, - 0, 51, 1, 20, + MIN_QP_10BIT, MAX_QP, 1, MAX_QP, V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP, HFI_PROP_MAX_QP_PACKED, - CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT}, + CAP_FLAG_OUTPUT_PORT, + {PIX_FMTS}, {0}, + msm_vidc_adjust_hevc_max_qp, msm_vidc_set_min_qp}, {I_FRAME_MAX_QP, ENC, H264, - 0, 51, 1, 20, - V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MAX_QP, - HFI_PROP_MAX_QP_PACKED, - CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT}, + MIN_QP_8BIT, MAX_QP, 1, MAX_QP, + V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MAX_QP}, + + {I_FRAME_MAX_QP, ENC, HEVC, + MIN_QP_10BIT, MAX_QP, 1, MAX_QP, + V4L2_CID_MPEG_VIDC_HEVC_I_FRAME_MAX_QP}, {P_FRAME_MAX_QP, ENC, H264, - 0, 51, 1, 20, - V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MAX_QP, - HFI_PROP_MAX_QP_PACKED, - CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT}, + MIN_QP_8BIT, MAX_QP, 1, MAX_QP, + V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MAX_QP}, - {B_FRAME_MAX_QP, ENC, HEVC|H264, - 0, 51, 1, 20, - V4L2_CID_MPEG_VIDC_B_FRAME_MAX_QP, - HFI_PROP_MAX_QP_PACKED, - CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT}, + {P_FRAME_MAX_QP, ENC, HEVC, + MIN_QP_10BIT, MAX_QP, 1, MAX_QP, + V4L2_CID_MPEG_VIDC_HEVC_P_FRAME_MAX_QP}, + + {B_FRAME_MAX_QP, ENC, H264, + MIN_QP_8BIT, MAX_QP, 1, MAX_QP, + V4L2_CID_MPEG_VIDC_B_FRAME_MAX_QP}, + + {B_FRAME_MAX_QP, ENC, HEVC, + MIN_QP_10BIT, MAX_QP, 1, MAX_QP, + V4L2_CID_MPEG_VIDC_B_FRAME_MAX_QP}, {HEVC_HIER_QP, ENC, HEVC, V4L2_MPEG_MSM_VIDC_DISABLE, V4L2_MPEG_MSM_VIDC_ENABLE, @@ -511,50 +543,39 @@ static struct msm_platform_inst_capability instance_data_waipio[] = { HFI_PROP_QP_PACKED, CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT}, - /* - * HEVC I_MIN_QP, I_MAX_QP, P_MIN_QP, P_MAX_QP, B_MIN_QP, B_MAX_QP are missing - */ {I_FRAME_QP, ENC, HEVC, - 0, 51, 1, 10, + MIN_QP_10BIT, MAX_QP, 1, DEFAULT_QP, V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP, HFI_PROP_QP_PACKED, - CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT}, + CAP_FLAG_OUTPUT_PORT, + {PIX_FMTS, BITRATE_MODE}, {0}, + msm_vidc_adjust_hevc_frame_qp, msm_vidc_set_frame_qp}, {I_FRAME_QP, ENC, H264, - 0, 51, 1, 10, + MIN_QP_8BIT, MAX_QP, 1, DEFAULT_QP, V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP, HFI_PROP_QP_PACKED, - CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT}, - - {I_FRAME_QP, ENC, VP9, 0, 127, 1, 20}, + CAP_FLAG_OUTPUT_PORT, + {BITRATE_MODE}, {0}, + NULL, msm_vidc_set_frame_qp}, {P_FRAME_QP, ENC, HEVC, - 0, 51, 1, 20, - V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP, - HFI_PROP_QP_PACKED, - CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT}, + MIN_QP_10BIT, MAX_QP, 1, DEFAULT_QP, + V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP}, {P_FRAME_QP, ENC, H264, - 0, 51, 1, 20, - V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP, - HFI_PROP_QP_PACKED, - CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT}, + MIN_QP_8BIT, MAX_QP, 1, DEFAULT_QP, + V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP}, {P_FRAME_QP, ENC, VP9, 0, 127, 1, 40}, {B_FRAME_QP, ENC, HEVC, - 0, 51, 1, 20, - V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP, - HFI_PROP_QP_PACKED, - CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT}, + MIN_QP_10BIT, MAX_QP, 1, DEFAULT_QP, + V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP}, {B_FRAME_QP, ENC, H264, - 0, 51, 1, 20, - V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP, - HFI_PROP_QP_PACKED, - CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT}, - - {B_FRAME_QP, ENC, VP9, 0, 127, 1, 40}, + MIN_QP_8BIT, MAX_QP, 1, DEFAULT_QP, + V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP}, {L0_QP, ENC, HEVC, 0, 51, 1, 20, diff --git a/driver/vidc/inc/msm_vidc_control.h b/driver/vidc/inc/msm_vidc_control.h index 005b63f8db..85c465725c 100644 --- a/driver/vidc/inc/msm_vidc_control.h +++ b/driver/vidc/inc/msm_vidc_control.h @@ -28,12 +28,21 @@ int msm_vidc_adjust_mark_ltr(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_ir_random(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_delta_based_rc(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_transform_8x8(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_hevc_min_qp(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_hevc_max_qp(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_hevc_frame_qp(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_v4l2_properties(struct msm_vidc_inst *inst); int msm_vidc_set_header_mode(void *instance, enum msm_vidc_inst_capability_type cap_id); int msm_vidc_set_deblock_mode(void *instance, enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_min_qp(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_max_qp(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_frame_qp(void *instance, + enum msm_vidc_inst_capability_type cap_id); int msm_vidc_set_u32(void *instance, enum msm_vidc_inst_capability_type cap_id); int msm_vidc_set_u32_enum(void *instance, diff --git a/driver/vidc/src/msm_vidc_control.c b/driver/vidc/src/msm_vidc_control.c index 4d9fba31c5..2827b261bd 100644 --- a/driver/vidc/src/msm_vidc_control.c +++ b/driver/vidc/src/msm_vidc_control.c @@ -11,6 +11,11 @@ #include "msm_vidc_internal.h" #include "msm_vidc_driver.h" +#define CAP_TO_8BIT_QP(a) { \ + if ((a) < 0) \ + (a) = 0; \ +} + static bool is_priv_ctrl(u32 id) { if (IS_PRIV_CTRL(id)) @@ -191,6 +196,14 @@ static const char *msm_vidc_get_priv_ctrl_name(u32 sid, u32 control_id) return "Encoder QP Metadata"; case V4L2_CID_MPEG_VIDC_MIN_BITSTREAM_SIZE_OVERWRITE: return "Bitstream Size Overwrite"; + case V4L2_CID_MPEG_VIDC_HEVC_I_FRAME_MIN_QP: + return "HEVC I Frame Min QP"; + case V4L2_CID_MPEG_VIDC_HEVC_P_FRAME_MIN_QP: + return "HEVC P Frame Min QP"; + case V4L2_CID_MPEG_VIDC_HEVC_I_FRAME_MAX_QP: + return "HEVC I Frame Max QP"; + case V4L2_CID_MPEG_VIDC_HEVC_P_FRAME_MAX_QP: + return "HEVC P Frame Max QP"; default: s_vpr_e(sid, "%s: ctrl name not available for ctrl id %#x\n", __func__, control_id); @@ -337,14 +350,54 @@ static int msm_vidc_get_parent_value(struct msm_vidc_inst* inst, *value = inst->capabilities->cap[parent].value; } else { s_vpr_e(inst->sid, - "%s: missing parent %d, please correct database\n", - func, parent); + "%s: missing parent %d for cap %d, please correct database\n", + func, parent, cap); rc = -EINVAL; } return rc; } +static int msm_vidc_adjust_hevc_qp(struct msm_vidc_inst *inst, + enum msm_vidc_inst_capability_type cap_id) +{ + struct msm_vidc_inst_capability *capability; + s32 pix_fmt = -1; + + capability = inst->capabilities; + + if (inst->codec != MSM_VIDC_HEVC) { + s_vpr_e(inst->sid, + "%s: incorrect entry in database for cap %d. fix the database\n", + __func__, cap_id); + return -EINVAL; + } + + if (msm_vidc_get_parent_value(inst, cap_id, + PIX_FMTS, &pix_fmt, __func__)) + return -EINVAL; + + if (pix_fmt == MSM_VIDC_FMT_P010 || pix_fmt == MSM_VIDC_FMT_TP10C) + goto exit; + + CAP_TO_8BIT_QP(capability->cap[cap_id].value); + if (cap_id == MIN_FRAME_QP) { + CAP_TO_8BIT_QP(capability->cap[I_FRAME_MIN_QP].value); + CAP_TO_8BIT_QP(capability->cap[P_FRAME_MIN_QP].value); + CAP_TO_8BIT_QP(capability->cap[B_FRAME_MIN_QP].value); + } else if (cap_id == MAX_FRAME_QP) { + CAP_TO_8BIT_QP(capability->cap[I_FRAME_MAX_QP].value); + CAP_TO_8BIT_QP(capability->cap[P_FRAME_MAX_QP].value); + CAP_TO_8BIT_QP(capability->cap[B_FRAME_MAX_QP].value); + } else if (cap_id == I_FRAME_QP) { + CAP_TO_8BIT_QP(capability->cap[P_FRAME_QP].value); + CAP_TO_8BIT_QP(capability->cap[B_FRAME_QP].value); + } + +exit: + return 0; +} + static int msm_vidc_adjust_property(struct msm_vidc_inst *inst, enum msm_vidc_inst_capability_type cap_id) { @@ -1015,6 +1068,57 @@ int msm_vidc_adjust_transform_8x8(void *instance, struct v4l2_ctrl *ctrl) return 0; } +int msm_vidc_adjust_hevc_min_qp(void *instance, struct v4l2_ctrl *ctrl) +{ + int rc = 0; + struct msm_vidc_inst_capability *capability; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + rc = msm_vidc_adjust_hevc_qp(inst, MIN_FRAME_QP); + + return rc; +} + +int msm_vidc_adjust_hevc_max_qp(void *instance, struct v4l2_ctrl *ctrl) +{ + int rc = 0; + struct msm_vidc_inst_capability *capability; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + rc = msm_vidc_adjust_hevc_qp(inst, MAX_FRAME_QP); + + return rc; +} + +int msm_vidc_adjust_hevc_frame_qp(void *instance, struct v4l2_ctrl *ctrl) +{ + int rc = 0; + struct msm_vidc_inst_capability *capability; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + rc = msm_vidc_adjust_hevc_qp(inst, I_FRAME_QP); + + return rc; +} + /* * Loop over instance capabilities with CAP_FLAG_ROOT * and call adjust function, where @@ -1114,7 +1218,7 @@ int msm_vidc_set_deblock_mode(void *instance, int rc = 0; struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; s32 alpha = 0, beta = 0; - u32 lf_mode, hfi_value = 0, lf_offset = 12; + u32 lf_mode, hfi_value = 0, lf_offset = 6; struct msm_vidc_inst_capability *capability; if (!inst || !inst->capabilities) { @@ -1127,11 +1231,6 @@ int msm_vidc_set_deblock_mode(void *instance, if (rc) return -EINVAL; - /* - * TODO: Revisit once s32 packing problem is fixed in hfi interface. - * For now, using offset value as 6 to shift alpha, beta ranges - * to (0 to 12) from (-6 to 6) - */ beta = inst->capabilities->cap[LF_BETA].value + lf_offset; alpha = inst->capabilities->cap[LF_ALPHA].value + lf_offset; @@ -1165,6 +1264,169 @@ int msm_vidc_set_use_and_mark_ltr(void *instance, return rc; } +int msm_vidc_set_min_qp(void *instance, + enum msm_vidc_inst_capability_type cap_id) +{ + int rc = 0; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; + struct msm_vidc_inst_capability *capability; + s32 i_frame_qp = 0, p_frame_qp = 0, b_frame_qp = 0, min_qp_enable = 0; + u32 i_qp_enable = 0, p_qp_enable = 0, b_qp_enable = 0; + u32 client_qp_enable = 0, hfi_value = 0, offset = 0; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + min_qp_enable = + capability->cap[MIN_FRAME_QP].flags & CAP_FLAG_CLIENT_SET; + + i_qp_enable = min_qp_enable || + capability->cap[I_FRAME_MIN_QP].flags & CAP_FLAG_CLIENT_SET; + p_qp_enable = min_qp_enable || + capability->cap[P_FRAME_MIN_QP].flags & CAP_FLAG_CLIENT_SET; + b_qp_enable = min_qp_enable || + capability->cap[B_FRAME_MIN_QP].flags & CAP_FLAG_CLIENT_SET; + + client_qp_enable = i_qp_enable | p_qp_enable << 1 | b_qp_enable << 2; + if (!client_qp_enable) + return 0; + + if (is_10bit_colorformat(capability->cap[PIX_FMTS].value)) + offset = 12; + + /* + * I_FRAME_MIN_QP, P_FRAME_MIN_QP, B_FRAME_MIN_QP, + * MIN_FRAME_QP caps have default value as MIN_QP_10BIT values. + * Hence, if client sets either one among MIN_FRAME_QP + * and (I_FRAME_MIN_QP or P_FRAME_MIN_QP or B_FRAME_MIN_QP), + * max of both caps will result into client set value. + */ + i_frame_qp = max(capability->cap[I_FRAME_MIN_QP].value, + capability->cap[MIN_FRAME_QP].value) + offset; + p_frame_qp = max(capability->cap[P_FRAME_MIN_QP].value, + capability->cap[MIN_FRAME_QP].value) + offset; + b_frame_qp = max(capability->cap[B_FRAME_MIN_QP].value, + capability->cap[MIN_FRAME_QP].value) + offset; + + hfi_value = i_frame_qp | p_frame_qp << 8 | b_frame_qp << 16 | + client_qp_enable << 24; + rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_32_PACKED, + &hfi_value, sizeof(u32), __func__); + + return rc; +} + +int msm_vidc_set_max_qp(void *instance, + enum msm_vidc_inst_capability_type cap_id) +{ + int rc = 0; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; + struct msm_vidc_inst_capability *capability; + s32 i_frame_qp = 0, p_frame_qp = 0, b_frame_qp = 0, max_qp_enable = 0; + u32 i_qp_enable = 0, p_qp_enable = 0, b_qp_enable = 0; + u32 client_qp_enable = 0, hfi_value = 0, offset = 0; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + max_qp_enable = + capability->cap[MAX_FRAME_QP].flags & CAP_FLAG_CLIENT_SET; + + i_qp_enable = max_qp_enable || + capability->cap[I_FRAME_MIN_QP].flags & CAP_FLAG_CLIENT_SET; + p_qp_enable = max_qp_enable || + capability->cap[P_FRAME_MIN_QP].flags & CAP_FLAG_CLIENT_SET; + b_qp_enable = max_qp_enable || + capability->cap[B_FRAME_MIN_QP].flags & CAP_FLAG_CLIENT_SET; + + client_qp_enable = i_qp_enable | p_qp_enable << 1 | b_qp_enable << 2; + if (!client_qp_enable) + return 0; + + if (is_10bit_colorformat(capability->cap[PIX_FMTS].value)) + offset = 12; + + /* + * I_FRAME_MAX_QP, P_FRAME_MAX_QP, B_FRAME_MAX_QP, + * MAX_FRAME_QP caps have default value as MAX_QP values. + * Hence, if client sets either one among MAX_FRAME_QP + * and (I_FRAME_MAX_QP or P_FRAME_MAX_QP or B_FRAME_MAX_QP), + * min of both caps will result into client set value. + */ + i_frame_qp = min(capability->cap[I_FRAME_MAX_QP].value, + capability->cap[MAX_FRAME_QP].value) + offset; + p_frame_qp = min(capability->cap[P_FRAME_MAX_QP].value, + capability->cap[MAX_FRAME_QP].value) + offset; + b_frame_qp = min(capability->cap[B_FRAME_MAX_QP].value, + capability->cap[MAX_FRAME_QP].value) + offset; + + hfi_value = i_frame_qp | p_frame_qp << 8 | b_frame_qp << 16 | + client_qp_enable << 24; + rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_32_PACKED, + &hfi_value, sizeof(u32), __func__); + + return rc; +} + +int msm_vidc_set_frame_qp(void *instance, + enum msm_vidc_inst_capability_type cap_id) +{ + int rc = 0; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; + struct msm_vidc_inst_capability *capab; + s32 i_frame_qp = 0, p_frame_qp = 0, b_frame_qp = 0; + u32 i_qp_enable = 0, p_qp_enable = 0, b_qp_enable = 0; + u32 client_qp_enable = 0, hfi_value = 0, offset = 0; + s32 rc_type = -1; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capab = inst->capabilities; + + if (msm_vidc_get_parent_value(inst, I_FRAME_QP, + BITRATE_MODE, &rc_type, __func__)) + return -EINVAL; + + if (rc_type == HFI_RC_OFF) { + /* Mandatorily set for rc off case */ + i_qp_enable = p_qp_enable = b_qp_enable = 1; + } else { + /* Set only if client has set for NON rc off case */ + i_qp_enable = + capab->cap[I_FRAME_QP].flags & CAP_FLAG_CLIENT_SET; + p_qp_enable = + capab->cap[P_FRAME_QP].flags & CAP_FLAG_CLIENT_SET; + b_qp_enable = + capab->cap[B_FRAME_QP].flags & CAP_FLAG_CLIENT_SET; + } + + client_qp_enable = i_qp_enable | p_qp_enable << 1 | b_qp_enable << 2; + if (!client_qp_enable) + return 0; + + if (is_10bit_colorformat(capab->cap[PIX_FMTS].value)) + offset = 12; + + i_frame_qp = capab->cap[I_FRAME_QP].value + offset; + p_frame_qp = capab->cap[P_FRAME_QP].value + offset; + b_frame_qp = capab->cap[B_FRAME_QP].value + offset; + + hfi_value = i_frame_qp | p_frame_qp << 8 | b_frame_qp << 16 | + client_qp_enable << 24; + rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_32_PACKED, + &hfi_value, sizeof(u32), __func__); + + return rc; +} + /* TODO int msm_vidc_set_flip(void *instance, enum msm_vidc_inst_capability_type cap_id) diff --git a/include/uapi/vidc/media/v4l2_vidc_extensions.h b/include/uapi/vidc/media/v4l2_vidc_extensions.h index 53e09c17be..3b6c4d751e 100644 --- a/include/uapi/vidc/media/v4l2_vidc_extensions.h +++ b/include/uapi/vidc/media/v4l2_vidc_extensions.h @@ -106,6 +106,16 @@ enum v4l2_mpeg_vidc_blur_types { #define V4L2_CID_MPEG_VIDC_MIN_BITSTREAM_SIZE_OVERWRITE \ (V4L2_CID_MPEG_VIDC_BASE + 0x23) +/* Deprecate below controls once they are available in upstream */ +#define V4L2_CID_MPEG_VIDC_HEVC_I_FRAME_MIN_QP \ + (V4L2_CID_MPEG_VIDC_BASE + 0x24) +#define V4L2_CID_MPEG_VIDC_HEVC_P_FRAME_MIN_QP \ + (V4L2_CID_MPEG_VIDC_BASE + 0x25) +#define V4L2_CID_MPEG_VIDC_HEVC_I_FRAME_MAX_QP \ + (V4L2_CID_MPEG_VIDC_BASE + 0x26) +#define V4L2_CID_MPEG_VIDC_HEVC_P_FRAME_MAX_QP \ + (V4L2_CID_MPEG_VIDC_BASE + 0x27) + enum v4l2_mpeg_vidc_metapayload_header_flags { METADATA_FLAGS_NONE = 0, METADATA_FLAGS_TOP_FIELD = (1 << 0),