主要介绍AVPacket这个结构体以及其用法。

AVPacket是FFmpeg中一个管理压缩后的媒体数据的结构,它本身不包含压缩的媒体数据,而是通过 data 指针指向媒体数据。

这里面的媒体数据通常是一帧视频的数据,或者一帧音频的数据。但是也有一些特殊情况,这个 AVPacket 的 data 是空的,只有 side data 的数据。side data 是一些附加信息。

读取文件内容相关函数:

1,av_packet_alloc,初始化一个 AVPacket

2,av_read_frame,从 AVFormatContext 容器里面读取一个 AVPacket,需要注意,虽然函数名是 frame,但是读取的是 AVPacket

3,av_packet_unref,减少 AVPacket 对 编码数据的引用次数。减到 0 会释放 编码数据的内存。

4,av_packet_free,释放 AVPacket 自身的内存。里面会调 av_packet_unref

av_packet_alloc 初始化一个 AVPacket ,那是不是用 av_read_frame 读一次数据,就要调一次 av_packet_alloc 呢?

不是,因为 AVPacket 他本身是没有编码数据的,他只是管理编码数据,也就是说 av_packet_alloc 的时候,AVPacket 里面还没有编码数据的,是后面通过 av_read_frameAVPacket 里面的 buf 引用指向了编码数据。

如果你要调多次 av_read_frame,只需要先用 av_packet_unref 消除 AVPacket 里面对之前的编码数据的引用即可。只有最后用不到 AVPacket 的时候,才需要调 av_packet_free 来释放 AVPacket 的内存。

av_read_frame 的返回值有很多种情况。

1,成功读取到一个 AVPacket

2,读取到文件末尾。

3,网络流有问题,或者本地硬盘坏了。导致 AVFormatContext 里面的 pb->error 有异常。

AVPacket 里面有一个 stream_index 字段,代表这个 AVPacket 属于哪个流,那我们怎么知道这是一个音频包,还是视频包?在下面的字段里面:

fmt_ctx->streams[0]->codecpar->codec_type

codec_type 等于 0 代表这是一个视频流,1 代表这是一个音频流

然后 AVPacket 里面还有一个 duration 字段,代表这帧数据要播放 多久。时间基是 11988 ,时间基就是 1秒钟分成11988份,然后这个视频包占了 500 份,也就是当前帧要播放 0.04 秒

然后 AVPacket 里面还有一个 pos 字段,这个字段就代表,data 里面的数据是从 mp4 文件的哪个位置读取出来的

AVPacket 里面 size 字段代表这个视频包有多大,也就是 data 的长度

详细的:

avpkt(输入AVPacket

  • 内容avpkt通常包含单个视频帧或几个完整的音频帧。它是解码过程的输入。

  • 所有权AVPacket的所有权保留在调用者手中。解码器不会修改AVPacket本身(即不会写入数据到AVPacket),但可能会创建对AVPacket数据的引用(如果AVPacket不是引用计数的,则可能会复制数据)。

  • 处理:与旧API不同,AVPacket总是被完全消耗。如果它包含多个帧(例如某些音频编解码器),则需要在发送新的AVPacket之前多次调用avcodec_receive_frame()函数来接收所有帧。

  • 空数据包/刷新流avpkt可以是NULL(或一个AVPacketdata设置为NULLsize设置为0)。在这种情况下,它被视为一个刷新包(flush packet),用于指示流的结束。发送第一个刷新包将返回成功;后续的刷新包是不必要的,并会返回AVERROR_EOF。如果解码器仍然有缓冲的帧,它将在发送刷新包后返回这些帧。