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

Commit 5bcf89d8 authored by Amit Shekhar's avatar Amit Shekhar
Browse files

msm: vidc: Add HEIF encode support



Add support for HEIF HW encoding which uses HEVC encoder
and performs tile based frame encoding.
Supports configuration of Grid-enable, Quality-factor,
Constant-quality rate control and MainStill profile.

Change-Id: I3062b97f6a713a64119427135f4699d8900810c3
Signed-off-by: default avatarAmit Shekhar <ashekhar@codeaurora.org>
parent 853d7314
Loading
Loading
Loading
Loading
+29 −0
Original line number Diff line number Diff line
@@ -1234,6 +1234,32 @@ int create_pkt_cmd_session_set_property(
		pkt->rg_property_data[0] =
			HFI_PROPERTY_CONFIG_VENC_REQUEST_SYNC_FRAME;
		break;
	case HAL_CONFIG_HEIC_FRAME_QUALITY:
	{
		struct hfi_heic_frame_quality *hfi;

		pkt->rg_property_data[0] =
			HFI_PROPERTY_CONFIG_HEIC_FRAME_QUALITY;
		hfi =
		(struct hfi_heic_frame_quality *) &pkt->rg_property_data[1];
		hfi->frame_quality =
			((struct hal_heic_frame_quality *)pdata)->frame_quality;
		pkt->size += sizeof(u32) +
			sizeof(struct hfi_heic_frame_quality);
		break;
	}
	case HAL_CONFIG_HEIC_GRID_ENABLE:
	{
		struct hfi_heic_grid_enable *hfi;

		pkt->rg_property_data[0] =
			HFI_PROPERTY_CONFIG_HEIC_GRID_ENABLE;
		hfi = (struct hfi_heic_grid_enable *) &pkt->rg_property_data[1];
		hfi->grid_enable =
			((struct hal_heic_grid_enable *)pdata)->grid_enable;
		pkt->size += sizeof(u32) + sizeof(struct hfi_heic_grid_enable);
		break;
	}
	case HAL_CONFIG_VENC_TARGET_BITRATE:
	{
		struct hfi_bitrate *hfi;
@@ -1315,6 +1341,9 @@ int create_pkt_cmd_session_set_property(
		case HAL_RATE_CONTROL_MBR_VFR:
			pkt->rg_property_data[1] = HFI_RATE_CONTROL_MBR_VFR;
			break;
		case HAL_RATE_CONTROL_CQ:
			pkt->rg_property_data[1] = HFI_RATE_CONTROL_CQ;
			break;
		default:
			dprintk(VIDC_ERR,
					"Invalid Rate control setting: %pK\n",
+75 −2
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ static const char *const mpeg_video_rate_control[] = {
	"RC OFF",
	"CBR VFR",
	"MBR VFR",
	"CQ",
	NULL
};

@@ -350,7 +351,7 @@ static struct msm_vidc_ctrl msm_venc_ctrls[] = {
		.name = "Video Framerate and Bitrate Control",
		.type = V4L2_CTRL_TYPE_MENU,
		.minimum = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
		.maximum = V4L2_MPEG_VIDEO_BITRATE_MODE_MBR_VFR,
		.maximum = V4L2_MPEG_VIDEO_BITRATE_MODE_CQ,
		.default_value = V4L2_MPEG_VIDEO_BITRATE_MODE_RC_OFF,
		.step = 0,
		.menu_skip_mask = ~(
@@ -359,10 +360,33 @@ static struct msm_vidc_ctrl msm_venc_ctrls[] = {
		(1 << V4L2_MPEG_VIDEO_BITRATE_MODE_MBR) |
		(1 << V4L2_MPEG_VIDEO_BITRATE_MODE_RC_OFF) |
		(1 << V4L2_MPEG_VIDEO_BITRATE_MODE_CBR_VFR) |
		(1 << V4L2_MPEG_VIDEO_BITRATE_MODE_MBR_VFR)
		(1 << V4L2_MPEG_VIDEO_BITRATE_MODE_MBR_VFR) |
		(1 << V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)
		),
		.qmenu = mpeg_video_rate_control,
	},
	{
		.id = V4L2_CID_MPEG_VIDC_VIDEO_FRAME_QUALITY,
		.name = "Frame quality",
		.type = V4L2_CTRL_TYPE_INTEGER,
		.minimum = MIN_FRAME_QUALITY,
		.maximum = MAX_FRAME_QUALITY,
		.default_value = DEFAULT_FRAME_QUALITY,
		.step = FRAME_QUALITY_STEP,
		.menu_skip_mask = 0,
		.qmenu = NULL,
	},
	{
		.id = V4L2_CID_MPEG_VIDC_IMG_GRID_ENABLE,
		.name = "Image grid enable",
		.type = V4L2_CTRL_TYPE_BOOLEAN,
		.minimum = V4L2_MPEG_MSM_VIDC_DISABLE,
		.maximum = V4L2_MPEG_MSM_VIDC_ENABLE,
		.default_value = V4L2_MPEG_MSM_VIDC_DISABLE,
		.step = 1,
		.menu_skip_mask = 0,
		.qmenu = NULL,
	},
	{
		.id = V4L2_CID_MPEG_VIDEO_BITRATE,
		.name = "Bit Rate",
@@ -1275,6 +1299,8 @@ int msm_venc_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
	enum hal_iframesize_type iframesize_type = HAL_IFRAMESIZE_TYPE_DEFAULT;
	u32 color_primaries, custom_matrix;
	struct hal_nal_stream_format_select stream_format;
	struct hal_heic_frame_quality frame_quality;
	struct hal_heic_grid_enable grid_enable;

	if (!inst || !inst->core || !inst->core->device) {
		dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
@@ -1377,11 +1403,58 @@ int msm_venc_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
			rc = -ENOTSUPP;
			break;
		}
		if ((ctrl->val == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ) &&
			inst->fmts[CAPTURE_PORT].fourcc != V4L2_PIX_FMT_HEVC) {
			dprintk(VIDC_ERR, "CQ supported only for HEVC\n");
			rc = -ENOTSUPP;
			break;
		}
		property_id = HAL_PARAM_VENC_RATE_CONTROL;
		property_val = ctrl->val;
		pdata = &property_val;
		break;
	}
	case V4L2_CID_MPEG_VIDC_VIDEO_FRAME_QUALITY:
	{
		struct v4l2_ctrl *rc_mode = TRY_GET_CTRL(
			V4L2_CID_MPEG_VIDEO_BITRATE_MODE);
		if (rc_mode->val != V4L2_MPEG_VIDEO_BITRATE_MODE_CQ) {
			dprintk(VIDC_ERR,
				"Frame quality supported only for CQ\n");
			rc = -ENOTSUPP;
			break;
		}
		if (ctrl->val < MIN_FRAME_QUALITY ||
			ctrl->val > MAX_FRAME_QUALITY) {
			dprintk(VIDC_ERR,
				"Frame quality value %d is not supported\n",
				ctrl->val);
			rc = -ENOTSUPP;
			break;
		}
		property_id = HAL_CONFIG_HEIC_FRAME_QUALITY;
		frame_quality.frame_quality = ctrl->val;
		inst->frame_quality = ctrl->val;
		pdata = &frame_quality;
		break;
	}
	case V4L2_CID_MPEG_VIDC_IMG_GRID_ENABLE:
	{
		struct v4l2_ctrl *rc_mode = TRY_GET_CTRL(
			V4L2_CID_MPEG_VIDEO_BITRATE_MODE);
		if (rc_mode->val != V4L2_MPEG_VIDEO_BITRATE_MODE_CQ &&
			ctrl->val) {
			dprintk(VIDC_ERR,
				"Grid enable supported only for CQ\n");
			rc = -ENOTSUPP;
			break;
		}
		property_id = HAL_CONFIG_HEIC_GRID_ENABLE;
		grid_enable.grid_enable = ctrl->val;
		inst->grid_enable = ctrl->val;
		pdata = &grid_enable;
		break;
	}
	case V4L2_CID_MPEG_VIDEO_BITRATE:
	{
		property_id = HAL_CONFIG_VENC_TARGET_BITRATE;
+15 −1
Original line number Diff line number Diff line
@@ -999,11 +999,23 @@ static inline int start_streaming(struct msm_vidc_inst *inst)
	int rc = 0;
	struct hfi_device *hdev;
	struct hal_buffer_size_minimum b;
	u32 rc_mode;

	dprintk(VIDC_DBG, "%s: %x : inst %pK\n", __func__,
		hash32_ptr(inst->session), inst);
	hdev = inst->core->device;

	rc_mode =  msm_comm_g_ctrl_for_id(inst,
		V4L2_CID_MPEG_VIDEO_BITRATE_MODE);
	/* HEIC HW/FWK tiling encode is supported only for CQ RC mode */
	if (rc_mode == 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) {
@@ -1599,7 +1611,9 @@ static int try_get_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
			V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE,
			inst->profile);
		break;

	case V4L2_CID_MPEG_VIDC_IMG_GRID_ENABLE:
		ctrl->val = inst->grid_enable;
		break;
	case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
		ctrl->val = msm_comm_hal_to_v4l2(
			V4L2_CID_MPEG_VIDEO_H264_LEVEL,
+49 −0
Original line number Diff line number Diff line
@@ -2323,6 +2323,50 @@ 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;
	u32 n_bframes;
	u32 n_pframes;

	slice_mode =  msm_comm_g_ctrl_for_id(inst,
		V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE);
	idr_period =  msm_comm_g_ctrl_for_id(inst,
		V4L2_CID_MPEG_VIDC_VIDEO_IDR_PERIOD);
	n_bframes =  msm_comm_g_ctrl_for_id(inst,
		V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES);
	n_pframes =  msm_comm_g_ctrl_for_id(inst,
		V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAMES);

	/*
	 * 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.
	 */
	if (inst->session_type == MSM_VIDC_ENCODER &&
		get_hal_codec(inst->fmts[CAPTURE_PORT].fourcc) ==
			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 (!(inst->prop.height[CAPTURE_PORT] ==
				inst->prop.width[CAPTURE_PORT] &&
				inst->prop.width[CAPTURE_PORT] ==
					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;
@@ -5279,6 +5323,11 @@ int msm_vidc_check_scaling_supported(struct msm_vidc_inst *inst)
	u32 input_height, input_width, output_height, output_width;
	u32 rotation;

	if (inst->grid_enable > 0) {
		dprintk(VIDC_DBG, "Skip scaling check for HEIC\n");
		return 0;
	}

	input_height = inst->prop.height[OUTPUT_PORT];
	input_width = inst->prop.width[OUTPUT_PORT];
	output_height = inst->prop.height[CAPTURE_PORT];
+5 −0
Original line number Diff line number Diff line
@@ -19,6 +19,11 @@
#define MAX_DEC_BATCH_WIDTH                    1920
#define MAX_DEC_BATCH_HEIGHT                   1088
#define SKIP_BATCH_WINDOW                      100
#define MIN_FRAME_QUALITY 0
#define MAX_FRAME_QUALITY 100
#define DEFAULT_FRAME_QUALITY 80
#define FRAME_QUALITY_STEP 1
#define HEIC_GRID_DIMENSION 512

struct vb2_buf_entry {
	struct list_head list;
Loading