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

简介: 这里请注意,在编译ffmpeg时,不要使用--disable-devices选项。 使用 --enable-encoder=rawvideo --enable-decoder=rawvideo 启用rawvideo codec。

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

使用

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

启用rawvideo codec。

代码如下:

[cpp]   view plain copy print ?
  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. }  

目录
相关文章
|
计算机视觉 Windows Python
windows下使用python + opencv读取含有中文路径的图片 和 把图片数据保存到含有中文的路径下
在Windows系统中,直接使用`cv2.imread()`和`cv2.imwrite()`处理含中文路径的图像文件时会遇到问题。读取时会返回空数据,保存时则无法正确保存至目标目录。为解决这些问题,可以使用`cv2.imdecode()`结合`np.fromfile()`来读取图像,并使用`cv2.imencode()`结合`tofile()`方法来保存图像至含中文的路径。这种方法有效避免了路径编码问题,确保图像处理流程顺畅进行。
1323 1
|
10月前
|
数据库 数据安全/隐私保护 Windows
Windows远程桌面出现CredSSP加密数据修正问题解决方案
【10月更文挑战第30天】本文介绍了两种解决Windows系统凭据分配问题的方法。方案一是通过组策略编辑器(gpedit.msc)启用“加密数据库修正”并将其保护级别设为“易受攻击”。方案二是通过注册表编辑器(regedit)在指定路径下创建或修改名为“AllowEncryptionOracle”的DWORD值,并将其数值设为2。
8842 3
|
9月前
|
存储 缓存 安全
硬盘数据恢复:恢复硬盘数据的9个实用方法(Windows版)
无论是工作文档、家庭照片,还是其他珍贵的数字资产,数据丢失总是一件让人头疼的事情。然而,当硬盘发生问题时,不必过于慌张——只要正确应对,许多数据都可以被成功恢复。本文将从常见数据丢失原因到具体恢复方法,为您提供全面的硬盘数据恢复指导。
|
11月前
|
Java 数据安全/隐私保护
Java ffmpeg 实现视频加文字/图片水印功能
【10月更文挑战第22天】在 Java 中使用 FFmpeg 实现视频加文字或图片水印功能,需先安装 FFmpeg 并添加依赖(如 JavaCV)。通过构建 FFmpeg 命令行参数,使用 `drawtext` 滤镜添加文字水印,或使用 `overlay` 滤镜添加图片水印。示例代码展示了如何使用 JavaCV 实现文字水印。
915 1
|
缓存 NoSQL Linux
【Azure Redis 缓存】Windows和Linux系统本地安装Redis, 加载dump.rdb中数据以及通过AOF日志文件追加数据
【Azure Redis 缓存】Windows和Linux系统本地安装Redis, 加载dump.rdb中数据以及通过AOF日志文件追加数据
256 1
【Azure Redis 缓存】Windows和Linux系统本地安装Redis, 加载dump.rdb中数据以及通过AOF日志文件追加数据
|
Web App开发 存储 安全
微软警告数百万Windows用户:切勿冒险丢失所有数据
微软警告数百万Windows用户:切勿冒险丢失所有数据
微软警告数百万Windows用户:切勿冒险丢失所有数据
|
数据采集 大数据 Python
FFmpeg 在爬虫中的应用案例:流数据解码详解
在大数据背景下,网络爬虫与FFmpeg结合,高效采集小红书短视频。需准备FFmpeg、Python及库如Requests和BeautifulSoup。通过设置User-Agent、Cookie及代理IP增强隐蔽性,解析HTML提取视频链接,利用FFmpeg下载并解码视频流。示例代码展示完整流程,强调代理IP对避免封禁的关键作用,助你掌握视频数据采集技巧。
260 7
FFmpeg 在爬虫中的应用案例:流数据解码详解
|
Linux Apache C++
FFmpeg开发笔记(三十五)Windows环境给FFmpeg集成libsrt
该文介绍了如何在Windows环境下为FFmpeg集成SRT协议支持库libsrt。首先,需要安装Perl和Nasm,然后编译OpenSSL。接着,下载libsrt源码并使用CMake配置,生成VS工程并编译生成srt.dll和srt.lib。最后,将编译出的库文件和头文件按照特定目录结构放置,并更新环境变量,重新配置启用libsrt的FFmpeg并进行编译安装。该过程有助于优化直播推流的性能,减少卡顿问题。
331 2
FFmpeg开发笔记(三十五)Windows环境给FFmpeg集成libsrt
|
编解码 开发工具 Android开发
Windows平台RTMP推送|轻量级RTSP服务如何实现摄像头叠加到屏幕输出
大牛直播SDK采用先进的图层概念实现视频叠加,如将摄像头画面实时叠加到屏幕输出,以C#为例展示了具体的配置方法。用户可在推送RTMP或启动RTSP服务前选择“摄像头叠加到屏幕”的选项,并调整位置。SDK还支持摄像头的开启与关闭、水平垂直翻转及旋转等功能。此外,该SDK提供了丰富的特性,包括但不限于视频和音频采集处理、硬编码与软编码支持、多实例推送、水印添加、网络适应性调整等,几乎涵盖了RTMP推送的所有常规需求,并能与播放器协同工作达到毫秒级的低延迟,非常适合无纸化同屏、智慧教室等应用场景。
199 4
|
开发工具 数据安全/隐私保护 开发者
Windows平台RTMP推送|轻量级RTSP服务摄像头如何添加动态文字水印
本文介绍了在Windows平台上实现摄像头或屏幕流中动态文字水印的技术方法。通过大牛直播SDK示例,展示了如何从文本获取RGB数据,并将其叠加到视频流上。文中提供了代码片段来说明如何开启文字水印、生成包含实时信息的位图、以及如何更新和控制图层。最终实现了动态显示时间和位置信息的需求。对这一领域的开发者而言,本文提供了实用的参考与指导。
254 2