Video4Linux框架简介(4) - v4l2_ioctl_ops

25 篇文章 2 订阅
12 篇文章 10 订阅

译注:本节主要会介绍一些v4l2常用的ioctl回调函数,每个驱动开发者可根据硬件需要来做具体实现或者不做实现。

1. Input ioctls

vidioc_enum_input,顾名思义就是枚举输入,对于本示例驱动来说,有标准的S-Video输入和HDMI两种。

static int skeleton_enum_input(struct file *file, void *priv,
struct v4l2_input *i)
{
if (i->index > 1)
return -EINVAL;
i->type = V4L2_INPUT_TYPE_CAMERA; //指定输入类型,有V4L2_INPUT_TYPE_CAMERA和V4L2_INPUT_TYPE_TUNER两种
if (i->index == 0) {
i->std = V4L2_STD_ALL;
strlcpy(i->name, "S-Video", sizeof(i->name));
i->capabilities = V4L2_IN_CAP_STD;
} else {
i->std = 0;
strlcpy(i->name, "HDMI", sizeof(i->name));
i->capabilities = V4L2_IN_CAP_DV_TIMINGS;
}
return 0;
}
static const struct v4l2_ioctl_ops skel_ioctl_ops = {
.vidioc_enum_input = skeleton_enum_input, //可以和之前的vidioc_query_cap放在一起,后面的也一样
}; 

vidioc_g_input 和 vidioc_s_input

应用会调用这两个ioctl来设置和获取当前的input。

static int skeleton_s_input(struct file *file, void *priv, unsigned int i)
{
struct skeleton *skel = video_drvdata(file);
if (i > 1)
return -EINVAL;
skel->input = i;
skel->vdev.tvnorms = i ? 0 : V4L2_STD_ALL;
skeleton_fill_pix_format(skel, &skel->format); //和硬件相关
return 0;
}
static int skeleton_g_input(struct file *file, void *priv, unsigned int *i)
{
struct skeleton *skel = video_drvdata(file);
*i = skel->input;
return 0;
}
static const struct v4l2_ioctl_ops skel_ioctl_ops = {
.vidioc_g_input = skeleton_g_input,
.vidioc_s_input = skeleton_s_input,
}; 

2. SDTV Standards ioctls

vidioc_g_std和vidioc_s_std

获取/设置视频标准,在streaming状态下是不能做设置的。

static int skeleton_s_std(struct file *file, void *priv, v4l2_std_id std)
{
struct skeleton *skel = video_drvdata(file);
if (skel->input)
return -ENODATA;
if (std == skel->std)
return 0;
/* TODO: handle changing std */
skel->std = std;
skeleton_fill_pix_format(skel, &skel->format);
return 0;
}
static int skeleton_g_std(struct file *file, void *priv, v4l2_std_id *std)
{
struct skeleton *skel = video_drvdata(file);
if (skel->input)
return -ENODATA;
*std = skel->std;
return 0;
}
static const struct v4l2_ioctl_ops skel_ioctl_ops = {
.vidioc_g_std = skeleton_g_std,
.vidioc_s_std = skeleton_s_std,
}; 

vidioc_querystd

static int skeleton_querystd(struct file *file, void *priv,
v4l2_std_id *std)
{
struct skeleton *skel = video_drvdata(file);
if (skel->input)
return -ENODATA;
/* TODO: Query currently seen standard. */
return 0;
}
static const struct v4l2_ioctl_ops skel_ioctl_ops = {
.vidioc_querystd = skeleton_querystd,
}; 

3. DV Timings ioctls

vidioc_dv_timings_cap

static const struct v4l2_dv_timings_cap skel_timings_cap = {
.type = V4L2_DV_BT_656_1120,
/* keep this initialization for compatibility with GCC < 4.4.6 */
.reserved = { 0 },
V4L2_INIT_BT_TIMINGS(
720, 1920, /* min/max width */
480, 1080, /* min/max height */
27000000, 74250000, /* min/max pixelclock*/
V4L2_DV_BT_STD_CEA861, /* Supported standards */
/* capabilities */
V4L2_DV_BT_CAP_INTERLACED | V4L2_DV_BT_CAP_PROGRESSIVE
)
};
static int skeleton_dv_timings_cap(struct file *file, void *fh,
struct v4l2_dv_timings_cap *cap)
{
struct skeleton *skel = video_drvdata(file);
if (skel->input == 0)
return -ENODATA;
*cap = skel_timings_cap;
return 0;
}
static const struct v4l2_ioctl_ops skel_ioctl_ops = {
.vidioc_dv_timings_cap = skeleton_dv_timings_cap,
}; 


vidioc_s_dv_timings

