video: driver: add get and set selection support

Add support to get and set selection to update
crop and compose values in driver.

Change-Id: I1f38ac6a4f3ceac64d08d66f30b422efd79959a9
Signed-off-by: Maheshwar Ajja <majja@codeaurora.org>
This commit is contained in:
Maheshwar Ajja
2020-12-23 12:13:32 -08:00
parent 8f55c1030e
commit e48a514a89
11 changed files with 288 additions and 24 deletions

View File

@@ -16,6 +16,8 @@ int msm_vdec_start_output(struct msm_vidc_inst *inst);
int msm_vdec_qbuf(struct msm_vidc_inst *inst, struct vb2_buffer *vb2);
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);
int msm_vdec_g_selection(struct msm_vidc_inst* inst, struct v4l2_selection* s);
int msm_vdec_enum_fmt(struct msm_vidc_inst *inst, struct v4l2_fmtdesc *f);
int msm_vdec_inst_init(struct msm_vidc_inst *inst);
int msm_vdec_input_port_settings_change(struct msm_vidc_inst *inst);

View File

@@ -16,6 +16,8 @@ int msm_venc_start_output(struct msm_vidc_inst *inst);
int msm_venc_process_cmd(struct msm_vidc_inst *inst, u32 cmd);
int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f);
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 msm_venc_g_selection(struct msm_vidc_inst* inst, struct v4l2_selection* s);
int msm_venc_enum_fmt(struct msm_vidc_inst *inst, struct v4l2_fmtdesc *f);
int msm_venc_inst_init(struct msm_vidc_inst *inst);

View File

@@ -21,6 +21,8 @@ int msm_vidc_querycap(void *instance, struct v4l2_capability *cap);
int msm_vidc_enum_fmt(void *instance, struct v4l2_fmtdesc *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);
int msm_vidc_g_selection(void* instance, struct v4l2_selection* s);
int msm_vidc_s_ctrl(void *instance, struct v4l2_control *a);
int msm_vidc_s_ext_ctrl(void *instance, struct v4l2_ext_controls *a);
int msm_vidc_g_ext_ctrl(void *instance, struct v4l2_ext_controls *a);

View File

