先放一张总体框架图
代码详解:(只贴重点代码,下同)
主函数:
<drivers/media/platform/vivid/vivid-core.c>
module_init(vivid_init);
platform_device_register(&vivid_pdev);
platform_driver_register(&vivid_pdrv);
vivid_probe
vivid_create_instance(pdev, i);
vivid_create_instance(pdev, i); //
struct vivid_dev *dev;
struct video_device *vfd;
struct vb2_queue *q;
//!!!初始化v4l2_dev
v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
//参数设置
/*
dev->num_inputs 4
dev->input_type[0] 0 0xe4 = 11 10 01 00
dev->input_type[1] 1
dev->input_type[2] 2
dev->input_type[3] 3
dev->input_name_counter[0] 0
dev->input_name_counter[1] 0
dev->input_name_counter[2] 0
dev->input_name_counter[3] 0
dev->has_audio_inputs
dev->num_outputs
dev->output_type[i]
dev->output_name_counter[i]
dev->has_audio_outputs
dev->has_vid_cap 1 //0x1d3d
dev->has_vid_out 1
dev->has_vbi_cap 0
dev->has_vbi_out 0
dev->has_sdr_cap 1
dev->has_fb 0
dev->has_radio_rx 1
dev->has_radio_tx 1
*/
tpg_init(&dev->tpg, 640, 360); //初始化参数
//填充tpg初始值
tpg_s_fourcc(tpg, V4L2_PIX_FMT_RGB24); //设置图像格式相关的参数
tpg_alloc(&dev->tpg, MAX_ZOOM * MAX_WIDTH) //分配planes内存
tpg_s_fourcc(&dev->tpg, dev->fmt_cap->fourcc); //重新配置参数
//实现用到的是ioctl(fd, VIDIOC_S_FMT, &fmt)里的tpg_s_fourcc
dev->scaled_line = vzalloc(MAX_ZOOM * MAX_WIDTH);
dev->blended_line = vzalloc(MAX_ZOOM * MAX_WIDTH);
dev->edid = vmalloc(256 * 128);
dev->query_dv_timings_qmenu = kmalloc(dev->query_dv_timings_size
//设置dev参数
//!!!初始化control
vivid_create_controls(dev, ccs_cap == -1,
struct v4l2_ctrl_handler *hdl_user_gen = &dev->ctrl_hdl_user_gen;
struct v4l2_ctrl_handler *hdl_vid_cap = &dev->ctrl_hdl_vid_cap;
v4l2_ctrl_handler_init(hdl_user_gen, 10);
v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_class
dev->button = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_button, NULL);
if (dev->has_vid_cap)
dev->test_pattern = v4l2_ctrl_new_custom(hdl_vid_cap,
if (dev->has_vid_cap)
v4l2_ctrl_add_handler(hdl_vid_cap, hdl_user_gen, NULL);
dev->vid_cap_dev.ctrl_handler = hdl_vid_cap;
vivid_update_format_cap(dev, false); //
tpg_reset_source(&dev->tpg, dev->src_rect.width
tpg->bytesperline[p] = (width * tpg->twopixelsize[p])
//实现用到的是ioctl(fd, VIDIOC_S_FMT, &fmt)里的tpg_s_bytesperline(&dev->tpg,
vivid_update_format_out(dev);
v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vid_cap);
v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vid_out);
v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vbi_cap);
v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vbi_out);
v4l2_ctrl_handler_setup(&dev->ctrl_hdl_radio_rx);
v4l2_ctrl_handler_setup(&dev->ctrl_hdl_radio_tx);
v4l2_ctrl_handler_setup(&dev->ctrl_hdl_sdr_cap);
//设置dev->fb_cap.fmt参数
/* init dma queues */
INIT_LIST_HEAD(&dev->vid_cap_active);
INIT_LIST_HEAD(&dev->vid_out_active);
INIT_LIST_HEAD(&dev->vbi_cap_active);
INIT_LIST_HEAD(&dev->vbi_out_active);
INIT_LIST_HEAD(&dev->sdr_cap_active);
if (dev->has_vid_cap)
q = &dev->vb_vid_cap_q;
//填充q
vb2_queue_init(q);
if (dev->has_vid_cap)
vfd = &dev->vid_cap_dev;
//填充vfd
video_register_device(vfd, VFL_TYPE_GRABBER, vid_cap_nr[inst]);
vivid_devs[inst] = dev;