最近写了个解析MP4的类来解析MP4文件,现在来聊一聊,有不对的地方,请大家指正,谢谢。

说点要注意的地方:

1.首先MP4的数据是网络字节序,也就是按照大端进行存储(高位在低地址),所以我们在解析box的时候,需要做个转换。

类似这样:

uint32_t n_to_uInt(const uint32_t val)
{return (val >> 24) + ((val & 0xFF0000) >> 8) + ((val & 0xFF00) << 8) + ((val & 0xFF) << 24);
}uint64_t n_to_uInt64(const uint64_t val)
{return (val >> 56) + ((val & 0xFF000000000000) >> 40) + ((val & 0xFF0000000000) >> 24) + ((val & 0xFF00000000) >> 8)+ ((val & 0xFF000000) << 8) + ((val & 0xFF0000) << 24) + ((val & 0xFF00) << 40) + ((val & 0xFF) << 56);
}

2:对于文件比较大的情况,可能需要_fseeki64。

进入正题:

MP4是 由一系列的box组成,有的box是相对独立的,比如ftyp box。有的box 中还包含其他的Box,比如moov Box等。

box由header和body组成,其中header指明box的size和type。size是整个box的大小(包括header+body)。

这个size为1,则表示box长度需要64位来表示,在后面会有一个64bits位的largesize用来描述box的长度。

如果size为0,表示该box为文件的最后一个box,文件结尾。

box分为两种,Box和Fullbox。FullBox 是 Box 的扩展,字段中增加了version 和 flags字段,主要是在 trak box 中使用

聊聊音频和视频:

视频:我们关注 宽、高、帧率。帧率就是一秒钟多少张图片,一般来说,超过25帧,人眼就感觉不出画面中图片的切换。还有就是时间戳,h264编码的视频时间戳是90000,也就是把一秒切成90000份,每秒25帧。也就是每帧的时间戳是90000/25=3600.

看解码视频的时间戳就是以3600递增的,例如:0,3600,7200.。。。

音频:我们关注采样率、通道数。

这个MP4封装格式,有一些sample和chunk。我的理解,对于视频,一个sample就是一帧。chunk是包含一个或者多个sample。

为啥要这样?我看后面的box知道,其实有很多 sample的时间戳是一样的,封装在一个chunk,至少可以省点空间吧。当然每帧的数据长度是不一样的。

至于box的总图,网上到处都是,我就不贴图了。

先说说一些常见的box的结构,后面聊聊怎么用,比如我怎么找到MP4的30s的位置。

先解析前面的8个字节:得到size和type,根据type解析不同的box。

typedef struct
{uint32_t size;char type[4];
}Header;

(1)Ftyp Box:

//参考vlc 数据格式的定义
typedef struct MP4_Box_data_ftyp_s
{char major_brand[4];int  minor_version;//char compatible_brands[16]; 长度待定
}MP4_Box_data_ftyp_t;
Header header;
memset(&header, 0, sizeof(Header));int read_len = fread(&header, 1, sizeof(Header), fp);
if (read_len != sizeof(Header)) return ;uint32_t  box_total_size = n_to_uInt(header.size);if (strncmp("ftyp", header.type, 4) == 0)
{MP4_Box_data_ftyp_s ftyp_box;fread(&ftyp_box, 1, sizeof(MP4_Box_data_ftyp_t), fp);uint32_t remain = box_total_size  - sizeof(Header)-sizeof(MP4_Box_data_ftyp_t);char temp[100] = { 0 };fread(temp, 1, remain, fp);printf("ftyp box,%s\n",temp);
}

类似这样解析。

(2)mdat box 如果文件很大,这个size可能等于1,需要借助64位来解析。

(3)mvhd box 是moov的一个子box。

typedef struct MP4_Box_data_mvhd_s
{char version;//版本char flags[3];//标志 0 int creation_time;uint32_t modification_time;uint32_t timescale;uint32_t duration;uint32_t rate;//播放速度uint16_t volume;//音量char reserved[10];char matrix[36];//36字节视频变换矩阵int preview_time;int preview_duration;int poster_time;int selection_time;int selection_duration;int current_time;int next_track_id;
}MP4_Box_data_mvhd_t;从mvhd 可以获取视频的时长。
uint32_t rate = mvhd.rate;
uint32_t volume = mvhd.volume;uint32_t duration = n_to_uInt(mvhd.duration) / n_to_uInt(mvhd.timescale);
uint32_t hour = duration / 3600;
uint32_t minute = (duration - 3600 * hour)/60;
uint32_t second = (duration - 3600 * hour) % 60;
printf("  mvhd Box,播放时长=%02u:%02u:%02u,播放速度=%u:%u,播放音量=%u:%u\n", hour, minute, second ,(rate & 0xFFFF0000 >> 16), (rate & 0xFFFF),(volume & 0xFF00 >> 8), (rate & 0xFF));

(4)trak box ,分为视频或者音频trak。每种trak 一般包括 tkhd box,edts box ,mdia box。

(5)tkhd box,从此box中可以获取视频的宽高。

