使用mp4v2解码mp4转成h264码流和aac码流

以下代码是通过往后是网上查找的资料,自己改动了下代码,适和自己使用mp4v2编码成的mp4文件的解码,其他的mp4文件没测试过,至于aac解码正在调试,调试好后统一加上来。因为是改动的别人的代码,所以代码比较凌乱,没整理过。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <time.h> 
#include <sys/time.h>
#include <mp4v2/mp4v2.h>

unsigned char sps[64],pps[64];
int spslen = 0,ppslen = 0;

int get264stream(MP4FileHandle oMp4File,int VTrackId,int totalFrame,char *name)
{
    if(!oMp4File) return -1;
    char NAL[5] = {0x00,0x00,0x00,0x01};    
    unsigned char *pData = NULL;
    unsigned char *p = NULL;
    unsigned int i=0;
    unsigned int nSize = 0;
    MP4Timestamp pStartTime;
    MP4Duration pDuration;
    MP4Duration pRenderingOffset;
    unsigned long framesize=0x00000000;
    bool pIsSyncSample = 0;

    int nReadIndex = 0;
    FILE *pFile = NULL;
    pFile = fopen(name,"wb"); 

    while(nReadIndex < totalFrame)
    {   
        nReadIndex ++;
        //printf("nReadIndex:%d\n",nReadIndex);
        MP4ReadSample(oMp4File,VTrackId,nReadIndex,&pData,&nSize,&pStartTime,&pDuration,&pRenderingOffset,&pIsSyncSample);
        p = pData;
        while(nSize > 0){
            fwrite(NAL,4,1,pFile);
            framesize = 0x0;
            framesize |= *pData<<24;
            framesize |= *(pData+1)<<16;
            framesize |= *(pData+2)<<8;
            framesize |= *(pData+3);
            printf("nSize=%d\n",nSize);
            nSize = nSize-framesize-4;
            printf("framesize=%x,nSize=%d\n",framesize,nSize);
            pData = pData+4;
            fwrite(pData,framesize,1,pFile);
            if(nSize > 0)
                pData=pData+framesize;
        }
        
        //如果传入MP4ReadSample的视频pData是null
        // 它内部就会new 一个内存
        //如果传入的是已知的内存区域,
        //则需要保证空间bigger then max frames size.
        free(p);
        pData = NULL;
        p = NULL;
    }       
    fflush(pFile);
    fclose(pFile);  

    return 0;
}
#if 0
int GetAacStream(MP4FileHandle oMp4File,int ATrackId,int totalFrame,char *name)
{
    if(!oMp4File) return -1;
    char NAL[5] = {0x00,0x00,0x00,0x01};    
    unsigned char *pData = NULL;
    unsigned char *p = NULL;
    unsigned int i=0;
    unsigned int nSize = 0;
    MP4Timestamp pStartTime;
    MP4Duration pDuration;
    MP4Duration pRenderingOffset;
    unsigned long framesize=0x00000000;

    int nReadIndex = 0;
    FILE *pFile = NULL;
    pFile = fopen(name,"wb"); 

    while(nReadIndex < totalFrame)
    {   
        nReadIndex ++;
  
        MP4ReadSample(oMp4File,ATrackId,nReadIndex,&pData,&nSize,&pStartTime,&pDuration,&pRenderingOffset,&pIsSyncSample);
        p = pData;
        fwrite(pData,nsize,1,pFile);
        
        
        //如果传入MP4ReadSample的视频pData是null
        // 它内部就会new 一个内存
        //如果传入的是已知的内存区域,
        //则需要保证空间bigger then max frames size.
        free(p);
        pData = NULL;
        p = NULL;
    }       
    fflush(pFile);
    fclose(pFile);  

  
    return 0;
}
#endif
int openmp4file(char *sMp4file,char *Vname,char *Aname)
{
    MP4FileHandle oMp4File;
    int i;

    //unsigned int oStreamDuration;
    unsigned int VFrameCount;
    unsigned int AFrameCount;

    oMp4File = MP4Read(sMp4file);
    int videoindex = -1,audioindex = -1;
    uint32_t VnumSamples;
    uint32_t AnumSamples;
    //uint32_t timescale;
    //uint64_t duration;        

    if (!oMp4File)
    {
        printf("Read error....%s\r\n",sMp4file);
        return -1;
    }

    MP4TrackId trackId = MP4_INVALID_TRACK_ID;
    uint32_t numTracks = MP4GetNumberOfTracks(oMp4File,NULL,0);//获取音视频轨道数 2 
    printf("numTracks:%d\n",numTracks);

    for (i = 0; i < numTracks; i++)
    {
        trackId = MP4FindTrackId(oMp4File, i,NULL,0); //获取trackId,判断获取数据类型 1 获取视频数据,2 获取音频数据
        printf("trackId:%d\n",trackId);
        const char* trackType = MP4GetTrackType(oMp4File, trackId);
        if (MP4_IS_VIDEO_TRACK_TYPE(trackType)){
            //printf("[%s %d] trackId:%d\r\n",__FUNCTION__,__LINE__,trackId);
            videoindex= trackId;

            //duration = MP4GetTrackDuration(oMp4File, trackId );
            VnumSamples = MP4GetTrackNumberOfSamples(oMp4File, trackId);
            //timescale = MP4GetTrackTimeScale(oMp4File, trackId);          
            //oStreamDuration = duration/(timescale/1000);          
            VFrameCount = VnumSamples;
#if 0
            // read sps/pps 
            uint8_t **seqheader;
            uint8_t **pictheader;
            uint32_t *pictheadersize;
            uint32_t *seqheadersize;
            uint32_t ix;
            MP4GetTrackH264SeqPictHeaders(oMp4File, trackId, &seqheader, &seqheadersize, &pictheader, &pictheadersize);//读取pps和sps

            for (ix = 0; seqheadersize[ix] != 0; ix++)
            {
                memcpy(sps, seqheader[ix], seqheadersize[ix]);//获取sps
                spslen = seqheadersize[ix];
                free(seqheader[ix]);
            }
            free(seqheader);
            free(seqheadersize);
            for (ix =0;pictheader[ix]!=0;ix++)
            {
                memcpy(pps,pictheader[ix],pictheadersize[ix]); //获取pps
                ppslen=pictheadersize[ix];
                free(pictheader[ix]);
            }
                free(pictheader);
                free(pictheadersize);
#endif
        }else if (MP4_IS_AUDIO_TRACK_TYPE(trackType)){
            audioindex = trackId;
             AnumSamples = MP4GetTrackNumberOfSamples(oMp4File, trackId);
             AFrameCount = AnumSamples;
          //  printf("audioindex:%d\n",audioindex);
        }   
    }
    //解析完了mp4,主要是为了获取sps pps 还有video的trackID
    if(videoindex >= 0){
        get264stream(oMp4File,videoindex,VFrameCount,Vname);  
    }else if(audioindex >= 0){
        //GetAacStream(oMp4File,aduindex,AFrameCount,Aname);
    }

    //需要mp4close 否则在嵌入式设备打开mp4上多了会内存泄露挂掉.
    MP4Close(oMp4File,0);   
    return 0;
}

int main(int argc,char **argv)
{
    openmp4file(argv[1],argv[2],argv[3]);    
    return 0;
}

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值