windows下ffmpeg编译成lib、dll与使用ffmpeg制作播放器

来源:互联网 发布:dnf为什么不停网络中断 编辑:程序博客网 时间:2024/05/24 05:26

自己编译ffmpeg的话比较麻烦的还是,可以参考这篇文章。

windows下使用MinGW+msys编译ffmpeg

http://blog.chinaunix.net/uid-20718335-id-2980793.html


实际上我按照这个流程编译了一遍,有些库不全,虽然编译通过了,最终似乎无法使用。

只好引用了ffmpeg项目组的 FFMPEG SDK,我下载的是当前最新的3.2版本。

点击直接下载

对应的FFmpeg SDK开发手册直接下载。


此外还有一份参考资料

英文版:An_ffmpeg_and_SDL_Tutorial

中文版:FFmpeg和SDL


下面大致列举一下我遇到的问题,我的操作系统是Windows 7,,64位旗舰版。

其中第八项faad2、第九项faac、第11、12项目amr-nb和amr-wb编译出了一些问题

直接忽视,最后在编译ffmpeg的时候去掉对应项的enable指令就好了。


之后是集成ffmpeg的功能到自己的播放器上,我是基于MFC的对话框做了一个小小的播放器。

这里记录一点点流程,需要全部工程源码的可以私信我。


引用头文件的方法是这样子,不然最后链接的时候会提示出错

