LINUX&UVC驱动枚举视频格式
2024-04-01
76
0
vidioc_enum_fmt_vid_cap 和 vidioc_enum_fmt_vid_out 是Linux内核中V4L2(Video for Linux 2)驱动程序中的两个ioctl命令,用于枚举视频设备的捕获(capture)和输出(output)格式。
vidioc_enum_fmt_vid_cap:
- 这个ioctl命令用于枚举视频设备(例如摄像头)支持的捕获格式。
- 当应用程序想要捕获视频流时,它可以使用此命令来查询设备支持的不同捕获格式,如像素格式(RGB、YUV等)和分辨率。
- 通常用于设置视频捕获的参数,如帧率、分辨率等。
vidioc_enum_fmt_vid_out:
- 这个ioctl命令用于枚举视频设备(例如视频显示卡)支持的输出格式。
- 当应用程序想要输出视频流时,它可以使用此命令来查询设备支持的不同输出格式,例如显示屏上支持的像素格式和分辨率。
- 通常用于设置视频输出的参数,如输出分辨率、缩放比例等。
因此,两者之间的主要区别在于它们涉及的操作对象和操作的方向。vidioc_enum_fmt_vid_cap用于捕获设备的格式枚举,而vidioc_enum_fmt_vid_out用于输出设备的格式枚举。不过在应用层都使用的控制码为VIDIOC_ENUM_FMT,故使用fmt_desc.type的值是V4L2_BUF_TYPE_VIDEO_CAPTURE还是V4L2_BUF_TYPE_VIDEO_OUTPUT等来区分。
enum v4l2_buf_type {
V4L2_BUF_TYPE_VIDEO_CAPTURE = 1,
V4L2_BUF_TYPE_VIDEO_OUTPUT = 2,
V4L2_BUF_TYPE_VIDEO_OVERLAY = 3,
V4L2_BUF_TYPE_VBI_CAPTURE = 4,
V4L2_BUF_TYPE_VBI_OUTPUT = 5,
V4L2_BUF_TYPE_SLICED_VBI_CAPTURE = 6,
V4L2_BUF_TYPE_SLICED_VBI_OUTPUT = 7,
V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY = 8,
V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE = 9,
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE = 10,
V4L2_BUF_TYPE_SDR_CAPTURE = 11,
V4L2_BUF_TYPE_SDR_OUTPUT = 12,
V4L2_BUF_TYPE_META_CAPTURE = 13,
V4L2_BUF_TYPE_META_OUTPUT = 14,
/* Deprecated, do not use */
V4L2_BUF_TYPE_PRIVATE = 0x80,
};
在LINUX&UVC驱动中,分别使用uvc_ioctl_enum_fmt_vid_cap和uvc_ioctl_enum_fmt_vid_out函数来枚举视频设备的格式。不过其实两者的代码最终是相同的。
const struct v4l2_ioctl_ops uvc_ioctl_ops = {
...
.vidioc_enum_fmt_vid_cap = uvc_ioctl_enum_fmt_vid_cap,
.vidioc_enum_fmt_vid_out = uvc_ioctl_enum_fmt_vid_out,
...
}
最终都是使用的是uvc_ioctl_enum_fmt获取视频设备的格式:
static int uvc_ioctl_enum_fmt_vid_cap(struct file *file, void *fh,struct v4l2_fmtdesc *fmt)
{
struct uvc_fh *handle = fh;
struct uvc_streaming *stream = handle->stream;
return uvc_ioctl_enum_fmt(stream, fmt);
}
static int uvc_ioctl_enum_fmt_vid_out(struct file *file, void *fh,struct v4l2_fmtdesc *fmt)
{
struct uvc_fh *handle = fh;
struct uvc_streaming *stream = handle->stream;
return uvc_ioctl_enum_fmt(stream, fmt);
}
uvc_ioctl_enum_fmt
uvc_ioctl_enum_fmt的代码其实是将UVC视频流接口描述符中解析出的视频格式。
static int uvc_ioctl_enum_fmt(struct uvc_streaming *stream,
struct v4l2_fmtdesc *fmt)
{
struct uvc_format *format;
enum v4l2_buf_type type = fmt->type;
u32 index = fmt->index;
if (fmt->type != stream->type || fmt->index >= stream->nformats)
return -EINVAL;
memset(fmt, 0, sizeof(*fmt));
fmt->index = index;
fmt->type = type;
format = &stream->format[fmt->index];
fmt->flags = 0;
if (format->flags & UVC_FMT_FLAG_COMPRESSED)
fmt->flags |= V4L2_FMT_FLAG_COMPRESSED;
strscpy(fmt->description, format->name, sizeof(fmt->description));
fmt->description[sizeof(fmt->description) - 1] = 0;
fmt->pixelformat = format->fcc;
return 0;
}
当然,这里只解析出了支持的视频格式,其下应还有分辨率Frame和帧率。
- struct uvc_streaming
- struct uvc_format
- struct uvc_frame
- struct uvc_format
struct uvc_frame {
u8 bFrameIndex;
u8 bmCapabilities;
u16 wWidth;
u16 wHeight;
u32 dwMinBitRate;
u32 dwMaxBitRate;
u32 dwMaxVideoFrameBufferSize;
u8 bFrameIntervalType;
u32 dwDefaultFrameInterval;
u32 *dwFrameInterval;
};