[转载] ffmpeg Windows下采集摄像头一帧数据,并保存为bmp图片
2016-07-26 10:52
375 查看
这里请注意,在编译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、ffplay, 音视频、流媒体
使用
--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、ffplay, 音视频、流媒体
相关文章推荐
- 前清时期坐过堂
- 从DLL返回字符串数组
- 修改 crontab默认编辑器nano为Vi
- 创建maven的web项目
- PHP进阶(三)——字符串
- 顺序表应用3:元素位置互换之移位算法
- Ubuntu16.04安装串口调试工具gtkterm
- Cookie和session区别
- centos系统出现Read-only file system的解决方案
- ScrollerView中嵌套多个ListView,ListView都展示出
- 正则表达式转义字符
- 动态工厂模式---(3)
- 【WebService】带你走进webservice的世界
- 代码重构——程序员应有的基因
- 各LaunchMode的使用场景
- CodeForces 289B Polo the Penguin and Matrix (贪心)
- 十分钟玩转 jQuery、实例大全
- SecureCRT 实用配置
- POJ-2677 Tour(双调欧几里得旅行商问题)(动态规划)
- Batch Normalization & Layer Normalization