【音视频开发(六)】---MP4文件读取,提取H264裸流包

接口:

  static int OpenInputFile(MP4FileHandle &hMP4File, MP4TrackId &m_videoTrackId, uint32_t &numSamples, const char *fileName);
    static int ReadConfigData(MP4FileHandle &hMP4File, MP4TrackId &m_videoTrackId,unsigned char **sps, int *spsSize, unsigned char **pps, int *ppsSize);
    static void CloseInputFile(MP4FileHandle &hMP4File);
    static int ReadH264Data(MP4FileHandle &hMP4File, MP4TrackId &m_videoTrackId, uint32_t numSamples, int  sampleId, unsigned char** ppData,int *size, int cfgsize);
    static void ReleaseConfigData(unsigned char **sps, unsigned char **pps);
    static void ReleaseH264Data(unsigned char** ppData);

打开输入文件,查找视频轨:


int Mp4v2Util::OpenInputFile(MP4FileHandle &hMP4File, MP4TrackId &m_videoTrackId, uint32_t &numSamples, const char *fileName)
{
    if (hMP4File == NULL) {
        DM_NATIVE_ERR_PRINT("open file %s.\n", fileName);
        hMP4File = MP4Read(fileName);
        if (hMP4File == MP4_INVALID_FILE_HANDLE)    {
            DM_NATIVE_ERR_PRINT("open file failed %s.\n", fileName);
            return -1;
        }
        uint32_t trackId = MP4_INVALID_TRACK_ID;
        uint32_t numOfTracks = MP4GetNumberOfTracks(hMP4File);
        DM_NATIVE_ERR_PRINT("numOfTracks=%d\n", numOfTracks);
        // find video track
        for (uint32_t tmpTrackId = 1; tmpTrackId <= numOfTracks; tmpTrackId++) {

            const char* trackType = MP4GetTrackType(hMP4File, tmpTrackId);
            DM_NATIVE_ERR_PRINT("%d trackType=%s\n", tmpTrackId, trackType);
            if (MP4_IS_VIDEO_TRACK_TYPE(trackType)) {
                trackId = tmpTrackId;
                break;
            }
        }
        if (trackId == MP4_INVALID_TRACK_ID) {
            DM_NATIVE_ERR_PRINT("Can't find video track\n");
            CloseOutputFile(hMP4File);
            return -1;
        }
        m_videoTrackId = trackId;
        //DM_NATIVE_ERR_PRINT("m_videoTrackId=%d\n", m_videoTrackId);
        numSamples = MP4GetTrackNumberOfSamples(hMP4File, m_videoTrackId);
    }
    return 0;
}

读取视频文件的SPS和PPS:


int Mp4v2Util::ReadConfigData(MP4FileHandle &hMP4File, MP4TrackId &m_videoTrackId,unsigned char **sps, int *spsSize, unsigned char **pps, int *ppsSize)
{
    // read sps/pps
    uint8_t **seqheader;
    uint8_t **pictheader;
    uint32_t *pictheadersize;
    uint32_t *seqheadersize;
    uint32_t ix;
    const char nalHeader[] = {0x00, 0x00, 0x00, 0x01};
    MP4GetTrackH264SeqPictHeaders(hMP4File, m_videoTrackId, &seqheader, &seqheadersize, &pictheader,
                                  &pictheadersize);


    int size = 4;
    //sps
    for (ix = 0; seqheadersize[ix] != 0; ix++) {
        size += seqheadersize[ix];
    }

    *sps = (uint8_t *)malloc(size);
    uint8_t *spsBase =  *sps;
    memcpy(spsBase, nalHeader, 4);
    spsBase += 4;
    for (ix = 0; seqheadersize[ix] != 0; ix++) {
        memcpy(spsBase,seqheader[ix], seqheadersize[ix]);
        spsBase += seqheadersize[ix];
        free(seqheader[ix]);
    }
    free(seqheader);
    free(seqheadersize);
    *spsSize = size;
    //pps
    size = 4;
    for (ix = 0; pictheadersize[ix] != 0; ix++) {
        size += pictheadersize[ix];
    }
    *pps = (uint8_t *)malloc(size);
    uint8_t *ppsBase =  *pps;
    memcpy(ppsBase, nalHeader, 4);
    ppsBase += 4;

    for (ix = 0; pictheadersize[ix] != 0; ix++) {
        memcpy(ppsBase, pictheader[ix], pictheadersize[ix]);
        ppsBase += pictheadersize[ix];
        free(pictheader[ix]);
    }
    free(pictheader);
    free(pictheadersize);
    *ppsSize = size;
    return 0;
}

