ffmpeg Windows下采集攝像頭一幀數據,并保存為bmp圖片 2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀 睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接 這里請注意,在編譯ffmpeg時,不要使用--disable-devices選項。 使用 --enable-encoder=rawvideo --enable-decoder=rawvideo 啟用rawvideo codec。 代碼如下: [cpp] view plaincopyprint? #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; } RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成