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

Commit 048032c0 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: vidc: Check image encode capabilities"

parents bc901062 61344c19
Loading
Loading
Loading
Loading
+76 −66
Original line number Diff line number Diff line
@@ -1506,12 +1506,6 @@ int msm_venc_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
				"%s: set bitrate mode failed\n", __func__);
		break;
	}
	case V4L2_CID_MPEG_VIDC_COMPRESSION_QUALITY:
		inst->frame_quality = ctrl->val;
		break;
	case V4L2_CID_MPEG_VIDC_IMG_GRID_SIZE:
		inst->grid_enable = ctrl->val;
		break;
	case V4L2_CID_MPEG_VIDEO_BITRATE:
		inst->clk_data.bitrate = ctrl->val;
		if (inst->state == MSM_VIDC_START_DONE) {
@@ -1774,6 +1768,8 @@ int msm_venc_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
					__func__);
		}
		break;
	case V4L2_CID_MPEG_VIDC_COMPRESSION_QUALITY:
	case V4L2_CID_MPEG_VIDC_IMG_GRID_SIZE:
	case V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER:
	case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE:
	case V4L2_CID_ROTATE:
@@ -2800,40 +2796,73 @@ int msm_venc_set_qp_range(struct msm_vidc_inst *inst)
	return rc;
}

int msm_venc_set_frame_quality(struct msm_vidc_inst *inst)
static void set_all_intra_preconditions(struct msm_vidc_inst *inst)
{
	int rc = 0;
	struct hfi_device *hdev;
	struct v4l2_ctrl *ctrl;
	struct hfi_heic_frame_quality frame_quality;
	struct v4l2_ctrl *ctrl = NULL, *ctrl_t = NULL;

	if (!inst || !inst->core) {
		dprintk(VIDC_ERR, "%s: invalid params\n", __func__);
		return -EINVAL;
	/* Disable multi slice */
	ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE);
	if (ctrl->val) {
		dprintk(VIDC_HIGH, "Disable multi slice for all intra\n");
		ctrl->val = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE;
	}
	hdev = inst->core->device;

	if (inst->rc_type != V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)
		return 0;
	/* Disable LTR */
	ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_LTRCOUNT);
	if (ctrl->val) {
		dprintk(VIDC_HIGH, "Disable LTR for all intra\n");
		ctrl->val = 0;
	}

	ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_COMPRESSION_QUALITY);
	frame_quality.frame_quality = ctrl->val;
	/* Disable Layer encoding */
	ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER);
	ctrl_t = get_ctrl(inst,
		V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER);
	if (ctrl->val || ctrl_t->val) {
		dprintk(VIDC_HIGH, "Disable layer encoding for all intra\n");
		ctrl->val = 0;
		ctrl_t->val = 0;
	}

	dprintk(VIDC_HIGH, "%s: %d\n", __func__, frame_quality.frame_quality);
	rc = call_hfi_op(hdev, session_set_property, inst->session,
		HFI_PROPERTY_CONFIG_HEIC_FRAME_QUALITY, &frame_quality,
		sizeof(frame_quality));
	if (rc)
		dprintk(VIDC_ERR, "%s: set property failed\n", __func__);
	/* Disable IR */
	ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_RANDOM);
	ctrl_t = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB);
	if (ctrl->val || ctrl_t->val) {
		dprintk(VIDC_HIGH, "Disable IR for all intra\n");
		ctrl->val = 0;
		ctrl_t->val = 0;
	}

	return rc;
	return;
}

int msm_venc_set_grid(struct msm_vidc_inst *inst)
static void set_heif_preconditions(struct msm_vidc_inst *inst)
{
	struct v4l2_ctrl *ctrl = NULL;

	/* Reset PFrames */
	ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_GOP_SIZE);
	if (ctrl->val) {
		dprintk(VIDC_HIGH, "Reset P-frame count for HEIF\n");
		ctrl->val = 0;
	}

	/* Reset BFrames */
	ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_B_FRAMES);
	if (ctrl->val) {
		dprintk(VIDC_HIGH, "Reset B-frame count for HEIF\n");
		ctrl->val = 0;
	}

	return;
}

