博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
在Visual Studio 2010[VC++]中使用ffmpeg类库
阅读量:4973 次
发布时间:2019-06-12

本文共 6336 字,大约阅读时间需要 21 分钟。

1,准备工作

很多播放器都使用了ffmpeg这个类库来编解码,使用没有关系,但总是有些人不守规则。在上我看到了腾讯(QQPlayer),还有另一家深圳的公司。

我对GPL协议也不太了解,中显示QQPlayer需要提供完整项目代码。我的疑问是:

如果是QQPlayer。其中集成了QQ的一些登陆模块,但这些代码不方便公开。但Player相关的代码已经公开。这样违反GPL吗?

NOTE:下文中DLL或LIB(大写指文件即avcodec.dll,avcodec.lib.etc.),dll或lib(小写,指目录)。

继上篇之后,我们便可以得到一些LIB和DLL,我们可以使用这些LIB和DLL来使用ffmpeg的相关功能函数。

其中头文件在include目录下,LIB及DLL在bin目录下。其实这些LIB并不是传统的静态库文件(真正的静态库文件是在lib目录下的*.a文件),他们是dll的导出文件。

 

另外,C99中添加了几个新的头文件,VC++中没有,所以需要你自己。并放至。对于VS2010来说通常是:C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include。

 

2,示例代码

网上的ffmpeg的示例代码大多过时了,在2009年初了,所以可能你从网上找到的示例代码并不可以运行(但代码运作原理还是一样的)。

我这里贴出一份当前可以运行的代码。

// ffmpeg-example.cpp : Defines the entry point for the console application.//#include "stdafx.h"#define inline _inline#ifndef INT64_C#define INT64_C(c) (c ## LL)#define UINT64_C(c) (c ## ULL)#endif#ifdef __cplusplusextern "C" {#endif	/*Include ffmpeg header file*/#include 
#include
#include
#ifdef __cplusplus}#endif#include
static void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame);int main (int argc, const char * argv[]){ AVFormatContext *pFormatCtx; int i, videoStream; AVCodecContext *pCodecCtx; AVCodec *pCodec; AVFrame *pFrame; AVFrame *pFrameRGB; AVPacket packet; int frameFinished; int numBytes; uint8_t *buffer; // Register all formats and codecs av_register_all(); // Open video file if(av_open_input_file(&pFormatCtx, argv[1], NULL, 0, NULL)!=0) return -1; // Couldn't open file // Retrieve stream information if(av_find_stream_info(pFormatCtx)<0) return -1; // Couldn't find stream information // Dump information about file onto standard error dump_format(pFormatCtx, 0, argv[1], false); // Find the first video stream videoStream=-1; for(i=0; i
nb_streams; i++) if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) { videoStream=i; break; } if(videoStream==-1) return -1; // Didn't find a video stream // Get a pointer to the codec context for the video stream pCodecCtx=pFormatCtx->streams[videoStream]->codec; // Find the decoder for the video stream pCodec=avcodec_find_decoder(pCodecCtx->codec_id); if(pCodec==NULL) return -1; // Codec not found // Open codec if(avcodec_open(pCodecCtx, pCodec)<0) return -1; // Could not open codec // Hack to correct wrong frame rates that seem to be generated by some codecs if(pCodecCtx->time_base.num>1000 && pCodecCtx->time_base.den==1) pCodecCtx->time_base.den=1000; // Allocate video frame pFrame=avcodec_alloc_frame(); // Allocate an AVFrame structure pFrameRGB=avcodec_alloc_frame(); if(pFrameRGB==NULL) return -1; // Determine required buffer size and allocate buffer numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height); //buffer=malloc(numBytes); buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t)); // Assign appropriate parts of buffer to image planes in pFrameRGB avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height); // Read frames and save first five frames to disk i=0; while(av_read_frame(pFormatCtx, &packet)>=0) { // Is this a packet from the video stream? if(packet.stream_index==videoStream) { // Decode video frame avcodec_decode_video(pCodecCtx, pFrame, &frameFinished, packet.data, packet.size); // Did we get a video frame? if(frameFinished) { static struct SwsContext *img_convert_ctx;#if 0 // Older removed code // Convert the image from its native format to RGB swscale img_convert((AVPicture *)pFrameRGB, PIX_FMT_RGB24, (AVPicture*)pFrame, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height); // function template, for reference int sws_scale(struct SwsContext *context, uint8_t* src[], int srcStride[], int srcSliceY, int srcSliceH, uint8_t* dst[], int dstStride[]);#endif // Convert the image into YUV format that SDL uses if(img_convert_ctx == NULL) { int w = pCodecCtx->width; int h = pCodecCtx->height; img_convert_ctx = sws_getContext(w, h, pCodecCtx->pix_fmt, w, h, PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL); if(img_convert_ctx == NULL) { fprintf(stderr, "Cannot initialize the conversion context!\n"); exit(1); } } int ret = sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);#if 0 // this use to be true, as of 1/2009, but apparently it is no longer true in 3/2009 if(ret) { fprintf(stderr, "SWS_Scale failed [%d]!\n", ret); exit(-1); }#endif // Save the frame to disk if(i++<=5) SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height, i); } } // Free the packet that was allocated by av_read_frame av_free_packet(&packet); } // Free the RGB image //free(buffer); av_free(buffer); av_free(pFrameRGB); // Free the YUV frame av_free(pFrame); // Close the codec avcodec_close(pCodecCtx); // Close the video file av_close_input_file(pFormatCtx); return 0;}static void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame){ FILE *pFile; char szFilename[32]; int y; // Open file sprintf(szFilename, "frame%d.ppm", iFrame); pFile=fopen(szFilename, "wb"); if(pFile==NULL) return; // Write header fprintf(pFile, "P6\n%d %d\n255\n", width, height); // Write pixel data for(y=0; y
data[0]+y*pFrame->linesize[0], 1, width*3, pFile); // Close file fclose(pFile);}

 

