Qt 通过ffmpeg获取视频预览图(windows下)

2024-06-20 07:38

本文主要是介绍Qt 通过ffmpeg获取视频预览图(windows下),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 一、 搭建ffmpeg开发环境
    • 1. 下载ffmpeg shared库
    • 2. 设置环境变量
  • 二、qtCreator 集成ffmpeg
  • 三、实现视频预览,完整demo如下
    • 在线地址和本地文件均可
    • 刚开始报错 FFmpeg: avcodec_send_packet() -1094995529

一、 搭建ffmpeg开发环境

1. 下载ffmpeg shared库

很早之前用过一段时间的ffmpeg,主要参考的雷神的博客,现在回过头搭建下开发环境,发现都不一样了,这里记录下环境搭建过程。

官网:https://www.ffmpeg.org/
github地址:https://github.com/FFmpeg/FFmpeg

打开官网:
在这里插入图片描述
点击Download,本文选择windows下的 Windows builds from gyan.dev
在这里插入图片描述
然后选择release builds下面的 ffmpeg-release-full-shared.7z下载

在这里插入图片描述
下载完成后,解压拿到下面目录结构文件:
在这里插入图片描述

2. 设置环境变量

然后在电脑->环境变量中加入bin目录
在这里插入图片描述

二、qtCreator 集成ffmpeg

新建工程,在pro文件中加入:

QT       += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
DEFINES += QT_DEPRECATED_WARNINGSSOURCES += \main.cpp \mainwindow.cppHEADERS += \mainwindow.hFORMS += \mainwindow.uiqnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += targetINCLUDEPATH += "C:/Qt/ffmpeg-5.0-full_build-shared/include"
LIBS += -LC:/Qt/ffmpeg-5.0-full_build-shared/lib -lavutil -lavformat -lavcodec -lavfilter -lswscale -lswresample

注意自己的库路径

代码中加入

extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
#include <libswresample/swresample.h>
}

三、实现视频预览,完整demo如下

在线地址和本地文件均可

附上在线测试地址:http://www.w3school.com.cn/example/html5/mov_bbb.mp4
main.cpp

#include "mainwindow.h"#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);MainWindow w;w.show();return a.exec();
}

MainWindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();void createPreviewWidthFile(const char * file);
private:Ui::MainWindow *ui;};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtDebug>
#include <QImage>
#include <QElapsedTimer>
extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
#include <libswresample/swresample.h>
}MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);//本地文件//createPreviewWidthFile("C:/Users/wmm/Desktop/demo/test.mp4");//在线地址QElapsedTimer t;t.start();createPreviewWidthFile("http://www.w3school.com.cn/example/html5/mov_bbb.mp4");qDebug()<< "last = "<< t.elapsed();
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::createPreviewWidthFile(const char *file){AVFormatContext* fmt_ctx_ = nullptr;qDebug() << "111" << avcodec_version();//打开视频文件int errCode = avformat_open_input(&fmt_ctx_, file, nullptr, nullptr);if(errCode != 0){qDebug() << "avformat_open_input fail" << errCode;return;}qDebug() << "222" ;//读取音视频流信息errCode = avformat_find_stream_info(fmt_ctx_, nullptr);if(errCode != 0){qDebug() << "avformat_find_stream_info fail" << errCode;avformat_close_input(&fmt_ctx_);return;}qDebug() << "333" ;//打印输出视频相关信息av_dump_format(fmt_ctx_, 0, file, 0);qDebug() << "444" ;AVPacket* pkt = av_packet_alloc();AVFrame* temp_frame = av_frame_alloc();SwsContext* sws_ctx = nullptr;int ret = 0;QImage preview;bool preview_done = false;int videoStream = 0;for (int i=0; i<int(fmt_ctx_->nb_streams) && !preview_done; i++){//只处理视频信息if (fmt_ctx_->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {//查找视频解码器videoStream = i;const AVCodec* codec = avcodec_find_decoder(fmt_ctx_->streams[i]->codecpar->codec_id);AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);//根据提供的编解码器参数的值填充编解码器上下文avcodec_parameters_to_context(codec_ctx, fmt_ctx_->streams[i]->codecpar);//打开解码器avcodec_open2(codec_ctx, codec, nullptr);qDebug() << "555" ;//读取帧数据while (av_read_frame(fmt_ctx_, pkt) >= 0){if (pkt->stream_index == videoStream) {av_frame_unref(temp_frame);qDebug() << "666" ;//对视频帧数据进行解码while ((ret = avcodec_receive_frame(codec_ctx, temp_frame)) == AVERROR(EAGAIN)){ret = avcodec_send_packet(codec_ctx, pkt);qDebug() << "777" ;if (ret < 0) {qCritical() << "Failed to send packet to decoder." << ret;break;}}if(ret < 0 && ret != AVERROR_EOF){qDebug() << "Failed to receive packet from decoder." << ret;continue;}qDebug() << "777" << temp_frame->width << temp_frame->height;//等比例缩放int dstH = 240;int dstW = qRound(dstH * (float(temp_frame->width)/float(temp_frame->height)));//消除可能的告警dstH = (dstH >> 4) << 4;dstW = (dstW >> 4) << 4;qDebug() << "777" << dstW << dstH;sws_ctx = sws_getContext(temp_frame->width,temp_frame->height,static_cast<AVPixelFormat>(temp_frame->format),dstW,dstH,static_cast<AVPixelFormat>(AV_PIX_FMT_RGBA),SWS_FAST_BILINEAR,nullptr,nullptr,nullptr);int linesize[AV_NUM_DATA_POINTERS];linesize[0] = dstW*4;qDebug() << "888" ;//生成图片preview = QImage(dstW, dstH, QImage::Format_RGBA8888);uint8_t* data = preview.bits();sws_scale(sws_ctx,temp_frame->data,temp_frame->linesize,0,temp_frame->height,&data,linesize);sws_freeContext(sws_ctx);qDebug() << "9999" ;avcodec_close(codec_ctx);avcodec_free_context(&codec_ctx);preview_done = true;break;}}}}qDebug() << "10" ;av_frame_free(&temp_frame);av_packet_free(&pkt);avformat_close_input(&fmt_ctx_);if(preview_done){ui->label->setPixmap(QPixmap::fromImage(preview));}
}

运行效果图如下:
在这里插入图片描述

刚开始报错 FFmpeg: avcodec_send_packet() -1094995529

解决方法
调用 int av_read_frame(AVFormatContext *s, AVPacket *pkt) 函数 时,将会读取一帧数据并填充到AVPacket里面,但是读取的这帧数据可能是视频也可能是音频,也可能是字幕,具体是什么类型可以通过 AVPacket对象的 stream_index 属性来判断,因此在读取完一帧数据后,调用 avcodec_send_packet(inputCodecCtx, inputPacket) 函数将这帧数据发送到解码队列之前,一定要确保这帧数据(AVPacket)的类型与 解码器上下文的类型保持一致!

也就是说你AVPacket中的stream_index对应的是音频流数据,那你在调用avcodec_send_packet()函数时,第二个参数传入的必须是一个音频解码器上下文,只有这样send packet才有可能成功。

这篇关于Qt 通过ffmpeg获取视频预览图(windows下)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1077513

相关文章

问题-windows-VPN不正确关闭导致网页打不开

为什么会发生这类事情呢? 主要原因是关机之前vpn没有关掉导致的。 至于为什么没关掉vpn会导致网页打不开,我猜测是因为vpn建立的链接没被更改。 正确关掉vpn的时候,会把ip链接断掉,如果你不正确关掉,ip链接没有断掉,此时你vpn又是没启动的,没有域名解析,所以就打不开网站。 你可以在打不开网页的时候,把vpn打开,你会发现网络又可以登录了。 方法一 注意:方法一虽然方便,但是可能会有

