嵌入式网络视频采集源程序servfox解析03

 接嵌入式网络视频采集源程序servfox解析02


跟踪进入 init_v4l (vd)

 

/****************************************************************************************************

init_v4l (vd)是初始化V4L视频设备的函数,在spcav4l.c中定义:

static int
init_v4l (struct vdIn *vd)
{
  int f;
  int erreur = 0;
  int err;
  if ((vd->fd = open (vd->videodevice, O_RDWR)) == -1)//打开
视频设备
    exit_fatal ("ERROR opening V4L interface");

  if (ioctl (vd->fd, VIDIOCGCAP, &(vd->videocap)) == -1)
    exit_fatal ("Couldn't get videodevice capability");
    /*************************************************************************************************
        ioctl用于向设备发控制和配置命令 ,有些命令也需要读写一些数据,但这些数据是不能用read/write读写的,称为Out-of-band数据。也就是说,read/write读写的数据是in-band数据,是I/O操作的主体,而ioctl命令传送的是控制信息,其中的数据是辅助的数据。ioctl是设备驱动程序中对设备的I/O通道进行管理的函数,所谓对I/O通道进行管理,就是对设备的一些特性进行控制,例如,在串口线上收发数据通过read/write操作,而串口的波特率、校验位、停止位通过ioctl设置,A/D转换的结果通过read读取,而A/D转换的精度和工作频率通过ioctl设置。
    ioctl函数是文件结构中的一个属性分量,就是说如果你的驱动程序提供了对ioctl的支持,用户就可以在用户程序中使用ioctl函数控制设备的I/O通道。
    如果不用ioctl的话,也可以实现对设备I/O通道的控制,但那就是蛮拧了。例如,我们可以在驱动程序中实现write的时候检查一下是否有特殊约定的数据流通过,如果有的话,那么后面就跟着控制命令(一般在socket编程中常常这样做)。但是如果这样做的话,会导致代码分工不明,程序结构混乱,程序员自己也会头昏眼花的。
  
  所以,我们就使用ioctl来实现控制的功能 。要记住,用户程序所作的只是通过命令码告诉驱动程序它想做什么,至于怎么解释这些命令和怎么实现这些命令,这都是驱动程序要做的事情。
    int ioctl(int fd, ind cmd, …);
    其中fd就是用户程序打开设备时使用open函数返回的文件标示符,cmd就是用户程序对设备的控制命令,至于后面的省略号,那是一些补充参数,一般最多一个,有或没有是和cmd的意义相关的。

   

    调用函数ioctl (vd->fd, VIDIOCGCAP, &(vd->videocap))成功后可读取vd->capability各分量 , 读video_capability 中信息包括设备名称,支持最大最小分辨率,信号源信息等。

    video_capability是Video4linux支持的数据结构, 在前面定义:

    struct vdIn {
    int fd;      //设备
描述符, 文件描述符
    char *videodevice ; //设备, 视频捕捉接口文件
    struct video_mmap vmmap;

    struct video_capability videocap;   // 包含设备的基本信息(设备名称、支持的最大最小分辨率、信号源     .....................................

    }

.

video_capability 包含设备的基本信息(设备名称、支持的最大最小分辨率、信号源信息等),包含的分量:
•name[32]   //设备名称
•maxwidth ,maxheight,minwidth,minheight
•Channels //信号源个数
•type    //是否能capture,彩色还是黑白,是否能裁剪等等。值如VID_TYPE_CAPTURE等


struct video_capability
{
        char name[32];
        int type;
        int channels;        /* Num channels */
        int audios;        /* Num audio devices */
        int maxwidth;        /* Supported width */
        int maxheight;        /* And height */
        int minwidth;        /* Supported width */
        int minheight;        /* And height */
};
    name是摄像头的名字,maxwidth maxheight是摄像头所能获取的最大图像大小,用像素作单位
    在程序中,通过ioctl函数的VIDIOCGCAP控制命令读写设备通道已获取这个结构

