motion源代码分析

转自:http://blog.csdn.net/sakaue/article/details/22816475

 

楔子

前几天研究了如何将ffmpeg编入motion,并实现录像功能。现在研究下motion的工作流程。

 

几个主要模块

 

motion.c主程序,视频采集编码主循环
ffmpeg.c一个代理模块,封装了ffmpeg的方法,根据v4l获取的数据编码录像
video.2.c提供video4linux功能
video_common.c封装video.2.c中功能,为motion.c提供支持
vebhttpd.c向客户端提供控制功能
webcam.c向客户端提供实时图像服务(浏览器刷图片)

 

 

正文

照例从main函数进入。在这里,main起了两个线程,一个是集视频采集录像放送于一体的motion_loop:

 

[cpp] view plain copy

  1. /* Start the motion threads. First 'cnt_list' item is global if 'thread' 
  2.  * option is used, so start at 1 then and 0 otherwise. 
  3.  */  
  4. for (i = cnt_list[1] != NULL ? 1 : 0; cnt_list[i]; i++) {  
  5.     /* If i is 0 it means no thread files and we then set the thread number to 1 */  
  6.     cnt_list[i]->threadnr = i ? i : 1;  
  7.   
  8.     if (strcmp(cnt_list[i]->conf_filename,"") )  
  9.         motion_log(LOG_INFO, 0, "Thread %d is from %s", cnt_list[i]->threadnr, cnt_list[i]->conf_filename );  
  10.   
  11.         if (cnt_list[0]->conf.setup_mode) {  
  12.             motion_log(-1, 0, "Thread %d is device: %s input %d", cnt_list[i]->threadnr,  
  13.                        cnt_list[i]->conf.netcam_url ? cnt_list[i]->conf.netcam_url : cnt_list[i]->conf.video_device,  
  14.                        cnt_list[i]->conf.netcam_url ? -1 : cnt_list[i]->conf.input  
  15.                        );  
  16.         }  
  17.   
  18.         if (cnt_list[0]->conf.setup_mode)  
  19.             motion_log(LOG_ERR, 0, "Webcam port %d", cnt_list[i]->conf.webcam_port);  
  20.   
  21.         start_motion_thread(cnt_list[i], &thread_attr); //在这里启动线程函数motion_loop  
  22. }  

一个是用于web控制的motion_web_control:

 

 

[cpp] view plain copy

  1. /* Create a thread for the control interface if requested. Create it 
  2.  * detached and with 'motion_web_control' as the thread function. 
  3.  */  
  4. if (cnt_list[0]->conf.control_port)  
  5.     pthread_create(&thread_id, &thread_attr, &motion_web_control, cnt_list); //启动线程函数motion_web_control  

 

而main中的迭代主要负责一些统计任务。我们主要关心motion的核心——motion_loop。

 

刷照片的效果实在太挫了,让我们看看如何打开ffmpeg录像的配置。这里需要修改motion-dist.conf中的两个选项(采用默认值则不会录像):

[cpp] view plain copy

  1. # Use ffmpeg to encode a timelapse movie   
  2. # Default value 0 = off - else save frame every Nth second  
  3. ffmpeg_timelapse 1  
  4.   
  5.   
  6. # Enables and defines variable bitrate for the ffmpeg encoder.  
  7. # ffmpeg_bps is ignored if variable bitrate is enabled.  
  8. # Valid values: 0 (default) = fixed bitrate defined by ffmpeg_bps,  
  9. # or the range 2 - 31 where 2 means best quality and 31 is worst.  
  10. ffmpeg_variable_bitrate 1  

第一个选项是设置每一秒保存帧(帧的数量由配置文件中的framerate决定 ),第二个选项设置ffmpeg编码的比特率。下面还有个选项:

[cpp] view plain copy

  1. # Codec to used by ffmpeg for the video compression.  
  2. # Timelapse mpegs are always made in mpeg1 format independent from this option.  
  3. # Supported formats are: mpeg1 (ffmpeg-0.4.8 only), mpeg4 (default), and msmpeg4.  
  4. # mpeg1 - gives you files with extension .mpg  
  5. # mpeg4 or msmpeg4 - gives you files with extension .avi  
  6. # msmpeg4 is recommended for use with Windows Media Player because  
  7. # it requires no installation of codec on the Windows client.  
  8. # swf - gives you a flash film with extension .swf  
  9. # flv - gives you a flash video with extension .flv  
  10. # ffv1 - FF video codec 1 for Lossless Encoding ( experimental )  
  11. # mov - QuickTime ( testing )  
  12. ffmpeg_video_codec mpeg4  

