Ver Fonte

video: driver: Add support to adjust slice mode

Add support to adjust slice mode.

Change-Id: Id09e951b3085c55cc5bc6b15a2ce002645923435
Signed-off-by: Akshata Sahukar <[email protected]>
Akshata Sahukar há 4 anos atrás
pai
commit
5a2b2ee399

+ 14 - 7
driver/platform/waipio/src/msm_vidc_waipio.c

@@ -25,6 +25,11 @@
 #define MAX_QP                  51
 #define DEFAULT_QP              20
 #define MAX_CONSTANT_QUALITY    100
+#define MIN_SLICE_BYTE_SIZE     512
+#define MAX_SLICE_BYTE_SIZE       \
+	((MAX_BITRATE) >> 3)
+#define MAX_SLICE_MB_SIZE         \
+	(((4096 + 15) >> 4) * ((2304 + 15) >> 4))
 
 #define UBWC_CONFIG(mc, ml, hbb, bs1, bs2, bs3, bsp) \
 {	\
@@ -329,7 +334,8 @@ static struct msm_platform_inst_capability instance_data_waipio[] = {
 		{0},
 		{LTR_COUNT, IR_RANDOM, TIME_DELTA_BASED_RC, I_FRAME_QP,
 			ENH_LAYER_COUNT, BIT_RATE, CONTENT_ADAPTIVE_CODING,
-			BITRATE_BOOST, MIN_QUALITY, VBV_DELAY, PEAK_BITRATE},
+			BITRATE_BOOST, MIN_QUALITY, VBV_DELAY, PEAK_BITRATE,
+			SLICE_MODE},
 		msm_vidc_adjust_bitrate_mode, msm_vidc_set_u32_enum},
 
 	{BITRATE_MODE, ENC, HEVC,
@@ -347,7 +353,7 @@ static struct msm_platform_inst_capability instance_data_waipio[] = {
 			CONSTANT_QUALITY, ENH_LAYER_COUNT,
 			CONTENT_ADAPTIVE_CODING, BIT_RATE,
 			BITRATE_BOOST, MIN_QUALITY, VBV_DELAY,
-			PEAK_BITRATE},
+			PEAK_BITRATE, SLICE_MODE},
 		msm_vidc_adjust_bitrate_mode, msm_vidc_set_u32_enum},
 
 	{LOSSLESS, ENC, HEVC|HEIC,
@@ -1027,18 +1033,19 @@ static struct msm_platform_inst_capability instance_data_waipio[] = {
 		V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE,
 		V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE,
 		0,
-		CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
-		{0}, {0},
-		NULL, msm_vidc_set_slice_count},
+		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+		{BITRATE_MODE}, {0},
+		msm_vidc_adjust_slice_count, msm_vidc_set_slice_count},
 
 	{SLICE_MAX_BYTES, ENC, H264|HEVC|HEIC,
-		1, INT_MAX, 1, INT_MAX,
+		MIN_SLICE_BYTE_SIZE, MAX_SLICE_BYTE_SIZE,
+		1, MIN_SLICE_BYTE_SIZE,
 		V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES,
 		HFI_PROP_MULTI_SLICE_BYTES_COUNT,
 		CAP_FLAG_OUTPUT_PORT},
 
 	{SLICE_MAX_MB, ENC, H264|HEVC|HEIC,
-		1, INT_MAX, 1, INT_MAX,
+		1, MAX_SLICE_MB_SIZE, 1, 1,
 		V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB,
 		HFI_PROP_MULTI_SLICE_MB_COUNT,
 		CAP_FLAG_OUTPUT_PORT},

+ 1 - 0
driver/vidc/inc/msm_vidc_control.h

@@ -28,6 +28,7 @@ int msm_vidc_adjust_mark_ltr(void *instance, struct v4l2_ctrl *ctrl);
 int msm_vidc_adjust_ir_random(void *instance, struct v4l2_ctrl *ctrl);
 int msm_vidc_adjust_delta_based_rc(void *instance, struct v4l2_ctrl *ctrl);
 int msm_vidc_adjust_transform_8x8(void *instance, struct v4l2_ctrl *ctrl);
+int msm_vidc_adjust_slice_count(void *instance, struct v4l2_ctrl *ctrl);
 int msm_vidc_adjust_layer_count(void *instance, struct v4l2_ctrl *ctrl);
 int msm_vidc_adjust_gop_size(void *instance, struct v4l2_ctrl *ctrl);
 int msm_vidc_adjust_b_frame(void *instance, struct v4l2_ctrl *ctrl);

+ 9 - 0
driver/vidc/inc/msm_vidc_internal.h

