h.264视频编码加生成QT7可播放的mp4文件

实际上只是一个头文件h264_util.h。h264_util.h封装了x264库。我做的工作就是使用模板封装了一下,保证使用任何mp4 container库都可以方便地输出mp4文件。使用模板的目的是为了避免任何回调的开销。h264_util.h依赖于x264库。main.cpp依赖于h264_util.h和libmp42(可选)和libmp4av(可选),后两者都是mpeg4ip的一部分。使用
摘要由CSDN通过智能技术生成

实际上只是一个头文件h264_util.h。h264_util.h封装了x264库。我做的工作就是使用模板封装了一下,保证使用任何mp4 container库都可以方便地输出mp4文件。使用模板的目的是为了避免任何回调的开销。

h264_util.h依赖于x264库。

main.cpp依赖于h264_util.h和libmp42(可选)和libmp4av(可选),后两者都是mpeg4ip的一部分。使用的mpeg4ip是为了生成Quicktime7可播放的mp4文件(相信我,这点很难的,我试了很多库了。原因不是这些库不好,而是QT7太糟糕)。

附带说明一下,所用到的库和我写的代码都是可以同时在window下和linux编译运行的(我已经都试过了)。要在windows下编译x264很简单的,参考说明文档就可以。麻烦的是mpeg4ip,其文档声称不再会对windows下的兼容性负责了。要在windows下编译并使用mpeg4ip,有两个办法,或者自己提供gettimeofday的定义,或者使用其libmissing(和libmissing60是一回事,60表示vs6下编译通过,实际上我用vc7也编译运行过了)。

如果同时使用x264和mpeg4ip,又会发现一些兼容性问题。问题的关键在于windows操作下默认没有提供int8_t之类的类型定义,于是mpeg4ip会自己提供一个mpeg4ip_version.h,补上这些定义。所有的跨平台的开源项目似乎都会自说自话地为windows平台(linux下有标准头文件)提供这些定义,如果我同时使用两个这样的开源项目,就可能会产生类型重复定义的编译错误。x264是个特例,它的libx264根本就没有提供这些定义,所以我在h264_util.h补上了这些定义。又由于这些类型定义可能和mpeg4ip_version.h中的定义冲突,所以我在h264_util.h中预先加入了判断避免冲突的宏。要这些宏起作用,mpeg4ip的头文件必须先被#include于我的h264_util.h之前。

要编译x264,必须安装nasm(一种汇编语言编译器),mpeg4ip如果是只编译上文中的两个库的话,不需要,否则也需要nasm。

下面就是源代码,包括两个源代码文件,h264_util.h和main.cpp和一个makefile(仅用于linux),GNUmakefile。

h264_util.h封装了x264,main.cpp提供了两个测试例子,一个仅使用h264_util.h演示了如何进行视频编码,另一个测试例子说明了如何生成mp4。test_h264_utilities是在内存中快速生成rgb888的raw image的工具,仅仅是为了我测试方便用,你完全可以不使用它。

使用方法很简单(仅限于于linux,windows下懒得写了),安装libx264,libmp4ip,libmp4v2(./configure;make;make install总会吧?mpeg4ip安装完整的软件包也许会有问题,但是安装库是没问题的(先在源代码包的根目录下./configure,然后还是在对应的库代码的目录里make;make install),把下述三个文件拷贝到同一个目录里,然后make clean;make;./test_main,就会生成一个叫test.mp4的文件。

//h264_util.h

#ifndef __H264_UTIL_H__
#define __H264_UTIL_H__
 
#include <cstdio>
#include <cassert>
#include <climits>
#include <cstdlib>


#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
 
#ifdef __cplusplus
extern "C" {
#endif

#if (defined HAVE_INTTYPES_H)
#include <inttypes.h>
#elif (defined HAVE_STDINT_H)
#include <stdint.h>
#else
#ifndef __MPEG4IP_WIN32_H__
typedef signed char  int8_t;
typedef signed short int16_t;
typedef signed int   int32_t;
typedef unsigned char  uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int   uint32_t;
#if (defined WIN32)||(defined _WIN32)
typedef signed __int64   int64_t;
typedef unsigned __int64 uint64_t;
#else //other OS
typedef signed long long   int64_t;
typedef unsigned long long uint64_t;
#endif
#endif
#endif

#include "x264.h"
#ifdef __cplusplus
}
#endif


struct ContainerTraits{
 //insert+=return of write_nalu ; x264_nal_encode( _bit_buffer+inserter ......);
 static int write_nalu(unsigned char *nalu, int size){ return 0;}
 //encoded bit buffer, contains raw h.264 data
 static void set_eop(unsigned char* bit_buffer, int size){ }
};

template <typename CTraits=ContainerTraits>
class h264_utilities
{
public:
 h264_utilities(int width, int height):_h(0),_bit_buffer(0),_bit_buffer_capacity(1024*256)
 {
  assert(width%16==0);
    assert(height%16==0);
    
  x264_param_default(&_param);
  _param.i_width = width;
  _param.i_height= height;
  
  _h=x264_encoder_open(&_param);
  assert(_h);
  
  //http://www.via.ecp.fr/via/ml/vlc-devel/2005-02/msg00371.html or google "x264_encoder_encode"
  
  //if we do not allocate the new buffer ,
  //the code "RGB_TO_I420( rgb_to_i420,  0, 1, 2, 3 );" will raise segment fault
  x264_picture_alloc(&_pic,X264_CSP_RGB,_param.i_width ,_param.i_height);
  // Do not force any parameters
  _pic.i_type = X264_TYPE_AUTO;
  _pic.i_qpplus1 = 0;
  
  _bit_buffer_capacity=(_bit_buffer_capacity>_param.i_width*_param.i_height*4? _bit_buffer_capacity:_param.i_width*_param.i_height*4);
     if (!_bit_buffer)
      _bit_buffer = (unsigned char*)av_malloc(_bit_buffer_capacity);
 }
 
 ~h264_utilities()
 {
  //assert(0);
  if(_bit_buffer)
  {
   av_free(_bit_buffer);
   _bit_buffer=0;
  }
  
  x264_encoder_close(_h);
 }
 
 //only accept row images (rgb888)
 bool compress(unsigned char* frame)
 {
  memcpy(reinterpret_cast<void*>(_pic.img.plane[0]), reinterpret_cast<void*

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值