MP4v2封装H264文件,时长只有1s
#include "MP4Encoder.h"
#include
#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*/)
{
MP4FileHandle hMp4file = MP4Create(pFileName);
if(pFileName == NULL)
{
return hMp4file;
}
// create mp4 file
if (hMp4file == MP4_INVALID_FILE_HANDLE)
{
printf("ERROR:Open file fialed.\n");
return hMp4file;
}
m_nWidth = width;
m_nHeight = height;
m_nTimeScale = 90000;
m_nFrameRate = 30;
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))
{
printf("size %d pos %d nalu-type %d nalu-size %d\n",size,pos,nalu.type,nalu.size);
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))
{
printf("write nok!\n");
delete[] data;
return 0;
}
// fflush(hMp4File);
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(iif(buffer[i++] == 0x00 &&
buffer[i++] == 0x00 &&
buffer[i++] == 0x00 &&
buffer[i++] == 0x01
)
{
int pos = i;
while (posif(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,1920,1080);
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;
}
}
static int cnt = 0;
printf("writeH264Data start %d\n",cnt++);
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的库也查看了生成的视频信息(由于篇幅设置,只截取了部分log),共有15个track,理论上应该对应15s,但转化后的视频时长就1s,
搞不懂为什么,求帮忙解答,谢谢
./mp4trackdump version 2.0.0
mp4file test.mp4, track 1, samples 30, timescale 90000
sampleId 1, size 29107 duration 3000 time 0 00:00:00.000 S
sampleId 2, size 864 duration 3000 time 3000 00:00:00.033 S
sampleId 3, size 2129 duration 3000 time 6000 00:00:00.066 S
sampleId 4, size 9758 duration 3000 time 9000 00:00:00.100 S
sampleId 5, size 547 duration 3000 time 12000 00:00:00.133 S
sampleId 6, size 2318 duration 3000 time 15000 00:00:00.166 S
sampleId 7, size 11209 duration 3000 time 18000 00:00:00.200 S
sampleId 8, size 502 duration 3000 time 21000 00:00:00.233 S
sampleId 9, size 3837 duration 3000 time 24000 00:00:00.266 S
sampleId 10, size 1391 duration 3000 time 27000 00:00:00.300 S
sampleId 11, size 8701 duration 3000 time 30000 00:00:00.333 S
sampleId 12, size 702 duration 3000 time 33000 00:00:00.366 S
sampleId 13, size 4360 duration 3000 time 36000 00:00:00.400 S
sampleId 14, size 884 duration 3000 time 39000 00:00:00.433 S
sampleId 15, size 8617 duration 3000 time 42000 00:00:00.466 S
sampleId 16, size 1174 duration 3000 time 45000 00:00:00.500 S
sampleId 17, size 5123 duration 3000 time 48000 00:00:00.533 S
sampleId 18, size 1365 duration 3000 time 51000 00:00:00.566 S
sampleId 19, size 4155 duration 3000 time 54000 00:00:00.600 S
sampleId 20, size 1937 duration 3000 time 57000 00:00:00.633 S
sampleId 21, size 8139 duration 3000 time 60000 00:00:00.666 S
sampleId 22, size 1478 duration 3000 time 63000 00:00:00.700 S
sampleId 23, size 5250 duration 3000 time 66000 00:00:00.733 S
sampleId 24, size 1269 duration 3000 time 69000 00:00:00.766 S
sampleId 25, size 4455 duration 3000 time 72000 00:00:00.800 S
sampleId 26, size 1160 duration 3000 time 75000 00:00:00.833 S
sampleId 27, size 3511 duration 3000 time 78000 00:00:00.866 S
sampleId 28, size 1066 duration 3000 time 81000 00:00:00.900 S
sampleId 29, size 2945 duration 3000 time 84000 00:00:00.933 S
sampleId 30, size 2569 duration 3000 time 87000 00:00:00.966 S
mp4file test.mp4, track 2, samples 29, timescale 90000
sampleId 1, size 48220 duration 3000 time 0 00:00:00.000 S
sampleId 2, size 20471 duration 3000 time 3000 00:00:00.033 S
sampleId 3, size 1409 duration 3000 time 6000 00:00:00.066 S
sampleId 4, size 4455 duration 3000 time 9000 00:00:00.100 S
sampleId 5, size 3027 duration 3000 time 12000 00:00:00.133 S
sampleId 6, size 491 duration 3000 time 15000 00:00:00.166 S
sampleId 7, size 2313 duration 3000 time 18000 00:00:00.200 S
sampleId 8, size 985 duration 3000 time 21000 00:00:00.233 S
sampleId 9, size 8041 duration 3000 time 24000 00:00:00.266 S
sampleId 10, size 743 duration 3000 time 27000 00:00:00.300 S
sampleId 11, size 4510 duration 3000 time 30000 00:00:00.333 S
sampleId 12, size 500 duration 3000 time 33000 00:00:00.366 S
sampleId 13, size 3416 duration 3000 time 36000 00:00:00.400 S
sampleId 14, size 300 duration 3000 time 39000 00:00:00.433 S
sampleId 15, size 2704 duration 3000 time 42000 00:00:00.466 S
sampleId 16, size 681 duration 3000 time 45000 00:00:00.500 S
sampleId 17, size 6881 duration 3000 time 48000 00:00:00.533 S
sampleId 18, size 657 duration 3000 time 51000 00:00:00.566 S
sampleId 19, size 5333 duration 3000 time 54000 00:00:00.600 S
sampleId 20, size 607 duration 3000 time 57000 00:00:00.633 S
sampleId 21, size 3735 duration 3000 time 60000 00:00:00.666 S
sampleId 22, size 855 duration 3000 time 63000 00:00:00.700 S
sampleId 23, size 1478 duration 3000 time 66000 00:00:00.733 S
sampleId 24, size 411 duration 3000 time 69000 00:00:00.766 S
sampleId 25, size 1518 duration 3000 time 72000 00:00:00.800 S
sampleId 26, size 321 duration 3000 time 75000 00:00:00.833 S
sampleId 27, size 1121 duration 3000 time 78000 00:00:00.866 S
sampleId 28, size 433 duration 3000 time 81000 00:00:00.900 S
sampleId 29, size 288 duration 3000 time 84000 00:00:00.933 S
mp4file test.mp4, track 3, samples 29, timescale 90000
sampleId 1, size 53770 duration 3000 time 0 00:00:00.000 S
sampleId 2, size 5786 duration 3000 time 3000 00:00:00.033 S
sampleId 3, size 700 duration 3000 time 6000 00:00:00.066 S
不知道你这个问题是否已经解决, 如果还没有解决的话: