Qt 开源音视频框架模块QtAV01:介绍编译以及简单使用
Posted jbyyy、
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Qt 开源音视频框架模块QtAV01:介绍编译以及简单使用相关的知识,希望对你有一定的参考价值。
介绍
QtAV 是一个基于 Qt 和 FFmpeg 的跨平台、高性能多媒体播放框架,能够帮助你轻而易举地编写出一个播放器。
为什么选择 QtAV 而非 QtMultimedia?
QtMultimedia 无法支持 Qt4。QtAV 同时支持 Qt4 和 Qt5
QtMultimedia’s 的实现依赖与平台,比如 Windows 上使用 DShow, Linux 上使用 gstreamer等。移植新平台比较困难。 而 QtAV 使用 FFmpeg, 支持绝大部分平台,无需额外的工作。
QtMultimedia 可能需要额外的解码器才能正常工作
如果嫌麻烦不想编译 可以直接下载我这边已经编译好的QTAV依赖库
MSVC和WINGW版本都有
测试DEMO 根据使用方法使用就行
QtAV的编译
官网地址:http://www.qtav.org/
Github 地址:https://github.com/wang-bin/QtAV
编译 QtAV:https://github.com/wang-bin/QtAV/wiki/Build-QtAV
在项目中使用 QtAV:https://github.com/wang-bin/QtAV/wiki/Use-QtAV-In-Your-Projects
前期准备
以 Windows 平台为例
1.下载QTAV源码
2.下载依赖 QtAV-depends-windows-x86+x64.7z
解压缩之后,里面有构建时需要用到的头文件和库,分别存储在 include、lib、bin 目录下。 ps:这里面是QTAV依赖的FFMEPEG第三方库
3.将QTAV源码和QtAV-depends-windows-x86+x64解压在同一个根目录下
编译安装
1.编辑 QtAV 源码目录中的 .qmake.conf文件,在其中添加以下 2 行内容:
INCLUDEPATH += $$PWD/../QtAV-depends-windows-x86+x64/include
#这里我们要注意 如果我们编译器是64位的 填以下路径
#LIBS += -L$$PWD/../QtAV-depends-windows-x86+x64/lib/x64
#这里我们要注意 如果我们编译器是32位的 填以下路径
LIBS += -L$$PWD/../QtAV-depends-windows-x86+x64/lib
#注意:这里我引用的是相对路径,$$PWD/../ 表示当前路径的上一层目录。
2.打开 QtAV.pro,选择编译器版本,执行 qmake -> 构建。完成之后,会生成相应的库文件和程序:
以Qt5.9.7MSVC2015-64bit版本 debug方式构建为例,文件夹lib_win_x86_64 目录包含的 .lib 和 .dll 库文件就是我们需要的编译好的QTAV第三方库。
配置环境以及简单使用
方法一直接使用
1.将ffmpeg第三方库QtAV-depends-windows-x86+x64,QTAV源码中的QtAV、QtAVWidgets文件夹移到新建的include文件夹中,以及文件夹中lib_win_x86_64的.lib和.dll放到同一个文件夹内进行统一管理,如图。
QtAV、QtAVWidget 头文件文件夹所在源码路径为
源码根文件\\src\\ -----》QtAV
源码根文件\\widgets\\ -------》 QtAVWidgets
2.新建QT空项目(编译器版本和我们上面构建QTAV是的编译器版本相同)并将步骤1中创建的QTAV文件夹放到新建项目的根文件目录中
2.在我们新建的项目的pro文件中添加外部库
INCLUDEPATH += $$PWD/QTAV/include
INCLUDEPATH += $$PWD/QTAV/include/QtAV
INCLUDEPATH += $$PWD/QTAV/include/QtAV/5.9.7/QtAV/private
INCLUDEPATH += $$PWD/QTAV/include/QtAV/private
INCLUDEPATH += $$PWD/QTAV/include/QtAVWidgets
win32:CONFIG(release, debug|release): LIBS += -L$$PWD/QTAV/lib_win_x86_64/ -lcommon
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/QTAV/lib_win_x86_64/ -lcommond
win32:CONFIG(release, debug|release): LIBS += -L$$PWD/QTAV/lib_win_x86_64/ -lQmlAV
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/QTAV/lib_win_x86_64/ -lQmlAVd
win32:CONFIG(release, debug|release): LIBS += -L$$PWD/QTAV/lib_win_x86_64/ -lQtAV1
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/QTAV/lib_win_x86_64/ -lQtAVd1
win32:CONFIG(release, debug|release): LIBS += -L$$PWD/QTAV/lib_win_x86_64/ -lQtAVWidgets1
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/QTAV/lib_win_x86_64/ -lQtAVWidgetsd1
3.1. 复制lib_win_x86_64文件夹内的所有文件 到编译后生成的构造目录中
3.2.如果是32位编译器 将QTAV\\QtAV-depends-windows-x86+x64\\bin 的文件 复制到编译后生成的构造目录中
3.3如果是64位编译器 将QTAV\\QtAV-depends-windows-x86+x64\\bin\\x64 的文件 复制到编译后生成的构造目录中
4.程序编写并运行
#include "mainwindow.h"
#include <QApplication>
#include <QtAV>
#include <QtAVWidgets>
using namespace QtAV;
int main(int argc, char *argv[])
QApplication a(argc, argv);
MainWindow w;
VideoOutput *m_vo;
AVPlayer *m_player;
m_player = new AVPlayer(&w);
m_vo = new VideoOutput(&w);
m_player->setRenderer(m_vo);
m_player->play("C:/Users/jbyyy/Desktop/work/jbywork/opencv200/OPENCV/test2.mp4");
w.setCentralWidget(m_vo->widget());
w.show();
return a.exec();
方法二 将QTAV作为模块加入到QT中
可以参考其他博主:https://blog.csdn.net/lxw88586390/article/details/107058013/
只需要在pro文件中 添加avwidgets模块就能正常使用
下面以Qt5.9.7MSVC2015-64bit debug版本演示
1.找到我们刚才使用 MSVC2015-64bit debug编译好的构造目录,并双击skd_install.bat 该脚本会自动拷贝编译完成的文件到qt文件夹内(包含.dll,.lib和.h有兴趣的可以用记事本打开看下里面的脚本内容)
2.将QTAV依赖的FFMEPEG库也放到QT安装目录下否则会导致程序运行异常报错
2.1将QtAV-depends-windows-x86+x64的include的文件夹都复制到 5.9.7\\msvc2015_64\\include 文件夹中
2.2将QtAV-depends-windows-x86+x64的lib/x64的文件都复制到 5.9.7\\msvc2015_64\\lib文件夹中
2.3将QtAV-depends-windows-x86+x64的bin/x64的文件都复制到 5.9.7\\msvc2015_64\\bin文件夹中
【Qt 开源音视频框架模块QtAV】01:介绍、编译以及简单使用
【Qt 开源音视频框架模块QtAV】02:QTAV自带的DEMO
【Qt 开源音视频框架模块QtAV】03:QTAV主要接口展示以及播放器源码分享
QT软件开发:基于QtAV设计的视频播放器
一、环境介绍
操作系统: win10 64位
QT版本: QT5.12.6
编译器: MinGW 32
QtAV版本: QtAV-1.12.0
FFMPEG版本: ffmpeg 3.1 使用的是QtAV提供的包,直接使用
完整源码下载: https://download.csdn.net/download/xiaolong1126626497/19759245
二、编译QTAV模块
参考链接: https://blog.csdn.net/xiaolong1126626497/article/details/112209279
三、开发的视频播放器效果
完整播放器下载地址: https://download.csdn.net/download/xiaolong1126626497/19759245
四、功能介绍
1. 支持命令行传入视频播放
2. 支持图像旋转播放
3. 支持查看媒体信息
4. 支持选择GPU加速解码
5. 支持快进、快退
6. 支持预览画面(鼠标放在进度条上查看画面缩略图)
7. 支持单帧播放,就是一帧一帧的点击切换画面
8. 支持画面拍照、截图
9. 支持复位到视频首页
10. 支持音量调整
11. 支持拖拽文件到窗口播放
12. 默认打开视频不会自动播放。 自动显示在第一帧,视频放完停留在最后一帧。
13. 支持视频列表
五、示例代码
5.1 整体工程
5.2 widget.cpp代码
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QString filename,QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
ui->setupUi(this);
//设置窗口的标题名称
this->setWindowTitle("视频播放器-DS小龙哥");
//加载样式表
SetStyle(":/resource/VideoPlayer.qss");
//读取配置文件
ReadConfig();
//QTAV初始化
QtAV_InitConfig();
//UI界面相关初始化
UI_InitConfig();
setAcceptDrops(true);
//如果构造函数传入的视频文件就直接加载
if(!filename.isEmpty())
load_video_file(0,filename);
Widget::~Widget()
delete ui;
/*
工程: ECRS_VideoPlayer
日期: 2021-02-23
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 加载样式表
*/
void Widget::SetStyle(const QString &qssFile)
QFile file(qssFile);
if (file.open(QFile::ReadOnly))
QByteArray qss=file.readAll();
qApp->setStyleSheet(qss);
file.close();
/*
工程: ECRS_VideoPlayer
日期: 2021-02-23
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: UI界面初始化
*/
void Widget::UI_InitConfig()
//音量滑块范围设置
ui->horizontalSlider_AudioValue->setMaximum(10);
ui->horizontalSlider_AudioValue->setMinimum(0);
//播放速度设置
ui->MediaSpeedBtn->setCheckable(true);
m_TimeSpeedGrp = new QActionGroup(this);
QStringList strSpeedItems;
strSpeedItems << tr("0.03X") << tr("0.05X") << tr("0.1X") << tr("0.5X") << tr("1.0X") << tr("2.0X") << tr("4.0X") << tr("8.0X");
double speeds[] = 0.03, 0.05, 0.1, 0.5, 1.0, 2.0, 4.0, 8.0 ;
for (int i = 0; i < strSpeedItems.size(); i++)
QAction *pSpeedItem = m_SpeedMenu.addAction(strSpeedItems.at(i));
pSpeedItem->setData(QVariant::fromValue(speeds[i]));
pSpeedItem->setCheckable(true);
m_TimeSpeedGrp->addAction(pSpeedItem);
if (i == 4)
pSpeedItem->setChecked(true);
connect(m_TimeSpeedGrp, SIGNAL(triggered(QAction *)), this, SLOT(slot_onSetTimeSpeed(QAction *)));
//图像的旋转方向
m_RotateGrp = new QActionGroup(this);
QStringList strDegrees;
strDegrees << tr("0~") << tr("90~") << tr("180~") << tr("270~");
int Degrees[] = 0, 90, 180, 270 ;
for (int i = 0; i < strDegrees.size(); i++)
QAction *pItem = m_RotateMenu.addAction(strDegrees.at(i));
pItem->setData(QVariant::fromValue(Degrees[i]));
pItem->setCheckable(true);
m_RotateGrp->addAction(pItem);
connect(m_RotateGrp, SIGNAL(triggered(QAction *)), this, SLOT(slot_onMediaRotate(QAction *)));
//截图保存
ui->MediaSnapshotBtn->setCheckable(true);
m_SnapshotGrp = new QActionGroup(this);
QAction *pClipboard = m_SnapshotMenu.addAction(tr("保存到剪切板"));
QAction *pFileDirectory = m_SnapshotMenu.addAction(tr("保存到文件"));
pClipboard->setData(MENU_COPY_CLIPBOARD); //保存到剪切板
pFileDirectory->setData(MENU_SAVE_FILE_SYSTEM); //保存到文件
m_SnapshotGrp->addAction(pClipboard); //添加到分组
m_SnapshotGrp->addAction(pFileDirectory); //添加到分组
connect(m_SnapshotGrp, SIGNAL(triggered(QAction *)), this, SLOT(slot_onMediaSnapshot(QAction *)));
//安装事件监听器 事件筛选器是接收发送到此对象的所有事件的对象
ui->horizontalSlider_PlayPosition->installEventFilter(this);
ui->widget_videoDisplay->installEventFilter(this);
//状态信息初始化
MediaInfo.state=MEDIA_NOLOAD;
//工具提示信息
ui->toolButton_init_load->setToolTip(tr("加载视频,也可以直接将视频文件拖拽到窗口"));
ui->toolButton_load->setToolTip(tr("加载视频,也可以直接将视频文件拖拽到窗口"));
ui->toolButton_media_info->setToolTip(tr("媒体信息"));
ui->MediaPrevBtn->setToolTip(tr("快退"));
ui->MediaPlayBtn->setToolTip(tr("快进"));
ui->MediaPauseBtn->setToolTip(tr("暂停/继续"));
ui->MediaSpeedBtn->setToolTip(tr("倍速选择"));
ui->MediaResetBtn->setToolTip(tr("复位"));
ui->MediaSnapshotBtn->setToolTip(tr("截图"));
ui->MediaRotateBtn->setToolTip(tr("画面旋转"));
ui->ReverseFrameBtn->setToolTip(tr("左一帧"));
ui->ForwardFrameBtn->setToolTip(tr("右一帧"));
ui->VolumeBtn->setToolTip(tr("静音切换"));
ui->checkBox_gpu_set->setToolTip(tr("GPU硬件解码支持(需要重启软件才能生效)"));
//播放进度条滑块初始化
connect(ui->horizontalSlider_PlayPosition, SIGNAL(onLeave()), SLOT(onTimeSliderLeave()));
connect(ui->horizontalSlider_PlayPosition, SIGNAL(onHover(int,int)), SLOT(onTimeSliderHover(int,int)));
connect(ui->horizontalSlider_PlayPosition, SIGNAL(sliderMoved(int)), SLOT(seek(int)));
connect(ui->horizontalSlider_PlayPosition, SIGNAL(sliderPressed()), SLOT(seek()));
this->setMouseTracking(true);
connect(this, SIGNAL(s_pause_state(bool,qint64)),ui->widget_videoDisplay,SLOT(slot_pause_state(bool,qint64)));
connect(this, SIGNAL(s_PlayPosTime(qint64)),ui->widget_videoDisplay,SLOT(slot_PlayPosTime(qint64)));
/*
工程: ECRS_VideoPlayer
日期: 2021-02-23
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: QTAV初始化配置
*/
void Widget::QtAV_InitConfig()
Widgets::registerRenderers();
m_player = new AVPlayer(this);
m_vo=new my_qtav_videoOut;
m_player->setRenderer(m_vo);
//设置间隔时间(ms单位)
m_player->setNotifyInterval(100);
//设置视频在最后一帧停止
m_player->setMediaEndAction(MediaEndAction_Pause);
//播放的进度改变信号
connect(m_player, SIGNAL(positionChanged(qint64)),this, SLOT(updateSliderPosition(qint64)));
//关联播放器的视频帧显示
connect(m_vo, SIGNAL(SendOneFrame(QImage)),ui->widget_videoDisplay,SLOT(slotGetOneFrame(QImage)));
//设置跳转帧类型
m_player->setSeekType(AccurateSeek);
//得到音频输出接口
m_audio=m_player->audio();
//音量设置
m_audio->setVolume(0.5); //0.0 (silence) to 1.0
ui->horizontalSlider_AudioValue->setValue(5);
//显示进度条上的小窗口
m_preview = new VideoPreviewWidget();
//显示媒体信息的对话框
mpStatisticsView=nullptr;
//播放器信号关联
connect(m_player, SIGNAL(started()), this, SLOT(onStartPlay()));
connect(m_player, SIGNAL(stopped()), this, SLOT(onStopPlay()));
connect(m_player, SIGNAL(paused(bool)), this, SLOT(onPaused(bool)));
//判断是否需要设置硬件解码. 设置解码器的顺序
if(ui->checkBox_gpu_set->isChecked())
m_player->setVideoDecoderPriority(QStringList() << "CUDA" << "D3D11" << "DXVA" << "FFmpeg");
qDebug()<<m_player->videoDecoderPriority();
/*
工程: ECRS_VideoPlayer
日期: 2021-02-23
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 更新播放进度
*/
void Widget::updateSliderPosition(qint64 value)
//QMouseEvent event(QEvent::MouseButtonPress, pos, 0, 0, 0);
//QApplication::sendEvent(hWindow, &event);
// int m_unit = m_player->notifyInterval(); //获取更新间隔时间
// qDebug()<<"视频持续时间:"<<int(m_player->duration()/m_unit);
// qDebug()<<"当前进度:"<<int(value/m_unit);
//设置进度条的时间
ui->horizontalSlider_PlayPosition->setValue(int(value));
//通知播放器显示窗体
emit s_PlayPosTime(value);
//设置右上角的时间
//ui->label_Total_Time->setText(QString("%1").arg(int(m_player->duration()/m_unit)));
//ui->label_current_Time->setText(QString("%1").arg(int(value/m_unit)));
ui->label_current_Time->setText(QTime(0, 0, 0).addMSecs(int(value)).toString(QString::fromLatin1("HH:mm:ss")));
ui->label_Total_Time->setText(QTime(0, 0, 0).addMSecs(int(m_player->mediaStopPosition())).toString(QString::fromLatin1("HH:mm:ss")));
/*
工程: ECRS_VideoPlayer
日期: 2021-02-23
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 加载视频文件 flag=0 重新加载文件 flag=1 重新开始播放
QString file_path 这参数可以传入文件名称,因为窗口支持拖放文件进来
返回值: true 成功 false 失败
*/
bool Widget::load_video_file(bool flag,QString file_path)
if(flag==false)
QString filename=file_path;
if(filename.isEmpty())
filename=QFileDialog::getOpenFileName(this,"选择播放的视频","D:/",tr("*.mp4 *.wmv *.*"));
strncpy(video_name,filename.toUtf8().data(),sizeof(video_name));
ui->toolButton_init_load->setVisible(false);
//判断文件是否存在
if(QFileInfo::exists(video_name)==false)
return false;
else
MediaInfo.state=MEDIA_LOAD;
MediaInfo.mediaName=video_name;
//每次加载新文件设置播放进度条为0
ui->horizontalSlider_PlayPosition->setValue(0);
qDebug()<<"停止原视频";
//停止播放
m_player->stop();
//播放视频
m_player->play(video_name);
qDebug()<<"当期播放视频:"<<video_name;
//设置当前播放的视频名称
QFileInfo info(video_name);
ui->label_FileName->setText(QString("%1").arg(info.fileName()));
return true;
/*
工程: ECRS_VideoPlayer
日期: 2021-02-23
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 加载视频文件
*/
void Widget::on_toolButton_load_clicked()
qDebug()<<"加载视频文件状态:"<<load_video_file(0,"");
void Widget::on_toolButton_init_load_clicked()
load_video_file(0,"");
/*
工程: ECRS_VideoPlayer
日期: 2021-02-23
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 暂停播放
*/
void Widget::on_MediaPauseBtn_clicked()
if (!m_player->isPlaying())
//通知播放器
s_pause_state(true,ui->horizontalSlider_PlayPosition->value());
m_player->play();
return;
m_player->pause(!m_player->isPaused());
/*
工程: ECRS_VideoPlayer
日期: 2021-02-23
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 重新开始播放
*/
void Widget::on_MediaResetBtn_clicked()
//加重新开始播放
load_video_file(true,"");
/*
工程: ECRS_VideoPlayer
日期: 2021-02-23
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 快退播放
*/
void Widget::on_MediaPrevBtn_clicked()
// //得到播放进度的当前位置
// int value=ui->horizontalSlider_PlayPosition->value();
// int m_unit = m_player->notifyInterval(); //获取更新间隔时间
// //设置每次点击快退的距离
// m_player->seek(qint64(value*m_unit)-10*m_unit);
m_player->seekBackward();
/*
工程: ECRS_VideoPlayer
日期: 2021-02-23
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 快进播放
*/
void Widget::on_MediaPlayBtn_clicked()
// //得到播放进度的当前位置
// int value=ui->horizontalSlider_PlayPosition->value();
// int m_unit = m_player->notifyInterval(); //获取更新间隔时间
// //设置每次点击快进的距离
// m_player->seek(qint64(value*m_unit)+10*m_unit);
m_player->seekForward();
/*
工程: ECRS_VideoPlayer
日期: 2021-02-23
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 向左一帧
*/
void Widget::on_ReverseFrameBtn_clicked()
//得到播放进度的当前位置
int value=ui->horizontalSlider_PlayPosition->value();
int m_unit = m_player->notifyInterval(); //获取更新间隔时间
//设置每次点击快退的距离
m_player->seek(qint64(value-m_unit));
/*
工程: ECRS_VideoPlayer
日期: 2021-02-23
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 向右一帧
*/
void Widget::on_ForwardFrameBtn_clicked()
//得到播放进度的当前位置
int value=ui->horizontalSlider_PlayPosition->value();
int m_unit = m_player->notifyInterval(); //获取更新间隔时间
m_player->seek(qint64(value+m_unit));
/*
工程: ECRS_VideoPlayer
日期: 2021-02-23
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 音量设置
*/
void Widget::on_VolumeBtn_clicked()
//得到音频输出接口
AudioOutput *ao=m_player->audio();
bool checked=ui->VolumeBtn->isChecked();
if(checked)
//静音
//音量设置
ao->setVolume(0.0); //0.0 (silence) to 1.
else
//设置正常音量
qreal volume_val=ui->horizontalSlider_AudioValue->value();
//音量设置
ao->setVolume(volume_val/10.0); //0.0 (silence) to 1.
/*
工程: ECRS_VideoPlayer
日期: 2021-02-23
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 音量设置
*/
void Widget::on_horizontalSlider_AudioValue_valueChanged(int value)
//得到音频输出接口
AudioOutput *ao=m_player->audio();
//音量设置
ao->setVolume(value/10.0); //0.0 (silence) to 1.
/*
工程: ECRS_VideoPlayer
日期: 2021-02-23
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 播放速度设置菜单选择
*/
void Widget::slot_onSetTimeSpeed(QAction *action)
action->setChecked(true);
ui->MediaSpeedBtn->setToolTip(action->text());
ui->MediaSpeedBtn->setText(action->text());
//设置速度 正常速度是1.0
m_player->setSpeed(qreal(action->data().toFloat()));
/*
工程: ECRS_VideoPlayer
日期: 2021-02-23
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 点击了速度设置按钮
*/
void Widget::on_MediaSpeedBtn_clicked()
QPoint ptWgt = ui->MediaSpeedBtn->mapToGlobal(QPoint(0, 0));
ptWgt -= QPoint(10, 180);
QAction *pSelect = m_SpeedMenu.exec(ptWgt);
if (pSelect == nullptr)
return;
/*
工程: ECRS_VideoPlayer
日期: 2021-02-23
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 点击了旋转选择菜单
*/
void Widget::slot_onMediaRotate(QAction *action)
action->setChecked(true);
ui->MediaRotateBtn->setToolTip(action->text());
ui->widget_videoDisplay->Set_Rotate(action->data().toInt());
/*
工程: ECRS_VideoPlayer
日期: 2021-02-23
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 点击了画面旋转菜单
*/
void Widget::on_MediaRotateBtn_clicked()
QPoint ptWgt = ui->MediaRotateBtn->mapToGlobal(QPoint(0, 0));
ptWgt -= QPoint(10, 94);
QAction *pSelect = m_RotateMenu.exec(ptWgt);
if (pSelect == nullptr)
return;
/*
工程: ECRS_VideoPlayer
日期: 2021-02-24
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 点击了截图菜单
*/
void Widget::slot_onMediaSnapshot(QAction *action)
if (action == nullptr)
return;
//得到按下的序号
MENU_ITEM item = MENU_ITEM(action->data().toInt());
QImage Pic=ui->widget_videoDisplay->GetImage();
if (Pic.isNull() || Pic.height() <= 0)return;
//保存到剪切板
if (item == MENU_COPY_CLIPBOARD)
QApplication::clipboard()->setImage(Pic);
//保存到文件
else if (item == MENU_SAVE_FILE_SYSTEM)
QString strFile = QDateTime::currentDateTime().toString("yyyyMMddHHmmss") + ".png";
QString strFileName = QFileDialog::getSaveFileName(nullptr, "保存图片", strFile, "PNG(*.png);;BMP(*.bmp);;JPEG(*.jpg *.jpeg)");
if (!strFileName.isEmpty())
strFileName = QDir::toNativeSeparators(strFileName);
QFileInfo fInfo(strFileName);
Pic.save(strFileName, fInfo.completeSuffix().toStdString().c_str(), 80);
/*
工程: ECRS_VideoPlayer
日期: 2021-02-24
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 点击了截图按钮
*/
void Widget::on_MediaSnapshotBtn_clicked()
QPoint ptWgt = ui->MediaSnapshotBtn->mapToGlobal(QPoint(0, 0));
ptWgt -= QPoint(10, 48);
QAction *pSelect = m_SnapshotMenu.exec(ptWgt);
if (pSelect == nullptr)
return;
/*
工程: ECRS_VideoPlayer
日期: 2021-02-24
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 拦截事件
*/
bool Widget::eventFilter(QObject *obj, QEvent *event)
// //判断是否是视频播放进度条产生了事件,解决QSlider点击不能到鼠标指定位置的问题
// if(obj==ui->horizontalSlider_PlayPosition)
//
// //暂停状态才可以点击进度条进行跳转
// if(m_player->isPaused())
//
// if (event->type()==QEvent::MouseButtonPress) //判断类型
//
// //视频加载成功才能进行下面的操作
// if(MediaInfo.state==MEDIA_LOAD)
//
// QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
// if (mouseEvent->button() == Qt::LeftButton) //判断左键
//
// int value = QStyle::sliderValueFromPosition(ui->horizontalSlider_PlayPosition->minimum(), ui->horizontalSlider_PlayPosition->maximum(), mouseEvent->pos().x(), ui->horizontalSlider_PlayPosition->width());
// ui->horizontalSlider_PlayPosition->setValue(value);
// //跳转帧
// int m_unit = m_player->notifyInterval(); //获取更新间隔时间
// m_player->seek(qint64(value*m_unit));
//
//
//
//
//
//判断是否在视频窗口范围内按下的鼠标
if(obj==ui->widget_videoDisplay)
//视频加载成功才能进行下面的操作
if(MediaInfo.state==MEDIA_LOAD)
//判断是否是鼠标事件
if (event->type()==QEvent::MouseButtonPress)
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
//如果按下的是左键
if(mouseEvent->button() == Qt::LeftButton)
//如果是暂停状态
if(m_player->isPaused())
//继续播放
m_player->pause(false);
//通知播放器
s_pause_state(true,ui->horizontalSlider_PlayPosition->value());
else
//暂停播放
m_player->pause(true);
return QObject::eventFilter(obj,event);
void Widget::on_toolButton_set_clicked()
/*
工程: ECRS_VideoPlayer
日期: 2021-02-24
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 查看媒体信息
*/
void Widget::on_toolButton_media_info_clicked()
if(mpStatisticsView==nullptr)
mpStatisticsView = new StatisticsView(this);
if (m_player)
mpStatisticsView->setStatistics(m_player->statistics());
//设置对话框的大小与父窗口一样大
mpStatisticsView->setGeometry(this->geometry());
mpStatisticsView->show();
void Widget::onTimeSliderHover(int pos, int value)
QPoint gpos = mapToGlobal(ui->horizontalSlider_PlayPosition->pos() + QPoint(pos, 0));
QToolTip::showText(gpos, QTime(0, 0, 0).addMSecs(value).toString(QString::fromLatin1("HH:mm:ss")));
if(ui->widget_videoDisplay->GetImage().height()<=0)
return;
m_preview->setFile(m_player->file());
m_preview->setTimestamp(value);
m_preview->preview();
const int w =ui->widget_videoDisplay->width()/5;
const int h = ui->widget_videoDisplay->height()/5;
m_preview->setWindowFlags(m_preview->windowFlags() |Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint);
m_preview->resize(w, h);
m_preview->move(gpos - QPoint(w/2, h));
m_preview->show();
void Widget::onTimeSliderLeave()
if (m_preview && m_preview->isVisible())
m_preview->hide();
void Widget::seek(int value)
if(ui->widget_videoDisplay->GetImage().height()<=0)
return;
m_player->setSeekType(AccurateSeek);
m_player->seek((qint64)value);
m_preview->setTimestamp(value);
m_preview->preview();
m_preview->setWindowFlags(m_preview->windowFlags() |Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint);
m_preview->resize(ui->widget_videoDisplay->width()/5,ui->widget_videoDisplay->height()/5);
m_preview->show();
void Widget::seek()
seek(ui->horizontalSlider_PlayPosition->value());
void Widget::onPaused(bool p)
if (p)
ui->MediaPauseBtn->setChecked(true);
qDebug("start pausing...");
else
ui->MediaPauseBtn->setChecked(false);
qDebug("stop pausing...");
void Widget::onStartPlay()
if (!m_player)
return;
ui->horizontalSlider_PlayPosition->setMinimum(int(m_player->mediaStartPosition()));
ui->horizontalSlider_PlayPosition->setMaximum(int(m_player->mediaStopPosition()));
//视频第一次加载只显示第一帧画面
//暂停播放
m_player->pause(true);
//偏移到第一帧
int m_unit = m_player->notifyInterval(); //获取更新间隔时间
m_player->seek(qint64(m_unit));
qDebug()<<"开始播放";
void Widget::onStopPlay()
if (m_preview)
m_preview->setFile(QString());
void Widget::dragEnterEvent(QDragEnterEvent *e)
if (e->mimeData()->hasUrls())
e->acceptProposedAction();
void Widget::dropEvent(QDropEvent *e)
foreach (const QUrl &url, e->mimeData()->urls())
QString fileName = url.toLocalFile();
qDebug() << "拖入的文件名称:" << fileName;
//加载视频文件
load_video_file(false,fileName);
/*
工程: ECRS_VideoPlayer
日期: 2021-02-24
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 保存配置
*/
void Widget::SaveConfig()
//从UI界面获取用户的个性化配置参数
bool val=ui->checkBox_gpu_set->isChecked();
/*保存数据到文件,方便下次加载*/
QString text;
text=QCoreApplication::applicationDirPath()+"/"+ConfigFile;
QFile filesrc(text);
filesrc.open(QIODevice::WriteOnly);
QDataStream out(&filesrc);
out << val; //序列化
filesrc.flush();
filesrc.close();
/*
工程: ECRS_VideoPlayer
日期: 2021-02-24
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 读取配置
*/
void Widget::ReadConfig()
//读取配置文件
QString text;
text=QCoreApplication::applicationDirPath()+"/"+ConfigFile;
bool val;
//判断文件是否存在
if(QFile::exists(text))
QFile filenew(text);
filenew.open(QIODevice::ReadOnly);
QDataStream in(&filenew); // 从文件读取序列化数据
in >> val; //提取写入的数据
filenew.close();
//设置界面值
ui->checkBox_gpu_set->setChecked(val);
/*
工程: ECRS_VideoPlayer
日期: 2021-02-24
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: GPU支持选择
*/
void Widget::on_checkBox_gpu_set_clicked(bool checked)
SaveConfig();
下面公众号里有全套的单片机、C语言、C++、Python、Linux、QT等基础教程,欢迎关注。
以上是关于Qt 开源音视频框架模块QtAV01:介绍编译以及简单使用的主要内容,如果未能解决你的问题,请参考以下文章