linux V4L2子系统——v4l2的结构体(4)之ioctl

linux V4L2子系统——v4l2的结构体(4)之ioctl

备注:
  1. Kernel版本:5.4
  2. 使用工具:Source Insight 4.0

文章目录

  • linux V4L2子系统——v4l2的结构体(4)之ioctl
  • struct v4l2_ioctl_ops
    • 介绍
    • 定义
    • v4l2 API介绍
      • Query Capability:
      • Application Priority
      • Input/Output
      • Image Format
      • TV视频标准
      • Device Inputs and Outputs
      • Camera Control Reference
      • Cropping, composing and scaling
      • 其他杂项
    • struct v4l2_capability 与 VIDIOC_QUERYCAP
    • struct v4l2_format 与 VIDIOC_G_FMT、VIDIOC_S_FMT、VIDIOC_TRY_FMT
    • struct v4l2_requestbuffers 与 VIDIOC_REQBUFS
    • struct v4l2_buffer与 VIDIOC_QUERYBUF、VIDIOC_QBUF、VIDIOC_DQBUF
    • enum v4l2_buf_type 与 VIDIOC_STREAMON、VIDIOC_STREAMOFF
    • struct v4l2_queryctrl 与 VIDIOC_QUERYCTRL
    • ioctl的实现video_ioctl2

struct v4l2_ioctl_ops

介绍

在应用程序获取视频数据的流程中,都是通过 ioctl 命令与驱动程序进行交互,结合实际需求,实现struct v4l2_ioctl_ops相关的成员即可。

定义

//源码:include/media/v4l2-ioctl.h

