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

相关文章

Qt使用QSqlDatabase连接MySQL实现增删改查功能

《Qt使用QSqlDatabase连接MySQL实现增删改查功能》这篇文章主要为大家详细介绍了Qt如何使用QSqlDatabase连接MySQL实现增删改查功能,文中的示例代码讲解详细,感兴趣的小伙伴... 目录一、创建数据表二、连接mysql数据库三、封装成一个完整的轻量级 ORM 风格类3.1 表结构

Python使用OpenCV实现获取视频时长的小工具

《Python使用OpenCV实现获取视频时长的小工具》在处理视频数据时,获取视频的时长是一项常见且基础的需求,本文将详细介绍如何使用Python和OpenCV获取视频时长,并对每一行代码进行深入解析... 目录一、代码实现二、代码解析1. 导入 OpenCV 库2. 定义获取视频时长的函数3. 打开视频文

Qt QCustomPlot库简介(最新推荐)

《QtQCustomPlot库简介(最新推荐)》QCustomPlot是一款基于Qt的高性能C++绘图库,专为二维数据可视化设计,它具有轻量级、实时处理百万级数据和多图层支持等特点,适用于科学计算、... 目录核心特性概览核心组件解析1.绘图核心 (QCustomPlot类)2.数据容器 (QCPDataC

MySQL 获取字符串长度及注意事项

《MySQL获取字符串长度及注意事项》本文通过实例代码给大家介绍MySQL获取字符串长度及注意事项,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录mysql 获取字符串长度详解 核心长度函数对比⚠️ 六大关键注意事项1. 字符编码决定字节长度2

python3如何找到字典的下标index、获取list中指定元素的位置索引

《python3如何找到字典的下标index、获取list中指定元素的位置索引》:本文主要介绍python3如何找到字典的下标index、获取list中指定元素的位置索引问题,具有很好的参考价值,... 目录enumerate()找到字典的下标 index获取list中指定元素的位置索引总结enumerat

Qt如何实现文本编辑器光标高亮技术

《Qt如何实现文本编辑器光标高亮技术》这篇文章主要为大家详细介绍了Qt如何实现文本编辑器光标高亮技术,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以了解下... 目录实现代码函数作用概述代码详解 + 注释使用 QTextEdit 的高亮技术(重点)总结用到的关键技术点应用场景举例示例优化建议

Qt 设置软件版本信息的实现

《Qt设置软件版本信息的实现》本文介绍了Qt项目中设置版本信息的三种常用方法,包括.pro文件和version.rc配置、CMakeLists.txt与version.h.in结合,具有一定的参考... 目录在运行程序期间设置版本信息可以参考VS在 QT 中设置软件版本信息的几种方法方法一:通过 .pro

Python中对FFmpeg封装开发库FFmpy详解

《Python中对FFmpeg封装开发库FFmpy详解》:本文主要介绍Python中对FFmpeg封装开发库FFmpy,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录一、FFmpy简介与安装1.1 FFmpy概述1.2 安装方法二、FFmpy核心类与方法2.1 FF

基于Python开发Windows屏幕控制工具

《基于Python开发Windows屏幕控制工具》在数字化办公时代,屏幕管理已成为提升工作效率和保护眼睛健康的重要环节,本文将分享一个基于Python和PySide6开发的Windows屏幕控制工具,... 目录概述功能亮点界面展示实现步骤详解1. 环境准备2. 亮度控制模块3. 息屏功能实现4. 息屏时间

SpringMVC高效获取JavaBean对象指南

《SpringMVC高效获取JavaBean对象指南》SpringMVC通过数据绑定自动将请求参数映射到JavaBean,支持表单、URL及JSON数据,需用@ModelAttribute、@Requ... 目录Spring MVC 获取 JavaBean 对象指南核心机制:数据绑定实现步骤1. 定义 Ja