使用mp4v2封装H.264成mp4最简单示例

使用mp4v2封装h.264成mp4最简单示例


几个重要的API

  • MP4Create

    /*
     * 函数功能:创建一个mp4文件
     * 参数:fileName - mp4文件名
     * 参数:flags - 设置属性(MP4_CREATE_64BIT_DATA、MP4_CREATE_64BIT_TIME)
     * 返回值:mp4文件的句柄 */
    
    MP4FileHandle MP4Create(
        const char* fileName,
        uint32_t    flags DEFAULT(0) );
    
  • MP4Close

    /*
     * 函数功能:关闭mp4文件,在写入mp4文件后必须调用此函数,不然mp4文件会损坏
     * 参数:hFile - mp4文件的句柄
     */
    
    void MP4Close(
        MP4FileHandle hFile,
        uint32_t    flags DEFAULT(0) );
    
  • MP4AddH264VideoTrack

    /*
     * 函数功能:添加track,相当于添加一路流
     * 参数:hFile - mp4文件的句柄
     * 参数:width - 视频宽度
     * 参数:height - 视频高度
     * 参数:AVCProfileIndication - sps[1]
     * 参数:profile_compat - sps[2]
     * 参数:AVCLevelIndication - sps[3]
     * 参数:sampleLenFieldSizeMinusOne - 设置为3即可
     * 返回值:添加track的id
     */
    MP4TrackId MP4AddH264VideoTrack(
        MP4FileHandle hFile,
        uint32_t      timeScale,
        MP4Duration   sampleDuration,
        uint16_t      width,
        uint16_t      height,
        uint8_t       AVCProfileIndication,
        uint8_t       profile_compat,
        uint8_t       AVCLevelIndication,
        uint8_t       sampleLenFieldSizeMinusOne );
    
  • MP4AddH264SequenceParameterSet

    /*
     * 函数功能:添加sps到mp4文件
     * 参数:hFile - mp4文件的句柄
     * 参数:pSequence - 指向sps的指针
     * 参数:sequenceLen - sps的长度
     */
    MP4V2_EXPORT
    void MP4AddH264SequenceParameterSet(
        MP4FileHandle  hFile,
        MP4TrackId     trackId,
        const uint8_t* pSequence,
        uint16_t       sequenceLen );
    
  • MP4AddH264PictureParameterSet

    /*
     * 函数功能:添加sps到mp4文件
     * 参数:hFile - mp4文件的句柄
     * 参数:pPict - 指向pps的指针
     * 参数:pictLen - pps的长度
     */
    void MP4AddH264PictureParameterSet(
        MP4FileHandle  hFile,
        MP4TrackId     trackId,
        const uint8_t* pPict,
        uint16_t       pictLen );
    
  • MP4WriteSample

    /*
     * 函数功能:写入nalu
     * 参数:hFile - mp4文件的句柄
     * 注意:前四个字节表示该nalu的长度
     */
    bool MP4WriteSample(
        MP4FileHandle  hFile,
        MP4TrackId     trackId,
        const uint8_t* pBytes,
        uint32_t       numBytes,
        MP4Duration    duration DEFAULT(MP4_INVALID_DURATION),
        MP4Duration    renderingOffset DEFAULT(0),
        bool           isSyncSample DEFAULT(true) );
    

封装流程

sps
pps
其他类型的nalu
MP4Create
MP4AddH264VideoTrack
MP4AddH264SequenceParameterSet
MP4AddH264PictureParameterSet
MP4WriteSample

源码

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <mp4v2/mp4v2.h>

int getNalu(FILE *pFile, unsigned char *pNalu)
{
    unsigned char c;
    int pos = 0;
    int len;

    if(!pFile)
        return -1;

    if((len = fread(pNalu, 1, 4, pFile)) <= 0)
        return -1;

    if(pNalu[0] != 0 || pNalu[1] != 0 || pNalu[2] != 0 || pNalu[3] != 1)
        return -1;

    pos = 4;

    while(1)
    {
        if(feof(pFile))
            break;

        pNalu[pos] = fgetc(pFile);
        
        if(pNalu[pos-3] == 0 && pNalu[pos-2] == 0 && pNalu[pos-1] == 0 && pNalu[pos] == 1)
        {
            fseek(pFile, -4, SEEK_CUR);
            pos -= 4;
            break;
        }

        pos++;
    }

    len = pos+1;

    return len;
}