/**
 * struct v4l2_ioctl_ops - describe operations for each V4L2 ioctl
 *
 * @vidioc_querycap: pointer to the function that implements
 *	:ref:`VIDIOC_QUERYCAP ` ioctl
 * @vidioc_enum_fmt_vid_cap: pointer to the function that implements
 *	:ref:`VIDIOC_ENUM_FMT ` ioctl logic
 *	for video capture in single plane mode
 * @vidioc_enum_fmt_vid_overlay: pointer to the function that implements
 *	:ref:`VIDIOC_ENUM_FMT ` ioctl logic
 *	for video overlay
 * @vidioc_enum_fmt_vid_out: pointer to the function that implements
 *	:ref:`VIDIOC_ENUM_FMT ` ioctl logic
 *	for video output in single plane mode
 * @vidioc_enum_fmt_vid_cap_mplane: pointer to the function that implements
 *	:ref:`VIDIOC_ENUM_FMT ` ioctl logic
 *	for video capture in multiplane mode
 * @vidioc_enum_fmt_vid_out_mplane: pointer to the function that implements
 *	:ref:`VIDIOC_ENUM_FMT ` ioctl logic
 *	for video output in multiplane mode
 * @vidioc_enum_fmt_sdr_cap: pointer to the function that implements
 *	:ref:`VIDIOC_ENUM_FMT ` ioctl logic
 *	for Software Defined Radio capture
 * @vidioc_enum_fmt_sdr_out: pointer to the function that implements
 *	:ref:`VIDIOC_ENUM_FMT ` ioctl logic
 *	for Software Defined Radio output
 * @vidioc_enum_fmt_meta_cap: pointer to the function that implements
 *	:ref:`VIDIOC_ENUM_FMT ` ioctl logic
 *	for metadata capture
 * @vidioc_g_fmt_vid_cap: pointer to the function that implements
 *	:ref:`VIDIOC_G_FMT ` ioctl logic for video capture
 *	in single plane mode
 * @vidioc_g_fmt_vid_overlay: pointer to the function that implements
 *	:ref:`VIDIOC_G_FMT ` ioctl logic for video overlay
 * @vidioc_g_fmt_vid_out: pointer to the function that implements
 *	:ref:`VIDIOC_G_FMT ` ioctl logic for video out
 *	in single plane mode
 * @vidioc_g_fmt_vid_out_overlay: pointer to the function that implements
 *	:ref:`VIDIOC_G_FMT ` ioctl logic for video overlay output
 * @vidioc_g_fmt_vbi_cap: pointer to the function that implements
 *	:ref:`VIDIOC_G_FMT ` ioctl logic for raw VBI capture
 * @vidioc_g_fmt_vbi_out: pointer to the function that implements
 *	:ref:`VIDIOC_G_FMT ` ioctl logic for raw VBI output
 * @vidioc_g_fmt_sliced_vbi_cap: pointer to the function that implements
 *	:ref:`VIDIOC_G_FMT ` ioctl logic for sliced VBI capture
 * @vidioc_g_fmt_sliced_vbi_out: pointer to the function that implements
 *	:ref:`VIDIOC_G_FMT ` ioctl logic for sliced VBI output
 * @vidioc_g_fmt_vid_cap_mplane: pointer to the function that implements
 *	:ref:`VIDIOC_G_FMT ` ioctl logic for video capture
 *	in multiple plane mode
 * @vidioc_g_fmt_vid_out_mplane: pointer to the function that implements
 *	:ref:`VIDIOC_G_FMT ` ioctl logic for video out
 *	in multiplane plane mode
 * @vidioc_g_fmt_sdr_cap: pointer to the function that implements
 *	:ref:`VIDIOC_G_FMT ` ioctl logic for Software Defined
 *	Radio capture
 * @vidioc_g_fmt_sdr_out: pointer to the function that implements
 *	:ref:`VIDIOC_G_FMT ` ioctl logic for Software Defined
 *	Radio output
 * @vidioc_g_fmt_meta_cap: pointer to the function that implements
 *	:ref:`VIDIOC_G_FMT ` ioctl logic for metadata capture
 * @vidioc_s_fmt_vid_cap: pointer to the function that implements
 *	:ref:`VIDIOC_S_FMT ` ioctl logic for video capture
 *	in single plane mode
 * @vidioc_s_fmt_vid_overlay: pointer to the function that implements
 *	:ref:`VIDIOC_S_FMT ` ioctl logic for video overlay
 * @vidioc_s_fmt_vid_out: pointer to the function that implements
 *	:ref:`VIDIOC_S_FMT ` ioctl logic for video out
 *	in single plane mode
 * @vidioc_s_fmt_vid_out_overlay: pointer to the function that implements
 *	:ref:`VIDIOC_S_FMT ` ioctl logic for video overlay output
 * @vidioc_s_fmt_vbi_cap: pointer to the function that implements
 *	:ref:`VIDIOC_S_FMT ` ioctl logic for raw VBI capture
 * @vidioc_s_fmt_vbi_out: pointer to the function that implements
 *	:ref:`VIDIOC_S_FMT ` ioctl logic for raw VBI output
 * @vidioc_s_fmt_sliced_vbi_cap: pointer to the function that implements
 *	:ref:`VIDIOC_S_FMT ` ioctl logic for sliced VBI capture
 * @vidioc_s_fmt_sliced_vbi_out: pointer to the function that implements
 *	:ref:`VIDIOC_S_FMT ` ioctl logic for sliced VBI output
 * @vidioc_s_fmt_vid_cap_mplane: pointer to the function that implements
 *	:ref:`VIDIOC_S_FMT ` ioctl logic for video capture
 *	in multiple plane mode
 * @vidioc_s_fmt_vid_out_mplane: pointer to the function that implements
 *	:ref:`VIDIOC_S_FMT ` ioctl logic for video out
 *	in multiplane plane mode
 * @vidioc_s_fmt_sdr_cap: pointer to the function that implements
 *	:ref:`VIDIOC_S_FMT ` ioctl logic for Software Defined
 *	Radio capture
 * @vidioc_s_fmt_sdr_out: pointer to the function that implements
 *	:ref:`VIDIOC_S_FMT ` ioctl logic for Software Defined
 *	Radio output
 * @vidioc_s_fmt_meta_cap: pointer to the function that implements
 *	:ref:`VIDIOC_S_FMT ` ioctl logic for metadata capture
 * @vidioc_try_fmt_vid_cap: pointer to the function that implements
 *	:ref:`VIDIOC_TRY_FMT ` ioctl logic for video capture
 *	in single plane mode
 * @vidioc_try_fmt_vid_overlay: pointer to the function that implements
 *	:ref:`VIDIOC_TRY_FMT ` ioctl logic for video overlay
 * @vidioc_try_fmt_vid_out: pointer to the function that implements
 *	:ref:`VIDIOC_TRY_FMT ` ioctl logic for video out
 *	in single plane mode
 * @vidioc_try_fmt_vid_out_overlay: pointer to the function that implements
 *	:ref:`VIDIOC_TRY_FMT ` ioctl logic for video overlay
 *	output
 * @vidioc_try_fmt_vbi_cap: pointer to the function that implements
 *	:ref:`VIDIOC_TRY_FMT ` ioctl logic for raw VBI capture
 * @vidioc_try_fmt_vbi_out: pointer to the function that implements
 *	:ref:`VIDIOC_TRY_FMT ` ioctl logic for raw VBI output
 * @vidioc_try_fmt_sliced_vbi_cap: pointer to the function that implements
 *	:ref:`VIDIOC_TRY_FMT ` ioctl logic for sliced VBI
 *	capture
 * @vidioc_try_fmt_sliced_vbi_out: pointer to the function that implements
 *	:ref:`VIDIOC_TRY_FMT ` ioctl logic for sliced VBI output
 * @vidioc_try_fmt_vid_cap_mplane: pointer to the function that implements
 *	:ref:`VIDIOC_TRY_FMT ` ioctl logic for video capture
 *	in multiple plane mode
 * @vidioc_try_fmt_vid_out_mplane: pointer to the function that implements
 *	:ref:`VIDIOC_TRY_FMT ` ioctl logic for video out
 *	in multiplane plane mode
 * @vidioc_try_fmt_sdr_cap: pointer to the function that implements
 *	:ref:`VIDIOC_TRY_FMT ` ioctl logic for Software Defined
 *	Radio capture
 * @vidioc_try_fmt_sdr_out: pointer to the function that implements
 *	:ref:`VIDIOC_TRY_FMT ` ioctl logic for Software Defined
 *	Radio output
 * @vidioc_try_fmt_meta_cap: pointer to the function that implements
 *	:ref:`VIDIOC_TRY_FMT ` ioctl logic for metadata capture
 * @vidioc_reqbufs: pointer to the function that implements
 *	:ref:`VIDIOC_REQBUFS ` ioctl
 * @vidioc_querybuf: pointer to the function that implements
 *	:ref:`VIDIOC_QUERYBUF ` ioctl
 * @vidioc_qbuf: pointer to the function that implements
 *	:ref:`VIDIOC_QBUF ` ioctl
 * @vidioc_expbuf: pointer to the function that implements
 *	:ref:`VIDIOC_EXPBUF ` ioctl
 * @vidioc_dqbuf: pointer to the function that implements
 *	:ref:`VIDIOC_DQBUF ` ioctl
 * @vidioc_create_bufs: pointer to the function that implements
 *	:ref:`VIDIOC_CREATE_BUFS ` ioctl
 * @vidioc_prepare_buf: pointer to the function that implements
 *	:ref:`VIDIOC_PREPARE_BUF ` ioctl
 * @vidioc_overlay: pointer to the function that implements
 *	:ref:`VIDIOC_OVERLAY ` ioctl
 * @vidioc_g_fbuf: pointer to the function that implements
 *	:ref:`VIDIOC_G_FBUF ` ioctl
 * @vidioc_s_fbuf: pointer to the function that implements
 *	:ref:`VIDIOC_S_FBUF ` ioctl
 * @vidioc_streamon: pointer to the function that implements
 *	:ref:`VIDIOC_STREAMON ` ioctl
 * @vidioc_streamoff: pointer to the function that implements
 *	:ref:`VIDIOC_STREAMOFF ` ioctl
 * @vidioc_g_std: pointer to the function that implements
 *	:ref:`VIDIOC_G_STD ` ioctl
 * @vidioc_s_std: pointer to the function that implements
 *	:ref:`VIDIOC_S_STD ` ioctl
 * @vidioc_querystd: pointer to the function that implements
 *	:ref:`VIDIOC_QUERYSTD ` ioctl
 * @vidioc_enum_input: pointer to the function that implements
 *	:ref:`VIDIOC_ENUM_INPUT ` ioctl
 * @vidioc_g_input: pointer to the function that implements
 *	:ref:`VIDIOC_G_INPUT ` ioctl
 * @vidioc_s_input: pointer to the function that implements
 *	:ref:`VIDIOC_S_INPUT ` ioctl
 * @vidioc_enum_output: pointer to the function that implements
 *	:ref:`VIDIOC_ENUM_OUTPUT ` ioctl
 * @vidioc_g_output: pointer to the function that implements
 *	:ref:`VIDIOC_G_OUTPUT ` ioctl
 * @vidioc_s_output: pointer to the function that implements
 *	:ref:`VIDIOC_S_OUTPUT ` ioctl
 * @vidioc_queryctrl: pointer to the function that implements
 *	:ref:`VIDIOC_QUERYCTRL ` ioctl
 * @vidioc_query_ext_ctrl: pointer to the function that implements
 *	:ref:`VIDIOC_QUERY_EXT_CTRL ` ioctl
 * @vidioc_g_ctrl: pointer to the function that implements
 *	:ref:`VIDIOC_G_CTRL ` ioctl
 * @vidioc_s_ctrl: pointer to the function that implements
 *	:ref:`VIDIOC_S_CTRL ` ioctl
 * @vidioc_g_ext_ctrls: pointer to the function that implements
 *	:ref:`VIDIOC_G_EXT_CTRLS ` ioctl
 * @vidioc_s_ext_ctrls: pointer to the function that implements
 *	:ref:`VIDIOC_S_EXT_CTRLS ` ioctl
 * @vidioc_try_ext_ctrls: pointer to the function that implements
 *	:ref:`VIDIOC_TRY_EXT_CTRLS ` ioctl
 * @vidioc_querymenu: pointer to the function that implements
 *	:ref:`VIDIOC_QUERYMENU ` ioctl
 * @vidioc_enumaudio: pointer to the function that implements
 *	:ref:`VIDIOC_ENUMAUDIO ` ioctl
 * @vidioc_g_audio: pointer to the function that implements
 *	:ref:`VIDIOC_G_AUDIO ` ioctl
 * @vidioc_s_audio: pointer to the function that implements
 *	:ref:`VIDIOC_S_AUDIO ` ioctl
 * @vidioc_enumaudout: pointer to the function that implements
 *	:ref:`VIDIOC_ENUMAUDOUT ` ioctl
 * @vidioc_g_audout: pointer to the function that implements
 *	:ref:`VIDIOC_G_AUDOUT ` ioctl
 * @vidioc_s_audout: pointer to the function that implements
 *	:ref:`VIDIOC_S_AUDOUT ` ioctl
 * @vidioc_g_modulator: pointer to the function that implements
 *	:ref:`VIDIOC_G_MODULATOR ` ioctl
 * @vidioc_s_modulator: pointer to the function that implements
 *	:ref:`VIDIOC_S_MODULATOR ` ioctl
 * @vidioc_cropcap: pointer to the function that implements
 *	:ref:`VIDIOC_CROPCAP ` ioctl
 * @vidioc_g_crop: pointer to the function that implements
 *	:ref:`VIDIOC_G_CROP ` ioctl
 * @vidioc_s_crop: pointer to the function that implements
 *	:ref:`VIDIOC_S_CROP ` ioctl
 * @vidioc_g_selection: pointer to the function that implements
 *	:ref:`VIDIOC_G_SELECTION ` ioctl
 * @vidioc_s_selection: pointer to the function that implements
 *	:ref:`VIDIOC_S_SELECTION ` ioctl
 * @vidioc_g_jpegcomp: pointer to the function that implements
 *	:ref:`VIDIOC_G_JPEGCOMP ` ioctl
 * @vidioc_s_jpegcomp: pointer to the function that implements
 *	:ref:`VIDIOC_S_JPEGCOMP ` ioctl
 * @vidioc_g_enc_index: pointer to the function that implements
 *	:ref:`VIDIOC_G_ENC_INDEX ` ioctl
 * @vidioc_encoder_cmd: pointer to the function that implements
 *	:ref:`VIDIOC_ENCODER_CMD ` ioctl
 * @vidioc_try_encoder_cmd: pointer to the function that implements
 *	:ref:`VIDIOC_TRY_ENCODER_CMD ` ioctl
 * @vidioc_decoder_cmd: pointer to the function that implements
 *	:ref:`VIDIOC_DECODER_CMD ` ioctl
 * @vidioc_try_decoder_cmd: pointer to the function that implements
 *	:ref:`VIDIOC_TRY_DECODER_CMD ` ioctl
 * @vidioc_g_parm: pointer to the function that implements
 *	:ref:`VIDIOC_G_PARM ` ioctl
 * @vidioc_s_parm: pointer to the function that implements
 *	:ref:`VIDIOC_S_PARM ` ioctl
 * @vidioc_g_tuner: pointer to the function that implements
 *	:ref:`VIDIOC_G_TUNER ` ioctl
 * @vidioc_s_tuner: pointer to the function that implements
 *	:ref:`VIDIOC_S_TUNER ` ioctl
 * @vidioc_g_frequency: pointer to the function that implements
 *	:ref:`VIDIOC_G_FREQUENCY ` ioctl
 * @vidioc_s_frequency: pointer to the function that implements
 *	:ref:`VIDIOC_S_FREQUENCY ` ioctl
 * @vidioc_enum_freq_bands: pointer to the function that implements
 *	:ref:`VIDIOC_ENUM_FREQ_BANDS ` ioctl
 * @vidioc_g_sliced_vbi_cap: pointer to the function that implements
 *	:ref:`VIDIOC_G_SLICED_VBI_CAP ` ioctl
 * @vidioc_log_status: pointer to the function that implements
 *	:ref:`VIDIOC_LOG_STATUS ` ioctl
 * @vidioc_s_hw_freq_seek: pointer to the function that implements
 *	:ref:`VIDIOC_S_HW_FREQ_SEEK ` ioctl
 * @vidioc_g_register: pointer to the function that implements
 *	:ref:`VIDIOC_DBG_G_REGISTER ` ioctl
 * @vidioc_s_register: pointer to the function that implements
 *	:ref:`VIDIOC_DBG_S_REGISTER ` ioctl
 * @vidioc_g_chip_info: pointer to the function that implements
 *	:ref:`VIDIOC_DBG_G_CHIP_INFO ` ioctl
 * @vidioc_enum_framesizes: pointer to the function that implements
 *	:ref:`VIDIOC_ENUM_FRAMESIZES ` ioctl
 * @vidioc_enum_frameintervals: pointer to the function that implements
 *	:ref:`VIDIOC_ENUM_FRAMEINTERVALS ` ioctl
 * @vidioc_s_dv_timings: pointer to the function that implements
 *	:ref:`VIDIOC_S_DV_TIMINGS ` ioctl
 * @vidioc_g_dv_timings: pointer to the function that implements
 *	:ref:`VIDIOC_G_DV_TIMINGS ` ioctl
 * @vidioc_query_dv_timings: pointer to the function that implements
 *	:ref:`VIDIOC_QUERY_DV_TIMINGS ` ioctl
 * @vidioc_enum_dv_timings: pointer to the function that implements
 *	:ref:`VIDIOC_ENUM_DV_TIMINGS ` ioctl
 * @vidioc_dv_timings_cap: pointer to the function that implements
 *	:ref:`VIDIOC_DV_TIMINGS_CAP ` ioctl
 * @vidioc_g_edid: pointer to the function that implements
 *	:ref:`VIDIOC_G_EDID ` ioctl
 * @vidioc_s_edid: pointer to the function that implements
 *	:ref:`VIDIOC_S_EDID ` ioctl
 * @vidioc_subscribe_event: pointer to the function that implements
 *	:ref:`VIDIOC_SUBSCRIBE_EVENT ` ioctl
 * @vidioc_unsubscribe_event: pointer to the function that implements
 *	:ref:`VIDIOC_UNSUBSCRIBE_EVENT ` ioctl
 * @vidioc_default: pointed used to allow other ioctls
 */
struct v4l2_ioctl_ops {
	/* ioctl callbacks */

	/* VIDIOC_QUERYCAP handler */
	int (*vidioc_querycap)(struct file *file, void *fh,
			       struct v4l2_capability *cap);

