Browse Source

video: driver: add nv12 format support

add nv12 format support

Change-Id: I6a9f2eb814504e35797fb91053417f16cfdf8b25
Signed-off-by: Darshana Patil <[email protected]>
Darshana Patil 4 năm trước cách đây
mục cha
commit
60b7435a4c

+ 13 - 13
driver/variant/iris2/inc/hfi_buffer_iris2.h

@@ -155,8 +155,8 @@ typedef HFI_U32 HFI_BOOL;
  * frame dimensions NV12_UBWC format (including interlace UBWC)
  * (calculation includes all data & metadata planes)
  */
-#define HFI_NV12_UBWC_IL_CALC_BUF_SIZE_V2 \
-	(buf_size, frame_width, frame_height, y_stride_multiple,\
+#define HFI_NV12_UBWC_IL_CALC_BUF_SIZE_V2(buf_size,\
+	frame_width, frame_height, y_stride_multiple,\
 	y_buffer_height_multiple, uv_stride_multiple, \
 	uv_buffer_height_multiple, y_metadata_stride_multiple, \
 	y_metadata_buffer_height_multiple, \
@@ -164,35 +164,35 @@ typedef HFI_U32 HFI_BOOL;
 	do \
 	{ \
 		HFI_U32 y_buf_size, uv_buf_size, y_meta_size, uv_meta_size;   \
-		HFI_U32 stride, height; \
-		HFI_U32 halfHeight = (frame_height + 1) >> 1; \
+		HFI_U32 stride, _height; \
+		HFI_U32 half_height = (frame_height + 1) >> 1; \
 		HFI_NV12_IL_CALC_Y_STRIDE(stride, frame_width,\
 					y_stride_multiple); \
-		HFI_NV12_IL_CALC_Y_BUFHEIGHT(height, half_height,\
+		HFI_NV12_IL_CALC_Y_BUFHEIGHT(_height, half_height,\
 					y_buffer_height_multiple); \
-		HFI_NV12_UBWC_IL_CALC_Y_BUF_SIZE(y_buf_size, stride, height);\
+		HFI_NV12_UBWC_IL_CALC_Y_BUF_SIZE(y_buf_size, stride, _height);\
 		HFI_NV12_IL_CALC_UV_STRIDE(stride, frame_width, \
 					uv_stride_multiple); \
-		HFI_NV12_IL_CALC_UV_BUFHEIGHT(height, half_height, \
+		HFI_NV12_IL_CALC_UV_BUFHEIGHT(_height, half_height, \
 					uv_buffer_height_multiple); \
-		HFI_NV12_UBWC_IL_CALC_UV_BUF_SIZE(uv_buf_size, stride, height);\
+		HFI_NV12_UBWC_IL_CALC_UV_BUF_SIZE(uv_buf_size, stride, _height);\
 		HFI_UBWC_CALC_METADATA_PLANE_STRIDE(stride, frame_width,\
 				y_metadata_stride_multiple, \
 			HFI_COLOR_FORMAT_YUV420_NV12_UBWC_Y_TILE_WIDTH);\
-		HFI_UBWC_METADATA_PLANE_BUFHEIGHT(height, half_height, \
+		HFI_UBWC_METADATA_PLANE_BUFHEIGHT(_height, half_height, \
 				y_metadata_buffer_height_multiple,\
 			HFI_COLOR_FORMAT_YUV420_NV12_UBWC_Y_TILE_HEIGHT);\
 		HFI_UBWC_METADATA_PLANE_BUFFER_SIZE(y_meta_size, stride, \
-				height);    \
+				_height);    \
 		HFI_UBWC_UV_METADATA_PLANE_STRIDE(stride, frame_width,\
 				uv_metadata_stride_multiple, \
 			HFI_COLOR_FORMAT_YUV420_NV12_UBWC_UV_TILE_WIDTH); \
-		HFI_UBWC_UV_METADATA_PLANE_BUFHEIGHT(height, half_height,\
+		HFI_UBWC_UV_METADATA_PLANE_BUFHEIGHT(_height, half_height,\
 				uv_metadata_buffer_height_multiple,\
 			HFI_COLOR_FORMAT_YUV420_NV12_UBWC_UV_TILE_HEIGHT);\
 		HFI_UBWC_METADATA_PLANE_BUFFER_SIZE(uv_meta_size, stride, \
-				 height); \
-		bufSize = (y_buf_size + uv_buf_size + y_meta_size + \
+				 _height); \
+		buf_size = (y_buf_size + uv_buf_size + y_meta_size + \
 			uv_meta_size) << 1;\
 	} while (0)
 

+ 94 - 5
driver/variant/iris2/src/msm_vidc_buffer_iris2.c

@@ -12,6 +12,7 @@
 #include "msm_vidc_platform.h"
 #include "msm_vidc_driver.h"
 #include "msm_vidc_debug.h"
+#include "msm_media_info.h"
 
 static u32 msm_vidc_decoder_bin_size_iris2(struct msm_vidc_inst *inst)
 {
@@ -189,6 +190,51 @@ static u32 msm_vidc_decoder_persist_size_iris2(struct msm_vidc_inst *inst)
 	return size;
 }
 
+static u32 msm_vidc_decoder_dpb_size_iris2(struct msm_vidc_inst *inst)
+{
+
+	u32 size = 0;
+	u32 color_fmt, media_fmt;
+	u32 width, height;
+	struct v4l2_format *f;
+
+	if (!inst) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return size;
+	}
+
+	color_fmt = inst->capabilities->cap[PIX_FMTS].value;
+	if (!is_linear_colorformat(color_fmt))
+		return size;
+
+	f = &inst->fmts[OUTPUT_PORT];
+	width = f->fmt.pix_mp.width;
+	height = f->fmt.pix_mp.height;
+
+	if (color_fmt == MSM_VIDC_FMT_NV12) {
+		media_fmt = COLOR_FMT_NV12_UBWC;
+		HFI_NV12_UBWC_IL_CALC_BUF_SIZE_V2(size, width, height,
+			VENUS_Y_STRIDE(media_fmt, width), VENUS_Y_SCANLINES(media_fmt, height),
+			VENUS_UV_STRIDE(media_fmt, width), VENUS_UV_SCANLINES(media_fmt, height),
+			VENUS_Y_META_STRIDE(media_fmt, width), VENUS_Y_META_SCANLINES(media_fmt,
+				height),
+			VENUS_UV_META_STRIDE(media_fmt, width), VENUS_UV_META_SCANLINES(media_fmt,
+				height));
+	} else if (color_fmt == MSM_VIDC_FMT_P010) {
+		media_fmt = COLOR_FMT_P010_UBWC;
+		HFI_YUV420_TP10_UBWC_CALC_BUF_SIZE(size,
+			VENUS_Y_STRIDE(media_fmt, width), VENUS_Y_SCANLINES(media_fmt, height),
+			VENUS_UV_STRIDE(media_fmt, width), VENUS_UV_SCANLINES(media_fmt, height),
+			VENUS_Y_META_STRIDE(media_fmt, width), VENUS_Y_META_SCANLINES(media_fmt,
+				height),
+			VENUS_UV_META_STRIDE(media_fmt, width), VENUS_UV_META_SCANLINES(media_fmt,
+				height));
+	}
+
+	s_vpr_l(inst->sid, "%s: size %d\n", __func__, size);
+	return size;
+}
+
 /* encoder internal buffers */
 static u32 msm_vidc_encoder_bin_size_iris2(struct msm_vidc_inst *inst)
 {
@@ -436,6 +482,9 @@ int msm_buffer_size_iris2(struct msm_vidc_inst *inst,
 		case MSM_VIDC_BUF_PERSIST:
 			size = msm_vidc_decoder_persist_size_iris2(inst);
 			break;
+		case MSM_VIDC_BUF_DPB:
+			size = msm_vidc_decoder_dpb_size_iris2(inst);
+			break;
 		default:
 			break;
 		}
@@ -482,6 +531,44 @@ int msm_buffer_size_iris2(struct msm_vidc_inst *inst,
 	return size;
 }
 
+static int msm_buffer_encoder_dpb_count(struct msm_vidc_inst *inst)
+{
+	int count = 0;
+
+	if (!inst) {
+		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) {
+		// TODO: replace zeros with appropriate variables
+		HFI_IRIS2_ENC_RECON_BUF_COUNT(count, 0, 0, 0, 0, 0,
+			HFI_CODEC_ENCODE_HEVC);
+	}
+	return count;
+}
+
+static int msm_buffer_decoder_dpb_count(struct msm_vidc_inst *inst)
+{
+	int count = 0;
+	u32 color_fmt;
+
+	if (!inst) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return 0;
+	}
+
+	color_fmt = inst->capabilities->cap[PIX_FMTS].value;
+	if (is_linear_colorformat(color_fmt))
+		count = inst->buffers.output.min_count;
+
+	return count;
+}
+
 int msm_buffer_min_count_iris2(struct msm_vidc_inst *inst,
 		enum msm_vidc_buffer_type buffer_type)
 {
@@ -489,7 +576,7 @@ int msm_buffer_min_count_iris2(struct msm_vidc_inst *inst,
 
 	if (!inst) {
 		d_vpr_e("%s: invalid params\n", __func__);
-		return -EINVAL;
+		return 0;
 	}
 
 	if (is_decode_session(inst)) {
@@ -509,7 +596,9 @@ int msm_buffer_min_count_iris2(struct msm_vidc_inst *inst,
 		case MSM_VIDC_BUF_PERSIST:
 			count = 1;
 			break;
-		//todo: add DPB
+		case MSM_VIDC_BUF_DPB:
+			count = msm_buffer_decoder_dpb_count(inst);
+			break;
 		default:
 			break;
 		}
@@ -527,12 +616,12 @@ int msm_buffer_min_count_iris2(struct msm_vidc_inst *inst,
 		case MSM_VIDC_BUF_COMV:
 		case MSM_VIDC_BUF_NON_COMV:
 		case MSM_VIDC_BUF_LINE:
-		case MSM_VIDC_BUF_DPB:
-		//todo: add DPB count
 		case MSM_VIDC_BUF_ARP:
 		case MSM_VIDC_BUF_VPSS:
 			count = 1;
 			break;
+		case MSM_VIDC_BUF_DPB:
+			count = msm_buffer_encoder_dpb_count(inst);
 		default:
 			break;
 		}
@@ -548,7 +637,7 @@ int msm_buffer_extra_count_iris2(struct msm_vidc_inst *inst,
 
 	if (!inst) {
 		d_vpr_e("%s: invalid params\n", __func__);
-		return -EINVAL;
+		return 0;
 	}
 
 	switch (buffer_type) {

+ 1 - 1
driver/vidc/inc/msm_vidc_driver.h

@@ -202,7 +202,7 @@ int v4l2_type_to_driver_port(struct msm_vidc_inst *inst, u32 type,
 const char *state_name(enum msm_vidc_inst_state state);
 int msm_vidc_change_inst_state(struct msm_vidc_inst *inst,
 	enum msm_vidc_inst_state request_state, const char *func);
-int msm_vidc_get_input_internal_buffers(struct msm_vidc_inst *inst,
+int msm_vidc_get_internal_buffers(struct msm_vidc_inst *inst,
 	enum msm_vidc_buffer_type buffer_type);
 int msm_vidc_create_internal_buffers(struct msm_vidc_inst *inst,
 		enum msm_vidc_buffer_type buffer_type);

+ 93 - 9
driver/vidc/src/msm_vdec.c

@@ -726,27 +726,27 @@ static int msm_vdec_get_input_internal_buffers(struct msm_vidc_inst *inst)
 		return -EINVAL;
 	}
 
-	rc = msm_vidc_get_input_internal_buffers(inst, MSM_VIDC_BUF_BIN);
+	rc = msm_vidc_get_internal_buffers(inst, MSM_VIDC_BUF_BIN);
 	if (rc)
 		return rc;
 
-	rc = msm_vidc_get_input_internal_buffers(inst, MSM_VIDC_BUF_COMV);
+	rc = msm_vidc_get_internal_buffers(inst, MSM_VIDC_BUF_COMV);
 	if (rc)
 		return rc;
 
-	rc = msm_vidc_get_input_internal_buffers(inst, MSM_VIDC_BUF_NON_COMV);
+	rc = msm_vidc_get_internal_buffers(inst, MSM_VIDC_BUF_NON_COMV);
 	if (rc)
 		return rc;
 
-	rc = msm_vidc_get_input_internal_buffers(inst, MSM_VIDC_BUF_LINE);
+	rc = msm_vidc_get_internal_buffers(inst, MSM_VIDC_BUF_LINE);
 	if (rc)
 		return rc;
 
-	rc = msm_vidc_get_input_internal_buffers(inst, MSM_VIDC_BUF_PERSIST);
+	rc = msm_vidc_get_internal_buffers(inst, MSM_VIDC_BUF_PERSIST);
 	if (rc)
 		return rc;
 
-	s_vpr_h(inst->sid, "internal buffer: min     size     reuse\n");
+	s_vpr_h(inst->sid, "input internal buffer: min     size     reuse\n");
 	s_vpr_h(inst->sid, "bin  buffer: %d      %d      %d\n",
 		inst->buffers.bin.min_count,
 		inst->buffers.bin.size,
@@ -771,11 +771,32 @@ static int msm_vdec_get_input_internal_buffers(struct msm_vidc_inst *inst)
 	return rc;
 }
 
+static int msm_vdec_get_output_internal_buffers(struct msm_vidc_inst *inst)
+{
+	int rc = 0;
+
+	if (!inst) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+
+	rc = msm_vidc_get_internal_buffers(inst, MSM_VIDC_BUF_DPB);
+	if (rc)
+		return rc;
+
+	s_vpr_h(inst->sid, "output internal buffer: min     size     reuse\n");
+	s_vpr_h(inst->sid, "dpb  buffer: %d      %d      %d\n",
+		inst->buffers.bin.min_count,
+		inst->buffers.bin.size,
+		inst->buffers.bin.reuse);
+
+	return rc;
+}
+
 static int msm_vdec_create_input_internal_buffers(struct msm_vidc_inst *inst)
 {
 	int rc = 0;
 
-	d_vpr_h("%s()\n", __func__);
 	if (!inst || !inst->core) {
 		d_vpr_e("%s: invalid params\n", __func__);
 		return -EINVAL;
@@ -800,11 +821,26 @@ static int msm_vdec_create_input_internal_buffers(struct msm_vidc_inst *inst)
 	return 0;
 }
 
+static int msm_vdec_create_output_internal_buffers(struct msm_vidc_inst *inst)
+{
+	int rc = 0;
+
+	if (!inst || !inst->core) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+
+	rc = msm_vidc_create_internal_buffers(inst, MSM_VIDC_BUF_DPB);
+	if (rc)
+		return rc;
+
+	return 0;
+}
+
 static int msm_vdec_queue_input_internal_buffers(struct msm_vidc_inst *inst)
 {
 	int rc = 0;
 
-	d_vpr_h("%s()\n", __func__);
 	if (!inst || !inst->core) {
 		d_vpr_e("%s: invalid params\n", __func__);
 		return -EINVAL;
@@ -829,16 +865,31 @@ static int msm_vdec_queue_input_internal_buffers(struct msm_vidc_inst *inst)
 	return 0;
 }
 
+static int msm_vdec_queue_output_internal_buffers(struct msm_vidc_inst *inst)
+{
+	int rc = 0;
+
+	if (!inst || !inst->core) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+
+	rc = msm_vidc_queue_internal_buffers(inst, MSM_VIDC_BUF_DPB);
+	if (rc)
+		return rc;
+
+	return 0;
+}
 
 static int msm_vdec_release_input_internal_buffers(struct msm_vidc_inst *inst)
 {
 	int rc = 0;
 
-	d_vpr_h("%s()\n", __func__);
 	if (!inst || !inst->core) {
 		d_vpr_e("%s: invalid params\n", __func__);
 		return -EINVAL;
 	}
+	s_vpr_h(inst->sid, "%s()\n",__func__);
 
 	rc = msm_vidc_release_internal_buffers(inst, MSM_VIDC_BUF_BIN);
 	if (rc)
@@ -859,6 +910,23 @@ static int msm_vdec_release_input_internal_buffers(struct msm_vidc_inst *inst)
 	return 0;
 }
 
+static int msm_vdec_release_output_internal_buffers(struct msm_vidc_inst *inst)
+{
+	int rc = 0;
+
+	if (!inst || !inst->core) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+	s_vpr_h(inst->sid, "%s()\n",__func__);
+
+	rc = msm_vidc_release_internal_buffers(inst, MSM_VIDC_BUF_DPB);
+	if (rc)
+		return rc;
+
+	return 0;
+}
+
 static int msm_vdec_subscribe_input_port_settings_change(struct msm_vidc_inst *inst,
 	enum msm_vidc_port_type port)
 {
@@ -1447,6 +1515,22 @@ int msm_vdec_streamon_output(struct msm_vidc_inst *inst)
 	if (rc)
 		goto error;
 
+	rc = msm_vdec_get_output_internal_buffers(inst);
+	if (rc)
+		goto error;
+
+	rc = msm_vdec_release_output_internal_buffers(inst);
+	if (rc)
+		goto error;
+
+	rc = msm_vdec_create_output_internal_buffers(inst);
+	if (rc)
+		goto error;
+
+	rc = msm_vdec_queue_output_internal_buffers(inst);
+	if (rc)
+		goto error;
+
 	rc = msm_vidc_session_streamon(inst, OUTPUT_PORT);
 	if (rc)
 		goto error;

+ 2 - 2
driver/vidc/src/msm_vidc_driver.c

@@ -1557,7 +1557,7 @@ int msm_vidc_destroy_internal_buffer(struct msm_vidc_inst *inst,
 	return 0;
 }
 
-int msm_vidc_get_input_internal_buffers(struct msm_vidc_inst *inst,
+int msm_vidc_get_internal_buffers(struct msm_vidc_inst *inst,
 	enum msm_vidc_buffer_type buffer_type)
 {
 	u32 buf_size;
@@ -2660,7 +2660,7 @@ void msm_vidc_destroy_buffers(struct msm_vidc_inst *inst)
 		if (!buffers)
 			continue;
 		list_for_each_entry_safe(buf, dummy, &buffers->list, list) {
-			s_vpr_e(inst->sid,
+			s_vpr_h(inst->sid,
 				"destroying buffer: type %d idx %d fd %d addr %#x size %d\n",
 				buf->type, buf->index, buf->fd, buf->device_addr, buf->buffer_size);
 			if (is_internal_buffer(buf->type))

+ 43 - 0
driver/vidc/src/venus_hfi_response.c

@@ -557,6 +557,35 @@ static int handle_dequeue_buffers(struct msm_vidc_inst* inst)
 	return rc;
 }
 
+static int handle_dpb_buffer(struct msm_vidc_inst *inst,
+	struct hfi_buffer *buffer)
+{
+	int rc = 0;
+	struct msm_vidc_buffers *buffers;
+	struct msm_vidc_buffer *buf;
+	bool found;
+
+	buffers = msm_vidc_get_buffers(inst, MSM_VIDC_BUF_DPB, __func__);
+	if (!buffers)
+		return -EINVAL;
+
+	found = false;
+	list_for_each_entry(buf, &buffers->list, list) {
+		if (buf->device_addr == buffer->base_address) {
+			found = true;
+			break;
+		}
+	}
+	if (found) {
+		rc = msm_vidc_destroy_internal_buffer(inst, buf);
+	} else {
+		s_vpr_e(inst->sid, "%s: invalid idx %d daddr %#x\n",
+			__func__, buffer->index, buffer->base_address);
+		return -EINVAL;
+	}
+	return rc;
+}
+
 static int handle_persist_buffer(struct msm_vidc_inst *inst,
 	struct hfi_buffer *buffer)
 {
@@ -734,11 +763,17 @@ static int handle_session_buffer(struct msm_vidc_inst *inst,
 				rc = handle_output_metadata_buffer(inst, buffer);
 			else if (buf_type == HFI_BUFFER_BITSTREAM)
 				rc = handle_output_buffer(inst, buffer);
+			else
+				s_vpr_e(inst->sid, "%s: unknown bitstream port buffer type %#x\n",
+					__func__, buf_type);
 		} else if (port_type == HFI_PORT_RAW) {
 			if (buf_type == HFI_BUFFER_METADATA)
 				rc = handle_input_metadata_buffer(inst, buffer);
 			else if (buf_type == HFI_BUFFER_RAW)
 				rc = handle_input_buffer(inst, buffer);
+			else
+				s_vpr_e(inst->sid, "%s: unknown raw port buffer type %#x\n",
+					__func__, buf_type);
 		}
 	} else if (is_decode_session(inst)) {
 		if (port_type == HFI_PORT_BITSTREAM) {
@@ -756,11 +791,19 @@ static int handle_session_buffer(struct msm_vidc_inst *inst,
 				rc = handle_line_buffer(inst, buffer);
 			else if (buf_type == HFI_BUFFER_PERSIST)
 				rc = handle_persist_buffer(inst, buffer);
+			else
+				s_vpr_e(inst->sid, "%s: unknown bitstream port buffer type %#x\n",
+					__func__, buf_type);
 		} else if (port_type == HFI_PORT_RAW) {
 			if (buf_type == HFI_BUFFER_METADATA)
 				rc = handle_output_metadata_buffer(inst, buffer);
 			else if (buf_type == HFI_BUFFER_RAW)
 				rc = handle_output_buffer(inst, buffer);
+			else if (buf_type == HFI_BUFFER_DPB)
+				rc = handle_dpb_buffer(inst, buffer);
+			else
+				s_vpr_e(inst->sid, "%s: unknown raw port buffer type %#x\n",
+					__func__, buf_type);
 		}
 	} else {
 		s_vpr_e(inst->sid, "%s: invalid session %d\n",