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。

相关推荐
甲方求你学点技术吧18 小时前
8:从USB摄像头把声音拿出来--ALSA大佬登场!
linux·图像处理·ffmpeg·音视频
hjjdebug1 天前
ffmpeg 中 write_option()函数详细注释
ffmpeg·write_option
biubiubiu07061 天前
FFmpeg Windows安装
windows·ffmpeg
Gene_20221 天前
[TOOL] ubuntu 使用 ffmpeg 操作 gif、mp4
linux·ubuntu·ffmpeg
xhBruce2 天前
FFmpeg+javacpp中av_log使用
ffmpeg·ffmpeg+javacpp
DogDaoDao2 天前
Windows下VScode配置FFmpeg开发环境保姆级教程
windows·vscode·ffmpeg·音视频·gcc
1nv1s1ble2 天前
ffmpeg-api记录
ffmpeg
九流下半2 天前
window wsl 环境下编译openharmony,HarmonyOS 三方库 FFmpeg
windows·ffmpeg·harmonyos·编译·openharmony·三方库
aqi003 天前
FFmpeg开发笔记(七十四)Windows给FFmpeg集成二维码图像的编解码器
ffmpeg·音视频·直播·流媒体