其实研究这个的目的主要是今后给Java项目使用。好久没看C了,公司业务大部分都是编解码视频的,带着一股冲动研究了一下。懂得了一点皮毛。
首先下载ffmpeg的开发包以及依赖包,当然也可以下载源码。
http://ffmpeg.zeranoe.com/builds/
其次为了编码为JPEG格式的图片,需要下载Independent JPEG Group
http://www.ijg.org/files/jpegsr9.zip
下载IJG后,需要对源码进行编译,生成静态库,
本人是使用VS2010编译的,其中含有install.txt文件讲述了怎么讲make file文件转换为VS工程文件,使用下面命令可以做到:
NMAKE /f makefile.vc setup-v10
其中会遇到windows环境变量中没有NMAKE 的问题,还有Win32.Mak找不到的问题。
1、找到nmake.exe配一下环境变量
2、在makefile.vc文件中找到Win32.Mak,将相应路径添加上,如:
!include <C:\Program Files\Microsoft SDKs\Windows\v7.0A\Include\Win32.Mak>
#include <math.h> #include <windows.h> #include <libavutil/opt.h> #include <libavcodec/avcodec.h> #include <libavutil/channel_layout.h> #include <libavutil/common.h> #include <libavutil/imgutils.h> #include <libavutil/mathematics.h> #include <libavutil/samplefmt.h> #include <libavformat/avformat.h> #include <libswscale/swscale.h> #include <jpeglib.h> #include <setjmp.h> #define inline __inline #define snprintf _snprintf #define INBUF_SIZE 4096 #define AUDIO_INBUF_SIZE 20480 #define AUDIO_REFILL_THRESH 4096 #pragma comment (lib, "Ws2_32.lib") #pragma comment (lib, "avcodec.lib") #pragma comment (lib, "avdevice.lib") #pragma comment (lib, "avfilter.lib") #pragma comment (lib, "avformat.lib") #pragma comment (lib, "avutil.lib") #pragma comment (lib, "swresample.lib") #pragma comment (lib, "swscale.lib") #pragma comment(lib, "jpeg.lib") static void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame); static void yuv420p_save(AVFrame *pFrame, int width, int height, int iFrame); static void bmp_save(AVFrame *pFrame, int width, int height, int iFrame); static void saveFrame_jpg(uint8_t *pRGBBuffer, int iFrame, int width, int height); int main(int argc, char **argv) { AVFormatContext *pFormatCtx = NULL; char *fileName = "E:\\aa.rm"; int i,videoStream; AVCodecContext *pCodecCtx; AVCodec *pCodec; AVFrame *pFrame; AVFrame *pFrameRGB; int numBytes; uint8_t *buffer; AVPacket packet; int frameFinished; struct SwsContext *img_convert_ctx = NULL; av_register_all(); if(avformat_open_input(&pFormatCtx, fileName, NULL, NULL)!=0) { printf("can not open"); return -1; } if(avformat_find_stream_info(pFormatCtx, NULL) < 0) { printf("can not find"); return -1; } av_dump_format(pFormatCtx, -1, fileName, 0); videoStream = -1; for (i=0;i<pFormatCtx->nb_streams;i++) { if( pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { videoStream = i; break; } } if ( videoStream == -1 ) { printf("not find videoStream"); return -1; } pCodecCtx = pFormatCtx->streams[videoStream]->codec; pCodec = avcodec_find_decoder(pCodecCtx->codec_id); if ( pCodec == NULL ) { return -1; } if( avcodec_open2(pCodecCtx, pCodec, NULL) < 0 ) { return -1; } pFrame = av_frame_alloc(); if( pFrame == NULL ) { return -1; } pFrameRGB = av_frame_alloc(); if( pFrameRGB == NULL ) { return -1; } numBytes = avpicture_get_size(PIX_FMT_BGR24, pCodecCtx->width, pCodecCtx->height); buffer = av_malloc(numBytes); avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_BGR24, pCodecCtx->width, pCodecCtx->height); img_convert_ctx = sws_getCachedContext(img_convert_ctx, pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL); i = 0; while( av_read_frame(pFormatCtx, &packet) >= 0 ) { if( packet.stream_index == videoStream ) { avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet); if ( frameFinished ) { if (!img_convert_ctx ) { fprintf(stderr, "Cannot initialize sws conversion context\n"); exit(1); } sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize); if(i++<5) { //SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height, i); //yuv420p_save(pFrameRGB, pCodecCtx->width, pCodecCtx->height, i); //bmp_save(pFrameRGB, pCodecCtx->width, pCodecCtx->height, i); saveFrame_jpg(pFrameRGB->data[0], i, pCodecCtx->width, pCodecCtx->height); } } } if(i > 5) { break; } } av_free_packet(&packet); av_free(buffer); av_free(pFrame); av_free(pFrameRGB); avcodec_close(pCodecCtx); avformat_close_input(&pFormatCtx); return 0; } static void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame) { FILE *pFile; char szFilename[32]; int y; sprintf(szFilename, "frame%d.jpg", iFrame); pFile = fopen(szFilename, "wb"); if( !pFile ) { return; } fprintf(pFile, "P6\n%d %d\n255\n", width, height); for ( y=0; y<height; y++ ) { fwrite(pFrame->data[0] + y * pFrame->linesize[0], 1, width * 3, pFile); } fclose(pFile); } static void yuv420p_save(AVFrame *pFrame, int width, int height, int iFrame) { int i = 0; FILE *pFile; char szFilename[32]; int height_half = height / 2, width_half = width / 2; int y_wrap = pFrame->linesize[0]; int u_wrap = pFrame->linesize[1]; int v_wrap = pFrame->linesize[2]; unsigned char *y_buf = pFrame->data[0]; unsigned char *u_buf = pFrame->data[1]; unsigned char *v_buf = pFrame->data[2]; sprintf(szFilename, "frame%d.jpg", iFrame); pFile = fopen(szFilename, "wb"); //save y for (i = 0; i < height; i++) fwrite(y_buf + i * y_wrap, 1, width, pFile); fprintf(stderr, "===>save Y success\n"); //save u for (i = 0; i < height_half; i++) fwrite(u_buf + i * u_wrap, 1, width_half, pFile); fprintf(stderr, "===>save U success\n"); //save v for (i = 0; i < height_half; i++) fwrite(v_buf + i * v_wrap, 1, width_half, pFile); fprintf(stderr, "===>save V success\n"); fflush(pFile); fclose(pFile); } static void bmp_save(AVFrame *pFrame, int width, int height, int iFrame) { BITMAPFILEHEADER bmpheader; BITMAPINFO bmpinfo; int y = 0; FILE *pFile; char szFilename[32]; unsigned char *y_buf = pFrame->data[0]; sprintf(szFilename, "frame%d.bmp", iFrame); pFile = fopen(szFilename, "wb"); bmpheader.bfReserved1 = 0; bmpheader.bfReserved2 = 0; bmpheader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); bmpheader.bfSize = bmpheader.bfOffBits + width*height*24/8; bmpinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmpinfo.bmiHeader.biWidth = width; bmpinfo.bmiHeader.biHeight = -height; bmpinfo.bmiHeader.biPlanes = 1; bmpinfo.bmiHeader.biBitCount = 24; 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, pFile); fwrite(&bmpinfo.bmiHeader, sizeof(BITMAPINFOHEADER), 1, pFile); fwrite(pFrame->data[0], width*height*24/8, 1, pFile); /*for(y=0; y<height; y++) { fwrite(pFrame->data[0] + y*pFrame->linesize[0], 1, width*3, pFile); }*/ //fflush(pFile); fclose(pFile); } static void saveFrame_jpg(uint8_t *pRGBBuffer, int iFrame, int width, int height) { struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; char szFilename[1024]; int row_stride; FILE *fp; JSAMPROW row_pointer[1]; // 一行位图 cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); sprintf(szFilename, "test%d.jpg", iFrame);//图片名字为视频名+号码 fp = fopen(szFilename, "wb"); if(fp == NULL) return; jpeg_stdio_dest(&cinfo, fp); cinfo.image_width = width; // 为图的宽和高,单位为像素 cinfo.image_height = height; cinfo.input_components = 3; // 在此为1,表示灰度图, 如果是彩色位图,则为3 cinfo.in_color_space = JCS_RGB; //JCS_GRAYSCALE表示灰度图,JCS_RGB表示彩色图像 jpeg_set_defaults(&cinfo); jpeg_set_quality (&cinfo, 80, 1); jpeg_start_compress(&cinfo, TRUE); row_stride = cinfo.image_width * 3;//每一行的字节数,如果不是索引图,此处需要乘以3 // 对每一行进行压缩 while (cinfo.next_scanline < cinfo.image_height) { row_pointer[0] = &(pRGBBuffer[cinfo.next_scanline * row_stride]); jpeg_write_scanlines(&cinfo, row_pointer, 1); } jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); fclose(fp); }
最后,将相应的lib和dll给链接上,以及头文件给添加好,应该没问题。
后续思考方向为如何添加自己的解码器,比如海康大华的SDK接入,封装dll给Java调用,希望更上一层楼吧。
相关推荐
使用ffmpeg库把mp4视频文件保存为一帧一帧的JPG格式图片
本源码是ffmpeg转换视频,编译环境为vs2017,如需要转换其他格式视频填写对应的视频格式的编码格式【-f image2 -i c:\temp\d.jpg -vcodec libx264 test.mp4】,支持的图片格式为jpg,bmp,tiff等等。请注意对应的...
本源码是ffmpeg转换视频,编译环境为vs2017,如需要转换其他格式视频填写对应的视频格式的编码格式【-f image2 -i c:\temp\d.jpg -vcodec libx264 test.mp4】,支持的图片格式为jpg,bmp,tiff等等。请注意对应的...
Qt工程,ffmpeg库和h264测试文件。纯原创,仅供交流学习。
ffmpeg -framerate 0.05 -f image2 -loop 1 -y -i d:/img/img%d.jpg -i d:/img/gyz.mp3 -s 1080*1920 -r 25 -t 100 d:/img/output.mp4 -framerate 速率,越小每张图片停留时间越长 -loop 循环一遍文件夹内的图片 -i ...
2018/03/12 21:03 391 视频中截帧变jpg指定分辨率.bat 2018/03/12 21:19 541 视频批量转换jpeg15秒开始抽取15帧.bat 2018/03/12 21:23 583 视频批量转换jpeg只抽取5秒从5秒开始-5张图.bat 2018/03/12 20:55 420 视频...
该软件是一款完全免费的视频封面制作工具,可以一键导出视频中的画面作为封面。 另存为(jpg格式),不限制数量,只要...操作非常简单,只需要你拖拽文件夹或者文件到列表即可。 支持主流视频格式(mp4,avi,mov)等。
调用ffmpeg.exe进程,获取视频截屏文件:选择文件夹,将文件夹中所有视频的第一帧图片保存为同名图片(jpg)。
C++源码,可以很方便的把视频文件转为图片集。利用ffmpeg将获取到的视频帧转换为jpg格式的图片,jpg格式的图片用到了libjpeg的库。具体:https://blog.csdn.net/rootusers/article/details/43272641
ffmpeg+sdl 播放视频文件并将获取的每一帧视频保存为bmp和jpg格式文件
/* avi2jpg 函数,将摄像头当前帧保存为jpg格式照片 */ void Video_to_image(CvCapture* capture) { //初始化一个视频文件捕捉器 //CvCapture* capture = cvCaptureFromAVI(filename); //获取视频信息 ...
拍照使用ffmpeg将RTSP流转换为jpeg / png的脚本。 基本上是什么。 php文件中包含node.js脚本,供Web服务器查看转换后的图像。 注意:这需要一个node.js依赖项:image-plucker(所以npm install image-plucker)。 这...
ffmpeg框架提取器
如下所示: ffmpeg中文文档:...-f fmt 强迫采用格式fmt -I filename 输入文件 -y 覆盖输出文件 -t duration 设置纪录时间 hh:mm:ss[.xxx]格式的记录时间也支持 -ss position 搜索到指定的时间 [-]hh:mm
下面的是数据文件: ---------------------------------------------------------...c#调用百度api生成语音文件,再根据语音文件的长度生成图片帧,最后调用ffmpeg生成视频。 vs2013项目,配置好ffmpeg,即可运行。。。
FFmpegify ... 安装FFmpeg并确保它可用于命令行(即添加到PATH环境变量中) 使用pip install -r requirements.txt安装必要的python库 调整“ ffmpegify.reg”中的条目,以指向正确的Python安装位置和FFmpe
此项目是 H264/H265 转 Jpeg 的源码,可支持将 H264 或 H265 格式的图片文件转码为 Jpeg 格式的图片文件。 转码流程如下: 解码:将 H264/H265 解码为 YUV。 编码:将 YUV 编码为 Jpeg。 项目结构 项目结构如下: in...
输出图像在原始视频文件夹中另存为jpg文件。软件功能特性 无损地修剪或剪切视频/音频的一部分 任意文件的无损合并/串联(相同的编解码器参数) 无损流编辑:组合来自多个文件的任意轨道 无损提取文件中的所有曲目 ...
java实现可以获取视频中某一帧的图片,并将图片保存至本地,自定义设置截取图片的宽度和高度,获取视频的总帧数,视频总时长。
这是一个VS2017工程,可以直接编译运行。实现了利用OpenCV来实时播放RTSP视频流,并能过够截取图片保存为文件。为了不影响RTSP视频流的获取与播放,图片的保存在另一个线程里实现。