您的位置:首页 > 其它

[转载] 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, 音视频、流媒体
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: