一、H264视频编码成MP4文件

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

(1)mp4v2 库在VS2017下的编译过程

注:此段内容参考:编译MP4v2
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 文件夹下。

上面的内容其实就是获取 MP4V2 源码。上面两个谷歌网站没有进入,原因你懂的。可从 CSDN 下载。
下载:mp4v2最新源码
然后在进入 vs2013 目录下,用 vs2017 打开 mp4v2.sln 。选择配置为 release win32,成功后,编译 libmp4v2。
在 mp4v2-master\buildwin\lib.vs2013\Win32\Release 下会生成 4 个文件,lbmp4v2.lib、libmp4v2.dll、libmp4v2.pdb、libmp4v2.exp。这样就完成了。
备注:
1. mp4v2 的源码下载需要用到 SVN 客户端 TortoiseSVN,官方网站上能下载的是 Linux 平台下的代码。
Linux下安装编译之前有讲,参看:mp4v2再学习 -- mp4v2 安装说明
2. 此过程在 VS2017 下打开没有问题。
3. 以后在你的项目中会用到 lbmp4v2.lib、libmp4v2.dll 这两个文件。
上面的操作有几处需要注意的:
(1)首先选择配置为 release win32,这个该如何配置?
配置方法:生成->配置管理器,然后将 libmp4v2 配置改为 Release 
(2)问题分析
出现 无法打开包括文件: “corecrt.h”
解决方法,参看:VS2015无法打开包括文件corecrt.h
简单来说就是按如下图,把里面的 10.0.15063.0 文件复制一份,重命名成 10.0.10240.0

(2)mp4v2库在VS2010中的使用

注:此处测试代码参考:H264视频编码成MP4文件,作者代码写的很好,赞一个。此处只是把配置过程再详讲一下。

原文如下:
最近需要将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文件。
[cpp] view plaincopy
  1. class MP4Encoder
  2. {
  3. public:
  4. MP4Encoder(void);
  5. ~MP4Encoder(void);
  6. public:
  7. // open or creat a mp4 file.
  8. MP4FileHandle CreateMP4File(const char *fileName,int width,int height,int timeScale = 90000,int frameRate = 25);
  9. // wirte 264 metadata in mp4 file.
  10. bool Write264Metadata(MP4FileHandle hMp4File,LPMP4ENC_Metadata lpMetadata);
  11. // wirte 264 data, data can contain  multiple frame.
  12. int WriteH264Data(MP4FileHandle hMp4File,const unsigned char* pData,int size);
  13. // close mp4 file.
  14. void CloseMP4File(MP4FileHandle hMp4File);
  15. // convert H264 file to mp4 file.
  16. // no need to call CreateMP4File and CloseMP4File,it will create/close mp4 file automaticly.
  17. bool WriteH264File(const char* pFile264,const char* pFileMp4);
  18. // Prase H264 metamata from H264 data frame
  19. static bool PraseMetadata(const unsigned char* pData,int size,MP4ENC_Metadata &metadata);
  20. };

客户端调用示例代码:

[cpp] view plaincopy
  1. #include <stdio.h>
  2. #include "MP4Encoder.h"
  3. int main(int argc, char** argv)
  4. {
  5. MP4Encoder mp4Encoder;
  6. // convert H264 file to mp4 file
  7. mp4Encoder.WriteH264File("test.264","test.mp4");
  8. }

MP4Encoder的完整代码如下:

[cpp] view plaincopy
  1. /********************************************************************
  2. filename:   MP4Encoder.h
  3. created:    2013-04-16
  4. author:     firehood
  5. purpose:    MP4编码器,基于开源库mp4v2实现(https://code.google.com/p/mp4v2/)。
  6. *********************************************************************/
  7. #pragma once
  8. #include "mp4v2\mp4v2.h"
  9. // NALU单元
  10. typedef struct _MP4ENC_NaluUnit
  11. {
  12. int type;
  13. int size;
  14. unsigned char *data;
  15. }MP4ENC_NaluUnit;
  16. typedef struct _MP4ENC_Metadata
  17. {
  18. // video, must be h264 type
  19. unsigned int    nSpsLen;
  20. unsigned char   Sps[1024];
  21. unsigned int    nPpsLen;
  22. unsigned char   Pps[1024];
  23. } MP4ENC_Metadata,*LPMP4ENC_Metadata;
  24. class MP4Encoder
  25. {
  26. public:
  27. MP4Encoder(void);
  28. ~MP4Encoder(void);
  29. public:
  30. // open or creat a mp4 file.
  31. MP4FileHandle CreateMP4File(const char *fileName,int width,int height,int timeScale = 90000,int frameRate = 25);
  32. // wirte 264 metadata in mp4 file.
  33. bool Write264Metadata(MP4FileHandle hMp4File,LPMP4ENC_Metadata lpMetadata);
  34. // wirte 264 data, data can contain  multiple frame.
  35. int WriteH264Data(MP4FileHandle hMp4File,const unsigned char* pData,int size);
  36. // close mp4 file.
  37. void CloseMP4File(MP4FileHandle hMp4File);
  38. // convert H264 file to mp4 file.
  39. // no need to call CreateMP4File and CloseMP4File,it will create/close mp4 file automaticly.
  40. bool WriteH264File(const char* pFile264,const char* pFileMp4);
  41. // Prase H264 metamata from H264 data frame
  42. static bool PraseMetadata(const unsigned char* pData,int size,MP4ENC_Metadata &metadata);
  43. private:
  44. // read one nalu from H264 data buffer
  45. static int ReadOneNaluFromBuf(const unsigned char *buffer,unsigned int nBufferSize,unsigned int offSet,MP4ENC_NaluUnit &nalu);
  46. private:
  47. int m_nWidth;
  48. int m_nHeight;
  49. int m_nFrameRate;
  50. int m_nTimeScale;
  51. MP4TrackId m_videoId;
  52. };

MP4Encoder.cpp

