H264视频编码成MP4文件 h264解码器

最近需要将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

classMP4Encoder

{

public:

MP4Encoder(void);

~MP4Encoder(void);

public:

//openorcreatamp4file.

MP4FileHandleCreateMP4File(constchar*fileName,intwidth,intheight,inttimeScale=90000,intframeRate=25);

//wirte264metadatainmp4file.

boolWrite264Metadata(MP4FileHandlehMp4File,LPMP4ENC_MetadatalpMetadata);

//wirte264data,datacancontainmultipleframe.

intWriteH264Data(MP4FileHandlehMp4File,constunsignedchar*pData,intsize);

//closemp4file.

voidCloseMP4File(MP4FileHandlehMp4File);

//convertH264filetomp4file.

//noneedtocallCreateMP4FileandCloseMP4File,itwillcreate/closemp4fileautomaticly.

boolWriteH264File(constchar*pFile264,constchar*pFileMp4);

//PraseH264metamatafromH264dataframe

staticboolPraseMetadata(constunsignedchar*pData,intsize,MP4ENC_Metadata&metadata);

};

客户端调用示例代码:

[cpp] view plaincopy

#include<stdio.h>

#include"MP4EncoderMP4Encoder.h"

intmain(intargc,char**argv)

{

MP4Encodermp4Encoder;

//convertH264filetomp4file

mp4Encoder.WriteH264File("test.264","test.mp4");

}

MP4Encoder完整的代码如下:[cpp] view plaincopy

/********************************************************************

filename:MP4Encoder.h

created:2013-04-16

author:firehood

purpose:MP4编码器,基于开源库mp4v2实现(https://code.google.com/p/mp4v2/)。

H264视频编码成MP4文件 h264解码器
*********************************************************************/

#pragmaonce

#include"mp4v2mp4v2.h"

//NALU单元

typedefstruct_MP4ENC_NaluUnit

{

inttype;

intsize;

unsignedchar*data;

}MP4ENC_NaluUnit;

typedefstruct_MP4ENC_Metadata

{

//video,mustbeh264type

unsignedintnSpsLen;

unsignedcharSps[1024];

unsignedintnPpsLen;

unsignedcharPps[1024];

}MP4ENC_Metadata,*LPMP4ENC_Metadata;

classMP4Encoder

{

public:

MP4Encoder(void);

~MP4Encoder(void);

public:

//openorcreatamp4file.

MP4FileHandleCreateMP4File(constchar*fileName,intwidth,intheight,inttimeScale=90000,intframeRate=25);

//wirte264metadatainmp4file.

boolWrite264Metadata(MP4FileHandlehMp4File,LPMP4ENC_MetadatalpMetadata);

//wirte264data,datacancontainmultipleframe.

intWriteH264Data(MP4FileHandlehMp4File,constunsignedchar*pData,intsize);

//closemp4file.

voidCloseMP4File(MP4FileHandlehMp4File);

//convertH264filetomp4file.

//noneedtocallCreateMP4FileandCloseMP4File,itwillcreate/closemp4fileautomaticly.

boolWriteH264File(constchar*pFile264,constchar*pFileMp4);

//PraseH264metamatafromH264dataframe

staticboolPraseMetadata(constunsignedchar*pData,intsize,MP4ENC_Metadata&metadata);

private:

//readonenalufromH264databuffer

staticintReadOneNaluFromBuf(constunsignedchar*buffer,unsignedintnBufferSize,unsignedintoffSet,MP4ENC_NaluUnit&nalu);

private:

intm_nWidth;

intm_nHeight;

intm_nFrameRate;

intm_nTimeScale;

MP4TrackIdm_videoId;

};

MP4Encoder.cpp

[cpp] view plaincopy

/********************************************************************

filename:MP4Encoder.cpp

created:2013-04-16

author:firehood

purpose:MP4编码器,基于开源库mp4v2实现(https://code.google.com/p/mp4v2/)。

*********************************************************************/

#include"MP4Encoder.h"

#include<string.h>

#defineBUFFER_SIZE(1024*1024)

MP4Encoder::MP4Encoder(void):

m_videoId(NULL),

