1,准备工作

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

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

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

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

继上篇在MinGW中编译ffmpeg之后,我们便可以得到一些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年初img_convert这个函数被sws_scale取代了,所以可能你从网上找到的示例代码并不可以运行(但代码运作原理还是一样的)。

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

// 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 __cplusplus
extern "C" {
#endif/*Include ffmpeg header file*/
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
#ifdef __cplusplus
}
#endif#include <stdio.h>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 codecsav_register_all();// Open video fileif(av_open_input_file(&pFormatCtx, argv[1], NULL, 0, NULL)!=0)return -1; // Couldn't open file// Retrieve stream informationif(av_find_stream_info(pFormatCtx)<0)return -1; // Couldn't find stream information// Dump information about file onto standard errordump_format(pFormatCtx, 0, argv[1], false);// Find the first video streamvideoStream=-1;for(i=0; i<pFormatCtx->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 streampCodecCtx=pFormatCtx->streams[videoStream]->codec;// Find the decoder for the video streampCodec=avcodec_find_decoder(pCodecCtx->codec_id);if(pCodec==NULL)return -1; // Codec not found// Open codecif(avcodec_open(pCodecCtx, pCodec)<0)return -1; // Could not open codec// Hack to correct wrong frame rates that seem to be generated by some codecsif(pCodecCtx->time_base.num>1000 && pCodecCtx->time_base.den==1)pCodecCtx->time_base.den=1000;// Allocate video framepFrame=avcodec_alloc_frame();// Allocate an AVFrame structurepFrameRGB=avcodec_alloc_frame();if(pFrameRGB==NULL)return -1;// Determine required buffer size and allocate buffernumBytes=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 pFrameRGBavpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24,pCodecCtx->width, pCodecCtx->height);// Read frames and save first five frames to diski=0;while(av_read_frame(pFormatCtx, &packet)>=0){// Is this a packet from the video stream?if(packet.stream_index==videoStream){// Decode video frameavcodec_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 swscaleimg_convert((AVPicture *)pFrameRGB, PIX_FMT_RGB24, (AVPicture*)pFrame, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);// function template, for referenceint 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 usesif(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/2009if(ret) {fprintf(stderr, "SWS_Scale failed [%d]!\n", ret);exit(-1);}
#endif// Save the frame to diskif(i++<=5)SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height, i);}}// Free the packet that was allocated by av_read_frameav_free_packet(&packet);}// Free the RGB image//free(buffer);av_free(buffer);av_free(pFrameRGB);// Free the YUV frameav_free(pFrame);// Close the codecavcodec_close(pCodecCtx);// Close the video fileav_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 filesprintf(szFilename, "frame%d.ppm", iFrame);pFile=fopen(szFilename, "wb");if(pFile==NULL)return;// Write headerfprintf(pFile, "P6\n%d %d\n255\n", width, height);// Write pixel datafor(y=0; y<height; y++)fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width*3, pFile);// Close filefclose(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文件在场。你可以用dumpbin(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

