FFmpeg:浅谈 AVFrame 结构体

2024-04-09 20:48
文章标签 ffmpeg 结构 浅谈 avframe

本文主要是介绍FFmpeg:浅谈 AVFrame 结构体,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

成员变量

struct AVFrame 是一个很基础的类型,顾名思义,主要用来管理解码后的音视频数据:

  • 视频:一个 AVFrame 对象可存储一帧图像。
  • 音频:一个 AVFrame 对象可存储若干个采样点。

个人理解,AVFrame 主要的成员变量按照功能可划分为四部分:

  • 数据部分,这是最核心的部分啦,存储了解码后的音视频数据
    • uint8_t *data[AV_NUM_DATA_POINTERS]:存储音视频数据
    • int linesize[AV_NUM_DATA_POINTERS];:描述数据长度。具体含义取决于数据格式。
    • uint8_t **extended_data;data 的补充字段。当 data 不够用时,可用该字段存储。
    • AVBufferRef *buf[AV_NUM_DATA_POINTERS];:和 data 对应的引用计数器。buf[i]data[i] 一一对应。当 buf 全为 nullptr 时,说明该对应未启用引用计数功能。
    • AVBufferRef **extended_buf;:和 extended_data 对应的引用计数器。
    • int nb_extended_buf;extended_buf 的长度。
  • 辅助部分,用于解析数据部分,这里仅列出了一部分
    • 视频部分:
      • int width, height;:宽高
      • int key_frame;:1 → keyframe, 0 → not
      • enum AVPictureType pict_type;:类型。IPB, SSISP, BI
      • AVRational sample_aspect_ratio;:注释没看懂,度娘说是单个像素的宽高比。
      • int coded_picture_number;:比特流中的编码序列号。
      • int display_picture_number;:播放序列号。
      • int repeat_pict;:延迟参数,extra_delay = repeat_pict / (2*fps),未使用过。
    • 音频部分:
      • int nb_samples;:采样点的数量。
      • int sample_rate;:采样率。
      • uint64_t channel_layout;:声道布局。单声道,立体声,5.1 等等,详见函数 av_bprint_channel_layout
      • channels:声道数量。
    • 共用:
      • int format;:其值为 enum AVPixelFormat(对应视频) 或 enum AVSampleFormat(对应音频)
      • int64_t pts;:渲染时间,单位记录在 time_base 中。按个人经验看,有些解码器未给出该值,还是从对应的 AVStream 中取妥当。
      • int64_t pkt_dts;:该帧的解包时间。
      • AVRational time_base;:时间单位。
      • int quality;:取值范围在 [1,FF_LAMBDA_MAX],越小越好。
  • 用户相关部分:
    • AVBufferRef *opaque_ref; :用户可以放一些自定义数据在这。av_frame_* 等相关函数会维护其生命周期。
    • void *opaque:也是用户自定义的数据,但用户需自己维护生命周期。
  • codec 相关部分,一些 codec 依赖的字段,具体怎么用还不清楚,先记录在这里
    • AVFrameSideData **side_data;:具体怎么用还不清楚。
    • int nb_side_data;side_data 的长度。
    • AVBufferRef *private_ref;
    • AVBufferRef *hw_frames_ctx;
    • AVDictionary *metadata;:用户和 codec 可通过此字段传递各种类型的 KV 数据。

个人感觉,较难理清的是 dataextened_databufextended_buf 之间的关系,这里记录下 av_frame_get_buffer 如何初始化上述四个变量。

根据音视频数据是 packed 或者 planar 格式,使用方法略有差异。

视频的 packed 格式有 AV_PIX_FMT_YUYV422AV_PIX_FMT_UYYVYY411 等。
视频的 planar 格式有 AV_PIX_FMT_YUV420PAV_PIX_FMT_YUV444P 等。
音频的 packed 格式有 AV_SAMPLE_FMT_U8AV_SAMPLE_FMT_FLT 等。
音频的 planar 格式有 AV_SAMPLE_FMT_S32PAV_SAMPLE_FMT_FLTP 等。
简单概括,后缀为 P 的则为 planar 格式,反之为 packed 格式。

当数据为 packed 格式时:

  • extended_buf:未使用,初始化后值为 nullptr
  • buf:仅使用 buf[0],其余均为空。
  • data
    • 当数据为音频时,仅使用 data[0],值为 buf[0]->data
    • 当数据为视频时,根据AVFrame::format 字段决定。
  • extended_data:指向 data

下图是 AVFrame::formatAV_PIX_FMT_YUYV422 时的情形:

当数据为 planar 格式时,设 cplanar 的数量:

  • buf:使用 buf[0..min(7,c-1)]
  • extend_buf:当 c > 8 c\gt 8 c>8 时启用,指向一段新分配的内存,该内存存储了长度为 c − 8 c-8 c8 的指针数组。
  • data:使用 buf[0..min(7,c-1)]
  • extended_data
    • c ≤ 8 c\le 8 c8 时,指向 data
    • c > 8 c\gt 8 c>8 时,新分配一段内存,该内存存储了长度为 c c c 的指针数组。

下图以 c = 10 c = 10 c=10 的音频数据为例:

相关函数

AVFrame *av_frame_alloc(void)

分配一段内存,用于存储一个 AVFrame 对象。

void av_frame_free(AVFrame **frame)

释放相关内存。

int av_frame_ref(AVFrame *dst, const AVFrame *src)

该函数会处理所有字段,该复制的复制,该引用的引用。

void av_frame_unref(AVFrame *frame)

重置 AVFrame。可复用重置后的 AVFrame 对象,避免重复的分配回收内存。

int av_frame_copy_props(AVFrame *dst, const AVFrame *src)

该函数不会处理 AVFrame::bufAVFrame::extended_buf

int av_frame_get_buffer(AVFrame *frame, int align)

该函数会根据初始化 dataextended_databufextended_buf 等字段。

这篇关于FFmpeg:浅谈 AVFrame 结构体的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Python+FFmpeg实现视频自动化处理的完整指南

《Python+FFmpeg实现视频自动化处理的完整指南》本文总结了一套在Python中使用subprocess.run调用FFmpeg进行视频自动化处理的解决方案,涵盖了跨平台硬件加速、中间素材处理... 目录一、 跨平台硬件加速:统一接口设计1. 核心映射逻辑2. python 实现代码二、 中间素材处

MySQL快速复制一张表的四种核心方法(包括表结构和数据)

《MySQL快速复制一张表的四种核心方法(包括表结构和数据)》本文详细介绍了四种复制MySQL表(结构+数据)的方法,并对每种方法进行了对比分析,适用于不同场景和数据量的复制需求,特别是针对超大表(1... 目录一、mysql 复制表(结构+数据)的 4 种核心方法(面试结构化回答)方法 1:CREATE

Redis中Set结构使用过程与原理说明

《Redis中Set结构使用过程与原理说明》本文解析了RedisSet数据结构,涵盖其基本操作(如添加、查找)、集合运算(交并差)、底层实现(intset与hashtable自动切换机制)、典型应用场... 目录开篇:从购物车到Redis Set一、Redis Set的基本操作1.1 编程常用命令1.2 集

Vite 打包目录结构自定义配置小结

《Vite打包目录结构自定义配置小结》在Vite工程开发中,默认打包后的dist目录资源常集中在asset目录下,不利于资源管理,本文基于Rollup配置原理,本文就来介绍一下通过Vite配置自定义... 目录一、实现原理二、具体配置步骤1. 基础配置文件2. 配置说明(1)js 资源分离(2)非 JS 资

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

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

Java集合中的链表与结构详解

《Java集合中的链表与结构详解》链表是一种物理存储结构上非连续的存储结构,数据元素的逻辑顺序的通过链表中的引用链接次序实现,文章对比ArrayList与LinkedList的结构差异,详细讲解了链表... 目录一、链表概念与结构二、当向单链表的实现2.1 准备工作2.2 初始化链表2.3 打印数据、链表长

浅谈MySQL的容量规划

《浅谈MySQL的容量规划》进行MySQL的容量规划是确保数据库能够在当前和未来的负载下顺利运行的重要步骤,容量规划包括评估当前资源使用情况、预测未来增长、调整配置和硬件资源等,感兴趣的可以了解一下... 目录一、评估当前资源使用情况1.1 磁盘空间使用1.2 内存使用1.3 CPU使用1.4 网络带宽二、

创建springBoot模块没有目录结构的解决方案

《创建springBoot模块没有目录结构的解决方案》2023版IntelliJIDEA创建模块时可能出现目录结构识别错误,导致文件显示异常,解决方法为选择模块后点击确认,重新校准项目结构设置,确保源... 目录创建spChina编程ringBoot模块没有目录结构解决方案总结创建springBoot模块没有目录

SpringBoot利用树形结构优化查询速度

《SpringBoot利用树形结构优化查询速度》这篇文章主要为大家详细介绍了SpringBoot利用树形结构优化查询速度,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一个真实的性能灾难传统方案为什么这么慢N+1查询灾难性能测试数据对比核心解决方案:一次查询 + O(n)算法解决

Oracle查询表结构建表语句索引等方式

《Oracle查询表结构建表语句索引等方式》使用USER_TAB_COLUMNS查询表结构可避免系统隐藏字段(如LISTUSER的CLOB与VARCHAR2同名字段),这些字段可能为dbms_lob.... 目录oracle查询表结构建表语句索引1.用“USER_TAB_COLUMNS”查询表结构2.用“a