AVPacket结构体并不是很复杂, 但是在ffmpeg中用的非常多. 与其相关的函数也是比较多.
AVPacket保存了解复用之后, 解码之前的数据, 和这些数据相关的一些附加信息.
对于视频来说, AVPacket通常包含一个压缩的frame; 而音频可能包含多个压缩的frame. 一个packet也可能是空的, 不包含任何压缩数据data, 而只包含附加数据side data(容器提供的关于packet的一些附加信息, 例如: 在编码结束的时候更新一些流的参数)
AVPacket是FFmpeg中为数不多的结构之一, 其大小是公共abi的一部分, 因此它可以在堆栈上分配, 如果libavcodec和libavformat没有很大的改动, 就不会向其中添加任何新字段.
官方文档:
AVPacket is one of the few structs in FFmpeg,whose size is a part of public ABI.Thus it may be allocated on stack and no new fields can be added to it without libavcodec and libavformat major bump.
ffmpeg 版本3.4.1, struct AVPacket定义于<libavcodec/avcodec.h>
struct AVPacket结构体源码:
1 typedef struct AVPacket { 2 /** 3 * A reference to the reference-counted buffer where the packet data is 4 * stored. 5 * May be NULL, then the packet data is not reference-counted. 6 */ 7 AVBufferRef *buf; 8 /** 9 * Presentation timestamp in AVStream->time_base units; the time at which 10 * the decompressed packet will be presented to the user. 11 * Can be AV_NOPTS_VALUE if it is not stored in the file. 12 * pts MUST be larger or equal to dts as presentation cannot happen before 13 * decompression, unless one wants to view hex dumps. Some formats misuse 14 * the terms dts and pts/cts to mean something different. Such timestamps 15 * must be converted to true pts/dts before they are stored in AVPacket. 16 */ 17 int64_t pts; 18 /** 19 * Decompression timestamp in AVStream->time_base units; the time at which 20 * the packet is decompressed. 21 * Can be AV_NOPTS_VALUE if it is not stored in the file. 22 */ 23 int64_t dts; 24 uint8_t *data; 25 int size; 26 int stream_index; 27 /** 28 * A combination of AV_PKT_FLAG values 29 */ 30 int flags; 31 /** 32 * Additional packet data that can be provided by the container. 33 * Packet can contain several types of side information. 34 */ 35 AVPacketSideData *side_data; 36 int side_data_elems; 37 38 /** 39 * Duration of this packet in AVStream->time_base units, 0 if unknown. 40 * Equals next_pts - this_pts in presentation order. 41 */ 42 int64_t duration; 43 44 int64_t pos; ///< byte position in stream, -1 if unknown 45 46 #if FF_API_CONVERGENCE_DURATION 47 /** 48 * @deprecated Same as the duration field, but as int64_t. This was required 49 * for Matroska subtitles, whose duration values could overflow when the 50 * duration field was still an int. 51 */ 52 attribute_deprecated 53 int64_t convergence_duration; 54 #endif 55 } AVPacket;
用来管理data指针引用的数据缓存.
显示时间, 比较关键的数据, 在做seek和播放进度的时候都要用到它, pts只是一个数量, 对应于AVStream->time_base, 要根据time_base才能转换为具体的时间, 音频和视频一般有不同的time_base, 所以在做音视频同步一定要做转换, 不能直接拿pts做.
基本属性等同于pts, 区别就是dts对应的是解码时间.
保存指向未解码数据的指针.
data的大小..
帧数据所属流的索引, 用来区分音频, 视频, 字幕等数据.
标志, 比如包含AV_PKT_FLAG_KEY值表示是关键帧.
#define AV_PKT_FLAG_KEY 0x0001
#define AV_PKT_FLAG_CORRUPT 0x0002
#define AV_PKT_FLAG_DISCARD 0x0004
#define AV_PKT_FLAG_TRUSTED 0x0008
容器提供的一些附加数据
附加数据元素个数.
数据的时长, 以所属媒体流的时间基准为单位, 未知则默认值0
数据在媒体流中的位置, 未知则默认值-1
2. AVPacket相关函数
函数主要分为:
void av_init_packet(AVPacket *pkt);
初始化packet的值为默认值, 该函数不会影响data应用的数据缓存空间和size.
内部调用了av_init_packet(pkt); 而且会为data分配空间.
创建一个AVPacket, 将其字段设置为默认值, 没有给data分配空间.
增加src->data引用计数.
如果src已经设置了引用计数, 则直接将引用计数+1;
如果src没有设置引用计数, 则创建一个新的引用计数buf, 并复制src->data到buf->buffer中.
最后复制src其它字段到dst中.
将缓存空间的引用计数-1;
并将packet中的其它字段设置为初始值.
如果引用计数为0, 则释放缓存空间.
释放使用av_packet_alloc 创建的AVPacket, 该函数会调用av_packet_unref.
函数内部调用了av_packet_alloc和av_packet_ref.
复制一个新的packet, 包括数据缓存.
int av_copy_packet_side_data(AVPacket *pkt, const AVPacket *src);
复制src的附加数据到pkt.
增大pkt->data指向的数据缓存.
减小pkt->data指向的数据缓存.
原文:https://www.cnblogs.com/changdingfang/p/11283593.html