友善之臂视频监控方案源码学习(5) - 输入控制
更新时间:2023-08-12 04:12:01 阅读量: 外语学习 文档下载
- 友善之臂视频监控推荐度:
- 相关推荐
友善之臂视频监控方案源码学习(5) - 输入控制
【问题描述】在友善之臂视频监控方案源码学习(4) - 数据流向一文中,对视频数据流向进行了简要阐述。本文对输入控制进行解析。
【解析】
1 涉及到的文件和目录
mjpg-streamer-mini2440-read-only/start_uvc.sh
mjpg-streamer-mini2440-read-only/mjpg_streamer.c
mjpg-streamer-mini2440-read-only/mjpg_streamer.h
mjpg-streamer-mini2440-read-only/plugins/input.h
mjpg-streamer-mini2440-read-only/plugins/input_uvc
2 输入结构
mjpg-streamer-mini2440-read-only/plugins目录下input.h中对input结构描述如下:
[html] view plaincopy 1. /* structure to store variables/functions for input plugin */
2. typedef struct _input input;
3. struct _input {
4. char *plugin;
5. void *handle;
6. input_parameter param;
7.
8. int (*init)(input_parameter *);
9. int (*stop)(void);
10. int (*run)(void);
11. int (*cmd)(in_cmd_type, int);
12. };
友善之臂视频监控方案源码学习(1) - 架构分析一文,指出了该方案实质上就是实现了输入、输出的接口。从输入看,就是实现了init、stop、run、cmd函数指针。主程序中实际上,只调用了init、run接口。stop接口是在信号的回调函数void signal_handler(int sig);中调用的。 3 input_init分析
(1) 定义在mjpg-streamer-mini2440-read-only/plugins/input_uvc/Input_uvc.c文件中
(2) 在mjpg-streamer-mini2440-read-only/mjpg_streamer.c 的main函数中,默认的输入为:
[html] view plaincopy
1. char *input = "input_uvc.so --resolution 640x480 --fps 5 --device /dev/vide
o0";
若-i参数不为空,则采用下述方法更新输入:
[html] view plaincopy
1.
2. 3.
4.
5. /* i, input */ case 2: case 3: input = strdup(optarg); break;
传送给Input_uvc.c中input_init的参数为:
[html] view plaincopy
1. global.in.param.parameter_string = strchr(input, ' ');
下面分析mjpg-streamer-mini2440-read-only/plugins/input_uvc/input_uvc.c中的input_init接口。接口定义如下:
[html] view plaincopy
1. int input_init(input_parameter *param);
首先,定义了一系列默认的参数:
[html] view plaincopy
2.
3.
4. 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};
第二,初始化互斥锁:
[html] view plaincopy
1.
2.
3.
4.
5. /* initialize the mutes variable */ if( pthread_mutex_init(&controls_mutex, NULL) != 0 ) { IPRINT("could not initialize mutex variable\n"); exit(EXIT_FAILURE); }
第三,参数解析。参数解析又分为下面几个步骤:
(a) 读取参数
[html] view plaincopy 1. 2.
3.
4.
5. 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) 将字符串形式的参数分解为字符串数组
[html] view plaincopy 1. if ( strchr(arg, ' ') != NULL ) {
2. token=strtok_r(arg, " ", &saveptr);
3. if ( token != NULL ) {
4. argv[argc] = strdup(token);
5. argc++;
6. while ( (token=strtok_r(NULL, " ", &saveptr)) != NULL ) { 7. argv[argc] = strdup(token);
8. argc++;
9. if (argc >= MAX_ARGUMENTS) {
10. IPRINT("ERROR: too many arguments to input plugin\n"); 11. return 1;
12. }
14. } 15. }
16. }
(c) 利用getopt函数解析参数
[html] view plaincopy 1. reset_getopt();
2. while(1) {
3. int option_index = 0, c=0;
4. static struct option long_options[] = \
5. {
6. {"h", no_argument, 0, 0},
7. {"help", no_argument, 0, 0},
8. {"d", required_argument, 0, 0},
9. {"device", required_argument, 0, 0},
10. {"r", required_argument, 0, 0},
11. {"resolution", required_argument, 0, 0},
12. {"f", required_argument, 0, 0},
13. {"fps", required_argument, 0, 0},
14. {"y", no_argument, 0, 0},
15. {"yuv", no_argument, 0, 0},
16. {"q", required_argument, 0, 0},
17. {"quality", required_argument, 0, 0},
18. {"m", required_argument, 0, 0},
19. {"minimum_size", required_argument, 0, 0},
20. {"n", no_argument, 0, 0},
21. {"no_dynctrl", no_argument, 0, 0},
22. {"l", required_argument, 0, 0},
23. {"led", required_argument, 0, 0},
24. {0, 0, 0, 0}
25. };
26.
27. /* parsing all parameters according to the list above is sufficent */ 28. c = getopt_long_only(argc, argv, "", long_options, &option_index); 该过程详细请参考友善之臂视频监控方案源码学习(2) - 主程序实现细节一文描述。 (d) 根据输入的参数执行相应的操作:
[html] view plaincopy
1. /* no more options to parse */
2. if (c == -1) break;
3.
4. /* unrecognized option */
5. if (c == '?'){
6. help();
7. return 1;
8. }
9.
10. /* dispatch the given options */
11. switch (option_index) {
12. /* h, help */
13. case 0:
14. case 1:
15. DBG("case 0,1\n");
16. help();
17. return 1;
18. break;
19.
20. /* d, device */
21. case 2:
22. case 3:
23. DBG("case 2,3\n");
24. dev = strdup(optarg);
25. break;
26.
27. /* r, resolution */
28. case 4:
29. case 5:
30. DBG("case 4,5\n");
31. width = -1;
32. height = -1;
33.
34. /* try to find the resolution in lookup table "resolutions" */ 35. for ( i=0; i < LENGTH_OF(resolutions); i++ ) {
36. if ( strcmp(resolutions[i].string, optarg) == 0 ) { 37. width = resolutions[i].width;
38. height = resolutions[i].height;
39. }
40. }
41. /* done if width and height were set */
42. if(width != -1 && height != -1)
43. break;
44. /* parse value as decimal value */
46. height = strtol(s+1, NULL, 10);
47. break;
48.
49. /* f, fps */
50. case 6:
51. case 7:
52. DBG("case 6,7\n");
53. fps=atoi(optarg);
54. break;
55.
56. /* y, yuv */
57. case 8:
58. case 9:
59. DBG("case 8,9\n");
60. format = V4L2_PIX_FMT_YUYV;
61. break;
62.
63. /* q, quality */
64. case 10:
65. case 11:
66. DBG("case 10,11\n");
67. format = V4L2_PIX_FMT_YUYV;
68. gquality = MIN(MAX(atoi(optarg), 0), 100);
69. break;
70.
71. /* m, minimum_size */
72. case 12:
73. case 13:
74. DBG("case 12,13\n");
75. minimum_size = MAX(atoi(optarg), 0);
76. break;
77.
78. /* n, no_dynctrl */
79. case 14:
80. case 15:
81. DBG("case 14,15\n");
82. dynctrls = 0;
83. break;
84.
85. /* l, led */
86. case 16:
87. case 17:
88. DBG("case 16,17\n");
90. led = IN_CMD_LED_ON;
91. } else if ( strcmp("off", optarg) == 0 ) {
92. led = IN_CMD_LED_OFF;
93. } else if ( strcmp("auto", optarg) == 0 ) {
94. led = IN_CMD_LED_AUTO;
95. } else if ( strcmp("blink", optarg) == 0 ) {
96. led = IN_CMD_LED_BLINK;
97. }
98. break;
99.
100. default:
101. DBG("default case\n");
102. help();
103. return 1;
104. }
注:步骤(c)和(d)是在while(1)循环内检测的。
第四,使全局指针指向param->param->global
[html] view plaincopy
1.
2. /* keep a pointer to the global variables */ pglobal = param->global;
这一步非常重要,视频数据信息就存储在global结构的buf变量中。
第五,构建videoIn结构
[html] view plaincopy
1.
2.
3.
4.
5.
6. videoIn = malloc(sizeof(struct vdIn)); if ( videoIn == NULL ) { IPRINT("not enough memory for videoIn\n"); exit(EXIT_FAILURE); } memset(videoIn, 0, sizeof(struct vdIn));
该结构描述如下:
[html] view plaincopy
1. struct vdIn {
2. int fd;
3. char *videodevice ;
4. unsigned char *pFramebuffer;
5. unsigned char *ptframe[OUTFRMNUMB];
6. unsigned char *mem[NB_BUFFER];
7.
8. int framelock[OUTFRMNUMB];
9. pthread_mutex_t grabmutex;
10. int framesizeIn ; 11. volatile int frame_cour;
12. int bppIn;
13. int hdrwidth; 14. int hdrheight;
15. int formatIn;
16. int signalquit;
17. struct v4l2_capability cap;
18. struct v4l2_format fmt;
19. struct v4l2_buffer buf;
20. struct v4l2_requestbuffers rb;
21.
22. int grayscale;
23. uint32_t quality;
24.
25. };
主要定义了视频输入控制变量。
第六,打开视频设备
[html] view plaincopy
1.
2.
3.
4.
5.
6. /* 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具体实现如下:
[html] view plaincopy
1. int init_videoIn(struct vdIn *vd, char *device, int width, int height, int fps, int format, int grabmethod)
2. {
3. if (vd == NULL || device == NULL)
4. return -1;
5. if (width == 0 || height == 0)
6. return -1;
7. if (grabmethod < 0 || grabmethod > 1)
8. grabmethod = 1; //mmap by default;
9. vd->videodevice = NULL;
10. vd->status = NULL;
11. vd->pictName = NULL;
12. vd->videodevice = (char *) calloc (1, 16 * sizeof (char)); 13. vd->status = (char *) calloc (1, 100 * sizeof (char));
14. vd->pictName = (char *) calloc (1, 80 * sizeof (char));
15. snprintf (vd->videodevice, 12, "%s", device);
16. vd->toggleAvi = 0;
17. vd->getPict = 0;
18. vd->signalquit = 1;
19. vd->width = width;
20. vd->height = height;
21. vd->fps = fps;
22. vd->formatIn = format;
23. vd->grabmethod = grabmethod;
24. if (init_v4l2 (vd) < 0) {
25. fprintf (stderr, " Init v4L2 failed !! exit fatal \n"); 26. goto error;;
27. }
28. /* alloc a temp buffer to reconstruct the pict */
29. vd->framesizeIn = (vd->width * vd->height << 1);
30. switch (vd->formatIn) {
31. case V4L2_PIX_FMT_MJPEG:
32. vd->tmpbuffer = (unsigned char *) calloc(1, (size_t) vd->framesizeIn); 33. if (!vd->tmpbuffer)
34. goto error;
35. vd->framebuffer =
36. (unsigned char *) calloc(1, (size_t) vd->width * (vd->height + 8) *
2);
37. break;
38. case V4L2_PIX_FMT_YUYV:
39. default:
40. vd->framebuffer =
41. (unsigned char *) calloc(1, (size_t) vd->framesizeIn); 42. break;
43. //fprintf(stderr, " should never arrive exit fatal !!\n"); 44. //goto error;
45. //break;
46. }
47. if (!vd->framebuffer)
48. goto error;
49. return 0;
50. error:
51. free(vd->videodevice);
52. free(vd->status);
53. free(vd->pictName);
54. close(vd->fd);
55. return -1;
56. }
主要是完成了vdIn结构的初始化操作。
第七,动态控制初始化
[html] view plaincopy
1.
2. if (dynctrls) initDynCtrls(videoIn->fd);
第八,LED初始化
[html] view plaincopy
1.
2.
3.
4.
5.
6.
7. 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函数中:
[html] view plaincopy
1.
2.
3.
case IN_CMD_LED_AUTO: res = v4l2SetControl(videoIn, V4L2_CID_LED1_MODE_LOGITECH, 3); break;
4 input_run分析
input_run看上去十分简单: [html] view plaincopy 1. int input_run(void) {
2. pglobal->buf = malloc(videoIn->framesizeIn); 3. if (pglobal->buf == NULL) {
4. fprintf(stderr, "could not allocate memory\n"); 5. exit(EXIT_FAILURE);
6. }
7.
8. pthread_create(&cam, 0, cam_thread, NULL);
9. pthread_detach(cam);
10.
11. return 0;
12. }
input_run只做了两件事:
(1) 分配视频数据存储空间
(2) 开辟视频采集线程。后续文章详细分析。
5 input_stop分析
input_stop主要功能是关闭视频采集线程
[html] view plaincopy
1.
2.
3.
4.
5.
6.
int input_stop(void) { DBG("will cancel input thread\n"); pthread_cancel(cam); return 0; }
6 input_cmd分析
该函数完成了视频输入的命令控制。在后续文章中将进行详细分析。
正在阅读:
国企薪酬改革中的薪酬套改操作方法05-26
四年级语文三分之一测试卷05-05
假如我去橙子冷饮中过暑假作文600字06-15
国际贸易条款名称07-18
医药代理合同02-25
国际货物运输与交接05-22
通贤镇中心小学幼儿园教师奖励性绩效考核量化评分方案03-08
我忙但很快乐作文500字06-16
北京—— 华为项目管理工具与模板运03-20
- 奶牛焦虫病的诊断与防治 - 医学期刊频道--首席医学网
- 外包工程发包流程
- 管理信息系统(路晓丽版)课后题答案(1-12章全)
- 小学语文课题研究方案
- 企业内部培训师管理制度
- 《史记》拓展阅读设计
- 入口广场铺装施工方案
- 附录B塔式起重机安装验收记录表
- 云南省昆明三中2014-2015学年高二下学期期中考试物理试卷 (Word版含答案)
- 郑州大学毕业设计附件
- 民俗学视野下的中国百年歌谣研究
- 巩固练2020统编版(2019)高二选择性必修上册第一单元阶段复习 第一单元仿真模拟训练
- 量化研究学习书单
- 给尾注编号加方括号超级简单方法
- 第1课《放大镜》
- 定价的步骤及新产品定价策略(1)
- 八年级英语下册第六单元基础知识
- 全省地方志工作会议综述
- An Investigation of Tightly Coupled Time Synchronous Speech Language Interfaces Using a Uni
- 新目标英语八年级(上)单元测试题(Units6-7)
- 友善
- 视频监控
- 源码
- 输入
- 控制
- 方案
- 学习
- 招生办工作制度
- 纺织品测试知识简介
- 纯露芳香疗法
- Boost变换器仿真分析
- 学校安全教育知识资料
- 企业财务管理存在问题对策论文
- 且末县远程教育“小站点”发挥“大作用”
- 纸板线关键参数记录表
- Joint generalization of city points and road network for small-scale mapping
- 平面几何小册子
- 在培训中要对培训效果进行跟踪与反馈,对培训机构和培训人员的评估不包括(
- 2010年度中国建筑业企业竞争力百强名单
- 基于ARIMA模型对我国能源需求的预测
- 贵阳市新建改建居住区配建学校移交标准.doc
- 数学圆锥曲线历年高考题
- 煤矿开采方法试题(A卷)
- 3镀锌加热炉节能改造方案
- 五星级酒店VI设计清单
- 类二阶常微分方程组特解形式的探讨z
- 账户变更通知函