typedef struct MP4_Box_data_tkhd_s
{char version;//版本char flags[3];//标志 0 //uint32_t creation_time;//3bytechar creation_time[3];//3byteuint32_t modification_time;uint32_t track_id;char reserved[4];uint32_t duration;char reserved1[8];short layer;//default:0short alternate_group;uint16_t volume;char reserved2[2];char matrix[36];uint8_t width[3];uint8_t width_Q;uint8_t height[3];uint8_t height_Q; char padding;}MP4_Box_data_tkhd_t;MP4_Box_data_tkhd_t tkhd;uint32_t width  = ((tkhd.width[0]   & 0xFF)<<16) + ((tkhd.width[1]  & 0xFF) << 8) + (tkhd.width[2]  & 0xFF);uint32_t height = ((tkhd.height[0] & 0xFF)<<16) + ((tkhd.height[1] & 0xFF) << 8) + (tkhd.height[2] & 0xFF);

(6) mdia box,此box包含 mdhd box,hdlr box,minf box,从hdlr中可以解析数据类型。()

(7)minf box ,此box包含vmhd box,dinf  box,stbl box ,stbl 比较复杂。下面重点分析:

(6)stsd box,从此box 可以获取视频的数据类型和解码 用到的sps pps。

c++ MP4文件解析相关推荐

  1. ffmpeg源码分析及mp4文件解析

    一.mp4文件的组织 1. mp4文件的box(ffmpeg中叫atom) mp4是由一系列的box组成的,每个box的header是8个字节(4字节的长度,4字节的type) 第一个box比较特殊, ...

  2. mp4文件解析(c#)

    ISO/IEC 14496 ISO/IEC 14496 是MPEG专家组制定的MPEG-4标准,于2000年年初正式成为国际标准.MPEG-4与MPEG-1和MPEG-2有很大的不同.MPEG-4不只 ...

  3. 网页视频之MP4文件解析

    为了研究如何把H264打包成fMp4文件,今天先开始研究如何从fMp4中解析出H264数据. fMP4包括ftype+moov+(moof+mdat)*N这种格式组成. Box的定义: ftyp格式: ...

  4. MP4文件格式解析(结合实例分析)

    系列文章目录 MP4文件解析 文章目录 系列文章目录 前言 一.MP4文件的构成 二.MP4文件内部结构 1.基本结构 2.整体结构 三.结合实例 1.File Type Box(ftyp) 2.Mo ...

  5. MP4文件格式的解析,以及MP4文件的分割算法

    mp4应该算是一种比较复杂的媒体格式了,起源于QuickTime.以前研究的时候就花了一番的功夫,尤其是如何把它完美的融入到视频点播应用中,更是费尽了心思,主要问题是处理mp4文件庞大的"媒 ...

  6. 如何使用mp4v2解析mp4文件,抽取音视频数据帧【源码】【mp4】【NVR】

    前言: mp4文件目前已经成为了流媒体音视频行业的通用标准文件格式,它是基于mov格式基础上演变来的,特别适合多平台播放,录制一次,多个平台都可使用.但是,由于mp4格式相对比较复杂,直到mp4v2这 ...

  7. 使用 MediaExtractor 和 MediaMuxer API 解析和封装 mp4 文件

    一个音视频文件是由音频和视频组成的,我们可以通过MediaExtractor.MediaMuxer把音频或视频给单独抽取出来,抽取出来的音频和视频能单独播放: 一.MediaExtractor API ...

  8. 视频文件头解析--MP4-获取mp4 文件信息

    获取mp4 文件信息 2-1.计算电影图像宽度和高度 tkhd – track header atom中找到宽度和高度即是. 2-2. 计算电影声音采样频率 从tkhd – track header ...

  9. MP4文件介绍及SPS、PPS解析

    MP4文件介绍 mp4文件由box组成,每个box分为Header和Data.其中Header部分包含了box的类型和大小,Data包含了子box或者数据,box可以嵌套子box. 下图是一个典型mp ...

最新文章

  1. 订单管理之更新订单表状态数据
  2. pandas.read_csv——分块读取大文件
  3. 十八年开发经验分享(三)问题解决篇(中)
  4. Zookeeper C API 指南二(监视(Wathes), 基本常量和结构体介绍)
  5. Wix 3.0正式发布
  6. JQuery Easyui/TopJUI 创建多级联动下拉框(纯HTML实现!!!)
  7. 高通音频驱动录音流程(一)
  8. 向日葵 监控 android,就是如此简单!向日葵远程控制Android手机版教程
  9. 3.数据的一致性与一致性算法(CAP原则、Paxos算法、Raft算法、ZAB协议)
  10. 有关reducer拆分的学习
  11. 如何判断是否是ssd硬盘?win10查看固态硬盘的方法
  12. 系统安装无法创建新的系统分区的解决方法
  13. 名帖184 黄庭坚 行书《寄岳云帖》
  14. linux ora-39002,ORA-39002:invalidoperation
  15. 深入理解计算机系统(CSAPP)读书笔记 第一章
  16. 字符串转化为RTF格式-RTF研究系列
  17. 中联重科智慧产业城项目启动 千亿元投资打造全球典范
  18. 移动办公oa系统该如何搭配其他工具使用?
  19. WinServer 2012 域控组策略 用户发布软件部署
  20. 合作式智能运输系统-车用通信系统应用层及应用数据交互标准

热门文章

  1. 什么是网站内链,内链有什么作用,网站内链应该如何设置
  2. 无需Root手机导出系统 so库
  3. 让黑产无处遁形 京东云推出风险识别服务
  4. FIFO深度计算问题
  5. 数据库(SQL Sever) QQ查询
  6. bnu1258 神奇礼物盒 C语言版
  7. svn服务器 无线访问权限,SVN 服务器端权限管理
  8. JAVA URI 工具类
  9. HTML5手机的春天, Web Apps来袭
  10. 电力电子助力小米快充生态,磁材创新驱动未来无线充电