FFmpeg源码:AV_RB32宏定义分析

2024-06-22 03:04
文章标签 分析 源码 ffmpeg 定义 av rb32

本文主要是介绍FFmpeg源码:AV_RB32宏定义分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、AV_RB32宏定义的作用

AV_RB32是FFmpeg源码中经常出现的一个宏,其定义如下:

#ifndef AV_RB32
#   define AV_RB32(p)    AV_RB(32, p)
#endif

该宏定义有多层。把它简化为函数,其函数声明可以等价于:

uint32_t AV_RB32(uint8_t *data);

该函数作用是:按照大端模式 读取形参data指向的缓冲区的前四个字节,并返回。

形参data:输入型参数。指向某个缓冲区。

返回值:按照大端模式 读取到的 “形参data指向的缓冲区的前四个字节”。

二、AV_RB32宏定义的内部实现

 FFmpeg源码目录下的libavutil/intreadwrite.h 中存在如下宏定义:

#ifndef AV_RB32
#   define AV_RB32(p)    AV_RB(32, p)
#endif#ifndef AV_RN32
#   define AV_RN32(p) AV_RN(32, p)
#endif#   define AV_RB(s, p)    av_bswap##s(AV_RN##s(p))#   define AV_RN(s, p) (((const union unaligned_##s *) (p))->l)union unaligned_32 { uint32_t l; } __attribute__((packed)) av_alias;

libavutil/attributes.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#define av_alias __attribute__((may_alias))#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

所以 #   define AV_RB32(p)    AV_RB(32, p)  等价于 =>

#   define AV_RB32(p)  av_bswap32(AV_RN(32, p))  等价于 =>

#   define AV_RB32(p)  av_bswap32((((const union unaligned_32 *) (p))->l))

libavutil/bswap.h 中存在如下宏定义:

#define AV_BSWAP16C(x) (((x) << 8 & 0xff00)  | ((x) >> 8 & 0x00ff))
#define AV_BSWAP32C(x) (AV_BSWAP16C(x) << 16 | AV_BSWAP16C((x) >> 16))#ifndef av_bswap32
static av_always_inline av_const uint32_t av_bswap32(uint32_t x)
{return AV_BSWAP32C(x);
}
#endif

所以AV_BSWAP32C(x)  等价于 =>
(AV_BSWAP16C(x) << 16 | AV_BSWAP16C((x) >> 16))  等价于 =>

( (((x) << 8 & 0xff00)  | ((x) >> 8 & 0x00ff)) << 16 | ((((x) >> 16) << 8 & 0xff00)  | (((x) >> 16) >> 8 & 0x00ff)) )

所以

static av_always_inline av_const uint32_t av_bswap32(uint32_t x)
{return AV_BSWAP32C(x);
}

  等价于 =>

static __attribute__((always_inline)) inline __attribute__((const)) uint32_t av_bswap32(uint32_t x)
{return ( (((x) << 8 & 0xff00)  | ((x) >> 8 & 0x00ff)) << 16 | ((((x) >> 16) << 8 & 0xff00)  | (((x) >> 16) >> 8 & 0x00ff)) );
}

所以 AV_RB32(p);     等价于 =>

av_bswap32((((const union unaligned_32 *) (p))->l)); 等价于 =>

( ((((((const union unaligned_32 *) (p))->l)) << 8 & 0xff00)  | (((((const union unaligned_32 *) (p))->l)) >> 8 & 0x00ff)) << 16 | (((((((const union unaligned_32 *) (p))->l)) >> 16) << 8 & 0xff00)  | ((((((const union unaligned_32 *) (p))->l)) >> 16) >> 8 & 0x00ff)) );

三、编写测试例子,测试AV_RB32

main.c :

#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#define av_alias __attribute__((may_alias))#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#define AV_BSWAP16C(x) (((x) << 8 & 0xff00)  | ((x) >> 8 & 0x00ff))
#define AV_BSWAP32C(x) (AV_BSWAP16C(x) << 16 | AV_BSWAP16C((x) >> 16))#ifndef av_bswap32
static av_always_inline av_const uint32_t av_bswap32(uint32_t x)
{return AV_BSWAP32C(x);
}
#endifunion unaligned_32 { uint32_t l; } __attribute__((packed)) av_alias;#   define AV_RN(s, p) (((const union unaligned_##s *) (p))->l)
#   define AV_RB(s, p)    av_bswap##s(AV_RN##s(p))#ifndef AV_RB32
#   define AV_RB32(p)    AV_RB(32, p)
#endif#ifndef AV_RN32
#   define AV_RN32(p) AV_RN(32, p)
#endifint main()
{uint8_t *data = (uint8_t *)malloc(sizeof(uint8_t) * 8);if(data){data[0] = 0x12;data[1] = 0x34;data[2] = 0x56;data[3] = 0x78;data[4] = 0x9A;data[5] = 0xBC;data[6] = 0xDE;data[7] = 0xF0;printf("%lu\n", AV_RB32(data));printf("%lu\n", AV_RB32(data + 4));free(data);data = NULL;}return 0;
}

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

