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

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

【解析】

(1) 日志代码

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

int syslog(int priority, string message); 

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

closelog()接口定义如下:

void closelog( void ) ;

 

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

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

该封装使用了可变参数。

示例1

LOG("setting signal to stop\n");

经展开得:

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

示例2

#define SOURCE_VERSION "2.0"
LOG("MJPG Streamer Version.: %s\n", SOURCE_VERSION);

经展开得:

{ 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) 调试技巧

调试代码进行了封装:

#ifdef DEBUG
#define DBG(...) fprintf(stderr, " DBG(%s, %s(), %d): ", __FILE__, __FUNCTION__, __LINE__); fprintf(stderr, __VA_ARGS__)
#else
#define DBG(...)
#endif


示例

DBG("all plugin handles closed\n");

经展开得:

fprintf(stderr, " DBG(%s, %s(), %d): ", "test.c", __FUNCTION__, 9);;

 

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

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

/* parameter parsing */
  while(1) {
    int option_index = 0, c=0;
    static struct option long_options[] = \
    {
      {"h", no_argument, 0, 0},
      {"help", no_argument, 0, 0},
      {"i", required_argument, 0, 0},
      {"input", required_argument, 0, 0},
      {"o", required_argument, 0, 0},
      {"output", required_argument, 0, 0},
      {"v", no_argument, 0, 0},
      {"version", no_argument, 0, 0},
      {"b", no_argument, 0, 0},
      {"background", no_argument, 0, 0},
      {0, 0, 0, 0}
    };

    c = getopt_long_only(argc, argv, "", long_options, &option_index);

    /* no more options to parse */
    if (c == -1) break;

    /* unrecognized option */
    if(c=='?'){ help(argv[0]); return 0; }

    switch (option_index) {
      /* h, help */
      case 0:
      case 1:
        help(argv[0]);
        return 0;
        break;

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

      /* o, output */
      case 4:
      case 5:
        output[global.outcnt++] = strdup(optarg);
        break;

      /* v, version */
      case 6:
      case 7:
        printf("MJPG Streamer Version: %s\n" \
               "Compilation Date.....: %s\n" \
               "Compilation Time.....: %s\n", SOURCE_VERSION, __DATE__, __TIME__);
        return 0;
        break;

      /* b, background */
      case 8:
      case 9:
        daemon=1;
        break;

      default:
        help(argv[0]);
        return 0;
    }
  }

(a) struct option的原型

struct option
{
#if defined (__STDC__) && __STDC__
  const char *name;
#else
  char *name;
#endif
  /* has_arg can't be an enum because some compilers complain about
     type mismatches in all the code that assumes it is an int.  */
  int has_arg;
  int *flag;
  int val;
};

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原型

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脚本执行类似语句:

./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) 默认插件

默认的输入插件为

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

默认的输出插件为

output[0] = "output_http.so --port 8080";

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

/* check if at least one output plugin was selected */
  if ( global.outcnt == 0 ) {
    /* no? Then use the default plugin instead */
    global.outcnt = 1;
  }


 


 【源码下载】

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

 

 

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

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




 

 

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值