很久沒有更新blog,這樣不好,工作之後仍然需要不斷的學習新的技術,工作外的技術等等……
motion是一個基於Linux平台的開源項目,其功能是檢測視頻流中的畫面運動,類似於移動偵測。整個項目只有30多個檔案,非常小巧。據說axis這個網路攝像機的大牌廠商也使用該演算法處理。所有我也需要啃一啃才行啊~!
程式的入口是在motion.c中的main函數
/**<br /> * main<br /> *<br /> * Main entry point of Motion. Launches all the motion threads and contains<br /> * the logic for starting up, restarting and cleaning up everything.<br /> *<br /> * Parameters:<br /> *<br /> * argc - size of argv<br /> * argv - command-line options<br /> *<br /> * Returns: Motion exit status = 0 always<br /> */<br />int main (int argc, char **argv)<br />{<br /> int i;<br /> pthread_attr_t thread_attr;<br /> pthread_t thread_id;<br /> /* Setup signals and do some initialization. 1 in the call to<br /> * 'motion_startup' means that Motion will become a daemon if so has been<br /> * requested, and argc and argc are necessary for reading the command<br /> * line options.<br /> */<br /> struct sigaction sig_handler_action;<br /> struct sigaction sigchild_action;<br /> setup_signals(&sig_handler_action, &sigchild_action);<br /> motion_startup(1, argc, argv);<br />#ifdef HAVE_FFMPEG<br /> /* FFMpeg initialization is only performed if FFMpeg support was found<br /> * and not disabled during the configure phase.<br /> */<br /> ffmpeg_init();<br />#endif /* HAVE_FFMPEG */<br /> /* In setup mode, Motion is very communicative towards the user, which<br /> * allows the user to experiment with the config parameters in order to<br /> * optimize motion detection and stuff.<br /> */<br /> if (cnt_list[0]->conf.setup_mode)<br /> motion_log(-1, 0, "Motion running in setup mode.");<br /> /* Create and a thread attribute for the threads we spawn later on.<br /> * PTHREAD_CREATE_DETACHED means to create threads detached, i.e.<br /> * their termination cannot be synchronized through 'pthread_join'.<br /> */<br /> pthread_attr_init(&thread_attr);<br /> pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);<br /> /* Create the TLS key for thread number. */<br /> pthread_key_create(&tls_key_threadnr, NULL);<br /> do {<br /> if (restart) {<br /> /* Handle the restart situation. Currently the approach is to<br /> * cleanup everything, and then initialize everything again<br /> * (including re-reading the config file(s)).<br /> */<br /> motion_shutdown();<br /> restart = 0; /* only one reset for now */<br /> motion_log(LOG_INFO,0,"motion restarted");<br />#ifndef WITHOUT_V4L<br /> SLEEP(5,0); // maybe some cameras needs less time<br />#endif<br /> motion_startup(0, argc, argv); /* 0 = skip daemon init */<br /> }</p><p> /* Start the motion threads. First 'cnt_list' item is global if 'thread'<br /> * option is used, so start at 1 then and 0 otherwise.<br /> */<br /> for (i = cnt_list[1] != NULL ? 1 : 0; cnt_list[i]; i++) {<br /> /* If i is 0 it means no thread files and we then set the thread number to 1 */<br /> cnt_list[i]->threadnr = i ? i : 1;<br /> if (strcmp(cnt_list[i]->conf_filename,"") )<br /> motion_log(LOG_INFO, 0, "Thread %d is from %s", cnt_list[i]->threadnr, cnt_list[i]->conf_filename );<br /> if (cnt_list[0]->conf.setup_mode) {<br /> motion_log(-1, 0, "Thread %d is device: %s input %d", cnt_list[i]->threadnr,<br /> cnt_list[i]->conf.netcam_url ? cnt_list[i]->conf.netcam_url : cnt_list[i]->conf.video_device,<br /> cnt_list[i]->conf.netcam_url ? -1 : cnt_list[i]->conf.input<br /> );<br /> }<br /> if (cnt_list[0]->conf.setup_mode)<br /> motion_log(LOG_ERR, 0, "Webcam port %d", cnt_list[i]->conf.webcam_port);<br /> start_motion_thread(cnt_list[i], &thread_attr);<br /> }<br /> /* Create a thread for the control interface if requested. Create it<br /> * detached and with 'motion_web_control' as the thread function.<br /> */<br /> if (cnt_list[0]->conf.control_port)<br /> pthread_create(&thread_id, &thread_attr, &motion_web_control, cnt_list);<br /> if (cnt_list[0]->conf.setup_mode)<br /> motion_log(-1, 0,"Waiting for threads to finish, pid: %d", getpid());<br /> /* Crude way of waiting for all threads to finish - check the thread<br /> * counter (because we cannot do join on the detached threads).<br /> */<br /> while (1) {<br /> SLEEP(1,0);<br /> /* Calculate how many threads runnig or wants to run<br /> * if zero and we want to finish, break out<br /> */<br /> int motion_threads_running = 0;<br /> for (i = (cnt_list[1] != NULL ? 1 : 0); cnt_list[i]; i++) {<br /> if (cnt_list[i]->running || cnt_list[i]->restart)<br /> motion_threads_running++;<br /> }<br /> if (((motion_threads_running == 0 ) && finish ) ||<br /> ((motion_threads_running == 0 ) && (threads_running == 0)) ){<br /> if (debug_level >= CAMERA_DEBUG){<br /> motion_log(LOG_INFO, 0, "DEBUG-1 threads_running %d motion_threads_running %d , finish %d",<br /> threads_running, motion_threads_running, finish);<br /> }<br /> break;<br /> }<br /> for (i = (cnt_list[1] != NULL ? 1 : 0); cnt_list[i]; i++) {<br /> /* Check if threads wants to be restarted */<br /> if ((!cnt_list[i]->running) && (cnt_list[i]->restart) ) {<br /> motion_log(LOG_INFO, 0, "Motion thread %d restart", cnt_list[i]->threadnr);<br /> start_motion_thread(cnt_list[i], &thread_attr);<br /> }<br /> if (cnt_list[i]->watchdog > WATCHDOG_OFF) {<br /> cnt_list[i]->watchdog--;<br /> if (cnt_list[i]->watchdog == 0) {<br /> motion_log(LOG_ERR, 0, "Thread %d - Watchdog timeout, trying to do a graceful restart",<br /> cnt_list[i]->threadnr);<br /> cnt_list[i]->finish = 1;<br /> }<br /> if (cnt_list[i]->watchdog == -60) {<br /> motion_log(LOG_ERR, 0, "Thread %d - Watchdog timeout, did NOT restart graceful,"<br /> "killing it!", cnt_list[i]->threadnr);<br /> pthread_cancel(cnt_list[i]->thread_id);<br /> pthread_mutex_lock(&global_lock);<br /> threads_running--;<br /> pthread_mutex_unlock(&global_lock);<br /> motion_cleanup(cnt_list[i]);<br /> cnt_list[i]->running = 0;<br /> cnt_list[i]->finish = 0;<br /> }<br /> }<br /> }<br /> if (debug_level >= CAMERA_DEBUG){<br /> motion_log(LOG_INFO, 0, "DEBUG-2 threads_running %d motion_threads_running %d , finish %d",<br /> threads_running, motion_threads_running, finish);<br /> }<br /> }<br /> /* Reset end main loop flag */<br /> finish = 0;<br /> if (cnt_list[0]->conf.setup_mode)<br /> motion_log(LOG_DEBUG, 0, "Threads finished");<br /> /* Rest for a while if we're supposed to restart. */<br /> if (restart)<br /> SLEEP(2,0);<br /> } while (restart); /* loop if we're supposed to restart */<br /> // Be sure that http control exits fine<br /> cnt_list[0]->finish = 1;<br /> SLEEP(1,0);<br /> motion_log(LOG_INFO, 0, "Motion terminating");<br /> /* Perform final cleanup. */<br /> pthread_key_delete(tls_key_threadnr);<br /> pthread_attr_destroy(&thread_attr);<br /> pthread_mutex_destroy(&global_lock);<br /> motion_shutdown();<br /> return 0;<br />}