int msm_venc_set_image_properties(struct msm_vidc_inst *inst)
{
	int rc = 0;
	struct hfi_device *hdev;
	struct v4l2_ctrl *ctrl;
	struct hfi_heic_frame_quality frame_quality;
	struct hfi_heic_grid_enable grid_enable;

	if (!inst || !inst->core) {
@@ -2845,6 +2874,17 @@ int msm_venc_set_grid(struct msm_vidc_inst *inst)
	if (inst->rc_type != V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)
		return 0;

	ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_COMPRESSION_QUALITY);
	frame_quality.frame_quality = ctrl->val;

	dprintk(VIDC_HIGH, "%s: frame quality: %d\n", __func__,
		frame_quality.frame_quality);
	rc = call_hfi_op(hdev, session_set_property, inst->session,
		HFI_PROPERTY_CONFIG_HEIC_FRAME_QUALITY, &frame_quality,
		sizeof(frame_quality));
	if (rc)
		dprintk(VIDC_ERR, "%s: set frame quality failed\n", __func__);

	ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_IMG_GRID_SIZE);

	/* Need a change in HFI if we want to pass size */
@@ -2853,12 +2893,16 @@ int msm_venc_set_grid(struct msm_vidc_inst *inst)
	else
		grid_enable.grid_enable = true;

	dprintk(VIDC_HIGH, "%s: %d\n", __func__, grid_enable.grid_enable);
	dprintk(VIDC_HIGH, "%s: grid enable: %d\n", __func__,
		grid_enable.grid_enable);
	rc = call_hfi_op(hdev, session_set_property, inst->session,
		HFI_PROPERTY_CONFIG_HEIC_GRID_ENABLE, &grid_enable,
		sizeof(grid_enable));
	if (rc)
		dprintk(VIDC_ERR, "%s: set property failed\n", __func__);
		dprintk(VIDC_ERR, "%s: set grid enable failed\n", __func__);

	set_all_intra_preconditions(inst);
	set_heif_preconditions(inst);

	return rc;
}
@@ -4027,7 +4071,7 @@ int msm_venc_set_lossless(struct msm_vidc_inst *inst)

int handle_all_intra_restrictions(struct msm_vidc_inst *inst)
{
	struct v4l2_ctrl *ctrl, *ctrl_t;
	struct v4l2_ctrl *ctrl = NULL;
	u32 n_fps, fps_max;
	struct msm_vidc_capability *capability;
	struct v4l2_format *f;
@@ -4078,38 +4122,7 @@ int handle_all_intra_restrictions(struct msm_vidc_inst *inst)
		return -ENOTSUPP;
	}

	/* Disable multi slice */
	ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE);
	if (ctrl->val) {
		dprintk(VIDC_HIGH, "Disable multi slice for all intra\n");
		ctrl->val = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE;
	}

	/* Disable LTR */
	ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_LTRCOUNT);
	if (ctrl->val) {
		dprintk(VIDC_HIGH, "Disable LTR for all intra\n");
		ctrl->val = 0;
	}

	/* Disable Layer encoding */
	ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER);
	ctrl_t = get_ctrl(inst,
		V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER);
	if (ctrl->val || ctrl_t->val) {
		dprintk(VIDC_HIGH, "Disable layer encoding for all intra\n");
		ctrl->val = 0;
		ctrl_t->val = 0;
	}

	/* Disable IR */
	ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_RANDOM);
	ctrl_t = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB);
	if (ctrl->val || ctrl_t->val) {
		dprintk(VIDC_HIGH, "Disable IR for all intra\n");
		ctrl->val = 0;
		ctrl_t->val = 0;
	}
	set_all_intra_preconditions(inst);

	return 0;
}
@@ -4210,10 +4223,7 @@ int msm_venc_set_properties(struct msm_vidc_inst *inst)
	rc = msm_venc_set_qp_range(inst);
	if (rc)
		goto exit;
	rc = msm_venc_set_frame_quality(inst);
	if (rc)
		goto exit;
	rc = msm_venc_set_grid(inst);
	rc = msm_venc_set_image_properties(inst);
	if (rc)
		goto exit;
	rc = msm_venc_set_au_delimiter_mode(inst);
