Davinci V4L2视频采集框架分析

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://blog.csdn.net/piaozhiye

这里只是记录一些日志,难免有些错误,欢迎批评指正。Davinci V4L2视频采集框架主要是分析davinci_capture.c这个模块。

V4L2简介

Davinci V4L2视频采集驱动其是根据V4L2采集驱动来编写的,想要熟悉其驱动流程,也就比先要了解V4L2德的一些相关知识。我们这里只了解它的采集部分

V4L2(video for linux) 可以支持多种设备它可以有以下5种接口

1视频采集接口(video capture interface)这种应用的设备可以是高频头或者摄像头.V4L2的最初设计就是应用于这种功能的.下面也是着重讲解这种应用

2视频输出接口(video output interface)可以驱动计算机的外围视频图像设备——像可以输出电视信号格式的设备

3直接传输视频接口(video overlay interface)它的主要工作是把从视频采集设备采集过来的信号直接输出到输出设备之上,而不用经过系统的CPU

4视频间隔消隐信号接口(VBI interface)它可以使应用可以访问传输消隐期的视频信号

5收音机接口(radio interface)可用来处理从AMFM高频头设备接收来的音频流

V4L2驱动的主要功能是使程序有发现设备的能力和操作设备.它主要是用过一系列的回调函数来实现这些功能.像设置高频头的频率,帧频,视频压缩格式和图像像参数等等.

关于它的采集流程可以查看http://blog.csdn.net/piaozhiye/article/details/7537419这里我就不罗嗦了。

模块注册与注销

3290 module_init(vpif_init);

3291 module_exit(vpif_cleanup);

另外向其他模块提供了两个导出函数,提供给视频设备注册和注销。

3286 EXPORT_SYMBOL(vpif_register_decoder);

3287 EXPORT_SYMBOL(vpif_unregister_decoder);

vpif_init VPIF采集接口的初始化工作

主要是分配缓冲,检查设备类型,分配内存给channel objects,建立VBI处理的工作队列,注册vpif_driver,注册_vpif_device,申请request_irq,引脚复用的设置。在注册的时候会使用vpif_driver probe来进行注册,注册一些相关的ioctrol等。

	具体如下:
