浅显易懂 FFmpeg学习(03)— QT+FFmpeg解码本地视频(中篇)


前言

  本篇,作者将分享如何在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解码本地视频(中篇)的所有内容,希望大家阅读后都能有所收获!原创不易,转载请标明出处,若文章出现有误之处,欢迎读者留言指正批评!

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_59134387/article/details/127218469