zoukankan      html  css  js  c++  java
  • 01.mp4v2应用—mp4转h264

    1.h264文件基本功能

    NAL 头 0x00 0x00 0x00 0x01 
    sps :nal+0x67开头 
    pps :nal+0x68开头

    I帧 0x65 开头 

    ......

    2.mp4v2提取264文件的代码

    #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)
    {
        if(!oMp4File) return -1;
        char NAL[5] = {0x00,0x00,0x00,0x01};    
        unsigned char *pData = NULL;
        unsigned int nSize = 0;
        MP4Timestamp pStartTime;
        MP4Duration pDuration;
        MP4Duration pRenderingOffset;
        bool pIsSyncSample = 0;
    
        int nReadIndex = 0;
        FILE *pFile = NULL;
        pFile = fopen("out.h264","wb"); 
    
        while(nReadIndex < totalFrame)
        {   
            nReadIndex ++;
            //printf("nReadIndex:%d
    ",nReadIndex);
            MP4ReadSample(oMp4File,VTrackId,nReadIndex,&pData,&nSize,&pStartTime,&pDuration,&pRenderingOffset,&pIsSyncSample);
    
            //IDR֡ 帧,写入sps pps先
            if(pIsSyncSample)
            {
                fwrite(NAL,4,1,pFile);
                fwrite(sps,spslen,1,pFile);
    
                fwrite(NAL,4,1,pFile);
                fwrite(pps,ppslen,1,pFile);
    
            }
            //264frame
            if(pData && nSize > 4)
            {
                //标准的264帧,前面几个字节就是frame的长度.
                //需要替换为标准的264 nal 头.
                pData[0] = 0x00;
                pData[1] = 0x00;
                pData[2] = 0x00;
                pData[3] = 0x01;
                fwrite(pData,nSize,1,pFile);
            }
    
            //如果传入MP4ReadSample的视频pData是null
            // 它内部就会new 一个内存
            //如果传入的是已知的内存区域,
            //则需要保证空间bigger then max frames size.
            free(pData);
            pData = NULL;
        }       
        fflush(pFile);
        fclose(pFile);  
    
        return 0;
    }
    int openmp4file(char *sMp4file)
    {
        MP4FileHandle oMp4File;
        int i;
    
        //unsigned int oStreamDuration;
        unsigned int oFrameCount;
    
        oMp4File = MP4Read(sMp4file);
        int videoindex = -1,audioindex = -1;
        uint32_t numSamples;
        //uint32_t timescale;
        //uint64_t duration;        
    
        if (!oMp4File)
        {
            printf("Read error....%s
    ",sMp4file);
            return -1;
        }
    
        MP4TrackId trackId = MP4_INVALID_TRACK_ID;
        uint32_t numTracks = MP4GetNumberOfTracks(oMp4File,NULL,0);
        printf("numTracks:%d
    ",numTracks);
    
        for (i = 0; i < numTracks; i++)
        {
            trackId = MP4FindTrackId(oMp4File, i,NULL,0);
            const char* trackType = MP4GetTrackType(oMp4File, trackId);
            if (MP4_IS_VIDEO_TRACK_TYPE(trackType))
            {
                //printf("[%s %d] trackId:%d
    ",__FUNCTION__,__LINE__,trackId);
                videoindex= trackId;
    
                //duration = MP4GetTrackDuration(oMp4File, trackId );
                numSamples = MP4GetTrackNumberOfSamples(oMp4File, trackId);
                //timescale = MP4GetTrackTimeScale(oMp4File, trackId);          
                //oStreamDuration = duration/(timescale/1000);          
                oFrameCount = numSamples;
    
                // 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);
    
                for (ix = 0; seqheadersize[ix] != 0; ix++)
                {
                    memcpy(sps, seqheader[ix], seqheadersize[ix]);
                    spslen = seqheadersize[ix];
                    free(seqheader[ix]);
                }
                free(seqheader);
                free(seqheadersize);
    
                for (ix = 0; pictheadersize[ix] != 0; ix++)
                {
                    memcpy(pps, pictheader[ix], pictheadersize[ix]);
                    ppslen = pictheadersize[ix];
                    free(pictheader[ix]);
                }
              free(pictheader);
                    free(pictheadersize);
            }131         else if (MP4_IS_AUDIO_TRACK_TYPE(trackType))
            {
                audioindex = trackId;
                printf("audioindex:%d
    ",audioindex);
            }   
        }
    
        //解析完了mp4,主要是为了获取sps pps 还有video的trackID
        if(videoindex >= 0)
            get264stream(oMp4File,videoindex,oFrameCount);  
    
        //需要mp4close 否则在嵌入式设备打开mp4上多了会内存泄露挂掉.
        MP4Close(oMp4File,0);   
        return 0;
    }
    
    int main(void)
    {
        openmp4file("test.mp4");    
        return 0;
    }
  • 相关阅读:
    根据指定的编码格式返回请求的参数集合
    【C++ 学习笔记】 size_t 和 int
    C++ 编译错误
    【Flex】 加载Gif文件
    【C++ 学习笔记】:STLmap
    【C++ 学习笔记】:MFC(细节部分)
    小卡的土豆园开园了~
    [论文笔记] A novel reduction approach to analyzing QoS of workflow processes (Concurrency and Computation: Practice and Experience, 2009)
    [论文收集] WWW2008 相关或感兴趣的论文
    [论文泛读] Accurate and efficient stochastic reliability analysis of composite services using their compact Markov reward model representations (SCC, 2007)
  • 原文地址:https://www.cnblogs.com/Lwd-linux/p/7390951.html
Copyright © 2011-2022 走看看