2979 /* vpif_init : This function registers device and driver to
2980  * the kernel, requests irq handler and allocates memory
2981  * for channel objects
2982  */
2983 static __init int vpif_init(void)
2984 {
2985         int free_irq_no_index;
2986         int err = 0, i, j;
2987         int free_channel_objects_index;
2988         int free_buffer_channel_index;
2989         int free_buffer_index;
2990         u8 *addr;
2991         u32 size;
2992 
2993         /* Default number of buffers should be 3 */
2994         if ((channel0_numbuffers > 0) &&
2995             (channel0_numbuffers < config_params.min_numbuffers))
2996                 channel0_numbuffers = config_params.min_numbuffers;
2997         if ((channel1_numbuffers > 0) &&
2998             (channel1_numbuffers < config_params.min_numbuffers))
2999                 channel1_numbuffers = config_params.min_numbuffers;
3000 
3001         /* Set buffer size to min buffers size if invalid buffer size is
3002          * given */
3003         if (channel0_bufsize < config_params.min_bufsize[VPIF_CHANNEL0_VIDEO])
3004                 channel0_bufsize =
3005                     config_params.min_bufsize[VPIF_CHANNEL0_VIDEO];
3006         if (channel1_bufsize < config_params.min_bufsize[VPIF_CHANNEL1_VIDEO])
3007                 channel1_bufsize =
3008                     config_params.min_bufsize[VPIF_CHANNEL1_VIDEO];
3009 
3010         config_params.numbuffers[VPIF_CHANNEL0_VIDEO] = channel0_numbuffers;
3011         config_params.numbuffers[VPIF_CHANNEL1_VIDEO] = channel1_numbuffers;
3012         if (channel0_numbuffers) {
3013                 config_params.channel_bufsize[VPIF_CHANNEL0_VIDEO]
3014                     = channel0_bufsize;
3015         }
3016         if (channel1_numbuffers) {
3017                 config_params.channel_bufsize[VPIF_CHANNEL1_VIDEO]
3018                     = channel1_bufsize;
3019         }
3020 
3021         /* Check the correct value of device_type */
3022         if ((device_type > config_params.max_device_type) || (device_type < 0)) {
3023                 config_params.device_type = 0;
3024         } else {
3025                 config_params.device_type = device_type;
3026         }
3027         /* Allocate memory for six channel objects */
3028         for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
3029                 vpif_obj.dev[i] =
3030                     kmalloc(sizeof(struct channel_obj), GFP_KERNEL);
3031                 /* If memory allocation fails, return error */
3032                 if (!vpif_obj.dev[i]) {
3033                         free_channel_objects_index = i;
3034                         goto vpif_init_free_channel_objects;
3035                         err = -ENOMEM;
3036                 }
3037         }
3038         free_channel_objects_index = VPIF_CAPTURE_MAX_DEVICES;
3039 
3040         /* Allocate memory for buffers */
3041         for (i = 0; i < VPIF_CAPTURE_NUM_CHANNELS; i++) {
3042                 size = config_params.channel_bufsize[i];
3043                 for (j = 0; j < config_params.numbuffers[i]; j++) {
3044                         addr = (u8 *) vpif_alloc_buffer(size);
3045                         if (!addr) {
3046                                 free_buffer_channel_index = i;
3047                                 free_buffer_index = j;
3048                                 err = -ENOMEM;
3049                                 goto vpif_init_free_buffers;
3050                         }
3051                         vpif_obj.dev[i]->common[VPIF_VIDEO_INDEX].fbuffers[j] =
3052                             addr;
3053                 }
3054         }
3055         free_buffer_channel_index = VPIF_CAPTURE_NUM_CHANNELS;
3056         free_buffer_index = config_params.numbuffers[i - 1];
3057 
3058         /* Create the workqueue */
3059         vbi_workqueue = create_singlethread_workqueue("vbi");
3060         if (!vbi_workqueue) {
3061                 err = -ENOMEM;
3062                 goto vpif_init_free_buffers;
3063         }
3064 
3065         /* Register driver to the kernel */
3066         err = driver_register(&vpif_driver);
3067         if (0 != err) {
3068                 goto vpif_init_free_buffers;
3069         }
3070         /* register device as a platform device to the kernel */
3071         err = platform_device_register(&_vpif_device);
3072         if (0 != err) {
3073                 goto vpif_init_unregister_vpif_driver;
3074         }
3075         for (j = 0; j < VPIF_CAPTURE_NUM_CHANNELS; j++) {
3076                 err =
3077                     request_irq(vpif_get_irq_number(j),
3078                                 vpif_channel_isr, SA_INTERRUPT,
3079                                 "DM646x_Capture",
3080                                 (void *)(&(vpif_obj.dev[j]->channel_id)));
3081                 if (0 != err) {
3082                         if (j == 0) {
3083                                 goto vpif_init_unregister_vpif_device;
3084                         } else {
3085                                 free_irq_no_index = j;
3086                                 goto vpif_init_free_irq;
3087                         }
3088                 }
3089         }
3090         free_irq_no_index = VPIF_CAPTURE_NUM_CHANNELS;
3091 
3092         /*err = request_irq(4, vpif_err_isr, SA_INTERRUPT, "DM646x_Capture_err",*/
3093         /*(void *)NULL);*/
3094         /*if (0 != err)*/
3095         /*{*/
3096         /*printk("request error interrupt is err!\n");*/
3097         /*return err;*/
3098         /*}*/
3099 
3100         /*//initialize error interrupt register.*/
3101         /*init_int_err();*/
3102 
3103         /* Set the pinmux settings */
3104         set_vpif_pinmux();
3105         set_vpif_capture_pinmux();
3106 
3107         return 0;
3108 
3109 vpif_init_free_irq:
3110         for (j = 0; j < free_irq_no_index; j++) {
3111                 free_irq(vpif_get_irq_number(j),
3112                          (void *)(&(vpif_obj.dev[j]->channel_id)));
3113         }
3114 vpif_init_unregister_vpif_device:
3115         platform_device_unregister(&_vpif_device);
3116 
3117 vpif_init_unregister_vpif_driver:
3118         driver_unregister(&vpif_driver);
3119 
3120 vpif_init_free_buffers:
3121         for (i = 0; i < free_buffer_channel_index; i++) {
3122                 for (j = 0; j < config_params.numbuffers[i]; j++) {
3123                         addr = vpif_obj.dev[i]->common[VPIF_VIDEO_INDEX].
3124                             fbuffers[j];
3125                         if (addr) {
3126                                 vpif_free_buffer((unsigned long)addr,
3127                                                  config_params.
3128                                                  channel_bufsize[i]
3129                                     );
3130                                 vpif_obj.dev[i]->common[VPIF_VIDEO_INDEX].
3131                                     fbuffers[j] = NULL;
3132                         }
3133                 }
3134         }
3135         for (j = 0; j < free_buffer_index; j++) {
3136                 addr =
3137                     vpif_obj.dev[free_buffer_channel_index]->
3138                     common[VPIF_VIDEO_INDEX].fbuffers[j];
3139                 if (addr) {
3140                         vpif_free_buffer((unsigned long)addr,
3141                                          config_params.channel_bufsize[i]);
3142                         vpif_obj.dev[free_buffer_channel_index]->
3143                             common[VPIF_VIDEO_INDEX].fbuffers[j]
3144                             = NULL;
3145                 }
3146         }
3147 
3148 vpif_init_free_channel_objects:
3149         for (j = 0; j < free_channel_objects_index; j++) {
3150                 if (vpif_obj.dev[i]) {
3151                         kfree(vpif_obj.dev[j]);
3152                         vpif_obj.dev[i] = NULL;
3153                 }
3154         }
3155         return err;
3156 }


