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) 。

相关推荐
LoyalToOrigin6 小时前
iOS 26 libass字幕渲染问题兼容解决实践
ios·ffmpeg·objective-c
siv7711 小时前
影视解说视频智能生产全链路方案解析:从脚本生成到多平台分发
ffmpeg·srt字幕·ai剪辑·影视解说·ai电影解说·视频自动切割·字幕文件解析
独占的甜蜜11 小时前
从FLAC到WAV:whisper.cpp中的FFmpeg音频预处理全解析过程
ffmpeg·whisper·音视频
独占的甜蜜12 小时前
从FLAC到WAV:whisper.cpp中的FFmpeg音频预处理全解析
ffmpeg·whisper·音视频
JMchen1231 天前
集成第三方 C/C++ 库到 Android NDK 项目:OpenCV 与 FFmpeg 实战指南
opencv·ffmpeg·音视频开发·cmake·jni·ndk·abi 兼容性
qcx231 天前
【AI Agent实战】 0 成本视频处理全流程:ffmpeg + whisper 实现去水印、双语字幕、品牌片尾 | 实战SOP
人工智能·ffmpeg·音视频
huxiao_06011 天前
Windosw下VS 2022编译FFmpeg(支持x264、x265、fdk-acc)
ffmpeg·音视频
小驴程序源3 天前
TS 分片合并完整教程
python·ffmpeg
鬼蛟4 天前
Spring Cloud Alibaba
ffmpeg·bootstrap
米优4 天前
ffmpeg实现解码h264/h265裸码流
ffmpeg