读取H264裸流编码帧:


int Mp4v2Util::ReadH264Data(MP4FileHandle &hMP4File, MP4TrackId &m_videoTrackId, uint32_t numSamples, int sampleId, unsigned char** ppData,int *size, int cfgsize)
{
    // read samples

    uint8_t* pSample = NULL;
    uint32_t sampleSize = 0;
    const char nalHeader[] = {0x00, 0x00, 0x00, 0x01};

    
        if (!MP4ReadSample(hMP4File, m_videoTrackId, sampleId, &pSample, &sampleSize)) {
            DM_NATIVE_ERR_PRINT("read sampleId %u error\n", sampleId);
            if (pSample != NULL) {
                free(pSample);
                pSample = NULL;
            }
            return -1;
        }

    if (pSample != NULL) {

        uint32_t pktsize = pSample[0];
        pktsize <<= 8;
        pktsize |= pSample[1];
        pktsize <<= 8;
        pktsize |= pSample[2];
        pktsize <<= 8;
        pktsize |= pSample[3];
       // DM_NATIVE_DEBUG_PRINT("test %02X %02X %02X %02X pktsize=%d sampleSize=%d\n",pSample[0],pSample[1],pSample[2],pSample[3], pktsize, sampleSize );
        if((pktsize + 4) == sampleSize) {
            memcpy(pSample, nalHeader, 4);
            *ppData = pSample;
            *size = sampleSize;
        } else if((pktsize + 4) < sampleSize) {
            int leftsize = sampleSize-cfgsize;
            if (leftsize > 4) {
                uint32_t pktsize1 = pSample[cfgsize+0];
                pktsize1 <<= 8;
                pktsize1 |= pSample[cfgsize+1];
                pktsize1 <<= 8;
                pktsize1 |= pSample[cfgsize+2];
                uint32_t pktsize2 = pktsize1;
                pktsize1 <<= 8;
                pktsize1 |= pSample[cfgsize+3];
                if ((pktsize2+3) == leftsize) {
                    memcpy(&pSample[cfgsize], &nalHeader[1], 3);
                }else if ((pktsize2+4) == leftsize) {
                    memcpy(&pSample[cfgsize], &nalHeader[0], 4);
                }
            }
            memcpy(pSample, nalHeader, 4);
            *ppData = pSample;
            *size = sampleSize;
        } else {
            DM_NATIVE_ERR_PRINT("ReadH264Data ERR %02X %02X %02X %02X\n",pSample[0],pSample[1],pSample[2],pSample[3] );
            free(pSample);

            *ppData = NULL;
            *size = 0;
        }
        return 0;
    }

  
    return -2;
}

释放数据:


void Mp4v2Util::ReleaseConfigData(unsigned char **sps, unsigned char **pps)
{
    if(*sps) {
        free(*sps);
        *sps = NULL;
    }
    if(*pps) {
        free(*pps);
        *pps = NULL;
    }
}


void Mp4v2Util::ReleaseH264Data(unsigned char** ppData)
{
    if(*ppData) {
        free(*ppData);
        *ppData = NULL;
    }
}

关闭文件:

void Mp4v2Util::CloseInputFile(MP4FileHandle &hMP4File)
{
    DM_NATIVE_DEBUG_PRINT("CloseOutputFile end\n");
    if(hMP4File) MP4Close(hMP4File, 0);
    hMP4File = NULL;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值