当前位置: 首页 > news >正文

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

四、参考文章

《大小端模式》

相关文章:

  • 检测管理信息系统的设计与开发实现:软件功能设计
  • MyBatis系列六: 映射关系多对一
  • pip设置国内源:阿里云、腾讯云、清华大学源
  • leetcode144. 二叉树的前序遍历
  • python学习笔记-10
  • 新版本vue-cli打包之后没有css文件
  • 数据分析:解锁业务洞察与决策优化的关键
  • android之WindowManager悬浮框
  • C#面:C# 类的执行顺序?
  • [pmayavi][python]mayavi所有whl文件下载地址汇总
  • “探索未来之音:AI音乐创作的前沿技术与应用“
  • 安卓逆向案例——XX电影网
  • Ilya出走记:SSI的超级安全革命
  • Python面试宝典:Python中与常用的机器学习库相关的面试笔试题(1000加面试笔试题助你轻松捕获大厂Offer)
  • 设置Docker容器开机自启
  • ES6指北【2】—— 箭头函数
  • 2017届校招提前批面试回顾
  • ERLANG 网工修炼笔记 ---- UDP
  • ES6简单总结(搭配简单的讲解和小案例)
  • EventListener原理
  • JavaScript中的对象个人分享
  • Js基础知识(一) - 变量
  • Sublime Text 2/3 绑定Eclipse快捷键
  • 番外篇1:在Windows环境下安装JDK
  • 如何利用MongoDB打造TOP榜小程序
  • 山寨一个 Promise
  • 限制Java线程池运行线程以及等待线程数量的策略
  • 想写好前端,先练好内功
  • 一天一个设计模式之JS实现——适配器模式
  • 正则与JS中的正则
  • 自制字幕遮挡器
  • 东超科技获得千万级Pre-A轮融资,投资方为中科创星 ...
  • !! 2.对十份论文和报告中的关于OpenCV和Android NDK开发的总结
  • (3)选择元素——(17)练习(Exercises)
  • (c语言+数据结构链表)项目:贪吃蛇
  • (二)hibernate配置管理
  • (附源码)spring boot儿童教育管理系统 毕业设计 281442
  • (含笔试题)深度解析数据在内存中的存储
  • (免费领源码)python+django+mysql线上兼职平台系统83320-计算机毕业设计项目选题推荐
  • (已更新)关于Visual Studio 2019安装时VS installer无法下载文件,进度条为0,显示网络有问题的解决办法
  • (原創) 如何刪除Windows Live Writer留在本機的文章? (Web) (Windows Live Writer)
  • .NET Core 控制台程序读 appsettings.json 、注依赖、配日志、设 IOptions
  • .net on S60 ---- Net60 1.1发布 支持VS2008以及新的特性
  • .net 打包工具_pyinstaller打包的exe太大?你需要站在巨人的肩膀上-VC++才是王道
  • .net 后台导出excel ,word
  • .NET 直连SAP HANA数据库
  • .NetCore Flurl.Http 升级到4.0后 https 无法建立SSL连接
  • .NET面试题解析(11)-SQL语言基础及数据库基本原理
  • .Net通用分页类(存储过程分页版,可以选择页码的显示样式,且有中英选择)
  • @vue-office/excel 解决移动端预览excel文件触发软键盘
  • @取消转义
  • [012-1].第12节:Mysql的配置文件的使用
  • [1159]adb判断手机屏幕状态并点亮屏幕
  • [5] CUDA线程调用与存储器架构
  • [ACTF2020 新生赛]Include