在Visual Studio 2010[VC++]中使用ffmpeg类库相关推荐

  1. 软件测试msf模型,Visual Studio 2010 Ultimate中MSF过程模型的设计

    Visual Studio 2010 Ultimate中MSF过程模型的设计 发表于:2010-04-06来源:作者:点击数: 过程模型是 软件工程 学中的一部分,就好比我们用什么过程方法进行软件&q ...

  2. 在Visual Studio 2010/2012中 找不到创建WebService的项目模板

    参考文章: http://blog.sina.com.cn/s/blog_6d545999010152wb.html 在 Visual Studio 2010 或者2012的新建 Web 应用程序或者 ...

  3. Visual Studio 2010中C++项目升级指南

    如何升级? Visual Studio 2010支持来自VC6.Visual Studio 2002.Visual Studio 2003.Visual Studio 2005和Visual Stud ...

  4. Visual Studio 2010 项目属性配置

    Visual Studio 2010使用方案管理项目,一个解决方案下可包含多个项目. 默认情况下,项目属性的设置的目录起点为项目配置文件所在的位置,实际上就是项目头文件和源文件所在的位置.Visual ...

  5. Visual Studio 2010 Ultimate测试体系结构

    VS2010测试概述<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&g ...

  6. Visual Studio 2010 Ultimate敏捷功能特性(上)

    随着软件开发日趋国际化,对软件的质量要求和管理也随之增高.微软看到了应用程序生命周期管理在业界逐渐被接受认可的趋势,并宣称VSTS2010将会是一个革命性的.Net软件开发以及管理工具的产品,预计在2 ...

  7. Visual Studio 2010 Ultimate敏捷之道:特性解析

    随着软件开发日趋国际化,对软件的质量要求和管理也随之增高.微软看到了应用程序生命周期管理在业界逐渐被接受认可的趋势,并宣称VSTS2010将会是一个革命性的.Net软件开发以及管理工具的产品,预计在2 ...

  8. Visual Studio 2010在简洁中强调团队合作

    Visual Studio 2010警告用户Silverlight项目会出现安全风险,并提供了两种项目模式.其次,Visual Studio 2010更加讲求团队精神.   开发更具有强大功能与简洁的 ...

  9. 在Visual Studio 2010中创建多项目(解决方案)模板【三】

    前文回顾: 在Visual Studio 2010中创建多项目(解决方案)模板[一]:多项目解决方案模板的创建 在Visual Studio 2010中创建多项目(解决方案)模板[二]:Templat ...

最新文章

  1. if null 锁 java_史上最全 Java 中各种锁的介绍
  2. python【力扣LeetCode算法题库】面试题62- 圆圈中最后剩下的数字(约瑟夫环)
  3. http / 关于长连接和短链接的理解
  4. c++深拷贝和浅拷贝的区别?
  5. 摩尔投票法(力扣- -229. 求众数 II)
  6. 【51Nod - 1001 】 数组中和等于K的数对 (排序+ 尺取)
  7. 乖乖,腾讯天美研发20万月薪刷爆朋友圈,网友:小丑竟是我自己
  8. qml 信号槽第二次才响应_QML中各种代理的用法
  9. 苹果邮箱 android设置字体,苹果6邮件怎么设置qq邮箱怎么设置几号字体
  10. Android通讯录程序设计报告,Android个人通讯录课程设计报告.doc
  11. SPI FLASH与NOR FLASH的区别
  12. 【杂】Excel中匹配筛选操作VLOOKUP 函数使用问题排查
  13. 【跨境电商】EDM邮件营销完整指南(二):如何开展EDM营销活动
  14. 做直播|流量大时需要CDN加速
  15. 用latex的tikz宏包mindmap包绘制mindmap
  16. 导弹发射-河南省第九届省赛D题
  17. 大众创业热度不减,好机友项目强势来袭
  18. 第三篇 考研这一年
  19. Php设计模式之【适配器模式 Adapter Pattern】
  20. 计算机丢s7aregsx.dll,打开STEP7 显示:S7aregsx.dll 文件丢失-工业支持中心-西门子中国...

热门文章

  1. 反射(reflection)基础
  2. 【html5】纯css实现圆圈中显示居中文字效果
  3. ​编码的未来是“无码”?
  4. 用PL/SQL语言编写一程序,实现按部门分段(6000以上、(6000,3000)、3000元以下)统计各工资段的职工人数、以及各部门的工资总额(工资总额中不包括奖金)
  5. 计算机专业硕士论文评语,硕士论文答辩导师评语
  6. 程矢Axure夜话:程序员眼中的原型设计视频教程之书到用时方恨少
  7. You computer needs to restart to complete your Nahimic 3 installation.Do you want to restart now?
  8. android 蓝牙编程基础,​Android 蓝牙编程的基本步骤
  9. 移通创联 Modbus转Profinet网关将丹佛斯变频器接入西门子1200PLC配置案例
  10. 华为交换机的软件升级方法,很实用