zoukankan      html  css  js  c++  java
  • 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 != '')  
    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 == '' || *s2 == '')  
    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. ");  
    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. ");  
    114.         return -2;  
    115.     }  
    116.     printf("input device no. is %d ",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. ");  
    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 ",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. }  

  • 相关阅读:
    Python代写使用矩阵分解法找到类似的音乐
    (转)语义分析透镜洞察婚庆微博用户行为数据
    (转)虎扑论坛基因探秘:社群用户行为数据洞察
    bzoj 4922: [Lydsy1706月赛]Karp-de-Chant Number 贪心+dp
    bzoj 1110: [POI2007]砝码Odw 贪心
    bzoj 3721: PA2014 Final Bazarek 贪心
    bzoj 2563: 阿狸和桃子的游戏 贪心
    bzoj 3999: [TJOI2015]旅游 LCT
    bzoj 4240: 有趣的家庭菜园 树状数组+贪心
    CF369E Valera and Queries kdtree
  • 原文地址:https://www.cnblogs.com/lidabo/p/3482843.html
Copyright © 2011-2022 走看看