v4l2驱动编写篇(2)
2011年04月01日
应用可以通过调用VIDIOC_G_FMT知道硬件现在的配置如何。这种情况下传递的参数是一个v4l2_format 结构体:
struct v4l2_format
{
enum v4l2_buf_type type;
union
{
struct v4l2_pix_format pix;
struct v4l2_window win;
struct v4l2_vbi_format vbi;
struct v4l2_sliced_vbi_format sliced;
__u8 raw_data[200];
} fmt;
};
同样,type 描述的是缓冲区类型;V4L2层会根据type的不同,将调用解释成不同的驱动的回调函数. 对于视频捕获设备而言,这个回调函数就是:
int (*vidioc_g_fmt_cap)(struct file *file, void *private_data,
struct v4l2_format *f);
对于视频捕获(和输出)设备, 联合体中pix 字段是我们关注的重点. 这是我们在上一期中见过的v4l2_pix_format 结构体;驱动应该用现在的硬件设置填充那个结构体并且返回。这个调用通常不会失败,除非是硬件出现了非常严重的问题。
其他的回调函数还有:
int (*vidioc_s_fmt_overlay)(file, private_data, f);
int (*vidioc_s_fmt_video_output)(file, private_data, f);
int (*vidioc_s_fmt_vbi)(file, private_data, f);
int (*vidioc_s_fmt_vbi_output)(file, private_data, f);
int (*vidioc_s_fmt_vbi_capture)(file, private_data, f);
int (*vidioc_s_fmt_type_private)(file, private_data, f);
vidioc_s_fmt_video_output()与捕获接口一样使用相同的方式使用同一个pix字段。
多数应用都想最终对硬件进行配置以使其为应用提供一种符合其目的的格式。改变视频格有两个接口。第一个是VIDIOC_TRY_FMT 调用,它在V4L2驱动中转化为下面的回调函数:
int (*vidioc_try_fmt_cap)(struct file *file, void *private_data,
struct v4l2_format *f);
int (*vidioc_try_fmt_video_output)(struct file *file, void *private_data,
struct v4l2_format *f);
/* And so on for the other buffer types */
要处理这个调用,驱动会查看请求的视频格式,然后断定硬件是否支持这个格式。如果应用请求的格式是不能支持的,就会返回-EINVAL.所以,例如,一个描述了一个不支持格的fourcc编码或者请求了一个隔行扫描的视频,而设备只支持逐行扫描的就会失败。在另一方面,驱动可以调整size字段,以与硬件支持的图像大小相适应。普便的做法是可能的话就将大小调小。所以一个只能处理VGA分辨率的设备驱动会根据情况相应地调整width和height参数而成功返回。v4l2_format 结构体会在调用后复制给用户空间;驱动应该更新这个结构体以反映改变的参数,这样应用才可以知道它真正得到就是什么。
VIDIOC_TRY_FMT 这个处理对于驱动来说是可选的,但是不推荐忽略这个功能.如果提供了的话,这个函数可以在任何时候调用,甚至时设备正在工作的时候。它不可以对实质上的硬件参数做任何改变,只是让应用知道都可以做什么的一种方式。
如果应用要真正的改变硬件的格式,它使用VIDIOC_S_FMT 调用,它以下面的方式到达驱动:
int (*vidioc_s_fmt_cap)(struct file *file, void *private_data,
struct v4l2_format *f);
int (*vidioc_s_fmt_video_output)(struct file *file, void *private_data,
struct v4l2_format *f);
与VIDIOC_TRY_FMT不同,这个调用是不能随时调用的.如果硬件正在工作,或者有流缓冲器己经开辟了(未来另一篇文章的),改变格式会带来无尽的麻烦。想想会发生什么,比如说,一个新的格式比现在使的缓冲区大的时候。所以驱动要一直保证硬件是空闲的,如果不空闲就对请求返回失败 (-EBUSY).
格式的改变应该是原子的
2011年04月01日
应用可以通过调用VIDIOC_G_FMT知道硬件现在的配置如何。这种情况下传递的参数是一个v4l2_format 结构体:
struct v4l2_format
{
enum v4l2_buf_type type;
union
{
struct v4l2_pix_format pix;
struct v4l2_window win;
struct v4l2_vbi_format vbi;
struct v4l2_sliced_vbi_format sliced;
__u8 raw_data[200];
} fmt;
};
同样,type 描述的是缓冲区类型;V4L2层会根据type的不同,将调用解释成不同的驱动的回调函数. 对于视频捕获设备而言,这个回调函数就是:
int (*vidioc_g_fmt_cap)(struct file *file, void *private_data,
struct v4l2_format *f);
对于视频捕获(和输出)设备, 联合体中pix 字段是我们关注的重点. 这是我们在上一期中见过的v4l2_pix_format 结构体;驱动应该用现在的硬件设置填充那个结构体并且返回。这个调用通常不会失败,除非是硬件出现了非常严重的问题。
其他的回调函数还有:
int (*vidioc_s_fmt_overlay)(file, private_data, f);
int (*vidioc_s_fmt_video_output)(file, private_data, f);
int (*vidioc_s_fmt_vbi)(file, private_data, f);
int (*vidioc_s_fmt_vbi_output)(file, private_data, f);
int (*vidioc_s_fmt_vbi_capture)(file, private_data, f);
int (*vidioc_s_fmt_type_private)(file, private_data, f);
vidioc_s_fmt_video_output()与捕获接口一样使用相同的方式使用同一个pix字段。
多数应用都想最终对硬件进行配置以使其为应用提供一种符合其目的的格式。改变视频格有两个接口。第一个是VIDIOC_TRY_FMT 调用,它在V4L2驱动中转化为下面的回调函数:
int (*vidioc_try_fmt_cap)(struct file *file, void *private_data,
struct v4l2_format *f);
int (*vidioc_try_fmt_video_output)(struct file *file, void *private_data,
struct v4l2_format *f);
/* And so on for the other buffer types */
要处理这个调用,驱动会查看请求的视频格式,然后断定硬件是否支持这个格式。如果应用请求的格式是不能支持的,就会返回-EINVAL.所以,例如,一个描述了一个不支持格的fourcc编码或者请求了一个隔行扫描的视频,而设备只支持逐行扫描的就会失败。在另一方面,驱动可以调整size字段,以与硬件支持的图像大小相适应。普便的做法是可能的话就将大小调小。所以一个只能处理VGA分辨率的设备驱动会根据情况相应地调整width和height参数而成功返回。v4l2_format 结构体会在调用后复制给用户空间;驱动应该更新这个结构体以反映改变的参数,这样应用才可以知道它真正得到就是什么。
VIDIOC_TRY_FMT 这个处理对于驱动来说是可选的,但是不推荐忽略这个功能.如果提供了的话,这个函数可以在任何时候调用,甚至时设备正在工作的时候。它不可以对实质上的硬件参数做任何改变,只是让应用知道都可以做什么的一种方式。
如果应用要真正的改变硬件的格式,它使用VIDIOC_S_FMT 调用,它以下面的方式到达驱动:
int (*vidioc_s_fmt_cap)(struct file *file, void *private_data,
struct v4l2_format *f);
int (*vidioc_s_fmt_video_output)(struct file *file, void *private_data,
struct v4l2_format *f);
与VIDIOC_TRY_FMT不同,这个调用是不能随时调用的.如果硬件正在工作,或者有流缓冲器己经开辟了(未来另一篇文章的),改变格式会带来无尽的麻烦。想想会发生什么,比如说,一个新的格式比现在使的缓冲区大的时候。所以驱动要一直保证硬件是空闲的,如果不空闲就对请求返回失败 (-EBUSY).
格式的改变应该是原子的