[转载] ffmpeg Windows下采集摄像头一帧数据,并保存为bmp图片
这里请注意,在编译ffmpeg时,不要使用--disable-devices选项。
使用
--enable-encoder=rawvideo
--enable-decoder=rawvideo
启用rawvideo codec。
代码如下:
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <libavformat/avformat.h>
- #include <libavcodec/avcodec.h>
- #include <libavdevice/avdevice.h>
- #include <libswscale/swscale.h>
- #include <windows.h>
- #include <time.h>
- #define MAX_INPUT_DEVICE_NUM 10
- #ifdef _WIN32
- int strcasecmp(const char *s1, const char *s2)
- {
- while ((*s1 != '\0')
- && (tolower(*(unsigned char *) s1) ==
- tolower(*(unsigned char *) s2)))
- {
- s1++;
- s2++;
- }
- return tolower(*(unsigned char *) s1) - tolower(*(unsigned char *) s2);
- }
- int strncasecmp(const char *s1, const char *s2, unsigned int n)
- {
- if (n == 0)
- return 0;
- while ((n-- != 0)
- && (tolower(*(unsigned char *) s1) ==
- tolower(*(unsigned char *) s2))) {
- if (n == 0 || *s1 == '\0' || *s2 == '\0')
- return 0;
- s1++;
- s2++;
- }
- return tolower(*(unsigned char *) s1) - tolower(*(unsigned char *) s2);
- }
- #endif
- void save_bmp(unsigned char * data,int data_size,int w,int h,FILE * out)
- {
- // 位图文件头
- BITMAPFILEHEADER bmpheader;
- BITMAPINFO bmpinfo;
- int bit = 24;
- bmpheader.bfType = ('M' <<8)|'B';
- bmpheader.bfReserved1 = 0;
- bmpheader.bfReserved2 = 0;
- bmpheader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
- bmpheader.bfSize = bmpheader.bfOffBits + w*h*bit/8;
- bmpinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- bmpinfo.bmiHeader.biWidth = w;
- bmpinfo.bmiHeader.biHeight = 0-h;
- bmpinfo.bmiHeader.biPlanes = 1;
- bmpinfo.bmiHeader.biBitCount = bit;
- bmpinfo.bmiHeader.biCompression = BI_RGB;
- bmpinfo.bmiHeader.biSizeImage = 0;
- bmpinfo.bmiHeader.biXPelsPerMeter = 100;
- bmpinfo.bmiHeader.biYPelsPerMeter = 100;
- bmpinfo.bmiHeader.biClrUsed = 0;
- bmpinfo.bmiHeader.biClrImportant = 0;
- fwrite(&bmpheader,sizeof(BITMAPFILEHEADER),1,out);
- fwrite(&bmpinfo.bmiHeader,sizeof(BITMAPINFOHEADER),1,out);
- fwrite(data,data_size,1,out);
- }
- int CaptureFromLocalCamera()
- {
- AVFormatContext *ic = NULL;
- AVFormatParameters in_fmt_para={0};
- AVPacket packet;
- char buffer[MAX_PATH]={0};
- int width = 0,height = 0;
- int ret,video_stream = -1,i=0;
- //查找输入(vfwcap)格式
- AVInputFormat *in_fmt = av_find_input_format ("vfwcap");
- if (in_fmt == NULL)
- {
- printf("not support input device vfwcap.\n");
- return -1;
- }
- memset (&in_fmt_para, 0, sizeof(in_fmt_para));
- //指定需要采集图像的高度
- in_fmt_para.height = height;
- //指定需要采集图像的宽度
- in_fmt_para.width = width;
- //设置帧率
- av_parse_video_frame_rate(&in_fmt_para.time_base,"20");
- //打开摄像头设备,从"0"到MAX_INPUT_DEVICE_NUM依次尝试打开
- for( i=0 ; i < MAX_INPUT_DEVICE_NUM + 1; i++ )
- {
- sprintf(buffer,"%d",i);
- ret = av_open_input_file ( &ic, buffer, in_fmt,sizeof(in_fmt_para),&in_fmt_para);
- if ( ret == 0 && ic)
- {
- break;
- }
- }
- //open success?
- if(!ic || ret != 0)
- {
- if(ic)
- av_close_input_file(ic);
- printf("can not open input file.\n");
- return -2;
- }
- printf("input device no. is %d\n",i);
- //find the video stream
- for(i=0;i<ic ->nb_streams;i++)
- {
- if ( CODEC_TYPE_VIDEO == ic ->streams[i] ->codec ->codec_type )
- {
- video_stream = i;
- break;
- }
- }
- if(video_stream < 0)
- {
- av_close_input_file(ic);
- printf("can not find a video stream.\n");
- return -3;
- }
- //获取视频时间宽度和高度
- width = ic ->streams[video_stream] ->codec ->width;
- height = ic ->streams[video_stream] ->codec ->height;
- printf("video size: %dx%d\n",width,height);
- //从摄像头获取图像数据
- if( 0 == av_read_frame(ic,&packet))
- {
- //find the decode codec
- AVCodec * decodec = avcodec_find_decoder(ic ->streams[video_stream] ->codec ->codec_id);
- if(decodec)
- {
- //open the decode codec
- if( 0 == avcodec_open(ic ->streams[video_stream] ->codec,decodec) )
- {
- int got_picture = 0;
- AVFrame * frame = avcodec_alloc_frame();
- avcodec_decode_video2(ic ->streams[video_stream] ->codec,frame,&got_picture,&packet);
- //decode success
- if(got_picture)
- {
- uint8_t * buffer = NULL;
- size_t buffer_size = 0;
- struct SwsContext *pSwsCtx=NULL;
- AVFrame * rgb_frame = avcodec_alloc_frame();
- buffer_size = avpicture_get_size(PIX_FMT_BGR24,width,height);
- buffer = (uint8_t *)av_malloc(buffer_size);
- avpicture_fill((AVPicture*)rgb_frame,(uint8_t *)buffer,PIX_FMT_BGR24,width,height);
- //get swscale ctx
- pSwsCtx = sws_getContext(
- ic ->streams[video_stream] ->codec ->width,
- ic ->streams[video_stream] ->codec ->height,
- ic ->streams[video_stream] ->codec ->pix_fmt,
- width,
- height,
- PIX_FMT_BGR24,
- SWS_BILINEAR,
- NULL,
- NULL,
- NULL);
- if(pSwsCtx)
- {
- FILE *fp = NULL;
- SYSTEMTIME dt={0};
- //图像格式转换
- sws_scale(
- pSwsCtx,
- frame ->data,
- frame ->linesize,
- 0,
- ic ->streams[video_stream] ->codec ->height,
- rgb_frame ->data,
- rgb_frame ->linesize);
- //create the image file name
- GetLocalTime(&dt);
- srand(0);
- 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);
- //
- CreateDirectoryA("imgs",NULL);
- //open file
- fp = fopen(buffer, "wb");
- if(fp)
- {
- save_bmp(rgb_frame ->data[0],rgb_frame ->linesize[0]*height,width,height,fp);
- fclose(fp);
- }
- //free sws ctx
- sws_freeContext(pSwsCtx);
- }
- //free buffer
- av_free(rgb_frame);
- av_free(buffer);
- }
- //free buffer
- av_free(frame);
- //close the decode codec
- avcodec_close(ic ->streams[video_stream] ->codec);
- }
- }
- }
- //close the input device
- av_close_input_file(ic);
- return 0;
- }
- int main()
- {
- //avcodec_init();
- avcodec_register_all();
- avdevice_register_all();
- CaptureFromLocalCamera();
- return 0;
- }
[转载] ffmpeg Windows下采集摄像头一帧数据,并保存为bmp图片的更多相关文章
- ffmpeg Windows下采集摄像头一帧数据,并保存为bmp图片
这里请注意,在编译ffmpeg时,不要使用--disable-devices选项. 使用 --enable-encoder=rawvideo --enable-decoder=rawvideo 启用r ...
- JavaCV 采集摄像头和麦克风数据推送到流媒体服务器
越来越觉得放弃JavaCV FFmpeg native API,直接使用JavaCV二次封装的API开发是很明智的选择,使用JavaCV二次封装的API开发避免了各种内存操作不当引起的crash. 上 ...
- wireshark在windows下无法抓取localhost数据包
在调试SSL时要抓包,通过tcpview和minisniffer等工具明明看到tcp连接已经建立并开始收发数据了,但wireshark却总是无法抓到相应的数据包. 今天早上,HQ的高工告诉我“wire ...
- 使用ffmpeg将BMP图片编码为x264视频文件,将H264视频保存为BMP图片,yuv视频文件保存为图片的代码
ffmpeg开源库,实现将bmp格式的图片编码成x264文件,并将编码好的H264文件解码保存为BMP文件. 实现将视频文件yuv格式保存的图片格式的測试,图像格式png,jpg, gif等等測试均O ...
- 【转载】Windows下VSCode编译调试c/c++
懒得自己配置或自己配置出现不明问题的朋友可以点这里: [VSCode]Windows下VSCode便携式c/c++环境 http://blog.csdn.net/c_duoduo/article/de ...
- ffmpeg windows下编译ffmpeg
windows下编译ffmpeg 今天由于工作需求需重新编译ffmpeg,百度,goole了一大堆,看眼花缭乱的,但几乎都是三种方案,大部分都是直接转发,一字不漏,错误的缺文件的还是照转,可是问题都大 ...
- (转载)Windows下手动完全卸载Oracle
使用Oracle自带的Universal Installer卸载存在问题: 不干净,不完全,还有一些注册表残留,会影响到后来的安装. 所以,推荐使用手工卸载Oracle. 1.[win+R]-> ...
- [转载]在Windows下搭建Android开发环境
http://jingyan.baidu.com/article/bea41d437a41b6b4c51be6c1.html 在Windows下搭建Android开发环境 | 浏览:30780 | 更 ...
- 转载:Windows下三分钟搭建Shadowoscks服务器端
Windows下三分钟搭建Shadowoscks服务器端 之前在V2EX上有人问为啥没人做个在Windows上一键运行Shadowsocks服务器端的程序,我只想说……这是因为没人关注我的libQtS ...
随机推荐
- BZOJ 5312: 冒险
首先我们考虑,对于And 和 Or 操作,对于操作位上只有And 0 和 Or 1 是有效果的. 我们注意到如果区间内需要改动的操作位上的数字都相同,那么是可以区间取与以及区间取或的. 那其实可以维护 ...
- MySQL主备复制原理、实现及异常处理
复制概述 MySQL支持三种复制方式:基于行(Row)的复制.基于语句(Statement)的复制和混合类型(Mixed)的复制. 基于语句的复制早在3.23版本中就存在,而基于行的复制方式在5.1版 ...
- Cnblog页面美化小记
Cnblog页面美化小记 这两天我在网上翻找了许许多多的资料,打开了不计其数的博客,对着\(js\).\(html\).\(css\)等文件删删改改,在浏览器和\(vscode\)间辗转腾挪...总算 ...
- Hibernate常见优化策略
① 制定合理的缓存策略(二级缓存.查询缓存). ② 采用合理的Session管理机制. ③ 尽量使用延迟加载特性. ④ 设定合理的批处理参数. ⑤ 如果可以,选用UUID作为主键生成器. ⑥ 如果可以 ...
- mysql desc esc 基本命令总结
asc 按升序排列desc 按降序排列 下列语句部分是Mssql语句,不可以在access中使用. SQL分类:DDL—数据定义语言(CREATE,ALTER,DROP,DECLARE)DML—数据操 ...
- JDBC插入性能优化对比
今天对Insert进行了性能测试,结果反差很大,平时都是单条插入,虽然性能要求没有那么高,但是突然在项目中,人家给定时间内完成,这就尴尬了. 优化数据库,优化服务器,优化代码,反正通过各种优化提高数据 ...
- 阿里云centOS7.4 nginx: [emerg] "server" directive is not allowed here in /etc/nginx/vhost/xxxxxx.conf:2
里云centOS7.4配置多个站点遇到的问题nginx: [emerg] "server" directive is not allowed here in /etc/nginx/ ...
- 英语每日阅读---3、VOA慢速英语(翻译+字幕+讲解):哈佛大学被控歧视亚裔学生
英语每日阅读---3.VOA慢速英语(翻译+字幕+讲解):哈佛大学被控歧视亚裔学生 一.总结 一句话总结:Harvard Accused of Discriminating Against Asian ...
- Spring3: 在Bean定义中使用EL-表达式语言
5.4.1 xml风格的配置 SpEL支持在Bean定义时注入,默认使用“#{SpEL表达式}”表示,其中“#root”根对象默认可以认为是ApplicationContext,只有Applicat ...
- Load事件
Load事件 在 窗体完全呈现之后 被 触发 如下伪代码: void ShowWindows { .....//显示父容器 .....//显示子容器 .....//显示控件 //至此,窗体完全呈现 ...