[cpp] view plaincopy
  1. /********************************************************************
  2. filename:   MP4Encoder.cpp
  3. created:    2013-04-16
  4. author:     firehood
  5. purpose:    MP4编码器,基于开源库mp4v2实现(https://code.google.com/p/mp4v2/)。
  6. *********************************************************************/
  7. #include "MP4Encoder.h"
  8. #include <string.h>
  9. #define BUFFER_SIZE  (1024*1024)
  10. MP4Encoder::MP4Encoder(void):
  11. m_videoId(NULL),
  12. m_nWidth(0),
  13. m_nHeight(0),
  14. m_nTimeScale(0),
  15. m_nFrameRate(0)
  16. {
  17. }
  18. MP4Encoder::~MP4Encoder(void)
  19. {
  20. }
  21. MP4FileHandle MP4Encoder::CreateMP4File(const char *pFileName,int width,int height,int timeScale/* = 90000*/,int frameRate/* = 25*/)
  22. {
  23. if(pFileName == NULL)
  24. {
  25. return false;
  26. }
  27. // create mp4 file
  28. MP4FileHandle hMp4file = MP4Create(pFileName);
  29. if (hMp4file == MP4_INVALID_FILE_HANDLE)
  30. {
  31. printf("ERROR:Open file fialed.\n");
  32. return false;
  33. }
  34. m_nWidth = width;
  35. m_nHeight = height;
  36. m_nTimeScale = 90000;
  37. m_nFrameRate = 25;
  38. MP4SetTimeScale(hMp4file, m_nTimeScale);
  39. return hMp4file;
  40. }
  41. bool MP4Encoder::Write264Metadata(MP4FileHandle hMp4File,LPMP4ENC_Metadata lpMetadata)
  42. {
  43. m_videoId = MP4AddH264VideoTrack
  44. (hMp4File,
  45. m_nTimeScale,
  46. m_nTimeScale / m_nFrameRate,
  47. m_nWidth, // width
  48. m_nHeight,// height
  49. lpMetadata->Sps[1], // sps[1] AVCProfileIndication
  50. lpMetadata->Sps[2], // sps[2] profile_compat
  51. lpMetadata->Sps[3], // sps[3] AVCLevelIndication
  52. 3);           // 4 bytes length before each NAL unit
  53. if (m_videoId == MP4_INVALID_TRACK_ID)
  54. {
  55. printf("add video track failed.\n");
  56. return false;
  57. }
  58. MP4SetVideoProfileLevel(hMp4File, 0x01); //  Simple Profile @ Level 3
  59. // write sps
  60. MP4AddH264SequenceParameterSet(hMp4File,m_videoId,lpMetadata->Sps,lpMetadata->nSpsLen);
  61. // write pps
  62. MP4AddH264PictureParameterSet(hMp4File,m_videoId,lpMetadata->Pps,lpMetadata->nPpsLen);
  63. return true;
  64. }
  65. int MP4Encoder::WriteH264Data(MP4FileHandle hMp4File,const unsigned char* pData,int size)
  66. {
  67. if(hMp4File == NULL)
  68. {
  69. return -1;
  70. }
  71. if(pData == NULL)
  72. {
  73. return -1;
  74. }
  75. MP4ENC_NaluUnit nalu;
  76. int pos = 0, len = 0;
  77. while (len = ReadOneNaluFromBuf(pData,size,pos,nalu))
  78. {
  79. if(nalu.type == 0x07) // sps
  80. {
  81. // 添加h264 track
  82. m_videoId = MP4AddH264VideoTrack
  83. (hMp4File,
  84. m_nTimeScale,
  85. m_nTimeScale / m_nFrameRate,
  86. m_nWidth,     // width
  87. m_nHeight,    // height
  88. nalu.data[1], // sps[1] AVCProfileIndication
  89. nalu.data[2], // sps[2] profile_compat
  90. nalu.data[3], // sps[3] AVCLevelIndication
  91. 3);           // 4 bytes length before each NAL unit
  92. if (m_videoId == MP4_INVALID_TRACK_ID)
  93. {
  94. printf("add video track failed.\n");
  95. return 0;
  96. }
  97. MP4SetVideoProfileLevel(hMp4File, 1); //  Simple Profile @ Level 3
  98. MP4AddH264SequenceParameterSet(hMp4File,m_videoId,nalu.data,nalu.size);
  99. }
  100. else if(nalu.type == 0x08) // pps
  101. {
  102. MP4AddH264PictureParameterSet(hMp4File,m_videoId,nalu.data,nalu.size);
  103. }
  104. else
  105. {
  106. int datalen = nalu.size+4;
  107. unsigned char *data = new unsigned char[datalen];
  108. // MP4 Nalu前四个字节表示Nalu长度
  109. data[0] = nalu.size>>24;
  110. data[1] = nalu.size>>16;
  111. data[2] = nalu.size>>8;
  112. data[3] = nalu.size&0xff;
  113. memcpy(data+4,nalu.data,nalu.size);
  114. if(!MP4WriteSample(hMp4File, m_videoId, data, datalen,MP4_INVALID_DURATION, 0, 1))
  115. {
  116. return 0;
  117. }
  118. delete[] data;
  119. }
  120. pos += len;
  121. }
  122. return pos;
  123. }
  124. int MP4Encoder::ReadOneNaluFromBuf(const unsigned char *buffer,unsigned int nBufferSize,unsigned int offSet,MP4ENC_NaluUnit &nalu)
  125. {
  126. int i = offSet;
  127. while(i<nBufferSize)
  128. {
  129. if(buffer[i++] == 0x00 &&
  130. buffer[i++] == 0x00 &&
  131. buffer[i++] == 0x00 &&
  132. buffer[i++] == 0x01
  133. )
  134. {
  135. int pos = i;
  136. while (pos<nBufferSize)
  137. {
  138. if(buffer[pos++] == 0x00 &&
  139. buffer[pos++] == 0x00 &&
  140. buffer[pos++] == 0x00 &&
  141. buffer[pos++] == 0x01
  142. )
  143. {
  144. break;
  145. }
  146. }
  147. if(pos == nBufferSize)
  148. {
  149. nalu.size = pos-i;
  150. }
  151. else
  152. {
  153. nalu.size = (pos-4)-i;
  154. }
  155. nalu.type = buffer[i]&0x1f;
  156. nalu.data =(unsigned char*)&buffer[i];
  157. return (nalu.size+i-offSet);
  158. }
  159. }
  160. return 0;
  161. }
  162. void MP4Encoder::CloseMP4File(MP4FileHandle hMp4File)
  163. {
  164. if(hMp4File)
  165. {
  166. MP4Close(hMp4File);
  167. hMp4File = NULL;
  168. }
  169. }
  170. bool MP4Encoder::WriteH264File(const char* pFile264,const char* pFileMp4)
  171. {
  172. if(pFile264 == NULL || pFileMp4 == NULL)
  173. {
  174. return false;
  175. }
  176. MP4FileHandle hMp4File = CreateMP4File(pFileMp4,352,288);
  177. if(hMp4File == NULL)
  178. {
  179. printf("ERROR:Create file failed!");
  180. return false;
  181. }
  182. FILE *fp = fopen(pFile264, "rb");
  183. if(!fp)
  184. {
  185. printf("ERROR:open file failed!");
  186. return false;
  187. }
  188. fseek(fp, 0, SEEK_SET);
  189. unsigned char *buffer  = new unsigned char[BUFFER_SIZE];
  190. int pos = 0;
  191. while(1)
  192. {
  193. int readlen = fread(buffer+pos, sizeof(unsigned char), BUFFER_SIZE-pos, fp);
  194. if(readlen<=0)
  195. {
  196. break;
  197. }
  198. readlen += pos;
  199. int writelen = 0;
  200. for(int i = readlen-1; i>=0; i--)
  201. {
  202. if(buffer[i--] == 0x01 &&
  203. buffer[i--] == 0x00 &&
  204. buffer[i--] == 0x00 &&
  205. buffer[i--] == 0x00
  206. )
  207. {
  208. writelen = i+5;
  209. break;
  210. }
  211. }
  212. writelen = WriteH264Data(hMp4File,buffer,writelen);
  213. if(writelen<=0)
  214. {
  215. break;
  216. }
  217. memcpy(buffer,buffer+writelen,readlen-writelen+1);
  218. pos = readlen-writelen+1;
  219. }
  220. fclose(fp);
  221. delete[] buffer;
  222. CloseMP4File(hMp4File);
  223. return true;
  224. }
  225. bool MP4Encoder:: PraseMetadata(const unsigned char* pData,int size,MP4ENC_Metadata &metadata)
  226. {
  227. if(pData == NULL || size<4)
  228. {
  229. return false;
  230. }
  231. MP4ENC_NaluUnit nalu;
  232. int pos = 0;
  233. bool bRet1 = false,bRet2 = false;
  234. while (int len = ReadOneNaluFromBuf(pData,size,pos,nalu))
  235. {
  236. if(nalu.type == 0x07)
  237. {
  238. memcpy(metadata.Sps,nalu.data,nalu.size);
  239. metadata.nSpsLen = nalu.size;
  240. bRet1 = true;
  241. }
  242. else if((nalu.type == 0x08))
  243. {
  244. memcpy(metadata.Pps,nalu.data,nalu.size);
  245. metadata.nPpsLen = nalu.size;
  246. bRet2 = true;
  247. }
  248. pos += len;
  249. }
  250. if(bRet1 && bRet2)
  251. {
  252. return true;
  253. }
  254. return false;
  255. }
