Commit 69ff4b2c authored by Stanimir Varbanov's avatar Stanimir Varbanov Committed by Mauro Carvalho Chehab
Browse files

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: default avatarStanimir Varbanov <stanimir.varbanov@linaro.org>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
parent 4ad1b0d4
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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;
+36 −1
Original line number Diff line number Diff line
@@ -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);

	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)
+9 −1
Original line number Diff line number Diff line
@@ -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;
+13 −1
Original line number Diff line number Diff line
@@ -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
+9 −2
Original line number Diff line number Diff line
@@ -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;