首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 其他教程 > 其他相关 >

友好之臂视频监控方案源码学习(5) - 输入控制

2013-01-04 
友善之臂视频监控方案源码学习(5) - 输入控制【问题描述】在/* structure to store variables/functions for

友善之臂视频监控方案源码学习(5) - 输入控制

【问题描述】在/* structure to store variables/functions for input plugin */typedef struct _input input;struct _input { char *plugin; void *handle; input_parameter param; int (*init)(input_parameter *); int (*stop)(void); int (*run)(void); int (*cmd)(in_cmd_type, int);};

char *input = "input_uvc.so --resolution 640x480 --fps 5 --device /dev/video0";

若-i参数不为空,则采用下述方法更新输入:

/* i, input */      case 2:      case 3:        input = strdup(optarg);        break;

传送给Input_uvc.c中input_init的参数为:

global.in.param.parameter_string = strchr(input, ' ');

下面分析int input_init(input_parameter *param);

首先,定义了一系列默认的参数:

char *argv[MAX_ARGUMENTS]={NULL}, *dev = "/dev/video0", *s;int argc=1, width=640, height=480, fps=5, format=V4L2_PIX_FMT_MJPEG, i;in_cmd_type led = IN_CMD_LED_AUTO;char fourcc[5]={0,0,0,0,0};

第二,初始化互斥锁:

 /* initialize the mutes variable */  if( pthread_mutex_init(&controls_mutex, NULL) != 0 ) {    IPRINT("could not initialize mutex variable\n");    exit(EXIT_FAILURE);  }

第三,参数解析。参数解析又分为下面几个步骤:

(a) 读取参数

argv[0] = INPUT_PLUGIN_NAME;  if ( param->parameter_string != NULL && strlen(param->parameter_string) != 0 ) {    char *arg=NULL, *saveptr=NULL, *token=NULL;    arg=(char *)strdup(param->parameter_string);

(b) 将字符串形式的参数分解为字符串数组

if ( strchr(arg, ' ') != NULL ) {      token=strtok_r(arg, " ", &saveptr);      if ( token != NULL ) {        argv[argc] = strdup(token);        argc++;        while ( (token=strtok_r(NULL, " ", &saveptr)) != NULL ) {          argv[argc] = strdup(token);          argc++;          if (argc >= MAX_ARGUMENTS) {            IPRINT("ERROR: too many arguments to input plugin\n");            return 1;          }        }      }    }  }

(c) 利用getopt函数解析参数