	/* VIDIOC_ENUM_FMT handlers */
	int (*vidioc_enum_fmt_vid_cap)(struct file *file, void *fh,
				       struct v4l2_fmtdesc *f);
	int (*vidioc_enum_fmt_vid_overlay)(struct file *file, void *fh,
					   struct v4l2_fmtdesc *f);
	int (*vidioc_enum_fmt_vid_out)(struct file *file, void *fh,
				       struct v4l2_fmtdesc *f);
	int (*vidioc_enum_fmt_vid_cap_mplane)(struct file *file, void *fh,
					      struct v4l2_fmtdesc *f);
	int (*vidioc_enum_fmt_vid_out_mplane)(struct file *file, void *fh,
					      struct v4l2_fmtdesc *f);
	int (*vidioc_enum_fmt_sdr_cap)(struct file *file, void *fh,
				       struct v4l2_fmtdesc *f);
	int (*vidioc_enum_fmt_sdr_out)(struct file *file, void *fh,
				       struct v4l2_fmtdesc *f);
	int (*vidioc_enum_fmt_meta_cap)(struct file *file, void *fh,
					struct v4l2_fmtdesc *f);

	/* VIDIOC_G_FMT handlers */
	int (*vidioc_g_fmt_vid_cap)(struct file *file, void *fh,
				    struct v4l2_format *f);
	int (*vidioc_g_fmt_vid_overlay)(struct file *file, void *fh,
					struct v4l2_format *f);
	int (*vidioc_g_fmt_vid_out)(struct file *file, void *fh,
				    struct v4l2_format *f);
	int (*vidioc_g_fmt_vid_out_overlay)(struct file *file, void *fh,
					    struct v4l2_format *f);
	int (*vidioc_g_fmt_vbi_cap)(struct file *file, void *fh,
				    struct v4l2_format *f);
	int (*vidioc_g_fmt_vbi_out)(struct file *file, void *fh,
				    struct v4l2_format *f);
	int (*vidioc_g_fmt_sliced_vbi_cap)(struct file *file, void *fh,
					   struct v4l2_format *f);
	int (*vidioc_g_fmt_sliced_vbi_out)(struct file *file, void *fh,
					   struct v4l2_format *f);
	int (*vidioc_g_fmt_vid_cap_mplane)(struct file *file, void *fh,
					   struct v4l2_format *f);
	int (*vidioc_g_fmt_vid_out_mplane)(struct file *file, void *fh,
					   struct v4l2_format *f);
	int (*vidioc_g_fmt_sdr_cap)(struct file *file, void *fh,
				    struct v4l2_format *f);
	int (*vidioc_g_fmt_sdr_out)(struct file *file, void *fh,
				    struct v4l2_format *f);
	int (*vidioc_g_fmt_meta_cap)(struct file *file, void *fh,
				     struct v4l2_format *f);

	/* VIDIOC_S_FMT handlers */
	int (*vidioc_s_fmt_vid_cap)(struct file *file, void *fh,
				    struct v4l2_format *f);
	int (*vidioc_s_fmt_vid_overlay)(struct file *file, void *fh,
					struct v4l2_format *f);
	int (*vidioc_s_fmt_vid_out)(struct file *file, void *fh,
				    struct v4l2_format *f);
	int (*vidioc_s_fmt_vid_out_overlay)(struct file *file, void *fh,
					    struct v4l2_format *f);
	int (*vidioc_s_fmt_vbi_cap)(struct file *file, void *fh,
				    struct v4l2_format *f);
	int (*vidioc_s_fmt_vbi_out)(struct file *file, void *fh,
				    struct v4l2_format *f);
	int (*vidioc_s_fmt_sliced_vbi_cap)(struct file *file, void *fh,
					   struct v4l2_format *f);
	int (*vidioc_s_fmt_sliced_vbi_out)(struct file *file, void *fh,
					   struct v4l2_format *f);
	int (*vidioc_s_fmt_vid_cap_mplane)(struct file *file, void *fh,
					   struct v4l2_format *f);
	int (*vidioc_s_fmt_vid_out_mplane)(struct file *file, void *fh,
					   struct v4l2_format *f);
	int (*vidioc_s_fmt_sdr_cap)(struct file *file, void *fh,
				    struct v4l2_format *f);
	int (*vidioc_s_fmt_sdr_out)(struct file *file, void *fh,
				    struct v4l2_format *f);
	int (*vidioc_s_fmt_meta_cap)(struct file *file, void *fh,
				     struct v4l2_format *f);

	/* VIDIOC_TRY_FMT handlers */
	int (*vidioc_try_fmt_vid_cap)(struct file *file, void *fh,
				      struct v4l2_format *f);
	int (*vidioc_try_fmt_vid_overlay)(struct file *file, void *fh,
					  struct v4l2_format *f);
	int (*vidioc_try_fmt_vid_out)(struct file *file, void *fh,
				      struct v4l2_format *f);
	int (*vidioc_try_fmt_vid_out_overlay)(struct file *file, void *fh,
					     struct v4l2_format *f);
	int (*vidioc_try_fmt_vbi_cap)(struct file *file, void *fh,
				      struct v4l2_format *f);
	int (*vidioc_try_fmt_vbi_out)(struct file *file, void *fh,
				      struct v4l2_format *f);
	int (*vidioc_try_fmt_sliced_vbi_cap)(struct file *file, void *fh,
					     struct v4l2_format *f);
	int (*vidioc_try_fmt_sliced_vbi_out)(struct file *file, void *fh,
					     struct v4l2_format *f);
	int (*vidioc_try_fmt_vid_cap_mplane)(struct file *file, void *fh,
					     struct v4l2_format *f);
	int (*vidioc_try_fmt_vid_out_mplane)(struct file *file, void *fh,
					     struct v4l2_format *f);
	int (*vidioc_try_fmt_sdr_cap)(struct file *file, void *fh,
				      struct v4l2_format *f);
	int (*vidioc_try_fmt_sdr_out)(struct file *file, void *fh,
				      struct v4l2_format *f);
	int (*vidioc_try_fmt_meta_cap)(struct file *file, void *fh,
				       struct v4l2_format *f);

	/* Buffer handlers */
	int (*vidioc_reqbufs)(struct file *file, void *fh,
			      struct v4l2_requestbuffers *b);
	int (*vidioc_querybuf)(struct file *file, void *fh,
			       struct v4l2_buffer *b);
	int (*vidioc_qbuf)(struct file *file, void *fh,
			   struct v4l2_buffer *b);
	int (*vidioc_expbuf)(struct file *file, void *fh,
			     struct v4l2_exportbuffer *e);
	int (*vidioc_dqbuf)(struct file *file, void *fh,
			    struct v4l2_buffer *b);

	int (*vidioc_create_bufs)(struct file *file, void *fh,
				  struct v4l2_create_buffers *b);
	int (*vidioc_prepare_buf)(struct file *file, void *fh,
				  struct v4l2_buffer *b);

	int (*vidioc_overlay)(struct file *file, void *fh, unsigned int i);
	int (*vidioc_g_fbuf)(struct file *file, void *fh,
			     struct v4l2_framebuffer *a);
	int (*vidioc_s_fbuf)(struct file *file, void *fh,
			     const struct v4l2_framebuffer *a);

		/* Stream on/off */
	int (*vidioc_streamon)(struct file *file, void *fh,
			       enum v4l2_buf_type i);
	int (*vidioc_streamoff)(struct file *file, void *fh,
				enum v4l2_buf_type i);

		/*
		 * Standard handling
		 *
		 * Note: ENUMSTD is handled by videodev.c
		 */
	int (*vidioc_g_std)(struct file *file, void *fh, v4l2_std_id *norm);
	int (*vidioc_s_std)(struct file *file, void *fh, v4l2_std_id norm);
	int (*vidioc_querystd)(struct file *file, void *fh, v4l2_std_id *a);

		/* Input handling */
	int (*vidioc_enum_input)(struct file *file, void *fh,
				 struct v4l2_input *inp);
	int (*vidioc_g_input)(struct file *file, void *fh, unsigned int *i);
	int (*vidioc_s_input)(struct file *file, void *fh, unsigned int i);

		/* Output handling */
	int (*vidioc_enum_output)(struct file *file, void *fh,
				  struct v4l2_output *a);
	int (*vidioc_g_output)(struct file *file, void *fh, unsigned int *i);
	int (*vidioc_s_output)(struct file *file, void *fh, unsigned int i);

		/* Control handling */
	int (*vidioc_queryctrl)(struct file *file, void *fh,
				struct v4l2_queryctrl *a);
	int (*vidioc_query_ext_ctrl)(struct file *file, void *fh,
				     struct v4l2_query_ext_ctrl *a);
	int (*vidioc_g_ctrl)(struct file *file, void *fh,
			     struct v4l2_control *a);
	int (*vidioc_s_ctrl)(struct file *file, void *fh,
			     struct v4l2_control *a);
	int (*vidioc_g_ext_ctrls)(struct file *file, void *fh,
				  struct v4l2_ext_controls *a);
	int (*vidioc_s_ext_ctrls)(struct file *file, void *fh,
				  struct v4l2_ext_controls *a);
	int (*vidioc_try_ext_ctrls)(struct file *file, void *fh,
				    struct v4l2_ext_controls *a);
	int (*vidioc_querymenu)(struct file *file, void *fh,
				struct v4l2_querymenu *a);

	/* Audio ioctls */
	int (*vidioc_enumaudio)(struct file *file, void *fh,
				struct v4l2_audio *a);
	int (*vidioc_g_audio)(struct file *file, void *fh,
			      struct v4l2_audio *a);
	int (*vidioc_s_audio)(struct file *file, void *fh,
			      const struct v4l2_audio *a);

	/* Audio out ioctls */
	int (*vidioc_enumaudout)(struct file *file, void *fh,
				 struct v4l2_audioout *a);
	int (*vidioc_g_audout)(struct file *file, void *fh,
			       struct v4l2_audioout *a);
	int (*vidioc_s_audout)(struct file *file, void *fh,
			       const struct v4l2_audioout *a);
	int (*vidioc_g_modulator)(struct file *file, void *fh,
				  struct v4l2_modulator *a);
	int (*vidioc_s_modulator)(struct file *file, void *fh,
				  const struct v4l2_modulator *a);
	/* Crop ioctls */
	int (*vidioc_cropcap)(struct file *file, void *fh,
			      struct v4l2_cropcap *a);
	int (*vidioc_g_crop)(struct file *file, void *fh,
			     struct v4l2_crop *a);
	int (*vidioc_s_crop)(struct file *file, void *fh,
			     const struct v4l2_crop *a);
	int (*vidioc_g_selection)(struct file *file, void *fh,
				  struct v4l2_selection *s);
	int (*vidioc_s_selection)(struct file *file, void *fh,
				  struct v4l2_selection *s);
	/* Compression ioctls */
	int (*vidioc_g_jpegcomp)(struct file *file, void *fh,
				 struct v4l2_jpegcompression *a);
	int (*vidioc_s_jpegcomp)(struct file *file, void *fh,
				 const struct v4l2_jpegcompression *a);
	int (*vidioc_g_enc_index)(struct file *file, void *fh,
				  struct v4l2_enc_idx *a);
	int (*vidioc_encoder_cmd)(struct file *file, void *fh,
				  struct v4l2_encoder_cmd *a);
	int (*vidioc_try_encoder_cmd)(struct file *file, void *fh,
				      struct v4l2_encoder_cmd *a);
	int (*vidioc_decoder_cmd)(struct file *file, void *fh,
				  struct v4l2_decoder_cmd *a);
	int (*vidioc_try_decoder_cmd)(struct file *file, void *fh,
				      struct v4l2_decoder_cmd *a);

