Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b0d98933 authored by Amit Shekhar's avatar Amit Shekhar Committed by Gerrit - the friendly Code Review server
Browse files

msm: vidc: Add hierp max control and fix hierp encode



Hierp encoding needs max layer count details. Hence, adding support
for max layer count. Also, enabling hybrid hierp along with normal
hierp encoding.

Change-Id: I89eda99735768ae3c80464c95957e4a5adb5bb8e
Signed-off-by: default avatarAmit Shekhar <ashekhar@codeaurora.org>
parent e6a209df
Loading
Loading
Loading
Loading
+133 −75
Original line number Diff line number Diff line
@@ -621,14 +621,36 @@ static struct msm_vidc_ctrl msm_venc_ctrls[] = {
		.step = 1,
		.qmenu = NULL,
	},
	{
		.id = V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER,
		.name = "Set Hier max layers",
		.type = V4L2_CTRL_TYPE_INTEGER,
		.minimum = 0,
		.maximum = 6,
		.default_value = 0,
		.step = 1,
		.menu_skip_mask = ~(
		(1 << V4L2_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER_0) |
		(1 << V4L2_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER_1) |
		(1 << V4L2_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER_2) |
		(1 << V4L2_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER_3) |
		(1 << V4L2_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER_4) |
		(1 << V4L2_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER_5) |
		(1 << V4L2_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER_6)
		),
	},
	{
		.id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE,
		.name = "Set Hier coding type",
		.type = V4L2_CTRL_TYPE_MENU,
		.minimum = V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B,
		.minimum = V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P,
		.maximum = V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P,
		.default_value = V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P,
		.menu_skip_mask = 0,
		.step = 1,
		.menu_skip_mask = ~(
		(1 << V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P)
		),
		.qmenu = NULL,
	},
	{
		.id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L0_QP,
@@ -1738,11 +1760,21 @@ int msm_venc_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
					__func__);
		}
		break;
	case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER:
		if (inst->state == MSM_VIDC_START_DONE) {
			rc = msm_venc_set_hp_layer(inst);
			if (rc)
				dprintk(VIDC_ERR,
					"%s: set dyn hp layer failed.\n",
					__func__);
		}
		break;
	case V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER:
	case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE:
	case V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP:
	case V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP:
	case V4L2_CID_MPEG_VIDEO_B_FRAMES:
	case V4L2_CID_ROTATE:
	case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER:
	case V4L2_CID_MPEG_VIDC_VIDEO_LTRCOUNT:
	case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
	case V4L2_CID_HFLIP:
@@ -2153,8 +2185,6 @@ int msm_venc_set_rate_control(struct msm_vidc_inst *inst)
{
	int rc = 0;
	struct hfi_device *hdev;
	struct v4l2_ctrl *hier_layers;
	struct v4l2_ctrl *hier_type;
	u32 hfi_rc;

	if (!inst || !inst->core) {
@@ -2163,21 +2193,6 @@ int msm_venc_set_rate_control(struct msm_vidc_inst *inst)
	}
	hdev = inst->core->device;

	if ((inst->rc_type == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR_VFR) &&
		(inst->fmts[CAPTURE_PORT].fourcc == V4L2_PIX_FMT_H264)) {
		hier_layers = get_ctrl(inst,
			V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER);
		hier_type = get_ctrl(inst,
			V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE);
		if (hier_layers->val &&
			(hier_type->val ==
			V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P)){
			dprintk(VIDC_ERR,
				"%s: CBR_VFR not allowed with Hybrid HP\n",
				__func__);
			return -EINVAL;
		}
	}
	switch (inst->rc_type) {
	case RATE_CONTROL_OFF:
		hfi_rc = HFI_RATE_CONTROL_OFF;
@@ -2653,38 +2668,45 @@ int msm_venc_set_au_delimiter_mode(struct msm_vidc_inst *inst)
	return rc;
}

int msm_venc_hierp_check(struct msm_vidc_inst *inst, u32 value)
int msm_venc_enable_hybrid_hp(struct msm_vidc_inst *inst)
{
	if (!inst) {
	struct v4l2_ctrl *ctrl = NULL;
	struct v4l2_ctrl *layer = NULL;

	if (!inst || !inst->core) {
		dprintk(VIDC_ERR, "%s: invalid params\n", __func__);
		return -EINVAL;
	}

	if (value > inst->capability.hier_p.max) {
		dprintk(VIDC_ERR,
			"%s: hierp value (%d) > max supported (%d)\n",
			__func__, value,
			inst->capability.hier_p.max);
		return -EINVAL;
	}
	if (inst->fmts[CAPTURE_PORT].fourcc != V4L2_PIX_FMT_H264)
		return 0;

	if (inst->rc_type != V4L2_MPEG_VIDEO_BITRATE_MODE_VBR)
		return 0;
}

int msm_venc_hybrid_hp_check(struct msm_vidc_inst *inst, bool *hyb_hp)
{
	*hyb_hp = false;
	ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_B_FRAMES);
	if (ctrl->val)
		return 0;

	if (!inst || !inst->core) {
		dprintk(VIDC_ERR, "%s: invalid params\n", __func__);
		return -EINVAL;
	}
	ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_LTRCOUNT);
	if (ctrl->val)
		return 0;

	if (inst->fmts[CAPTURE_PORT].fourcc != V4L2_PIX_FMT_H264)
	ctrl = get_ctrl(inst,
		V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER);
	layer = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER);
	if (ctrl->val != layer->val)
		return 0;

	if (inst->rc_type == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR)
		*hyb_hp = true;
	/*
	 * Hybrid HP is enabled only for H264 when
	 * LTR and B-frame are both disabled,
	 * Rate control type is VBR and
	 * Max layer equals layer count.
	 */

	inst->hybrid_hp = true;

	return 0;
}

