/********************************************************************
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 file
MP4FileHandle 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, // width
m_nHeight,// height
lpMetadata->Sps[1], // sps[1] AVCProfileIndication
lpMetadata->Sps[2], // sps[2] profile_compat
lpMetadata->Sps[3], // sps[3] AVCLevelIndication
3); // 4 bytes length before each NAL unit
if (m_videoId == MP4_INVALID_TRACK_ID)
{
printf("add video track failed.\n");
return false;
}
MP4SetVideoProfileLevel(hMp4File, 0x01); // Simple Profile @ Level 3
// write sps
MP4AddH264SequenceParameterSet(hMp4File, m_videoId, lpMetadata->Sps, lpMetadata->nSpsLen);
// write pps
MP4AddH264PictureParameterSet(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, // width
m_nHeight, // height
nalu.data[1], // sps[1] AVCProfileIndication
nalu.data[2], // sps[2] profile_compat
nalu.data[3], // sps[3] AVCLevelIndication
3); // 4 bytes length before each NAL unit
if (m_videoId == MP4_INVALID_TRACK_ID)
{
printf("add video track failed.\n");
return 0;
}
MP4SetVideoProfileLevel(hMp4File, 1); // Simple Profile @ Level 3
MP4AddH264SequenceParameterSet(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, 1280, 720);
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;
}
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
收起资源包目录
mp4v2Test.rar (44个子文件)
mp4v2Test
mp4v2Test.sdf 2.69MB
mp4v2Test
mp4v2Test.cpp 245B
libmp4v2.dll 603KB
MP4Encoder.cpp 6KB
mp4v2Test.vcxproj 4KB
test.mp4 610KB
mp4v2Test.vcxproj.user 165B
include
mp4v2
chapter.h 6KB
streaming.h 4KB
file.h 14KB
track.h 13KB
project.h.in 2KB
platform.h 2KB
project.h 2KB
itmf_generic.h 9KB
isma.h 3KB
itmf_tags.h 11KB
sample.h 22KB
file_prop.h 4KB
general.h 16KB
mp4v2.h 2KB
track_prop.h 8KB
MP4Encoder.h 2KB
lib
libmp4v2.lib 165KB
Debug
MP4Encoder.obj 19KB
vc120.pdb 84KB
mp4v2Test.log 2KB
vc120.idb 107KB
mp4v2Test.Build.CppClean.log 892B
mp4v2Test.obj 8KB
mp4v2Test.tlog
CL.write.1.tlog 1KB
CL.read.1.tlog 7KB
cl.command.1.tlog 1KB
link.write.1.tlog 574B
mp4v2Test.lastbuildstate 165B
link.command.1.tlog 1KB
link.read.1.tlog 3KB
mp4v2Test.vcxproj.filters 1KB
output.h264 614KB
mp4v2Test.v12.suo 23KB
mp4v2Test.sln 973B
Debug
mp4v2Test.ilk 262KB
mp4v2Test.pdb 500KB
mp4v2Test.exe 40KB
共 44 条
- 1
资源评论
余莫星辰
- 粉丝: 764
- 资源: 51
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功