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

Commit a4b3e25f authored by Ashray Kulkarni's avatar Ashray Kulkarni
Browse files

msm: vidc: add LTR support for video encoder



Enable LTR support for VP8 codec to add robust error resilience.

Change-Id: I3b87c5cdaef836a6d02d5b9fe71b7165b7f13581
Signed-off-by: default avatarAshray Kulkarni <ashrayk@codeaurora.org>
parent 75bb475d
Loading
Loading
Loading
Loading
+63 −1
Original line number Diff line number Diff line
/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -455,6 +455,9 @@ static int get_hfi_extradata_index(enum hal_extradata_id index)
	case HAL_EXTRADATA_FRAME_BITS_INFO:
		ret = HFI_PROPERTY_PARAM_VDEC_FRAME_BITS_INFO_EXTRADATA;
		break;
	case HAL_EXTRADATA_LTR_INFO:
		ret = HFI_PROPERTY_PARAM_VENC_LTR_INFO;
		break;
	default:
		dprintk(VIDC_WARN, "Extradata index not found: %d\n", index);
		break;
@@ -504,6 +507,28 @@ static u32 get_hfi_buf_mode(enum buffer_mode_type hal_buf_mode)
	return buf_mode;
}

static u32 get_hfi_ltr_mode(enum ltr_mode ltr_mode_type)
{
	u32 ltrmode;
	switch (ltr_mode_type) {
	case HAL_LTR_MODE_DISABLE:
		ltrmode = HFI_LTR_MODE_DISABLE;
		break;
	case HAL_LTR_MODE_MANUAL:
		ltrmode = HFI_LTR_MODE_MANUAL;
		break;
	case HAL_LTR_MODE_PERIODIC:
		ltrmode = HFI_LTR_MODE_PERIODIC;
		break;
	default:
		dprintk(VIDC_ERR, "Invalid ltr mode :0x%x\n",
			ltr_mode_type);
		ltrmode = HFI_LTR_MODE_DISABLE;
		break;
	}
	return ltrmode;
}