Windows/macOS/Linux 安装 Redis 和 Redis Desktop Manager 可视化工具

本文所有安装都在macOS High Sierra 10.13.4进行,Windows安装相对容易些,Linux安装与macOS类似,文中会做区分讲解 1. Redis安装 1.下载Redis https://redis.io/download 把下载的源码更名为redis-4.0.9-source,我喜欢跟maven、Tomcat放在一起,就放到/Users/zhan/Documents

Windows中,.net framework 3.5安装

安装.net framework,目前已知2种方法,如下: 一、在MSDN下载对应的安装包,安装,这种可能无法安装成功,概率很大,不成功使用第二种方法,基本上没问题。 二、win8/8.1/10 下安装 .net framework 3.5.1: 1. 打开 win8/8.1/10 安装盘(这里指系统安装镜像文件),提取 sources\sxs 文件夹到 X:\sources\sxs (X代

Windows 可变刷新率是什么?如何开启?

在现代计算设备中,显示屏的刷新率对用户体验起着至关重要的作用。随着显示技术的不断进步,固定刷新率显示器逐渐被支持可变刷新率(Variable Refresh Rate, VRR)技术的显示器所取代。 可变刷新率定义 可变刷新率是什么?可变刷新率(VRR)是一种显示技术,它允许显示器的刷新率动态调整,以匹配显卡输出的帧率。传统的显示器通常具有固定的刷新率(如60Hz、75Hz等),这意味着显示器

百度OCR识别结构结构化处理视频

https://edu.csdn.net/course/detail/10506

如何设置windows计划任务

如何设置windows计划任务 前言:在工作过程中写了一个python脚本,用于调用jira接口查询bug单数量,想要在本地定时任务执行,每天发送到钉钉群提醒,写下操作步骤用于记录。 1. 准备 Python 脚本 确保你的 Python 脚本已经保存到一个文件,比如 jira_reminder.py。 2. 创建批处理文件 为了方便任务计划程序运行 Python 脚本,创建一个批处理文

【青龙面板辅助】JD商品自动给好评获取京豆脚本

1.打开链接 开下面的链接进入待评价商品页面 https://club.jd.com/myJdcomments/myJdcomments.action?sort=0 2.登陆后执行脚本 登陆后,按F12键,选择console,复制粘贴以下代码,先运行脚本1,再运行脚本2 脚本1代码 可以自行修改评价内容。 var content = '材质很好,质量也不错,到货也很快物流满分,包装快递满

QT 中ListView和ListWidget有什么区别

ListView和ListWidget在Qt框架中都是用于显示列表数据的控件,但它们在使用方法和特性上存在一些明显的差异。以下是关于它们用法不一样的地方的详细分析: 数据管理方式: ListView:使用QAbstractItemModel数据模型来管理和显示列表数据。QAbstractItemModel是一个抽象类,允许开发者自定义数据模型以适应特定的数据结构和需求。这使得ListView在处

el-upload 上传图片及回显照片和预览图片,文件流和http线上链接格式操作

<div v-for="(info, index) in zsjzqwhxqList.helicopterTourInfoList" :key="info.id" >编辑上传图片// oss返回线上地址http链接格式:<el-form-itemlabel="巡视结果照片":label-width="formLabelWidth"><el-upload:action="'http:

如何使用Qt的PIMPL习惯用法(PIMPL Idiom

) PIMPL是指“Pointer to IMPLementation”(指向实现的指针),意味着将实现细节隐藏起来,用户类无需关注这些实现细节。在Qt中常用PIMPL习惯用法来清晰地区分接口与实现,尽管Qt官方文档并未详细说明该机制。本文将演示如何在Qt中使用PIMPL习惯用法,并以一个简单的坐标输入对话框作为实例。 原理与动机 PIMPL的核心在于将类的实现细节封装在一个私有类中,这个私