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

Commit 8fc58186 authored by Stanimir Varbanov's avatar Stanimir Varbanov Committed by Mauro Carvalho Chehab
Browse files

media: venus: venc: set correctly GOP size and number of B-frames



This change fixes the calculation of B-frames and GOP size by
adopt v4l2 controls with the firmware interface expectations.

Signed-off-by: default avatarStanimir Varbanov <stanimir.varbanov@linaro.org>
Signed-off-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
[hans.verkuil@cisco.com: fixed two small checkpatch comments]
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
parent fdda0109
Loading
Loading
Loading
Loading
+10 −5
Original line number Diff line number Diff line
@@ -652,8 +652,13 @@ static int venc_set_properties(struct venus_inst *inst)
			return ret;
	}

	/* IDR periodicity, n:
	 * n = 0 - only the first I-frame is IDR frame
	 * n = 1 - all I-frames will be IDR frames
	 * n > 1 - every n-th I-frame will be IDR frame
	 */
	ptype = HFI_PROPERTY_CONFIG_VENC_IDR_PERIOD;
	idrp.idr_period = ctr->gop_size;
	idrp.idr_period = 0;
	ret = hfi_session_set_property(inst, ptype, &idrp);
	if (ret)
		return ret;
@@ -667,10 +672,6 @@ static int venc_set_properties(struct venus_inst *inst)
			return ret;
	}

	/* intra_period = pframes + bframes + 1 */
	if (!ctr->num_p_frames)
		ctr->num_p_frames = 2 * 15 - 1,

	ptype = HFI_PROPERTY_CONFIG_VENC_INTRA_PERIOD;
	intra_period.pframes = ctr->num_p_frames;
	intra_period.bframes = ctr->num_b_frames;
@@ -767,6 +768,10 @@ static int venc_init_session(struct venus_inst *inst)
	if (ret)
		goto deinit;

	ret = venc_set_properties(inst);
	if (ret)
		goto deinit;

	return 0;
deinit:
	hfi_session_deinit(inst);
+58 −1
Original line number Diff line number Diff line
@@ -30,10 +30,57 @@
#define AT_SLICE_BOUNDARY	\
	V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY

static int venc_calc_bpframes(u32 gop_size, u32 conseq_b, u32 *bf, u32 *pf)
{
	u32 half = (gop_size - 1) >> 1;
	u32 b, p, ratio;
	bool found = false;

	if (!gop_size)
		return -EINVAL;

	*bf = *pf = 0;

	if (!conseq_b) {
		*pf = gop_size -  1;
		return 0;
	}

	b = p = half;

	for (; b <= gop_size - 1; b++, p--) {
		if (b % p)
			continue;

		ratio = b / p;

		if (ratio == conseq_b) {
			found = true;
			break;
		}

		if (ratio > conseq_b)
			break;
	}

	if (!found)
		return -EINVAL;

	if (b + p + 1 != gop_size)
		return -EINVAL;

	*bf = b;
	*pf = p;

	return 0;
}

static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl)
{
	struct venus_inst *inst = ctrl_to_inst(ctrl);
	struct venc_controls *ctr = &inst->controls.enc;
	u32 bframes;
	int ret;

	switch (ctrl->id) {
	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
@@ -102,6 +149,11 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl)
	case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB:
		break;
	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
		ret = venc_calc_bpframes(ctrl->val, ctr->num_b_frames, &bframes,
					 &ctr->num_p_frames);
		if (ret)
			return ret;

		ctr->gop_size = ctrl->val;
		break;
	case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD:
@@ -114,7 +166,12 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl)
		ctr->vp8_max_qp = ctrl->val;
		break;
	case V4L2_CID_MPEG_VIDEO_B_FRAMES:
		ctr->num_b_frames = ctrl->val;
		ret = venc_calc_bpframes(ctr->gop_size, ctrl->val, &bframes,
					 &ctr->num_p_frames);
		if (ret)
			return ret;

		ctr->num_b_frames = bframes;
		break;
	default:
		return -EINVAL;