这个其实该不该无所谓,因为编码器的格式在里面是写死的,稍后会提到。motion的录像在motion_loop(motion.c:1698)当中:

 

[cpp] view plain copy

  1. #ifdef HAVE_FFMPEG  
  2.   
  3.   
  4.   
  5.         if (cnt->conf.timelapse) {  
  6.   
  7.             /* Check to see if we should start a new timelapse file. We start one when 
  8.              * we are on the first shot, and and the seconds are zero. We must use the seconds 
  9.              * to prevent the timelapse file from getting reset multiple times during the minute. 
  10.              */  
  11.             if (cnt->current_image->timestamp_tm.tm_min == 0 &&  
  12.                 (time_current_frame % 60 < time_last_frame % 60) &&  
  13.                 cnt->shots == 0) {  
  14.   
  15.                 if (strcasecmp(cnt->conf.timelapse_mode,"manual") == 0) {  
  16.                     ;/* No action */  
  17.   
  18.                 /* If we are daily, raise timelapseend event at midnight */  
  19.                 } else if (strcasecmp(cnt->conf.timelapse_mode, "daily") == 0) {  //根据配置文件中ffmpeg_timelapse_mode的选则执行相应代码  
  20.                     if (cnt->current_image->timestamp_tm.tm_hour == 0)  
  21.                         event(cnt, EVENT_TIMELAPSEEND, NULL, NULL, NULL,   
  22.                               &cnt->current_image->timestamp_tm);  
  23.   
  24.                 /* handle the hourly case */  
  25.                 } else if (strcasecmp(cnt->conf.timelapse_mode, "hourly") == 0) {  
  26.                     event(cnt, EVENT_TIMELAPSEEND, NULL, NULL, NULL,   
  27.                           &cnt->current_image->timestamp_tm);  
  28.   
  29.                 /* If we are weekly-sunday, raise timelapseend event at midnight on sunday */  
  30.                 } else if (strcasecmp(cnt->conf.timelapse_mode, "weekly-sunday") == 0) {  
  31.                     if (cnt->current_image->timestamp_tm.tm_wday == 0 && cnt->current_image->timestamp_tm.tm_hour == 0)  
  32.                         event(cnt, EVENT_TIMELAPSEEND, NULL, NULL, NULL, &cnt->current_image->timestamp_tm);  
  33.   
  34.                 /* If we are weekly-monday, raise timelapseend event at midnight on monday */      
  35.                 } else if (strcasecmp(cnt->conf.timelapse_mode, "weekly-monday") == 0) {  
  36.                     if (cnt->current_image->timestamp_tm.tm_wday == 1 && cnt->current_image->timestamp_tm.tm_hour == 0)  
  37.                         event(cnt, EVENT_TIMELAPSEEND, NULL, NULL, NULL, &cnt->current_image->timestamp_tm);  
  38.   
  39.                 /* If we are monthly, raise timelapseend event at midnight on first day of month */      
  40.                 } else if (strcasecmp(cnt->conf.timelapse_mode, "monthly") == 0) {  
  41.                     if (cnt->current_image->timestamp_tm.tm_mday == 1 && cnt->current_image->timestamp_tm.tm_hour == 0)  
  42.                         event(cnt, EVENT_TIMELAPSEEND, NULL, NULL, NULL, &cnt->current_image->timestamp_tm);  
  43.   
  44.                 /* If invalid we report in syslog once and continue in manual mode */      
  45.                 } else {  
  46.                     motion_log(LOG_ERR, 0, "Invalid timelapse_mode argument '%s'",  
  47.                                cnt->conf.timelapse_mode);  
  48.                     motion_log(LOG_ERR, 0, "Defaulting to manual timelapse mode");  
  49.                     conf_cmdparse(&cnt, (char *)"ffmpeg_timelapse_mode",(char *)"manual");  
  50.                 }  
  51.             }  
  52.   
  53.             /* If ffmpeg timelapse is enabled and time since epoch MOD ffmpeg_timelaps = 0 
  54.              * add a timelapse frame to the timelapse mpeg. 
  55.              */  
  56.             if (cnt->shots == 0 &&  
  57.                 time_current_frame % cnt->conf.timelapse <= time_last_frame % cnt->conf.timelapse)  
  58.                 event(cnt, EVENT_TIMELAPSE, cnt->current_image->image, NULL, NULL,   
  59.                       &cnt->current_image->timestamp_tm);     // Line:1757 在这里创建并保存录制的视频  
  60.         } else if (cnt->ffmpeg_timelapse) {  
  61.         /* if timelapse mpeg is in progress but conf.timelapse is zero then close timelapse file 
  62.          * This is an important feature that allows manual roll-over of timelapse file using the http 
  63.          * remote control via a cron job. 
  64.          */  
  65.             event(cnt, EVENT_TIMELAPSEEND, NULL, NULL, NULL, cnt->currenttime_tm);   
  66.         }  
  67.   
  68. #endif /* HAVE_FFMPEG */  

