video: driver: implement TRY_FMT for encoder and decoder

Any video device which supports capture multiplanar buf type
should implement VIDIOC_TRY_FMT.

Fixes: v4l2-compliance: testTryFormats (VIDIOC_TRY_FMT).

Change-Id: Id7ec171115c9374c6173fcf74a609382c3acf2d0
Signed-off-by: Dikshita Agarwal <dikshita@codeaurora.org>
This commit is contained in:
Dikshita Agarwal
2021-06-21 18:35:15 +05:30
parent c7b23776f2
commit a7ce77cfc7
9 changed files with 158 additions and 1 deletions

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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_

View File

@@ -2090,6 +2090,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;

View File

@@ -1036,6 +1036,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;

View File

@@ -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;

View File

@@ -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,

View File

@@ -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)
{