int packet2Mp4(const char *inputFile, const char *outputFiles)
{
    FILE *pIn = NULL;
    unsigned char *pBuf = malloc(1024*1024);
    unsigned char *pNalu = NULL;
    unsigned char naluType;
    int len;
    int num = 0;
    MP4FileHandle pHandle = NULL;
    MP4TrackId videoId;
	int width = 640;
	int height = 480;
	int frameRate = 15;
	int timeScale = 90000;
    int addStream = 1;

    pIn = fopen(inputFile, "rb");
    if(!pIn)
        return -1;

    pHandle = MP4Create(outputFiles, 0);
    if(pHandle == MP4_INVALID_FILE_HANDLE)
    {
		printf("ERROR:Create mp4 handle fialed.\n");
		return -1;
    }

    MP4SetTimeScale(pHandle, timeScale);

    while(1)
    {
        len = getNalu(pIn, pBuf);
        if (len <= 0)
            break;

        if (pBuf[0] != 0 || pBuf[1] != 0 || pBuf[2] != 0 || pBuf[3] != 1)
            continue;

        len -= 4;
        pNalu = pBuf+4;
        naluType = pNalu[0]&0x1F;

        switch (naluType)
        {
            case 0x07: // SPS
                printf("------------------------------------\n");
                printf("sps(%d)\n", len);
                if (addStream)
                {
                    videoId = MP4AddH264VideoTrack
                            (pHandle, 
                            timeScale,              // 一秒钟多少timescale
                            timeScale/frameRate,    // 每个帧有多少个timescale
                            width,                  // width
                            height,                 // height
                            pNalu[1],               // sps[1] AVCProfileIndication
                            pNalu[2],               // sps[2] profile_compat
                            pNalu[3],               // sps[3] AVCLevelIndication
                            3);                     // 4 bytes length before each NAL unit
                    if (videoId == MP4_INVALID_TRACK_ID)
                    {
                        printf("Error:Can't add track.\n");
                        return -1;
                    }
                    
                    MP4SetVideoProfileLevel(pHandle, 0x7F);

                    addStream = 0;
                }

                MP4AddH264SequenceParameterSet(pHandle, videoId, pNalu, len);

                break;
            
            case 0x08: // PPS
                printf("pps(%d)\n", len);
                MP4AddH264PictureParameterSet(pHandle, videoId, pNalu, len);
                break;

            default:
                printf("slice(%d)\n", len);
                pBuf[0] = (len>>24)&0xFF;
                pBuf[1] = (len>>16)&0xFF;
                pBuf[2] = (len>>8)&0xFF;
                pBuf[3] = (len>>0)&0xFF;

                MP4WriteSample(pHandle, videoId, pBuf, len+4, MP4_INVALID_DURATION, 0, 1);

                break;
        }
}

    free(pBuf);
    fclose(pIn);
    MP4Close(pHandle, 0);

    return 0;
}

int main(int argc, char *argv[])
{
    if (packet2Mp4("test.h264", "test.mp4"))
    {
        printf("Error:Packet to Mp4 fail.\n");
        return -1;
    }

    return 0;
}

  • 10
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 17
    评论
### 回答1: mp4v2-master.zip是一个开源的MP4媒体格式库,它专门用于编写和读取MP4文件的元数据。该库包括用于访问和修改MP4文件头、示例和原子数据的API。在实际场景中,它可以用于处理和编辑MP4文件中的音频和视频数据。 此外,mp4v2-master.zip还提供了一些额外的功能,如支持MP4文件的时间戳管理和编码配置、处理具有复杂数据结构的MP4文件的原子数据等。此外,MP4文件的容量可以被使用它优化,使其尽可能小,同时保持数据结构的一致性。 mp4v2-master.zip是一个非常实用的工具,尤其是对于那些需要处理大量的MP4文件的人来说。它不仅能够更加高效地操作MP4文件,还提供了一些额外的功能,使它为一个卓越的MP4文件处理工具。总之,mp4v2-master.zip是一个非常高效、稳定和易于使用的开源库,可以满足MP4文件的许多处理需求。 ### 回答2: mp4v2-master.zip是一个开源软件项目的压缩文件,主要用于MP4视频文件的处理。这个软件项目的代码基于C++语言编写,并被广泛应用于多种嵌入式和移动设备上。 使用mp4v2-master.zip,你可以对MP4视频文件进行多种操作,包括提取音频、添加、编辑和删除元数据、修改视频编解码参数等等。这个软件项目还提供了丰富的API,使得其可以和其他程序集,并提供更灵活的功能和控制。 mp4v2-master.zip的开源许可证允许开发者自由地使用、修改和分发代码,这使得它为了许多视频处理软件的重要组部分。同时,开发者也可以通过贡献自己的代码和修复bug来参与到这个开源项目中。 总之,mp4v2-master.zip是一个强大的MP4视频处理工具,既有简单易用的命令行操作,也提供了丰富的API供开发者使用。它在开源社区中有着广泛的应用和积极的维护,对于MP4视频的处理和开发来说都是一个不错的选择。
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值