@@ -2707,11 +2729,6 @@ int msm_venc_set_base_layer_id(struct msm_vidc_inst *inst)

	ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_BASELAYER_ID);
	baselayerid = ctrl->val;
	rc = msm_venc_hierp_check(inst, baselayerid);
	if (rc) {
		dprintk(VIDC_ERR, "%s: hierp check failed\n", __func__);
		return rc;
	}

	dprintk(VIDC_DBG, "%s: %d\n", __func__, baselayerid);
	rc = call_hfi_op(hdev, session_set_property, inst->session,
@@ -2723,14 +2740,12 @@ int msm_venc_set_base_layer_id(struct msm_vidc_inst *inst)
	return rc;
}

int msm_venc_set_hierp_layers(struct msm_vidc_inst *inst)
int msm_venc_set_hp_max_layer(struct msm_vidc_inst *inst)
{
	int rc = 0;
	struct hfi_device *hdev;
	struct v4l2_ctrl *ctrl;
	u32 hierp_layers;
	struct hfi_hybrid_hierp hyb_hierp;
	bool hyb_hp;
	u32 hp_layer = 0;

	if (!inst || !inst->core) {
		dprintk(VIDC_ERR, "%s: invalid params\n", __func__);
@@ -2742,39 +2757,79 @@ int msm_venc_set_hierp_layers(struct msm_vidc_inst *inst)
		inst->fmts[CAPTURE_PORT].fourcc != V4L2_PIX_FMT_HEVC)
		return 0;

	ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE);
	ctrl = get_ctrl(inst,
		V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER);

	rc = msm_venc_hierp_check(inst, ctrl->val);
	rc = msm_venc_enable_hybrid_hp(inst);
	if (rc) {
		dprintk(VIDC_ERR, "%s: hierp check failed\n", __func__);
		dprintk(VIDC_ERR, "%s: get hybrid hp decision failed\n",
			__func__);
		return rc;
	}

	rc = msm_venc_hybrid_hp_check(inst, &hyb_hp);
	if (rc) {
		dprintk(VIDC_ERR, "%s: hybrid hp check failed\n", __func__);
		return rc;
	}
	/*
	 * We send enhancement layer count to FW,
	 * hence, input 0/1 indicates absence of layer encoding.
	 */
	if (ctrl->val)
		hp_layer = ctrl->val - 1;

	if (hyb_hp) {
		hyb_hierp.layers = ctrl->val;
		dprintk(VIDC_DBG, "%s: %d\n", __func__, hyb_hierp.layers);
	if (inst->hybrid_hp) {
		rc = call_hfi_op(hdev, session_set_property, inst->session,
			HFI_PROPERTY_PARAM_VENC_HIER_P_HYBRID_MODE,
			&hyb_hierp, sizeof(hyb_hierp));
			&hp_layer, sizeof(hp_layer));
	} else {
		rc = call_hfi_op(hdev, session_set_property, inst->session,
			HFI_PROPERTY_PARAM_VENC_HIER_P_MAX_NUM_ENH_LAYER,
			&hp_layer, sizeof(hp_layer));
	}
	if (rc)
		dprintk(VIDC_ERR,
			"%s: set property failed\n", __func__);
	} else {
		hierp_layers = ctrl->val;
		dprintk(VIDC_DBG, "%s: %d\n", __func__, hierp_layers);
	return rc;
}

