ffmpeg Windows下采集摄像头一帧数据,并保存为bmp图片

这里请注意,在编译ffmpeg时,不要使用--disable-devices选项。

使用

--enable-encoder=rawvideo
 --enable-decoder=rawvideo

启用rawvideo codec。

代码如下:

[cpp] view plaincopyprint?

  1. #include <stdlib.h>  
  2. #include <stdio.h>  
  3. #include <string.h>  
  4.   
  5. #include <libavformat/avformat.h>  
  6. #include <libavcodec/avcodec.h>  
  7. #include <libavdevice/avdevice.h>  
  8. #include <libswscale/swscale.h>  
  9.   
  10. #include <windows.h>  
  11.   
  12. #include <time.h>  
  13.   
  14. #define MAX_INPUT_DEVICE_NUM 10  
  15.   
  16. #ifdef _WIN32  
  17. int strcasecmp(const char *s1, const char *s2)  
  18. {  
  19.     while ((*s1 != '\0')  
  20.         && (tolower(*(unsigned char *) s1) ==  
  21.         tolower(*(unsigned char *) s2)))   
  22.     {  
  23.         s1++;  
  24.         s2++;  
  25.     }  
  26.     return tolower(*(unsigned char *) s1) - tolower(*(unsigned char *) s2);  
  27. }  
  28. int strncasecmp(const char *s1, const char *s2, unsigned int n)  
  29. {  
  30.     if (n == 0)  
  31.         return 0;  
  32.     while ((n-- != 0)  
  33.         && (tolower(*(unsigned char *) s1) ==  
  34.         tolower(*(unsigned char *) s2))) {  
  35.             if (n == 0 || *s1 == '\0' || *s2 == '\0')  
  36.                 return 0;  
  37.             s1++;  
  38.             s2++;  
  39.     }  
  40.     return tolower(*(unsigned char *) s1) - tolower(*(unsigned char *) s2);  
  41. }  
  42. #endif  
  43.   
  44. void save_bmp(unsigned char * data,int data_size,int w,int h,FILE * out)  
  45. {  
  46.     // 位图文件头  
  47.     BITMAPFILEHEADER bmpheader;   
  48.     BITMAPINFO bmpinfo;   
  49.     int bit = 24;  
  50.   
  51.     bmpheader.bfType = ('M' <<8)|'B';   
  52.     bmpheader.bfReserved1 = 0;   
  53.     bmpheader.bfReserved2 = 0;   
  54.     bmpheader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);   
  55.     bmpheader.bfSize = bmpheader.bfOffBits + w*h*bit/8;  
  56.   
  57.     bmpinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);   
  58.     bmpinfo.bmiHeader.biWidth = w;   
  59.     bmpinfo.bmiHeader.biHeight = 0-h;   
  60.     bmpinfo.bmiHeader.biPlanes = 1;   
  61.     bmpinfo.bmiHeader.biBitCount = bit;   
  62.     bmpinfo.bmiHeader.biCompression = BI_RGB;   
  63.     bmpinfo.bmiHeader.biSizeImage = 0;   
  64.     bmpinfo.bmiHeader.biXPelsPerMeter = 100;   
  65.     bmpinfo.bmiHeader.biYPelsPerMeter = 100;   
  66.     bmpinfo.bmiHeader.biClrUsed = 0;   
  67.     bmpinfo.bmiHeader.biClrImportant = 0;  
  68.   
  69.     fwrite(&bmpheader,sizeof(BITMAPFILEHEADER),1,out);   
  70.     fwrite(&bmpinfo.bmiHeader,sizeof(BITMAPINFOHEADER),1,out);  
  71.     fwrite(data,data_size,1,out);  
  72. }  
  73. int CaptureFromLocalCamera()  
  74. {  
  75.     AVFormatContext *ic = NULL;  
  76.     AVFormatParameters in_fmt_para={0};  
  77.     AVPacket packet;  
  78.     char buffer[MAX_PATH]={0};  
  79.     int width = 0,height = 0;  
  80.     int ret,video_stream = -1,i=0;  
  81.   
  82.     //查找输入(vfwcap)格式  
  83.     AVInputFormat *in_fmt = av_find_input_format ("vfwcap");   
  84.     if (in_fmt == NULL)   
  85.     {  
  86.         printf("not support input device vfwcap.\n");  
  87.         return -1;  
  88.     }  
  89.     memset (&in_fmt_para, 0, sizeof(in_fmt_para));  
  90.     //指定需要采集图像的高度  
  91.     in_fmt_para.height = height;  
  92.     //指定需要采集图像的宽度  
  93.     in_fmt_para.width  = width;  
  94.   
  95.     //设置帧率  
  96.     av_parse_video_frame_rate(&in_fmt_para.time_base,"20");  
  97.   
  98.     //打开摄像头设备,从"0"到MAX_INPUT_DEVICE_NUM依次尝试打开  
  99.     for( i=0 ; i < MAX_INPUT_DEVICE_NUM + 1; i++ )  
  100.     {  
  101.         sprintf(buffer,"%d",i);  
  102.         ret = av_open_input_file ( &ic, buffer, in_fmt,sizeof(in_fmt_para),&in_fmt_para);  
  103.         if ( ret == 0 && ic)  
  104.         {  
  105.             break;  
  106.         }  
  107.     }  
  108.     //open success?  
  109.     if(!ic || ret != 0)  
  110.     {  
  111.         if(ic)  
  112.             av_close_input_file(ic);  
  113.         printf("can not open input file.\n");  
  114.         return -2;  
  115.     }  
  116.     printf("input device no. is %d\n",i);  
  117.     //find the video stream  
  118.     for(i=0;i<ic ->nb_streams;i++)  
  119.     {  
  120.         if ( CODEC_TYPE_VIDEO == ic ->streams[i] ->codec ->codec_type )  
  121.         {  
  122.             video_stream = i;  
  123.             break;  
  124.         }  
  125.     }  
  126.     if(video_stream < 0)  
  127.     {  
  128.         av_close_input_file(ic);  
  129.         printf("can not find a video stream.\n");  
  130.         return -3;  
  131.     }  
  132.     //获取视频时间宽度和高度  
  133.     width  = ic ->streams[video_stream] ->codec ->width;  
  134.     height = ic ->streams[video_stream] ->codec ->height;  
  135.     printf("video size: %dx%d\n",width,height);  
  136.     //从摄像头获取图像数据  
  137.     if( 0 == av_read_frame(ic,&packet))  
  138.     {  
  139.         //find the decode codec  
  140.         AVCodec * decodec =  avcodec_find_decoder(ic ->streams[video_stream] ->codec ->codec_id);  
  141.         if(decodec)  
  142.         {  
  143.             //open the decode codec  
  144.             if( 0 == avcodec_open(ic ->streams[video_stream] ->codec,decodec) )  
  145.             {  
  146.                 int got_picture = 0;  
  147.                 AVFrame * frame = avcodec_alloc_frame();  
  148.                 avcodec_decode_video2(ic ->streams[video_stream] ->codec,frame,&got_picture,&packet);  
  149.                 //decode success  
  150.                 if(got_picture)  
  151.                 {  
  152.                     uint8_t * buffer = NULL;  
  153.                     size_t buffer_size = 0;  
  154.                     struct SwsContext *pSwsCtx=NULL;  
  155.                     AVFrame * rgb_frame = avcodec_alloc_frame();  
  156.                     buffer_size = avpicture_get_size(PIX_FMT_BGR24,width,height);  
  157.                     buffer = (uint8_t *)av_malloc(buffer_size);  
  158.                     avpicture_fill((AVPicture*)rgb_frame,(uint8_t *)buffer,PIX_FMT_BGR24,width,height);  
  159.                     //get swscale ctx  
  160.                     pSwsCtx = sws_getContext(  
  161.                         ic ->streams[video_stream] ->codec ->width,  
  162.                         ic ->streams[video_stream] ->codec ->height,  
  163.                         ic ->streams[video_stream] ->codec ->pix_fmt,  
  164.                         width,  
  165.                         height,  
  166.                         PIX_FMT_BGR24,  
  167.                         SWS_BILINEAR,  
  168.                         NULL,  
  169.                         NULL,  
  170.                         NULL);  
  171.                     if(pSwsCtx)  
  172.                     {  
  173.                         FILE *fp = NULL;  
  174.                         SYSTEMTIME dt={0};  
  175.                         //图像格式转换  
  176.                         sws_scale(  
  177.                             pSwsCtx,  
  178.                             frame ->data,  
  179.                             frame ->linesize,  
  180.                             0,  
  181.                             ic ->streams[video_stream] ->codec ->height,  
  182.                             rgb_frame ->data,  
  183.                             rgb_frame ->linesize);  
  184.                         //create the image file name  
  185.                         GetLocalTime(&dt);  
  186.                         srand(0);  
  187.                         sprintf(buffer,"imgs/%04d_%02d_%02d %02d_%02d_%02d %02d.bmp",dt.wYear,dt.wMonth,dt.wDay,dt.wHour,dt.wMinute,dt.wSecond,rand()%30);  
  188.                         //  
  189.                         CreateDirectoryA("imgs",NULL);  
  190.                         //open file  
  191.                         fp = fopen(buffer, "wb");  
  192.                         if(fp)  
  193.                         {  
  194.                             save_bmp(rgb_frame ->data[0],rgb_frame ->linesize[0]*height,width,height,fp);  
  195.                             fclose(fp);  
  196.                         }  
  197.                         //free sws ctx  
  198.                         sws_freeContext(pSwsCtx);  
  199.                     }  
  200.                     //free buffer  
  201.                     av_free(rgb_frame);  
  202.                     av_free(buffer);  
  203.                 }  
  204.                 //free buffer  
  205.                 av_free(frame);  
  206.                 //close the decode codec  
  207.                 avcodec_close(ic ->streams[video_stream] ->codec);  
  208.             }  
  209.         }  
  210.     }  
  211.           
  212.     //close the input device  
  213.     av_close_input_file(ic);  
  214.   
  215.     return 0;  
  216. }  
  217.   
  218.   
  219. int main()  
  220. {  
  221.     //avcodec_init();      
  222.     avcodec_register_all();  
  223.     avdevice_register_all();  
  224.     CaptureFromLocalCamera();  
  225.   
  226.     return 0;  
  227. }  
