Mjpg_streamer.c的main函数分析

本文详细介绍了MJPEGStreamer的启动过程,包括参数解析、插件加载、日志配置及信号处理等内容。通过分析源代码,揭示了如何使用动态链接库实现输入输出插件,并展示了如何初始化这些插件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

int main(int argc, char *argv[])
{
	char *input  = "input_uvc.so --resolution 640x480 --fps 5 --device /dev/video0";	
	// 指向输入选项参数字符串
	char *output[MAX_OUTPUT_PLUGINS];	
	/* 指向输出选项参数字符串 */
	int daemon=0, i;						
	/* 是否让程序在后台运行的标志 */
	size_t tmp=0;

	output[0] = "output_http.so --port 8080";
	global.outcnt = 0;		/* 输出方式个数*/

	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}
		};

		/*  -i "input_uvc.so -f 10 -r 320*240" -o "output_http.so -w www"  */
		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);	// input = "input_uvc.so -f 10 -r 320*240"
				break;

			/* o, output */
			case 4:
			case 5:
				output[global.outcnt++] = strdup(optarg);//output[0] = "output_http.so -w www"
				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;
		}
	}

	openlog("MJPG-streamer ", LOG_PID|LOG_CONS, LOG_USER);
	syslog(LOG_INFO, "starting application");

	/* fork to the background */
	/* 如daemon = 1,则让程序后台运行 */
	if ( daemon )
	{
		LOG("enabling daemon mode");
		daemon_mode();
	}

	/* initialise the global variables */
	global.stop      = 0;
	global.buf       = NULL;
	global.size      = 0;
	global.in.plugin = NULL;

	/* this mutex and the conditional variable are used to synchronize access to the 
		global picture buffer */
	if( pthread_mutex_init(&global.db, NULL) != 0 )
	{
		LOG("could not initialize mutex variable\n");
		closelog();
		exit(EXIT_FAILURE);
	}
	if( pthread_cond_init(&global.db_update, NULL) != 0 )	/* 条件变量,用于线程间通讯 */
	{
		LOG("could not initialize condition variable\n");
		closelog();
		exit(EXIT_FAILURE);
	}

	/* ignore SIGPIPE (send by OS if transmitting to closed TCP sockets) */
	signal(SIGPIPE, SIG_IGN);

	/* register signal handler for <CTRL>+C in order to clean up */
	if (signal(SIGINT, signal_handler) == SIG_ERR)
	{
		LOG("could not register signal handler\n");
		closelog();
		exit(EXIT_FAILURE);
	}
   /*
	* messages like the following will only be visible on your terminal
	* if not running in daemon mode
	*/
	LOG("MJPG Streamer Version.: %s\n", SOURCE_VERSION);

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

	/* open input plugin */
	/* "input_uvc.so -f 10 -r 320*240" */
	tmp = (size_t)(strchr(input, ' ')-input); // 让tmp 等于 "input_uvc.so"字符串的长度
	global.in.plugin = (tmp > 0)?strndup(input, tmp):strdup(input);//plugin="input_uvc.so"
	global.in.handle = dlopen(global.in.plugin, RTLD_LAZY); // 打开"input_uvc.so"动态链接库
	if ( !global.in.handle )
	{
		LOG("ERROR: could not find input plugin\n");
		LOG("       Perhaps you want to adjust the search path with:\n");
		LOG("       # export LD_LIBRARY_PATH=/path/to/plugin/folder\n");
		LOG("       dlopen: %s\n", dlerror() );
		closelog();
		exit(EXIT_FAILURE);
	}
	global.in.init = dlsym(global.in.handle, "input_init");//让 global.in.init = input_init
	if ( global.in.init == NULL )
	{
		LOG("%s\n", dlerror());
		exit(EXIT_FAILURE);
	}
	global.in.stop = dlsym(global.in.handle, "input_stop");
	if ( global.in.stop == NULL )
	{
		LOG("%s\n", dlerror());
		exit(EXIT_FAILURE);
	}
	global.in.run = dlsym(global.in.handle, "input_run");
	if ( global.in.run == NULL )
	{
		LOG("%s\n", dlerror());
		exit(EXIT_FAILURE);
	}
	/* try to find optional command */
	global.in.cmd = dlsym(global.in.handle, "input_cmd");

	global.in.param.parameter_string = strchr(input, ' ');		
	// global.in.param.parameter_string = "-f 10 -r 320*240"
	global.in.param.global = &global;

	if ( global.in.init(&global.in.param) )
	{
		LOG("input_init() return value signals to exit");
		closelog();
		exit(0);
	}

	/* open output plugin */
	for (i=0; i<global.outcnt; i++)		// outcnt = 1
	{
		/* "output_http.so -w www" */
		tmp = (size_t)(strchr(output[i], ' ')-output[i]);
		global.out[i].plugin = (tmp > 0)?strndup(output[i], tmp):strdup(output[i]);
		global.out[i].handle = dlopen(global.out[i].plugin, RTLD_LAZY);
		if ( !global.out[i].handle )
		{
			LOG("ERROR: could not find output plugin %s\n", global.out[i].plugin);
			LOG("       Perhaps you want to adjust the search path with:\n");
			LOG("       # export LD_LIBRARY_PATH=/path/to/plugin/folder\n");
			LOG("       dlopen: %s\n", dlerror() );
			closelog();
			exit(EXIT_FAILURE);
		}
		global.out[i].init = dlsym(global.out[i].handle, "output_init");
		if ( global.out[i].init == NULL )
		{
			LOG("%s\n", dlerror());
			exit(EXIT_FAILURE);
		}
		global.out[i].stop = dlsym(global.out[i].handle, "output_stop");
		if ( global.out[i].stop == NULL )
		{
			LOG("%s\n", dlerror());
			exit(EXIT_FAILURE);
		}
		global.out[i].run = dlsym(global.out[i].handle, "output_run");
		if ( global.out[i].run == NULL )
		{
			LOG("%s\n", dlerror());
			exit(EXIT_FAILURE);
		}
		/* try to find optional command */
		global.out[i].cmd = dlsym(global.out[i].handle, "output_cmd");

		global.out[i].param.parameter_string = strchr(output[i], ' ');
		global.out[i].param.global = &global;
		global.out[i].param.id = i;
		if ( global.out[i].init(&global.out[i].param) )
		{
			LOG("output_init() return value signals to exit");
			closelog();
			exit(0);
		}
	}

	/* start to read the input, push pictures into global buffer */
	DBG("starting input plugin\n");
	syslog(LOG_INFO, "starting input plugin");
	global.in.run();

	DBG("starting %d output plugin(s)\n", global.outcnt);
	for(i=0; i<global.outcnt; i++)
	{
		syslog(LOG_INFO, "starting output plugin: %s (ID: %02d)", 
			global.out[i].plugin, global.out[i].param.id);
		global.out[i].run(global.out[i].param.id);
	}
	/* wait for signals */
	pause();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值