传送门:MP4 文档 P20页
这个 Box 也是 Full Box,意味着 Box Header 有 Version 和 Flag 字段,该 Box 解释了媒体的播放过程信息,用来设置不同 Track 的处理方式,标识了该 Track 的类型。
名称 | 大小(byte) | 意义 | 说明 |
---|---|---|---|
Box length | 4 | Box 整体的大小 | 包含 Header 和 Data部分 |
Box type | 4 | ”mdhd”的ASCII码,表明是 mdhd box | box 属性值,通常是固定值 |
version | 1 | box版本 | 一般为0 |
flags | 3 | 该 Box 该字段填充0 | |
handle type | 4 | Handle 的类型 | 不太重要,默认为0即可 |
hand sub type | 4 | Track 类型 | 视频:“vide” 音频:“soun” |
reserved | 3 | 保留字段 | 默认为0 |
name | 可变,根据box length算出 | Track 的名字 | 打包时填写的字符串 |
16 进制工具分析查看
名称 | 实际值(16进制) | 具体值(10进制 / ASCII) | 字段位置 |
---|---|---|---|
Box length | 00 00 00 2D | 45 | Header |
Box type | 68 64 6C 72 | "hdlr" | Header |
version | 00 | Header | |
flags | 00 00 00 | Header | |
handle type | 00 00 00 00 | Data | |
hand sub type | 76 69 64 65 | vide | Data |
reserved | 00 ... | Data | |
name | 56 ... 72 | VideoHandler | Data |
上面解析完后打开 MP4 Infor 进行分析对比
video track 下的 hdlr
audio track 下的 hdlr
符合我们上面的解析
// BaseBox.h
// ...
// 其他 Box 的定义
class TimeHdlrBox : public BaseBox {
public:
Timebyte version = 0;
Timebyte flags = 0;
unsigned int handle_type = 0;
char hand_sub_type[5] = {0}; // Track 类型
unsigned char reserved[3] = {0};
char name[1024] = {0}; // Track 的名字
TimeHdlrBox(BoxHeader h);
TimeHdlrBox(BoxHeader h, Timebyte * d): BaseBox(h, d){};
void PrintDataInfo() override;
};
实现
TimeHdlrBox::TimeHdlrBox(BoxHeader h) : BaseBox(h) {
if (h.GetDataSize()) {
data = new Timebyte[h.GetDataSize()];
}
}
void TimeHdlrBox::PrintDataInfo() {
printf("===========================\n");
h.to_string();
TimeBufferStream bufferStream(data, h.GetDataSize());
version = bufferStream.GetUChar();
bufferStream.GetLenData(&flags, 3);
handle_type = bufferStream.GetUInt();
bufferStream.GetLenData(hand_sub_type, 4);
bufferStream.GetLenData(reserved, 12);
bufferStream.GetLenData(name, 1024);
printf("version:%ud \n", version);
printf("flags:%ud \n", flags);
printf("handle_type:%ud \n", handle_type);
printf("hand_sub_type: %s\n", hand_sub_type);
printf("name:%s \n", name);
}
最后运行解析
Video Track :
Audio Track :