extern "C" {#ifndef INT64_C#define INT64_C#define UINT64_C#endif#include "avcodec.h"#include "avdevice.h"#include "avfilter.h"#include "avformat.h"#include "avutil.h"#include "swscale.h"}

这里我把上面步骤里面最后导出的头文件其实是直接放到了一个目录下面,

大家也可以直接在VS的项目属性(配置属性-> VC++目录->包含目录和库目录)里面增加对应的头文件所在目录,

就可以这么直接包含头文件了。

然后是添加静态库lib文件,方法比较多,我是在.cpp文件里面这么弄:

#pragma comment(lib, "avcodec.lib")#pragma comment(lib, "avdevice.lib")#pragma comment(lib, "avfilter.lib")#pragma comment(lib, "avformat.lib")#pragma comment(lib, "swscale.lib")#pragma comment(lib, "avutil.lib")#pragma comment(lib, "postproc.lib")#pragma comment(lib, "swresample.lib")


然后是对应的bin文件,也就是导出到 local/bin目录下的一些文件,这里我直接拷贝到了项目exe生成目录里面。

给大家看看我的目录结构,如下图:其中FFmpeg-full-sdk-3.2是最开始的那个SDK解压直接得到的。

以下的话我直接对ffmpeg的内容进行了封装,生成了一个类CNcMCodec,类的头文件内容如下:

#ifndef _NC_MEDIA_DECODER_H_#define _NC_MEDIA_DECODER_H_extern "C" {#if 0#ifndef INT64_C#define INT64_C#define UINT64_C#endif#include "libavcodec/avcodec.h"#include "libavdevice/avdevice.h"#include "libavfilter/avfilter.h"#include "libavformat/avformat.h"#include "libavutil/avutil.h"#include "libswscale/swscale.h"#else#include "avcodec.h"#include "avdevice.h"#include "avfilter.h"#include "avformat.h"#include "avutil.h"#include "swscale.h"#endif}class CNcMCodec{protected:AVFormatContext *pFormatCtx;AVCodecContext  *pCodecCtx;AVCodec*pCodec;intvideoStream;AVFrame*pFrame, *pFrameRGB;uint8_t*buffer;DWORDbmfHeaderLen;public:CNcMCodec(void);virtual ~CNcMCodec(void);bool OpenFile(LPCTSTR lpFilePath, BITMAPINFO &bmpInfo);AVPicture * GetNextFrame();};#endif// _NC_MEDIA_DECODER_H_


下面是.cpp的内容。

#include "stdafx.h"#include "NcMCodec.h"// 用于不同类型字符串的转换,宏T2A、A2T等#include <atlconv.h>#pragma comment(lib, "avcodec.lib")#pragma comment(lib, "avdevice.lib")#pragma comment(lib, "avfilter.lib")#pragma comment(lib, "avformat.lib")#pragma comment(lib, "swscale.lib")#pragma comment(lib, "avutil.lib")#pragma comment(lib, "postproc.lib")#pragma comment(lib, "swresample.lib")static void CodecInit(void){static bool bInitialed(false);if ( true == bInitialed )return;av_register_all();}CNcMCodec::CNcMCodec(void){pFormatCtx = NULL;pCodecCtx = NULL;CodecInit();}CNcMCodec::~CNcMCodec(void){}bool CNcMCodec::OpenFile(LPCTSTR lpFilePath, BITMAPINFO &bmpInfo){char path[MAX_PATH];#ifdef _UNICODEUSES_CONVERSION;strcpy_s<MAX_PATH>( path, T2A(lpFilePath) );#elsestrcpy_s<MAX_PATH>( path, lpFilePath );#endifif ( av_open_input_file( &pFormatCtx, path, NULL, 0, NULL  ) )return false;// 文件打开失败if ( av_find_stream_info(pFormatCtx) < 0 )return 0;// 无法找到流信息dump_format( pFormatCtx, 0, path, 0 );size_t i = 0;videoStream = -1;for ( i = 0; i < pFormatCtx->nb_streams; i++ ){if ( pFormatCtx->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO ){videoStream = i;break;}}if ( -1 == videoStream )return false;pCodecCtx = pFormatCtx->streams[videoStream]->codec;pCodec = avcodec_find_decoder( pCodecCtx->codec_id );if ( NULL == pCodec )return false;if ( avcodec_open(pCodecCtx, pCodec) < 0 )return false;// 无法打开解码器pFrame = avcodec_alloc_frame();pFrameRGB = avcodec_alloc_frame();if ( NULL == pFrame )return false;int bytes = avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);buffer = (uint8_t *)av_malloc(bytes * sizeof(uint8_t));avpicture_fill( (AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height );// 设置位图信息头数据BITMAPINFOHEADER &infoHeader(bmpInfo.bmiHeader);infoHeader.biBitCount = 24;infoHeader.biClrImportant = 0;infoHeader.biClrUsed = 0;infoHeader.biCompression = 0;infoHeader.biHeight = 0 - pCodecCtx->height;// 这里要是负数,否则在MFC下面使用stretchBlt显示的图像是倒着的infoHeader.biWidth =  pCodecCtx->width;infoHeader.biPlanes = 1;infoHeader.biSize = 40;infoHeader.biSizeImage = 0; infoHeader.biXPelsPerMeter = 0;infoHeader.biYPelsPerMeter = 0;return true;}AVPicture * CNcMCodec::GetNextFrame(){AVPacket packet;int frameFinished = 0;// Convert the image from its native format to RGBwhile ( av_read_frame( pFormatCtx, &packet ) >= 0 ){if ( videoStream == packet.stream_index ){avcodec_decode_video(pCodecCtx, pFrame, &frameFinished, packet.data, packet.size);}if ( frameFinished ){//img_convert((AVPicture *)pFrameRGB, PIX_FMT_RGB24, (AVPicture *)pFrame, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height );// 这里不能用那个 turial上的函数,目前的版本上已经没有了这个img_convert函数,需要用下面的三句话来替换static struct SwsContext *img_convert_ctx;img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height,PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);// other codes// Convert the image from its native format to RGBsws_scale(img_convert_ctx, (uint8_t **)pFrame->data, pFrame->linesize,0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);return (AVPicture *)pFrameRGB;}}return NULL;}// NcMCodec.cpp至此已经结束// 至于如何把这个AVPicture结构转换成HBITMAP,用于MFC的显示,// 我的方法如下,其中dec是上述的一个解码器类对象,使用之前应该先进行dec.OpenFile操作:HBITMAP CNcMPlayerDlg::GetNextFrame(CDC *pDC, HBITMAP &hBitmap){    AVPicture *pFrame = dec.GetNextFrame();    if ( NULL == pFrame )    {        hBitmap = NULL;        return NULL;    }    LPVOID    lpDIBBits = (LPVOID)pFrame->data[0];/*(lpBuffer)+((BITMAPFILEHEADER *)lpBuffer)->bfOffBits*/ // 像素的数值    hBitmap = CreateDIBitmap(pDC->m_hDC, &bmpInfo.bmiHeader , CBM_INIT,lpDIBBits, &bmpInfo, DIB_RGB_COLORS);    return hBitmap;}

这个代码只有一个很基本的框架,还有一点BUG(设置读取指定位置会出错),

我自己没弄明白是怎么回事。

如果你解决了或者对代码做了优化,希望能够分享给我。

需要VS工程与源代码的:点这里

http://download.csdn.net/detail/luofl1992/5089125

收资源分是希望大家好好利用资源。谢谢。