Browse Source

video: driver: Add support to handle GOP and its dependencies

Add support to below mentioned properties:
- HFI_PROP_LAYER_ENCODING_TYPE
- HFI_PROP_LAYER_COUNT
- HFI_PROP_MAX_GOP_FRAMES
- HFI_PROP_MAX_B_FRAMES.

Change-Id: I3be975a48dc668d0ec83f6ff13837488fc570b78
Signed-off-by: Akshata Sahukar <[email protected]>
Akshata Sahukar 4 năm trước cách đây
mục cha
commit
98e799da29

+ 34 - 30
driver/platform/waipio/src/msm_vidc_waipio.c

@@ -60,6 +60,7 @@ static struct msm_platform_core_capability core_data_waipio[] = {
 	{MAX_MBPS_HQ, 489600}, /* ((1920x1088)/256)@60fps */
 	{MAX_MBPF_B_FRAME, 32640}, /* 3840x2176/256 */
 	{MAX_MBPS_B_FRAME, 1958400}, /* 3840x2176/256 MBs@60fps */
+	{MAX_ENH_LAYER_COUNT, 5},
 	{NUM_VPP_PIPE, 4},
 	{SW_PC, 1},
 	{SW_PC_DELAY, 20000}, /* 20000 ms (>HW_RESPONSE_TIMEOUT)*/
@@ -193,12 +194,6 @@ static struct msm_platform_inst_capability instance_data_waipio[] = {
 	{SCALE_X, DEC, H264|HEVC|VP9, 65536, 65536, 1, 65536},
 	{SCALE_Y, ENC, H264|HEVC, 8192, 65536, 1, 8192},
 	{SCALE_Y, DEC, H264|HEVC|VP9, 65536, 65536, 1, 65536},
-	{B_FRAME, ENC, H264|HEVC,
-		V4L2_MPEG_MSM_VIDC_DISABLE, V4L2_MPEG_MSM_VIDC_ENABLE,
-		1, V4L2_MPEG_MSM_VIDC_DISABLE,
-		V4L2_CID_MPEG_VIDEO_B_FRAMES,
-		HFI_PROP_MAX_B_FRAMES,
-		CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT},
 
 	{MB_CYCLES_VSP, ENC, CODECS_ALL, 25, 25, 1, 25},
 	{MB_CYCLES_VSP, DEC, CODECS_ALL, 25, 25, 1, 25},
@@ -328,7 +323,8 @@ static struct msm_platform_inst_capability instance_data_waipio[] = {
 		HFI_PROP_RATE_CONTROL,
 		CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
 		{0},
-		{LTR_COUNT, IR_RANDOM, TIME_DELTA_BASED_RC, I_FRAME_QP},
+		{LTR_COUNT, IR_RANDOM, TIME_DELTA_BASED_RC, I_FRAME_QP,
+			ENH_LAYER_COUNT},
 		msm_vidc_adjust_bitrate_mode, msm_vidc_set_u32_enum},
 
 	{BITRATE_MODE, ENC, HEVC,
@@ -343,7 +339,7 @@ static struct msm_platform_inst_capability instance_data_waipio[] = {
 		CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
 		{0},
 		{LTR_COUNT, IR_RANDOM, TIME_DELTA_BASED_RC,
-			I_FRAME_QP, CONSTANT_QUALITY},
+			I_FRAME_QP, CONSTANT_QUALITY, ENH_LAYER_COUNT},
 		msm_vidc_adjust_bitrate_mode, msm_vidc_set_u32_enum},
 
 	{LOSSLESS, ENC, HEVC|HEIC,
@@ -375,14 +371,14 @@ static struct msm_platform_inst_capability instance_data_waipio[] = {
 		{BITRATE_MODE}, {0},
 		NULL, msm_vidc_set_constant_quality},
 
-	// TODO: GOP dependencies
 	{GOP_SIZE, ENC, CODECS_ALL,
 		0, INT_MAX, 1, 2 * DEFAULT_FPS - 1,
 		V4L2_CID_MPEG_VIDEO_GOP_SIZE,
 		HFI_PROP_MAX_GOP_FRAMES,
-		CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED,
-		{0}, {0},
-		NULL, msm_vidc_set_u32},
+		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED,
+		{ENH_LAYER_COUNT},
+		{0},
+		msm_vidc_adjust_gop_size, msm_vidc_set_gop_size},
 
 	{GOP_CLOSURE, ENC, H264|HEVC,
 		V4L2_MPEG_MSM_VIDC_DISABLE, V4L2_MPEG_MSM_VIDC_ENABLE,
@@ -390,6 +386,15 @@ static struct msm_platform_inst_capability instance_data_waipio[] = {
 		V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
 		0},
 
+	{B_FRAME, ENC, H264|HEVC,
+		0, 7, 1, 0,
+		V4L2_CID_MPEG_VIDEO_B_FRAMES,
+		HFI_PROP_MAX_B_FRAMES,
+		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED,
+		{ENH_LAYER_COUNT},
+		{0},
+		msm_vidc_adjust_b_frame, msm_vidc_set_u32},
+
 	{BLUR_TYPES, ENC, CODECS_ALL,
 		VIDC_BLUR_NONE, VIDC_BLUR_ADAPTIVE, 1, VIDC_BLUR_NONE,
 		V4L2_CID_MPEG_VIDC_VIDEO_BLUR_TYPES,
@@ -662,8 +667,7 @@ static struct msm_platform_inst_capability instance_data_waipio[] = {
 		HFI_PROP_QP_PACKED,
 		CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT},
 
-	// TODO: Enable while reveiwing support for layer encoding
-	{HIER_CODING_TYPE, ENC, HEVC,
+	{LAYER_TYPE, ENC, HEVC,
 		V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B,
 		V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P,
 		BIT(V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B) |
@@ -671,12 +675,9 @@ static struct msm_platform_inst_capability instance_data_waipio[] = {
 		V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P,
 		V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE,
 		HFI_PROP_LAYER_ENCODING_TYPE,
-		CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
-		{0}, {0},
-		NULL, NULL},
+		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
 
-	/* TODO(AS) - ctrl init failing. Need to fix
-	{HIER_CODING_TYPE, ENC, H264,
+	{LAYER_TYPE, ENC, H264,
 		V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B,
 		V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P,
 		BIT(V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B) |
@@ -684,29 +685,32 @@ static struct msm_platform_inst_capability instance_data_waipio[] = {
 		V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P,
 		V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE,
 		HFI_PROP_LAYER_ENCODING_TYPE,
-		CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
-	*/
+		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU},
 
-	//TODO (AS)
-	{HIER_CODING, ENC, H264,
+	{LAYER_ENABLE, ENC, H264,
 		V4L2_MPEG_MSM_VIDC_DISABLE, V4L2_MPEG_MSM_VIDC_ENABLE,
 		1, V4L2_MPEG_MSM_VIDC_DISABLE,
 		V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING,
 		HFI_PROP_LAYER_ENCODING_TYPE,
-		CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT},
+		CAP_FLAG_OUTPUT_PORT},
 
-	// TODO: add relationship with GOP_SIZE in caps
-	{HIER_CODING_LAYER, ENC, HEVC,
+	{ENH_LAYER_COUNT, ENC, HEVC,
 		0, 5, 1, 0,
 		V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER,
 		HFI_PROP_LAYER_COUNT,
-		CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT},
+		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED,
+		{BITRATE_MODE},
+		{GOP_SIZE, B_FRAME},
+		msm_vidc_adjust_layer_count, msm_vidc_set_layer_count_and_type},
 
-	{HIER_CODING_LAYER, ENC, H264,
-		0, 6, 1, 0,
+	{ENH_LAYER_COUNT, ENC, H264,
+		0, 5, 1, 0,
 		V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER,
 		HFI_PROP_LAYER_COUNT,
-		CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT},
+		CAP_FLAG_OUTPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED,
+		{BITRATE_MODE},
+		{GOP_SIZE, B_FRAME},
+		msm_vidc_adjust_layer_count, msm_vidc_set_layer_count_and_type},
 
 	{L0_BR, ENC, HEVC,
 		1, 220000000, 1, 20000000,

+ 35 - 23
driver/variant/iris2/src/msm_vidc_buffer_iris2.c

@@ -277,13 +277,42 @@ static u32 msm_vidc_encoder_bin_size_iris2(struct msm_vidc_inst *inst)
 	return size;
 }
 
+static u32 msm_vidc_get_recon_buf_count(struct msm_vidc_inst *inst)
+{
+	u32 num_buf_recon = 0;
+	s32 n_bframe, ltr_count, hp_layers = 0, hb_layers = 0;
+	bool is_hybrid_hp = false;
+	u32 hfi_codec = 0;
+
+	n_bframe = inst->capabilities->cap[B_FRAME].value;
+	ltr_count = inst->capabilities->cap[LTR_COUNT].value;
+
+	if (inst->hfi_layer_type == HFI_HIER_B) {
+		hb_layers = inst->capabilities->cap[ENH_LAYER_COUNT].value + 1;
+	} else {
+		hp_layers = inst->capabilities->cap[ENH_LAYER_COUNT].value + 1;
+		if (inst->hfi_layer_type == HFI_HIER_P_HYBRID_LTR)
+			is_hybrid_hp = true;
+	}
+
+	if (inst->codec == MSM_VIDC_H264)
+		hfi_codec = HFI_CODEC_ENCODE_AVC;
+	else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC)
+		hfi_codec = HFI_CODEC_ENCODE_HEVC;
+
+	HFI_IRIS2_ENC_RECON_BUF_COUNT(num_buf_recon, n_bframe, ltr_count,
+			hp_layers, hb_layers, is_hybrid_hp, hfi_codec);
+
+	return num_buf_recon;
+}
+
 static u32 msm_vidc_encoder_comv_size_iris2(struct msm_vidc_inst* inst)
 {
 	u32 size = 0;
 	u32 width, height, num_recon = 0;
 	struct v4l2_format* f;
 
-	if (!inst || !inst->core) {
+	if (!inst || !inst->core || !inst->capabilities) {
 		d_vpr_e("%s: invalid params\n", __func__);
 		return size;
 	}
@@ -292,17 +321,11 @@ static u32 msm_vidc_encoder_comv_size_iris2(struct msm_vidc_inst* inst)
 	width = f->fmt.pix_mp.width;
 	height = f->fmt.pix_mp.height;
 
-	if (inst->codec == MSM_VIDC_H264) {
-		// TODO: replace zeros with appropriate variables
-		HFI_IRIS2_ENC_RECON_BUF_COUNT(num_recon, 0, 0, 0, 0, 0,
-			HFI_CODEC_ENCODE_AVC);
+	num_recon = msm_vidc_get_recon_buf_count(inst);
+	if (inst->codec == MSM_VIDC_H264)
 		HFI_BUFFER_COMV_H264E(size, width, height, num_recon);
-	} else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC) {
-		// TODO: replace zeros with appropriate variables
-		HFI_IRIS2_ENC_RECON_BUF_COUNT(num_recon, 0, 0, 0, 0, 0,
-			HFI_CODEC_ENCODE_HEVC);
+	else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC)
 		HFI_BUFFER_COMV_H265E(size, width, height, num_recon);
-	}
 
 	i_vpr_l(inst, "%s: size %d\n", __func__, size);
 	return size;
@@ -521,23 +544,12 @@ int msm_buffer_size_iris2(struct msm_vidc_inst *inst,
 
 static int msm_buffer_encoder_dpb_count(struct msm_vidc_inst *inst)
 {
-	int count = 0;
-
-	if (!inst) {
+	if (!inst || !inst->capabilities) {
 		d_vpr_e("%s: invalid params\n", __func__);
 		return 0;
 	}
 
-	if (inst->codec == MSM_VIDC_H264) {
-		// TODO: replace zeros with appropriate variables
-		HFI_IRIS2_ENC_RECON_BUF_COUNT(count, 0, 0, 0, 0, 0,
-			HFI_CODEC_ENCODE_AVC);
-	} else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC) {
-		// TODO: replace zeros with appropriate variables
-		HFI_IRIS2_ENC_RECON_BUF_COUNT(count, 0, 0, 0, 0, 0,
-			HFI_CODEC_ENCODE_HEVC);
-	}
-	return count;
+	return msm_vidc_get_recon_buf_count(inst);
 }
 
 static int msm_buffer_decoder_dpb_count(struct msm_vidc_inst *inst)

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

@@ -28,6 +28,9 @@ 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_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);
 int msm_vidc_adjust_hevc_min_qp(void *instance, struct v4l2_ctrl *ctrl);
 int msm_vidc_adjust_hevc_max_qp(void *instance, struct v4l2_ctrl *ctrl);
 int msm_vidc_adjust_hevc_frame_qp(void *instance, struct v4l2_ctrl *ctrl);
@@ -49,6 +52,10 @@ int msm_vidc_set_chroma_qp_index_offset(void *instance,
 	enum msm_vidc_inst_capability_type cap_id);
 int msm_vidc_set_slice_count(void* instance,
 	enum msm_vidc_inst_capability_type cap_id);
+int msm_vidc_set_layer_count_and_type(void *instance,
+	enum msm_vidc_inst_capability_type cap_id);
+int msm_vidc_set_gop_size(void *instance,
+	enum msm_vidc_inst_capability_type cap_id);
 int msm_vidc_set_u32(void *instance,
 	enum msm_vidc_inst_capability_type cap_id);
 int msm_vidc_set_u32_enum(void *instance,

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

@@ -103,6 +103,7 @@ struct msm_vidc_inst {
 	struct msm_vidc_inst_cap_entry     children;
 	struct msm_vidc_inst_cap_entry     firmware;
 	enum hfi_rate_control              hfi_rc_type;
+	enum hfi_layer_encoding_type       hfi_layer_type;
 	bool                               request;
 	struct vb2_queue                   vb2q[MAX_PORT];
 	struct msm_vidc_rectangle          crop;

+ 10 - 4
driver/vidc/inc/msm_vidc_internal.h

@@ -50,6 +50,11 @@
 #define BIT_DEPTH_10 (10 << 16 | 10)
 #define CODED_FRAMES_PROGRESSIVE 0x0
 #define CODED_FRAMES_INTERLACE 0x1
+/* TODO: move below macros to waipio.c */
+#define MAX_ENH_LAYER_HB        3
+#define MAX_HEVC_ENH_LAYER_SLIDING_WINDOW     5
+#define MAX_AVC_ENH_LAYER_SLIDING_WINDOW      3
+#define MAX_AVC_ENH_LAYER_HYBRID_HP           5
 
 /* TODO
  * #define MAX_SUPERFRAME_COUNT     32
@@ -269,6 +274,7 @@ enum msm_vidc_core_capability_type {
 	MAX_MBPS_HQ,
 	MAX_MBPF_B_FRAME,
 	MAX_MBPS_B_FRAME,
+	MAX_ENH_LAYER_COUNT,
 	NUM_VPP_PIPE,
 	SW_PC,
 	SW_PC_DELAY,
@@ -313,7 +319,6 @@ enum msm_vidc_inst_capability_type {
 	OPERATING_RATE,
 	SCALE_X,
 	SCALE_Y,
-	B_FRAME,
 	MB_CYCLES_VSP,
 	MB_CYCLES_VPP,
 	MB_CYCLES_LP,
@@ -339,6 +344,7 @@ enum msm_vidc_inst_capability_type {
 	CONSTANT_QUALITY,
 	GOP_SIZE,
 	GOP_CLOSURE,
+	B_FRAME,
 	BLUR_TYPES,
 	BLUR_RESOLUTION,
 	CSC,
@@ -374,9 +380,9 @@ enum msm_vidc_inst_capability_type {
 	L4_QP,
 	L5_QP,
 	HIER_LAYER_QP,
-	HIER_CODING_TYPE,
-	HIER_CODING,
-	HIER_CODING_LAYER,
+	LAYER_TYPE,
+	LAYER_ENABLE,
+	ENH_LAYER_COUNT,
 	L0_BR,
 	L1_BR,
 	L2_BR,

+ 12 - 0
driver/vidc/src/msm_venc.c

@@ -986,12 +986,23 @@ int msm_venc_process_cmd(struct msm_vidc_inst *inst, u32 cmd)
 int msm_venc_streamoff_output(struct msm_vidc_inst *inst)
 {
 	int rc = 0;
+	struct msm_vidc_core *core;
 
 	if (!inst || !inst->core || !inst->capabilities) {
 		d_vpr_e("%s: invalid params\n", __func__);
 		return -EINVAL;
 	}
 
+	core = inst->core;
+	if (!core->capabilities) {
+		i_vpr_e(inst, "%s: core capabilities is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	/* restore LAYER_COUNT max allowed value */
+	inst->capabilities->cap[ENH_LAYER_COUNT].max =
+		core->capabilities[MAX_ENH_LAYER_COUNT].value;
+
 	rc = msm_vidc_session_streamoff(inst, OUTPUT_PORT);
 	if (rc)
 		return rc;
@@ -1774,6 +1785,7 @@ int msm_venc_inst_init(struct msm_vidc_inst *inst)
 	inst->buffers.input_meta.size = 0;
 
 	inst->hfi_rc_type = HFI_RC_VBR_CFR;
+	inst->hfi_layer_type = HFI_HIER_P_SLIDING_WINDOW;
 
 	rc = msm_venc_codec_change(inst,
 			inst->fmts[OUTPUT_PORT].fmt.pix_mp.pixelformat);

+ 319 - 3
driver/vidc/src/msm_vidc_control.c

@@ -18,6 +18,8 @@
 
 static bool is_priv_ctrl(u32 id)
 {
+	bool private = false;
+
 	if (IS_PRIV_CTRL(id))
 		return true;
 
@@ -25,8 +27,21 @@ static bool is_priv_ctrl(u32 id)
 	 * Treat below standard controls as private because
 	 * we have added custom values to the controls
 	 */
+	switch (id) {
+	/*
+	 * TODO: V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE is
+	 * std ctrl. But needs some fixes in v4l2-ctrls.c. Hence,
+	 * make this as private ctrl for time being
+	 */
+	case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE:
+		private = true;
+		break;
+	default:
+		private = false;
+		break;
+	}
 
-	return false;
+	return private;
 }
 
 static bool is_meta_ctrl(u32 id)
@@ -75,6 +90,12 @@ static const char *const mpeg_video_blur_types[] = {
 	NULL,
 };
 
+static const char *const mpeg_video_avc_coding_layer[] = {
+	"B",
+	"P",
+	NULL,
+};
+
 static const char *const roi_map_type[] = {
 	"None",
 	"2-bit",
@@ -112,6 +133,8 @@ static const char * const * msm_vidc_get_qmenu_type(
 		return mpeg_video_stream_format;
 	case V4L2_CID_MPEG_VIDC_VIDEO_BLUR_TYPES:
 		return mpeg_video_blur_types;
+	case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE:
+		return mpeg_video_avc_coding_layer;
 	default:
 		i_vpr_e(inst, "%s: No available qmenu for ctrl %#x\n",
 			__func__, control_id);
@@ -257,10 +280,17 @@ static int msm_vidc_get_parent_value(struct msm_vidc_inst* inst,
 	int rc = 0;
 
 	if (is_parent_available(inst, cap, parent)) {
-		if (parent == BITRATE_MODE)
+		switch (parent) {
+		case BITRATE_MODE:
 			*value = inst->hfi_rc_type;
-		else
+			break;
+		case LAYER_TYPE:
+			*value = inst->hfi_layer_type;
+			break;
+		default:
 			*value = inst->capabilities->cap[parent].value;
+			break;
+		}
 	} else {
 		i_vpr_e(inst,
 			"%s: missing parent %d for cap %d, please correct database\n",
@@ -994,6 +1024,219 @@ int msm_vidc_adjust_transform_8x8(void *instance, struct v4l2_ctrl *ctrl)
 	return 0;
 }
 
+static int msm_vidc_adjust_static_layer_count_and_type(struct msm_vidc_inst *inst,
+	s32 layer_count)
+{
+	bool hb_requested = false;
+
+	if (!inst || !inst->capabilities) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!layer_count) {
+		i_vpr_h(inst, "client not enabled layer encoding\n");
+		goto exit;
+	}
+
+	if (inst->hfi_rc_type == HFI_RC_CQ) {
+		i_vpr_h(inst, "rc type is CQ, disabling layer encoding\n");
+		layer_count = 0;
+		goto exit;
+	}
+
+	if (inst->codec == MSM_VIDC_H264) {
+		if (!inst->capabilities->cap[LAYER_ENABLE].value) {
+			layer_count = 0;
+			goto exit;
+		}
+
+		hb_requested = (inst->capabilities->cap[LAYER_TYPE].value ==
+				V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B) ?
+				true : false;
+	} else if (inst->codec == MSM_VIDC_HEVC) {
+		hb_requested = (inst->capabilities->cap[LAYER_TYPE].value ==
+				V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B) ?
+				true : false;
+	}
+
+	if (hb_requested && inst->hfi_rc_type != HFI_RC_VBR_CFR) {
+		i_vpr_h(inst,
+			"%s: HB layer encoding is supported for VBR rc only\n",
+			__func__);
+		layer_count = 0;
+		goto exit;
+	}
+
+	/* decide hfi layer type */
+	if (hb_requested) {
+		inst->hfi_layer_type = HFI_HIER_B;
+	} else {
+		/* HP requested */
+		inst->hfi_layer_type = HFI_HIER_P_SLIDING_WINDOW;
+		if (inst->codec == MSM_VIDC_H264 &&
+			inst->hfi_rc_type == HFI_RC_VBR_CFR)
+			inst->hfi_layer_type = HFI_HIER_P_HYBRID_LTR;
+	}
+
+	/* sanitize layer count based on layer type and codec */
+	if (inst->hfi_layer_type == HFI_HIER_B) {
+		if (layer_count > MAX_ENH_LAYER_HB)
+			layer_count = MAX_ENH_LAYER_HB;
+	} else if (inst->hfi_layer_type == HFI_HIER_P_HYBRID_LTR) {
+		if (layer_count > MAX_AVC_ENH_LAYER_HYBRID_HP)
+			layer_count = MAX_AVC_ENH_LAYER_HYBRID_HP;
+	} else if (inst->hfi_layer_type == HFI_HIER_P_SLIDING_WINDOW) {
+		if (inst->codec == MSM_VIDC_H264) {
+			if (layer_count > MAX_AVC_ENH_LAYER_SLIDING_WINDOW)
+				layer_count = MAX_AVC_ENH_LAYER_SLIDING_WINDOW;
+		} else {
+			if (layer_count > MAX_HEVC_ENH_LAYER_SLIDING_WINDOW)
+				layer_count = MAX_HEVC_ENH_LAYER_SLIDING_WINDOW;
+		}
+	}
+
+exit:
+	msm_vidc_update_cap_value(inst, ENH_LAYER_COUNT,
+		layer_count, __func__);
+	inst->capabilities->cap[ENH_LAYER_COUNT].max = layer_count;
+	return 0;
+}
+
+int msm_vidc_adjust_layer_count(void *instance, struct v4l2_ctrl *ctrl)
+{
+	int rc = 0;
+	struct msm_vidc_inst_capability *capability;
+	s32 client_layer_count;
+	struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance;
+
+	if (!inst || !inst->capabilities) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+	capability = inst->capabilities;
+
+	client_layer_count = ctrl ? ctrl->val :
+		capability->cap[ENH_LAYER_COUNT].value;
+
+	if (!is_parent_available(inst, ENH_LAYER_COUNT, BITRATE_MODE)) {
+		i_vpr_e(inst, "%s: missing parent %d in database",
+			__func__, BITRATE_MODE);
+		return -EINVAL;
+	}
+
+	if (!inst->vb2q[OUTPUT_PORT].streaming) {
+		rc = msm_vidc_adjust_static_layer_count_and_type(inst,
+			client_layer_count);
+		if (rc)
+			goto exit;
+	} else {
+		if (inst->hfi_layer_type == HFI_HIER_P_HYBRID_LTR ||
+			inst->hfi_layer_type == HFI_HIER_P_SLIDING_WINDOW) {
+			/* dynamic layer count change is only supported for HP */
+			if (client_layer_count >
+				inst->capabilities->cap[ENH_LAYER_COUNT].max)
+				client_layer_count =
+					inst->capabilities->cap[ENH_LAYER_COUNT].max;
+
+			msm_vidc_update_cap_value(inst, ENH_LAYER_COUNT,
+				client_layer_count, __func__);
+		}
+	}
+
+exit:
+	return rc;
+}
+
+/*
+ * 1. GOP calibration is only done for HP layer encoding type.
+ * 2. Dynamic GOP size should not exceed static GOP size
+ * 3. For HB case, or when layer encoding is not enabled,
+ *    client set GOP size is directly set to FW.
+ */
+int msm_vidc_adjust_gop_size(void *instance, struct v4l2_ctrl *ctrl)
+{
+	struct msm_vidc_inst_capability *capability;
+	struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance;
+	s32 adjusted_value, enh_layer_count = -1;
+
+	if (!inst || !inst->capabilities) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+	capability = inst->capabilities;
+
+	adjusted_value = ctrl ? ctrl->val : capability->cap[GOP_SIZE].value;
+
+	if (msm_vidc_get_parent_value(inst, GOP_SIZE,
+		ENH_LAYER_COUNT, &enh_layer_count, __func__))
+		return -EINVAL;
+
+	if (!enh_layer_count)
+		goto exit;
+
+	/* calibrate GOP size */
+	if (inst->hfi_layer_type == HFI_HIER_P_SLIDING_WINDOW ||
+		inst->hfi_layer_type == HFI_HIER_P_HYBRID_LTR) {
+		/*
+		 * Layer encoding needs GOP size to be multiple of subgop size
+		 * And subgop size is 2 ^ number of enhancement layers.
+		 */
+		u32 min_gop_size;
+		u32 num_subgops;
+
+		/* v4l2 layer count is the number of enhancement layers */
+		min_gop_size = 1 << enh_layer_count;
+		num_subgops = (adjusted_value + (min_gop_size >> 1)) /
+				min_gop_size;
+		if (num_subgops)
+			adjusted_value = num_subgops * min_gop_size;
+		else
+			adjusted_value = min_gop_size;
+	}
+
+exit:
+	msm_vidc_update_cap_value(inst, GOP_SIZE, adjusted_value, __func__);
+	return 0;
+}
+
+int msm_vidc_adjust_b_frame(void *instance, struct v4l2_ctrl *ctrl)
+{
+	struct msm_vidc_inst_capability *capability;
+	struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance;
+	s32 adjusted_value, enh_layer_count = -1;
+	const u32 max_bframe_size = 7;
+
+	if (!inst || !inst->capabilities) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+	capability = inst->capabilities;
+
+	if (inst->vb2q[OUTPUT_PORT].streaming)
+		return 0;
+
+	adjusted_value = ctrl ? ctrl->val : capability->cap[B_FRAME].value;
+
+	if (msm_vidc_get_parent_value(inst, B_FRAME,
+		ENH_LAYER_COUNT, &enh_layer_count, __func__))
+		return -EINVAL;
+
+	if (!enh_layer_count || inst->hfi_layer_type != HFI_HIER_B) {
+		adjusted_value = 0;
+		goto exit;
+	}
+
+	adjusted_value = (2 << enh_layer_count) - 1;
+	/* Allowed Bframe values are 0, 1, 3, 7 */
+	if (adjusted_value > max_bframe_size)
+		adjusted_value = max_bframe_size;
+
+exit:
+	msm_vidc_update_cap_value(inst, B_FRAME, adjusted_value, __func__);
+	return 0;
+}
+
 int msm_vidc_adjust_hevc_min_qp(void *instance, struct v4l2_ctrl *ctrl)
 {
 	int rc = 0;
@@ -1493,6 +1736,79 @@ int msm_vidc_set_nal_length(void* instance,
 	return rc;
 }
 
+int msm_vidc_set_layer_count_and_type(void *instance,
+	enum msm_vidc_inst_capability_type cap_id)
+{
+	int rc = 0;
+	struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance;
+	u32 hfi_layer_count, hfi_layer_type = 0;
+
+	if (!inst || !inst->capabilities) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!inst->vb2q[OUTPUT_PORT].streaming) {
+		/* set layer type */
+		hfi_layer_type = inst->hfi_layer_type;
+		cap_id = LAYER_TYPE;
+
+		rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32_ENUM,
+			&hfi_layer_type, sizeof(u32), __func__);
+		if (rc)
+			goto exit;
+	} else {
+		if (inst->hfi_layer_type == HFI_HIER_B) {
+			i_vpr_l(inst,
+				"%s: HB dyn layers change is not supported\n",
+				__func__);
+			return 0;
+		}
+	}
+
+	/* set layer count */
+	cap_id = ENH_LAYER_COUNT;
+	/* hfi baselayer starts from 1 */
+	hfi_layer_count = inst->capabilities->cap[ENH_LAYER_COUNT].value + 1;
+
+	rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32,
+		&hfi_layer_count, sizeof(u32), __func__);
+	if (rc)
+		goto exit;
+
+exit:
+	return rc;
+}
+
+int msm_vidc_set_gop_size(void *instance,
+	enum msm_vidc_inst_capability_type cap_id)
+{
+	int rc = 0;
+	struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance;
+	u32 hfi_value;
+
+	if (!inst || !inst->capabilities) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+
+	if (inst->vb2q[OUTPUT_PORT].streaming) {
+		if (inst->hfi_layer_type == HFI_HIER_B) {
+			i_vpr_l(inst,
+				"%s: HB dyn GOP setting is not supported\n",
+				__func__);
+			return 0;
+		}
+	}
+
+	hfi_value = inst->capabilities->cap[GOP_SIZE].value;
+
+	rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32,
+		&hfi_value, sizeof(u32), __func__);
+
+	return rc;
+}
+
 /* TODO
 int msm_vidc_set_flip(void *instance,
 	enum msm_vidc_inst_capability_type cap_id)

+ 5 - 4
driver/vidc/src/msm_vidc_driver.c

@@ -62,7 +62,6 @@ static const struct msm_vidc_cap_name cap_name_arr[] = {
 	{OPERATING_RATE,                 "OPERATING_RATE"             },
 	{SCALE_X,                        "SCALE_X"                    },
 	{SCALE_Y,                        "SCALE_Y"                    },
-	{B_FRAME,                        "B_FRAME"                    },
 	{MB_CYCLES_VSP,                  "MB_CYCLES_VSP"              },
 	{MB_CYCLES_VPP,                  "MB_CYCLES_VPP"              },
 	{MB_CYCLES_LP,                   "MB_CYCLES_LP"               },
@@ -88,6 +87,7 @@ static const struct msm_vidc_cap_name cap_name_arr[] = {
 	{CONSTANT_QUALITY,               "CONSTANT_QUALITY"           },
 	{GOP_SIZE,                       "GOP_SIZE"                   },
 	{GOP_CLOSURE,                    "GOP_CLOSURE"                },
+	{B_FRAME,                        "B_FRAME"                    },
 	{BLUR_TYPES,                     "BLUR_TYPES"                 },
 	{BLUR_RESOLUTION,                "BLUR_RESOLUTION"            },
 	{CSC,                            "CSC"                        },
@@ -123,9 +123,9 @@ static const struct msm_vidc_cap_name cap_name_arr[] = {
 	{L4_QP,                          "L4_QP"                      },
 	{L5_QP,                          "L5_QP"                      },
 	{HIER_LAYER_QP,                  "HIER_LAYER_QP"              },
-	{HIER_CODING_TYPE,               "HIER_CODING_TYPE"           },
-	{HIER_CODING,                    "HIER_CODING"                },
-	{HIER_CODING_LAYER,              "HIER_CODING_LAYER"          },
+	{LAYER_TYPE,                     "LAYER_TYPE"                 },
+	{LAYER_ENABLE,                   "LAYER_ENABLE"               },
+	{ENH_LAYER_COUNT,                "ENH_LAYER_COUNT"            },
 	{L0_BR,                          "L0_BR"                      },
 	{L1_BR,                          "L1_BR"                      },
 	{L2_BR,                          "L2_BR"                      },
@@ -1063,6 +1063,7 @@ bool msm_vidc_allow_s_ctrl(struct msm_vidc_inst *inst, u32 id)
 			case V4L2_CID_VFLIP:
 			case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP:
 			case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER:
+			case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER:
 			case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L0_BR:
 			case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L1_BR:
 			case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L2_BR: