基本介绍

AVPacket 是 FFmpeg 库中的一个重要结构体,用于表示音频、视频或字幕等媒体数据的一个数据包(packet)。在多媒体处理流程中,AVPacket 是最基本的传输和处理单元,它包含了编解码数据以及与数据相关的元信息,如时间戳、数据大小等。

AVPacket 的作用

AVPacket 是在解复用(demuxing)和复用(muxing)过程中传递音视频数据的结构体。解复用器从多媒体文件中提取出 AVPacket,解码器处理 AVPacket 中的数据,并生成帧(AVFrame)。同样,编码器会将帧编码成 AVPacket,复用器会将这些 AVPacket 写入多媒体文件。

AVPacket 结构体的主要成员

以下是 AVPacket 结构体中一些关键的成员变量及其作用:

  • uint8_t *data:指向数据包的实际数据。它包含了经过编码的音频或视频数据,通常是压缩的格式(如 H.264 视频或 AAC 音频)。
  • int size:表示数据包的大小,以字节为单位。这个值表示 data 指针指向的数据区域的大小。
  • int64_t pts:表示显示时间戳(Presentation Timestamp)。PTS 用于确定该数据包中的数据在播放时应该何时显示,确保音视频同步。
  • int64_t dts:表示解码时间戳(Decoding Timestamp)。DTS 用于指示解码器何时解码这个数据包。对于一些复杂的编码格式,如包含 B 帧的视频,DTS 和 PTS 可能不一样。
  • int64_t duration:表示该数据包在时间轴上的持续时间。这个值用于计算帧之间的显示间隔。
  • int stream_index:表示该数据包所属的流的索引。一个多媒体文件可能包含多个流(音频流、视频流、字幕流等),这个索引用于标识 AVPacket 属于哪个流。
  • int64_t pos:表示数据包在输入文件中的字节位置。这个值在某些情况下用于回溯或者调试。
  • int flags:用于指示数据包的特殊属性,如是否是关键帧(AV_PKT_FLAG_KEY)等。
  • AVBufferRef *buf:引用计数的缓冲区指针,用于管理 AVPacket 的数据内存。如果你复制或分配了 AVPacket,它帮助管理数据的生命周期。

PTS、DTS、duration介绍

  1. PTS(Presentation Timestamp)
  • 含义:PTS 表示帧应该在什么时候被显示出来。它是控制视频或音频在播放时的显示顺序和时间的关键参数。
  • 作用:PTS 用于确保帧在正确的时间被显示,从而保持音视频的同步。
  1. DTS(Decoding Timestamp)
  • 含义:DTS 表示帧应该在什么时候被解码。与 PTS 不同,DTS 用于控制帧的解码顺序。DTS 通常用于处理包含 B 帧(双向预测帧)的流,因为这些帧的解码顺序和显示顺序可能不同。
  • 作用:DTS 确保解码器按正确的顺序处理帧,从而生成正确的图像序列。
  1. duration(持续时间)
  • 含义duration 表示帧的持续时间,即在没有下一个帧到达之前,这个帧应该保持显示多长时间。
  • 作用:它用于确定帧之间的间隔,以维持正确的帧率。

关于duration * num / den

  • duration * num / den 是将时间长度从一个时间基转换为另一个时间基的常用计算方式。
  • 它确保在进行时间戳操作时,duration 的单位能够正确匹配新的时间基,使得时间轴上的所有操作(如解码、显示等)都能够正确同步。

duration举例

假设:

  • duration = 5000(表示 5000 个时间单位)
  • 源时间基 time_base = {1, 1000}(表示单位是毫秒)

那么:

1
2
3
duration * num / den = 5000 * 1 / 1000
= 5000 / 1000
= 5

这意味着在新的时间基下,duration 对应的时间长度是 5

注意】:在编码的时候$PTS >= DTS$

AVPacket 的生命周期

  • 分配:在处理前,AVPacket 需要被分配内存。你可以使用 av_init_packet() 函数初始化 AVPacket 结构,或者使用 av_packet_alloc() 动态分配一个新的 AVPacket
  • 填充数据:在解复用时,AVPacket 由解复用器填充数据,并将数据传递给解码器。或者,在编码时,编码器将生成的数据填充到 AVPacket 中,然后传递给复用器。
  • 释放:当一个 AVPacket 使用完毕后,需要释放它占用的内存。你可以使用 av_packet_unref() 来释放 AVPacket 持有的数据,并将其重置为默认状态。这样可以重复使用该 AVPacket。或者使用 av_packet_free() 来释放整个 AVPacket 结构体及其数据。

总结

AVPacket 是 FFmpeg 中用于表示媒体数据包的重要结构体,它封装了音频、视频或字幕数据以及相关的元数据。在媒体处理过程中,AVPacket 是数据传递的基本单元,广泛应用于解复用、解码、编码和复用等过程中。了解并正确使用 AVPacket 对于有效地处理多媒体数据至关重要。