int create_pkt_cmd_session_set_buffers(
		struct hfi_cmd_session_set_buffers_packet *pkt,
		u32 session_id,
@@ -1605,6 +1630,43 @@ int create_pkt_cmd_session_set_property(
			sizeof(struct hfi_mvc_buffer_layout_descp_type);
		break;
	}
	case HAL_PARAM_VENC_LTRMODE:
	{
		struct hfi_ltrmode *hfi;
		struct hal_ltrmode *hal = pdata;
		pkt->rg_property_data[0] =
			HFI_PROPERTY_PARAM_VENC_H264_LTRMODE;
		hfi = (struct hfi_ltrmode *) &pkt->rg_property_data[1];
		hfi->ltrmode = get_hfi_ltr_mode(hal->ltrmode);
		hfi->ltrcount = hal->ltrcount;
		hfi->trustmode = hal->trustmode;
		pkt->size += sizeof(u32) + sizeof(struct hfi_ltrmode);
		break;
	}
	case HAL_CONFIG_VENC_USELTRFRAME:
	{
		struct hfi_ltruse *hfi;
		struct hal_ltruse *hal = pdata;
		pkt->rg_property_data[0] =
			HFI_PROPERTY_CONFIG_VENC_H264_USELTRFRAME;
		hfi = (struct hfi_ltruse *) &pkt->rg_property_data[1];
		hfi->frames = hal->frames;
		hfi->refltr = hal->refltr;
		hfi->useconstrnt = hal->useconstrnt;
		pkt->size += sizeof(u32) + sizeof(struct hfi_ltruse);
		break;
	}
	case HAL_CONFIG_VENC_MARKLTRFRAME:
	{
		struct hfi_ltrmark *hfi;
		struct hal_ltrmark *hal = pdata;
		pkt->rg_property_data[0] =
			HFI_PROPERTY_CONFIG_VENC_H264_MARKLTRFRAME;
		hfi = (struct hfi_ltrmark *) &pkt->rg_property_data[1];
		hfi->markframe = hal->markframe;
		pkt->size += sizeof(u32) * 2;
		break;
	}
	/* FOLLOWING PROPERTIES ARE NOT IMPLEMENTED IN CORE YET */
	case HAL_CONFIG_BUFFER_REQUIREMENTS:
	case HAL_CONFIG_PRIORITY:
+9 −0
Original line number Diff line number Diff line
@@ -120,6 +120,13 @@ int msm_v4l2_g_ctrl(struct file *file, void *fh,
	return msm_vidc_g_ctrl((void *)vidc_inst, a);
}

int msm_v4l2_s_ext_ctrl(struct file *file, void *fh,
					struct v4l2_ext_controls *a)
{
	struct msm_vidc_inst *vidc_inst = get_vidc_inst(file, fh);
	return msm_vidc_s_ext_ctrl((void *)vidc_inst, a);
}

int msm_v4l2_reqbufs(struct file *file, void *fh,
				struct v4l2_requestbuffers *b)
{
@@ -226,6 +233,7 @@ static int msm_v4l2_enum_framesizes(struct file *file, void *fh,
	struct msm_vidc_inst *vidc_inst = get_vidc_inst(file, fh);
	return msm_vidc_enum_framesizes((void *)vidc_inst, fsize);
}

static const struct v4l2_ioctl_ops msm_v4l2_ioctl_ops = {
	.vidioc_querycap = msm_v4l2_querycap,
	.vidioc_enum_fmt_vid_cap_mplane = msm_v4l2_enum_fmt,
@@ -242,6 +250,7 @@ static const struct v4l2_ioctl_ops msm_v4l2_ioctl_ops = {
	.vidioc_streamoff = msm_v4l2_streamoff,
	.vidioc_s_ctrl = msm_v4l2_s_ctrl,
	.vidioc_g_ctrl = msm_v4l2_g_ctrl,
	.vidioc_s_ext_ctrls = msm_v4l2_s_ext_ctrl,
	.vidioc_subscribe_event = msm_v4l2_subscribe_event,
	.vidioc_unsubscribe_event = msm_v4l2_unsubscribe_event,
	.vidioc_decoder_cmd = msm_v4l2_decoder_cmd,
+148 −4
Original line number Diff line number Diff line
@@ -149,7 +149,8 @@ enum msm_venc_ctrl_cluster {
	MSM_VENC_CTRL_CLUSTER_TIMING = 1 << 9,
	MSM_VENC_CTRL_CLUSTER_VP8_PROFILE_LEVEL = 1 << 10,
	MSM_VENC_CTRL_CLUSTER_DEINTERLACE = 1 << 11,
	MSM_VENC_CTRL_CLUSTER_MAX = 1 << 12,
	MSM_VENC_CTRL_CLUSTER_USE_LTRFRAME = 1 << 12,
	MSM_VENC_CTRL_CLUSTER_MAX = 1 << 13,
};

static struct msm_vidc_ctrl msm_venc_ctrls[] = {
@@ -686,7 +687,7 @@ static struct msm_vidc_ctrl msm_venc_ctrls[] = {
		.name = "Extradata Type",
		.type = V4L2_CTRL_TYPE_MENU,
		.minimum = V4L2_MPEG_VIDC_EXTRADATA_NONE,
		.maximum = V4L2_MPEG_VIDC_EXTRADATA_ASPECT_RATIO,
		.maximum = V4L2_MPEG_VIDC_EXTRADATA_LTR,
		.default_value = V4L2_MPEG_VIDC_EXTRADATA_NONE,
		.menu_skip_mask = ~(
			(1 << V4L2_MPEG_VIDC_EXTRADATA_NONE) |
@@ -704,7 +705,8 @@ static struct msm_vidc_ctrl msm_venc_ctrls[] = {
			(1 << V4L2_MPEG_VIDC_EXTRADATA_METADATA_FILLER) |
			(1 << V4L2_MPEG_VIDC_EXTRADATA_INPUT_CROP) |
			(1 << V4L2_MPEG_VIDC_EXTRADATA_DIGITAL_ZOOM) |
			(1 << V4L2_MPEG_VIDC_EXTRADATA_ASPECT_RATIO)
			(1 << V4L2_MPEG_VIDC_EXTRADATA_ASPECT_RATIO)|
			(1 << V4L2_MPEG_VIDC_EXTRADATA_LTR)
			),
		.qmenu = mpeg_video_vidc_extradata,
		.step = 0,
@@ -809,6 +811,48 @@ static struct msm_vidc_ctrl msm_venc_ctrls[] = {
		.menu_skip_mask = 0,
		.qmenu = NULL,
		.cluster = 0,
	},
	{
		.id = V4L2_CID_MPEG_VIDC_VIDEO_USELTRFRAME,
		.name = "H264 Use LTR",
		.type = V4L2_CTRL_TYPE_BUTTON,
		.minimum = 0,
		.maximum = 1,
		.default_value = 0,
		.step = 1,
		.cluster = 0,
	},
	{
		.id = V4L2_CID_MPEG_VIDC_VIDEO_LTRCOUNT,
		.name = "Ltr Count",
		.type = V4L2_CTRL_TYPE_INTEGER,
		.minimum = 0,
		.maximum = 1,
		.default_value = 0,
		.step = 1,
		.qmenu = NULL,
		.cluster = MSM_VENC_CTRL_CLUSTER_USE_LTRFRAME,
	},
	{
		.id = V4L2_CID_MPEG_VIDC_VIDEO_LTRMODE,
		.name = "Ltr Mode",
		.type = V4L2_CTRL_TYPE_INTEGER,
		.minimum = V4L2_MPEG_VIDC_VIDEO_LTR_MODE_DISABLE,
		.maximum = V4L2_MPEG_VIDC_VIDEO_LTR_MODE_PERIODIC,
		.default_value = V4L2_MPEG_VIDC_VIDEO_LTR_MODE_DISABLE,
		.step = 1,
		.qmenu = NULL,
		.cluster = MSM_VENC_CTRL_CLUSTER_USE_LTRFRAME,
	},
	{
		.id = V4L2_CID_MPEG_VIDC_VIDEO_MARKLTRFRAME,
		.name = "H264 Mark LTR",
		.type = V4L2_CTRL_TYPE_BUTTON,
		.minimum = 0,
		.maximum = 0,
		.default_value = 0,
		.step = 0,
		.cluster = 0,
	}
};

@@ -932,7 +976,8 @@ static int msm_venc_queue_setup(struct vb2_queue *q,
				V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA);
		if (ctrl)
			extradata = v4l2_ctrl_g_ctrl(ctrl);
		if (extradata == V4L2_MPEG_VIDC_EXTRADATA_MULTISLICE_INFO)
		if ((extradata == V4L2_MPEG_VIDC_EXTRADATA_MULTISLICE_INFO) ||
			(extradata == V4L2_MPEG_VIDC_EXTRADATA_LTR))
			*num_planes = *num_planes + 1;
		inst->fmts[CAPTURE_PORT]->num_planes = *num_planes;
		for (i = 0; i < *num_planes; i++) {
@@ -1372,6 +1417,8 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
	struct hfi_device *hdev;
	struct hal_extradata_enable extra;
	struct hal_mpeg4_time_resolution time_res;
	struct hal_ltruse useltr;
	struct hal_ltrmark markltr;

	if (!inst || !inst->core || !inst->core->device) {
		dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
@@ -2110,7 +2157,20 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
	case V4L2_CID_MPEG_VIDC_VIDEO_REQUEST_SEQ_HEADER:
		atomic_inc(&inst->get_seq_hdr_cnt);
		break;
	case V4L2_CID_MPEG_VIDC_VIDEO_USELTRFRAME:
		property_id = HAL_CONFIG_VENC_USELTRFRAME;
		useltr.refltr = 0x1;
		useltr.useconstrnt = false;
		useltr.frames = 0;
		pdata = &useltr;
		break;
	case V4L2_CID_MPEG_VIDC_VIDEO_MARKLTRFRAME:
		property_id = HAL_CONFIG_VENC_MARKLTRFRAME;
		markltr.markframe = 0x1;
		pdata = &markltr;
		break;
	default:
		dprintk(VIDC_ERR, "Unsupported index: %x\n", ctrl->id);
		rc = -ENOTSUPP;
		break;
	}
@@ -2127,6 +2187,74 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
	return rc;
}

static struct v4l2_ctrl *get_cluster_from_id(int id)
{
	int c;
	for (c = 0; c < ARRAY_SIZE(msm_venc_ctrls); ++c)
		if (msm_venc_ctrls[c].id == id)
			return (struct v4l2_ctrl *)msm_venc_ctrls[c].priv;
	return NULL;
}

static int try_set_ext_ctrl(struct msm_vidc_inst *inst,
	struct v4l2_ext_controls *ctrl)
{
	int rc = 0, i;
	struct v4l2_ext_control *control;
	struct hfi_device *hdev;
	struct hal_ltrmode ltrmode;
	struct v4l2_ctrl *cluster;
	u32 property_id = 0;
	void *pdata = NULL;

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

	cluster = get_cluster_from_id(ctrl->controls[0].id);

	if (!cluster) {
		dprintk(VIDC_ERR, "Invalid Ctrl returned for id: %x\n",
			ctrl->controls[0].id);
		return -EINVAL;
	}

	hdev = inst->core->device;

	if (ctrl->count) {
		control = ctrl->controls;
		for (i = 0; i < ctrl->count; i++) {
			switch (control[i].id) {
			case V4L2_CID_MPEG_VIDC_VIDEO_LTRMODE:
				ltrmode.ltrmode = control[i].value;
				ltrmode.trustmode = 1;
				property_id = HAL_PARAM_VENC_LTRMODE;
				pdata = &ltrmode;
				break;
			case V4L2_CID_MPEG_VIDC_VIDEO_LTRCOUNT:
				ltrmode.ltrcount =  control[i].value;
				ltrmode.trustmode = 1;
				property_id = HAL_PARAM_VENC_LTRMODE;
				pdata = &ltrmode;
				break;
			default:
				dprintk(VIDC_ERR, "Invalid id set: %d\n",
					control[i].id);
				rc = -ENOTSUPP;
				break;
			}
		}
	}

	if (!rc && property_id) {
		dprintk(VIDC_DBG, "Control: HAL property=%x\n", property_id);
		rc = call_hfi_op(hdev, session_set_property,
				(void *)inst->session, property_id, pdata);
	}
	return rc;
}

static int msm_venc_op_s_ctrl(struct v4l2_ctrl *ctrl)
{

@@ -2213,6 +2341,22 @@ int msm_venc_g_ctrl(struct msm_vidc_inst *inst, struct v4l2_control *ctrl)
	return v4l2_g_ctrl(&inst->ctrl_handler, ctrl);
}

int msm_venc_s_ext_ctrl(struct msm_vidc_inst *inst,
	struct v4l2_ext_controls *ctrl)
{
	int rc = 0;
	if (ctrl->ctrl_class != V4L2_CTRL_CLASS_MPEG) {
		dprintk(VIDC_ERR, "Invalid Class set for extended control\n");
		return -EINVAL;
	}
	rc = try_set_ext_ctrl(inst, ctrl);
	if (rc) {
		dprintk(VIDC_ERR, "Error setting extended control\n");
		return rc;
	}
	return rc;
}

int msm_venc_cmd(struct msm_vidc_inst *inst, struct v4l2_encoder_cmd *enc)
{
	int rc = 0;
+2 −1
Original line number Diff line number Diff line
/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -25,6 +25,7 @@ int msm_venc_s_fmt(void *instance, struct v4l2_format *f);
int msm_venc_g_fmt(void *instance, struct v4l2_format *f);
int msm_venc_s_ctrl(void *instance, struct v4l2_control *a);
int msm_venc_g_ctrl(void *instance, struct v4l2_control *a);
int msm_venc_s_ext_ctrl(void *instance, struct v4l2_ext_controls *a);
int msm_venc_reqbufs(void *instance, struct v4l2_requestbuffers *b);
int msm_venc_prepare_buf(struct msm_vidc_inst *inst, struct v4l2_buffer *b);
int msm_venc_release_buf(struct msm_vidc_inst *inst, struct v4l2_buffer *b);
+11 −0
Original line number Diff line number Diff line
@@ -201,6 +201,17 @@ int msm_vidc_g_ctrl(void *instance, struct v4l2_control *control)
}
EXPORT_SYMBOL(msm_vidc_g_ctrl);

int msm_vidc_s_ext_ctrl(void *instance, struct v4l2_ext_controls *control)
{
	struct msm_vidc_inst *inst = instance;
	if (!inst || !control)
		return -EINVAL;
	if (inst->session_type == MSM_VIDC_ENCODER)
		return msm_venc_s_ext_ctrl(instance, control);
	return -EINVAL;
}
EXPORT_SYMBOL(msm_vidc_s_ext_ctrl);

int msm_vidc_reqbufs(void *instance, struct v4l2_requestbuffers *b)
{
	struct msm_vidc_inst *inst = instance;
Loading