=================================================================
AVPacket结构体和其相关的函数分析:
FFmpeg存放压缩后的音视频数据的结构体:AVPacket简介
FFmpeg源码:av_init_packet、get_packet_defaults、av_packet_alloc函数分析
FFmpeg源码:av_packet_free_side_data、av_packet_unref、av_packet_free函数分析
FFmpeg源码:packet_alloc、av_new_packet、av_shrink_packet、av_grow_packet函数分析
FFmpeg源码:av_packet_move_ref、av_packet_make_refcounted函数分析
FFmpeg源码:PacketList结构体、avpriv_packet_list_put、avpriv_packet_list_get、avpriv_packet_list_free函数分析
FFmpeg源码:append_packet_chunked、av_get_packet、av_append_packet函数分析
FFmpeg中调用av_read_frame函数导致的内存泄漏问题
=================================================================
FFmpeg源码中通过AVPacket存储压缩后的音视频数据。它通常由解复用器(demuxers)输出,然后作为输入传递给解码器,或者从编码器作为输出接收,然后传递给多路复用器(muxers)。对于视频,它通常包含一个压缩帧;对于音频,它可能包含几个压缩帧。编码器允许输出不包含压缩音视频数据、只包含side data(边数据:例如,在编码结束时更新一些流参数)的空的数据包( empty packets)。
AVPacket结构体声明在FFmpeg源码(本文演示用的FFmpeg源码版本为7.0.1)的头文件libavcodec/packet.h中:
/**
* @}
*/
/**
* @defgroup lavc_packet AVPacket
*
* Types and functions for working with AVPacket.
* @{
*/
/**
* 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;
成员变量buf:AVBufferRef类型指针,指向“存储packet(一个数据包的压缩后的音视频)数据的引用计数缓冲区”。如果为NULL,表示该packet数据未被引用计数。AVPacket通过AVBufferRef来管理引用计数缓冲区。通过AVBufferRef结构体里面的AVBuffer里面的成员变量refcount记录资源使用的次数,控制资源的释放。关于AVBufferRef类型可以参考:《FFmpeg引用计数数据缓冲区相关的结构体:AVBuffer、AVBufferRef简介》。
成员变量pts:显示时间戳(presentation time stamp)。即帧显示的时间刻度,用来告诉播放器在哪个时间点显示此帧(可以简单理解为这帧视频或音频数据的播放时间)。其单位不是秒,而是以AVStream->time_base为单位。pts必须大于或等于dts,因为一帧视频或音频数据必须在解码后才能播放,所以一帧视频或音频数据的显示/播放时间必须大于或等于解码时间。
成员变量dts:解码时间戳(Decompression timestamp)。即帧解码的时间刻度,用来告诉播放器在哪个时间点解码此帧。其单位不是秒,而是以AVStream->time_base为单位。
成员变量data:指针,指向“存放压缩后的一帧(对于视频通常包含一个压缩帧,对于音频可能包含几个压缩帧)音视频数据的缓冲区”。
成员变量size:成员变量data指向的缓冲区的大小,单位为字节。
成员变量stream_index:索引,用来标识该AVPacket所属的视频/音频流的序号,表示这是第几路流。注意:它是从0而不是从1开始的。
成员变量flags:AV_PKT_FLAG的组合。值有如下选择:
#define AV_PKT_FLAG_KEY 0x0001 ///< The packet contains a keyframe
#define AV_PKT_FLAG_CORRUPT 0x0002 ///< The packet content is corrupted
/**
* Flag is used to discard packets which are required to maintain valid
* decoder state but are not required for output and should be dropped
* after decoding.
**/
#define AV_PKT_FLAG_DISCARD 0x0004
/**
* The packet comes from a trusted source.
*
* Otherwise-unsafe constructs such as arbitrary pointers to data
* outside the packet may be followed.
*/
#define AV_PKT_FLAG_TRUSTED 0x0008
/**
* Flag is used to indicate packets that contain frames that can
* be discarded by the decoder. I.e. Non-reference frames.
*/
#define AV_PKT_FLAG_DISPOSABLE 0x0010
AV_PKT_FLAG_KEY:数据包包含一个关键帧,即当前AVPacket是关键帧。
AV_PKT_FLAG_CORRUPT:数据包内容已损坏。
AV_PKT_FLAG_DISCARD:用于丢弃需要保持有效解码器状态但不需要输出的数据包,并且在解码后应该丢弃。带有该标志的AVPacket所携带的数据为解码器相关的信息,不会被解码出一幅图像。
AV_PKT_FLAG_TRUSTED:该数据包来自一个可信的源。
AV_PKT_FLAG_DISPOSABLE:用于指示包含可以被解码器丢弃的帧的数据包。也就是非参考帧。
成员变量side_data:存放“容器可以提供的额外数据包数据”的数组的首地址。数据包可以包含多种类型的边信息,比如,在编码结束的时候更新一些流的参数。指针side_data指向的空间存储了用于解码、展现或处理编码流的辅助信息,它通常由解复用器和编码器导出,可以以分组为单位提供给解码器和复用器,也可以作为全局侧数据(应用于整个编码流)。
成员变量side_data_elems: side_data的数量。
成员变量duration:该数据包的持续时间,以AVStream->time_base为单位。值为下一个数据包的pts减去当前数据包的pts。如果值为0表示未知。
成员变量pos:该数据包在流中的位置,单位为字节。值为-1表示未知。
成员变量opaque:指针,指向“存放用户使用的私有数据的缓冲区”。
成员变量time_base:AVRational类型,数据包时间戳的时间基准,即pts和dts的时间基。关于AVRational类型可以参考:《FFmpeg有理数相关的源码:AVRational结构体和其相关的函数分析》。