友善之臂视频监控方案源码学习(5) - 输入控制
更新时间:2023-05-19 22:52: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分析
该函数完成了视频输入的命令控制。在后续文章中将进行详细分析。
正在阅读:
农夫与蛇10-08
四川省 2018 年下半年教师公招考试真题 09-13
社会保障学课程教学大纲06-05
数字媒体艺术专业建设与教学 心得体会11-14
开学第一课:语文的魅力 (1)08-26
2018年行政人事部工作计划1与2018年行政人力资源工作计划汇编11-28
农业局创建市级文明单位复查的自我检查报告(精选多篇)09-26
晶体硅太阳电池的暗电流类型分析05-25
- 教学能力大赛决赛获奖-教学实施报告-(完整图文版)
- 互联网+数据中心行业分析报告
- 2017上海杨浦区高三一模数学试题及答案
- 招商部差旅接待管理制度(4-25)
- 学生游玩安全注意事项
- 学生信息管理系统(文档模板供参考)
- 叉车门架有限元分析及系统设计
- 2014帮助残疾人志愿者服务情况记录
- 叶绿体中色素的提取和分离实验
- 中国食物成分表2020年最新权威完整改进版
- 推动国土资源领域生态文明建设
- 给水管道冲洗和消毒记录
- 计算机软件专业自我评价
- 高中数学必修1-5知识点归纳
- 2018-2022年中国第五代移动通信技术(5G)产业深度分析及发展前景研究报告发展趋势(目录)
- 生产车间巡查制度
- 2018版中国光热发电行业深度研究报告目录
- (通用)2019年中考数学总复习 第一章 第四节 数的开方与二次根式课件
- 2017_2018学年高中语文第二单元第4课说数课件粤教版
- 上市新药Lumateperone(卢美哌隆)合成检索总结报告
- 友善
- 视频监控
- 源码
- 输入
- 控制
- 方案
- 学习
- 在春节期间道路交通安全工作视频会上的讲话
- 煤矿开采方法试题(A卷)
- 2020年朝阳区将台医院医药护技人员考试试题及解析
- 稳态法测量不良导体导热系数
- The MinnesotA Rural Health
- 2014年漳州公务员面试政策之面试时考官会给读题吗
- 3镀锌加热炉节能改造方案
- 80后童年动漫搅动怀旧经济:老动画如伙伴忘不了
- 2015年湖南省数据概述纲要
- 中医执业医师考试辅导中药学11
- 上海牛津英语初中必背单词表
- 新编房屋出租合同完整版
- 乡镇卫生院优化服务流程
- 物质的量 第一课时巩固练习
- 五年级下册unit 6 work quietly B let&39;s talk
- 高效课堂的简易操作(李炳亭)
- 浅谈幼儿园里的德育
- 2012年度中国服务外包企业五十强
- 大学语文(第3版)_在线作业_3
- 我国社会体育指导员现状及对策分析