FFmpeg源码:get_bit_length函数分析

一、get_bit_length函数的作用

get_bit_length函数的定义放在FFmpeg源码(本文演示用的FFmpeg源码版本为5.0.3,该ffmpeg在CentOS 7.5上通过10.2.1版本的gcc编译)的源文件libavcodec/h2645_parse.c中:

cpp 复制代码
static int get_bit_length(H2645NAL *nal, int skip_trailing_zeros)
{
//...
}

该函数在H.264/H.265解码时被调用。当FFmpeg对H.264/H.265解码执行完ff_h2645_extract_rbsp函数后,指针nal->data会指向一个缓冲区(该缓冲区存放"NALU Header + RBSP",详情可以参考FFmpeg源码:ff_h2645_extract_rbsp函数分析)。然后调用get_bit_length函数,可以得到nal->data指向的缓冲区的去掉补齐后的位数(bit),也就是NALU Header + SODB的位数。关于RBSP、SODB的概念可以参考《音视频入门基础:H.264专题(3)------EBSP, RBSP和SODB

形参nal:输入型参数:

nal->data:指向一个缓冲区,该缓冲区存放"NALU Header + RBSP"。

nal->size:nal->data指向的缓冲区的大小,单位为字节。

形参skip_trailing_zeros:计算返回值的位数(bit)时是否忽略nal->data指向的缓冲区最后ASCII码值为0的字符。值为0表示不忽略,1表示忽略。一般skip_trailing_zeros的值为1。

返回值:NALU Header + SODB的位数(bit)。注意这个返回值的单位是bit不是byte。8 bit 等于 1 byte,也就是1个字节等于8位。

二、get_bit_length函数的内部实现

get_bit_length函数的完整定义如下:

cpp 复制代码
static int get_bit_length(H2645NAL *nal, int skip_trailing_zeros)
{
    int size = nal->size;
    int v;

    while (skip_trailing_zeros && size > 0 && nal->data[size - 1] == 0)
        size--;

    if (!size)
        return 0;

    v = nal->data[size - 1];

    if (size > INT_MAX / 8)
        return AVERROR(ERANGE);
    size *= 8;

    /* remove the stop bit and following trailing zeros,
     * or nothing for damaged bitstreams */
    if (v)
        size -= ff_ctz(v) + 1;

    return size;
}

get_bit_length函数中首先会通过语句int size = nal->size;拿到 nal->data指向的缓冲区的大小(单位为字节)。然后通过:

cpp 复制代码
while (skip_trailing_zeros && size > 0 && nal->data[size - 1] == 0)
        size--;

去掉nal->data指向的缓冲区中最后ASCII码值为0的字符(因为最后ASCII码值为0的字符可能是下一个NALU的起始码的一部分。H.264 RBSP的最后必定是值为1的stop bit + 补齐用的rbsp_alignment_zero_bit,故最后ASCII码值为0的字符不可能是RBSP的结尾,所以得去掉)。

执行完上述语句后,size的值为NALU Header + RBSP 的实际长度(单位为字节)。

然后通过v = nal->data[size - 1] 得到RBSP最后一个字节的数据。由于8 bit 等于1 byte,通过size *= 8;得到NALU Header + RBSP的总位数,单位为bit。

通过ff_ctz(v),得到RBSP stop bit后面rbsp_alignment_zero_bit的位数。关于ff_ctz函数,可以参考:《FFmpeg源码:ff_ctz / ff_ctz_c函数分析》。

所以 ff_ctz(v) + 1 等于RBSP stop bit 加上 rbsp_alignment_zero_bit的位数。

语句size -= ff_ctz(v) + 1 等价于 size = size -( ff_ctz(v) + 1)。执行完后size的值即为NALU Header + SODB的位数(bit) 。

相关推荐
l***77524 小时前
从MySQL5.7平滑升级到MySQL8.0的最佳实践分享
ffmpeg
ZouZou老师10 小时前
FFmpeg性能优化经典案例
性能优化·ffmpeg
aqi0012 小时前
FFmpeg开发笔记(九十)采用FFmpeg套壳的音视频转码百宝箱FFBox
ffmpeg·音视频·直播·流媒体
齐齐大魔王14 小时前
FFmpeg
ffmpeg
你好音视频15 小时前
FFmpeg RTSP拉流流程深度解析
ffmpeg
IFTICing1 天前
【环境配置】ffmpeg下载、安装、配置(Windows环境)
windows·ffmpeg
haiy20111 天前
FFmpeg 编译
ffmpeg
aqi001 天前
FFmpeg开发笔记(八十九)基于FFmpeg的直播视频录制工具StreamCap
ffmpeg·音视频·直播·流媒体
八月的雨季 最後的冰吻1 天前
FFmepg--28- 滤镜处理 YUV 视频帧:实现上下镜像效果
ffmpeg·音视频
ganqiuye1 天前
向ffmpeg官方源码仓库提交patch
大数据·ffmpeg·video-codec