其中的一些关键结构:

vpif_driver
2950 static struct device_driver vpif_driver = {
2951         .name = "vpif capture",
2952         .bus = &platform_bus_type,
2953         .probe = vpif_probe,
2954         .remove = vpif_remove,
2955 };      
2956 static struct platform_device _vpif_device = {
2957         .name = "vpif capture",
2958         .id = 1,
2959         .dev = {
2960                 .release = vpif_platform_release,
2961                 }
2962 };              

vpif_probe 

video_device_alloc(); video_device *vfd 分配内存,并初始化,然后channel->video_dev 指向vfd,初始化channel objects,最后使用video_register_device注册video_dev

具体如下:

2816 /* vpif_probe : This function creates device entries by register
2817  * itself to the V4L2 driver and initializes fields of each
2818  * channel objects */
2819 static __init int vpif_probe(struct device *device)
2820 {
2821         struct common_obj *common = NULL;
2822         int i, j = 0, k, err = 0, index = 0;
2823         struct video_device *vfd = NULL;
2824         struct channel_obj *channel = NULL;
2825         struct video_obj *vid_ch = NULL;
2826         vpif_dev = device;
2827 
2828         for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
2829                 /* Get the pointer to the channel object */
2830                 channel = vpif_obj.dev[i];
2831                 /* Allocate memory for video device */
2832                 vfd = video_device_alloc();
2833                 if (ISNULL(vfd)) {
2834                         for (j = 0; j < i; j++) {
2835                                 video_device_release(vpif_obj.dev[j]->
2836                                                      video_dev);
2837                         }
2838                         return -ENOMEM;
2839                 }
2840 
2841                 /* Initialize field of video device */
2842                 *vfd = vpif_video_template;
2843                 vfd->dev = device;
2844                 vfd->release = video_device_release;
2845                 snprintf(vfd->name, sizeof(vfd->name),
2846                          "DM646x_VPIFCapture_DRIVER_V%d.%d.%d",
2847                          (VPIF_CAPTURE_VERSION_CODE >> 16) & 0xff,
2848                          (VPIF_CAPTURE_VERSION_CODE >> 8) & 0xff,
2849                          (VPIF_CAPTURE_VERSION_CODE) & 0xff);
2850                 /* Set video_dev to the video device */
2851                 channel->video_dev = vfd;
2852         }
2853 
2854         for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) {
2855                 channel = vpif_obj.dev[j];
2856                 channel->usrs = 0;
2857                 for (k = VPIF_VIDEO_INDEX; k <= VPIF_HBI_INDEX; k++) {
2858                         common = &(channel->common[k]);
2859                         common->io_usrs = 0;
2860                         common->started = 0;
2861                         spin_lock_init(&common->irqlock);
2862                         init_MUTEX(&common->lock);
2863                         common->numbuffers = 0;
2864                         common->set_addr = NULL;
2865                         common->ytop_off = common->ybtm_off = 0;
2866                         common->ctop_off = common->cbtm_off = 0;
2867                         common->curFrm = common->nextFrm = NULL;
2868                         memset(&common->fmt, 0, sizeof(struct v4l2_format));
2869                 }
2870                 channel->video.std = 0;
2871                 channel->initialized = 0;
2872                 channel->channel_id = j;
2873 
2874                 common = &(channel->common[VPIF_VIDEO_INDEX]);
2875                 vid_ch = &(channel->video);
2876                 /* Initialize field of the channel objects */
2877                 channel->usrs = common->io_usrs = vid_ch->std = 0;
2878                 common->started = channel->initialized = 0;
2879                 channel->channel_id = j;
2880                 common->numbuffers =
2881                     config_params.numbuffers[channel->channel_id];
2882 
2883                 channel->numdecoders = 0;
2884                 channel->current_decoder = 0;
2885                 for (index = 0; index < VPIF_CAPTURE_NUM_DECODERS; index++) {
2886                         channel->decoder[index] = NULL;
2887                 }
2888 
2889                 memset(&(channel->vpifparams), 0, sizeof(struct vpif_params));
2890                 /* Initialize prio member of channel object */
2891                 v4l2_prio_init(&channel->prio);
2892 
2893                 /* Set the tasklet handler in the tasklet struct */
2894                 channel->vbi.vbi_tasklet.func = vbi_work_handler;
2895                 /* Set Timer counter */
2896                 channel->vbi.timer_counter = VPIF_TIMER_COUNT;
2897                 /* Initialize the work structure */
2898                 INIT_WORK(&vbi_work[channel->channel_id],
2899                           (void (*)(void *))vbi_work_handler, (void *)channel);
2900                 /* register video device */
2901                 dev_dbg(vpif_dev, "trying to register vpif device.\n");
2902                 dev_dbg(vpif_dev, "channel=%x,channel->video_dev=%x\n",
2903                         (int)channel, (int)&channel->video_dev);
2904                 channel->common[VPIF_VIDEO_INDEX].fmt.type =
2905                     V4L2_BUF_TYPE_VIDEO_OUTPUT;
2906                 channel->common[VPIF_VBI_INDEX].fmt.type =
2907                     V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
2908                 channel->common[VPIF_HBI_INDEX].fmt.type =
2909                     V4L2_BUF_TYPE_HBI_CAPTURE;
2910                 err = video_register_device(channel->video_dev,
2911                                             VFL_TYPE_GRABBER, vpif_nr[j]);
2912                 if (err)
2913                         goto probe_out;
2914         }
2915         return 0;
2916 
2917 probe_out:
2918         for (k = 0; k < j; k++) {
2919                 /* Get the pointer to the channel object */
2920                 channel = vpif_obj.dev[k];
2921                 /* Unregister video device */
2922                 video_unregister_device(channel->video_dev);
2923                 /* Release video device */
2924                 video_device_release(channel->video_dev);
2925                 channel->video_dev = NULL;
2926         }
2927         dev_dbg(vpif_dev, "</vpif_probe>\n");
2928         return err;
2929 }

