转自该处

最近做项目需要将H264文件封装为mp4文件,从网上找到了MP4V2库,下载下来后不知道从何下手,官方网站https://code.google.com/p/mp4v2/在windows下的编译过程介绍的很简短,对刚刚开始使用VS2010做大型项目的人来说,实在是有些无力。于是从网上找到了下面几篇博客文章,亲测可用,留下来以备查看。

1.mp4v2 库在VS2010下的编译过程

注:此段内容参考自http://blog.csdn.net/elinchen88/article/details/7987284

Mp4v2 一开始是与mpeg4ip这个开源项目捆绑在一起的,现在已经脱离mpeg4ip以一个单独的库存在着。Mp4v2库提供了一些API用来创建修改MP4文件。

源码在http://mp4v2.googlecode.com/svn/trunk/,首先新建一个文件夹用来导入源码,创建文件夹后右键SVN checkout(需要预先在电脑上安装TortoiseSVN 客户端),在URL  of repository 中填入http://mp4v2.googlecode.com/svn/trunk/这个网址,点击ok后导入代码,再把vstudio9.0\libmp4v2\Version.rc放入src文件夹下,然后在进入vstudio9.0目录下,用vs2008打开mp4v2.sln进行编译。编译libmp4v2,选择配置为release win32,成功后,在bin\Windows-Win32\Release下会生成4个文件,lbmp4v2.lib、libmp4v2.dll、libmp4v2.pdb、libmp4v2.exp。这样就完成了。

   备注:

1.mp4v2的源码下载需要用到SVN客户端TortoiseSVN,官方网站上能下载的是linux平台下的代码。

2.此过程在VS2010下打开没有问题。

3.以后在你的项目中会用到lbmp4v2.lib、libmp4v2.dll这两个文件。

2.mp4v2库在VS2010中的使用

注:此处测试代码参考自http://blog.csdn.net/firehood_/article/details/8813587,作者代码写的很好,赞一个。此处只是把配置过程再详讲一下。原文如下:

最近需要将H264视频编码成MP4格式。研究了一下,一种方法是采用ffmpeg库,可以先将H264文件解码,再编码生成MP4文件,但这种方式效率较低,10M的视频可能需要几秒钟才能完成。另一种方式根据MP4文件协议直接将H264包封装成MP4格式,由于是直接基于MP4的封装,因而效率很高。H264可以很方便的封装成FLV文件,但MP4格式格式相对比较复杂,封装起来会比较麻烦。由于没时间研究MP4协议,在Google Code上找到一个开源的MP4编解码库Mp4v2(https://code.google.com/p/mp4v2/),通过Mp4v2可以很方便的将H264编码成MP4格式文件。为了方便使用,基于该库封装了一个MP4Encoder类,MP4Encoder封装的接口如下。目前仅支持将H264文件或数据帧编码成MP4文件。

class MP4Encoder
{
public:MP4Encoder(void);~MP4Encoder(void);
public:// open or creat a mp4 file.MP4FileHandle CreateMP4File(const char *fileName,int width,int height,int timeScale = 90000,int frameRate = 25);// wirte 264 metadata in mp4 file.bool Write264Metadata(MP4FileHandle hMp4File,LPMP4ENC_Metadata lpMetadata);// wirte 264 data, data can contain  multiple frame.int WriteH264Data(MP4FileHandle hMp4File,const unsigned char* pData,int size); // close mp4 file.void CloseMP4File(MP4FileHandle hMp4File);// convert H264 file to mp4 file.// no need to call CreateMP4File and CloseMP4File,it will create/close mp4 file automaticly.bool WriteH264File(const char* pFile264,const char* pFileMp4);// Prase H264 metamata from H264 data framestatic bool PraseMetadata(const unsigned char* pData,int size,MP4ENC_Metadata &metadata);
};

客户端调用示例代码:

#include <stdio.h>
#include "MP4Encoder\MP4Encoder.h"int main(int argc, char** argv)
{MP4Encoder mp4Encoder;// convert H264 file to mp4 filemp4Encoder.WriteH264File("test.264","test.mp4");
}

MP4Encoder的完整代码如下:

1)MP4Encoder.h

