文章目录
前言
本篇,作者将分享如何在QT环境下,使用FFmpeg函数库解码本地视频(中篇)—— 解码过程所调用的各个函数作用。
一、FFmpeg解码流程
- 下图为解码流程图,黄色部分为解码所调用函数,绿色部分为解码所需要的参数(结构体)。
二、解码所需函数及其作用
1.av_register_all 函数
- 作用:注册复用器、解码器,与该函数类似的还有
设备注册函数
和网络注册函数
。
//环境注册
av_register_all(); //复用器、编码器等注册
avdevice_register_all(); //进行设备注册
avformat_network_init(); //进行网络注册
2.avformat_open_input 函数
- 作用:打开多媒体文件,函数定义如下。
/*
函数参数信息如下:
ps:函数调用成功之后处理过的AVFormatContext结构体。
url:输入多媒体文件的名称,如startMovie.mp4,该多媒体文件必须放在工程文件当前目录下。
fmt:强制指定AVFormatContext中AVInputFormat的。一般情况下为NULL,这样FFmpeg可以自动检测AVInputFormat。
dictionay:附加的一些选项,一般情况下为NULL。
*/
int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options);
- 使用实例, 函数执行成功的话,其返回值大于等于0;否则使用av_strerror函数打印错误信息。
int avformat_open_ret = avformat_open_input(&this->formatContext,filename.toLatin1(),NULL,NULL);
if(avformat_open_ret < 0)
{
char *result = new char[64];
av_strerror(avformat_open_ret,result,64);
qDebug() << QString("错误信息:%1").arg(result);
}
qDebug() << "打开多媒体文件成功!";
3.avformat_find_stream_info 函数
- 作用:获取音视频码流信息,函数定义如下。
/*
函数参数信息如下:
ic:输入的AVFormatContext。
options:额外的选项,可设置为NULL。
*/
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);
- 使用实例, 函数执行成功的话,其返回值大于等于0;否则使用av_strerror函数打印错误信息。
int avformat_find_ret = avformat_find_stream_info(this->formatContext,NULL);
if(avformat_find_ret < 0)
{
char *result = new char[64];
av_strerror(avformat_open_ret,result,64);
qDebug() << QString("错误信息:%1").arg(result);
}
qDebug() << "获取音视频流信息成功!";
4.avcodec_find_decoder 函数
- 作用:查找FFmpeg内适合多媒体文件的解码器,函数定义如下。
//函数的参数是一个解码器的ID,返回查找到的解码器(没有找到就返回NULL)。
AVCodec *avcodec_find_decoder(enum AVCodecID id);
- 解码器ID通过遍历音视频流信息获取,如下所示。
int streamIndex = -1;
//nb_streams:音视频流的个数
for(int i=0;i<this->formatContext->nb_streams;i++)
{
//若流的类型为视频流,保存该视频流的索引
if(this->formatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
streamIndex = i;
break;
}
}
if(this->streamIndex == -1)
{
qDebug() << "找不到相应的流信息!";
}
解码器ID:this->formatContext->streams[this->streamIndex]->codec->codec_id
- avcodec_find_decoder 函数使用实例如下。
//获取编解码器上下文
AVCodecContext *codecContext = this->formatContext->streams[this->streamIndex]->codec;
//查找合适的解码器
AVCodec *codec = avcodec_find_decoder(this->codecContext->codec_id);
5.avcodec_open2 函数
- 作用:打开找到的解码器,若省略该步骤,在进行读取音视频帧时将会造成程序崩溃。
/*
函数参数信息如下:
avctx:初始化的AVCodecContext。
codec:输入的AVCodec。
options:一些选项,可设置为NULL。
*/
int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);
- 使用实例, 函数执行成功的话,其返回值大于等于0;否则使用av_strerror函数打印错误信息。
//通过编解码器上下文打开解码器
int avcodec_open_ret = avcodec_open2(this->codecContext,this->codec,NULL);
if(avcodec_open_ret < 0)
{
char *result = new char[64];
av_strerror(avformat_open_ret,result,64);
qDebug() << QString("错误信息:%1").arg(result);
}
qDebug() << "打开解码器成功!";
6.av_read_frame 函数
- 作用:读取音视频帧,函数定义如下。
/*
函数参数信息如下:
s:输入的AVFormatContext。
pkt:输出的AVPacket。
*/
int av_read_frame(AVFormatContext *s, AVPacket *pkt);
- 使用实例,通过while循环不断调用该函数,将音视频帧读取到数据包中。
while(av_read_frame(this->formatContext,this->packet) >= 0){}
7.avcodec_send_packet 函数
- 作用:将数据包发送到编解码器上下文,函数定义如下。
/*
函数参数信息如下:
avctx:输出的AVCodecContext。
avpkt:输入的AVPacket。
*/
int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt);
- 使用实例,如下所示。
avcodec_send_packet(this->codecContext,this->packet);
8.decode_video_ret 函数
- 作用:从编解码器上下文中读取帧数据到AVFrame,函数定义如下。
/*
函数参数信息如下:
avctx:输入的AVCodecContext。
frame:输出的AVFrame。
*/
int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame);
- 使用实例,函数执行成功,其返回值大于等于0。
int decode_video_ret = avcodec_receive_frame(this->codecContext,this->frame);
三、FFmpeg参考资料
版权声明:本文部分内容,参考CSDN博主「雷霄骅」原创文章整理而成,供学习参考使用。
博客地址:https://blog.csdn.net/leixiaohua1020?type=blog。
总结
以上就是浅显易懂 FFmpeg学习(03)— QT+FFmpeg解码本地视频(中篇)的所有内容,希望大家阅读后都能有所收获!原创不易,转载请标明出处,若文章出现有误之处,欢迎读者留言指正批评!