友善之臂视频监控方案源码学习(2) - 主程序实现细节

来源:互联网 发布:linux查找jdk安装路径 编辑:程序博客网 时间:2024/06/04 19:18

转载于http://blog.csdn.net/tandesir/article/details/8373205

【问题描述】在 友善之臂视频监控方案源码学习(1) - 架构分析一文中,对程序执行的步骤简单的进行了描述,本文对该过程的一些细节进行总结。

【解析】

(1) 日志代码

日志记录可调用syslog.h提供的syslog,closelog函数。syslog()接口定义如下:

[html] view plaincopy
  1. int syslog(int priority, string message);   

该函数指定了优先级和日志信息。

closelog()接口定义如下:

[html] view plaincopy
  1. void closelog( void ) ;  

 

该方案对日志进行了封装:

[html] view plaincopy
  1. #define LOG(...) { char _bf[1024] = {0}; snprintf(_bf, sizeof(_bf)-1, __VA_ARGS__); fprintf(stderr, "%s", _bf); syslog(LOG_INFO, "%s", _bf); }  

该封装使用了可变参数。

示例1

[html] view plaincopy
  1. LOG("setting signal to stop\n");  

经展开得:

[html] view plaincopy
  1. { char _bf[1024] = {0}; snprintf(_bf, sizeof(_bf)-1, "setting signal to stop\n"); fprintf(stderr, "%s", _bf); syslog(6, "%s", _bf); };  

示例2

[html] view plaincopy
  1. #define SOURCE_VERSION "2.0"  
  2. LOG("MJPG Streamer Version.: %s\n", SOURCE_VERSION);  

经展开得:

[html] view plaincopy
  1. { char _bf[1024] = {0}; snprintf(_bf, sizeof(_bf)-1, "MJPG Streamer Version.: %s\n", "2.0"); fprintf(stderr, "%s", _bf); syslog(6, "%s", _bf); };  


(2) 调试技巧

调试代码进行了封装:

[html] view plaincopy
  1. #ifdef DEBUG  
  2. #define DBG(...) fprintf(stderr, " DBG(%s, %s(), %d): ", __FILE__, __FUNCTION__, __LINE__); fprintf(stderr, __VA_ARGS__)  
  3. #else  
  4. #define DBG(...)  
  5. #endif  


示例

[html] view plaincopy
  1. DBG("all plugin handles closed\n");  

经展开得:

[html] view plaincopy
  1. fprintf(stderr, " DBG(%s, %s(), %d): ", "test.c", __FUNCTION__, 9);;  

 

(3) 参数解析的具体实现

参数解析实现代码如下所示:

[html] view plaincopy
  1. /* parameter parsing */  
  2.   while(1) {  
  3.     int option_index = 0c=0;  
  4.     static struct option long_options[] = \  
  5.     {  
  6.       {"h", no_argument, 0, 0},  
  7.       {"help", no_argument, 0, 0},  
  8.       {"i", required_argument, 0, 0},  
  9.       {"input", required_argument, 0, 0},  
  10.       {"o", required_argument, 0, 0},  
  11.       {"output", required_argument, 0, 0},  
  12.       {"v", no_argument, 0, 0},  
  13.       {"version", no_argument, 0, 0},  
  14.       {"b", no_argument, 0, 0},  
  15.       {"background", no_argument, 0, 0},  
  16.       {0, 0, 0, 0}  
  17.     };  
  18.   
  19.     c = getopt_long_only(argc, argv, "", long_options, &option_index);  
  20.   
  21.     /* no more options to parse */  
  22.     if (c == -1) break;  
  23.   
  24.     /* unrecognized option */  
  25.     if(c=='?'){ help(argv[0]); return 0; }  
  26.   
  27.     switch (option_index) {  
  28.       /* h, help */  
  29.       case 0:  
  30.       case 1:  
  31.         help(argv[0]);  
  32.         return 0;  
  33.         break;  
  34.   
  35.       /* i, input */  
  36.       case 2:  
  37.       case 3:  
  38.         input = strdup(optarg);  
  39.         break;  
  40.   
  41.       /* o, output */  
  42.       case 4:  
  43.       case 5:  
  44.         output[global.outcnt++] = strdup(optarg);  
  45.         break;  
  46.   
  47.       /* v, version */  
  48.       case 6:  
  49.       case 7:  
  50.         printf("MJPG Streamer Version: %s\n" \  
  51.                "Compilation Date.....: %s\n" \  
  52.                "Compilation Time.....: %s\n", SOURCE_VERSION, __DATE__, __TIME__);  
  53.         return 0;  
  54.         break;  
  55.   
  56.       /* b, background */  
  57.       case 8:  
  58.       case 9:  
  59.         daemon=1;  
  60.         break;  
  61.   
  62.       default:  
  63.         help(argv[0]);  
  64.         return 0;  
  65.     }  
  66.   }  

(a) struct option的原型

[html] view plaincopy
  1. struct option  
  2. {  
  3. #if defined (__STDC__) && __STDC__  
  4.   const char *name;  
  5. #else  
  6.   char *name;  
  7. #endif  
  8.   /* has_arg can't be an enum because some compilers complain about  
  9.      type mismatches in all the code that assumes it is an int.  */  
  10.   int has_arg;  
  11.   int *flag;  
  12.   int val;  
  13. };  

name:不带短横线的选项名,前面没有短横线。譬如“help”、“verbose”之类。

ihas_arg: 描述了选项是否有选项参数。如果有,是哪种类型的参数。此时,它的值一定是下表中的一个。符号常量数值含义

no_argument  0 选项没有参数

required_argument  1 选项需要参数

optional_argument  2 选项参数可选

flag:指明长选项如何返回,如果flag为NULL,则getopt_long返回val。否则返回0,flag指向一个值为val的变量。如果该长选项没有发现,flag保持不变;

val:指明返回的值,或者需要加载到被flag所指示的变量中。


(b) getopt_long_only原型

[html] view plaincopy
  1. int getopt_long_only(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex);  

具体实现:http://download.csdn.net/detail/tandesir/4917037

若解析成功,则返回0。错误情况(包括选项含糊不明确或者无关参数),返回'?。若解析终止,则返回-1。

 

(c) 过程分析

start_uvc_yuv.sh之类的shell脚本执行类似语句:

[html] view plaincopy
  1. ./mjpg_streamer -o "output_http.so -w ./www" -i "input_uvc.so -y -d /dev/video2"  

main函数执行后,首先利用getopt_long_only查看传入的参数是否在定义的long_options列表中。若存在于列表中,则解析对应的索引值option_index,然后根据索引值判断执行何种命令。

 

(4) 默认插件

默认的输入插件为

[html] view plaincopy
  1. char *input  = "input_uvc.so --resolution 640x480 --fps 5 --device /dev/video0";  

默认的输出插件为

[html] view plaincopy
  1. output[0] = "output_http.so --port 8080";  

输出插件结构中包含一个插件计数器,如果在main的参数列表中没有新的插件,则采用默认插件

[html] view plaincopy
  1. /* check if at least one output plugin was selected */  
  2.   if ( global.outcnt == 0 ) {  
  3.     /* no? Then use the default plugin instead */  
  4.     global.outcnt = 1;  
  5.   }  


 


 【源码下载】

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

 

 

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

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