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

相关文章

Spring核心思想之浅谈IoC容器与依赖倒置(DI)

《Spring核心思想之浅谈IoC容器与依赖倒置(DI)》文章介绍了Spring的IoC和DI机制,以及MyBatis的动态代理,通过注解和反射,Spring能够自动管理对象的创建和依赖注入,而MyB... 目录一、控制反转 IoC二、依赖倒置 DI1. 详细概念2. Spring 中 DI 的实现原理三、

Java中switch-case结构的使用方法举例详解

《Java中switch-case结构的使用方法举例详解》:本文主要介绍Java中switch-case结构使用的相关资料,switch-case结构是Java中处理多个分支条件的一种有效方式,它... 目录前言一、switch-case结构的基本语法二、使用示例三、注意事项四、总结前言对于Java初学者

结构体和联合体的区别及说明

《结构体和联合体的区别及说明》文章主要介绍了C语言中的结构体和联合体,结构体是一种自定义的复合数据类型,可以包含多个成员,每个成员可以是不同的数据类型,联合体是一种特殊的数据结构,可以在内存中共享同一... 目录结构体和联合体的区别1. 结构体(Struct)2. 联合体(Union)3. 联合体与结构体的

PostgreSQL如何查询表结构和索引信息

《PostgreSQL如何查询表结构和索引信息》文章介绍了在PostgreSQL中查询表结构和索引信息的几种方法,包括使用`d`元命令、系统数据字典查询以及使用可视化工具DBeaver... 目录前言使用\d元命令查看表字段信息和索引信息通过系统数据字典查询表结构通过系统数据字典查询索引信息查询所有的表名可

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

浅谈主机加固,六种有效的主机加固方法

在数字化时代,数据的价值不言而喻,但随之而来的安全威胁也日益严峻。从勒索病毒到内部泄露,企业的数据安全面临着前所未有的挑战。为了应对这些挑战,一种全新的主机加固解决方案应运而生。 MCK主机加固解决方案,采用先进的安全容器中间件技术,构建起一套内核级的纵深立体防护体系。这一体系突破了传统安全防护的局限,即使在管理员权限被恶意利用的情况下,也能确保服务器的安全稳定运行。 普适主机加固措施:

自定义类型:结构体(续)

目录 一. 结构体的内存对齐 1.1 为什么存在内存对齐? 1.2 修改默认对齐数 二. 结构体传参 三. 结构体实现位段 一. 结构体的内存对齐 在前面的文章里我们已经讲过一部分的内存对齐的知识,并举出了两个例子,我们再举出两个例子继续说明: struct S3{double a;int b;char c;};int mian(){printf("%zd\n",s

音视频入门基础:WAV专题(10)——FFmpeg源码中计算WAV音频文件每个packet的pts、dts的实现

一、引言 从文章《音视频入门基础:WAV专题(6)——通过FFprobe显示WAV音频文件每个数据包的信息》中我们可以知道,通过FFprobe命令可以打印WAV音频文件每个packet(也称为数据包或多媒体包)的信息,这些信息包含该packet的pts、dts: 打印出来的“pts”实际是AVPacket结构体中的成员变量pts,是以AVStream->time_base为单位的显

OpenCV结构分析与形状描述符(11)椭圆拟合函数fitEllipse()的使用

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C++11 算法描述 围绕一组2D点拟合一个椭圆。 该函数计算出一个椭圆,该椭圆在最小二乘意义上最好地拟合一组2D点。它返回一个内切椭圆的旋转矩形。使用了由[90]描述的第一个算法。开发者应该注意,由于数据点靠近包含的 Mat 元素的边界,返回的椭圆/旋转矩形数据

浅谈PHP5中垃圾回收算法(Garbage Collection)的演化

前言 PHP是一门托管型语言,在PHP编程中程序员不需要手工处理内存资源的分配与释放(使用C编写PHP或Zend扩展除外),这就意味着PHP本身实现了垃圾回收机制(Garbage Collection)。现在如果去PHP官方网站(php.net)可以看到,目前PHP5的两个分支版本PHP5.2和PHP5.3是分别更新的,这是因为许多项目仍然使用5.2版本的PHP,而5.3版本对5.2并不是完