其实讲 ffmpeg 时就已经讲了VS 开发环境搭建。参看:ffmpeg再学习 -- Windows下安装说明
好吧,那我再讲一遍。。
(1)新建项目
打开 VS;
文件->新建->项目->Win32控制台应用程序->选择空项目,点击完成。
注意,选择的位置最好不要有 空格或者汉字。
(2)拷贝考法文件
头文件( *.h)拷贝至项目文件夹的 include 子文件夹下
导入库文件( *.lib)拷贝至项目文件夹的 lib 子文件夹下
动态库文件( *.dll) 拷贝至项目文件夹下
这三组文件具体是,mp4v2-master文件夹下的 include 文件夹 和 mp4v2-master\buildwin\lib.vs2013\Win32\Release 文件夹下的 libmp4v2.lib 和 libmp4v2.dll
点击右键,选择在资源管理器中打开文件夹,进入项目目录。
(注意,如果手动进入注意文件夹位置,我就是没找好位置,试了半天最后才发现,将上面的这些文件拷贝到错误的文件夹下了)
放置完成即下图:
(3)添加代码
右击 MP4Encoder 工程,添加->类
双击 C++类 进入 一般 C++类向导,类名写为 CMP4Encoder ,然后把上面 MP4Encoder.h 和MP4Encoder.cpp 的代码拷贝到对应的文件中。
右击工程 MP4Encoder ->添加->新建项
选择C++文件,名称写做 main.cpp,位置默认即可,然后将上面的“客户端调用示例代码”拷贝到此文件。