static int skeleton_s_dv_timings(struct file *file, void *_fh,
struct v4l2_dv_timings *timings)
{
struct skeleton *skel = video_drvdata(file);
if (skel->input == 0)
return -ENODATA;
if (!v4l2_valid_dv_timings(timings, &skel_timings_cap, NULL,
NULL))
return -EINVAL;
if (!v4l2_find_dv_timings_cap(timings, &skel_timings_cap, 0, NULL,
NULL))
return -EINVAL;
if (v4l2_match_dv_timings(timings, &skel->timings, 0))
return 0;
/* TODO: Configure new timings */
skel->timings = *timings;
skeleton_fill_pix_format(skel, &skel->format);
return 0;
}
static const struct v4l2_ioctl_ops skel_ioctl_ops = {
.vidioc_s_dv_timings = skeleton_s_dv_timings,
}; 

vidioc_g_dv_timings & vidioc_enum_dv_timings

static int skeleton_g_dv_timings(struct file *file, void *_fh,
struct v4l2_dv_timings *timings)
{
struct skeleton *skel = video_drvdata(file);
if (skel->input == 0)
return -ENODATA;
*timings = skel->timings;
return 0;
}
static int skeleton_enum_dv_timings(struct file *file, void *_fh,
struct v4l2_enum_dv_timings *timings)
{
struct skeleton *skel = video_drvdata(file);
if (skel->input == 0)
return -ENODATA;
return v4l2_enum_dv_timings_cap(timings, &skel_timings_cap, NULL, NULL);
}
static const struct v4l2_ioctl_ops skel_ioctl_ops = {
.vidioc_g_dv_timings = skeleton_g_dv_timings,
.vidioc_enum_dv_timings = skeleton_enum_dv_timings,
}; 

vidioc_query_dv_timings

static int skeleton_query_dv_timings(struct file *file, void *_fh,
struct v4l2_dv_timings *timings)
{
struct skeleton *skel = video_drvdata(file);
if (skel->input == 0)
return -ENODATA;
/* TODO: Query currently seen timings. */
detect_timings();
if (no_signal)
return -ENOLINK;
if (cannot_lock_to_signal)
return -ENOLCK;
if (signal_out_of_range_of_capabilities)
return -ERANGE;
/* Useful for debugging */
if (debug)
v4l2_print_dv_timings(skel->v4l2_dev.name,
"query_dv_timings:",
timings, true);
return 0;
}
static const struct v4l2_ioctl_ops skel_ioctl_ops = {
.vidioc_query_dv_timings = skeleton_query_dv_timings,
}; 

4. Format ioctls

static int skeleton_s_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct skeleton *skel = video_drvdata(file);
int ret;
ret = skeleton_try_fmt_vid_cap(file, priv, f);
if (ret)
return ret;
/* TODO: change format */
skel->format = f->fmt.pix;
return 0;
}
static int skeleton_g_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct skeleton *skel = video_drvdata(file);
f->fmt.pix = skel->format;
return 0;
}
static const struct v4l2_ioctl_ops skel_ioctl_ops = {
.vidioc_s_fmt_vid_cap = skeleton_s_fmt_vid_cap,
.vidioc_g_fmt_vid_cap = skeleton_g_fmt_vid_cap,
};

static int skeleton_enum_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
if (f->index != 0)
return -EINVAL;
strlcpy(f->description, "4:2:2, packed, UYVY", sizeof(f-
>description));
f->pixelformat = V4L2_PIX_FMT_UYVY;
f->flags = 0;
return 0;
}
static const struct v4l2_ioctl_ops skel_ioctl_ops = {
.vidioc_enum_fmt_vid_cap = skeleton_enum_fmt_vid_cap,
};

static void skeleton_fill_pix_format(struct skeleton *skel, struct v4l2_pix_format *pix)
{
pix->pixelformat = V4L2_PIX_FMT_UYVY;
if (skel->input == 0) {
pix->width = 720;
pix->height = (skel->std & V4L2_STD_525_60) ? 480 : 576;
pix->field = V4L2_FIELD_INTERLACED;
pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
} else {
pix->width = skel->timings.bt.width;
pix->height = skel->timings.bt.height;
if (skel->timings.bt.interlaced)
pix->field = V4L2_FIELD_INTERLACED;
else
pix->field = V4L2_FIELD_NONE;
pix->colorspace = V4L2_COLORSPACE_REC709;
}
pix->bytesperline = pix->width * 2;
pix->sizeimage = pix->bytesperline * pix->height;
pix->priv = 0;
}
static int skeleton_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f)
{
struct skeleton *skel = video_drvdata(file);
struct v4l2_pix_format *pix = &f->fmt.pix;
if (pix->pixelformat != V4L2_PIX_FMT_UYVY)
return -EINVAL;
skeleton_fill_pix_format(skel, pix);
return 0;
}
static const struct v4l2_ioctl_ops skel_ioctl_ops = {
.vidioc_try_fmt_vid_cap = skeleton_try_fmt_vid_cap,
} 



  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值