执行录制视频的方法在1757行,根据EVENT_TIMELAPSE,它对应的方法叫event_ffmpeg_timelapse

 

 

[cpp] view plain copy

  1. // event.c:673  
  2.   
  3. {  
  4. EVENT_TIMELAPSE,  
  5. event_ffmpeg_timelapse  
  6. },  

[cpp] view plain copy

  1. // event.c:461  
  2.   
  3. static void event_ffmpeg_timelapse(struct context *cnt,  
  4.             int type ATTRIBUTE_UNUSED, unsigned char *img,  
  5.             char *dummy1 ATTRIBUTE_UNUSED, void *dummy2 ATTRIBUTE_UNUSED,  
  6.             struct tm *currenttime_tm)  
  7. {  
  8.     int width = cnt->imgs.width;  
  9.     int height = cnt->imgs.height;  
  10.     unsigned char *convbuf, *y, *u, *v;  
  11.   
  12.     if (!cnt->ffmpeg_timelapse) {  //只在第一次创建时执行  
  13.         char tmp[PATH_MAX];  
  14.         const char *timepath;  
  15.   
  16.         /* conf.timepath would normally be defined but if someone deleted it by control interface 
  17.            it is better to revert to the default than fail */  
  18.         if (cnt->conf.timepath)  
  19.             timepath = cnt->conf.timepath;  
  20.         else  
  21.             timepath = DEF_TIMEPATH;  
  22.           
  23.         mystrftime(cnt, tmp, sizeof(tmp), timepath, currenttime_tm, NULL, 0);  
  24.           
  25.         /* PATH_MAX - 4 to allow for .mpg to be appended without overflow */  
  26.         snprintf(cnt->timelapsefilename, PATH_MAX - 4, "%s/%s", cnt->conf.filepath, tmp);  
  27.           
  28.         if (cnt->imgs.type == VIDEO_PALETTE_GREY) {  
  29.             convbuf = mymalloc((width * height) / 2);  
  30.             y = img;  
  31.             u = convbuf;  
  32.             v = convbuf+(width * height) / 4;  
  33.             grey2yuv420p(u, v, width, height);  
  34.         } else {  
  35.             convbuf = NULL;  
  36.             y = img;  
  37.             u = img + width * height;  
  38.             v = u + (width * height) / 4;  
  39.         }  
  40.           
  41.         if ((cnt->ffmpeg_timelapse =  
  42.              ffmpeg_open((char *)TIMELAPSE_CODEC, cnt->timelapsefilename, y, u, v,   //#define TIMELAPSE_CODEC "mpeg1_tl"  
  43.                          cnt->imgs.width, cnt->imgs.height, 24, cnt->conf.ffmpeg_bps,  
  44.                          cnt->conf.ffmpeg_vbr)) == NULL) {   // 创建录像文件  
  45.             motion_log(LOG_ERR, 1, "ffopen_open error creating (timelapse) file [%s]", cnt->timelapsefilename);  
  46.             cnt->finish = 1;  
  47.             return;  
  48.         }  
  49.           
  50.         cnt->ffmpeg_timelapse->udata = convbuf;  
  51.         event(cnt, EVENT_FILECREATE, NULL, cnt->timelapsefilename, (void *)FTYPE_MPEG_TIMELAPSE, NULL);  
  52.     }  
  53.       
  54.     y = img;  
  55.       
  56.     if (cnt->imgs.type == VIDEO_PALETTE_GREY)  
  57.         u = cnt->ffmpeg_timelapse->udata;  
  58.     else  
  59.         u = img + width * height;  
  60.       
  61.     v = u + (width * height) / 4;  
  62.     ffmpeg_put_other_image(cnt->ffmpeg_timelapse, y, u, v);  //put图像进录像  
  63.       
  64. }  

其中Line:500,如果是第一次进入,则执行ffmpeg_open:

 

 

