Browse Source

Merge "video: driver: implement TRY_FMT for encoder and decoder"

qctecmdr 3 years ago
parent
commit
cc48023758

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

@@ -14,6 +14,7 @@ int msm_vdec_streamon_input(struct msm_vidc_inst *inst);
 int msm_vdec_streamoff_output(struct msm_vidc_inst *inst);
 int msm_vdec_streamon_output(struct msm_vidc_inst *inst);
 int msm_vdec_qbuf(struct msm_vidc_inst *inst, struct vb2_buffer *vb2);
+int msm_vdec_try_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f);
 int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f);
 int msm_vdec_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f);
 int msm_vdec_s_selection(struct msm_vidc_inst* inst, struct v4l2_selection* s);

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

@@ -15,6 +15,7 @@ int msm_venc_streamoff_output(struct msm_vidc_inst *inst);
 int msm_venc_streamon_output(struct msm_vidc_inst *inst);
 int msm_venc_qbuf(struct msm_vidc_inst *inst, struct vb2_buffer *vb2);
 int msm_venc_process_cmd(struct msm_vidc_inst *inst, u32 cmd);
+int msm_venc_try_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f);
 int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f);
 int msm_venc_s_fmt_output(struct msm_vidc_inst *inst, struct v4l2_format *f);
 int msm_venc_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f);

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

@@ -19,6 +19,7 @@ int msm_vidc_close(void *instance);
 int msm_vidc_suspend(int core_id);
 int msm_vidc_querycap(void *instance, struct v4l2_capability *cap);
 int msm_vidc_enum_fmt(void *instance, struct v4l2_fmtdesc *f);
+int msm_vidc_try_fmt(void *instance, struct v4l2_format *f);
 int msm_vidc_s_fmt(void *instance, struct v4l2_format *f);
 int msm_vidc_g_fmt(void *instance, struct v4l2_format *f);
 int msm_vidc_s_selection(void* instance, struct v4l2_selection* s);

+ 4 - 1
driver/vidc/inc/msm_vidc_v4l2.h

@@ -18,6 +18,8 @@ int msm_v4l2_querycap(struct file *filp, void *fh,
 		struct v4l2_capability *cap);
 int msm_v4l2_enum_fmt(struct file *file, void *fh,
 		struct v4l2_fmtdesc *f);
+int msm_v4l2_try_fmt(struct file *file, void *fh,
+		struct v4l2_format *f);
 int msm_v4l2_s_fmt(struct file *file, void *fh,
 		struct v4l2_format *f);
 int msm_v4l2_g_fmt(struct file *file, void *fh,
@@ -62,4 +64,5 @@ int msm_v4l2_querymenu(struct file *file, void *fh,
 		struct v4l2_querymenu *qmenu);
 unsigned int msm_v4l2_poll(struct file *filp,
 	struct poll_table_struct *pt);
-#endif // _MSM_VIDC_V4L2_H_
+
+#endif // _MSM_VIDC_V4L2_H_

+ 50 - 0
driver/vidc/src/msm_vdec.c

@@ -2128,6 +2128,56 @@ int msm_vdec_process_cmd(struct msm_vidc_inst *inst, u32 cmd)
 	return 0;
 }
 
+int msm_vdec_try_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
+{
+	int rc = 0;
+	struct msm_vidc_core *core;
+	struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
+	u32 pix_fmt;
+
+	if (!inst || !inst->core) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+	core = inst->core;
+
+	memset(pixmp->reserved, 0, sizeof(pixmp->reserved));
+	if (f->type == INPUT_MPLANE) {
+		pix_fmt = v4l2_codec_to_driver(f->fmt.pix_mp.pixelformat, __func__);
+		if (!pix_fmt) {
+			i_vpr_h(inst, "%s: unsupported codec, set default params\n", __func__);
+			f->fmt.pix_mp.width = DEFAULT_WIDTH;
+			f->fmt.pix_mp.height = DEFAULT_HEIGHT;
+			f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264;
+			pix_fmt = v4l2_codec_to_driver(f->fmt.pix_mp.pixelformat, __func__);
+		}
+	} else if (f->type == OUTPUT_MPLANE) {
+		if (inst->vb2q[INPUT_PORT].streaming) {
+			f->fmt.pix_mp.height = inst->fmts[INPUT_PORT].fmt.pix_mp.height;
+			f->fmt.pix_mp.width = inst->fmts[INPUT_PORT].fmt.pix_mp.width;
+		}
+		pix_fmt = v4l2_colorformat_to_driver(f->fmt.pix_mp.pixelformat, __func__);
+		if (!pix_fmt) {
+			i_vpr_h(inst, "%s: unsupported format, set default params\n", __func__);
+			f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_VIDC_NV12C;
+			f->fmt.pix_mp.width = VIDEO_Y_STRIDE_PIX(f->fmt.pix_mp.pixelformat,
+								 DEFAULT_WIDTH);
+			f->fmt.pix_mp.height = VIDEO_Y_SCANLINES(f->fmt.pix_mp.pixelformat,
+								 DEFAULT_HEIGHT);
+			pix_fmt = v4l2_colorformat_to_driver(f->fmt.pix_mp.pixelformat, __func__);
+		}
+	} else {
+		i_vpr_e(inst, "%s: invalid type %d\n", __func__, f->type);
+		return -EINVAL;
+	}
+
+	if (pixmp->field == V4L2_FIELD_ANY)
+		pixmp->field = V4L2_FIELD_NONE;
+
+	pixmp->num_planes = 1;
+	return rc;
+}
+
 int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
 {
 	int rc = 0;

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

@@ -1048,6 +1048,52 @@ error:
 	return rc;
 }
 
