音视频从入门到精通——FFmpeg结构体:AVPacket分析

2023-10-28 13:20

本文主要是介绍音视频从入门到精通——FFmpeg结构体:AVPacket分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • FFmpeg结构体 AVPacket分析
  • AVPacket 相关函数介绍
  • FFmpeg AVPacket和AVFrame区别
  • 重要结构体之间的关系
    • 解协议(http, rtsp, rtmp, mms)
    • 解封装(flv, avi, rmvb, mp4)
    • 解码(h264, mpeg2, aac, mp3)
    • 存数据
  • 参考

FFmpeg结构体 AVPacket分析

FFmpeg结构体

AVPacket保存的是解码前的数据,也就是压缩后的数据。
该结构本身不直接包含数据,其有一个指向数据域的指针,FFmpeg中很多的数据结构都使用这种方法来管理数据。


/*** This structure stores compressed data. It is typically exported by demuxers* and then passed as input to decoders, or received as output from encoders and* then passed to muxers.** For video, it should typically contain one compressed frame. For audio it may* contain several compressed frames. Encoders are allowed to output empty* packets, with no compressed data, containing only side data* (e.g. to update some stream parameters at the end of encoding).** The semantics of data ownership depends on the buf field.* If it is set, the packet data is dynamically allocated and is* valid indefinitely until a call to av_packet_unref() reduces the* reference count to 0.** If the buf field is not set av_packet_ref() would make a copy instead* of increasing the reference count.** The side data is always allocated with av_malloc(), copied by* av_packet_ref() and freed by av_packet_unref().** sizeof(AVPacket) being a part of the public ABI is deprecated. once* av_init_packet() is removed, new packets will only be able to be allocated* with av_packet_alloc(), and new fields may be added to the end of the struct* with a minor bump.** @see av_packet_alloc* @see av_packet_ref* @see av_packet_unref*/
typedef struct AVPacket {/*** A reference to the reference-counted buffer where the packet data is* stored.* May be NULL, then the packet data is not reference-counted.*/AVBufferRef *buf;/*** Presentation timestamp in AVStream->time_base units; the time at which* the decompressed packet will be presented to the user.* Can be AV_NOPTS_VALUE if it is not stored in the file.* pts MUST be larger or equal to dts as presentation cannot happen before* decompression, unless one wants to view hex dumps. Some formats misuse* the terms dts and pts/cts to mean something different. Such timestamps* must be converted to true pts/dts before they are stored in AVPacket.*/int64_t pts;/*** Decompression timestamp in AVStream->time_base units; the time at which* the packet is decompressed.* Can be AV_NOPTS_VALUE if it is not stored in the file.*/int64_t dts;uint8_t *data;int   size;int   stream_index;/*** A combination of AV_PKT_FLAG values*/int   flags;/*** Additional packet data that can be provided by the container.* Packet can contain several types of side information.*/AVPacketSideData *side_data;int side_data_elems;/*** Duration of this packet in AVStream->time_base units, 0 if unknown.* Equals next_pts - this_pts in presentation order.*/int64_t duration;int64_t pos;                            ///< byte position in stream, -1 if unknown/*** for some private data of the user*/void *opaque;/*** AVBufferRef for free use by the API user. FFmpeg will never check the* contents of the buffer ref. FFmpeg calls av_buffer_unref() on it when* the packet is unreferenced. av_packet_copy_props() calls create a new* reference with av_buffer_ref() for the target packet's opaque_ref field.** This is unrelated to the opaque field, although it serves a similar* purpose.*/AVBufferRef *opaque_ref;/*** Time base of the packet's timestamps.* In the future, this field may be set on packets output by encoders or* demuxers, but its value will be by default ignored on input to decoders* or muxers.*/AVRational time_base;
} AVPacket;

部分字段说明

typedef struct AVPacket {
AVBufferRef *buf; //用来管理data指针引用的数据缓存
int64_t pts; //显示时间,结合AVStream->time_base转换成时间戳
int64_t dts; //解码时间,结合AVStream->time_base转换成时间戳
uint8_t *data; //★指向保存压缩数据的指针,这就是AVPacket的实际数据
int size; //data的大小
int stream_index; //packet在stream的index位置
int flags; //标示,结合AV_PKT_FLAG使用,其中最低为1表示该数据是一个关键帧。 
/*
* flags 可选:
* #define AV_PKT_FLAG_KEY 0x0001 //关键帧
* #define AV_PKT_FLAG_CORRUPT 0x0002 //损坏的数据
* #define AV_PKT_FLAG_DISCARD 0x0004 /丢弃的数据 
*/
AVPacketSideData *side_data; //容器提供的一些附加数据
int side_data_elems; //边缘数据元数个数
int64_t duration; //数据的时长,以所属媒体流的时间基准为单位,未知则值为默认值0 int64_t pos; //数据在流媒体中的位置,未知则值为默认值-1#if FF_API_CONVERGENCE_DURATIONattribute_deprecatedint64_t convergence_duration; //该字段已deprecated,不在使用 #endif
} AVPacket;

解码时AVPacket典型的使用场景为:

AVPacket *packet = av_packet_alloc(); // 创建一个packet
while(av_read_frame(pFormatCtx,packet))
{if(packet->stream_index == audio_index){...}else if(packet->stream_index == video_index){...}av_packet_unref(packet); // 不要忘记减少引用技术
}av_packet_free(packet);

在这里插入图片描述

AVPacket 相关函数介绍