	/* Stream type-dependent parameter ioctls */
	int (*vidioc_g_parm)(struct file *file, void *fh,
			     struct v4l2_streamparm *a);
	int (*vidioc_s_parm)(struct file *file, void *fh,
			     struct v4l2_streamparm *a);

	/* Tuner ioctls */
	int (*vidioc_g_tuner)(struct file *file, void *fh,
			      struct v4l2_tuner *a);
	int (*vidioc_s_tuner)(struct file *file, void *fh,
			      const struct v4l2_tuner *a);
	int (*vidioc_g_frequency)(struct file *file, void *fh,
				  struct v4l2_frequency *a);
	int (*vidioc_s_frequency)(struct file *file, void *fh,
				  const struct v4l2_frequency *a);
	int (*vidioc_enum_freq_bands)(struct file *file, void *fh,
				      struct v4l2_frequency_band *band);

	/* Sliced VBI cap */
	int (*vidioc_g_sliced_vbi_cap)(struct file *file, void *fh,
				       struct v4l2_sliced_vbi_cap *a);

	/* Log status ioctl */
	int (*vidioc_log_status)(struct file *file, void *fh);

	int (*vidioc_s_hw_freq_seek)(struct file *file, void *fh,
				     const struct v4l2_hw_freq_seek *a);

	/* Debugging ioctls */
#ifdef CONFIG_VIDEO_ADV_DEBUG
	int (*vidioc_g_register)(struct file *file, void *fh,
				 struct v4l2_dbg_register *reg);
	int (*vidioc_s_register)(struct file *file, void *fh,
				 const struct v4l2_dbg_register *reg);

	int (*vidioc_g_chip_info)(struct file *file, void *fh,
				  struct v4l2_dbg_chip_info *chip);
#endif

	int (*vidioc_enum_framesizes)(struct file *file, void *fh,
				      struct v4l2_frmsizeenum *fsize);

	int (*vidioc_enum_frameintervals)(struct file *file, void *fh,
					  struct v4l2_frmivalenum *fival);

	/* DV Timings IOCTLs */
	int (*vidioc_s_dv_timings)(struct file *file, void *fh,
				   struct v4l2_dv_timings *timings);
	int (*vidioc_g_dv_timings)(struct file *file, void *fh,
				   struct v4l2_dv_timings *timings);
	int (*vidioc_query_dv_timings)(struct file *file, void *fh,
				       struct v4l2_dv_timings *timings);
	int (*vidioc_enum_dv_timings)(struct file *file, void *fh,
				      struct v4l2_enum_dv_timings *timings);
	int (*vidioc_dv_timings_cap)(struct file *file, void *fh,
				     struct v4l2_dv_timings_cap *cap);
	int (*vidioc_g_edid)(struct file *file, void *fh,
			     struct v4l2_edid *edid);
	int (*vidioc_s_edid)(struct file *file, void *fh,
			     struct v4l2_edid *edid);

	int (*vidioc_subscribe_event)(struct v4l2_fh *fh,
				      const struct v4l2_event_subscription *sub);
	int (*vidioc_unsubscribe_event)(struct v4l2_fh *fh,
					const struct v4l2_event_subscription *sub);

	/* For other private ioctls */
	long (*vidioc_default)(struct file *file, void *fh,
			       bool valid_prio, unsigned int cmd, void *arg);
};

示例:

// 源码:drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c
static const struct v4l2_ioctl_ops sun6i_video_ioctl_ops = {
	.vidioc_querycap		= vidioc_querycap,
	.vidioc_enum_fmt_vid_cap	= vidioc_enum_fmt_vid_cap,
	.vidioc_g_fmt_vid_cap		= vidioc_g_fmt_vid_cap,
	.vidioc_s_fmt_vid_cap		= vidioc_s_fmt_vid_cap,
	.vidioc_try_fmt_vid_cap		= vidioc_try_fmt_vid_cap,

	.vidioc_enum_input		= vidioc_enum_input,
	.vidioc_s_input			= vidioc_s_input,
	.vidioc_g_input			= vidioc_g_input,

	.vidioc_reqbufs			= vb2_ioctl_reqbufs,
	.vidioc_querybuf		= vb2_ioctl_querybuf,
	.vidioc_qbuf			= vb2_ioctl_qbuf,
	.vidioc_expbuf			= vb2_ioctl_expbuf,
	.vidioc_dqbuf			= vb2_ioctl_dqbuf,
	.vidioc_create_bufs		= vb2_ioctl_create_bufs,
	.vidioc_prepare_buf		= vb2_ioctl_prepare_buf,
	.vidioc_streamon		= vb2_ioctl_streamon,
	.vidioc_streamoff		= vb2_ioctl_streamoff,

	.vidioc_log_status		= v4l2_ctrl_log_status,
	.vidioc_subscribe_event		= v4l2_ctrl_subscribe_event,
	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
};

v4l2 API介绍

大多数操作都是通过应用层调用ioctl实现的,可以将这些ioctl分为下面几类。

Query Capability:

查询设备支持的功能,由于V4L2涵盖了各种各样的设备,因此并非API的所有方面都适用于所有类型的设备,在使用v4l2设备时,必须调用此API,获得设备支持的功能(capture、output、overlay…)。

ID 描述
VIDIOC_QUERYCAP 查询设备功能

Application Priority

应用优先级

当多个应用程序共享设备时,可能需要为它们分配不同的优先级。视频录制应用程序可以例如阻止其他应用程序改变视频控制或切换当前的电视频道。另一个目标是允许在后台工作的低优先级应用程序,这些应用程序可以被用户控制的应用程序抢占,并在以后自动重新获得对设备的控制

ID 描述
VIDIOC_G_PRIORITY 获取优先级
VIDIOC_S_PRIORITY 设置优先级

Input/Output

数据的输入和输出

内核中使用缓存队列对图像数据进行管理,用户空间获取图像数据有两种方式,一种是通过read、write方式读取内核空间的缓存,一种是将内核空间的缓存映射到用户空间。在操作v4l2设备时,通过VIDIOC_QUERYCAP获取设备支持哪种方式。

ID 描述
VIDIOC_REQBUFS 向设备请求视频缓冲区,即初始化视频缓冲区
VIDIOC_QUERYBUF 查询缓冲区的状态
VIDIOC_QBUF 从设备获取一帧视频数据
VIDIOC_DQBUF 将视频缓冲区归回给设备,
VIDIOC_OVERLAY 开始或者停止overlay
VIDIOC_G_FBUF 获取video overlay设备或OSD设备的framebuffer参数
VIDIOC_S_FBUF 设置framebuffer参数
VIDIOC_STREAMON 开始流I/O操作,capture or output device
VIDIOC_STREAMOFF 关闭流I/O操作

Image Format

图像格式图像
由多种格式YUV和RGB还有压缩格式等等,其中每种格式又分有多种格式,比如RGB:RGB565、RGB888…所以在使用设备时,需要对格式进行设置

ID 描述
VIDIOC_ENUM_FMT 枚举设备所支持的所有数据格式
VIDIOC_S_FMT 设置数据格式
VIDIOC_G_FMT 获取数据格式
VIDIOC_TRY_FMT 与VIDIOC_S_FMT一样,但不会改变设备的状态

TV视频标准

TV Standard

ID 描述
VIDIOC_ENUMSTD 枚举设备支持的所有标准
VIDIOC_G_STD 获取当前正在使用的标准
VIDIOC_S_STD 设置视频标准
VIDIOC_QUERYSTD 有的设备支持自动侦测输入源的视频标准,此时使用此ioctl查询侦测到的视频标准

Device Inputs and Outputs

输入和输出设备

ID 描述
VIDIOC_ENUMINPUT 枚举所有input端口
VIDIOC_G_INPUT 获取当前正在使用的input端口
VIDIOC_S_INPUT 设置将要使用的input端口
VIDIOC_ENUMOUTPUT 枚举所有output端口
VIDIOC_G_OUTPUT 获取当前正在使用的output端口
VIDIOC_S_OUTPUT 设置将要使用的output端口
VIDIOC_ENUMAUDIO 枚举所有audio input端口
VIDIOC_G_AUDIO 获取当前正在使用的audio input端口
VIDIOC_S_AUDIO 设置将要使用的audio input端口
VIDIOC_ENUMAUDOUT 枚举所有audio output端口
VIDIOC_G_AUDOUT 获取当前正在使用的audio output端口
VIDIOC_S_AUDOUT 设置将要使用的audio output端口

Camera Control Reference

控制属性
设备特定的控制,例如设置对比度,亮度

ID 描述
VIDIOC_QUERYCTRL 查询指定control的详细信息
VIDIOC_G_CTRL 获取指定control的值
VIDIOC_S_CTRL 设置指定control的值
VIDIOC_G_EXT_CTRLS 获取多个control的值
VIDIOC_S_EXT_CTRLS 设置多个control的值
VIDIOC_TRY_EXT_CTRLS 与VIDIOC_S_EXT_CTRLS相同,但是不改变设备状态
VIDIOC_QUERYMENU 查询menu

Cropping, composing and scaling

图像裁剪、插入与缩放

ID 描述
VIDIOC_G_CROP 获取当前裁剪矩形
VIDIOC_S_CROP 设置当前裁剪矩形
VIDIOC_CROPCAP 有关视频裁剪和缩放功能的信息

其他杂项