m_nWidth(0),

m_nHeight(0),

m_nTimeScale(0),

m_nFrameRate(0)

{

}

MP4Encoder::~MP4Encoder(void)

{

}

MP4FileHandleMP4Encoder::CreateMP4File(constchar*pFileName,intwidth,intheight,inttimeScale/*=90000*/,intframeRate/*=25*/)

{

if(pFileName==NULL)

{

returnfalse;

}

//createmp4file

MP4FileHandlehMp4file=MP4Create(pFileName);

if(hMp4file==MP4_INVALID_FILE_HANDLE)

{

printf("ERROR:Openfilefialed.n");

returnfalse;

}

m_nWidth=width;

m_nHeight=height;

m_nTimeScale=90000;

m_nFrameRate=25;

MP4SetTimeScale(hMp4file,m_nTimeScale);

returnhMp4file;

}

boolMP4Encoder::Write264Metadata(MP4FileHandlehMp4File,LPMP4ENC_MetadatalpMetadata)

{

m_videoId=MP4AddH264VideoTrack

(hMp4File,

m_nTimeScale,

m_nTimeScale/m_nFrameRate,

m_nWidth,//width

m_nHeight,//height

lpMetadata->Sps[1],//sps[1]AVCProfileIndication

lpMetadata->Sps[2],//sps[2]profile_compat

lpMetadata->Sps[3],//sps[3]AVCLevelIndication

3);//4byteslengthbeforeeachNALunit

if(m_videoId==MP4_INVALID_TRACK_ID)

{

printf("addvideotrackfailed.n");

returnfalse;

}

MP4SetVideoProfileLevel(hMp4File,0x01);//SimpleProfile@Level3

//writesps

MP4AddH264SequenceParameterSet(hMp4File,m_videoId,lpMetadata->Sps,lpMetadata->nSpsLen);

//writepps

MP4AddH264PictureParameterSet(hMp4File,m_videoId,lpMetadata->Pps,lpMetadata->nPpsLen);

returntrue;

}

intMP4Encoder::WriteH264Data(MP4FileHandlehMp4File,constunsignedchar*pData,intsize)

{

if(hMp4File==NULL)

{

return-1;

}

if(pData==NULL)

{

return-1;

}

MP4ENC_NaluUnitnalu;

intpos=0,len=0;

while(len=ReadOneNaluFromBuf(pData,size,pos,nalu))

{

if(nalu.type==0x07)//sps

{

//添加h264track

m_videoId=MP4AddH264VideoTrack

(hMp4File,

m_nTimeScale,

m_nTimeScale/m_nFrameRate,

m_nWidth,//width

m_nHeight,//height

nalu.data[1],//sps[1]AVCProfileIndication

nalu.data[2],//sps[2]profile_compat

nalu.data[3],//sps[3]AVCLevelIndication

3);//4byteslengthbeforeeachNALunit

if(m_videoId==MP4_INVALID_TRACK_ID)

{

printf("addvideotrackfailed.n");

return0;

}

MP4SetVideoProfileLevel(hMp4File,1);//SimpleProfile@Level3

MP4AddH264SequenceParameterSet(hMp4File,m_videoId,nalu.data,nalu.size);

}

elseif(nalu.type==0x08)//pps

{

MP4AddH264PictureParameterSet(hMp4File,m_videoId,nalu.data,nalu.size);

}

else

{

intdatalen=nalu.size+4;

unsignedchar*data=newunsignedchar[datalen];

//MP4Nalu前四个字节表示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))

{

return0;

}

delete[]data;

}

pos+=len;

}

returnpos;

}

intMP4Encoder::ReadOneNaluFromBuf(constunsignedchar*buffer,unsignedintnBufferSize,unsignedintoffSet,MP4ENC_NaluUnit&nalu)

{

inti=offSet;

while(i<nBufferSize)

{

if(buffer[i++]==0x00&&

buffer[i++]==0x00&&

buffer[i++]==0x00&&

buffer[i++]==0x01

)

{

intpos=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=(unsignedchar*)&buffer[i];

return(nalu.size+i-offSet);

}

}

return0;

}

