传送门:MP4 文档 P28页
编码类型是 H264 数据的这个 Box 则为 Avc1 Box,Box 内部含有音视频信息。
这里由于官方定义的一些保留字段和预定义字段有些没太大意义,下面我会根据一些字段进行合并到一起,如果有疑问可以看官方文档的介绍。
名称 | 大小(byte) | 意义 | 说明 |
---|---|---|---|
Box length | 4 | Box 整体的大小 | 包含 Header 和 Data部分 |
Box type | 4 | ”stsd”的ASCII码,表明是 stsdbox | box 属性值,通常是固定值 |
reserve | 6 | 默认值0 | |
data_reference_ID | 2 | 引用参考 Dref Box | |
code_stream_version | 2 | 默认值0 | |
reserver | 14 | 默认值0 | |
width | 2 | 图像宽度 | |
height | 2 | 图像高度 | |
horizontal_resolution | 4 | 水平分辨率 | 默认值 0x00480000 |
vertical_resolution | 4 | 垂直分辨率 | 默认值 0x00480000 |
reserver | 4 | ||
frame_count | 2 | 每采样点图像的帧数,一般为1,有些情况下,每个采样点有多帧 | 默认值一般是0x00 01 |
compressorname | 32 | 编码名称 | |
depth | 2 | 深度,图像是彩色的,没有alpha | 默认 0x0018 |
reserver | 2 |
下面来分析具体值
名称 | 实际值(16进制) | 具体值(10进制 / ASCII) | 字段默认值 |
---|---|---|---|
Box length | 00 00 00 85 | 133 | Header 和 Data部分长度 |
Box type | 61 76 63 31 | “avc1” | box 属性值,通常是固定值 |
reserve | 00 ... | 0 | 默认值0 |
data_reference_ID | 00 01 | 1 | |
code_stream_version | 00 00 | 0 | 默认值0 |
reserver | 00 ... | 0 | 默认值0 |
width | 07 80 | 1920 | |
height | 04 38 | 1080 | |
horizontal_resolution | 00 48 00 00 | 0x00480000 | 默认值 0x00480000 |
vertical_resolution | 00 48 00 00 | 0x00480000 | 默认值 0x00480000 |
reserver | 00 ... | ||
frame_count | 00 01 | 1 | 默认值一般是0x00 01 |
compressorname | 0A 41 56 43 ... | "AVC Coding" | |
depth | 00 18 | 24 | 默认 0x0018 |
reserver | FF FF |
接下来我们继续分析一下 Audio Track 下的 Mp4a Box。
名称 | 大小(byte) | 意义 | 说明 |
---|---|---|---|
Box length | 4 | Box 整体的大小 | 包含 Header 和 Data部分 |
Box type | 4 | ”stsd”的ASCII码,表明是 stsdbox | box 属性值,通常是固定值 |
reserve | 6 | 默认值0 | |
data_reference_ID | 2 | 引用参考 Dref Box | |
reserver | 8 | 默认值 0 | |
channelcount | 2 | 声道数 | 默认值 2 |
samplesize | 2 | 样本数 | 默认值 16 |
reserved | 4 | 默认值 0 | |
samplerate | 4 | 采样率(高位) |
名称 | 实际值(16进制) | 具体值(10进制 / ASCII) | 字段默认值 |
---|---|---|---|
Box length | 00 00 00 54 | 84 | 包含 Header 和 Data部分 |
Box type | 6D 70 34 61 | "mp4a" | box 属性值,通常是固定值 |
reserve | 00 ... | 0 | 默认值0 |
data_reference_ID | 00 01 | 1 | |
reserver | 00 .. | 0 | 默认值 0 |
channelcount | 00 02 | 2 | 默认值 2 |
samplesize | 00 10 | 16 | 默认值 16 |
reserved | 00 ... | 0 | 默认值 0 |
samplerate | BB 80 00 00 | 48000 |
// BaseBox.h
// ...
// 其他 Box 的定义
class TimeAvc1 : public BaseBox{
public:
unsigned char reserver[6] = {0}; // 2 保留位默认0x00
unsigned short data_reference_ID = 0; // 2 引用参考Dref Box
unsigned short code_stream_version = 0; // 2 一般都是默认值0
unsigned char reserver2 [14] = {0};
unsigned short width = 0;
unsigned short heigth = 0;
unsigned int horizontal_resolution = 0; // 4 默认值一般都是72dpi(前两个字节整数部分,后面两个字节小数部分)
unsigned int vertical_resolution = 0; // 4 默认值一般都是72dpi(前两个字节整数部分,后面两个字节小数部分)
unsigned int reserver3 = 0;
unsigned short frame_count = 0; // 默认值一般是0x00 01 每采样点图像的帧数,一般为1,有些情况下,每个采样点有多帧
Timebyte compressorname[32] = {0};
unsigned short depth = 0; // 两个字节默认值是0x00 0x18 即24
unsigned short reserver4 = 0;
TimeAvc1(BoxHeader h);
TimeAvc1(BoxHeader h, Timebyte * d): BaseBox(h, d){};
void PrintDataInfo() override;
size_t GetDataOffset() const override {
// Data属性大小
return 78;
}
void AnalyzeBoxHeader(BoxHeader header, size_t offset) override;
};
class TimeMP4a : public BaseBox{
public:
unsigned char reserver[6] = {0}; // 2 保留位默认0x00
unsigned short data_reference_ID = 0; // 2 引用参考Dref Box
unsigned char reserver2 [8] = {0};
unsigned short channelcount = 0;
unsigned short samplesize = 0;
unsigned char reserver3 [4] = {0};
unsigned int samplerate = 0;
TimeMP4a(BoxHeader h);
TimeMP4a(BoxHeader h, Timebyte * d): BaseBox(h, d){};
void PrintDataInfo() override;
size_t GetDataOffset() const override {
// Data属性大小
return 28;
}
void AnalyzeBoxHeader(BoxHeader header, size_t offset) override;
};
实现
// TimeAvc1.cpp
TimeAvc1::TimeAvc1(BoxHeader h) : BaseBox(h) {
if (h.GetDataSize()) {
data = new Timebyte[h.GetDataSize()];
}
}
void TimeAvc1::PrintDataInfo() {
}
void TimeAvc1::AnalyzeBoxHeader(BoxHeader header, size_t offset) {
// 如果是avc/h.264编码则构造Avcc Box
// 如果是MPEG-4编码则构造Esds Box
// 如果是MPEG-4编码则构造Hvcc Box
if (header.GetType() == AVCC) {
}
}
Mp4a Box
// TimeMP4a.cpp
TimeMP4a::TimeMP4a(BoxHeader h) : BaseBox(h){
if (h.GetDataSize()) {
data = new Timebyte[h.GetDataSize()];
}
}
void TimeMP4a::PrintDataInfo() {
}
void TimeMP4a::AnalyzeBoxHeader(BoxHeader header, size_t offset) {
if(header.GetType() == ESDS) {
}
}