/********************************************************************
filename:   MP4Encoder.h
created:    2013-04-16
author:     firehood
purpose:    MP4编码器,基于开源库mp4v2实现(https://code.google.com/p/mp4v2/)。
*********************************************************************/
#pragma once
#include "mp4v2\mp4v2.h"// NALU单元
typedef struct _MP4ENC_NaluUnit
{int type;int size;unsigned char *data;
}MP4ENC_NaluUnit;typedef struct _MP4ENC_Metadata
{// video, must be h264 typeunsigned int    nSpsLen;unsigned char   Sps[1024];unsigned int  nPpsLen;unsigned char   Pps[1024];} MP4ENC_Metadata,*LPMP4ENC_Metadata;class MP4Encoder
{
public:MP4Encoder(void);~MP4Encoder(void);
public:// open or creat a mp4 file.MP4FileHandle CreateMP4File(const char *fileName,int width,int height,int timeScale = 90000,int frameRate = 25);// wirte 264 metadata in mp4 file.bool Write264Metadata(MP4FileHandle hMp4File,LPMP4ENC_Metadata lpMetadata);// wirte 264 data, data can contain  multiple frame.int WriteH264Data(MP4FileHandle hMp4File,const unsigned char* pData,int size); // close mp4 file.void CloseMP4File(MP4FileHandle hMp4File);// convert H264 file to mp4 file.// no need to call CreateMP4File and CloseMP4File,it will create/close mp4 file automaticly.bool WriteH264File(const char* pFile264,const char* pFileMp4);// Prase H264 metamata from H264 data framestatic bool PraseMetadata(const unsigned char* pData,int size,MP4ENC_Metadata &metadata);
private:// read one nalu from H264 data bufferstatic int ReadOneNaluFromBuf(const unsigned char *buffer,unsigned int nBufferSize,unsigned int offSet,MP4ENC_NaluUnit &nalu);
private:int m_nWidth;int m_nHeight;int m_nFrameRate;int m_nTimeScale;MP4TrackId m_videoId;
};

2)MP4Encoder.cpp