+int msm_venc_try_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
+{
+	int rc = 0;
+	struct msm_vidc_core *core;
+	struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
+	u32 pix_fmt;
+
+	if (!inst || !inst->core) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+	core = inst->core;
+
+	memset(pixmp->reserved, 0, sizeof(pixmp->reserved));
+
+	if (f->type == INPUT_MPLANE) {
+		pix_fmt = v4l2_colorformat_to_driver(f->fmt.pix_mp.pixelformat, __func__);
+		if (!pix_fmt) {
+			i_vpr_h(inst, "%s: unsupported format, set default params\n", __func__);
+			f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_VIDC_NV12C;
+			f->fmt.pix_mp.width = VIDEO_Y_STRIDE_PIX(f->fmt.pix_mp.pixelformat,
+								 DEFAULT_WIDTH);
+			f->fmt.pix_mp.height = VIDEO_Y_SCANLINES(f->fmt.pix_mp.pixelformat,
+								 DEFAULT_HEIGHT);
+		}
+	} else if (f->type == OUTPUT_MPLANE) {
+		pix_fmt = v4l2_codec_to_driver(f->fmt.pix_mp.pixelformat, __func__);
+		if (!pix_fmt) {
+			i_vpr_h(inst, "%s: unsupported codec, set default params\n", __func__);
+			f->fmt.pix_mp.width = DEFAULT_WIDTH;
+			f->fmt.pix_mp.height = DEFAULT_HEIGHT;
+			f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264;
+			pix_fmt = v4l2_colorformat_to_driver(f->fmt.pix_mp.pixelformat, __func__);
+		}
+	} else {
+		i_vpr_e(inst, "%s: invalid type %d\n", __func__, f->type);
+		return -EINVAL;
+	}
+
+	if (pixmp->field == V4L2_FIELD_ANY)
+		pixmp->field = V4L2_FIELD_NONE;
+	pixmp->num_planes = 1;
+
+	return rc;
+}
+
 int msm_venc_s_fmt_output(struct msm_vidc_inst *inst, struct v4l2_format *f)
 {
 	int rc = 0;

+ 25 - 0
driver/vidc/src/msm_vidc.c

@@ -210,6 +210,31 @@ int msm_vidc_query_menu(void *instance, struct v4l2_querymenu *qmenu)
 }
 EXPORT_SYMBOL(msm_vidc_query_menu);
 
+int msm_vidc_try_fmt(void *instance, struct v4l2_format *f)
+{
+	int rc = 0;
+	struct msm_vidc_inst *inst = instance;
+
+	if (!inst || !f) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!msm_vidc_allow_s_fmt(inst, f->type))
+		return -EBUSY;
+
+	if (inst->domain == MSM_VIDC_DECODER)
+		rc = msm_vdec_try_fmt(inst, f);
+	if (inst->domain == MSM_VIDC_ENCODER)
+		rc = msm_venc_try_fmt(inst, f);
+
+	if (rc)
+		i_vpr_e(inst, "%s: try_fmt(%d) failed %d\n",
+			__func__, f->type, rc);
+	return rc;
+}
+EXPORT_SYMBOL(msm_vidc_try_fmt);
+
 int msm_vidc_s_fmt(void *instance, struct v4l2_format *f)
 {
 	int rc = 0;

+ 2 - 0
driver/vidc/src/msm_vidc_platform.c

@@ -26,6 +26,8 @@ static struct v4l2_ioctl_ops msm_v4l2_ioctl_ops = {
 	.vidioc_enum_fmt_vid_out        = msm_v4l2_enum_fmt,
 	.vidioc_enum_framesizes         = msm_v4l2_enum_framesizes,
 	.vidioc_enum_frameintervals     = msm_v4l2_enum_frameintervals,
+	.vidioc_try_fmt_vid_cap_mplane  = msm_v4l2_try_fmt,
+	.vidioc_try_fmt_vid_out_mplane  = msm_v4l2_try_fmt,
 	.vidioc_s_fmt_vid_cap           = msm_v4l2_s_fmt,
 	.vidioc_s_fmt_vid_out           = msm_v4l2_s_fmt,
 	.vidioc_s_fmt_vid_cap_mplane    = msm_v4l2_s_fmt,

+ 28 - 0
driver/vidc/src/msm_vidc_v4l2.c

@@ -107,6 +107,34 @@ unlock:
 	return rc;
 }
 
+int msm_v4l2_try_fmt(struct file *filp, void *fh, struct v4l2_format *f)
+{
+	struct msm_vidc_inst *inst = get_vidc_inst(filp, fh);
+	int rc = 0;
+
+	inst = get_inst_ref(g_core, inst);
+	if (!inst) {
+		d_vpr_e("%s: invalid instance\n", __func__);
+		return -EINVAL;
+	}
+
+	inst_lock(inst, __func__);
+	if (is_session_error(inst)) {
+		i_vpr_e(inst, "%s: inst in error state\n", __func__);
+		rc = -EBUSY;
+		goto unlock;
+	}
+	rc = msm_vidc_try_fmt((void *)inst, f);
+	if (rc)
+		goto unlock;
+
+unlock:
+	inst_unlock(inst, __func__);
+	put_inst(inst);
+
+	return rc;
+}
+
 int msm_v4l2_s_fmt(struct file *filp, void *fh,
 					struct v4l2_format *f)
 {