千家信息网

Qt如何实现视频流播放ffmpeg内核

发表于:2024-10-01 作者:千家信息网编辑
千家信息网最后更新 2024年10月01日,这篇文章主要为大家展示了"Qt如何实现视频流播放ffmpeg内核",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"Qt如何实现视频流播放ffmpeg内核"这篇
千家信息网最后更新 2024年10月01日Qt如何实现视频流播放ffmpeg内核

这篇文章主要为大家展示了"Qt如何实现视频流播放ffmpeg内核",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"Qt如何实现视频流播放ffmpeg内核"这篇文章吧。

一、前言

好久以前就写过这个工具,后来因为Qt版本的不断升级以及ffmpeg也经历过好多次的迭代,可能从官网下载的ffmpeg搭配原来的代码不能正确编译,因为很多api已经变了,所以这次特意抽空全部整理重写一遍,只求最精简最好用,同时兼容了ffmpeg3和ffmpeg4,并且同时支持32位的库和64位的库,这样任何小白拿过去直接编译就能用。

二、代码思路

第一步:引入ffmpeg的头文件

//必须加以下内容,否则编译不能通过,为了兼容C和C99标准#ifndef INT64_C#define INT64_C#define UINT64_C#endif//引入ffmpeg头文件extern "C" {#include "libavutil/opt.h"#include "libavutil/time.h"#include "libavutil/frame.h"#include "libavutil/pixdesc.h"#include "libavutil/avassert.h"#include "libavutil/imgutils.h"#include "libavutil/ffversion.h"#include "libavcodec/avcodec.h"#include "libswscale/swscale.h"#include "libavformat/avformat.h"#include "libavfilter/avfilter.h"#ifdef ffmpegdevice#include "libavdevice/avdevice.h"#endif#ifndef gcc45#include "libavutil/hwcontext.h"#include "libavutil/hwcontext_qsv.h"#endif}

第二步:注册ffmpeg的库 这里发现很多人每个类都注册一次,搞得内存每次增加很多,不是不可以,而是没有必要,其实ffmpeg的库和解码器等,在一个程序中只需要注册一次即可,没必要每个视频类都注册一次。

//一个软件中只需要初始化一次就行void FFmpegThread::initlib(){    static QMutex mutex;    QMutexLocker locker(&mutex);    static bool isInit = false;    if (!isInit) {        //注册库中所有可用的文件格式和解码器        av_register_all();        //注册所有设备,主要用于本地摄像机播放支持#ifdef ffmpegdevice        avdevice_register_all();#endif        //初始化网络流格式,使用网络流时必须先执行        avformat_network_init();        isInit = true;        qDebug() << TIMEMS << "init ffmpeg lib ok" << " version:" << FFMPEG_VERSION;#if 0        //输出所有支持的解码器名称        QStringList listCodeName;        AVCodec *code = av_codec_next(NULL);        while (code != NULL) {            listCodeName << code->name;            code = code->next;        }        qDebug() << TIMEMS << listCodeName;#endif    }}

第三步:设置参数

//在打开码流前指定各种参数比如:探测时间/超时时间/最大延时等//设置缓存大小,1080p可将值调大av_dict_set(&options, "buffer_size", "8192000", 0);//以tcp方式打开,如果以udp方式打开将tcp替换为udpav_dict_set(&options, "rtsp_transport", "tcp", 0);//设置超时断开连接时间,单位微秒,3000000表示3秒av_dict_set(&options, "stimeout", "3000000", 0);//设置最大时延,单位微秒,1000000表示1秒av_dict_set(&options, "max_delay", "1000000", 0);//自动开启线程数av_dict_set(&options, "threads", "auto", 0);

第四步:打开视频流 具体代码比较多,详细代码请自行开源主页下载。

第五步:解码图像

void FFmpegThread::run(){    //计时    QTime time;    while (!stopped) {        //根据标志位执行初始化操作        if (isPlay) {            this->init();            isPlay = false;            continue;        }        time.restart();        if (av_read_frame(avFormatContext, avPacket) >= 0) {            //判断当前包是视频还是音频            int packetSize = avPacket->size;            int index = avPacket->stream_index;            if (index == videoStreamIndex) {                //解码视频流                avcodec_decode_video2(videoCodec, avFrame2, &frameFinish, avPacket);                if (frameFinish) {                    //将数据转成一张图片                    sws_scale(swsContext, (const uint8_t *const *)avFrame2->data, avFrame2->linesize, 0, videoHeight, avFrame3->data, avFrame3->linesize);                    //以下两种方法都可以                    //QImage image(avFrame3->data[0], videoWidth, videoHeight, QImage::Format_RGB32);                    QImage image((uchar *)buffer, videoWidth, videoHeight, QImage::Format_RGB32);                    if (!image.isNull()) {                        emit receiveImage(image);                    }                    msleep(1);                }            } else if (index == audioStreamIndex) {                //解码音频流,这里暂不处理,以后交给sdl播放            }        }        av_packet_unref(avPacket);        av_freep(avPacket);        msleep(1);    }    //线程结束后释放资源    free();    stopped = false;    isPlay = false;    qDebug() << TIMEMS << "stop ffmpeg thread";}

三、效果图

以上是"Qt如何实现视频流播放ffmpeg内核"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

0