FFmpeg源码:ff_ctz / ff_ctz_c函数分析

一、ff_ctz函数的作用

ff_ctz定义在FFmpeg源码目录的libavutil/intmath.h 下:

cpp 复制代码
#ifndef ff_ctz
#define ff_ctz ff_ctz_c
/**
 * Trailing zero bit count.
 *
 * @param v  input value. If v is 0, the result is undefined.
 * @return   the number of trailing 0-bits
 */
/* We use the De-Bruijn method outlined in:
 * http://supertech.csail.mit.edu/papers/debruijn.pdf. */
static av_always_inline av_const int ff_ctz_c(int v)
{
    //...
}
#endif

可以看到ff_ctz函数等价于ff_ctz_c函数。其作用是:如果形参v的值为0,返回0。否则将形参v转成二进制,返回其最后一个"1"后面"0"的个数。

形参v:输入型参数。需要被计算的值。

返回值:将形参v转成二进制,返回的最后一个"1"后面"0"的个数。

ff_ctz函数一般用在统计H.264 RBSP最后补齐了多少个0位。也就是stop bit后面rbsp_alignment_zero_bit的个数。详情可以参考:《音视频入门基础:H.264专题(3)------EBSP, RBSP和SODB

二、ff_ctz函数的内部实现

cpp 复制代码
#ifndef ff_ctz
#define ff_ctz ff_ctz_c
/**
 * Trailing zero bit count.
 *
 * @param v  input value. If v is 0, the result is undefined.
 * @return   the number of trailing 0-bits
 */
/* We use the De-Bruijn method outlined in:
 * http://supertech.csail.mit.edu/papers/debruijn.pdf. */
static av_always_inline av_const int ff_ctz_c(int v)
{
    static const uint8_t debruijn_ctz32[32] = {
        0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
        31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
    };
    return debruijn_ctz32[(uint32_t)((v & -v) * 0x077CB531U) >> 27];
}
#endif

三、编写测试例子,测试ff_ctz函数

main.c :

cpp 复制代码
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>


#ifdef __GNUC__
#    define AV_GCC_VERSION_AT_LEAST(x,y) (__GNUC__ > (x) || __GNUC__ == (x) && __GNUC_MINOR__ >= (y))
#    define AV_GCC_VERSION_AT_MOST(x,y)  (__GNUC__ < (x) || __GNUC__ == (x) && __GNUC_MINOR__ <= (y))
#else
#    define AV_GCC_VERSION_AT_LEAST(x,y) 0
#    define AV_GCC_VERSION_AT_MOST(x,y)  0
#endif

#ifndef av_always_inline
#if AV_GCC_VERSION_AT_LEAST(3,1)
#    define av_always_inline __attribute__((always_inline)) inline
#elif defined(_MSC_VER)
#    define av_always_inline __forceinline
#else
#    define av_always_inline inline
#endif
#endif

#if AV_GCC_VERSION_AT_LEAST(2,6) || defined(__clang__)
#    define av_const __attribute__((const))
#else
#    define av_const
#endif


#ifndef ff_ctz
#define ff_ctz ff_ctz_c
/**
 * Trailing zero bit count.
 *
 * @param v  input value. If v is 0, the result is undefined.
 * @return   the number of trailing 0-bits
 */
/* We use the De-Bruijn method outlined in:
 * http://supertech.csail.mit.edu/papers/debruijn.pdf. */
static av_always_inline av_const int ff_ctz_c(int v)
{
    static const uint8_t debruijn_ctz32[32] = {
        0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
        31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
    };
    return debruijn_ctz32[(uint32_t)((v & -v) * 0x077CB531U) >> 27];
}
#endif


int main()
{
    printf("%d\n", ff_ctz(0));
    printf("%d\n", ff_ctz(80));
    printf("%d\n", ff_ctz(100));
    printf("%d\n", ff_ctz(128));
    printf("%d\n", ff_ctz(255));
    return 0;
}

Linux平台下使用gcc编译(我用的是CentOS 7.5,通过10.2.1版本的gcc编译)。输出为:

ff_ctz函数形参v的值为0时,返回0,所以ff_ctz(0)值为0。

80转成二进制为01010000。最后的1后面有4位0。所以ff_ctz(80)值为4。

100转成二进制为01100100。最后的1后面有2位0。所以ff_ctz(100)值为2。

128转成二进制为10000000。最后的1后面有7位0。所以ff_ctz(128)值为7。

255转成二进制为11111111。最后的1后面有0位0。所以ff_ctz(255)值为0。

相关推荐
邪恶的贝利亚1 天前
《ffplay 读线程与解码线程分析:从初始化到 seek 操作,对比视频与音频解码的差异》
ffmpeg·php·音视频
路溪非溪2 天前
关于ffmpeg的简介和使用总结
ffmpeg
gushansanren2 天前
基于WSL用MSVC编译ffmpeg7.1
windows·ffmpeg
追随远方4 天前
Android平台FFmpeg音视频开发深度指南
android·ffmpeg·音视频
charlie1145141915 天前
编译日志:关于编译opencv带有ffmpeg视频解码支持的若干办法
opencv·ffmpeg·音视频·imx6ull·移植教程
追随远方5 天前
Android平台FFmpeg视频解码全流程指南
android·ffmpeg·音视频
urhero6 天前
Python+ffmpeg 实现给视频添加字幕
ffmpeg·音视频·python编程·视频编辑·实用视频工具·添加字幕
追随远方6 天前
Android NDK版本迭代与FFmpeg交叉编译完全指南
android·ffmpeg
带鱼工作室6 天前
ffmpeg多媒体(音视频)处理常用命令
ffmpeg·音视频
批量小王子7 天前
2025-05-07-FFmpeg视频裁剪(尺寸调整,画面比例不变)
ffmpeg·音视频