[cpp] view plain copy

  1. ffmpeg_open((char *)TIMELAPSE_CODEC,                                // #define TIMELAPSE_CODEC "mpeg1_tl"  
  2.                      cnt->timelapsefilename,                                    // 录像文件名  
  3.                       y, u, v,//#define TIMELAPSE_CODEC "mpeg1_tl"   
  4.                       cnt->imgs.width, cnt->imgs.height,                   // 录像的宽高  
  5.                       24,                                                                 // fps   
  6.                       cnt->conf.ffmpeg_bps,                                    // bps  
  7.                       cnt->conf.ffmpeg_vbr)) == NULL)  

如果不是第一次进入,则会直接执行ffmpeg_put_other_image将图像加入录像。

 

 

更多Linux资料及视频教程点击这里

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MATLAB编程源代码文件大全集合【约1000+】 MATLAB源代码MATLAB源码大集合220MB上千个源码文件: 2013全国大学生数学建模B题matlab代码.rar 802.11a OFDM MATLAB仿真代码!(推荐).rar MATLAB DCT水印源程序代码.rar MATLAB GUI 实例.rar matlab GUI实例.rar MATLAB GUI实现动态画图曲线的源程序代码.rar matlab.rar matlab7.0从入门到精通-光盘程序.rar Matlab_车牌识别.zip MATLAB中colorbar的设置 源程序代码.rar matlab中文字符的识别代码.rar MATLAB中的基本语法和语句示例代码.rar MATLAB使用欧拉Euler法求解微分方程组 源程序代码.rar MATLAB光通过三稜镜色散动画.rar Matlab十大算法源代码.rar Matlab图像处理与界面编程宝典源码.rar matlab图像处理代码.rar MATLAB图像处理实现直线识别(拟合角平分线).rar MATLAB图像处理实现螺纹识别 源程序代码.rar MATLAB图像配准程序.rar MATLAB在数学建模中的应用(上下 源程序).rar MATLAB夜间车牌识别程序.rar MATLAB实现不同插值方法的GUI界面设计 源程序代码.rar MATLAB实现偏微分方程的差分计算 源程序代码.rar MATLAB实现图像去噪 滤波 锐化 边缘检测.rar matlab实现图像拼接的代码.rar MATLAB实现学生成绩查询系统 源代码程序(1).rar MATLAB实现学生成绩查询系统 源代码程序.rar MATLAB实现灰度预测模型的源代码.rar MATLAB实现线性拟合和相关系数 源程序代码.rar matlab实现视频中动态目标跟踪.rar matlab实用程序300例.rar MATLAB寻找素数的源程序代码.rar MATLAB小波分析—张德丰(代码).rar MATLAB建模 人口增长模型 源程序代码.rar MATLAB文字连通域源程序代码.rar MATLAB智能算法30个案例分析 源代码.7z MATLAB求解非线性方程组 fsolve源程序代码.rar MATLAB生成Gif图片程序源代码.rar MATLAB绘制 维维安尼Viviani曲线 源代码程序.rar MATLAB计算粒子速度分布 源程序代码.rar MATLAB设计的简单滤波器程序源代码.rar Matlab语音信号滤波程序.rar matlab通信工程仿真源码(张德丰等编著).zip Matlab金融程序汇总.rar MATLAB霍夫曼Huffman编码译码GUI界面设计 源程序代码.rar mean+shift+tracking.rar MIMO-OFDM(simulinkANDmatlab).rar Motion_Detection.rar music_spectrum.rar OpenSURF_version1c.zip targettrackingusingkalman.rar VC++图像处理与识别实用案例精选.rar zhuantai.rar zxymath_matlab_program.doc 《MATLAB 7.0编程基础基础》源程序.rar 《MATLAB 神经网络43个案例分析源代码&数据.rar 《MATLAB程序设计教程》源代码-2660.rar 《图像分割中常用的水平集方法的matlab源代码》.zip 【MATLAB GUI设计学习手记】源代码.rar 国外的车牌识别程序.rar 图像分割算法的Matlab源程序matlab.zip 图像压缩.rar 图像处理.rar 图像处理源程序.rar 图像复原matlab程序.rar 图像形态学处理.rar 图像融合+源代码+matlab.rar 图像融合程序代码.rar 图像识别.rar 图像配准算法.rar 图论算法及其MATLAB实现(全书+源代码).zip 基于Matlab的多功能通信信号源仿真.rar 基于仿射变换的数字图象置乱技术 MATLAB源程序代码.rar 完整的QPSK-MSK-QAM-OFDM调制解调m程序.rar 实验心得总结.rar 拉格朗日插值 MATLAB源程序代码.rar 指纹识别的matlab源码.rar 指纹识别的matlab源码.zip 掌握和精通matlab之gui设计.rar 数字信号处理. 理论、算法与实现(胡广书)的MATLAB程序.rar 文字图像识别.rar 牛顿Newton插值 MATLAB源程序代码.rar 现代通信系统(MATLAB版) 源码.zip 用MATLAB对两幅图片进行
MATLAB源代码MATLAB源码大集合220MB上千个源码文件: 2013全国大学生数学建模B题matlab代码.rar 802.11a OFDM MATLAB仿真代码!(推荐).rar MATLAB DCT水印源程序代码.rar MATLAB GUI 实例.rar matlab GUI实例.rar MATLAB GUI实现动态画图曲线的源程序代码.rar matlab.rar matlab7.0从入门到精通-光盘程序.rar Matlab_车牌识别.zip MATLAB中colorbar的设置 源程序代码.rar matlab中文字符的识别代码.rar MATLAB中的基本语法和语句示例代码.rar MATLAB使用欧拉Euler法求解微分方程组 源程序代码.rar MATLAB光通过三稜镜色散动画.rar Matlab十大算法源代码.rar Matlab图像处理与界面编程宝典源码.rar matlab图像处理代码.rar MATLAB图像处理实现直线识别(拟合角平分线).rar MATLAB图像处理实现螺纹识别 源程序代码.rar MATLAB图像配准程序.rar MATLAB在数学建模中的应用(上下 源程序).rar MATLAB夜间车牌识别程序.rar MATLAB实现不同插值方法的GUI界面设计 源程序代码.rar MATLAB实现偏微分方程的差分计算 源程序代码.rar MATLAB实现图像去噪 滤波 锐化 边缘检测.rar matlab实现图像拼接的代码.rar MATLAB实现学生成绩查询系统 源代码程序(1).rar MATLAB实现学生成绩查询系统 源代码程序.rar MATLAB实现灰度预测模型的源代码.rar MATLAB实现线性拟合和相关系数 源程序代码.rar matlab实现视频中动态目标跟踪.rar matlab实用程序300例.rar MATLAB寻找素数的源程序代码.rar MATLAB小波分析—张德丰(代码).rar MATLAB建模 人口增长模型 源程序代码.rar MATLAB文字连通域源程序代码.rar MATLAB智能算法30个案例分析 源代码.7z MATLAB求解非线性方程组 fsolve源程序代码.rar MATLAB生成Gif图片程序源代码.rar MATLAB绘制 维维安尼Viviani曲线 源代码程序.rar MATLAB计算粒子速度分布 源程序代码.rar MATLAB设计的简单滤波器程序源代码.rar Matlab语音信号滤波程序.rar matlab通信工程仿真源码(张德丰等编著).zip Matlab金融程序汇总.rar MATLAB霍夫曼Huffman编码译码GUI界面设计 源程序代码.rar mean+shift+tracking.rar MIMO-OFDM(simulinkANDmatlab).rar Motion_Detection.rar music_spectrum.rar OpenSURF_version1c.zip targettrackingusingkalman.rar VC++图像处理与识别实用案例精选.rar zhuantai.rar zxymath_matlab_program.doc 《MATLAB 7.0编程基础基础》源程序.rar 《MATLAB 神经网络43个案例分析源代码&数据.rar 《MATLAB程序设计教程》源代码-2660.rar 《图像分割中常用的水平集方法的matlab源代码》.zip 【MATLAB GUI设计学习手记】源代码.rar 国外的车牌识别程序.rar 图像分割算法的Matlab源程序matlab.zip 图像压缩.rar 图像处理.rar 图像处理源程序.rar 图像复原matlab程序.rar 图像形态学处理.rar 图像融合+源代码+matlab.rar 图像融合程序代码.rar 图像识别.rar 图像配准算法.rar 图论算法及其MATLAB实现(全书+源代码).zip 基于Matlab的多功能通信信号源仿真.rar 基于仿射变换的数字图象置乱技术 MATLAB源程序代码.rar 完整的QPSK-MSK-QAM-OFDM调制解调m程序.rar 实验心得总结.rar 拉格朗日插值 MATLAB源程序代码.rar 指纹识别的matlab源码.rar 指纹识别的matlab源码.zip 掌握和精通matlab之gui设计.rar 数字信号处理. 理论、算法与实现(胡广书)的MATLAB程序.rar 文字图像识别.rar 牛顿Newton插值 MATLAB源程序代码.rar 现代通信系统(MATLAB版) 源码.zip 用MATLAB对两幅图片进行图像匹配.rar 电滤波效果查看器GUI设计--浙江

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值