【原创】动态图像监测开源代码 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()的执行流程和实现功能。


0 0