这篇文章主要为大家展示了“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替换为udp av_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内核”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。