int msm_venc_set_hp_layer(struct msm_vidc_inst *inst)
{
	int rc = 0;
	struct hfi_device *hdev;
	struct v4l2_ctrl *ctrl = NULL;
	u32 hp_layer = 0;

	if (!inst || !inst->core) {
		dprintk(VIDC_ERR, "%s: invalid params\n", __func__);
		return -EINVAL;
	}
	hdev = inst->core->device;

	if (inst->fmts[CAPTURE_PORT].fourcc != V4L2_PIX_FMT_H264 &&
		inst->fmts[CAPTURE_PORT].fourcc != V4L2_PIX_FMT_HEVC)
		return 0;

	if (inst->hybrid_hp) {
		dprintk(VIDC_WARN,
			"%s: Setting layer isn't allowed with hybrid hp\n",
			__func__);
		return 0;
	}

	ctrl = get_ctrl(inst,
		V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER);
	/*
	 * We send enhancement layer count to FW,
	 * hence, input 0/1 indicates absence of layer encoding.
	 */
	if (ctrl->val)
		hp_layer = ctrl->val - 1;

	dprintk(VIDC_DBG, "%s: HP layer: %d\n", __func__, hp_layer);
	rc = call_hfi_op(hdev, session_set_property, inst->session,
		HFI_PROPERTY_CONFIG_VENC_HIER_P_ENH_LAYER,
			&hierp_layers, sizeof(hierp_layers));
		&hp_layer, sizeof(hp_layer));
	if (rc)
		dprintk(VIDC_ERR,
			"%s: set property failed\n", __func__);
	}

	return rc;
}

@@ -3353,9 +3408,6 @@ int msm_venc_set_properties(struct msm_vidc_inst *inst)
	if (rc)
		goto exit;
	rc = msm_venc_set_base_layer_id(inst);
	if (rc)
		goto exit;
	rc = msm_venc_set_hierp_layers(inst);
	if (rc)
		goto exit;
	rc = msm_venc_set_vpx_error_resilience(inst);
@@ -3377,6 +3429,12 @@ int msm_venc_set_properties(struct msm_vidc_inst *inst)
	if (rc)
		goto exit;
	rc = msm_venc_set_ltr_mode(inst);
	if (rc)
		goto exit;
	rc = msm_venc_set_hp_max_layer(inst);
	if (rc)
		goto exit;
	rc = msm_venc_set_hp_layer(inst);
	if (rc)
		goto exit;
	rc = msm_venc_set_aspect_ratio(inst);
+2 −0
Original line number Diff line number Diff line
@@ -30,4 +30,6 @@ int msm_venc_set_ltr_markframe(struct msm_vidc_inst *inst);
int msm_venc_set_dyn_qp(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl);
int msm_venc_set_request_keyframe(struct msm_vidc_inst *inst);
int msm_venc_set_intra_refresh_mode(struct msm_vidc_inst *inst);
int msm_venc_set_hp_max_layer(struct msm_vidc_inst *inst);
int msm_venc_set_hp_layer(struct msm_vidc_inst *inst);
#endif
+1 −0
Original line number Diff line number Diff line
@@ -473,6 +473,7 @@ struct msm_vidc_inst {
	u32 grid_enable;
	u32 frame_quality;
	u32 rc_type;
	u32 hybrid_hp;
	struct internal_buf *dpb_extra_binfo;
	struct msm_vidc_codec_data *codec_data;
	struct hal_hdr10_pq_sei hdr10_sei_params;
+12 −0
Original line number Diff line number Diff line
@@ -961,6 +961,18 @@ enum v4l2_mpeg_vidc_video_vp9_level {
#define V4L2_CID_MPEG_VIDC_VIDEO_FRAME_RATE \
	(V4L2_CID_MPEG_MSM_VIDC_BASE + 119)

#define V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER \
	(V4L2_CID_MPEG_MSM_VIDC_BASE + 120)
enum v4l2_mpeg_vidc_video_hevc_max_hier_coding_layer {
	V4L2_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER_0 = 0,
	V4L2_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER_1 = 1,
	V4L2_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER_2 = 2,
	V4L2_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER_3 = 3,
	V4L2_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER_4 = 4,
	V4L2_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER_5 = 5,
	V4L2_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER_6 = 6,
};

/*  Camera class control IDs */

#define V4L2_CID_CAMERA_CLASS_BASE	(V4L2_CTRL_CLASS_CAMERA | 0x900)