ID 描述
VIDIOC_G_MODULATOR
VIDIOC_G_SELECTION 获取选择矩形
VIDIOC_S_SELECTION 设置选择矩形
VIDIOC_G_ENC_INDEX
VIDIOC_ENCODER_CMD
VIDIOC_TRY_ENCODER_CMD
VIDIOC_DECODER_CMD
VIDIOC_TRY_DECODER_CMD
VIDIOC_G_PARM 获取数据流的参数,一般为帧率等参数
VIDIOC_S_PARM 设置数据流的参数,一般为帧率等参数
VIDIOC_G_TUNER
VIDIOC_S_TUNER
VIDIOC_G_FREQUENCY
VIDIOC_S_FREQUENCY
VIDIOC_G_SLICED_VBI_CAP
VIDIOC_LOG_STATUS 记录驱动程序状态信息
VIDIOC_DBG_G_CHIP_IDENT
VIDIOC_S_HW_FREQ_SEEK
VIDIOC_ENUM_FRAMESIZES
VIDIOC_ENUM_FRAMEINTERVALS
VIDIOC_ENUM_DV_PRESETS
VIDIOC_S_DV_PRESET
VIDIOC_G_DV_PRESET
VIDIOC_QUERY_DV_PRESET
VIDIOC_S_DV_TIMINGS
VIDIOC_G_DV_TIMINGS
VIDIOC_DQEVENT
VIDIOC_SUBSCRIBE_EVENT
VIDIOC_UNSUBSCRIBE_EVENT
VIDIOC_CREATE_BUFS 为内存映射或用户指针或 DMA 缓冲区 I/O 创建缓冲区
VIDIOC_PREPARE_BUF 为 I/O 准备缓冲区

注:可参考Linux内核文档查找相关用法。
Linux Media Subsystem Documentation

struct v4l2_capability 与 VIDIOC_QUERYCAP

// 源码:include/uapi/linux/videodev2.h
struct v4l2_capability {
	__u8	driver[16];		// 驱动模块的名称,如"sun6i-video"
	__u8	card[32];		// 品牌名称,如"sunxi WinTV"
	__u8	bus_info[32];	// 总线名称,如"PCI:" + pci_name(pci_dev)
	__u32   version;		// 版本信息,KERNEL_VERSION
	__u32	capabilities;	// 设备整体的功能
	__u32	device_caps;
	__u32	reserved[3];
};

其中域 capabilities 代表设备支持的操作模式,常见的值有 V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING 表示是一个视频捕捉设备并且具有数据流控制模式;另外 driver 域需要和 struct video_device 中的 name 匹配。
如下:

// 源码:include/uapi/linux/videodev2.h

/* Values for 'capabilities' field */
#define V4L2_CAP_VIDEO_CAPTURE		0x00000001  /* Is a video capture device 图像捕获设备 */
#define V4L2_CAP_VIDEO_OUTPUT		0x00000002  /* Is a video output device  图像输出设备 */
#define V4L2_CAP_VIDEO_OVERLAY		0x00000004  /* Can do video overlay      支持预览功能 */
#define V4L2_CAP_VBI_CAPTURE		0x00000010  /* Is a raw VBI capture device */
#define V4L2_CAP_VBI_OUTPUT		0x00000020  /* Is a raw VBI output device */
#define V4L2_CAP_SLICED_VBI_CAPTURE	0x00000040  /* Is a sliced VBI capture device */
#define V4L2_CAP_SLICED_VBI_OUTPUT	0x00000080  /* Is a sliced VBI output device */
#define V4L2_CAP_RDS_CAPTURE		0x00000100  /* RDS data capture */
#define V4L2_CAP_VIDEO_OUTPUT_OVERLAY	0x00000200  /* Can do video output overlay */
#define V4L2_CAP_HW_FREQ_SEEK		0x00000400  /* Can do hardware frequency seek  */
#define V4L2_CAP_RDS_OUTPUT		0x00000800  /* Is an RDS encoder */

/* Is a video capture device that supports multiplanar formats */
#define V4L2_CAP_VIDEO_CAPTURE_MPLANE	0x00001000
/* Is a video output device that supports multiplanar formats */
#define V4L2_CAP_VIDEO_OUTPUT_MPLANE	0x00002000
/* Is a video mem-to-mem device that supports multiplanar formats */
#define V4L2_CAP_VIDEO_M2M_MPLANE	0x00004000
/* Is a video mem-to-mem device */
#define V4L2_CAP_VIDEO_M2M		0x00008000

#define V4L2_CAP_TUNER			0x00010000  /* has a tuner */
#define V4L2_CAP_AUDIO			0x00020000  /* has audio support */
#define V4L2_CAP_RADIO			0x00040000  /* is a radio device */
#define V4L2_CAP_MODULATOR		0x00080000  /* has a modulator */

#define V4L2_CAP_SDR_CAPTURE		0x00100000  /* Is a SDR capture device */
#define V4L2_CAP_EXT_PIX_FORMAT		0x00200000  /* Supports the extended pixel format */
#define V4L2_CAP_SDR_OUTPUT		0x00400000  /* Is a SDR output device */
#define V4L2_CAP_META_CAPTURE		0x00800000  /* Is a metadata capture device */

#define V4L2_CAP_READWRITE              0x01000000  /* read/write systemcalls */
#define V4L2_CAP_ASYNCIO                0x02000000  /* async I/O */
#define V4L2_CAP_STREAMING              0x04000000  /* streaming I/O ioctls */
#define V4L2_CAP_META_OUTPUT		0x08000000  /* Is a metadata output device */

#define V4L2_CAP_TOUCH                  0x10000000  /* Is a touch device */

#define V4L2_CAP_DEVICE_CAPS            0x80000000  /* sets device capabilities field */

struct v4l2_format 与 VIDIOC_G_FMT、VIDIOC_S_FMT、VIDIOC_TRY_FMT

// 源码:include/uapi/linux/videodev2.h
struct v4l2_format {
	__u32	 type;
	union {
		struct v4l2_pix_format		pix;     /* V4L2_BUF_TYPE_VIDEO_CAPTURE */
		struct v4l2_pix_format_mplane	pix_mp;  /* V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE */
		struct v4l2_window		win;     /* V4L2_BUF_TYPE_VIDEO_OVERLAY */
		struct v4l2_vbi_format		vbi;     /* V4L2_BUF_TYPE_VBI_CAPTURE */
		struct v4l2_sliced_vbi_format	sliced;  /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */
		struct v4l2_sdr_format		sdr;     /* V4L2_BUF_TYPE_SDR_CAPTURE */
		struct v4l2_meta_format		meta;    /* V4L2_BUF_TYPE_META_CAPTURE */
		__u8	raw_data[200];                   /* user-defined */
	} fmt;
};

type如下:
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,
	/* Deprecated, do not use */
	V4L2_BUF_TYPE_PRIVATE              = 0x80,
};


/*
 *	V I D E O   I M A G E   F O R M A T
 */
struct v4l2_pix_format {
	__u32			width;
	__u32			height;
	__u32			pixelformat;
	__u32			field;		/* enum v4l2_field */
	__u32			bytesperline;	/* for padding, zero if unused */
	__u32			sizeimage;
	__u32			colorspace;	/* enum v4l2_colorspace */
	__u32			priv;		/* private data, depends on pixelformat */
	__u32			flags;		/* format flags (V4L2_PIX_FMT_FLAG_*) */
	union {
		/* enum v4l2_ycbcr_encoding */
		__u32			ycbcr_enc;
		/* enum v4l2_hsv_encoding */
		__u32			hsv_enc;
	};
	__u32			quantization;	/* enum v4l2_quantization */
	__u32			xfer_func;	/* enum v4l2_xfer_func */
};


struct v4l2_pix_format_mplane {
	__u32				width;
	__u32				height;
	__u32				pixelformat;
	__u32				field;
	__u32				colorspace;

	struct v4l2_plane_pix_format	plane_fmt[VIDEO_MAX_PLANES];
	__u8				num_planes;
	__u8				flags;
	 union {
		__u8				ycbcr_enc;
		__u8				hsv_enc;
	};
	__u8				quantization;
	__u8				xfer_func;
	__u8				reserved[7];
} __attribute__ ((packed));


struct v4l2_window {
	struct v4l2_rect        w;
	__u32			field;	 /* enum v4l2_field */
	__u32			chromakey;
	struct v4l2_clip	__user *clips;
	__u32			clipcount;
	void			__user *bitmap;
	__u8                    global_alpha;
};

/* Raw VBI */
struct v4l2_vbi_format {
	__u32	sampling_rate;		/* in 1 Hz */
	__u32	offset;
	__u32	samples_per_line;
	__u32	sample_format;		/* V4L2_PIX_FMT_* */
	__s32	start[2];
	__u32	count[2];
	__u32	flags;			/* V4L2_VBI_* */
	__u32	reserved[2];		/* must be zero */
};

struct v4l2_sliced_vbi_format {
	__u16   service_set;
	/* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field
	   service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field
				 (equals frame lines 313-336 for 625 line video
				  standards, 263-286 for 525 line standards) */
	__u16   service_lines[2][24];
	__u32   io_size;
	__u32   reserved[2];            /* must be zero */
};


struct v4l2_sdr_format {
	__u32				pixelformat;
	__u32				buffersize;
	__u8				reserved[24];
} __attribute__ ((packed));

struct v4l2_meta_format {
	__u32				dataformat;
	__u32				buffersize;
} __attribute__ ((packed));

常见的捕获模式为 V4L2_BUF_TYPE_VIDEO_CAPTURE 即视频捕捉模式,在此模式下 fmt 联合体采用域 v4l2_pix_format:其中 width 为视频的宽、height 为视频的高、pixelformat 为视频数据格式(常见的值有 V4L2_PIX_FMT_YUV422P | V4L2_PIX_FMT_RGB565)、bytesperline 为一行图像占用的字节数、sizeimage 则为图像占用的总字节数、colorspace 指定设备的颜色空间。

struct v4l2_requestbuffers 与 VIDIOC_REQBUFS

// 源码:include/uapi/linux/videodev2.h
/*
 *	M E M O R Y - M A P P I N G   B U F F E R S
 */
struct v4l2_requestbuffers {
	__u32			count;
	__u32			type;		/* enum v4l2_buf_type */
	__u32			memory;		/* enum v4l2_memory */
	__u32			reserved[2];
};

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,
	/* Deprecated, do not use */
	V4L2_BUF_TYPE_PRIVATE              = 0x80,
};

enum v4l2_memory {
	V4L2_MEMORY_MMAP             = 1,
	V4L2_MEMORY_USERPTR          = 2,
	V4L2_MEMORY_OVERLAY          = 3,
	V4L2_MEMORY_DMABUF           = 4,
};

count 指定根据图像占用空间大小申请的缓存区个数,type 为视频捕获模式,memory 为内存区的使用方式。

