QT软件开发:基于QtAV设计的视频播放器

Posted DS小龙哥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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, &amp;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软件开发:基于QtAV设计的视频播放器的主要内容,如果未能解决你的问题,请参考以下文章

QtAV 播放rtsp视频流

QT5.14.2编译部署QTAV播放器环境

QtAV 播放rtsp视频流

QtAV 播放rtsp视频流

QT软件开发-基于FFMPEG设计视频播放器-解码音频

QT软件开发-基于FFMPEG设计视频播放器-GPU硬解图像