qt+ffmpeg 实现音视频播放(三)之视频播放

一、视频播放流程

(PS:视频的播放流程跟音频的及其相似!!)

1、打开视频文件

通过 avformat_open_input() 打开媒体文件并分配和初始化

AVFormatContext 结构体。

函数原型如下:

int avformat_open_input(AVFormatContext **ps, const char *url,

AVInputFormat *fmt, AVDictionary **options);

参数说明:

  • `ps`:指向 `AVFormatContext` 结构体指针的指针,用于存储打

开的媒体文件的信息。

  • `url`:要打开的媒体文件的 URL 或文件路径。

  • `fmt`:指定输入格式,通常可以设置为 `NULL`,由 FFmpeg 根

据文件内容自动检测。

  • `options`:附加选项,可以传入一些额外的选项参数。

2、查找输入流信息

调用 avformat_find_stream_info() 函数将会读取媒体文件中的

帧,解析它们的头部,

并填充 AVFormatContext 中的流信息,通过访问

AVFormatContext 的 streams 字段来获取每个流的详细信息。

函数原型如下:

int avformat_find_stream_info(AVFormatContext *ic,

AVDictionary **options);

参数说明:

  • `ic`:指向已打开媒体文件的 `AVFormatContext` 结构体的指

针。

  • `options`:指向包含附加选项的 `AVDictionary` 指针。

3、查找流索引

使用 av_find_best_stream() 从媒体文件中找到最佳的流索引

函数原型如下:

int av_find_best_stream(AVFormatContext *ic, enum

AVMediaType type, int wanted_stream, int related_stream,

AVCodec **decoder_ret, int flags);

参数说明:

  • `ic`:指向已打开媒体文件的 `AVFormatContext` 结构体的指

针。

  • `type`:要查找的流类型,可以是 `AVMEDIA_TYPE_VIDEO`、

`AVMEDIA_TYPE_AUDIO` 等。

  • `wanted_stream`:期望的流索引,如果为负值,则表示没有特

定的偏好。

  • `related_stream`:相关流索引,用于查找与之相关的最佳流。

  • `decoder_ret`:用于返回找到的解码器。

  • `flags`:附加标志,可以用来指定额外的查找选项。

4、查找解码器

使用 avcodec_find_decoder() 查找符合指定解码器名称的解码

器。

函数原型如下:

AVCodec *avcodec_find_decoder(enum AVCodecID id);

参数说明:

  • `id`:要查找的解码器的 ID。

5、初始化解码上下文

调用 avcodec_alloc_context3() 函数会为特定的编解码器分配一

个 AVCodecContext 结构体,并对其进行初始化。

AVCodecContext 结构体包含了编解码器的相关参数和状态信

息,比如编解码器类型、解码参数、帧率等。

函数原型如下:

AVCodecContext *avcodec_alloc_context3(const AVCodec

*codec);

参数说明:

  • `codec`:指定要使用的编解码器,可以通过

`avcodec_find_decoder()` 或其他方式获取。

6、获取解码参数

调用 `avcodec_parameters_to_context()` 函数可以方便地将

`AVCodecParameters` 结构体中的参数(如编解码器类型、帧

率、分辨率等)复制到 `AVCodecContext` 结构体中,从而准备

进行编解码操作。

函数原型如下:

int avcodec_parameters_to_context(AVCodecContext *codec,

const AVCodecParameters *par);

参数说明:

  • `codec`:要填充参数的 `AVCodecContext` 结构体指针。

  • `par`:包含编解码器参数的 `AVCodecParameters` 结构体指

针。

7、打开解码器

调用 `avcodec_open2()` 函数可以打开并初始化指定的编解码器

上下文,使其准备好进行编解码操作。

函数原型如下:

int avcodec_open2(AVCodecContext *avctx, const AVCodec

*codec, AVDictionary **options);

参数说明:

  • `avctx`:要打开和初始化的编解码器上下文。

  • `codec`:要使用的编解码器,可以通过

`avcodec_find_decoder()` 或其他方式获取。

  • `options`:可选的字典参数,用于设置编解码器的选项。

8、获取图像转换上下文

通过调用`sws_getContext`函数获取一个用于执行图像转换的上

下文对象,然后可以使用该上下文对象来进行图像转换操作。

函数原型如下:

struct SwsContext *sws_getContext(int srcW, int srcH, enum AVPixelFormat srcFormat,

int dstW, int dstH, enum AVPixelFormat dstFormat,

int flags, SwsFilter *srcFilter, SwsFilter *dstFilter, const double *param);

