media: venus: venc: Add support for constant quality control

Adds implementation of V4L2_CID_MPEG_VIDEO_CONSTANT_QUALITY v4l
control when the bitrate mode is CQ.

Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
This commit is contained in:
Stanimir Varbanov 2020-06-16 14:14:22 +02:00 committed by Mauro Carvalho Chehab
parent 4ad1b0d410
commit 69ff4b2caa
5 changed files with 68 additions and 5 deletions

View file

@ -206,6 +206,7 @@ struct venc_controls {
u32 bitrate;
u32 bitrate_peak;
u32 rc_enable;
u32 const_quality;
u32 h264_i_period;
u32 h264_entropy_mode;

View file

@ -640,6 +640,7 @@ static int pkt_session_set_property_1x(struct hfi_session_set_property_pkt *pkt,
case HFI_RATE_CONTROL_CBR_VFR:
case HFI_RATE_CONTROL_VBR_CFR:
case HFI_RATE_CONTROL_VBR_VFR:
case HFI_RATE_CONTROL_CQ:
break;
default:
ret = -EINVAL;
@ -1218,6 +1219,37 @@ pkt_session_set_property_4xx(struct hfi_session_set_property_pkt *pkt,
return 0;
}
static int
pkt_session_set_property_6xx(struct hfi_session_set_property_pkt *pkt,
void *cookie, u32 ptype, void *pdata)
{
void *prop_data;
if (!pkt || !cookie || !pdata)
return -EINVAL;
prop_data = &pkt->data[1];
pkt->shdr.hdr.size = sizeof(*pkt);
pkt->shdr.hdr.pkt_type = HFI_CMD_SESSION_SET_PROPERTY;
pkt->shdr.session_id = hash32_ptr(cookie);
pkt->num_properties = 1;
pkt->data[0] = ptype;
switch (ptype) {
case HFI_PROPERTY_CONFIG_HEIC_FRAME_QUALITY: {
struct hfi_heic_frame_quality *in = pdata, *cq = prop_data;
cq->frame_quality = in->frame_quality;
pkt->shdr.hdr.size += sizeof(u32) + sizeof(*cq);
break;
} default:
return pkt_session_set_property_4xx(pkt, cookie, ptype, pdata);
}
return 0;
}
int pkt_session_get_property(struct hfi_session_get_property_pkt *pkt,
void *cookie, u32 ptype)
{
@ -1236,7 +1268,10 @@ int pkt_session_set_property(struct hfi_session_set_property_pkt *pkt,
if (hfi_ver == HFI_VERSION_3XX)
return pkt_session_set_property_3xx(pkt, cookie, ptype, pdata);
return pkt_session_set_property_4xx(pkt, cookie, ptype, pdata);
if (hfi_ver == HFI_VERSION_4XX)
return pkt_session_set_property_4xx(pkt, cookie, ptype, pdata);
return pkt_session_set_property_6xx(pkt, cookie, ptype, pdata);
}
void pkt_set_version(enum hfi_version version)

View file

@ -231,6 +231,7 @@
#define HFI_RATE_CONTROL_VBR_CFR 0x1000003
#define HFI_RATE_CONTROL_CBR_VFR 0x1000004
#define HFI_RATE_CONTROL_CBR_CFR 0x1000005
#define HFI_RATE_CONTROL_CQ 0x1000008
#define HFI_VIDEO_CODEC_H264 0x00000002
#define HFI_VIDEO_CODEC_H263 0x00000004
@ -504,6 +505,7 @@
#define HFI_PROPERTY_CONFIG_VENC_HIER_P_ENH_LAYER 0x200600b
#define HFI_PROPERTY_CONFIG_VENC_LTRPERIOD 0x200600c
#define HFI_PROPERTY_CONFIG_VENC_PERF_MODE 0x200600e
#define HFI_PROPERTY_CONFIG_HEIC_FRAME_QUALITY 0x2006014
/*
* HFI_PROPERTY_PARAM_VPE_COMMON_START
@ -520,7 +522,8 @@
enum hfi_version {
HFI_VERSION_1XX,
HFI_VERSION_3XX,
HFI_VERSION_4XX
HFI_VERSION_4XX,
HFI_VERSION_6XX,
};
struct hfi_buffer_info {
@ -725,6 +728,11 @@ struct hfi_quality_vs_speed {
u32 quality_vs_speed;
};
struct hfi_heic_frame_quality {
u32 frame_quality;
u32 reserved[3];
};
struct hfi_quantization {
u32 qp_i;
u32 qp_p;

View file

@ -746,14 +746,26 @@ static int venc_set_properties(struct venus_inst *inst)
rate_control = HFI_RATE_CONTROL_OFF;
else if (ctr->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR)
rate_control = HFI_RATE_CONTROL_VBR_CFR;
else
else if (ctr->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
rate_control = HFI_RATE_CONTROL_CBR_CFR;
else if (ctr->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)
rate_control = HFI_RATE_CONTROL_CQ;
ptype = HFI_PROPERTY_PARAM_VENC_RATE_CONTROL;
ret = hfi_session_set_property(inst, ptype, &rate_control);
if (ret)
return ret;
if (rate_control == HFI_RATE_CONTROL_CQ && ctr->const_quality) {
struct hfi_heic_frame_quality quality = {};
ptype = HFI_PROPERTY_CONFIG_HEIC_FRAME_QUALITY;
quality.frame_quality = ctr->const_quality;
ret = hfi_session_set_property(inst, ptype, &quality);
if (ret)
return ret;
}
if (!ctr->bitrate)
bitrate = 64000;
else

View file

@ -202,6 +202,9 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl)
case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE:
ctr->rc_enable = ctrl->val;
break;
case V4L2_CID_MPEG_VIDEO_CONSTANT_QUALITY:
ctr->const_quality = ctrl->val;
break;
default:
return -EINVAL;
}
@ -217,7 +220,7 @@ int venc_ctrl_init(struct venus_inst *inst)
{
int ret;
ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, 31);
ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, 32);
if (ret)
return ret;
@ -225,7 +228,8 @@ int venc_ctrl_init(struct venus_inst *inst)
V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
~((1 << V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) |
(1 << V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)),
(1 << V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) |
(1 << V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)),
V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &venc_ctrl_ops,
@ -357,6 +361,9 @@ int venc_ctrl_init(struct venus_inst *inst)
v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE, 0, 1, 1, 1);
v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
V4L2_CID_MPEG_VIDEO_CONSTANT_QUALITY, 0, 100, 1, 0);
ret = inst->ctrl_handler.error;
if (ret)
goto err;