struct v4l2_buffer与 VIDIOC_QUERYBUF、VIDIOC_QBUF、VIDIOC_DQBUF

VIDIOC_QUERYBUF 命令通过结构 v4l2_buffer 查询驱动申请的内存区信息:

// 源码:include/uapi/linux/videodev2.h
struct v4l2_buffer {
	__u32			index;
	__u32			type;
	__u32			bytesused;
	__u32			flags;
	__u32			field;
	struct timeval		timestamp;
	struct v4l2_timecode	timecode;
	__u32			sequence;

	/* memory location */
	__u32			memory;
	union {
		__u32           offset;
		unsigned long   userptr;
		struct v4l2_plane *planes;
		__s32		fd;
	} m;
	__u32			length;
	__u32			reserved2;
	__u32			reserved;
};

enum v4l2_buf_type 与 VIDIOC_STREAMON、VIDIOC_STREAMOFF

这两个命令使用的只是一个整形数据,即 v4l2_buf_type,一般只要指定其值为 V4L2_BUF_TYPE_VIDEO_CAPTURE 即可。

struct v4l2_queryctrl 与 VIDIOC_QUERYCTRL

VIDIOC_QUERYCTRL 命令通过结构 v4l2_queryctrl 查询驱动是否支持该 id 代表的命令,并返回该命令的各种参数:

// 源码:include/uapi/linux/videodev2.h
/*  Used in the VIDIOC_QUERYCTRL ioctl for querying controls */
 struct v4l2_queryctrl {
     __u32                id;            /* 命令编号 */
     __u32		      type;	/* enum v4l2_ctrl_type 命令值的类型 */
     __u8                 name[32];        /* 命令名称*/
     __s32                minimum;       /* 最小的命令值 */
     __s32                maximum;       /* 最大的命令值 */
     __s32                step;          /* 命令值变化的步长 */
     __s32                default_value; /* 默认的命令值 */
    __u32                flags;         /* 命令的标志 */
    __u32                reserved[2];   /* 命令值的位图表示 */
};

enum v4l2_ctrl_type {
    V4L2_CTRL_TYPE_INTEGER       = 1,   /* 整形 */
    V4L2_CTRL_TYPE_BOOLEAN       = 2,   /* 真值 */
    V4L2_CTRL_TYPE_MENU          = 3,   /* 菜单 */
    V4L2_CTRL_TYPE_BUTTON        = 4,   /* 无值 */
    V4L2_CTRL_TYPE_INTEGER64     = 5,   /* 后面三种不常用 */
    V4L2_CTRL_TYPE_CTRL_CLASS    = 6
    V4L2_CTRL_TYPE_STRING        = 7,
    V4L2_CTRL_TYPE_BITMASK       = 8,
    V4L2_CTRL_TYPE_INTEGER_MENU  = 9,

    /* Compound types are >= 0x0100 */
    V4L2_CTRL_COMPOUND_TYPES    = 0x0100,
    V4L2_CTRL_TYPE_U8	     = 0x0100,
    V4L2_CTRL_TYPE_U16	     = 0x0101,
    V4L2_CTRL_TYPE_U32	     = 0x0102,
};

命令的标志取值如下:

// 源码:include/uapi/linux/videodev2.h
/*  Control flags  */
#define V4L2_CTRL_FLAG_DISABLED       0x0001
#define V4L2_CTRL_FLAG_GRABBED        0x0002
#define V4L2_CTRL_FLAG_READ_ONLY      0x0004
#define V4L2_CTRL_FLAG_UPDATE         0x0008
#define V4L2_CTRL_FLAG_INACTIVE       0x0010
#define V4L2_CTRL_FLAG_SLIDER         0x0020
#define V4L2_CTRL_FLAG_WRITE_ONLY     0x0040

id 是命令的编号,常见的命令有两种:一种以 V4L2_CID_BASE 为起始值,是公用命令;一种以 V4L2_CID_PRIVATE_BASE 为起始值,是私有命令。在一般的应用中命令值可见如下:

// 源码:include/uapi/linux/v4l2-controls.h
#define V4L2_CID_BASE		(V4L2_CTRL_CLASS_USER | 0x900)
#define V4L2_CID_USER_BASE		V4L2_CID_BASE
#define V4L2_CID_USER_CLASS		(V4L2_CTRL_CLASS_USER | 1)
#define V4L2_CID_BRIGHTNESS		(V4L2_CID_BASE+0)
#define V4L2_CID_CONTRAST		(V4L2_CID_BASE+1) /* 对比度调节 */
#define V4L2_CID_SATURATION		(V4L2_CID_BASE+2) /* 饱和度调节 */
#define V4L2_CID_HUE			(V4L2_CID_BASE+3)
#define V4L2_CID_AUDIO_VOLUME		(V4L2_CID_BASE+5) /* 音量调节 */
#define V4L2_CID_AUDIO_BALANCE		(V4L2_CID_BASE+6)
#define V4L2_CID_AUDIO_BASS		(V4L2_CID_BASE+7)
#define V4L2_CID_AUDIO_TREBLE		(V4L2_CID_BASE+8)
#define V4L2_CID_AUDIO_MUTE		(V4L2_CID_BASE+9) /* 静音设置 */
#define V4L2_CID_AUDIO_LOUDNESS		(V4L2_CID_BASE+10)
#define V4L2_CID_BLACK_LEVEL		(V4L2_CID_BASE+11) /* Deprecated */
#define V4L2_CID_AUTO_WHITE_BALANCE	(V4L2_CID_BASE+12)
#define V4L2_CID_DO_WHITE_BALANCE	(V4L2_CID_BASE+13) /* 白平衡调节 */
#define V4L2_CID_RED_BALANCE		(V4L2_CID_BASE+14)
#define V4L2_CID_BLUE_BALANCE		(V4L2_CID_BASE+15)
#define V4L2_CID_GAMMA			(V4L2_CID_BASE+16) /* 伽马值调节 */
#define V4L2_CID_WHITENESS		(V4L2_CID_GAMMA) /* Deprecated */
#define V4L2_CID_EXPOSURE		(V4L2_CID_BASE+17) /* 曝光度调节 */
#define V4L2_CID_AUTOGAIN		(V4L2_CID_BASE+18)
#define V4L2_CID_GAIN			(V4L2_CID_BASE+19)
#define V4L2_CID_HFLIP			(V4L2_CID_BASE+20)
#define V4L2_CID_VFLIP			(V4L2_CID_BASE+21)

type 为命令值的类型(总共有7中类型的值),name 是命令的名称,reserved 则是命令值的位图表示,驱动会将所有的命令值都以 bit 的形式写到 64 位的域中,上层应用查询时可以根据位图判断命令支持的值。

ioctl的实现video_ioctl2

// 源码:drivers/media/v4l2-core/v4l2-ioctl.c
long video_ioctl2(struct file *file,
	       unsigned int cmd, unsigned long arg)
{
	return video_usercopy(file, cmd, arg, __video_do_ioctl);
}
// 源码:drivers/media/v4l2-core/v4l2-ioctl.c


long
video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
	       v4l2_kioctl func)
{
	char	sbuf[128];
	void    *mbuf = NULL;
	void	*parg = (void *)arg;
	long	err  = -EINVAL;
	bool	has_array_args;
	bool	always_copy = false;
	size_t  array_size = 0;
	void __user *user_ptr = NULL;
	void	**kernel_ptr = NULL;
	const size_t ioc_size = _IOC_SIZE(cmd);

	/*  Copy arguments into temp kernel buffer  */
	/* 判断是否包含读写命令,如果是则将用户空间的参数值拷贝到内核 */
	if (_IOC_DIR(cmd) != _IOC_NONE) {
		 /* 判断参数大小是否超过128字节 */
		if (ioc_size <= sizeof(sbuf)) {
			parg = sbuf;
		} else {
			/* too big to allocate from stack */
			/* 如果超过128字节则从堆中申请 */
			mbuf = kvmalloc(ioc_size, GFP_KERNEL);
			if (NULL == mbuf)
				return -ENOMEM;
			parg = mbuf;
		}

		err = -EFAULT;
		if (_IOC_DIR(cmd) & _IOC_WRITE) {
			unsigned int n = ioc_size;

			/*
			 * In some cases, only a few fields are used as input,
			 * i.e. when the app sets "index" and then the driver
			 * fills in the rest of the structure for the thing
			 * with that index.  We only need to copy up the first
			 * non-input field.
			 */
			/* 确认命令是否为支持命令 */
			if (v4l2_is_known_ioctl(cmd)) {
				/* 计算需要拷贝的有效数据长度,有的命令不需要全部拷贝 */
				u32 flags = v4l2_ioctls[_IOC_NR(cmd)].flags;

				if (flags & INFO_FL_CLEAR_MASK)
					n = (flags & INFO_FL_CLEAR_MASK) >> 16;
				always_copy = flags & INFO_FL_ALWAYS_COPY;
			}

			/* 从用户空间拷贝参数值 */
			if (copy_from_user(parg, (void __user *)arg, n))
				goto out;

			/* zero out anything we don't copy from userspace */
			if (n < ioc_size)  /* 将剩下的空间清零 */
				memset((u8 *)parg + n, 0, ioc_size - n);
		} else {
			/* read-only ioctl */ /* 如果是只读命令则将整个buffer清零 */
			memset(parg, 0, ioc_size);
		}
	}

	/* 特殊命令个性化操作 */
	err = check_array_args(cmd, parg, &array_size, &user_ptr, &kernel_ptr);
	if (err < 0)
		goto out;
	has_array_args = err;

	if (has_array_args) {
		/*
		 * When adding new types of array args, make sure that the
		 * parent argument to ioctl (which contains the pointer to the
		 * array) fits into sbuf (so that mbuf will still remain
		 * unused up to here).
		 */
		mbuf = kvmalloc(array_size, GFP_KERNEL);
		err = -ENOMEM;
		if (NULL == mbuf)
			goto out_array_args;
		err = -EFAULT;
		if (copy_from_user(mbuf, user_ptr, array_size))
			goto out_array_args;
		*kernel_ptr = mbuf;
	}

	/* Handles IOCTL */
	/* 调用 v4l2_ioctl_ops 的成员函数处理命令 */
	err = func(file, cmd, parg);
	if (err == -ENOTTY || err == -ENOIOCTLCMD) {
		err = -ENOTTY;
		goto out;
	}

	if (err == 0) {
		if (cmd == VIDIOC_DQBUF)
			trace_v4l2_dqbuf(video_devdata(file)->minor, parg);
		else if (cmd == VIDIOC_QBUF)
			trace_v4l2_qbuf(video_devdata(file)->minor, parg);
	}

	if (has_array_args) {
		*kernel_ptr = (void __force *)user_ptr;
		if (copy_to_user(user_ptr, mbuf, array_size))
			err = -EFAULT;
		goto out_array_args;
	}
	/*
	 * Some ioctls can return an error, but still have valid
	 * results that must be returned.
	 */
	if (err < 0 && !always_copy)
		goto out;

out_array_args:
	/*  Copy results into user buffer  */
	/* 如果包含读命令则将参数值拷贝到用户空间 */
	switch (_IOC_DIR(cmd)) {
	case _IOC_READ:
	case (_IOC_WRITE | _IOC_READ):
		if (copy_to_user((void __user *)arg, parg, ioc_size))
			err = -EFAULT;
		break;
	}

out:
	kvfree(mbuf);
	return err;
}
// 源码:drivers/media/v4l2-core/v4l2-ioctl.c