struct video_device  *vfd = vpif_video_template;

	vfd = vpif_video_template;是V4L2里面的video_device结构,
	在drivers/media/video/davinci/davinci_capture.c 中
2809 static struct video_device vpif_video_template = {
2810         .name = "vpif", 
2811         .type = VID_TYPE_CAPTURE,
2812         .hardware = 0,
2813         .fops = &vpif_fops,.minor = -1,
2814 }; 

2801 static struct file_operations vpif_fops = {
2802         .owner = THIS_MODULE,
2803         .open = vpif_open,//打开设备做一些初始化工作
2804         .release = vpif_release, //释放资源
2805         .ioctl = vpif_ioctl,//控制命令包括V4L2的命令和自定义的命令
2806         .mmap = vpif_mmap,//映射内核空间内存到用户空间
2807         .poll = vpif_poll       
2808 };                       


vpif_ioctl的一些控制命令

vpif_ioctl封装了一些自定义的命了和V4L2的命令,其中V4L2的命令主要在vpif_doioctl实现。

 /* If the case is for querying capabilities */
            case VIDIOC_QUERYCAP:
                /* If the case is for enumerating inputs */
            case VIDIOC_ENUMINPUT:
                /* If the case is for getting input */
            case VIDIOC_G_INPUT:
                /* If the case is for setting input */
            case VIDIOC_S_INPUT:
                /* If the case is for enumerating standards */
            case VIDIOC_ENUMSTD:
                /* If the case is for querying standards */
            case VIDIOC_QUERYSTD:
                /* If the case is for getting standard */
            case VIDIOC_G_STD:
                /* If the case is for setting standard */
            case VIDIOC_S_STD:
                /* If the case is for enumerating formats */
            case VIDIOC_ENUM_FMT:
                /* If the case is for getting formats */
            case VIDIOC_G_FMT:
                /* If the case is for setting formats */
            case VIDIOC_S_FMT:
                /* If the case is for trying formats */
            case VIDIOC_TRY_FMT:
                /* If the case is for querying controls */
            case VIDIOC_QUERYCTRL:
                /* If the case is for getting controls value */
            case VIDIOC_G_CTRL:
                /* If the case is for getting controls value */
            case VIDIOC_S_CTRL:
                /* If the case is for getting decoder parameters */
            case VPIF_CMD_G_DECODER_PARAMS:
                /* If the case is for setting decoder parameters */
            case VPIF_CMD_S_DECODER_PARAMS:
                /* If the case is for requesting buffer allocation */
            case VIDIOC_REQBUFS:
                /* If the case is for en-queing buffer in the buffer
                 * queue */
            case VIDIOC_QBUF:
                /* If the case is for de-queing buffer from the buffer queue */
            case VIDIOC_DQBUF:
              /* If the case is for querying information about
                 *  buffer for memory mapping io */
            case VIDIOC_QUERYBUF:
                /* If the case is starting streaming */
            case VIDIOC_STREAMON:
                /* If the case is for stopping streaming */
            case VIDIOC_STREAMOFF:
                /* If the case is for setting VPIF parameters */
            case VPIF_S_VPIF_PARAMS:
                /* If the case is for getting VPIF Parameters */
            case VPIF_G_VPIF_PARAMS:
                /* If the case is for getting TVP5146 parameters */
            case VPFE_CMD_CONFIG_TVP5146:
                /* If the case is for setting mt9t001 parameters */
            case VPFE_S_MT9T001_PARAMS:
                /* If the case is for setting mt9t001 parameters */
            case VPFE_G_MT9T001_PARAMS:
            case VIDIOC_S_PRIORITY:
            case VIDIOC_G_PRIORITY:
                /* If the case is for getting sliced vbi capabilites */
            case VIDIOC_G_SLICED_VBI_CAP:
                /* If the case if for getting cropping parameters */
            case VIDIOC_CROPCAP:
            case VPIF_RESYNC:
            case VPIF_RESET:

例如使用VIDIOC_ENUMSTD查询标准的时候,大概流程是这样的

1、首先判断是芯片驱动std_opsdec->std_ops->enumstd是否有完成,如果没有完成则返回失败。

2、判断index是否是合法的

3、最后使用dec->std_ops->enumstd(std, dec),这个会函数直接调用芯片驱动的的xxx_enumstd函数(如sii9013_enumstd)。

具体代码如下:

1377                 /* If the case is for enumerating standards */
1378             case VIDIOC_ENUMSTD:
1379                 {
1380                     struct v4l2_standard *std = (struct v4l2_standard *)arg;
1381                     struct video_obj *vid_ch = &(channel->video);
1382                     int index = std->index, dec_idx;
1383                     dev_dbg(vpif_dev, "VIDIOC_ENUMSTD\n");
1384 
1385 
1386                     /* Call enumstd function of decoder device */
1387                     if (ISNULL(dec->std_ops)
1388                             || ISNULL(dec->std_ops->enumstd)) {
1389                         dev_err(vpif_dev, "vpif_doioctl:No enumstd\n");
1390                         return -EINVAL;
1391                     }
1392                     if (index >= vid_ch->count_std) {
1393                         dev_err(vpif_dev, "Invalid index\n");
1394                         return -EINVAL;
1395                     }
1396                     dec_idx = vid_ch->std_tbl[index].dec_idx;
1397                     dec = channel->decoder[dec_idx];
1398                     std->index = vid_ch->std_tbl[index].std_idx;
1399                     ret = dec->std_ops->enumstd(std, dec);
1400                     std->index = index;
1401                     break;
1402                 }

主要是记录了一些流程,具体的问题没有进行分析,相关芯片的驱动分析可以查阅前面的分析记录。


  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值