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

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

使用

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

启用rawvideo codec。

代码如下:

  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. }  

上一篇:自己写jquery.lazyloading图片延迟加载插件,通用


下一篇:最简单的基于JavaEE和FFmpeg的视频网站