时间: 2024-10-31 02:38:49

ffmpeg Windows下采集摄像头一帧数据,并保存为bmp图片的相关文章

android摄像头-Android摄像头视频帧数据保存

问题描述 Android摄像头视频帧数据保存 用Android手机自带的camera,采集视频信息,得到每帧中心点的像素值,写入到txt文档中,现在出现一个奇怪的问题:在onCreate()方法中,先创建好空的txt文档,用于后面的数据写入,视频处理后的帧率也快些,但是得到的数据与实际的有很大的出入:而在onPreviewFrame()方法中,读取每帧的时候重复创建空的txt文档,帧率是稍微降低些,但是数据更合理,不知道其中什么原因导致的.,各位大神,拜托了!(这个Android底层有关系么?)

serialize函数重载-mfc文档视图框架下怎么实现对话框中数据的保存与打开

问题描述 mfc文档视图框架下怎么实现对话框中数据的保存与打开 在文档菜单栏上自己添加了一个对话框资源,并在对话框上添加了保存与打开按钮,想在对话框中重载文档serialize函数,但程序总是进不去,请问怎么实现? 解决方案 先看serialize是否有调用,然后就是对话框是否获取到数据 解决方案二: 程序进不去是什么意思.你不如重新用向导创建一次. 新建一个单文档程序,最后一步,从CFormView继承.重写OnNewDocument和OnOpenDialog