reset_getopt();  while(1) {    int option_index = 0, c=0;    static struct option long_options[] = \    {      {"h", no_argument, 0, 0},      {"help", no_argument, 0, 0},      {"d", required_argument, 0, 0},      {"device", required_argument, 0, 0},      {"r", required_argument, 0, 0},      {"resolution", required_argument, 0, 0},      {"f", required_argument, 0, 0},      {"fps", required_argument, 0, 0},      {"y", no_argument, 0, 0},      {"yuv", no_argument, 0, 0},      {"q", required_argument, 0, 0},      {"quality", required_argument, 0, 0},      {"m", required_argument, 0, 0},      {"minimum_size", required_argument, 0, 0},      {"n", no_argument, 0, 0},      {"no_dynctrl", no_argument, 0, 0},      {"l", required_argument, 0, 0},      {"led", required_argument, 0, 0},      {0, 0, 0, 0}    };    /* parsing all parameters according to the list above is sufficent */    c = getopt_long_only(argc, argv, "", long_options, &option_index);

该过程详细请参考/* no more options to parse */ if (c == -1) break; /* unrecognized option */ if (c == '?'){ help(); return 1; } /* dispatch the given options */ switch (option_index) { /* h, help */ case 0: case 1: DBG("case 0,1\n"); help(); return 1; break; /* d, device */ case 2: case 3: DBG("case 2,3\n"); dev = strdup(optarg); break; /* r, resolution */ case 4: case 5: DBG("case 4,5\n"); width = -1; height = -1; /* try to find the resolution in lookup table "resolutions" */ for ( i=0; i < LENGTH_OF(resolutions); i++ ) { if ( strcmp(resolutions[i].string, optarg) == 0 ) { width = resolutions[i].width; height = resolutions[i].height; } } /* done if width and height were set */ if(width != -1 && height != -1) break; /* parse value as decimal value */ width = strtol(optarg, &s, 10); height = strtol(s+1, NULL, 10); break; /* f, fps */ case 6: case 7: DBG("case 6,7\n"); fps=atoi(optarg); break; /* y, yuv */ case 8: case 9: DBG("case 8,9\n"); format = V4L2_PIX_FMT_YUYV; break; /* q, quality */ case 10: case 11: DBG("case 10,11\n"); format = V4L2_PIX_FMT_YUYV; gquality = MIN(MAX(atoi(optarg), 0), 100); break; /* m, minimum_size */ case 12: case 13: DBG("case 12,13\n"); minimum_size = MAX(atoi(optarg), 0); break; /* n, no_dynctrl */ case 14: case 15: DBG("case 14,15\n"); dynctrls = 0; break; /* l, led */ case 16: case 17: DBG("case 16,17\n"); if ( strcmp("on", optarg) == 0 ) { led = IN_CMD_LED_ON; } else if ( strcmp("off", optarg) == 0 ) { led = IN_CMD_LED_OFF; } else if ( strcmp("auto", optarg) == 0 ) { led = IN_CMD_LED_AUTO; } else if ( strcmp("blink", optarg) == 0 ) { led = IN_CMD_LED_BLINK; } break; default: DBG("default case\n"); help(); return 1; }

注:步骤(c)和(d)是在while(1)循环内检测的。

第四,使全局指针指向param->param->global

/* keep a pointer to the global variables */  pglobal = param->global;

这一步非常重要,视频数据信息就存储在global结构的buf变量中。

第五,构建videoIn结构

videoIn = malloc(sizeof(struct vdIn));  if ( videoIn == NULL ) {    IPRINT("not enough memory for videoIn\n");    exit(EXIT_FAILURE);  }  memset(videoIn, 0, sizeof(struct vdIn));

该结构描述如下:

struct vdIn {int fd;char *videodevice ;unsigned char *pFramebuffer;unsigned char *ptframe[OUTFRMNUMB];  unsigned char *mem[NB_BUFFER];int framelock[OUTFRMNUMB];pthread_mutex_t grabmutex;int          framesizeIn ;volatile int frame_cour;int  bppIn;int  hdrwidth;int  hdrheight;int  formatIn;int  signalquit;struct v4l2_capability cap;struct v4l2_format fmt;struct v4l2_buffer buf;struct v4l2_requestbuffers rb;  int  grayscale;uint32_t quality;};

主要定义了视频输入控制变量。

第六,打开视频设备

/* open video device and prepare data structure */  if (init_videoIn(videoIn, dev, width, height, fps, format, 1) < 0) {    IPRINT("init_VideoIn failed\n");    closelog();    exit(EXIT_FAILURE);  }

init_videoIn具体实现如下:

int init_videoIn(struct vdIn *vd, char *device, int width, int height, int fps, int format, int grabmethod){  if (vd == NULL || device == NULL)    return -1;  if (width == 0 || height == 0)    return -1;  if (grabmethod < 0 || grabmethod > 1)    grabmethod = 1;//mmap by default;  vd->videodevice = NULL;  vd->status = NULL;  vd->pictName = NULL;  vd->videodevice = (char *) calloc (1, 16 * sizeof (char));  vd->status = (char *) calloc (1, 100 * sizeof (char));  vd->pictName = (char *) calloc (1, 80 * sizeof (char));  snprintf (vd->videodevice, 12, "%s", device);  vd->toggleAvi = 0;  vd->getPict = 0;  vd->signalquit = 1;  vd->width = width;  vd->height = height;  vd->fps = fps;  vd->formatIn = format;  vd->grabmethod = grabmethod;  if (init_v4l2 (vd) < 0) {    fprintf (stderr, " Init v4L2 failed !! exit fatal \n");    goto error;;  }  /* alloc a temp buffer to reconstruct the pict */  vd->framesizeIn = (vd->width * vd->height << 1);  switch (vd->formatIn) {  case V4L2_PIX_FMT_MJPEG:    vd->tmpbuffer = (unsigned char *) calloc(1, (size_t) vd->framesizeIn);    if (!vd->tmpbuffer)      goto error;    vd->framebuffer =        (unsigned char *) calloc(1, (size_t) vd->width * (vd->height + 8) * 2);    break;  case V4L2_PIX_FMT_YUYV:  default:    vd->framebuffer =        (unsigned char *) calloc(1, (size_t) vd->framesizeIn);    break;    //fprintf(stderr, " should never arrive exit fatal !!\n");    //goto error;    //break;  }  if (!vd->framebuffer)    goto error;  return 0;error:  free(vd->videodevice);  free(vd->status);  free(vd->pictName);  close(vd->fd);  return -1;}

主要是完成了vdIn结构的初始化操作。

第七,动态控制初始化

if (dynctrls)    initDynCtrls(videoIn->fd);

第八,LED初始化

in_cmd_type led = IN_CMD_LED_AUTO;.../*   * switch the LED according to the command line parameters (if any)   */  input_cmd(led, 0); 

其执行的命令定义在input_cmd函数中:

case IN_CMD_LED_AUTO:      res = v4l2SetControl(videoIn, V4L2_CID_LED1_MODE_LOGITECH, 3);    break;

 

4 input_run分析

input_run看上去十分简单:

int input_run(void) {  pglobal->buf = malloc(videoIn->framesizeIn);  if (pglobal->buf == NULL) {    fprintf(stderr, "could not allocate memory\n");    exit(EXIT_FAILURE);  }  pthread_create(&cam, 0, cam_thread, NULL);  pthread_detach(cam);  return 0;}

input_run只做了两件事:

(1) 分配视频数据存储空间

(2) 开辟视频采集线程。后续文章详细分析。

 

5 input_stop分析

input_stop主要功能是关闭视频采集线程

int input_stop(void) {  DBG("will cancel input thread\n");  pthread_cancel(cam);  return 0;}

 

6 input_cmd分析

该函数完成了视频输入的命令控制。在后续文章中将进行详细分析。

 


 【源码下载】

http://download.csdn.net/detail/tandesir/4915905

 

 

转载请标明出处,仅供学习交流,勿用于商业目的

Copyright @ http://blog.csdn.net/tandesir



 

热点排行