显示代码中有几个地方需要注意一下。就是开头的宏定义部分。第一个是C99中添加了inline关键字,第二个是对ffmpeg头文件中INT64_C的模拟(可能也是为了解决与C99的兼容问题)。第三个是使用extern C在C++代码中使用C的头文件。

 

3,设置Visual Studio

在你编译,调用上面的代码之前你还要在Visual Stuido中做相应的设置,才可以正确引用ffmpeg的库。

3.1 设置ffmpeg头文件位置

右击项目->属性,添加Include文件目录位置:

 

3.2 设置LIB文件位置

 

3.3 设置所引用的LIB文件

 

如果一切正常,这时你便可以编译成功。

 

4,可能出现的问题

4.1 运行时出错

虽然你可以成功编译,但你F5,调试时会出现以下错误。

原因是,你虽然引用了LIB文件,但这并不是真正的静态库文件,而是对DLL的引用,所以当你调用ffmpeg库函数时,需要DLL文件在场。你可以用(VS自带工具)来查看你生成的exe中引用了哪些DLL文件。你在命令行输入:

>dumpbin ffmpeg-example.exe /imports

你可以从输出中看出你实际引用以下几个的DLL文件。

avcodec-52.dll

avformat-52.dll
swscale-0.dll
avutil-50.dll

 

还有些朋友可能想将ffmpeg库进行静态引用,这样就不需要这些DLL文件了。这样做是可行的,但是的。

 

4.2 av_open_input_file失败

在VS的Command Argumetns中使用全路径。

转载于:https://www.cnblogs.com/Jerry-Chou/archive/2011/03/31/2000761.html

你可能感兴趣的文章
使用Analyze 和Instruments-Leaks分析解决iOS内存泄露
查看>>
Vue.js的入门
查看>>
【自定义异常】
查看>>
pip install 后 importError no module named "*"
查看>>
一些疑惑
查看>>
Codeforces Round #413 A. Carrot Cakes
查看>>
Linux(Ubuntu16.04)下添加新用户
查看>>
Windows c++应用程序通用日志组件(组件及测试程序下载)
查看>>
openstack dpdk
查看>>
springmvc跳转方式
查看>>
Linux安装Redis
查看>>
IOS 第三方管理库管理 CocoaPods
查看>>
背景色渐变(兼容各浏览器)
查看>>
Redis中7种集合类型应用场景
查看>>
MariaDB 和 MySQL 比较
查看>>
MYSQL: 1292 - Truncated incorrect DOUBLE value: '184B3C0A-C411-47F7-BE45-CE7C0818F420'
查看>>
Java JPA @Transient 在Hibernate中应用
查看>>
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
查看>>
springMVC Controller 参数映射
查看>>
JDK1.8源码分析02之阅读源码顺序
查看>>