【原创】动态图像监测开源代码 motion 学习 ----- Motion源码分析(1)
来源:互联网 发布:android入门编程视频 编辑:程序博客网 时间:2024/05/17 16:53
【原创】动态图像监测开源代码 motion 学习 ----- Motion源码分析(1)
经过这两天对motion源码的分析,发现关于motion代码分析的资料很少,现在终于看出来点儿意思了。因为motion源码文件不是太多,所以直接从main函数入手。
分析工具:Source Insight。
main函数位于源码文件motion.c中。下面是main函数的源代码。
/** * main * * Main entry point of Motion. Launches all the motion threads and contains * the logic for starting up, restarting and cleaning up everything. * * Parameters: * * argc - size of argv * argv - command-line options * * Returns: Motion exit status = 0 always */int main (int argc, char **argv){ int i; /* pthread_attr_t为线程属性结构体。 */ pthread_attr_t thread_attr; /* pthread_t为线程id类型,打印时要用%u。 */ pthread_t thread_id; /* Setup signals and do some initialization. 1 in the call to * 'motion_startup' means that Motion will become a daemon if so has been * requested, and argc and argc are necessary for reading the command * line options. 设置信号并做一些初始化。motion_startup中的1表示Motion将以守护进程的方式 运行,前提是用户有这样的需要。另外,命令行选项需要argc。 */ /* sigaction为结构体,详细规定了信号处理函数和信号标志等信息。 sigaction()为信号处理函数。 */ struct sigaction sig_handler_action; struct sigaction sigchild_action; setup_signals(&sig_handler_action, &sigchild_action); motion_startup(1, argc, argv);#ifdef HAVE_FFMPEG /* FFMpeg initialization is only performed if FFMpeg support was found * and not disabled during the configure phase. */ ffmpeg_init();#endif /* HAVE_FFMPEG */ /* In setup mode, Motion is very communicative towards the user, which * allows the user to experiment with the config parameters in order to * optimize motion detection and stuff. */ if (cnt_list[0]->conf.setup_mode) motion_log(-1, 0, "Motion running in setup mode."); /* Create and a thread attribute for the threads we spawn later on. * PTHREAD_CREATE_DETACHED means to create threads detached, i.e. * their termination cannot be synchronized through 'pthread_join'. */ pthread_attr_init(&thread_attr); pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); /* Create the TLS key for thread number. */ pthread_key_create(&tls_key_threadnr, NULL); do { if (restart) { /* Handle the restart situation. Currently the approach is to * cleanup everything, and then initialize everything again * (including re-reading the config file(s)). */ motion_shutdown(); restart = 0; /* only one reset for now */ motion_log(LOG_INFO,0,"motion restarted");#ifndef WITHOUT_V4L SLEEP(5,0); // maybe some cameras needs less time#endif motion_startup(0, argc, argv); /* 0 = skip daemon init */ } /* Start the motion threads. First 'cnt_list' item is global if 'thread' * option is used, so start at 1 then and 0 otherwise. */ for (i = cnt_list[1] != NULL ? 1 : 0; cnt_list[i]; i++) { /* If i is 0 it means no thread files and we then set the thread number to 1 */ cnt_list[i]->threadnr = i ? i : 1; if (strcmp(cnt_list[i]->conf_filename,"") ) motion_log(LOG_INFO, 0, "Thread %d is from %s", cnt_list[i]->threadnr, cnt_list[i]->conf_filename ); if (cnt_list[0]->conf.setup_mode) { motion_log(-1, 0, "Thread %d is device: %s input %d", cnt_list[i]->threadnr, cnt_list[i]->conf.netcam_url ? cnt_list[i]->conf.netcam_url : cnt_list[i]->conf.video_device, cnt_list[i]->conf.netcam_url ? -1 : cnt_list[i]->conf.input ); } if (cnt_list[0]->conf.setup_mode) motion_log(LOG_ERR, 0, "Webcam port %d", cnt_list[i]->conf.webcam_port); //线程处理函数入口 start_motion_thread(cnt_list[i], &thread_attr); } /* Create a thread for the control interface if requested. Create it * detached and with 'motion_web_control' as the thread function. */ //创建一个线程,注册线程处理函数motion_web_control() if (cnt_list[0]->conf.control_port) pthread_create(&thread_id, &thread_attr, &motion_web_control, cnt_list); if (cnt_list[0]->conf.setup_mode) motion_log(-1, 0,"Waiting for threads to finish, pid: %d", getpid()); /* Crude way of waiting for all threads to finish - check the thread * counter (because we cannot do join on the detached threads). */ while (1) { SLEEP(1,0); /* Calculate how many threads runnig or wants to run * if zero and we want to finish, break out */ int motion_threads_running = 0; for (i = (cnt_list[1] != NULL ? 1 : 0); cnt_list[i]; i++) { if (cnt_list[i]->running || cnt_list[i]->restart) motion_threads_running++; } if (((motion_threads_running == 0 ) && finish ) || ((motion_threads_running == 0 ) && (threads_running == 0)) ){ if (debug_level >= CAMERA_DEBUG){ motion_log(LOG_INFO, 0, "DEBUG-1 threads_running %d motion_threads_running %d , finish %d", threads_running, motion_threads_running, finish); } break; } for (i = (cnt_list[1] != NULL ? 1 : 0); cnt_list[i]; i++) { /* Check if threads wants to be restarted */ if ((!cnt_list[i]->running) && (cnt_list[i]->restart) ) { motion_log(LOG_INFO, 0, "Motion thread %d restart", cnt_list[i]->threadnr); start_motion_thread(cnt_list[i], &thread_attr); } if (cnt_list[i]->watchdog > WATCHDOG_OFF) { cnt_list[i]->watchdog--; if (cnt_list[i]->watchdog == 0) { motion_log(LOG_ERR, 0, "Thread %d - Watchdog timeout, trying to do a graceful restart", cnt_list[i]->threadnr); cnt_list[i]->finish = 1; } if (cnt_list[i]->watchdog == -60) { motion_log(LOG_ERR, 0, "Thread %d - Watchdog timeout, did NOT restart graceful," "killing it!", cnt_list[i]->threadnr); pthread_cancel(cnt_list[i]->thread_id); pthread_mutex_lock(&global_lock); threads_running--; pthread_mutex_unlock(&global_lock); motion_cleanup(cnt_list[i]); cnt_list[i]->running = 0; cnt_list[i]->finish = 0; } } } if (debug_level >= CAMERA_DEBUG){ motion_log(LOG_INFO, 0, "DEBUG-2 threads_running %d motion_threads_running %d , finish %d", threads_running, motion_threads_running, finish); } } /* Reset end main loop flag */ finish = 0; if (cnt_list[0]->conf.setup_mode) motion_log(LOG_DEBUG, 0, "Threads finished"); /* Rest for a while if we're supposed to restart. */ if (restart) SLEEP(2,0); } while (restart); /* loop if we're supposed to restart */ // Be sure that http control exits fine cnt_list[0]->finish = 1; SLEEP(1,0); motion_log(LOG_INFO, 0, "Motion terminating"); /* Perform final cleanup. */ pthread_key_delete(tls_key_threadnr); pthread_attr_destroy(&thread_attr); pthread_mutex_destroy(&global_lock); motion_shutdown(); return 0;}代码流程:
从分析流程可知:
main函数在做一些必要的初始化之后,会创建两个重要的线程。
1、在函数start_motion_thread(cnt_list[i], &thread_attr)中调用
函数pthread_create(&cnt->thread_id, thread_attr, &motion_loop, cnt);
进入static void *motion_loop(void *arg),正式进入motion_loop(),函数motion_loop()实现Motion的主要功能,如读取配置文件、采集图像、检测运动等。
2、pthread_create(&thread_id, &thread_attr, &motion_web_control, cnt_list)创建第二个线程,进入web网页浏览视频控制函数void *motion_web_control(void *arg),然后函数motion_web_control()调用函数httpd_run(cnt),用以远程控制motion。(这个线程只有配置文件中对应的选项被设置才会执行)
关联博文 【原创】动态图像监测开源代码 motion 学习 ----- Motion源码分析(2)
将分析函数motion_loop()的执行流程和实现功能。
- 【原创】动态图像监测开源代码 motion 学习 ----- Motion源码分析(1)
- 【原创】动态图像监测开源代码 motion 学习 ----- Motion源码分析(2)
- 【原创】动态图像监测开源代码 motion 学习 ----- Motion源码分析(3)
- 【原创】动态图像监测开源代码 motion 学习-----Motion常见问题和与Motion相关的应用(五)
- 【翻译】动态图像监测开源代码 motion 学习-----Motion Guide - Installation(motion的安装指南)
- 【翻译】动态图像监测开源代码 motion 学习-----Motion Guide-配置选项搜索表(四)
- 【翻译】动态图像监测开源代码 motion 学习-----Motion Guide - Basic Features(motion的基本特性)(一)
- 【翻译】动态图像监测开源代码 motion 学习-----Motion Guide - Basic Features(motion的基本特性)(二)
- 【翻译】动态图像监测开源代码 motion 学习-----Motion Guide - Special Features(motion的特殊功能)(三)
- 【翻译】动态图像监测开源代码 motion 学习-----Motion Guide - Getting It Running(让motion动起来)
- motion源码分析(一)
- motion源代码分析
- motion源码分析
- linux下的开源移动图像监测程序--motion编译与配置及ffmpeg
- linux下的开源移动图像监测程序--motion编译与配置
- Linux下移植motion到6410开发板(移动图像监测系统)
- motion源码分析(二)——录像
- motion
- 【小白的java成长系列】——windows下搭建和配置java环境
- ios中十六进制颜色转UIColor
- 关于Android 的常用信息输出命令的使用方法的汇总
- Hello World
- 怎样才能不浪费生命
- 【原创】动态图像监测开源代码 motion 学习 ----- Motion源码分析(1)
- Machine Learning(Andrew)Week10(下)
- TOP 10开源的推荐系统简介
- 线段树
- leetcode: Path Sum
- HttpClient4.3教程 第三章 Http状态管理
- 导出excel,最前面数字0不见了
- SMTP发送
- Delphi中MessageBox用法