static int check_array_args(unsigned int cmd, void *parg, size_t *array_size,
			    void __user **user_ptr, void ***kernel_ptr)
{
	int ret = 0;

	switch (cmd) {
	case VIDIOC_PREPARE_BUF:
	case VIDIOC_QUERYBUF:
	case VIDIOC_QBUF:
	case VIDIOC_DQBUF: {
		struct v4l2_buffer *buf = parg;

		if (V4L2_TYPE_IS_MULTIPLANAR(buf->type) && buf->length > 0) {
			if (buf->length > VIDEO_MAX_PLANES) {
				ret = -EINVAL;
				break;
			}
			*user_ptr = (void __user *)buf->m.planes;
			*kernel_ptr = (void **)&buf->m.planes;
			*array_size = sizeof(struct v4l2_plane) * buf->length;
			ret = 1;
		}
		break;
	}

	case VIDIOC_G_EDID:
	case VIDIOC_S_EDID: {
		struct v4l2_edid *edid = parg;

		if (edid->blocks) {
			if (edid->blocks > 256) {
				ret = -EINVAL;
				break;
			}
			*user_ptr = (void __user *)edid->edid;
			*kernel_ptr = (void **)&edid->edid;
			*array_size = edid->blocks * 128;
			ret = 1;
		}
		break;
	}

	case VIDIOC_S_EXT_CTRLS:
	case VIDIOC_G_EXT_CTRLS:
	case VIDIOC_TRY_EXT_CTRLS: {
		struct v4l2_ext_controls *ctrls = parg;

		if (ctrls->count != 0) {
			if (ctrls->count > V4L2_CID_MAX_CTRLS) {
				ret = -EINVAL;
				break;
			}
			*user_ptr = (void __user *)ctrls->controls;
			*kernel_ptr = (void **)&ctrls->controls;
			*array_size = sizeof(struct v4l2_ext_control)
				    * ctrls->count;
			ret = 1;
		}
		break;
	}
	}

	return ret;
}

// 源码:drivers/media/v4l2-core/v4l2-ioctl.c
static long __video_do_ioctl(struct file *file,
		unsigned int cmd, void *arg)
{
	struct video_device *vfd = video_devdata(file);
	struct mutex *req_queue_lock = NULL;
	struct mutex *lock; /* ioctl serialization mutex */
	const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
	bool write_only = false;
	struct v4l2_ioctl_info default_info;
	const struct v4l2_ioctl_info *info;
	void *fh = file->private_data;
	struct v4l2_fh *vfh = NULL;
	int dev_debug = vfd->dev_debug;
	long ret = -ENOTTY;

	if (ops == NULL) {
		pr_warn("%s: has no ioctl_ops.\n",
				video_device_node_name(vfd));
		return ret;
	}

	if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags))
		vfh = file->private_data;

	/*
	 * We need to serialize streamon/off with queueing new requests.
	 * These ioctls may trigger the cancellation of a streaming
	 * operation, and that should not be mixed with queueing a new
	 * request at the same time.
	 */
	if (v4l2_device_supports_requests(vfd->v4l2_dev) &&
	    (cmd == VIDIOC_STREAMON || cmd == VIDIOC_STREAMOFF)) {
		req_queue_lock = &vfd->v4l2_dev->mdev->req_queue_mutex;

		if (mutex_lock_interruptible(req_queue_lock))
			return -ERESTARTSYS;
	}

	lock = v4l2_ioctl_get_lock(vfd, vfh, cmd, arg);

	if (lock && mutex_lock_interruptible(lock)) {
		if (req_queue_lock)
			mutex_unlock(req_queue_lock);
		return -ERESTARTSYS;
	}

	if (!video_is_registered(vfd)) {
		ret = -ENODEV;
		goto unlock;
	}

	if (v4l2_is_known_ioctl(cmd)) {
		info = &v4l2_ioctls[_IOC_NR(cmd)];

		if (!test_bit(_IOC_NR(cmd), vfd->valid_ioctls) &&
		    !((info->flags & INFO_FL_CTRL) && vfh && vfh->ctrl_handler))
			goto done;

		if (vfh && (info->flags & INFO_FL_PRIO)) {
			ret = v4l2_prio_check(vfd->prio, vfh->prio);
			if (ret)
				goto done;
		}
	} else {
		default_info.ioctl = cmd;
		default_info.flags = 0;
		default_info.debug = v4l_print_default;
		info = &default_info;
	}

	write_only = _IOC_DIR(cmd) == _IOC_WRITE;
	if (info != &default_info) {
		ret = info->func(ops, file, fh, arg);
	} else if (!ops->vidioc_default) {
		ret = -ENOTTY;
	} else {
		ret = ops->vidioc_default(file, fh,
			vfh ? v4l2_prio_check(vfd->prio, vfh->prio) >= 0 : 0,
			cmd, arg);
	}

done:
	if (dev_debug & (V4L2_DEV_DEBUG_IOCTL | V4L2_DEV_DEBUG_IOCTL_ARG)) {
		if (!(dev_debug & V4L2_DEV_DEBUG_STREAMING) &&
		    (cmd == VIDIOC_QBUF || cmd == VIDIOC_DQBUF))
			goto unlock;

		v4l_printk_ioctl(video_device_node_name(vfd), cmd);
		if (ret < 0)
			pr_cont(": error %ld", ret);
		if (!(dev_debug & V4L2_DEV_DEBUG_IOCTL_ARG))
			pr_cont("\n");
		else if (_IOC_DIR(cmd) == _IOC_NONE)
			info->debug(arg, write_only);
		else {
			pr_cont(": ");
			info->debug(arg, write_only);
		}
	}

unlock:
	if (lock)
		mutex_unlock(lock);
	if (req_queue_lock)
		mutex_unlock(req_queue_lock);
	return ret;
}
// 源码:drivers/media/v4l2-core/v4l2-ioctl.c
static bool v4l2_is_known_ioctl(unsigned int cmd)
{
	if (_IOC_NR(cmd) >= V4L2_IOCTLS)
		return false;
	return v4l2_ioctls[_IOC_NR(cmd)].ioctl == cmd;
}

v4l2_ioctls定义如下:

