很久没有更新blog,这样不好,工作之后仍然需要不断的学习新的技术,工作外的技术等等……
motion是一个基于Linux平台的开源项目,其功能是检测视频流中的画面运动,类似于移动侦测。整个项目只有30多个文件,非常小巧。据说axis这个网络摄像机的大牌厂商也使用该算法处理。所有我也需要啃一啃才行啊~!
程序的入口是在motion.c中的main函数
/* 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.
*/
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;
}