ZigZag Sin
登 陆
上一篇:avcC mp4a Box 下一篇:esds Box

avcC Box

Time
2022-2-21 11:39 阅读 1637

具体 Box 分析

Avcc Box

介绍

该 Box 则包含了真实 H264 码流的SPS PPS等信息。

工具分析

image-20211224160944453

这里就直接分析字段值

名称实际值(16进制)具体值(10进制 / ASCII)字段默认值
Box length00 00 00 2F47Header 和 Data部分长度
Box type61 76 63 43“avcC”box 属性值,通常是固定值
configuration version011保留位默认0x01
avc profile indication4D77H.264编码配置:0x64表示Baseline,0x4D表示Main
profile compatibility40
avc level indication290H.264编码级别
reservedFF0b111111(6bit)默认都是1
length size minus oneFF0b11(2 bit)读出的每个packet的前几字节代表数据大小
reservedE10b111(3 bit)
number of spsE10b00001(5 bit)sps的个数,一般情况是1
sps length00 1824
sps红框部分
reserved010b000(3 bit)
number of pps010b00001(5 bit)pps的个数,一般情况是1
pps length00 044
pps黑框部分

代码定义

因为上面有些字段出现了 bit 部分,所以我们得弄个专门对bit操作的工具。

// TimeBufferBitStream.h

class TimeBufferBitStream {
private:
    void *Buffer;
    int len; // Byte
    int index=0;
    unsigned char BitIndex;
public:
    TimeBufferBitStream(void *b, int len);
    unsigned char GetBit();
    bool IsEnd();
    unsigned char GetUChar();
};

// TimeBufferBitStream.cpp

TimeBufferBitStream::TimeBufferBitStream(void *b, int len)
    :Buffer(b), len(len), index(0), BitIndex(0)
{

}

unsigned char TimeBufferBitStream::GetBit() {
//    if(index >= len) return 0;
    unsigned char* b = (unsigned char *)Buffer;
    unsigned char ret = b[index]>>(7-BitIndex++)&1;
    if(BitIndex==8) {
        index++;
        BitIndex = 0;
    }
    return ret;
}

bool TimeBufferBitStream::IsEnd() {
    return index>=len;
}

unsigned char TimeBufferBitStream::GetUChar() {
    if(len < 1 ) return 0;
    if(index==len && BitIndex>0) return 0;
    unsigned char* b = (unsigned char *)Buffer;
    // 如果上次读取当前字节的一点bit  则这次读取的Char为上次没读取完的Char
    if(BitIndex) {
        BitIndex = 0;
    }
    return b[index++];
}

具体Box的定义:

// BaseBox.h  

// ...
// 其他 Box 的定义

class TimeAVCCBox : public BaseBox{
public:
    unsigned char configuration_version = 0; // 1 保留位默认0x01
    unsigned char avc_profile_indication = 0; // 1 保留位默认0x01 0x64即100表示Baseline 0x4D即77表示Main
    unsigned char profile_compatibility = 0; // 1
    unsigned char avc_level_indication = 0; // 1 H.264编码级别
    unsigned char reserved = 0; // 6bit 默认填1
    unsigned char length_size_minus_one = 0; // 2bit 读出的每个packet的前几字节代表数据大小
    unsigned char reserved2 = 0; // 3bit 默认填1
    unsigned char number_of_sps = 0; // 5bit sps的个数,一般情况是1
    unsigned short sps_length = 0; // 2 sps 长度
    void * sps = nullptr; // sps实际内容
    unsigned char reserved3 = 0; // 3bit 默认填1
    unsigned char number_of_pps = 0; // 5bit sps的个数,一般情况是1
    unsigned short pps_length = 0; // 2 sps 长度
    void * pps = nullptr; // sps实际内容

    TimeAVCCBox(BoxHeader h);
    TimeAVCCBox(BoxHeader h, Timebyte * d): BaseBox(h, d){};
    void PrintDataInfo() override;
};

实现

TimeAVCCBox::TimeAVCCBox(BoxHeader h) : BaseBox(h) {
    if (h.GetDataSize()) {
        data = new Timebyte[h.GetDataSize()];
    }
}

void TimeAVCCBox::PrintDataInfo() {
    printf("===========================\n");
    h.to_string();
    TimeBufferBitStream timeBufferBitStream(data, h.GetSize() - 8);
    configuration_version = timeBufferBitStream.GetUChar();
    avc_profile_indication = timeBufferBitStream.GetUChar();
    profile_compatibility = timeBufferBitStream.GetUChar();
    avc_level_indication = timeBufferBitStream.GetUChar();
    reserved = timeBufferBitStream.GetUChar();
    reserved2 = timeBufferBitStream.GetUChar();
    sps_length = timeBufferBitStream.GetUChar() << 8 | timeBufferBitStream.GetUChar();
    printf("sps: ");
    for (int i = 0; i < sps_length; ++i) {
        printf("%d ", timeBufferBitStream.GetUChar());
    }
    printf("\n");
    reserved3 = timeBufferBitStream.GetUChar();
    pps_length = timeBufferBitStream.GetUChar() << 8 | timeBufferBitStream.GetUChar();
    printf("pps: ");
    for (int i = 0; i < pps_length; ++i) {
        printf("%d ", timeBufferBitStream.GetUChar());
    }
    printf("\n");
}

完善一下Avc1 Box

// TimeAvc1.cpp

// ...

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) {
        TimeAVCCBox avccBox(header, data + offset + 8);
        avccBox.PrintDataInfo();
    }
}

运行结果

image-20211229223150880

上一篇:avcC mp4a Box 下一篇:esds Box
给我买个键盘吧。。。求打赏。。。
欢迎加群,一起交流~~~