+0 −12
Original line number Diff line number Diff line
@@ -826,15 +826,6 @@ static inline int start_streaming(struct msm_vidc_inst *inst)
		is_secondary_output_mode(inst))
		b.buffer_type = HFI_BUFFER_OUTPUT2;

	/* HEIC HW/FWK tiling encode is supported only for CQ RC mode */
	if (inst->rc_type == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ) {
		if (!heic_encode_session_supported(inst)) {
			dprintk(VIDC_ERR,
				"HEIC Encode session not supported\n");
			return -ENOTSUPP;
		}
	}

	/* Check if current session is under HW capability */
	rc = msm_vidc_check_session_supported(inst);
	if (rc) {
@@ -1440,9 +1431,6 @@ static int try_get_ctrl_for_instance(struct msm_vidc_inst *inst,
			V4L2_CID_MPEG_VIDEO_HEVC_PROFILE,
			inst->profile);
		break;
	case V4L2_CID_MPEG_VIDC_IMG_GRID_SIZE:
		ctrl->val = inst->grid_enable;
		break;
	case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
		ctrl->val = msm_comm_hfi_to_v4l2(
			V4L2_CID_MPEG_VIDEO_H264_LEVEL,
+1 −2
Original line number Diff line number Diff line
@@ -1069,8 +1069,7 @@ int msm_dcvs_try_enable(struct msm_vidc_inst *inst)
			inst->flags & VIDC_THUMBNAIL ||
			inst->clk_data.low_latency_mode ||
			inst->batch.enable ||
			inst->rc_type == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ ||
			inst->grid_enable) {
			inst->rc_type == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ) {
		dprintk(VIDC_HIGH, "DCVS disabled: %pK\n", inst);
		inst->clk_data.dcvs_mode = false;
		return false;
+54 −45
Original line number Diff line number Diff line
@@ -2387,48 +2387,6 @@ int msm_comm_vb2_buffer_done(struct msm_vidc_inst *inst,
	return 0;
}

bool heic_encode_session_supported(struct msm_vidc_inst *inst)
{
	u32 slice_mode;
	u32 idr_period = IDR_PERIOD;
	u32 n_bframes;
	u32 n_pframes;
	struct v4l2_format *f;

	slice_mode =  msm_comm_g_ctrl_for_id(inst,
		V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE);
	n_bframes =  msm_comm_g_ctrl_for_id(inst,
		V4L2_CID_MPEG_VIDEO_B_FRAMES);
	n_pframes =  msm_comm_g_ctrl_for_id(inst,
		V4L2_CID_MPEG_VIDEO_GOP_SIZE);

	/*
	 * HEIC Encode is supported for Constant Quality RC mode only.
	 * All configurations below except grid_enable are required for any
	 * HEIC session including FWK tiled HEIC encode.
	 * grid_enable flag along with dimension check enables HW tiling.
	 */
	f = &inst->fmts[OUTPUT_PORT].v4l2_fmt;
	if (inst->session_type == MSM_VIDC_ENCODER &&
		get_hal_codec(f->fmt.pix_mp.pixelformat) ==
			HAL_VIDEO_CODEC_HEVC &&
		inst->frame_quality >= MIN_FRAME_QUALITY &&
		inst->frame_quality <= MAX_FRAME_QUALITY &&
		slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE &&
		idr_period == 1 &&
		n_bframes == 0 &&
		n_pframes == 0) {
		if (inst->grid_enable > 0) {
			if (f->fmt.pix_mp.width < HEIC_GRID_DIMENSION ||
				f->fmt.pix_mp.height < HEIC_GRID_DIMENSION)
				return false;
			}
		return true;
	} else {
		return false;
	}
}

static bool is_eos_buffer(struct msm_vidc_inst *inst, u32 device_addr)
{
	struct eos_buf *temp, *next;
@@ -5585,6 +5543,9 @@ static int msm_vidc_check_mbpf_supported(struct msm_vidc_inst *inst)
		/* ignore thumbnail session */
		if (is_thumbnail_session(temp))
			continue;
		/* ignore HEIF sessions */
		if (is_image_session(temp))
			continue;
		mbpf += NUM_MBS_PER_FRAME(
			temp->fmts[INPUT_PORT].v4l2_fmt.fmt.pix_mp.height,
			temp->fmts[INPUT_PORT].v4l2_fmt.fmt.pix_mp.width);
@@ -5629,11 +5590,16 @@ int msm_vidc_check_scaling_supported(struct msm_vidc_inst *inst)
	u32 x_min, x_max, y_min, y_max;
	u32 input_height, input_width, output_height, output_width;
	struct v4l2_format *f;
	struct v4l2_ctrl *ctrl = NULL;

	if (inst->grid_enable > 0) {
	/* Grid get_ctrl allowed for encode session only */
	if (is_image_session(inst)) {
		ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_IMG_GRID_SIZE);
		if (ctrl->val > 0) {
			dprintk(VIDC_HIGH, "Skip scaling check for HEIC\n");
			return 0;
		}
	}

	f = &inst->fmts[INPUT_PORT].v4l2_fmt;
	input_height = f->fmt.pix_mp.height;
@@ -5719,6 +5685,7 @@ int msm_vidc_check_session_supported(struct msm_vidc_inst *inst)
	u32 width_min, width_max, height_min, height_max;
	u32 mbpf_max;
	struct v4l2_format *f;
	struct v4l2_ctrl *ctrl = NULL;

	if (!inst || !inst->core || !inst->core->device) {
		dprintk(VIDC_ERR, "%s: Invalid parameter\n", __func__);
@@ -5774,6 +5741,48 @@ int msm_vidc_check_session_supported(struct msm_vidc_inst *inst)
	input_height = f->fmt.pix_mp.height;
	input_width = f->fmt.pix_mp.width;

	if (is_image_session(inst)) {
		if (is_secure_session(inst)) {
			dprintk(VIDC_ERR,
				"Secure image encode isn't supported!\n");
			return -ENOTSUPP;
		}

		ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_IMG_GRID_SIZE);
		if (ctrl->val > 0) {
			if (inst->fmts[INPUT_PORT].v4l2_fmt.fmt.pix_mp.pixelformat !=
				V4L2_PIX_FMT_NV12 &&
				inst->fmts[INPUT_PORT].v4l2_fmt.fmt.pix_mp.pixelformat !=
				V4L2_PIX_FMT_NV12_512)
				return -ENOTSUPP;

			width_min =
				capability->cap[CAP_HEIC_IMAGE_FRAME_WIDTH].min;
			width_max =
				capability->cap[CAP_HEIC_IMAGE_FRAME_WIDTH].max;
			height_min =
				capability->cap[CAP_HEIC_IMAGE_FRAME_HEIGHT].min;
			height_max =
				capability->cap[CAP_HEIC_IMAGE_FRAME_HEIGHT].max;
			mbpf_max = capability->cap[CAP_MBS_PER_FRAME].max;

			input_height = ALIGN(input_height, 512);
			input_width = ALIGN(input_width, 512);
			output_height = input_height;
			output_width = input_width;
		} else {
			width_min =
				capability->cap[CAP_HEVC_IMAGE_FRAME_WIDTH].min;
			width_max =
				capability->cap[CAP_HEVC_IMAGE_FRAME_WIDTH].max;
			height_min =
				capability->cap[CAP_HEVC_IMAGE_FRAME_HEIGHT].min;
			height_max =
				capability->cap[CAP_HEVC_IMAGE_FRAME_HEIGHT].max;
			mbpf_max = capability->cap[CAP_MBS_PER_FRAME].max;
		}
	}

	if (inst->session_type == MSM_VIDC_ENCODER && (input_width % 2 != 0 ||
			input_height % 2 != 0 || output_width % 2 != 0 ||
			output_height % 2 != 0)) {
+8 −0
Original line number Diff line number Diff line
@@ -84,6 +84,14 @@ static inline u32 get_v4l2_codec(struct msm_vidc_inst *inst)
	return f->fmt.pix_mp.pixelformat;
}

static inline bool is_image_session(struct msm_vidc_inst *inst)
{
	/* Grid may or may not be enabled for an image encode session */
	return inst->session_type == MSM_VIDC_ENCODER &&
		get_v4l2_codec(inst) == V4L2_PIX_FMT_HEVC &&
		inst->rc_type == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ;
}

static inline bool is_realtime_session(struct msm_vidc_inst *inst)
{
	return !!(inst->flags & VIDC_REALTIME);
Loading