************ ***************************************************************************************** /

  if(debug) printf ("Camera found: %s /n", vd->videocap.name);


  snprintf (vd->cameraname, 32, "%s", vd->videocap.name);

    /*********************************************************************************************

      我们通过在 Video4Linux视频设备数据结构中:
        struct vdIn {
    int fd;      //设备
描述符, 文件描述符
    char *videodevice ; //设备, 视频捕捉接口文件
    struct video_mmap vmmap;
    struct video_capability videocap;

      ............................................

    char *cameraname;   //设备名称

    }

       定义 struct video_capability videocap这个结构体,通过上面的 ioctl (vd->fd, VIDIOCGCAP, &(vd->videocap))获得视频采集设备的名称后传给 vd->cameraname。
     *********************************************************************************************/
  erreur = GetVideoPict (vd);

   /*********************************************************************************************

    GetVideoPict()也在spcav4l.c中定义:

       static int
GetVideoPict (struct vdIn *vd)
{
  if (ioctl (vd->fd, VIDIOCGPICT, &vd->videopict) < 0)
    exit_fatal ("Couldnt get videopict params with VIDIOCGPICT");
        -------------------------------------------------------------

             跟 ioctl (vd->fd, VIDIOCGCAP, &(vd->videocap))类似, ioctl (vd->fd, VIDIOCGPICT,                 &vd->videopict) 获取摄象头缓冲区中video_picture 中各 分量的值。

          vd->videopict在下面定义:

                struct vdIn {
        int fd;      //设备
描述符, 文件描述符
        char *videodevice ; //设备,
视频捕捉接口文件
        struct video_mmap vmmap;
        struct video_capability videocap;     // 包含设备的基本信息(设备名称、支持的最大最小分辨率、信                                                                              号源信息等)
         int mmapsize;
         struct video_mbuf videombuf;
    //映射的帧信息,实际是映射到摄像头存储缓冲区的帧信息,包括帧                                                                    的大小(size),最多支持的帧数(frames) 每帧相对基址的偏移                                                                        (offset)
         struct video_picture videopict;   //采集图像的各种属性
         struct video_window videowin;  
         struct video_channel videochan;  

       ...................................................................................

       }

               我们来看看 struct video_picture videopict这个结构体:

               

                struct video_picture

                {

                     __u16     brightness;

                __u16     hue;

                __u16     colour;

                __u16     contrast;

                __u16     whiteness;       /* Black and white only */

                __u16     depth;            /* Capture depth */

                __u16   palette;    /* Palette in use */

       }

                    video_picture 设备采集的图象的各种属性
                    •brightness 0~65535 
亮度
                    •hue
                    •colour
                    •contrast   
对比度
                    •whiteness
                    •depth // 24  
