传送门:MP4 文档 P15 页
这个 Box 也是唯一的一个 Box ,在 Moov Box 的第一个子 Box,这个 Box 里面主要是包含媒体文件的媒体数据(包含Video track 和 Audio Track 等)。其中包含了媒体的创建和修改时间,默认音量、色域、时长等信息。这里需要注意下该 Box 的 Header,因为这个 Box 是 Full Box 也就是在原来的头后面有扩展字段即在后面加上了 1byte 的 version 和 3 byte 的 flags 字段。
名称 | 大小(byte) | 意义 | 说明 |
---|---|---|---|
Box length | 4 | Box 整体的大小 | 包含 Header 和 Data部分 |
Box type | 4 | ”moov”的ASCII码,表明是 moov Box | box 属性值,通常是固定值 |
version | 1 | box版本 | 0或1,一般为0 |
flags | 3 | 根据各个Box类型定义是0还是1 | |
creation time | 4 | 创建时间(相对于UTC时间1904-01-01零点的秒数) | |
modification time | 4 | 修改时间(相对于UTC时间1904-01-01零点的秒数) | |
time scale | 4 | 把 1s 划分为多少个单位 | |
duration | 4 | 该影片的播放时长,除以 time scale 字段得到该影片的总时长,单位是秒 | |
rate | 4 | 播放速率,高16位和低16位分别为小数点整数部分和小数部分,即[16.16] 格式,该值为1.0(0x00010000)表示正常前向播放 | |
volume | 2 | 音量大小,[8.8] 格式,1.0(0x0100)表示最大音量 | |
reserved | 10 | 保留位 | |
matrix | 36 | 视频变换矩阵,实际填写都是默认值 | 不太重要 |
pre-defined | 24 | 预览相关的信息,一般都是填充0 | 不太重要 |
next track id | 4 | 下一个 Track 使用的id号 | 该值减去1,可以判断当前文件的 Track数量 |
首先用16进制工具查看:
我们可以看到 moov box 后面的 data 紧接着的就是 mvhd box,所以我们可以把 moov box 就看做一个分隔符。
具体值:
定义 | 实际值(16进制) | 具体值(10进制 / ASCII) | 字段位置 |
---|---|---|---|
Box length(4 byte) | 0x00 0x00 0x00 0x6C | 108 | Header |
Box type(4 byte) | 0x6D 0x76 0x68 0x64 | "mvhd" | Header |
version(1 byte) | 0x00 | 0 | Header |
flags(3 byte) | 0x00 0x00 0x00 | 0 | Header |
creation time(4 byte) | DA 25 22 45 | 3659866693 | Data |
modification time(4 byte) | DA 25 22 45 | 3659866693 | Data |
time scale(4 byte) | 00 00 EA 60 | 60000 | Data |
duration(4 byte) | 00 1D 33 A1 | 1913761 | Data |
rate(4 byte) | 00 01 00 00 | 1.0 | Data |
volume(2 byte) | 01 00 | 1.0 | Data |
reserved(10 byte) | ... | Data | |
matrix(36 byte) | ... | Data | |
pre-defined(24 byte) | ... | Data | |
next track id(4 byte) | 00 00 00 03 | 3 | Data |
根据上面的信息,大家可以进行验证,比如时长验证,用 duration / time scale 得到的就是视频时长,为多少秒,creation time 和 modification time 的时间戳是从 1904-01-01零点开始计算的。
MP4 Exprorer 软件查看:
符合上面我们得出的数据。
// BaseBox.h
// ...
// 其他 Box 的定义
class TimeMvhdBox : public BaseBox {
public:
Timebyte version = 0;
Timebyte flags = 0;
unsigned int creation_time = 0; // 创建时间(相对于UTC时间1904-01-01零点的秒数)
unsigned int modification_time = 0; // 修改时间(相对于UTC时间1904-01-01零点的秒数)
unsigned int time_scale = 0; // 文件媒体在1秒时间内的刻度值,可以理解为1秒长度的时间单元数,这个只用来计算了该Mp4文件的长度,但是没有参与PTS和DTS的计算。
unsigned int duration = 0; // 该影片的播放时长,该值除以time scale字段即可以得到该影片的总时长单位秒s
unsigned int rate = 0; // 推荐播放速率,高16位和低16位分别为小数点整数部分和小数部分,即[16.16] 格式,该值为1.0(0x00010000)表示正常前向播放
unsigned short int volume = 0; // 与Rate类似,[8.8] 格式,1.0(0x0100)表示最大音量
Timebyte reserved[10] = {0}; // 保留位
Timebyte matrix[36] = {0}; // 视频变换矩阵,实际填写都是默认值,一般不关心这个字段
Timebyte pre_defined[24] = {0}; // 预览相关的信息,一般都是填充0,所以不用太关心
unsigned int next_track_id = 0; // 下一个Track使用的id号
TimeMvhdBox(BoxHeader h);
TimeMvhdBox(BoxHeader h, Timebyte * d): BaseBox(h, d){};
void PrintDataInfo() override;
};
实现
// TimeMvhdBox.cpp
TimeMvhdBox::TimeMvhdBox(BoxHeader h) : BaseBox(h) {
data = new Timebyte[h.GetSize()];
}
void TimeMvhdBox::PrintDataInfo() {
printf("===========================\n");
h.to_string();
TimeBufferStream bufferStream(data, h.GetDataSize()); // 这里我们用到了之前我们写的Buff读取工具
version = bufferStream.GetUChar();
bufferStream.GetLenData(&flags, 3);
creation_time = bufferStream.GetUInt();
modification_time = bufferStream.GetUInt();
time_scale = bufferStream.GetUInt();
duration = bufferStream.GetUInt();
rate = bufferStream.GetUInt();
volume = bufferStream.GetUShort();
bufferStream.GetLenData(reserved, 10);
bufferStream.GetLenData(matrix, 36);
bufferStream.GetLenData(pre_defined, 24);
next_track_id = bufferStream.GetUInt();
printf("version: %d\n", version);
printf("flags: %ud\n", flags);
printf("creation_time: %ud\n", creation_time);
printf("modification_time: %ud\n", modification_time);
printf("modification_time: ");
printf("time_scale: %ud\n", time_scale);
printf("duration: %ud\n", duration);
printf("rate: %ud\n", rate);
printf("volume: %ud\n", volume);
printf("next_track_id: %ud\n", next_track_id);
}