c++ MP4文件解析
最近写了个解析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文件解析相关推荐
- ffmpeg源码分析及mp4文件解析
一.mp4文件的组织 1. mp4文件的box(ffmpeg中叫atom) mp4是由一系列的box组成的,每个box的header是8个字节(4字节的长度,4字节的type) 第一个box比较特殊, ...
- mp4文件解析(c#)
ISO/IEC 14496 ISO/IEC 14496 是MPEG专家组制定的MPEG-4标准,于2000年年初正式成为国际标准.MPEG-4与MPEG-1和MPEG-2有很大的不同.MPEG-4不只 ...
- 网页视频之MP4文件解析
为了研究如何把H264打包成fMp4文件,今天先开始研究如何从fMp4中解析出H264数据. fMP4包括ftype+moov+(moof+mdat)*N这种格式组成. Box的定义: ftyp格式: ...
- MP4文件格式解析(结合实例分析)
系列文章目录 MP4文件解析 文章目录 系列文章目录 前言 一.MP4文件的构成 二.MP4文件内部结构 1.基本结构 2.整体结构 三.结合实例 1.File Type Box(ftyp) 2.Mo ...
- MP4文件格式的解析,以及MP4文件的分割算法
mp4应该算是一种比较复杂的媒体格式了,起源于QuickTime.以前研究的时候就花了一番的功夫,尤其是如何把它完美的融入到视频点播应用中,更是费尽了心思,主要问题是处理mp4文件庞大的"媒 ...
- 如何使用mp4v2解析mp4文件,抽取音视频数据帧【源码】【mp4】【NVR】
前言: mp4文件目前已经成为了流媒体音视频行业的通用标准文件格式,它是基于mov格式基础上演变来的,特别适合多平台播放,录制一次,多个平台都可使用.但是,由于mp4格式相对比较复杂,直到mp4v2这 ...
- 使用 MediaExtractor 和 MediaMuxer API 解析和封装 mp4 文件
一个音视频文件是由音频和视频组成的,我们可以通过MediaExtractor.MediaMuxer把音频或视频给单独抽取出来,抽取出来的音频和视频能单独播放: 一.MediaExtractor API ...
- 视频文件头解析--MP4-获取mp4 文件信息
获取mp4 文件信息 2-1.计算电影图像宽度和高度 tkhd – track header atom中找到宽度和高度即是. 2-2. 计算电影声音采样频率 从tkhd – track header ...
- MP4文件介绍及SPS、PPS解析
MP4文件介绍 mp4文件由box组成,每个box分为Header和Data.其中Header部分包含了box的类型和大小,Data包含了子box或者数据,box可以嵌套子box. 下图是一个典型mp ...
最新文章
- 订单管理之更新订单表状态数据
- pandas.read_csv——分块读取大文件
- 十八年开发经验分享(三)问题解决篇(中)
- Zookeeper C API 指南二(监视(Wathes), 基本常量和结构体介绍)
- Wix 3.0正式发布
- JQuery Easyui/TopJUI 创建多级联动下拉框(纯HTML实现!!!)
- 高通音频驱动录音流程(一)
- 向日葵 监控 android,就是如此简单!向日葵远程控制Android手机版教程
- 3.数据的一致性与一致性算法(CAP原则、Paxos算法、Raft算法、ZAB协议)
- 有关reducer拆分的学习
- 如何判断是否是ssd硬盘?win10查看固态硬盘的方法
- 系统安装无法创建新的系统分区的解决方法
- 名帖184 黄庭坚 行书《寄岳云帖》
- linux ora-39002,ORA-39002:invalidoperation
- 深入理解计算机系统(CSAPP)读书笔记 第一章
- 字符串转化为RTF格式-RTF研究系列
- 中联重科智慧产业城项目启动 千亿元投资打造全球典范
- 移动办公oa系统该如何搭配其他工具使用?
- WinServer 2012 域控组策略 用户发布软件部署
- 合作式智能运输系统-车用通信系统应用层及应用数据交互标准