参数说明:

  • `srcW`: 源图像的宽度

  • `srcH`: 源图像的高度

  • `srcFormat`: 源图像的像素格式

  • `dstW`: 目标图像的宽度

  • `dstH`: 目标图像的高度

  • `dstFormat`: 目标图像的像素格式

  • `flags`: 可以指定一些转换的选项

  • `srcFilter`: 源图像滤镜

  • `dstFilter`: 目标图像滤镜

  • `param`: 一组额外的参数

9、读取视频源文件

调用 `av_read_frame()` 函数可以从输入文件或流中读取一帧音视

频数据,并将其存储在 AVPacket 结构体中。

函数原型如下:

int av_read_frame(AVFormatContext *s, AVPacket *pkt);

参数说明:

  • `s`:输入文件或流的 AVFormatContext 上下文。

  • `pkt`:存储读取到的音视频帧数据的 AVPacket 结构体。

12、发送音频数据到解码器

调用 `avcodec_send_packet()` 函数可以将 AVPacket 数据包发送

给解码器进行解码。在发送完所有数据包后,需要调用

`avcodec_send_packet()` 传递一个空的 AVPacket 指针,以便告

知解码器已经发送完所有数据。

函数原型如下:

int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt);

参数说明:

  • `avctx`:指向 AVCodecContext 结构体的指针,表示解码器上下文。

  • `avpkt`:指向要发送给解码器的 AVPacket 数据包的指针。

13、从解码器接收解码后的视频数据

调用 `avcodec_receive_frame()` 函数可以从解码器中接收解码后

的音视频帧数据,并将其存储在 AVFrame 结构体中。

函数原型如下:

int avcodec_receive_frame(AVCodecContext *avctx, AVFrame

*frame);

参数说明:

  • `avctx`:指向 AVCodecContext 结构体的指针,表示解码器上

下文。

  • `frame`:用于存储接收到的解码后的 AVFrame 帧数据的结构体。

14、分配图像数据缓冲区

通过调用`av_image_alloc`函数为图像数据分配内存,并

将分配的内存绑定到指定的指针数组和行大小数组中,以便后续

在这些内存区域中存储图像数据。

函数原型如下所示:

int av_image_alloc(uint8_t *pointers[4], int linesizes[4], int w, int h, enum AVPixelFormat pix_fmt, int align);

参数解释:

  • `pointers`: 用于存储图像数据的指针数组

  • `linesizes`: 每个图像数据平面的行大小

  • `w`: 图像宽度

  • `h`: 图像高度

  • `pix_fmt`: 像素格式

  • `align`: 内存对齐参数

15、执行图像转换和缩放操作

通过调用`sws_scale`函数,可以使用提供的SwcContext对象和输入图像数据,对图像进行转换和缩放操作,然后将结果存储到输出图像数据中。

函数原型如下所示:

int sws_scale(struct SwsContext *c, const uint8_t *const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t *const dst[], const int dstStride[]);

参数解释:

  • `c`: SwsContext对象,用于存储图像转换相关信息

  • `srcSlice`: 指向输入图像数据的指针数组

  • `srcStride`: 输入图像每个平面的跨度(stride)

  • `srcSliceY`: 输入图像的起始行

  • `srcSliceH`: 输入图像的高度

  • `dst`: 指向输出图像数据的指针数组

  • `dstStride`: 输出图像每个平面的跨度(stride)

16、显示图像

直接显示执行 sws_scale 后的图像便可。

二、代码例程

音頻播放:点击跳转

視頻播放:点击跳转

觉得有帮助的话,打赏一下呗。。

相关推荐
Mr.Q2 小时前
OpenCV和Qt坐标系不一致问题
qt·opencv
lxkj_20243 小时前
使用线程局部存储解决ffmpeg中多实例调用下自定义日志回调问题
ffmpeg
重生之我是数学王子5 小时前
QT基础 编码问题 定时器 事件 绘图事件 keyPressEvent QT5.12.3环境 C++实现
开发语言·c++·qt
简鹿办公6 小时前
如何提取某站 MV 视频中的音乐为 MP3 音频
音视频·简鹿视频格式转换器·视频提取mp3音频
yufengxinpian6 小时前
集成了高性能ARM Cortex-M0+处理器的一款SimpleLink 2.4 GHz无线模块-RF-BM-2340B1
单片机·嵌入式硬件·音视频·智能硬件
runing_an_min8 小时前
ffmpeg视频滤镜:替换部分帧-freezeframes
ffmpeg·音视频·freezeframes
ruizhenggang8 小时前
ffmpeg本地编译不容易发现的问题 — Error:xxxxx not found!
ffmpeg
runing_an_min10 小时前
ffmpeg视频滤镜:提取缩略图-framestep
ffmpeg·音视频·framestep
小曲曲11 小时前
接口上传视频和oss直传视频到阿里云组件
javascript·阿里云·音视频
安静读书13 小时前
Python解析视频FPS(帧率)、分辨率信息
python·opencv·音视频