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

相关文章

基于Java和FFmpeg实现视频压缩和剪辑功能

《基于Java和FFmpeg实现视频压缩和剪辑功能》在视频处理开发中,压缩和剪辑是常见的需求,本文将介绍如何使用Java结合FFmpeg实现视频压缩和剪辑功能,同时去除数据库操作,仅专注于视频处理,需... 目录引言1. 环境准备1.1 项目依赖1.2 安装 FFmpeg2. 视频压缩功能实现2.1 主要功

Android 缓存日志Logcat导出与分析最佳实践

《Android缓存日志Logcat导出与分析最佳实践》本文全面介绍AndroidLogcat缓存日志的导出与分析方法,涵盖按进程、缓冲区类型及日志级别过滤,自动化工具使用,常见问题解决方案和最佳实... 目录android 缓存日志(Logcat)导出与分析全攻略为什么要导出缓存日志?按需过滤导出1. 按

Linux中的HTTPS协议原理分析

《Linux中的HTTPS协议原理分析》文章解释了HTTPS的必要性:HTTP明文传输易被篡改和劫持,HTTPS通过非对称加密协商对称密钥、CA证书认证和混合加密机制,有效防范中间人攻击,保障通信安全... 目录一、什么是加密和解密?二、为什么需要加密?三、常见的加密方式3.1 对称加密3.2非对称加密四、

MySQL中读写分离方案对比分析与选型建议

《MySQL中读写分离方案对比分析与选型建议》MySQL读写分离是提升数据库可用性和性能的常见手段,本文将围绕现实生产环境中常见的几种读写分离模式进行系统对比,希望对大家有所帮助... 目录一、问题背景介绍二、多种解决方案对比2.1 原生mysql主从复制2.2 Proxy层中间件:ProxySQL2.3

Django中的函数视图和类视图以及路由的定义方式

《Django中的函数视图和类视图以及路由的定义方式》Django视图分函数视图和类视图,前者用函数处理请求,后者继承View类定义方法,路由使用path()、re_path()或url(),通过in... 目录函数视图类视图路由总路由函数视图的路由类视图定义路由总结Django允许接收的请求方法http

python使用Akshare与Streamlit实现股票估值分析教程(图文代码)

《python使用Akshare与Streamlit实现股票估值分析教程(图文代码)》入职测试中的一道题,要求:从Akshare下载某一个股票近十年的财务报表包括,资产负债表,利润表,现金流量表,保存... 目录一、前言二、核心知识点梳理1、Akshare数据获取2、Pandas数据处理3、Matplotl

python panda库从基础到高级操作分析

《pythonpanda库从基础到高级操作分析》本文介绍了Pandas库的核心功能,包括处理结构化数据的Series和DataFrame数据结构,数据读取、清洗、分组聚合、合并、时间序列分析及大数据... 目录1. Pandas 概述2. 基本操作:数据读取与查看3. 索引操作:精准定位数据4. Group

MySQL中EXISTS与IN用法使用与对比分析

《MySQL中EXISTS与IN用法使用与对比分析》在MySQL中,EXISTS和IN都用于子查询中根据另一个查询的结果来过滤主查询的记录,本文将基于工作原理、效率和应用场景进行全面对比... 目录一、基本用法详解1. IN 运算符2. EXISTS 运算符二、EXISTS 与 IN 的选择策略三、性能对比

MySQL 内存使用率常用分析语句

《MySQL内存使用率常用分析语句》用户整理了MySQL内存占用过高的分析方法,涵盖操作系统层确认及数据库层bufferpool、内存模块差值、线程状态、performance_schema性能数据... 目录一、 OS层二、 DB层1. 全局情况2. 内存占js用详情最近连续遇到mysql内存占用过高导致

深度解析Nginx日志分析与499状态码问题解决

《深度解析Nginx日志分析与499状态码问题解决》在Web服务器运维和性能优化过程中,Nginx日志是排查问题的重要依据,本文将围绕Nginx日志分析、499状态码的成因、排查方法及解决方案展开讨论... 目录前言1. Nginx日志基础1.1 Nginx日志存放位置1.2 Nginx日志格式2. 499