voidMP4Encoder::CloseMP4File(MP4FileHandlehMp4File)

{

if(hMp4File)

{

MP4Close(hMp4File);

hMp4File=NULL;

}

}

boolMP4Encoder::WriteH264File(constchar*pFile264,constchar*pFileMp4)

{

if(pFile264==NULL||pFileMp4==NULL)

{

returnfalse;

}

MP4FileHandlehMp4File=CreateMP4File(pFileMp4,352,288);

if(hMp4File==NULL)

{

printf("ERROR:Createfilefailed!");

returnfalse;

}

FILE*fp=fopen(pFile264,"rb");

if(!fp)

{

printf("ERROR:openfilefailed!");

returnfalse;

}

fseek(fp,0,SEEK_SET);

unsignedchar*buffer=newunsignedchar[BUFFER_SIZE];

intpos=0;

while(1)

{

intreadlen=fread(buffer+pos,sizeof(unsignedchar),BUFFER_SIZE-pos,fp);

if(readlen<=0)

{

break;

}

readlen+=pos;

intwritelen=0;

for(inti=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);

returntrue;

}

boolMP4Encoder::PraseMetadata(constunsignedchar*pData,intsize,MP4ENC_Metadata&metadata)

{

if(pData==NULL||size<4)

{

returnfalse;

}

MP4ENC_NaluUnitnalu;

intpos=0;

boolbRet1=false,bRet2=false;

while(intlen=ReadOneNaluFromBuf(pData,size,pos,nalu))

{

if(nalu.type==0x07)

{

memcpy(metadata.Sps,nalu.data,nalu.size);

metadata.nSpsLen=nalu.size;

bRet1=true;

}

elseif((nalu.type==0x08))

{

memcpy(metadata.Pps,nalu.data,nalu.size);

metadata.nPpsLen=nalu.size;

bRet2=true;

}

pos+=len;

}

if(bRet1&&bRet2)

{

returntrue;

}

returnfalse;

}

更多0

上一篇:H264视频通过RTMP直播

  

爱华网本文地址 » http://www.aihuau.com/a/25101011/100788.html

更多阅读

rm转mp4,rm怎么转换成mp4? mp4 rm转换专家破解版

现在的网络下载的电影很多都不是自己想要的视频格式,就如优酷、土豆、56、奇艺等等下载的视频格式都是不能在手机电影上播放的格式。所以想要转换成手机支持的电影格式,那么我们就要使用最好用的视频转换器,将其他格式的文件转换成手机

怎样把视频转换成MP4格式 qlv格式怎样转换成mp4

随着手机、MP4等移动终端的流行,MP4视频格式应运而生。由于手机、MP4、iPod、iPhone、PSP、iPad等移动终端对能兼容的视频格式有严格要求,因此要在各大移动终端观看电影视频,对导入的视频就要严格把关,否则轻则播放不流畅,影响观赏效果,重

怎么把xv转换成mp4? xv怎么转换成mp4

怎么把xv转换成mp4?——简介迅雷下载电影,当下载完成之后,如果没有安装有迅雷播放器的,我们可以看到文件是一个不可使用的文件。主要原因是迅雷下载的电影格式是为XV格式,也是迅雷的缓存文件,这种格式文件只能在迅雷特定的播放器上才可以

如何将pdf文件转换成html文件 将html文件转换为pdf

如何将pdf文件转换成html文件——简介pdf文件是我们在工作生活中用的非常多高质量文件格式,有时我们需要将pdf转换成html网页文件,便于嵌入网页中,并且可以提取 PDF 中的图片。如何将pdf文件转换成html文件——工具/原料电脑pdf转换

怎样把RMVB格式的视频转换成MP4格式 rmvb视频格式转换器

我们下载了一些RMVB格式的电影!但是我们想在自己的手机上看!可是我的手机不支持RMVB格式的的电影啊!现在我们就可以用格式工厂来把这些视频转换成MP4的吧!这样我们就能在手机上看这些视频了!怎样把RMVB格式的视频转换成MP4格式——工具

声明:《H264视频编码成MP4文件 h264解码器》为网友我以你为信念分享!如侵犯到您的合法权益请联系我们删除