由于AV_RB32是按照大端模式读取。而data[0] = 0x12,data[1] = 0x34,data[2] = 0x56,data[3] = 0x78; 所以AV_RB32(data) 的值为0x12345678,换算成10进制就是305419896。

data[4] = 0x9A;data[5] = 0xBC;data[6] = 0xDE;data[7] = 0xF0;所以AV_RB32(data + 4) 的值为0x9ABCDEF0,换算成10进制就是2596069104。

AV_RB32(data) 将宏展开,实际就是:

( ((((((const union unaligned_32 *) (data))->l)) << 8 & 0xff00)  | (((((const union unaligned_32 *) (data))->l)) >> 8 & 0x00ff)) << 16 | (((((((const union unaligned_32 *) (data))->l)) >> 16) << 8 & 0xff00)  | ((((((const union unaligned_32 *) (data))->l)) >> 16) >> 8 & 0x00ff)) )

四、参考文章

《大小端模式》

这篇关于FFmpeg源码:AV_RB32宏定义分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1083104

相关文章

Python基于wxPython和FFmpeg开发一个视频标签工具

《Python基于wxPython和FFmpeg开发一个视频标签工具》在当今数字媒体时代,视频内容的管理和标记变得越来越重要,无论是研究人员需要对实验视频进行时间点标记,还是个人用户希望对家庭视频进行... 目录引言1. 应用概述2. 技术栈分析2.1 核心库和模块2.2 wxpython作为GUI选择的优

Python实现无痛修改第三方库源码的方法详解

《Python实现无痛修改第三方库源码的方法详解》很多时候,我们下载的第三方库是不会有需求不满足的情况,但也有极少的情况,第三方库没有兼顾到需求,本文将介绍几个修改源码的操作,大家可以根据需求进行选择... 目录需求不符合模拟示例 1. 修改源文件2. 继承修改3. 猴子补丁4. 追踪局部变量需求不符合很

Spring事务中@Transactional注解不生效的原因分析与解决

《Spring事务中@Transactional注解不生效的原因分析与解决》在Spring框架中,@Transactional注解是管理数据库事务的核心方式,本文将深入分析事务自调用的底层原理,解释为... 目录1. 引言2. 事务自调用问题重现2.1 示例代码2.2 问题现象3. 为什么事务自调用会失效3

找不到Anaconda prompt终端的原因分析及解决方案

《找不到Anacondaprompt终端的原因分析及解决方案》因为anaconda还没有初始化,在安装anaconda的过程中,有一行是否要添加anaconda到菜单目录中,由于没有勾选,导致没有菜... 目录问题原因问http://www.chinasem.cn题解决安装了 Anaconda 却找不到 An

Spring定时任务只执行一次的原因分析与解决方案

《Spring定时任务只执行一次的原因分析与解决方案》在使用Spring的@Scheduled定时任务时,你是否遇到过任务只执行一次,后续不再触发的情况?这种情况可能由多种原因导致,如未启用调度、线程... 目录1. 问题背景2. Spring定时任务的基本用法3. 为什么定时任务只执行一次?3.1 未启用

C++ 各种map特点对比分析

《C++各种map特点对比分析》文章比较了C++中不同类型的map(如std::map,std::unordered_map,std::multimap,std::unordered_multima... 目录特点比较C++ 示例代码 ​​​​​​代码解释特点比较1. std::map底层实现:基于红黑

Spring、Spring Boot、Spring Cloud 的区别与联系分析

《Spring、SpringBoot、SpringCloud的区别与联系分析》Spring、SpringBoot和SpringCloud是Java开发中常用的框架,分别针对企业级应用开发、快速开... 目录1. Spring 框架2. Spring Boot3. Spring Cloud总结1. Sprin

Spring 中 BeanFactoryPostProcessor 的作用和示例源码分析

《Spring中BeanFactoryPostProcessor的作用和示例源码分析》Spring的BeanFactoryPostProcessor是容器初始化的扩展接口,允许在Bean实例化前... 目录一、概览1. 核心定位2. 核心功能详解3. 关键特性二、Spring 内置的 BeanFactory

MyBatis-Plus中Service接口的lambdaUpdate用法及实例分析

《MyBatis-Plus中Service接口的lambdaUpdate用法及实例分析》本文将详细讲解MyBatis-Plus中的lambdaUpdate用法,并提供丰富的案例来帮助读者更好地理解和应... 目录深入探索MyBATis-Plus中Service接口的lambdaUpdate用法及示例案例背景

MyBatis-Plus中静态工具Db的多种用法及实例分析

《MyBatis-Plus中静态工具Db的多种用法及实例分析》本文将详细讲解MyBatis-Plus中静态工具Db的各种用法,并结合具体案例进行演示和说明,具有很好的参考价值,希望对大家有所帮助,如有... 目录MyBATis-Plus中静态工具Db的多种用法及实例案例背景使用静态工具Db进行数据库操作插入