传送门:MP4 文档 P19页
这个 Box 是 Full Box,意味着Box Header 有 Version 和 Flag 字段,该 Box 里面主要定义了该 Track 的媒体头信息,其中我们最关心的两个字段是 Time scale 和 Duration,分别表示了该 Track 的时间戳和时长信息,这个时间戳信息也是PTS 和 DTS 的单位。
名称 | 大小(byte) | 意义 | 说明 |
---|---|---|---|
Box length | 4 | Box 整体的大小 | 包含 Header 和 Data部分 |
Box type | 4 | ”mdhd”的ASCII码,表明是 mdhd box | box 属性值,通常是固定值 |
version | 1 | box版本 | 一般为0 |
flags | 3 | 该 Box 该字段填充0 | |
creation time | 4 | 当前Track创建时间 | 1904-01-01零点开始 |
modification time | 4 | 当前Track修改时间 | 1904-01-01零点开始 |
timescale | 4 | Track的时间计算单位 | |
duration | 4 | 播放时长,需要参考前面的timescale计算 | |
pad | 1(bit) | ||
language | 15(bit) | 媒体语言码 | 参考标准 ISO639-2/T |
qualiiy | 2 | 媒体的回放质量 | 默认值00即可 |
使用16进制工具查看:
名称 | 实际值(16进制) | 具体值(10进制 / ASCII) | 字段位置 |
---|---|---|---|
Box length | 00 00 00 20 | 32 | Header |
Box type | 6D 64 68 64 | ”mdhd" | Header |
version | 00 | Header | |
flags | 00 00 00 | Header | |
creation time | DA 25 22 45 | 3659866693 | Data |
modification time | DA 25 22 45 | 3659866693 | Data |
timescale | 00 00 EA 60 | 60000 | Data |
duration | 00 1D 33 A1 | 1913761 | Data |
pad | 55 | 0 | Data |
language | 55 C4 | "und" | Data |
qualiiy | 00 | Data |
这里我拿 timescale 和 duration 来进行分析来计算当前 Track 的时长,1913761 / 60000 = 31.896(s)
上面解析完后打开 MP4 Infor 进行分析对比
下面关于音频 Track 的 mdhd box 也是一样的,这里也不花篇幅进行说明了,具体还是参照上面这些步骤。
// BaseBox.h
// ...
// 其他 Box 的定义
class TimeMdhdBox : public BaseBox {
public:
Timebyte version = 0;
Timebyte flags = 0;
unsigned int creation_time = 0; // 4 创建时间(相对于UTC时间1904-01-01零点的秒数)
unsigned int modification_time = 0;// 4 修改时间(相对于UTC时间1904-01-01零点的秒数)
unsigned int time_scale = 0; // 文件媒体在1秒时间内的刻度值,可以理解为1秒长度的时间单元数,这个只用来计算了该Mp4文件的长度,但是没有参与PTS和DTS的计算。
unsigned int duration = 0; // 该影片的播放时长,该值除以time scale字段即可以得到该影片的总时长单位秒s
// 后面3个 不太重要
unsigned char pad = 0;
unsigned char* language[3] = {0};
unsigned short qualiiy = 0;
TimeMdhdBox(BoxHeader h);
TimeMdhdBox(BoxHeader h, Timebyte * d): BaseBox(h, d){};
void PrintDataInfo() override;
};
实现
// TimeMdhdBox.cpp
TimeMdhdBox::TimeMdhdBox(BoxHeader h) : BaseBox(h) {
if (h.GetDataSize()) {
data = new Timebyte[h.GetDataSize()];
}
}
void TimeMdhdBox::PrintDataInfo() {
printf("===========================\n");
h.to_string();
TimeBufferStream bufferStream(data, h.GetDataSize());
version = bufferStream.GetUChar();
bufferStream.GetLenData(&flags, 3);
creation_time = bufferStream.GetUInt();
modification_time = bufferStream.GetUInt();
time_scale = bufferStream.GetUInt();
duration = bufferStream.GetUInt();
printf("version:%ud \n", version);
printf("flags:%ud \n", flags);
printf("creation_time:%ud \n", creation_time);
printf("modification_time:%ud \n", modification_time);
printf("time_scale:%ud \n", time_scale);
printf("duration:%ud \n", duration);
printf("Track duration:%f \n", duration / time_scale);
}