@@ -56,6 +56,15 @@
 #define MAX_AVC_ENH_LAYER_HYBRID_HP           5
 #define PERCENT_PEAK_BITRATE_INCREASED       10
 #define INVALID_DEFAULT_MARK_OR_USE_LTR      -1
+#define MAX_SLICES_PER_FRAME                 10
+#define MAX_SLICES_FRAME_RATE                60
+#define MAX_MB_SLICE_WIDTH                 4096
+#define MAX_MB_SLICE_HEIGHT                2160
+#define MAX_BYTES_SLICE_WIDTH              1920
+#define MAX_BYTES_SLICE_HEIGHT             1088
+#define MIN_HEVC_SLICE_WIDTH                384
+#define MIN_AVC_SLICE_WIDTH                 192
+#define MIN_SLICE_HEIGHT                    128
 
 #define DCVS_WINDOW 16
 /* Superframe can have maximum of 32 frames */

+ 19 - 2
driver/vidc/src/msm_venc.c

@@ -1245,6 +1245,7 @@ static int msm_venc_s_fmt_input(struct msm_vidc_inst *inst, struct v4l2_format *
 
 	if (fmt->fmt.pix_mp.width != crop_width ||
 		fmt->fmt.pix_mp.height != crop_height) {
+		struct v4l2_format *output_fmt;
 
 		/* reset crop dimensions with updated resolution */
 		inst->crop.top = inst->crop.left = 0;
@@ -1256,9 +1257,17 @@ static int msm_venc_s_fmt_input(struct msm_vidc_inst *inst, struct v4l2_format *
 		inst->compose.width = f->fmt.pix_mp.width;
 		inst->compose.height = f->fmt.pix_mp.height;
 
-		rc = msm_venc_s_fmt_output(inst, &inst->fmts[OUTPUT_PORT]);
+		output_fmt = &inst->fmts[OUTPUT_PORT];
+		rc = msm_venc_s_fmt_output(inst, output_fmt);
 		if (rc)
 			return rc;
+
+		i_vpr_h(inst,
+			"%s: type %d: format %#x width %d height %d size %d\n",
+			__func__, output_fmt->type, output_fmt->fmt.pix_mp.pixelformat,
+			output_fmt->fmt.pix_mp.width,
+			output_fmt->fmt.pix_mp.height,
+			output_fmt->fmt.pix_mp.plane_fmt[0].sizeimage);
 	}
 
 	//rc = msm_vidc_check_session_supported(inst);
@@ -1385,6 +1394,7 @@ int msm_venc_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
 int msm_venc_s_selection(struct msm_vidc_inst* inst, struct v4l2_selection* s)
 {
 	int rc = 0;
+	struct v4l2_format *output_fmt;
 
 	if (!inst || !s) {
 		d_vpr_e("%s: invalid params\n", __func__);
@@ -1431,9 +1441,16 @@ int msm_venc_s_selection(struct msm_vidc_inst* inst, struct v4l2_selection* s)
 		if (inst->compose.height > inst->crop.height)
 			inst->compose.height = inst->crop.height;
 		/* update output format based on new crop dimensions */
-		rc = msm_venc_s_fmt_output(inst, &inst->fmts[OUTPUT_PORT]);
+		output_fmt = &inst->fmts[OUTPUT_PORT];
+		rc = msm_venc_s_fmt_output(inst, output_fmt);
 		if (rc)
 			return rc;
+		i_vpr_h(inst,
+			"%s: type %d: format %#x width %d height %d size %d\n",
+			__func__, output_fmt->type, output_fmt->fmt.pix_mp.pixelformat,
+			output_fmt->fmt.pix_mp.width,
+			output_fmt->fmt.pix_mp.height,
+			output_fmt->fmt.pix_mp.plane_fmt[0].sizeimage);
 		break;
 	case V4L2_SEL_TGT_COMPOSE_BOUNDS:
 	case V4L2_SEL_TGT_COMPOSE_PADDED:

+ 109 - 1
driver/vidc/src/msm_vidc_control.c

@@ -1072,6 +1072,112 @@ int msm_vidc_adjust_transform_8x8(void *instance, struct v4l2_ctrl *ctrl)
 	return 0;
 }
 
+int msm_vidc_adjust_slice_count(void *instance, struct v4l2_ctrl *ctrl)
+{
+	struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance;
+	struct msm_vidc_inst_capability *capability;
+	struct v4l2_format *output_fmt;
+	s32 adjusted_value, rc_type = -1, slice_mode;
+	u32 slice_val, mbpf = 0, mbps = 0, max_mbpf = 0, max_mbps = 0;
+	u32 update_cap, max_avg_slicesize, output_width, output_height;
+	u32 min_width, min_height, max_width, max_height, fps;
+
+	if (!inst || !inst->capabilities) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+	capability = inst->capabilities;
+
+	slice_mode = ctrl ? ctrl->val :
+		capability->cap[SLICE_MODE].value;
+
+	if (msm_vidc_get_parent_value(inst, SLICE_MODE,
+		BITRATE_MODE, &rc_type, __func__))
+		return -EINVAL;
+
+	if (slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE)
+		return 0;
+
+	fps = capability->cap[FRAME_RATE].value >> 16;
+	if (fps > MAX_SLICES_FRAME_RATE ||
+		(rc_type != HFI_RC_OFF &&
+		rc_type != HFI_RC_CBR_CFR &&
+		rc_type != HFI_RC_CBR_VFR)) {
+		adjusted_value = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE;
+		update_cap = SLICE_MODE;
+		i_vpr_h(inst,
+			"%s: slice unsupported, fps: %u, rc_type: %#x\n",
+			__func__, fps, rc_type);
+		goto exit;
+	}
+
+	output_fmt = &inst->fmts[OUTPUT_PORT];
+	output_width = output_fmt->fmt.pix_mp.width;
+	output_height = output_fmt->fmt.pix_mp.height;
+
+	max_width = (slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) ?
+		MAX_MB_SLICE_WIDTH : MAX_BYTES_SLICE_WIDTH;
+	max_height = (slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) ?
+		MAX_MB_SLICE_HEIGHT : MAX_BYTES_SLICE_HEIGHT;
+	min_width = (inst->codec == MSM_VIDC_HEVC) ?
+		MIN_HEVC_SLICE_WIDTH : MIN_AVC_SLICE_WIDTH;
+	min_height = MIN_SLICE_HEIGHT;
+
+	/*
+	 * For V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB:
+	 * 	- width >= 384 and height >= 128
+	 * 	- width and height <= 4096
+	 * For V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES:
+	 * 	- width >= 192 and height >= 128
+	 * 	- width and height <= 1920
+	 */
+	if (output_width < min_width || output_height < min_height ||
+		output_width > max_width || output_height > max_width) {
+		adjusted_value = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE;
+		update_cap = SLICE_MODE;
+		i_vpr_h(inst,
+			"%s: slice unsupported, codec: %#x wxh: [%dx%d]\n",
+			__func__, inst->codec, output_width, output_height);
+		goto exit;
+	}
+
+	mbpf = NUM_MBS_PER_FRAME(output_height, output_width);
+	mbps = NUM_MBS_PER_SEC(output_height, output_width, fps);
+	max_mbpf = NUM_MBS_PER_FRAME(max_height, max_width);
+	max_mbps = NUM_MBS_PER_SEC(max_height, max_width, fps);
+
+	if (mbpf > max_mbpf || mbps > max_mbps) {
+		adjusted_value = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE;
+		update_cap = SLICE_MODE;
+		i_vpr_h(inst,
+			"%s: Unsupported, mbpf[%u] > max[%u], mbps[%u] > max[%u]\n",
+			__func__, mbpf, max_mbpf, mbps, max_mbps);
+		goto exit;
+	}
+
+	if (slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) {
+		update_cap = SLICE_MAX_MB;
+		slice_val = capability->cap[SLICE_MAX_MB].value;
+		slice_val = max(slice_val, mbpf / MAX_SLICES_PER_FRAME);
+	} else {
+		slice_val = capability->cap[SLICE_MAX_BYTES].value;
+		update_cap = SLICE_MAX_BYTES;
+		if (rc_type != HFI_RC_OFF) {
+			max_avg_slicesize = ((capability->cap[BIT_RATE].value /
+				fps) / 8) /
+				MAX_SLICES_PER_FRAME;
+			slice_val = max(slice_val, max_avg_slicesize);
+		}
+	}
+	adjusted_value = slice_val;
+
+exit:
+	msm_vidc_update_cap_value(inst, update_cap,
+		adjusted_value, __func__);
+
+	return 0;
+}
+
 static int msm_vidc_adjust_static_layer_count_and_type(struct msm_vidc_inst *inst,
 	s32 layer_count)
 {
@@ -2033,7 +2139,9 @@ int msm_vidc_set_slice_count(void* instance,
 		return 0;
 	}
 	if (slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) {
-		hfi_value = inst->capabilities->cap[SLICE_MAX_MB].value;
+		hfi_value = (inst->codec == MSM_VIDC_HEVC) ?
+			((inst->capabilities->cap[SLICE_MAX_MB].value + 3) / 4) :
+			inst->capabilities->cap[SLICE_MAX_MB].value;
 		set_cap_id = SLICE_MAX_MB;
 	} else if (slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES) {
 		hfi_value = inst->capabilities->cap[SLICE_MAX_BYTES].value;