mp4文件moov位置提前

时间:2024-03-16 08:23:35

转载请标明出处:https://blog.csdn.net/u013752202/article/details/80557556

文中使用到的工具说明:https://blog.csdn.net/u013752202/article/details/80556729

通过http协议在线播放mp4视频的时候,往往需要把moov信息放在mdat的前面(特别是再IOS浏览器上在线播放),而由录像设备生成的mp4文件一般来说moov信息都位于mdat之后。

为了能够在线播放,就需要把moov信息的位置提前。

下面的代码即可以实现mdat和moov位置调换,先找到mdat和moov的在文件中的偏移和大小,然后再调换位置:

#include <stdio.h>
#include <malloc.h>
#include <string.h>

#define SWAP_EDIAN_U32(X) (((0x000000ff&X)<<24)|((0x0000ff00&X)<<8)|((0x00ff0000&X)>>8)|((0xff000000&X)>>24))

typedef unsigned long long int VSize_t ;

#pragma pack(1)
typedef struct{
    unsigned int len;
    char name[4];
    unsigned int offset;
}MP4Box;
#pragma pack()


int findBox(const char *vidname,MP4Box *box)
{
    FILE *vfp=fopen(vidname,"rb");
    if(NULL==vfp){
        printf("[%s-%d]:Open %s failed !\n",__func__,__LINE__,vidname);
        return -1;
    }
    fseek(vfp,0,SEEK_END);
    VSize_t flen=ftell(vfp);
    fseek(vfp,0,SEEK_SET);

    VSize_t rlen=0;
    int ret=0;
    while(rlen<flen){
        MP4Box boxtmp;
        if(8!=fread((unsigned char *)&boxtmp,1,8,vfp)){
            printf("[%s-%d]:Read %s error !\n",__func__,__LINE__,vidname);
            ret=-1;
            break;
        }        
        char srcname[5];
        char dstname[5];    
        memcpy(srcname,boxtmp.name,4);
        srcname[4]=0;
        memcpy(dstname,box->name,4);
        dstname[4]=0;
        //printf("rlen=%x\n",rlen);
        //int t=0;
        //unsigned char *ppp=(unsigned char *)&boxtmp;
        //for(t=0;t<8;t++){
        //    printf("%02x ",ppp[t]);
        //}
        //printf("\n");
        VSize_t boxLen=SWAP_EDIAN_U32(boxtmp.len);
        if(boxLen<8){
            printf("[%s-%d]:%s file damage\n",__func__,__LINE__,vidname);
            ret=-1;
            break;
        }
        if(0==strcmp(srcname,dstname)){
            memcpy((unsigned char *)box,(unsigned char *)&boxtmp,8);
            if(rlen+boxLen>flen){
                ret=0;
                break;
            }
            box->offset=ftell(vfp)-8;
            ret=1;
            break;
        }
        else{
            if(rlen+boxLen>flen){
                printf("[%s-%d]:Box length beyond file !\n",__func__,__LINE__);
                ret=0;
                break;
            }
            fseek(vfp,boxLen-8,SEEK_CUR);
            rlen+=boxLen;
        }
    }
    fclose(vfp);
    return ret;
}

int main(int argc,char **argv)
{
    if(3!=argc){
        printf("Usage:\n");
        printf("mp4ThumbPick test.mp4 out.mp4");
    }

    MP4Box matBox,moovBox;
    {
        char dstName[4]={'m','d','a','t'};
        memcpy(matBox.name,dstName,4);
        if(findBox(argv[1],&matBox)>0){
            printf("mdat offset:0x%08x\n",matBox.offset);    
        }
    }
    {
        char dstName[4]={'m','o','o','v'};
        memcpy(moovBox.name,dstName,4);
        if(findBox(argv[1],&moovBox)>0){
            printf("moov offset:0x%08x\n",moovBox.offset);    
        }
    }

    int matLen=SWAP_EDIAN_U32(matBox.len);
    int moovLen=SWAP_EDIAN_U32(moovBox.len);
    printf("matBox.offset:%d,matBox.len=%d\n",matBox.offset,matLen);
    printf("moovBox.offset:%d,moovBox.len=%d\n",moovBox.offset,moovLen);

    FILE *infp=fopen(argv[1],"rb");
    FILE *outfp=fopen(argv[2],"wb");
    if(NULL==infp||NULL==outfp){
        printf("Open %s/%s error!\n",argv[1],argv[2]);
    }
    fseek(infp,0,SEEK_END);
    int flen=ftell(infp);
    fseek(infp,0,SEEK_SET);
    unsigned char *buf=(unsigned char *)malloc(matBox.offset);
    fread(buf,1,matBox.offset,infp);
    fwrite(buf,1,matBox.offset,outfp);
    free(buf);
    //save moov
        buf=(unsigned char *)malloc(moovLen);
    fseek(infp,moovBox.offset,SEEK_SET);
        fread(buf,1,moovLen,infp);
        fwrite(buf,1,moovLen,outfp);
    free(buf);
    //save mdat
    int rrlen=0,rlen=0;
    buf=(unsigned char *)malloc(1024);
    fseek(infp,matBox.offset,SEEK_SET);
        while(rlen<matLen){
                if(rlen+1024<=matLen){
            rrlen=fread(buf,1,1024,infp);
            fwrite(buf,1,1024,outfp);
            rlen+=rrlen;
        }
        else{
                        rrlen=fread(buf,1,matLen-rlen,infp);
                        fwrite(buf,1,matLen-rlen,outfp);
            break;
        }
    }
    free(buf);
    //after moov
        if(moovBox.offset+moovLen<flen){
                int sparelen=flen-(moovBox.offset+moovLen);
        buf=(unsigned char *)malloc(sparelen);
                fseek(infp,moovBox.offset+moovLen,SEEK_SET);
        fread(buf,1,sparelen,infp);
        fwrite(buf,1,sparelen,outfp);
        free(buf);
    }
    fclose(infp);
    fclose(outfp);
    return 0;
}
tttt.mp4为输入的mp4,moov在mdat后
out.mp4为输出的mp4,moov在mdat前
mp4文件moov位置提前

转载请标明出处:https://blog.csdn.net/u013752202/article/details/80557556