转载请标明出处: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的在文件中的偏移和大小,然后再调换位置:
需要注意的是,mdat位置变化后,moov下面的stco(chunk offset)也要改成新的offset,否则无法正常寻址播放!

#include <stdio.h>
#include <malloc.h>
#include <string.h>#if _WIN32
#define __func__ __FUNCTION__
#endif#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,int offset)
{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,offset,SEEK_SET);flen-=offset;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;
}void changeStco(unsigned char *buf,int len,int chunkDeta)
{int i=0;unsigned int *pchunkOffset=0;for(i=16;i<len;i+=4){pchunkOffset=(unsigned int *)(buf+i);*pchunkOffset=SWAP_EDIAN_U32(SWAP_EDIAN_U32(*pchunkOffset)+chunkDeta);}
}int main(int argc,char **argv)
{if(3!=argc){printf("Usage:\n");printf("mp4ThumbPick test.mp4 out.mp4");return -1;}MP4Box matBox,moovBox,stcoBox;{char dstName[4]={'m','d','a','t'};memcpy(matBox.name,dstName,4);if(findBox(argv[1],&matBox,0)>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)>0){printf("moov offset:0x%08x\n",moovBox.offset);    }}{MP4Box box;char dstName[4]={'t','r','a','k'};memcpy(box.name,dstName,4);if(findBox(argv[1],&box,moovBox.offset+8)<=0){printf("trak box not founc\n");return -1;}        char dstName1[4]={'m','d','i','a'};memcpy(box.name,dstName1,4);if(findBox(argv[1],&box,box.offset+8)<=0){printf("mdia box not founc\n");return -1;}char dstName2[4]={'m','i','n','f'};memcpy(box.name,dstName2,4);if(findBox(argv[1],&box,box.offset+8)<=0){printf("minf box not founc\n");return -1;}char dstName3[4]={'s','t','b','l'};memcpy(box.name,dstName3,4);if(findBox(argv[1],&box,box.offset+8)<=0){printf("stbl box not founc\n");return -1;}char dstName4[4]={'s','t','c','o'};memcpy(box.name,dstName4,4);if(findBox(argv[1],&box,box.offset+8)<=0){printf("stco box not founc\n");return -1;}stcoBox=box;}int matLen=SWAP_EDIAN_U32(matBox.len);int moovLen=SWAP_EDIAN_U32(moovBox.len);int stcoLen=SWAP_EDIAN_U32(stcoBox.len);printf("matBox.offset:%d,matBox.len=%d\n",matBox.offset,matLen);printf("moovBox.offset:%d,moovBox.len=%d\n",moovBox.offset,moovLen);printf("stcoBox.offset:%d,stcoBox.len=%d\n",stcoBox.offset,stcoLen);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 moovbuf=(unsigned char *)malloc(moovLen);fseek(infp,moovBox.offset,SEEK_SET);fread(buf,1,moovLen,infp);changeStco(buf+stcoBox.offset-moovBox.offset,stcoLen,moovLen);fwrite(buf,1,moovLen,outfp);free(buf);//save mdatint 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 moovif(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前

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

MP4边下载边播放——moov box前置相关推荐

  1. 手机端mp4文件头前置检测,检测mp4视频文件头(moov box)是否在前面

    分享一个软件,用来检测mp4的文件头(moov box)在前面还是后面. 当mp4文件头在后面时视频不支持流媒体播放,比如在线播放,边下载边播,边解压边播,边传输边播都不支持.此软件用来在安卓手机端检 ...

  2. mp4文件缺少moov box无法播放情况的修复【非完美】

    一.mp4文件缺少moov box可能出现的场景有:使用录屏工具录到一半crash或断电,手机摄像机录到一般突然没电等. 二.修复的前提条件:需要有一个同样工具录制的参考视频,需要相同的mp4头部参数 ...

  3. 在线短视频秒播优化之视频文件格式之MP4文件Moov box的位置

    之前我们介绍了在线短视频秒播优化的方方面面,从服务器,cdn部署接入,数据连接/获取,客户端缓存,出帧策略,到视频文件I帧位置等. 今天从视频文件格式的另外一个角度介绍,MP4文件的box排列顺序是如 ...

  4. MP4 moov box解析

    转载请标明出处:https://blog.csdn.net/u013752202/article/details/80557296 文中使用到的工具说明:https://blog.csdn.net/u ...

  5. java MP4解析 第二步 解析moov box

    moov box(movie box):包含若干子box,这些子box共同描述了媒体播放必需的元数据. 参考资料:https://blog.csdn.net/u013752202/article/de ...

  6. MP4文件格式详解——元数据moov(二)tkhd box

    ISO 14496 - 12 定义了一种封装媒体数据的基础文件格式,mp4.3gp.ismv等我们常见媒体封装格式都是以这种基础文件格式为基础衍生的. 如果从全局角度了解基础文件格式,请看我之前的博文 ...

  7. 实现MP4文件边下载边播放

    最近遇到的需求,在老系统中有部分MP4视频在播放时需要完全加载完才能播放,使得用户体验很差(现在都是边下载边播放模式),造成这种情况的原因是用来描述MP4文件的moov atom元数据被放在MP4文件 ...

  8. MP4中MOOV信息前置

    MOOV信息前置 import com.ctsi.common.utils.UUIDUtils; import org.apache.commons.fileupload.FileItem; impo ...

  9. 使用浏览器免费下载MP3,MP4等可在线播放的媒体资源(图文详解)。

    使用浏览器免费下载MP3,MP4等可在线播放的媒体资源 第一步进入你想要的媒体页面,本文任意使用一个网站(申明仅供学习使用,任何商用与本人无关). 2.按键盘f12,进入开发者页面. 3.点击Netw ...

最新文章

  1. CGpoint,CGSize,CGRect,NSRange
  2. 《Two Dozen Short Lessons in Haskell》学习(十三)迭代及重复的常规模式
  3. C++ Primer 5th笔记(chap 11)关联容器操作
  4. Java实现replaceAll 把 \ 替换成 /
  5. 2018安徽省计算机一级试题答案,2018年计算机等一级考试试题100题及参考答案.docx...
  6. java中菜单分几级_JavaWeb三级菜单分类查询详解
  7. 浅谈面试中常考的两种经典布局——圣杯与双飞翼 1
  8. SQL学习笔记四之MySQL数据操作
  9. 电子书下载:Pro ASP.NET MVC2 Framework 2nd
  10. 微服务自动化部署(ansible playbook)干货之--zookeeper部署
  11. 数据结构算法基础定义
  12. AndroidKK4.4 Power key电量屏幕时button light先亮LCD后亮的卡顿问题分析
  13. 搭建 WordPress 博客教程(超详细)
  14. 使用python调整图片大小
  15. uniapp小程序唤醒微信支付
  16. 快速理解绝对地址和相对地址
  17. 通达信接口公式怎样进行破解?
  18. springboot+vue+elementUI用户头像获取
  19. 看Lucene源码必须知道的基本概念
  20. 上海市重点小学排名(2018年)

热门文章

  1. win10 smb共享硬盘
  2. 微信消息模板发送通知
  3. 科学计算机如何开机,CASIO科学计算机怎么进入EQN模式
  4. 智能写作,让GPT-3来辅助你写作|Mixlab智能产品
  5. 将 PDF 压缩到 1 MB 或更小的 5 个工具
  6. PC购买XGP至游玩的记录-Xbox游戏不显示x下载速度慢解决
  7. 6.CSS介绍选择器
  8. 使用Storage实现登录弹出
  9. 稳定伴侣问题c语言步骤,稳定匹配问题
  10. .net敏捷软件开发框架核心功能特点