ZigZag Sin
登 陆
上一篇:EBSP, RBSP, SODB 下一篇:NALU 的第一个字节

*代码-从 NALU 中提取 EBSP 和 RBSP

乔红
2022-2-20 18:06 阅读 3050

引言

上一节,我们已经知道了 NALU 中 EBSP 和 RBSP 的关系。知道了一个 NALU 中,去掉 Nalu Start Code 就是 EBSP,EBSP 去掉防竞争字节序,就是 RBSP。这一小节,我们就来写代码,提取 EBSP 和 RBSP。

提取 EBSP

首先,我们创建一个类,叫做 EBSP。我们给 EBSP 设置两个成员变量。

class EBSP {
public:
    EBSP();
    ~EBSP();

public:
    uint8_t * buf = nullptr;
    int len = 0;
};

用来表示 EBSP 的数据和长度。

之后,我们在 EBSP 的析构函数中,加入释放代码。

EBSP::~EBSP()
{
    if(buf != nullptr){
        free(buf);
        buf = nullptr;
    }
}

这样,我们可以将提取后的 EBSP 数据封装到一个 EBSP 的对象里面去(会涉及到一些拷贝,但是性能并不是我们这门课程最看重的)。

之后,我们就可以给 Nalu 类添加一个成员函数,用过调用这个成员函数,就可以把 Nalu 的数据进行处理,并且把结果存放到一个 EBSP 对象当中去。

int GetEBSP(EBSP & ebsp);

从 Nalu 中提取 EBSP 是很简单的,只需要把头部的 Nalu Start Code 去掉就可以了。实现如下:

int Nalu::GetEBSP(EBSP & ebsp)
{
    ebsp.len = len - startCodeLen;
    ebsp.buf = (uint8_t *)malloc(ebsp.len);

    memcpy(ebsp.buf, buf + startCodeLen, ebsp.len);

    return 0;
}

之后,我们可以在调用测试一下。

while(1){
    Nalu nalu;
    ret = reader.ReadNalu(nalu);
    if(ret){
        break;
    }

    EBSP ebsp;
    ret = nalu.GetEBSP(ebsp);
    if(ret){
        break;
    }
    printf("=====================\n");
    printf("Buffer Len: %d\n", ebsp.len);
    printf("%d %d %d %d %d\n", ebsp.buf[0], ebsp.buf[1], ebsp.buf[2], ebsp.buf[3], ebsp.buf[4]);
}

提取 RBSP

接下来,我们继续从 EBSP 中提取 RBSP。所谓提取 RBSP,实际上就是把 EBSP 中的防竞争字节序给去掉了。

同样,我们还是创建一个 RBSP 的类,也是创建一个 buf,一个 len,用来表示 RBSP 的数据和数据长度,然后在析构函数里释放掉。

class RBSP {
public:
    RBSP();
    ~RBSP();

public:
    uint8_t * buf = nullptr;
    int len = 0;
};

之后,我们在 EBSP 中添加一个成员函数,这个函数可以将 EBSP 的代码进行处理,并将处理后的数据存成一个 RBSP 对象。

int GetRBSP(RBSP & rbsp);

具体实现就是去掉数据中的防竞争字节序

int EBSP::GetRBSP(RBSP & rbsp)
{
    rbsp.len = len;
    rbsp.buf = (uint8_t *)malloc(rbsp.len);

    int targetIndex = 0;
    for(int i=0; i<len; i++){
        if(buf[i] == 0x03){
            // 查看前两个是不是 0x00 0x00
            if(i > 2){
                if(buf[i - 1] == 0x00 && buf[i - 2] == 0x00){
                    // 判断 后一个是不是 0 1 2 3
                    if(i < len - 1){
                        if(buf[i + 1] == 0x00 || buf[i + 1] == 0x01 || buf[i + 1] == 0x02 || buf[i + 1] == 0x03){
                            // 满足条件,该位置不进行拷贝
                            rbsp.len--;
                            continue;
                        }
                    }
                }
            }
        }
        rbsp.buf[targetIndex] = buf[i];
        targetIndex++;
    }
    return 0;
}

完整代码获取

https://github.com/redknotmiaoyuqiao/EyerH264Decoder/tree/main/Lesson_2_3_ReadAnnexB

上一篇:EBSP, RBSP, SODB 下一篇:NALU 的第一个字节
给我买个键盘吧。。。求打赏。。。
欢迎加群,一起交流~~~