MP4v2封装H264文件,时长只有1s

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





不知道你这个问题是否已经解决, 如果还没有解决的话:

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^