(4)配置开发文件

打开属性面板

解决方案资源管理器->右键单击项目->属性

头文件配置

配置属性->C/C++->常规->附加包含目录,输入“ include”(刚才拷贝头文件的目录)

导入库配置

配置属性->链接器->常规->附加库目录,输入“ lib” (刚才拷贝库文件的目录)

配置属性->链接器->输入->附加依赖项,输入 libmp4v2.lib;

动态库不用配置


(5)测试

首先拷贝一个 H264 测试文件 (后缀为.264) 到 MP4Encoder 文件夹下。
测试文件可以从此处,下载:[开源世界]分享H.264视频文件下载地址 
注意,需要将该264文件,重命名为 test.h264,否则生成的 MP4 文件大小为1K。
或者你更改主函数:
然后点击本地Windows调试器,出现此项目已经过期,选择 是。
即可生成 test.mp4 文件,可以用VLC播放器打开看看。
不过生成文件时会出现,无法查找或打开 PDB 文件。如下图:
它对于生成文件没有影响的。如果看着不舒服,可参看:无法查找或打开 PDB 文件解决办法
这是我写的工程文件:MP4Encoder 工程文件

二、工程文件(可用)

讲了这么多,你发现没有上面这个例子只是将 H264 视频编码成MP4文件,缺少音频啊亲。

下面这个即音视频编码转MP4文件的例子,下载:MP4v2 -- h264 转 MP4

mp4v2再学习 -- H264视频编码成MP4文件相关推荐

  1. H264视频编码成MP4文件

    http://blog.csdn.net/firehood_/article/details/8813587 版权声明:本文为博主原创文章,未经博主允许不得转载. 最近需要将H264视频编码成MP4格 ...

  2. 使用mp4v2将aac音频h264视频数据封装成mp4开发心得

    这阵子在捣鼓一个将游戏视频打包成本地可播放文件的模块.开始使用avi作为容器,弄了半天无奈avi对aac的支持实在有限,在播放时音视频时无法完美同步. 关于这点avi文档中有提到: For AAC, ...

  3. FFmpeg再学习 -- 将 jpeg 转成 mp4

    参看:wiki -- ffmpeg 上一篇已讲将了 ffmpeg 的安装说明,接一下来讲一下我们要实现的功能,将 jpeg 转成 mp4. 参看:使用ffmpeg将jpeg转成mp4 参看:FFmpe ...

  4. 工具---《.264视频 转成 MP4视频》

    <.264视频 转成 MP4视频> 安装了"爱奇艺万能播放器"可以打开.264视频,但是opencv却不能直接读取.264视频,还是需要想办法".264视频 ...

  5. flv视频转换成mp4格式怎么转?

    flv视频转换成mp4格式怎么转?相信正在阅读文章的你,一定接触到了flv视频文件.flv是一种新型的小体积视频格式,因为体积小的特点使得flv的加载速度特别快,从而实现了在线观看浏览视频也很顺畅的愿 ...

  6. 【Python网络爬虫实战篇】使用selenium+requests爬取下载高清源视频:关于爬取m3u8文件链接解析为ts视频合并成mp4视频的分析实战

    这两天博主在摸鱼时,偶然间接触到了流媒体的概念,一时间来了兴致.再加上之前博主有着七.八年的视频制作经验,深知视频素材获取的不易.因此,打算利用自己所学的python网络爬虫的知识,通过编写代码实现获 ...

  7. 深度学习赋能视频编码

    深度学习赋予了诸如计算机视觉等领域新的研究契机,其应用也获得了视频编码领域的诸多关注.在LiveVideoStack线上分享中北京大学信息技术学院 助理研究员王苫社详细介绍了当下深度学习在视频编码中的 ...

  8. b站电脑客户端_如何将B站的flv格式的视频转换成mp4格式

    经常看到B站有精彩的视频片段,于是想把这些视频下载保存到电脑,但是发现没有下载按钮,是不是很悲催.有些时候想从优酷.土豆网这些视频网站下载视频,结果却提示要先下载视频客户端才能继续下载视频,运气差的话 ...

  9. 如何快速不借用转换工具将FLV格式视频转换成MP4

    FLV流媒体格式是一种新的视频格式,全称为Flash Video.它的出现有效地解决了视频文件导入Flash后,使导出的SWF文件体积庞大,所以就引出了FLV格式,主要特点就是体积小 适合作为流媒体在 ...

最新文章

  1. 多线程编程, 这三个方法够我用了.
  2. 第八章 熟练dom的几个常用方法
  3. wamp测试mysql_Wamp 配置及测试
  4. T-SQL里数据库工程师都不知道的秘密之SQL Server自定义函数UDF
  5. 执行setenv ethaddr的时候提示Can't over write的原因及解决方法
  6. 前端学习(2627):node安装
  7. hypermesh安装包百度云_新闻突然!全新百度网盘发布
  8. C++参考的翻译或校对
  9. windows10(专业版和家庭版)---禁止自动更新系统
  10. 串级pid算法c语言实现,【开源】分享一个经典的串级PID算法,附源代码
  11. sam机架和kx连线图_创新声卡KX 3552驱动连线搭载SAM机架
  12. 计算机office demo,办公软件应用(Office2007)中级 DEMO盘-2013.doc
  13. Hadoop安装教程单机/伪分布式配置
  14. 关于DCMM评估模型的全面解析
  15. 间歇性孤独症,我喜欢的,是你刚好在我身边
  16. matplotlib在一张图中画两条线
  17. 关于js导入Excel时,Excel的(年/月/日)日期是五位数字的问题。以及对Excel日期存在的错误的分析和处理。
  18. 爬取起点小说总排行榜
  19. 巴比特MatPool运营NEO节点,2019年必定是 Staking 经济元年
  20. ps 图片提取线稿方法2种 转

热门文章

  1. Bootstrap 栅格 样式 组件 插件
  2. 王爽《汇编语言》第三版 第三章 内存访问
  3. 从零学React Native之07View
  4. 一个多功能蓝色漂亮的搜索条
  5. MSSQL SERVER 2005 数学函数
  6. [文摘20070913]最好的消息
  7. 编程方法学25:设计实用社交网络
  8. getopt的用法与optarg
  9. 基于VTK的MFC应用程序开发(2)
  10. Jupyter Notebook 快速入门(上)