Windows下通过FTP自动备份数据到服务器并删除指定天数前的备份_win服务器

说明: 1.要备份的文件在D盘根目录下面,以时间命名,(一般我们通过护卫神的好备份软件实现备份)例如 D:\data_db_201112130001.BAK D:\data_db_201112140002.BAK D:\data_db_201112150003.BAK 每天会自动生成一个新的文件,例如2011年12月16号,会自动生成data_db_201112160004.BAK 2.要把D:\下面当天生成的那个数据定时备份到FTP服务器上,例如,今天是2011年12月16号,要把data_d

c# 读取ACCESS数据OLE字段的bmp图片,提示:参数无效。

问题描述 1.ACCESS2007建立了一个数据库,其中"TEST"字段为OLE类型,每条记录已经储存有bmp格式照片1张.2.我需要读取照片,显示到pic控件上.第一步:连接数据库,测试连接成功.第二步:读取储存照片的字段,转化为byte.但运行到断点语句时,提示:参数无效.求帮助..数据库: 解决方案 本帖最后由 powerswhlz 于 2016-05-08 17:18:58 编辑解决方案二:ole类型的字段存储格式没有公开,但是开头肯定不会是图像文件你要么改用VBA来读,要么在

[20160531]windows下bbed修复corrupt数据块

[20160531]windows下bbed修复corrupt数据块.txt --昨天别人的问题,使用windows下的bbed修复corrupt数据块报错.我自己也重复测试看看: --bbed在windows的安装看: http://blog.itpub.net/267265/viewspace-2109019/ 1.环境: SCOTT@book> @ &r/ver1 PORT_STRING                    VERSION        BANNER --------

android-Android 采集摄像头数据 , 通过ffmpeg推送流至服务器

问题描述 Android 采集摄像头数据 , 通过ffmpeg推送流至服务器 Android 采集摄像头数据 , 通过ffmpeg推送流, 通过AdobeMediaServer查看 , 为什么播放视频总是隔一段时间一缓冲 , 而且播放有延迟.求大神帮忙啊 AVFormatContext *ofmt_ctx; AVStream* video_st; //视音频流对应的结构体,用于视音频编解码. AVCodecContext* pCodecCtx; AVCodec* pCodec; AVPacket

通过摄像头设备采集一帧数据的例子程序(完整版)【转】

转自:http://blog.csdn.net/chance_yin/article/details/8947138 版权声明:本文为博主原创文章,未经博主允许不得转载. [cpp] view plain copy #include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> #include <getopt.h> #include <fcntl

fedora 9下驱动摄像头采集图像手记

最近一个月,在做视屏图像采集方面的项目.我安装了的是fedora 9.在fedora 9下让摄像头采集数据可谓是费尽了我半个月的时间.看似简单的问题,不知道我为什么做了这么长时间.    首先,摄像头要有保证.现在我发现市面上的摄像头芯片很多都是linux万能驱动无法无法驱动的.如果我没猜错的话,可能你现在手里的摄像头就是 linux万能摄像头驱动不支持的.为了能在linux下摄像头正常工作.最好是去买一个中星微3xx的摄像头(最常见的是中星微301,中星微303 等),这些都是linux万能摄

安卓 摄像头 预览-camera不预览但又能获得每一帧数据。

问题描述 camera不预览但又能获得每一帧数据. 如题,如何可以做到? 我想做的就是获得摄像头的每一帧数据,但是又不想预览. 解决方案 用ffmpeg这个库提取frames