【原创】动态图像监测开源代码 motion 学习 ----- Motion源码分析(1)


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


转载于:https://www.cnblogs.com/gengzj/p/3827087.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值