/********************************************************************
filename:   MP4Encoder.cpp
created:    2013-04-16
author:     firehood
purpose:    MP4编码器,基于开源库mp4v2实现(https://code.google.com/p/mp4v2/)。
*********************************************************************/
#include "MP4Encoder.h"
#include <string.h>#define BUFFER_SIZE  (1024*1024)MP4Encoder::MP4Encoder(void):
m_videoId(NULL),
m_nWidth(0),
m_nHeight(0),
m_nTimeScale(0),
m_nFrameRate(0)
{
}MP4Encoder::~MP4Encoder(void)
{
}MP4FileHandle MP4Encoder::CreateMP4File(const char *pFileName,int width,int height,int timeScale/* = 90000*/,int frameRate/* = 25*/)
{if(pFileName == NULL){return false;}// create mp4 fileMP4FileHandle hMp4file = MP4Create(pFileName);if (hMp4file == MP4_INVALID_FILE_HANDLE){printf("ERROR:Open file fialed.\n");return false;}m_nWidth = width;m_nHeight = height;m_nTimeScale = 90000;m_nFrameRate = 25;MP4SetTimeScale(hMp4file, m_nTimeScale);return hMp4file;
}bool MP4Encoder::Write264Metadata(MP4FileHandle hMp4File,LPMP4ENC_Metadata lpMetadata)
{m_videoId = MP4AddH264VideoTrack(hMp4File, m_nTimeScale, m_nTimeScale / m_nFrameRate, m_nWidth, // widthm_nHeight,// heightlpMetadata->Sps[1], // sps[1] AVCProfileIndicationlpMetadata->Sps[2], // sps[2] profile_compatlpMetadata->Sps[3], // sps[3] AVCLevelIndication3);           // 4 bytes length before each NAL unitif (m_videoId == MP4_INVALID_TRACK_ID){printf("add video track failed.\n");return false;}MP4SetVideoProfileLevel(hMp4File, 0x01); //  Simple Profile @ Level 3// write spsMP4AddH264SequenceParameterSet(hMp4File,m_videoId,lpMetadata->Sps,lpMetadata->nSpsLen);// write ppsMP4AddH264PictureParameterSet(hMp4File,m_videoId,lpMetadata->Pps,lpMetadata->nPpsLen);return true;
}int MP4Encoder::WriteH264Data(MP4FileHandle hMp4File,const unsigned char* pData,int size)
{if(hMp4File == NULL){return -1;}if(pData == NULL){return -1;}MP4ENC_NaluUnit nalu;int pos = 0, len = 0;while (len = ReadOneNaluFromBuf(pData,size,pos,nalu)){if(nalu.type == 0x07) // sps{// 添加h264 track    m_videoId = MP4AddH264VideoTrack(hMp4File, m_nTimeScale, m_nTimeScale / m_nFrameRate, m_nWidth,     // widthm_nHeight,    // heightnalu.data[1], // sps[1] AVCProfileIndicationnalu.data[2], // sps[2] profile_compatnalu.data[3], // sps[3] AVCLevelIndication3);           // 4 bytes length before each NAL unitif (m_videoId == MP4_INVALID_TRACK_ID){printf("add video track failed.\n");return 0;}MP4SetVideoProfileLevel(hMp4File, 1); //  Simple Profile @ Level 3MP4AddH264SequenceParameterSet(hMp4File,m_videoId,nalu.data,nalu.size);}else if(nalu.type == 0x08) // pps{MP4AddH264PictureParameterSet(hMp4File,m_videoId,nalu.data,nalu.size);}else{int datalen = nalu.size+4;unsigned char *data = new unsigned char[datalen];// MP4 Nalu前四个字节表示Nalu长度data[0] = nalu.size>>24;data[1] = nalu.size>>16;data[2] = nalu.size>>8;data[3] = nalu.size&0xff;memcpy(data+4,nalu.data,nalu.size);if(!MP4WriteSample(hMp4File, m_videoId, data, datalen,MP4_INVALID_DURATION, 0, 1)){return 0;}delete[] data;}pos += len;}return pos;
}int MP4Encoder::ReadOneNaluFromBuf(const unsigned char *buffer,unsigned int nBufferSize,unsigned int offSet,MP4ENC_NaluUnit &nalu)
{int i = offSet;while(i<nBufferSize){if(buffer[i++] == 0x00 &&buffer[i++] == 0x00 &&buffer[i++] == 0x00 &&buffer[i++] == 0x01){int pos = i;while (pos<nBufferSize){if(buffer[pos++] == 0x00 &&buffer[pos++] == 0x00 &&buffer[pos++] == 0x00 &&buffer[pos++] == 0x01){break;}}if(pos == nBufferSize){nalu.size = pos-i;   }else{nalu.size = (pos-4)-i;}nalu.type = buffer[i]&0x1f;nalu.data =(unsigned char*)&buffer[i];return (nalu.size+i-offSet);}}return 0;
}void MP4Encoder::CloseMP4File(MP4FileHandle hMp4File)
{if(hMp4File){MP4Close(hMp4File);hMp4File = NULL;}
}bool MP4Encoder::WriteH264File(const char* pFile264,const char* pFileMp4)
{if(pFile264 == NULL || pFileMp4 == NULL){return false;}MP4FileHandle hMp4File = CreateMP4File(pFileMp4,352,288);if(hMp4File == NULL){printf("ERROR:Create file failed!");return false;}FILE *fp = fopen(pFile264, "rb");  if(!fp)  {  printf("ERROR:open file failed!");return false;}  fseek(fp, 0, SEEK_SET);unsigned char *buffer  = new unsigned char[BUFFER_SIZE];int pos = 0;while(1){int readlen = fread(buffer+pos, sizeof(unsigned char), BUFFER_SIZE-pos, fp);if(readlen<=0){break;}readlen += pos;int writelen = 0;for(int i = readlen-1; i>=0; i--){if(buffer[i--] == 0x01 &&buffer[i--] == 0x00 &&buffer[i--] == 0x00 &&buffer[i--] == 0x00){writelen = i+5;break;}}writelen = WriteH264Data(hMp4File,buffer,writelen);if(writelen<=0){break;}memcpy(buffer,buffer+writelen,readlen-writelen+1);pos = readlen-writelen+1;}fclose(fp);delete[] buffer;CloseMP4File(hMp4File);return true;
}bool MP4Encoder:: PraseMetadata(const unsigned char* pData,int size,MP4ENC_Metadata &metadata)
{if(pData == NULL || size<4){return false;}MP4ENC_NaluUnit nalu;int pos = 0;bool bRet1 = false,bRet2 = false;while (int len = ReadOneNaluFromBuf(pData,size,pos,nalu)){if(nalu.type == 0x07){memcpy(metadata.Sps,nalu.data,nalu.size);metadata.nSpsLen = nalu.size;bRet1 = true;}else if((nalu.type == 0x08)){memcpy(metadata.Pps,nalu.data,nalu.size);metadata.nPpsLen = nalu.size;bRet2 = true;}pos += len;}if(bRet1 && bRet2){return true;}return false;
}

备注:说说我的将此代码与mp4v2库结合的过程。

1) 在MP4v2源代码中有一个vstudio9.0目录,用VS2010打开mp4v2.sln,然后新建一个项目,项目类型选Win32控制台应用程序,名称可以写为Test264ToMp4,解决方案选择“添加到解决方案”即可。这样在vstudio9.0目录下,就会多了一个文件夹Test264ToMp4(当然,也可以新打开一个VS2010,新建个名字叫做Test264Mp4的工程,对应的解决方案名字自动为Test264ToMp4,只要在3)中配置好include、lib、dll即可)。