色深
                    •palette //VIDEO_PALETTE_RGB24   调色板

                picture 结构包括了亮度,对比度,色深,调色板等等信息

        -------------------------------------------------------------

  if(debug) printf ("VIDIOCGPICT brightnes=%d hue=%d color=%d contrast=%d whiteness=%d"
      "depth=%d palette=%d/n", vd->videopict.brightness,
      vd->videopict.hue, vd->videopict.colour, vd->videopict.contrast,
      vd->videopict.whiteness, vd->videopict.depth,
      vd->videopict.palette);

  return 0;
}

    这个函数是为了获得 摄象头 采集到的图象 缓冲区中video_picture 中各分量的值

    如果要对 对采集图象的各种属性进行设置,可分为两步进行, 首先获取摄象头缓冲区中video_picture中信息调用函数ioctl(vd->fd, VIDIOCGPICT, &(vd->picture));然后改变video_picture中分量的值, 调用 ioctl (vd->fd, VIDIOCSPICT, &vd->videopict) 为vd->videopict分量赋新值。

   *********************************************************************************************/


   if (ioctl (vd->fd, VIDIOCGCHAN, &vd->videochan) == -1)


    {
      if(debug) printf ("Hmm did not support Video_channel/n");
      vd->cameratype = UNOW;
    }

      /*********************************************************************************************

          同样, ioctl (vd->fd, VIDIOCGCHAN, &vd->videochan)可以获得 各个信号源的属性的信息

             要 上面的 struct vdIn中定义的 struct video_channel videochan

          video_channel         关于各个信号源的属性
            Channel //信号源的编号
            name
            tuners
            Type     VIDEO_TYPE_TV  |  IDEO_TYPE_CAMERA
            Norm制式

          struct video_channel在 v4l API 中定义:

          struct video_channel
            {
                int channel;
                char name[32];
                int tuners;
                __u32  flags;
                #define VIDEO_VC_TUNER        1    /* Channel has a tuner */
                #define VIDEO_VC_AUDIO        2    /* Channel has audio */
                __u16  type;
                # define VIDEO_TYPE_TV        1
                #define VIDEO_TYPE_CAMERA    2
                __u16 norm;            /* Norm set by channel */
                };

                成员channel代表输入源,通常,0: television 1:composite1 2:s-video
                name 表示该输入源的名称。
                norm 表示制式,通常,0:pal 1:ntsc 2:secam 3:auto

             在linux下,在 /usr/include/linux /videodev.h中有详细定义。

          vd->cameratype:在

            struct vdIn {

                   .................................

                     int cameratype ;      // 是否能capture,彩色还是黑白,是否  能裁剪等等
                    char *cameraname;   //设备名称
                    char bridge[9];

                ........................................

             }

            中定义。

           **********************************************************************************************/
   
  else
    {
    if (vd->videochan.name){
      if(debug) printf ("Bridge found: %s /n", vd->videochan.name);
      snprintf (vd->bridge, 9, "%s", vd->videochan.name);
      vd->cameratype = GetStreamId (vd->bridge);
      }

      /*********************************************************************************************

          进入:GetStreamId ()函数定义在spcav4l.c中:

      static int
  GetStreamId (const char *BridgeName)
   {
          int i = -1;
          int match = -1;
/* return Stream_id otherwhise -1 */
  if ((match = isSpcaChip (BridgeName)) < 0)
    {
      if(debug) printf ("Not an Spca5xx Camera !!/n");
      return match;
    }


  

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    isSpcaChip也定义在spcav4l.c中:在  GetStreamId()的上面。

static int
isSpcaChip (const char *BridgeName)
{
  int i = -1;
  int find = -1;
  int size = 0;
 
  /* Spca506 return more with channel video, cut it */
 
  /* return Bridge otherwhise -1 */
  for (i = 0; i < MAX_BRIDGE -1; i++)
    {
    size = strlen (Blist[i].name) ;

      ===========================================

          MAX_BRIDGE在spcav4l.h中定义,是一个枚举成员

          static struct bridge_list Blist[]={
    Blist[]数组在spcav4l.c前面定义:


       static struct bridge_list Blist[]={
    {BRIDGE_SPCA505,"SPCA505"},
    {BRIDGE_SPCA506,"SPCA506"},
    {BRIDGE_SPCA501,"SPCA501"},
    {BRIDGE_SPCA508,"SPCA508"},
    {BRIDGE_SPCA504,"SPCA504"},
    {BRIDGE_SPCA500,"SPCA500"},
    {BRIDGE_SPCA504B,"SPCA504B"},
    {BRIDGE_SPCA533,"SPCA533"},
    {BRIDGE_SPCA504C,"SPCA504C"},
    {BRIDGE_SPCA561,"SPCA561"},
    {BRIDGE_SPCA536,"SPCA536"},
    {BRIDGE_SONIX,"SN9C102"},
    {BRIDGE_ZR364XX,"ZR364XX"},
    {BRIDGE_ZC3XX,"ZC301-2"},
    {BRIDGE_CX11646,"CX11646"},
    {BRIDGE_TV8532,"TV8532"},
    {BRIDGE_ETOMS,"ET61XX51"},
    {BRIDGE_SN9CXXX,"SN9CXXX"},
    {BRIDGE_MR97311,"MR97311"},
    {BRIDGE_UNKNOW,"UNKNOW"},
    {-1,NULL}
};

    static struct bridge_list结构体


      ===========================================

    if(debug) printf ("is_spca %s size %d /n",Blist[i].name,size);
      if (strncmp (BridgeName, Blist[i].name, size) == 0)
    { 
    find = i;
      break;
    }
    }

  return find;
}

    函数原型:extern int strcmp(char *str1,char * str2,int n)

    参数说明:str1为第一个要比较的字符串,str2为第二个要比较的字符串,n为指定的str1与str2的比较的    字符数。   
    所在库名:#include <string.h>
    函数功能:比较字符串str1和str2的前n个字符。
    返回说明:返回整数值:当str1<str2时,返回值<0; 当str1=str2时,返回值=0; 当str1>str2时,返回值>0。

…………………………………………………………………………………………………

  switch (match)
    {
    case BRIDGE_SPCA505:
    case BRIDGE_SPCA506:
      i = YYUV;
      break;
    case BRIDGE_SPCA501:
      i = YUYV;
      break;
    case BRIDGE_SPCA508:
      i = YUVY;
      break;
    case BRIDGE_SPCA536:
    case BRIDGE_SPCA504:
    case BRIDGE_SPCA500:
    case BRIDGE_SPCA504B:
    case BRIDGE_SPCA533:
    case BRIDGE_SPCA504C:
    case BRIDGE_ZR364XX:
    case BRIDGE_ZC3XX:
    case BRIDGE_CX11646:
    case BRIDGE_SN9CXXX:
    case BRIDGE_MR97311: 
      i = JPEG;
      break;
    case BRIDGE_ETOMS:
    case BRIDGE_SONIX:
    case BRIDGE_SPCA561:
    case BRIDGE_TV8532:
      i = GBRG;
      break;
    default:
      i = UNOW; // -1;
      if(debug) printf ("Unable to find a StreamId !!/n");
      break;

    }
  return i;
}

       返回的是视频图像信号的格式。

       现在退出GetStreamId(),回到init_v4l (struct vdIn *vd)中:

      *********************************************************************************************/

   回到init_v4l (struct vdIn *vd)中, 请看 嵌入式网络视频采集源程序servfox解析04

你可能感兴趣的:(数据结构,网络,struct,video,嵌入式,audio)