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_DURATION
attribute_deprecated
int64_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);
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_packet
和av_free_packet
av_free_packet
: 释放packet,包括其data引用的数据缓存,现在可以使用av_packet_free
或av_packet_unref
代替。
AVPacket:存储压缩数据(视频对应H.264等码流数据,音频对应AAC/MP3等码流数据)
AVFrame:存储非压缩的数据(视频对应RGB/YUV像素数据,音频对应PCM采样数据)
FFmpeg 中结构体很多。最关键的结构体可以分成以下几类:
视频的话,每个结构一般是存一帧;音频可能有好几帧
FFmpeg AVPacket 剖析以及使用
FFmpeg 中AVPacket的使用
ffmpeg中AVPacket与AVFrame中数据的传递与释放
AVPacket 详细说明
FFMPEG结构体分析:AVFrame
FFMPEG结构体分析:AVFormatContext
FFMPEG结构体分析:AVCodecContext
FFMPEG结构体分析:AVIOContext
FFMPEG结构体分析:AVCodec
FFMPEG结构体分析:AVStream
FFMPEG结构体分析:AVPacket