2) 在VS2010中,右击Test64ToMp4工程,添加->类,类名写为 CMP4Encoder,然后把上面MP4Encoder.h和MP4Encoder.cpp的代码拷贝到对应的文件中,main函数所在的文件需要重新写一个cpp,可起名为Test.cpp。步骤为:右击工程Test264ToMp4->添加->新建项,选择C++文件,名称写做Test.cpp,位置默认即可,然后将上面的“客户端调用示例代码”拷贝到此文件。

3)关键部分来了。将MP4V2类库添加到Test264ToMp4工程。

首先添加.h目录。需要将MP4V2开源软件包里面的include目录和vstudio9.0目录下的include目录添加到“附加包含目录”项中。如图所示:

此处最好路径位置最好用相对路径来代替,由于自己对这个还不怎么熟悉,先用绝对路径吧。

然后添加libmp4v2.lib

方法:右击Test264ToMp4->属性->配置属性->链接器->常规,在“附加库目录”里点“编辑”,把第1步中编译好的libmp4v2.lib库所在的路径加上,如图:

然后点击链接器下的“输入”,在“附加依赖项”中点“编辑”,写上libmp4v2.lib,如图:

最后,将libmp4v2.dll拷贝到Test264ToMp4目录下即可。

3.测试过程

首先拷贝一个H264测试文件(后缀为.264)到Test264ToMp4文件夹下,测试文件可以从此处下载(http://blog.163.com/lvan100@yeah/blog/static/68117214201381485753386/)。右击Test264ToMp4,生成,然后运行即可生成.mp4文件,可以用VLC播放器打开看看。

4.总结

当要调用开源项目的库时,最重要的三个东西分别是include目录(里面存放了所需的.h文件)、编译后的动态链接库(.dll文件)和编译后的静态链接库文件(.lib)文件,只要这三个地方配好了,一般就能用了。当VS编译时,报错如找不到.h文件之类,就得看是不是include路径没写对,当出现link错误时,就得看.lib路径是否没写对。

VS2010下编译mp4v2及在项目中的使用相关推荐

  1. 在VS2010 下编译 cocos2d-x-2.1.4

    在VS2010 下编译 cocos2d-x-2.1.4 首先感谢 cocos2d-x 团队为我们做出这么好的跨平台框架,让我们这些码农省了很多时间,事半功倍. 里沃特最近在编译 win32 版本的时候 ...

  2. IDEA下,如何在java项目中新增jsp模板文件

    IDEA下,如何在java项目中新增jsp模板文件 大家会不会有这样的烦恼,就是当想要创建一个jsp模板文件的时候,右键new的时候找不到JSP选项. 这是因为在创建项目的时候没有选中Web Appl ...

  3. 关于VS2010下编译NTL库方法及NTL库的应用

    之前帮np搞了一下NTL函数库的问题,从网上下载了相关工程的源代码,发现编译之后各种问题.而且,源工程是用DEVC++开发的,而本人对DEV C++不甚了解,看来只能曲线救国了.于是就想到了可以用vs ...

  4. 在VS2010下利用vue开发团队项目

    开发一个项目,采用什么语言都可以,主要能熟练高效的开发都是合理的,这次我们采用vue来开发一个团队项目.在开始之前掌握vue的基本用法,如双向数据绑定.组件和路由等,建议先去看之前的文档(webpac ...

  5. C语言编译时无法打开文件,在VS2010下编译无法打开包括文件:“GL/glaux.h”: No such file or director...

    最近测试了一个OpenGL的示例程序: #include #include #include "glos.h" void main(void) { auxInitDisplayMo ...

  6. linux编译taglib,在Windows上将TagLib编译到Qt C项目中

    我目前正试图通过使用Qt / C从C#转移并摆脱我的平台边界. 我在我的旧项目中使用TagLibSharp,但我现在正尝试使用此处找到的原始C源: 我正处于一个受伤的世界,试图将其编译到我的应用程序中 ...

  7. vs可以调用java接口吗_关于vs2010下编译dll动态库,JNA接口在java中调用的问题

    最近在搞关于把vs2010中的project,使之能够在Java下面运行,有一个调用本地接口的问题,JNI那个涉及到复杂细节太多,就使用了最新的JNA(java native access) 网上也给 ...

  8. VS2010下编译OpenCV2.4.6静态库

    1.   从 http://sourceforge.net/projects/opencvlibrary/files/opencv-win/2.4.3/ 下载最新的OpenCV2.4.6: 2.    ...

  9. visual studio编译linux,在 Visual Studio 中配置 Linux MSBuild C++ 项目

    在 Visual Studio 中配置 Linux MSBuild C++ 项目Configure a Linux MSBuild C++ project in Visual Studio 10/16 ...

  10. 如何使用Visual Studio 2010(VS2010)编译C语言

    1.打开VS2010主界面,然后选择,文件→新建→项目,在项目类型中选择VC++→win32 然后在右侧模板中选择win32控制台应用程序,再在下面输入一个名称(项目名称,不用带.C) 选择保存位置后 ...

最新文章

  1. 1.3-date命令
  2. 华为FusionCube从融合到超融合 只为让计算变简单
  3. LeetCode-28 实现strStr()
  4. echarts y轴数据过长处理
  5. 数据结构之串:串的模式匹配
  6. Hive 时间戳和日期相互转换
  7. 复述-软考高级-网规-数据灾备
  8. 东方电子全资子公司中标1.065亿元国家电网第三批采购项目
  9. AngularJS第六课(路由)
  10. 我为什么要写《OpenCV Android 开发实战》这本书
  11. 【Spring源码学习篇(一)】☀️Spring5本地环境编译,超级实用!!✨
  12. php jmail,PHP利用Jmail组件实现发送邮件
  13. 【JTT1078视频服务器】之音视频的拆解
  14. Mysql 免安装版本
  15. 推荐几部不错的网络玄幻小说
  16. windows默认共享的打开和关闭
  17. 用java做出长方体的表面积_计算长方体、四棱锥的表面积和体积(Java)acm.sdut...
  18. 2018-09-27工作日报
  19. CJOJ 1659 【中学高级本】倒酒
  20. 人造指针_如何用程式化的阴影和细节制作人造HDR照片

热门文章

  1. DDA算法画直线+源代码
  2. python马尔科夫链蒙特卡洛(MCMC)方法pyMC
  3. mysql 通达信公式_通达信的几个好用指标
  4. 网络电视机顶盒测试软件,调试接口查找方法,机顶盒刷成全网通盒子,实现免费看电视...
  5. Fgui: Glist 实现无限滑动 虚拟列表
  6. 王道计算机考研机试指南部分代码
  7. MySQL获取汉字拼音首字母
  8. Android 杂七杂八记录
  9. 物联网:LoRa无线通信技术
  10. 【PLSQL】PLSQL安装、破解以及汉化教程