@@ -100,7 +100,8 @@ struct msm_vidc_inst {
struct msm_vidc_inst_cap_entry firmware;
bool request;
struct vb2_queue vb2q[MAX_PORT];
struct msm_vidc_crop crop;
struct msm_vidc_rectangle crop;
struct msm_vidc_rectangle compose;
struct msm_vidc_properties prop;
enum msm_vidc_stage_type stage;
enum msm_vidc_pipe_type pipe;

View File

@@ -545,7 +545,7 @@ struct msm_vidc_color_info {
u32 quantization;
};
struct msm_vidc_crop {
struct msm_vidc_rectangle {
u32 left;
u32 top;
u32 width;

View File

@@ -22,6 +22,10 @@ int msm_v4l2_s_fmt(struct file *file, void *fh,
struct v4l2_format *f);
int msm_v4l2_g_fmt(struct file *file, void *fh,
struct v4l2_format *f);
int msm_v4l2_s_selection(struct file* file, void* fh,
struct v4l2_selection* s);
int msm_v4l2_g_selection(struct file* file, void* fh,
struct v4l2_selection* s);
int msm_v4l2_s_ctrl(struct file *file, void *fh,
struct v4l2_control *a);
int msm_v4l2_g_ctrl(struct file *file, void *fh,

View File

@@ -5,6 +5,7 @@
#include <media/v4l2_vidc_extensions.h>
#include <media/msm_media_info.h>
#include <linux/v4l2-common.h>
#include "msm_vdec.h"
#include "msm_vidc_core.h"
@@ -1477,7 +1478,6 @@ int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
struct msm_vidc_core *core;
struct v4l2_format *fmt;
d_vpr_h("%s()\n", __func__);
if (!inst || !inst->core) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
@@ -1652,7 +1652,6 @@ int msm_vdec_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
int rc = 0;
int port;
d_vpr_h("%s()\n", __func__);
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
@@ -1667,6 +1666,44 @@ int msm_vdec_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
return rc;
}
int msm_vdec_s_selection(struct msm_vidc_inst* inst, struct v4l2_selection* s)
{
if (!inst || !s) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
s_vpr_e(inst->sid, "%s: unsupported\n", __func__);
return -EINVAL;
}
int msm_vdec_g_selection(struct msm_vidc_inst* inst, struct v4l2_selection* s)
{
if (!inst || !s) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
switch (s->target) {
case V4L2_SEL_TGT_CROP_BOUNDS:
case V4L2_SEL_TGT_CROP_DEFAULT:
case V4L2_SEL_TGT_CROP:
case V4L2_SEL_TGT_COMPOSE_BOUNDS:
case V4L2_SEL_TGT_COMPOSE_PADDED:
case V4L2_SEL_TGT_COMPOSE_DEFAULT:
case V4L2_SEL_TGT_COMPOSE:
default:
s->r.left = inst->crop.left;
s->r.top = inst->crop.top;
s->r.width = inst->crop.width;
s->r.height = inst->crop.height;
break;
}
s_vpr_h(inst->sid, "%s: type %d target %d, r [%d, %d, %d, %d]\n",
__func__, s->type, s->target, s->r.top, s->r.left,
s->r.width, s->r.height);
return 0;
}
int msm_vdec_enum_fmt(struct msm_vidc_inst *inst, struct v4l2_fmtdesc *f)
{
int rc = 0;

View File

@@ -877,6 +877,7 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
int rc = 0;
struct msm_vidc_core *core;
struct v4l2_format *fmt;
u32 codec_align;
d_vpr_h("%s()\n", __func__);
if (!inst || !inst->core) {
@@ -899,12 +900,10 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
fmt->type = INPUT_MPLANE;
fmt->fmt.pix_mp.pixelformat = f->fmt.pix_mp.pixelformat;
fmt->fmt.pix_mp.width = VENUS_Y_STRIDE(
v4l2_colorformat_to_media(fmt->fmt.pix_mp.pixelformat,
__func__),
v4l2_colorformat_to_media(fmt->fmt.pix_mp.pixelformat, __func__),
f->fmt.pix_mp.width);
fmt->fmt.pix_mp.height = VENUS_Y_SCANLINES(
v4l2_colorformat_to_media(fmt->fmt.pix_mp.pixelformat,
__func__),
v4l2_colorformat_to_media(fmt->fmt.pix_mp.pixelformat, __func__),
f->fmt.pix_mp.height);
fmt->fmt.pix_mp.num_planes = 1;
@@ -926,6 +925,33 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
inst->buffers.input.size =
fmt->fmt.pix_mp.plane_fmt[0].sizeimage;
codec_align = inst->fmts[OUTPUT_PORT].fmt.pix_mp.pixelformat ==
V4L2_PIX_FMT_HEVC ? 32 : 16;
/* check if resolution changed */
if (inst->fmts[OUTPUT_PORT].fmt.pix_mp.width !=
ALIGN(f->fmt.pix_mp.width, codec_align) ||
inst->fmts[OUTPUT_PORT].fmt.pix_mp.height !=
ALIGN(f->fmt.pix_mp.height, codec_align)) {
/* reset bitstream port with updated resolution */
inst->fmts[OUTPUT_PORT].fmt.pix_mp.width =
ALIGN(f->fmt.pix_mp.width, codec_align);
inst->fmts[OUTPUT_PORT].fmt.pix_mp.height =
ALIGN(f->fmt.pix_mp.height, codec_align);
inst->fmts[OUTPUT_PORT].fmt.pix_mp.plane_fmt[0].sizeimage =
call_session_op(core, buffer_size,
inst, MSM_VIDC_BUF_OUTPUT);
/* reset crop dimensions with updated resolution */
inst->crop.top = inst->crop.left = 0;
inst->crop.width = f->fmt.pix_mp.width;
inst->crop.height = f->fmt.pix_mp.height;
/* reset compose dimensions with updated resolution */
inst->compose.top = inst->crop.left = 0;
inst->compose.width = f->fmt.pix_mp.width;
inst->compose.height = f->fmt.pix_mp.height;
}
//rc = msm_vidc_check_session_supported(inst);
if (rc)
goto err_invalid_fmt;
@@ -979,17 +1005,12 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
goto err_invalid_fmt;
}
fmt->type = OUTPUT_MPLANE;
if (f->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_HEVC) {
fmt->fmt.pix_mp.width = ALIGN(f->fmt.pix_mp.width,
H265_BITSTREM_ALIGNMENT);
fmt->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height,
H265_BITSTREM_ALIGNMENT);
} else {
fmt->fmt.pix_mp.width = ALIGN(f->fmt.pix_mp.width,
DEFAULT_BITSTREM_ALIGNMENT);
fmt->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height,
DEFAULT_BITSTREM_ALIGNMENT);
}
codec_align = f->fmt.pix_mp.pixelformat ==
V4L2_PIX_FMT_HEVC ? 32 : 16;
/* width, height is readonly for client */
fmt->fmt.pix_mp.width = ALIGN(inst->crop.width, codec_align);
fmt->fmt.pix_mp.height = ALIGN(inst->crop.height, codec_align);
fmt->fmt.pix_mp.pixelformat = f->fmt.pix_mp.pixelformat;
fmt->fmt.pix_mp.num_planes = 1;
fmt->fmt.pix_mp.plane_fmt[0].bytesperline = 0;
@@ -1013,11 +1034,6 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
if (rc)
goto err_invalid_fmt;
/* update crop dimensions */
inst->crop.left = inst->crop.top = 0;
inst->crop.width = f->fmt.pix_mp.width;
inst->crop.height = f->fmt.pix_mp.height;
//update_log_ctxt(inst->sid, inst->session_type,
// mplane->pixelformat);
@@ -1080,6 +1096,150 @@ int msm_venc_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
return rc;
}
int msm_venc_s_selection(struct msm_vidc_inst* inst, struct v4l2_selection* s)
{
int rc = 0;
u32 codec_align;
if (!inst || !s) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
if (s->type != INPUT_MPLANE && s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) {
s_vpr_e(inst->sid, "%s: invalid type %d\n", __func__, s->type);
return -EINVAL;
}
switch (s->target) {
case V4L2_SEL_TGT_CROP_BOUNDS:
case V4L2_SEL_TGT_CROP_DEFAULT:
case V4L2_SEL_TGT_CROP:
codec_align = inst->fmts[OUTPUT_PORT].fmt.pix_mp.pixelformat ==
V4L2_PIX_FMT_HEVC ? 32 : 16;
if (s->r.left || s->r.top) {
s_vpr_h(inst->sid, "%s: unsupported top %d or left %d\n",
__func__, s->r.left, s->r.top);
s->r.left = s->r.top = 0;
}
if (s->r.width > inst->fmts[OUTPUT_PORT].fmt.pix_mp.width ||
ALIGN(s->r.width, codec_align) != inst->fmts[OUTPUT_PORT].fmt.pix_mp.width) {
s_vpr_h(inst->sid, "%s: unsupported width %d, fmt width %d\n",
__func__, s->r.width,
inst->fmts[OUTPUT_PORT].fmt.pix_mp.width);
s->r.width = inst->fmts[OUTPUT_PORT].fmt.pix_mp.width;
}
if (s->r.height > inst->fmts[OUTPUT_PORT].fmt.pix_mp.height ||
ALIGN(s->r.height, codec_align) != inst->fmts[OUTPUT_PORT].fmt.pix_mp.height) {
s_vpr_h(inst->sid, "%s: unsupported height %d, fmt height %d\n",
__func__, s->r.height,
inst->fmts[OUTPUT_PORT].fmt.pix_mp.height);
s->r.height = inst->fmts[OUTPUT_PORT].fmt.pix_mp.height;
}
inst->crop.left = s->r.left;
inst->crop.top = s->r.top;
inst->crop.width = s->r.width;
inst->crop.height = s->r.height;
/* adjust compose such that it is within crop */
if (inst->compose.left < inst->crop.left)
inst->compose.left = inst->crop.left;
if (inst->compose.top < inst->crop.top)
inst->compose.top = inst->crop.top;
if (inst->compose.width > inst->crop.width)
inst->compose.width = inst->crop.width;
if (inst->compose.height > inst->crop.height)
inst->compose.height = inst->crop.height;
break;
case V4L2_SEL_TGT_COMPOSE_BOUNDS:
case V4L2_SEL_TGT_COMPOSE_PADDED:
case V4L2_SEL_TGT_COMPOSE_DEFAULT:
case V4L2_SEL_TGT_COMPOSE:
if (s->r.left < inst->crop.left) {
s_vpr_e(inst->sid,
"%s: compose left (%d) less than crop left (%d)\n",
__func__, s->r.left, inst->crop.left);
s->r.left = inst->crop.left;
}
if (s->r.top < inst->crop.top) {
s_vpr_e(inst->sid,
"%s: compose top (%d) less than crop top (%d)\n",
__func__, s->r.top, inst->crop.top);
s->r.top = inst->crop.top;
}
if (s->r.width > inst->crop.width) {
s_vpr_e(inst->sid,
"%s: compose width (%d) greate than crop width (%d)\n",
__func__, s->r.width, inst->crop.width);
s->r.width = inst->crop.width;
}
if (s->r.height > inst->crop.height) {
s_vpr_e(inst->sid,
"%s: compose height (%d) greate than crop height (%d)\n",
__func__, s->r.height, inst->crop.height);
s->r.height = inst->crop.height;
}
inst->compose.left = s->r.left;
inst->compose.top = s->r.top;
inst->compose.width = s->r.width;
inst->compose.height= s->r.height;
break;
default:
s_vpr_e(inst->sid, "%s: invalid target %d\n",
__func__, s->target);
rc = -EINVAL;
break;
}
if (!rc)
s_vpr_h(inst->sid, "%s: target %d, r [%d, %d, %d, %d]\n",
__func__, s->target, s->r.top, s->r.left,
s->r.width, s->r.height);
return rc;
}
int msm_venc_g_selection(struct msm_vidc_inst* inst, struct v4l2_selection* s)
{
int rc = 0;
if (!inst || !s) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
if (s->type != INPUT_MPLANE && s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) {
s_vpr_e(inst->sid, "%s: invalid type %d\n", __func__, s->type);
return -EINVAL;
}
switch (s->target) {
case V4L2_SEL_TGT_CROP_BOUNDS:
case V4L2_SEL_TGT_CROP_DEFAULT:
case V4L2_SEL_TGT_CROP:
s->r.left = inst->crop.left;
s->r.top = inst->crop.top;
s->r.width = inst->crop.width;
s->r.height = inst->crop.height;
break;
case V4L2_SEL_TGT_COMPOSE_BOUNDS:
case V4L2_SEL_TGT_COMPOSE_PADDED:
case V4L2_SEL_TGT_COMPOSE_DEFAULT:
case V4L2_SEL_TGT_COMPOSE:
s->r.left = inst->compose.left;
s->r.top = inst->compose.top;
s->r.width = inst->compose.width;
s->r.height = inst->compose.height;
break;
default:
s_vpr_e(inst->sid, "%s: invalid target %d\n",
__func__, s->target);
rc = -EINVAL;
break;
}
if (!rc)
s_vpr_h(inst->sid, "%s: target %d, r [%d, %d, %d, %d]\n",
__func__, s->target, s->r.top, s->r.left,
s->r.width, s->r.height);
return rc;
}
int msm_venc_enum_fmt(struct msm_vidc_inst *inst, struct v4l2_fmtdesc *f)
{
int rc = 0;

View File

@@ -266,6 +266,44 @@ int msm_vidc_g_fmt(void *instance, struct v4l2_format *f)
}
EXPORT_SYMBOL(msm_vidc_g_fmt);
int msm_vidc_s_selection(void* instance, struct v4l2_selection* s)
{
int rc = 0;
struct msm_vidc_inst* inst = instance;
if (!inst || !s) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
if (is_decode_session(inst))
rc = msm_vdec_s_selection(inst, s);
if (is_encode_session(inst))
rc = msm_venc_s_selection(inst, s);
return rc;
}
EXPORT_SYMBOL(msm_vidc_s_selection);
int msm_vidc_g_selection(void* instance, struct v4l2_selection* s)
{
int rc = 0;
struct msm_vidc_inst* inst = instance;
if (!inst || !s) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
if (is_decode_session(inst))
rc = msm_vdec_g_selection(inst, s);
if (is_encode_session(inst))
rc = msm_venc_g_selection(inst, s);
return rc;
}
EXPORT_SYMBOL(msm_vidc_g_selection);
int msm_vidc_s_ctrl(void *instance, struct v4l2_control *control)
{
struct msm_vidc_inst *inst = instance;

View File

@@ -39,6 +39,8 @@ static struct v4l2_ioctl_ops msm_v4l2_ioctl_ops = {
.vidioc_g_fmt_vid_out_mplane = msm_v4l2_g_fmt,
.vidioc_g_fmt_meta_out = msm_v4l2_g_fmt,
.vidioc_g_fmt_meta_cap = msm_v4l2_g_fmt,
.vidioc_g_selection = msm_v4l2_g_selection,
.vidioc_s_selection = msm_v4l2_s_selection,
.vidioc_reqbufs = msm_v4l2_reqbufs,
.vidioc_qbuf = msm_v4l2_qbuf,
.vidioc_dqbuf = msm_v4l2_dqbuf,

View File

@@ -88,6 +88,22 @@ int msm_v4l2_g_fmt(struct file *file, void *fh,
return msm_vidc_g_fmt((void *)vidc_inst, f);
}
int msm_v4l2_s_selection(struct file* file, void* fh,
struct v4l2_selection* s)
{
struct msm_vidc_inst* vidc_inst = get_vidc_inst(file, fh);
return msm_vidc_s_selection((void*)vidc_inst, s);
}
int msm_v4l2_g_selection(struct file* file, void* fh,
struct v4l2_selection* s)
{
struct msm_vidc_inst* vidc_inst = get_vidc_inst(file, fh);
return msm_vidc_g_selection((void*)vidc_inst, s);
}
int msm_v4l2_s_ctrl(struct file *file, void *fh,
struct v4l2_control *a)
{