FFmpeg读取文件内容AVPacket

简介: FFmpeg读取文件内容AVPacket

本文的代码下载地址:GitHub,编译环境是 Qt 5.15.2 跟 MSVC2019_64bit 。


读取文件内容 相关的结构体如下:

1,AVPacket,一个管理压缩后的媒体数据的结构,它本身不包含压缩的媒体数据,而是通过 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 会释放 编码数据的内存。

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



下面就结合本文代码来理解上面这些函数跟 AVPacket 的使用。请看下图:

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

1,成功读取到一个 AVPacket

2,读取到文件末尾。

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

我上面的代码没有处理这些情况,我假设他会成功读取到 一个 AVPacket 。这些情况 在 ffplay.c 里面都被正确处理。请参考 ffplay.c 写出更健壮的代码。


上面的代码只读了一个 AVPacket

从上图代码可以看出,我用 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 的内存。


上面的代码运行情况如下:

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

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

我代码里面打印了这个值,可以看到是 0 跟 1,实际上,这是两个常量 AVMEDIA_TYPE_VIDEOAVMEDIA_TYPE_AUDIO 的值,如下:

因此,codec_type 等于 0 代表这是一个视频流,1 代表这是一个音频流。因此咱们打印的这个包是视频包


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


然后 AVPacket 里面还有一个 pos 字段,这个字段就代表,data 里面的数据是从 mp4 文件的哪个位置读取出来的,我上面打印了 7个字节的数据,0 0 2 37 6 5 ff

pos 等于 48,也就是 0x30,我们可以用 HxD 来查看一下 juren-30s.mp4 文件,如下:

数据是完全一致的,size 字段代表这个视频包有多大,本文是 10201 字节大小。


最后,本文给出了循环读多个 AVPacket 的示例,读者只需把 type 变量设置成 2 即可,如下:

相关阅读:

1,《printf 格式化输出符号详细说明》

目录
相关文章
|
4月前
|
网络协议 应用服务中间件 Linux
【音视频 ffmpeg 学习】 RTMP推流 mp4文件
【音视频 ffmpeg 学习】 RTMP推流 mp4文件
|
Windows
WINDOWS编译ffmpeg:LINK : fatal error LNK1104: 无法打开文件“LIBCMT.lib”
WINDOWS编译ffmpeg:LINK : fatal error LNK1104: 无法打开文件“LIBCMT.lib”
355 0
|
编解码 C#
使用ffmpeg将裸码文件转成wav文件
使用ffmpeg将裸码文件转成wav文件
使用ffmpeg将裸码文件转成wav文件
|
网络协议 API 开发者
FFmpeg打开输入文件
本文介绍如何使用 FFmpeg 的 API 函数 avformat_open_input,avformat_find_stream_info 来打开跟获取一个输入文件的信息 (AVFormatContext )。
148 0
编译ffmpeg:libavdevice/xcbgrab.c:28:10: fatal error: xcb/xfixes.h: 没有那个文件或目录
编译ffmpeg:libavdevice/xcbgrab.c:28:10: fatal error: xcb/xfixes.h: 没有那个文件或目录
42 0
|
Ubuntu 编译器 开发工具
Ubuntu编译ffmpeg需要下载的文件
Ubuntu编译ffmpeg需要下载的文件
115 0
|
编解码 数据处理 vr&ar
|
编解码 vr&ar 内存技术
FFmpeg中的音频文件的封装格式和编码格式
FFmpeg对于音频文件的封装和编码是非常简单的,欢迎大家深入使用
|
存储 编解码 Android开发
【Android FFMPEG 开发】FFMPEG 解码 AVPacket 数据到 AVFrame ( AVPacket->解码器 | 初始化 AVFrame | 解码为 AVFrame 数据 )
【Android FFMPEG 开发】FFMPEG 解码 AVPacket 数据到 AVFrame ( AVPacket->解码器 | 初始化 AVFrame | 解码为 AVFrame 数据 )
260 0
|
存储 编解码 Android开发
【Android FFMPEG 开发】FFMPEG 读取音视频流中的数据到 AVPacket ( 初始化 AVPacket 数据 | 读取 AVPacket )
【Android FFMPEG 开发】FFMPEG 读取音视频流中的数据到 AVPacket ( 初始化 AVPacket 数据 | 读取 AVPacket )
210 0