// 源码:drivers/media/v4l2-core/v4l2-ioctl.c
static struct v4l2_ioctl_info v4l2_ioctls[] = {
	IOCTL_INFO(VIDIOC_QUERYCAP, v4l_querycap, v4l_print_querycap, 0),
	IOCTL_INFO(VIDIOC_ENUM_FMT, v4l_enum_fmt, v4l_print_fmtdesc, INFO_FL_CLEAR(v4l2_fmtdesc, type)),
	IOCTL_INFO(VIDIOC_G_FMT, v4l_g_fmt, v4l_print_format, 0),
	IOCTL_INFO(VIDIOC_S_FMT, v4l_s_fmt, v4l_print_format, INFO_FL_PRIO),
	IOCTL_INFO(VIDIOC_REQBUFS, v4l_reqbufs, v4l_print_requestbuffers, INFO_FL_PRIO | INFO_FL_QUEUE),
	IOCTL_INFO(VIDIOC_QUERYBUF, v4l_querybuf, v4l_print_buffer, INFO_FL_QUEUE | INFO_FL_CLEAR(v4l2_buffer, length)),
	IOCTL_INFO(VIDIOC_G_FBUF, v4l_stub_g_fbuf, v4l_print_framebuffer, 0),
	IOCTL_INFO(VIDIOC_S_FBUF, v4l_stub_s_fbuf, v4l_print_framebuffer, INFO_FL_PRIO),
	IOCTL_INFO(VIDIOC_OVERLAY, v4l_overlay, v4l_print_u32, INFO_FL_PRIO),
	IOCTL_INFO(VIDIOC_QBUF, v4l_qbuf, v4l_print_buffer, INFO_FL_QUEUE),
	IOCTL_INFO(VIDIOC_EXPBUF, v4l_stub_expbuf, v4l_print_exportbuffer, INFO_FL_QUEUE | INFO_FL_CLEAR(v4l2_exportbuffer, flags)),
	IOCTL_INFO(VIDIOC_DQBUF, v4l_dqbuf, v4l_print_buffer, INFO_FL_QUEUE),
	IOCTL_INFO(VIDIOC_STREAMON, v4l_streamon, v4l_print_buftype, INFO_FL_PRIO | INFO_FL_QUEUE),
	IOCTL_INFO(VIDIOC_STREAMOFF, v4l_streamoff, v4l_print_buftype, INFO_FL_PRIO | INFO_FL_QUEUE),
	IOCTL_INFO(VIDIOC_G_PARM, v4l_g_parm, v4l_print_streamparm, INFO_FL_CLEAR(v4l2_streamparm, type)),
	IOCTL_INFO(VIDIOC_S_PARM, v4l_s_parm, v4l_print_streamparm, INFO_FL_PRIO),
	IOCTL_INFO(VIDIOC_G_STD, v4l_stub_g_std, v4l_print_std, 0),
	IOCTL_INFO(VIDIOC_S_STD, v4l_s_std, v4l_print_std, INFO_FL_PRIO),
	IOCTL_INFO(VIDIOC_ENUMSTD, v4l_enumstd, v4l_print_standard, INFO_FL_CLEAR(v4l2_standard, index)),
	IOCTL_INFO(VIDIOC_ENUMINPUT, v4l_enuminput, v4l_print_enuminput, INFO_FL_CLEAR(v4l2_input, index)),
	IOCTL_INFO(VIDIOC_G_CTRL, v4l_g_ctrl, v4l_print_control, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_control, id)),
	IOCTL_INFO(VIDIOC_S_CTRL, v4l_s_ctrl, v4l_print_control, INFO_FL_PRIO | INFO_FL_CTRL),
	IOCTL_INFO(VIDIOC_G_TUNER, v4l_g_tuner, v4l_print_tuner, INFO_FL_CLEAR(v4l2_tuner, index)),
	IOCTL_INFO(VIDIOC_S_TUNER, v4l_s_tuner, v4l_print_tuner, INFO_FL_PRIO),
	IOCTL_INFO(VIDIOC_G_AUDIO, v4l_stub_g_audio, v4l_print_audio, 0),
	IOCTL_INFO(VIDIOC_S_AUDIO, v4l_stub_s_audio, v4l_print_audio, INFO_FL_PRIO),
	IOCTL_INFO(VIDIOC_QUERYCTRL, v4l_queryctrl, v4l_print_queryctrl, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_queryctrl, id)),
	IOCTL_INFO(VIDIOC_QUERYMENU, v4l_querymenu, v4l_print_querymenu, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_querymenu, index)),
	IOCTL_INFO(VIDIOC_G_INPUT, v4l_stub_g_input, v4l_print_u32, 0),
	IOCTL_INFO(VIDIOC_S_INPUT, v4l_s_input, v4l_print_u32, INFO_FL_PRIO),
	IOCTL_INFO(VIDIOC_G_EDID, v4l_stub_g_edid, v4l_print_edid, INFO_FL_ALWAYS_COPY),
	IOCTL_INFO(VIDIOC_S_EDID, v4l_stub_s_edid, v4l_print_edid, INFO_FL_PRIO | INFO_FL_ALWAYS_COPY),
	IOCTL_INFO(VIDIOC_G_OUTPUT, v4l_stub_g_output, v4l_print_u32, 0),
	IOCTL_INFO(VIDIOC_S_OUTPUT, v4l_s_output, v4l_print_u32, INFO_FL_PRIO),
	IOCTL_INFO(VIDIOC_ENUMOUTPUT, v4l_enumoutput, v4l_print_enumoutput, INFO_FL_CLEAR(v4l2_output, index)),
	IOCTL_INFO(VIDIOC_G_AUDOUT, v4l_stub_g_audout, v4l_print_audioout, 0),
	IOCTL_INFO(VIDIOC_S_AUDOUT, v4l_stub_s_audout, v4l_print_audioout, INFO_FL_PRIO),
	IOCTL_INFO(VIDIOC_G_MODULATOR, v4l_g_modulator, v4l_print_modulator, INFO_FL_CLEAR(v4l2_modulator, index)),
	IOCTL_INFO(VIDIOC_S_MODULATOR, v4l_s_modulator, v4l_print_modulator, INFO_FL_PRIO),
	IOCTL_INFO(VIDIOC_G_FREQUENCY, v4l_g_frequency, v4l_print_frequency, INFO_FL_CLEAR(v4l2_frequency, tuner)),
	IOCTL_INFO(VIDIOC_S_FREQUENCY, v4l_s_frequency, v4l_print_frequency, INFO_FL_PRIO),
	IOCTL_INFO(VIDIOC_CROPCAP, v4l_cropcap, v4l_print_cropcap, INFO_FL_CLEAR(v4l2_cropcap, type)),
	IOCTL_INFO(VIDIOC_G_CROP, v4l_g_crop, v4l_print_crop, INFO_FL_CLEAR(v4l2_crop, type)),
	IOCTL_INFO(VIDIOC_S_CROP, v4l_s_crop, v4l_print_crop, INFO_FL_PRIO),
	IOCTL_INFO(VIDIOC_G_SELECTION, v4l_g_selection, v4l_print_selection, INFO_FL_CLEAR(v4l2_selection, r)),
	IOCTL_INFO(VIDIOC_S_SELECTION, v4l_s_selection, v4l_print_selection, INFO_FL_PRIO | INFO_FL_CLEAR(v4l2_selection, r)),
	IOCTL_INFO(VIDIOC_G_JPEGCOMP, v4l_stub_g_jpegcomp, v4l_print_jpegcompression, 0),
	IOCTL_INFO(VIDIOC_S_JPEGCOMP, v4l_stub_s_jpegcomp, v4l_print_jpegcompression, INFO_FL_PRIO),
	IOCTL_INFO(VIDIOC_QUERYSTD, v4l_querystd, v4l_print_std, 0),
	IOCTL_INFO(VIDIOC_TRY_FMT, v4l_try_fmt, v4l_print_format, 0),
	IOCTL_INFO(VIDIOC_ENUMAUDIO, v4l_stub_enumaudio, v4l_print_audio, INFO_FL_CLEAR(v4l2_audio, index)),
	IOCTL_INFO(VIDIOC_ENUMAUDOUT, v4l_stub_enumaudout, v4l_print_audioout, INFO_FL_CLEAR(v4l2_audioout, index)),
	IOCTL_INFO(VIDIOC_G_PRIORITY, v4l_g_priority, v4l_print_u32, 0),
	IOCTL_INFO(VIDIOC_S_PRIORITY, v4l_s_priority, v4l_print_u32, INFO_FL_PRIO),
	IOCTL_INFO(VIDIOC_G_SLICED_VBI_CAP, v4l_g_sliced_vbi_cap, v4l_print_sliced_vbi_cap, INFO_FL_CLEAR(v4l2_sliced_vbi_cap, type)),
	IOCTL_INFO(VIDIOC_LOG_STATUS, v4l_log_status, v4l_print_newline, 0),
	IOCTL_INFO(VIDIOC_G_EXT_CTRLS, v4l_g_ext_ctrls, v4l_print_ext_controls, INFO_FL_CTRL),
	IOCTL_INFO(VIDIOC_S_EXT_CTRLS, v4l_s_ext_ctrls, v4l_print_ext_controls, INFO_FL_PRIO | INFO_FL_CTRL),
	IOCTL_INFO(VIDIOC_TRY_EXT_CTRLS, v4l_try_ext_ctrls, v4l_print_ext_controls, INFO_FL_CTRL),
	IOCTL_INFO(VIDIOC_ENUM_FRAMESIZES, v4l_stub_enum_framesizes, v4l_print_frmsizeenum, INFO_FL_CLEAR(v4l2_frmsizeenum, pixel_format)),
	IOCTL_INFO(VIDIOC_ENUM_FRAMEINTERVALS, v4l_stub_enum_frameintervals, v4l_print_frmivalenum, INFO_FL_CLEAR(v4l2_frmivalenum, height)),
	IOCTL_INFO(VIDIOC_G_ENC_INDEX, v4l_stub_g_enc_index, v4l_print_enc_idx, 0),
	IOCTL_INFO(VIDIOC_ENCODER_CMD, v4l_stub_encoder_cmd, v4l_print_encoder_cmd, INFO_FL_PRIO | INFO_FL_CLEAR(v4l2_encoder_cmd, flags)),
	IOCTL_INFO(VIDIOC_TRY_ENCODER_CMD, v4l_stub_try_encoder_cmd, v4l_print_encoder_cmd, INFO_FL_CLEAR(v4l2_encoder_cmd, flags)),
	IOCTL_INFO(VIDIOC_DECODER_CMD, v4l_stub_decoder_cmd, v4l_print_decoder_cmd, INFO_FL_PRIO),
	IOCTL_INFO(VIDIOC_TRY_DECODER_CMD, v4l_stub_try_decoder_cmd, v4l_print_decoder_cmd, 0),
	IOCTL_INFO(VIDIOC_DBG_S_REGISTER, v4l_dbg_s_register, v4l_print_dbg_register, 0),
	IOCTL_INFO(VIDIOC_DBG_G_REGISTER, v4l_dbg_g_register, v4l_print_dbg_register, 0),
	IOCTL_INFO(VIDIOC_S_HW_FREQ_SEEK, v4l_s_hw_freq_seek, v4l_print_hw_freq_seek, INFO_FL_PRIO),
	IOCTL_INFO(VIDIOC_S_DV_TIMINGS, v4l_stub_s_dv_timings, v4l_print_dv_timings, INFO_FL_PRIO | INFO_FL_CLEAR(v4l2_dv_timings, bt.flags)),
	IOCTL_INFO(VIDIOC_G_DV_TIMINGS, v4l_stub_g_dv_timings, v4l_print_dv_timings, 0),
	IOCTL_INFO(VIDIOC_DQEVENT, v4l_dqevent, v4l_print_event, 0),
	IOCTL_INFO(VIDIOC_SUBSCRIBE_EVENT, v4l_subscribe_event, v4l_print_event_subscription, 0),
	IOCTL_INFO(VIDIOC_UNSUBSCRIBE_EVENT, v4l_unsubscribe_event, v4l_print_event_subscription, 0),
	IOCTL_INFO(VIDIOC_CREATE_BUFS, v4l_create_bufs, v4l_print_create_buffers, INFO_FL_PRIO | INFO_FL_QUEUE),
	IOCTL_INFO(VIDIOC_PREPARE_BUF, v4l_prepare_buf, v4l_print_buffer, INFO_FL_QUEUE),
	IOCTL_INFO(VIDIOC_ENUM_DV_TIMINGS, v4l_stub_enum_dv_timings, v4l_print_enum_dv_timings, INFO_FL_CLEAR(v4l2_enum_dv_timings, pad)),
	IOCTL_INFO(VIDIOC_QUERY_DV_TIMINGS, v4l_stub_query_dv_timings, v4l_print_dv_timings, INFO_FL_ALWAYS_COPY),
	IOCTL_INFO(VIDIOC_DV_TIMINGS_CAP, v4l_stub_dv_timings_cap, v4l_print_dv_timings_cap, INFO_FL_CLEAR(v4l2_dv_timings_cap, pad)),
	IOCTL_INFO(VIDIOC_ENUM_FREQ_BANDS, v4l_enum_freq_bands, v4l_print_freq_band, 0),
	IOCTL_INFO(VIDIOC_DBG_G_CHIP_INFO, v4l_dbg_g_chip_info, v4l_print_dbg_chip_info, INFO_FL_CLEAR(v4l2_dbg_chip_info, match)),
	IOCTL_INFO(VIDIOC_QUERY_EXT_CTRL, v4l_query_ext_ctrl, v4l_print_query_ext_ctrl, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_query_ext_ctrl, id)),
};
#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)

你可能感兴趣的:(#,Linux,v4l2,linux,v4l2,V4L2)