V4L2_INT_WRAPPER_1(g_parm, struct v4l2_streamparm, *);
MACRO 的內容是:
#define V4L2_INT_WRAPPER_1(name, arg_type, asterisk) \
static inline int vidioc_int_##name(struct v4l2_int_device *d, \
arg_type asterisk arg) \
{ \
return v4l2_int_ioctl_1(d, vidioc_int_##name##_num, \
(void *)(unsigned long)arg); \
} \
\
static inline struct v4l2_int_ioctl_desc \
vidioc_int_##name##_cb(int (*func) \
(struct v4l2_int_device *, \
arg_type asterisk)) \
{ \
struct v4l2_int_ioctl_desc desc; \
\
desc.num = vidioc_int_##name##_num; \
desc.func = (v4l2_int_ioctl_func *)func; \
\
return desc; \
}
所以實際上call 的是 v4l2_int_ioctl_1
在 drivers/media/video/v4l2-int-device.c:155:int v4l2_int_ioctl_1(struct v4l2_int_device *d, int cmd, void *arg)
int v4l2_int_ioctl_1(struct v4l2_int_device *d, int cmd, void *arg)
{
return ((v4l2_int_ioctl_func_1 *)
find_ioctl(d->u.slave, cmd,
(v4l2_int_ioctl_func *)no_such_ioctl_1))(d, arg);
}
一樣的..
static v4l2_int_ioctl_func *find_ioctl(struct v4l2_int_slave *slave, int cmd,
v4l2_int_ioctl_func *no_such_ioctl)
{
const struct v4l2_int_ioctl_desc *first = slave->ioctls;
const struct v4l2_int_ioctl_desc *last =
first + slave->num_ioctls - 1;
while (first <= last) {
const struct v4l2_int_ioctl_desc *mid;
mid = (last - first) / 2 + first;
if (mid->num < cmd)
first = mid + 1;
else if (mid->num > cmd)
last = mid - 1;
else
return mid->func;
}
return no_such_ioctl;
}
只是在找對應 num 的 function.
這個 num - fun 列表在 register 的時候告訴vl2d, 然後這一段有點麻煩,直接看 num - function 的對應表好了:
drivers/media/video/mxc/capture/adv7180.c
列表:
static struct v4l2_int_ioctl_desc adv7180_ioctl_desc[] = {
....
{vidioc_int_g_parm_num, (v4l2_int_ioctl_func*)ioctl_g_parm},
....
也就是 call ioctl_g_parm..
然後看一下 struct v4l2_streamparm
struct v4l2_streamparm {
enum v4l2_buf_type type;
union {
struct v4l2_captureparm capture;
struct v4l2_outputparm output;
__u8 raw_data[200]; /* user-defined */
} parm;
};
附帶看一下 v4l2_bug_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,
#if 1
/* Experimental */
V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY = 8,
#endif
V4L2_BUF_TYPE_PRIVATE = 0x80,
};
VIDIOC_S_FMT: 主要在設定.. cam->v2f.fmt.fix
另外, VIDIOC_G_STD 可以用來取得 camera in video 的 standard (NTSC, PAL ..etc). 這個 function 會 call..
tv_fmt.type = V4L2_BUF_TYPE_PRIVATE;
vidioc_int_g_fmt_cap(cam->sensor, &tv_fmt);
if (cam->standard_autodetect) {
if (cam->standard.id != tv_fmt.fmt.pix.pixelformat) {
printk("MVC: mxc_v4l2_g_std: "
"Changing standard\n");
mxc_v4l2_s_std(cam, tv_fmt.fmt.pix.pixelformat);
}
}
*e = tv_fmt.fmt.pix.pixelformat;
會呼叫 vidioc_int_g_fmt_cap ,在 type = V4L2_BUF_TYPE_PRIVATE 時,會是
case V4L2_BUF_TYPE_PRIVATE: {
v4l2_std_id std;
adv7180_get_std(&std);
printk(" Returning size of %d\n",std);
f->fmt.pix.pixelformat = (u32)std;
}
break;
也就是 call adv7180 的 autodetect function 找出目前 video 的 standard.並且呼叫 s_std( ) 修改內部的變數 (所以不用再 call VIDIOC_S_STD)
總結:接 ADV7180 時,要call VIDIOC_G_STD, 讓 adv7180 重新 probe video standard。
probe 完後,v4l2 camera 的 format 應該已經設對了。
然後用 VIDIOC_G_FMT (type=V4L2_BUF_TYPE_VIDEO_CAPTURE) 取出 fmt.pix (w.h).
沒有留言:
張貼留言