av_read_frame:从媒体流中读取帧填充到Packet的数据缓存空间。如果Packet->buf为空,则Packet的数据缓存空间会在下次调用av_read_frame的时候失效。这也就是为何在FFmpeg3:播放音频中,从流中读取到Packet的时,在将该Packet插入队列时,要调用av_dup_avpacket重新复制一份缓存数据。

av_packet_alloc: 创建一个AVPacket,将其字段设为默认值(data为空,没有数据缓存空间)

av_packet_free: 释放使用av_packet_alloc创建的AVPacket,如果该Packet有引用计数(packet->buf不为空),则先调用av_packet_unref(&packet)。

av_packet_clone: 其功能是 av_packet_alloc + av_packet_ref

av_init_packet: 初始化packet的值为默认值,该函数不会影响data引用的数据缓存空间和size,需要单独处理。

av_new_packet: av_init_packet的增强版,不但会初始化字段,还为data分配了存储空间。

av_copy_packet: 复制一个新的packet,包括数据缓存。

av_packet_from_data: 初始化一个引用计数的packet,并指定了其数据缓存。

av_grow_packet: 增大Packet->data指向的数据缓存。

av_shrink_packet :减小Packet->data指向的数据缓存。

av_dup_packet: 是复制src->data引用的数据缓存,赋值给dst,也就是创建两个独立packet。说是3的版本册除了该方法,但4.1的源码里面又出现了该方法。

已经废弃的两个函数:av_dup_packetav_free_packet
av_free_packet: 释放packet,包括其data引用的数据缓存,现在可以使用av_packet_freeav_packet_unref代替。

FFmpeg AVPacket和AVFrame区别

在这里插入图片描述

AVPacket:存储压缩数据(视频对应H.264等码流数据,音频对应AAC/MP3等码流数据)
AVFrame:存储非压缩的数据(视频对应RGB/YUV像素数据,音频对应PCM采样数据)

重要结构体之间的关系

在这里插入图片描述
FFmpeg 中结构体很多。最关键的结构体可以分成以下几类:

解协议(http, rtsp, rtmp, mms)

  • AVIOContext ,URLProtocol ,URLContext 主要存储视音频使用的协议的类型以及状态。URLProtocol 存 储输入视音频使用的封装格式。每种协议都对应一个 URLProtocol 结构(注意:FFmpeg 中文件也被当 做一种协议 “file” )。

解封装(flv, avi, rmvb, mp4)

  • AVFormatContext 主要存储视音频封装格式中包含的信息;AVInputFormat 存储输入视音频使用的封装格式。每种视音频封装格式都对应一个 AVInputFormat 结构。

解码(h264, mpeg2, aac, mp3)

  • 每个 AVStream 存储一个视频/音频流的相关数据;每个 AVStream 对应一个 AVCodecContext ,存储该视 频/音频流使用解码方式的相关数据;每个 AVCodecContext 中对应一个 AVCodec ,包含该视频/音频对应 的解码器。每种解码器都对应一个 AVCodec 结构。

存数据

视频的话,每个结构一般是存一帧;音频可能有好几帧

  • 解码前数据:AVPacket
  • 解码后数据:AVFrame

参考

FFmpeg AVPacket 剖析以及使用
FFmpeg 中AVPacket的使用
ffmpeg中AVPacket与AVFrame中数据的传递与释放
AVPacket 详细说明

FFMPEG结构体分析:AVFrame
FFMPEG结构体分析:AVFormatContext
FFMPEG结构体分析:AVCodecContext
FFMPEG结构体分析:AVIOContext
FFMPEG结构体分析:AVCodec
FFMPEG结构体分析:AVStream
FFMPEG结构体分析:AVPacket

这篇关于音视频从入门到精通——FFmpeg结构体:AVPacket分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

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

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

从入门到精通详解Python虚拟环境完全指南

《从入门到精通详解Python虚拟环境完全指南》Python虚拟环境是一个独立的Python运行环境,它允许你为不同的项目创建隔离的Python环境,下面小编就来和大家详细介绍一下吧... 目录什么是python虚拟环境一、使用venv创建和管理虚拟环境1.1 创建虚拟环境1.2 激活虚拟环境1.3 验证虚

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

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

Java List 使用举例(从入门到精通)

《JavaList使用举例(从入门到精通)》本文系统讲解JavaList,涵盖基础概念、核心特性、常用实现(如ArrayList、LinkedList)及性能对比,介绍创建、操作、遍历方法,结合实... 目录一、List 基础概念1.1 什么是 List?1.2 List 的核心特性1.3 List 家族成

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

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

c++日志库log4cplus快速入门小结

《c++日志库log4cplus快速入门小结》文章浏览阅读1.1w次,点赞9次,收藏44次。本文介绍Log4cplus,一种适用于C++的线程安全日志记录API,提供灵活的日志管理和配置控制。文章涵盖... 目录简介日志等级配置文件使用关于初始化使用示例总结参考资料简介log4j 用于Java,log4c

史上最全MybatisPlus从入门到精通

《史上最全MybatisPlus从入门到精通》MyBatis-Plus是MyBatis增强工具,简化开发并提升效率,支持自动映射表名/字段与实体类,提供条件构造器、多种查询方式(等值/范围/模糊/分页... 目录1.简介2.基础篇2.1.通用mapper接口操作2.2.通用service接口操作3.进阶篇3

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

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

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

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

Python自定义异常的全面指南(入门到实践)

《Python自定义异常的全面指南(入门到实践)》想象你正在开发一个银行系统,用户转账时余额不足,如果直接抛出ValueError,调用方很难区分是金额格式错误还是余额不足,这正是Python自定义异... 目录引言:为什么需要自定义异常一、异常基础:先搞懂python的异常体系1.1 异常是什么?1.2