软编码Flv 到Mp4 容器(一)
软编码Flv 到Mp4 容器(二) flv tag拆解
软编码Flv 到Mp4 容器(三) flv metadata tag解析
软编码Flv 到Mp4 容器(四) fmp4 总览和基础讲解
软编码Flv 到Mp4 容器(五) fmp4 ftyp box 和moov>mvhd box详解
软编码Flv 到Mp4 容器(六) fmp4 moov>trak>tkhd box 和 moov>trak>mdia>mdhd box讲解
软编码Flv 到Mp4 容器(七) fmp4 mdia>hdlr box 和 mdia>minf> smhd 和dinf box讲解
软编码Flv 到Mp4 容器(八) fmp4 mdia>stbl>stsd box 讲解
软编码Flv 到Mp4 容器(九) fmp4 stts stsc stsz stco box 讲解
软编码Flv 到Mp4 容器(十) fmp4 mvex box 讲解
软编码Flv 到Mp4 容器(十一) fmp4 moof box详解
软编码Flv 到Mp4 容器(十二) fmp4 mdat box详解
软编码Flv 到Mp4 容器(十三) fmp4 生成ftyp和moov所必要的 flv数据
- ftyp
- moov
- mvhd
- trak
- tkhd
- mdia
- mdhd
- hdlr
- minf
- smhd
- dinf
- dref
- url
- stbl
- stsd
- mp4a(avc1)
- esds(avcC)
- stts
- stsc
- stsz
- stco
- mvex
-trex
- moof
- mfhd
- traf
-tfhd
-tfdt
-sdtp
-trun
- mdat
首先对应标题的box在 fmp4容器中的位置
Box Type: ‘tkhd’
Container: Track Box (‘trak’)
Mandatory: Yes
Quantity: Exactly one
先看官方定义
aligned(8) class TrackHeaderBox
extends FullBox(‘tkhd’, version, flags){
if (version==1) {
unsigned int(64) creation_time;
unsigned int(64) modification_time;
unsigned int(32) track_ID;
const unsigned int(32) reserved = 0;
unsigned int(64) duration;
} else { // version==0
unsigned int(32) creation_time; //创建时间(相对于UTC时间1904-01-01零点的秒数)
unsigned int(32) modification_time;//修改时间
unsigned int(32) track_ID;//id号,不能重复且不能为0
const unsigned int(32) reserved = 0;//4字节保留位
unsigned int(32) duration;//时长
}
const unsigned int(32)[2] reserved = 0;// reserved: 2 * 4 bytes 保留位
template int(16) layer = 0;
template int(16) alternate_group = 0;// layer(2bytes) + alternate_group(2bytes) 视频层,默认为0,值小的在上层.track分组信息,默认为0表示该track未与其他track有群组关系
template int(16) volume = {if track_is_audio 0x0100 else 0}; //volume(2bytes)
const unsigned int(16) reserved = 0;//reserved(2bytes)
template int(32)[9] matrix=//视频变换矩阵
{ 0x00010000,0,0,0,0x00010000,0,0,0,0x40000000 };// unity matrix
unsigned int(32) width;//宽
unsigned int(32) height;//高
}
由上可见,这个box也是一个full box,它不包含任何子box
var tkhd = new Uint8Array([
0x00, 0x00, 0x00, 0x07, // version(0) + flags 1位版本 box版本,0或1,一般为0。(以下字节数均按version=0)按位或操作结果值,预定义如下:
//0x000001 track_enabled,否则该track不被播放;
//0x000002 track_in_movie,表示该track在播放中被引用;
//0x000004 track_in_preview,表示该track在预览时被引用。
//一般该值为7,1+2+4 如果一个媒体所有track均未设置track_in_movie和track_in_preview,将被理解为所有track均设置了这两项;对于hint track,该值为0
//hint track 这个特殊的track并不包含媒体数据,而是包含了一些将其他数据track打包成流媒体的指示信息。
0x00, 0x00, 0x00, 0x00, // creation_time 创建时间(相对于UTC时间1904-01-01零点的秒数)
0x00, 0x00, 0x00, 0x00, // modification_time 修改时间
(trackId >>> 24) & 0xFF, // track_ID: 4 bytes id号,不能重复且不能为0
(trackId >>> 16) & 0xFF,
(trackId >>> 8) & 0xFF,
(trackId) & 0xFF,
0x00, 0x00, 0x00, 0x00, // reserved: 4 bytes 保留位
(duration >>> 24) & 0xFF, // duration: 4 bytes track的时间长度
(duration >>> 16) & 0xFF,
(duration >>> 8) & 0xFF,
(duration) & 0xFF,
0x00, 0x00, 0x00, 0x00, // reserved: 2 * 4 bytes 保留位
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, // layer(2bytes) + alternate_group(2bytes) 视频层,默认为0,值小的在上层.track分组信息,默认为0表示该track未与其他track有群组关系
0x00, 0x00, 0x00, 0x00, // volume(2bytes) + reserved(2bytes) [8.8] 格式,如果为音频track,1.0(0x0100)表示最大音量;否则为0 +保留位
0x00, 0x01, 0x00, 0x00, // ----begin composition matrix----
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00, //视频变换矩阵
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x40, 0x00, 0x00, 0x00, // ----end composition matrix----
(width >>> 8) & 0xFF, // //宽度
(width) & 0xFF,
0x00, 0x00,
(height >>> 8) & 0xFF, //高度
(height) & 0xFF,
0x00, 0x00
]));
tkhd是一个full box,所以它没有子box了,它最终的表现是 4字节长度+4字节’tkhd’+tkhd对象,就是一个完整的tkhd box
Box Type: ‘mdia’
Container: Track Box (‘trak’)
Mandatory: Yes
Quantity: Exactly one
先看官方定义
aligned(8) class MediaBox extends Box(‘mdia’) { }
很明显..这是一个container box
Box Type: ‘mdhd’
Container: Media Box (‘mdia’)
Mandatory: Yes
Quantity: Exactly one
官方定义
//继承自fullbox 版本是0
aligned(8) class MediaHeaderBox extends FullBox(‘mdhd’, version, 0) { if (version==1) {
unsigned int(64) creation_time;
unsigned int(64) modification_time;
unsigned int(32) timescale;
unsigned int(64) duration;
} else { // version==0
unsigned int(32) creation_time;//创建时间
unsigned int(32) modification_time;//修改时间
unsigned int(32) timescale;//文件媒体在1秒时间内的刻度值,可以理解为1秒长度
unsigned int(32) duration;//track的时间长度
}
bit(1) pad=0;
unsigned int(5)[3] language; // // language: und (undetermined) 媒体语言码。最高位为0,后面15位为3个字符(见ISO 639-2/T标准中定义)
pre_defined = 0;
}
这个mdhd box又是一个full box,所以它不不含任何子元素
var mdhd = new Uint8Array([
0x00, 0x00, 0x00, 0x00, // version(0) + flags // version(0) + flags box版本,0或1,一般为0。
0x00, 0x00, 0x00, 0x00, // creation_time 创建时间
0x00, 0x00, 0x00, 0x00, // modification_time修改时间
(timescale >>> 24) & 0xFF, // timescale: 4 bytes 文件媒体在1秒时间内的刻度值,可以理解为1秒长度
(timescale >>> 16) & 0xFF,
(timescale >>> 8) & 0xFF,
(timescale) & 0xFF,
(duration >>> 24) & 0xFF, // duration: 4 bytes track的时间长度
(duration >>> 16) & 0xFF,
(duration >>> 8) & 0xFF,
(duration) & 0xFF,
0x55, 0xC4, // language: und (undetermined) 媒体语言码。最高位为0,后面15位为3个字符(见ISO 639-2/T标准中定义)
0x00, 0x00 // pre_defined = 0
])
mdhd是一个full box,所以它没有子box了,它最终的表现是 4字节长度+4字节’mdhd’+mdhd对象,就是一个完整的mdhd box
本章完