QT应用编程: 基于mdk-sdk开发视频播放器

简介: QT应用编程: 基于mdk-sdk开发视频播放器

一、环境介绍

操作系统: win10 64位


QT版本:  QT5.12.6


编译器:  MinGW 32


二、mdk-sdk 介绍

github 首页地址:  https://github.com/wang-bin/mdk-sdk


Features

Simple and powerful API set

Cross platform: Windows, UWP, Linux, macOS, Android, iOS, Raspberry Pi

Hardware accelerated decoding and 0-copy GPU rendering for all platforms

OpenGL, D3D11, Vulkan and Metal rendering w/ or w/o user provided context

Integrated with any gui toolkits or apps via OpenGL, D3D11, Vulkan and Metal (OBS, Qt, SDL, glfw, SFML etc.) easily

Seamless/Gapless media and bitrate switch for any media

HDR rendering in GPU

Optimized Continuous seeking. As fast as mpv, but much lower cpu, memory and gpu load. Suitable for timeline preview

Smart FFmpeg runtime. See https://github.com/wang-bin/mdk-sdk/wiki/FFmpeg-Runtime

mdk-sdk的API使用介绍:  https://github.com/wang-bin/mdk-sdk/wiki/Player-APIs


mdk-sdk的使用例子(CSDN):  https://download.csdn.net/download/xiaolong1126626497/16273881


mdk-sdk的SDK包(CSDN)--截止当前是最新版本:  https://download.csdn.net/download/xiaolong1126626497/16273875


mdk-sdk的使用例子(GitHub):https://github.com/wang-bin/mdk-examples


三、工程源码

工程源码地址: https://download.csdn.net/download/xiaolong1126626497/16548885


下面播放器例子比较简单,但是完成了播放器基本功能,支持的功能如下:


1.  音量设置


2.  静音切换


3.  拍照(保存在程序运行目录下  png图片)


4. 跳转 (鼠标可以点击播放进度条进行跳转导致指定位置)


5. 播放进度时间


6. 暂停、加载、播放、重新播放


7.  播放的速率设置


完整的播放器实现看这里:https://xiaolong.blog.csdn.net/article/details/117557963


3.1 运行效果

image.png

image.png

3.2  pro工程文件

QT       += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets opengl
CONFIG += c++17 utf8_source
MDK_SDK = $$PWD/mdk-sdk
INCLUDEPATH += $$MDK_SDK/include
MDK_ARCH = x86
LIBS += -L$$MDK_SDK/lib/$$MDK_ARCH -lmdk
LIBS += -L$$MDK_SDK/bin/$$MDK_ARCH
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
    QMDKWidget.cpp \
    main.cpp \
    widget.cpp
HEADERS += \
    QMDKWidget.h \
    widget.h
FORMS += \
    widget.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

3.3 QMDKWidget.cpp

1./*
 * Copyright (c) 2020 WangBin <wbsecg1 at gmail.com>
 * MDK SDK with QOpenGLWidget example
 */
#include "QMDKWidget.h"
#include "mdk/Player.h"
#include <QCoreApplication>
#include <QDebug>
#include <QDir>
#include <QKeyEvent>
#include <QOpenGLContext>
#include <QStringList>
#include <QScreen>
bool av_MediaStatusChanged(mdk::MediaStatus m)
{
    qDebug()<<"av_MediaStatusChanged.";
    return true;
}
bool av_MediaEvent(const mdk::MediaEvent&m)
{
    qDebug()<<"av_MediaEvent.";
    return true;
}
using namespace MDK_NS;
QMDKWidget::QMDKWidget(QWidget *parent, Qt::WindowFlags f)
    : QOpenGLWidget(parent, f)
    , player_(std::make_shared<Player>())
{
    player_->setVideoDecoders({"VT", "VAAPI", "MFT:d3d=11", "DXVA", "MMAL", "AMediaCodec:java=1:copy=0:surface=1:async=0", "FFmpeg"});
    //设置回调: 例如在渲染器中接收到新帧时,将调用该回调
    player_->setRenderCallback([this](void*){
        QMetaObject::invokeMethod(this, "update", Qt::QueuedConnection);
    });
    //设置回调: 事件
    player_->onEvent(av_MediaEvent);
     //获取状态
     //  MediaStatus a=player_->mediaStatus();
    //设置回调: 状态改变
    player_->onMediaStatusChanged(av_MediaStatusChanged);
}
QMDKWidget::~QMDKWidget()
{
    makeCurrent();
    player_->setVideoSurfaceSize(-1, -1); // cleanup gl renderer resources
}
//设置音量  值:> = 0。1.0是原始音量
void QMDKWidget::setVolume(float value)
{
    player_->setVolume(value);
}
//当前进度 当前播放时间(以毫秒为单位)。相对于媒体的第一个时间戳。即mediaInfo().start_time,通常为0。
int64_t QMDKWidget::position()
{
    return player_->position();
}
//总时间
int64_t QMDKWidget::duration()
{
    return player_->mediaInfo().duration;
}
//设置静音
void QMDKWidget::setMute(bool value)
{
    player_->setMute(value);
}
void QMDKWidget::setPlaybackRate(float value)
{
    //设置播放器播放速度  正常速度是1.0
     player_->setPlaybackRate(value);
}
//旋转视频  逆时针0、90、180、270
//player_->rotate(int degree, void* vo_opaque = nullptr);
void QMDKWidget::setrotate(int degree) //设置旋转
{
    player_->rotate(degree);
}
/*
工程: QMDK_Player
日期: 2021-04-08
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 设置解码器
*/
void QMDKWidget::setDecoders(const QStringList &dec)
{
    std::vector<std::string> v;
    foreach (QString d, dec) {
        v.push_back(d.toStdString());
    }
    player_->setVideoDecoders(v);
}
/*
工程: QMDK_Player
日期: 2021-04-08
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 设置媒体文件
*/
void QMDKWidget::setMedia(const QString &url)
{
    player_->setMedia(url.toUtf8().constData());
}
void QMDKWidget::play()
{
    player_->setState(State::Playing);
}
void QMDKWidget::pause()
{
    player_->setState(State::Paused);
}
void QMDKWidget::stop()
{
    player_->setState(State::Stopped);
}
bool QMDKWidget::isPaused() const
{
    return player_->state() == State::Paused;
}
void QMDKWidget::seek(qint64 ms)
{
    player_->seek(ms);
}
void QMDKWidget::snapshot() {
    Player::SnapshotRequest sr{};
    player_->snapshot(&sr, [](Player::SnapshotRequest *_sr, double frameTime) {
        const QString path = QDir::toNativeSeparators(
            QString("%1/%2.png")
                .arg(QCoreApplication::applicationDirPath())
                .arg(frameTime));
        return path.toStdString();
        // Here's how to convert SnapshotRequest to QImage and save it to disk.
        /*if (_sr) {
            const QImage img = QImage(_sr->data, _sr->width, _sr->height,
                                      QImage::Format_RGBA8888);
            if (img.save(path)) {
                qDebug() << "Snapshot saved:" << path;
            } else {
                qDebug() << "Failed to save:" << path;
            }
        } else {
            qDebug() << "Snapshot failed.";
        }
        return "";*/
    });
}
void QMDKWidget::resizeGL(int w, int h)
{
    //auto s = screen();
    //qDebug("resizeGL>>>>>dpr: %f, logical dpi: (%f,%f), phy dpi: (%f,%f)", s->devicePixelRatio(), s->logicalDotsPerInchX(), s->logicalDotsPerInchY(), s->physicalDotsPerInchX(), s->physicalDotsPerInchY());
    player_->setVideoSurfaceSize(w*devicePixelRatio(), h*devicePixelRatio());
}
void QMDKWidget::paintGL()
{
    player_->renderVideo();
}

3.4 QMDKWidget.h

/*
 * Copyright (c) 2020 WangBin <wbsecg1 at gmail.com>
 * MDK SDK with QOpenGLWindow example
 */
#pragma once
#include <QOpenGLWidget>
#include <memory>
namespace mdk {
class Player;
}
class QMDKWidget : public QOpenGLWidget
{
public:
    QMDKWidget(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
    ~QMDKWidget();
    void setDecoders(const QStringList& dec);
    void setMedia(const QString& url);
    void play();
    void pause();
    void stop();
    bool isPaused() const;
    void seek(qint64 ms);
    void snapshot();
    void setPlaybackRate(float value); //播放速度
    void setrotate(int degree);   //设置旋转
    void setMute(bool value);     //设置静音
    void setVolume(float value);  //设置音量
    int64_t duration(); //视频总时间
    int64_t position(); //当前进度
protected:
    void resizeGL(int w, int h) override;
    void paintGL() override;
private:
    std::shared_ptr<mdk::Player> player_;
};

3.5 widget.cpp

#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(timeout_update()));
}
Widget::~Widget()
{
    delete ui;
}
bool Widget::eventFilter(QObject *obj, QEvent *event)
{
    if(obj==ui->horizontalSlider)
    {
        if (event->type()==QEvent::MouseButtonPress)           //判断类型
        {
            QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
            if (mouseEvent->button() == Qt::LeftButton) //判断左键
            {
               int value = QStyle::sliderValueFromPosition(ui->horizontalSlider->minimum(), ui->horizontalSlider->maximum(), mouseEvent->pos().x(), ui->horizontalSlider->width());
               ui->horizontalSlider->setValue(value);
               //跳转播放器
               ui->AV_player->seek(value);
            }
        }
    }
    return QObject::eventFilter(obj,event);
}
//定时器超时
void Widget::timeout_update()
{
    int64_t pos=ui->AV_player->position();
    ui->horizontalSlider->setValue(pos);
    // 设置时间
    ui->label_t2->setText(QString("%1").arg(pos));
}
/*
工程: QMDK_Player
日期: 2021-03-31
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 加载视频文件
*/
void Widget::on_pushButton_load_clicked()
{
    QString filename=QFileDialog::getOpenFileName(this,"选择打开的文件","C:/",tr("*.*"));
    ui->AV_player->setMedia(filename);
    ui->AV_player->play();
    QThread::msleep(100);
    //设置总时间
    ui->label_t1->setText(QString("%1").arg(ui->AV_player->duration()));
    //设置进度条滑块范围
    ui->horizontalSlider->setMinimum(0);
    ui->horizontalSlider->setMaximum(ui->AV_player->duration());
    //事件监听
    ui->horizontalSlider->installEventFilter(this);
    //开启定时器
    timer->start(100);
}
/*
工程: QMDK_Player
日期: 2021-03-31
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 暂停/继续
*/
void Widget::on_pushButton_pause_clicked()
{
    timer->stop();
    ui->AV_player->pause();
}
/*
工程: QMDK_Player
日期: 2021-03-31
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 重新播放
*/
void Widget::on_pushButton_reset_clicked()
{
    ui->AV_player->seek(0);
    ui->AV_player->play();
    timer->start(100);
}
/*
工程: QMDK_Player
日期: 2021-03-31
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 播放
*/
void Widget::on_pushButton_play_clicked()
{
    ui->AV_player->play();
    timer->start(100);
}
/*
工程: QMDK_Player
日期: 2021-03-31
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 停止播放
*/
void Widget::on_pushButton_stop_clicked()
{
    ui->AV_player->stop();
}
//静音设置
void Widget::on_pushButton_Volume_clicked()
{
    static bool value=false;
    value=!value;
    ui->AV_player->setMute(value);
}
//音量设置
void Widget::on_horizontalSlider_Volume_valueChanged(int value)
{
     ui->AV_player->setVolume(float(value/10.0));
}
//拍照. 保存到本地目录下png
void Widget::on_pushButton_snapshot_clicked()
{
    ui->AV_player->snapshot();
}
//设置速度
void Widget::on_comboBox_speed_currentTextChanged(const QString &arg1)
{
    qDebug()<<"速度:"<<arg1;
    ui->AV_player->setPlaybackRate(arg1.toDouble());
}

3.6 widget.h代码

#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QOpenGLWidget>
#include <memory>
#include "QMDKWidget.h"
#include <QFileDialog>
#include "QDebug"
#include <QThread>
#include <QMouseEvent>
#include <QStyle>
#include <QTimer>
namespace mdk {
class Player;
}
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
    Q_OBJECT
public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
private slots:
    void timeout_update();
    void on_pushButton_load_clicked();
    void on_pushButton_pause_clicked();
    void on_pushButton_reset_clicked();
    void on_pushButton_play_clicked();
    void on_pushButton_stop_clicked();
    void on_pushButton_Volume_clicked();
    void on_horizontalSlider_Volume_valueChanged(int value);
    void on_pushButton_snapshot_clicked();
    void on_comboBox_speed_currentTextChanged(const QString &arg1);
protected:
    bool eventFilter(QObject *obj, QEvent *event);
private:
    Ui::Widget *ui;
    QTimer *timer;
};
#endif // WIDGET_H

3.7 ui文件

image.png

image.png

   image.png

image.png

目录
相关文章
|
3天前
|
数据安全/隐私保护 C++ 计算机视觉
Qt(C++)开发一款图片防盗用水印制作小工具
文本水印是一种常用的防盗用手段,可以将文本信息嵌入到图片、视频等文件中,用于识别和证明文件的版权归属。在数字化和网络化的时代,大量的原创作品容易被不法分子盗用或侵犯版权,因此加入文本水印成为了保护原创作品和维护知识产权的必要手段。 通常情况下,文本水印可以包含版权声明、制作者姓名、日期、网址等信息,以帮助识别文件的来源和版权归属。同时,为了增强防盗用效果,文本水印通常会采用字体、颜色、角度等多种组合方式,使得水印难以被删除或篡改,有效地降低了盗用意愿和风险。 开发人员可以使用图像处理技术和编程语言实现文本水印的功能,例如使用Qt的QPainter类进行文本绘制操作,将文本信息嵌入到图片中,
11 1
Qt(C++)开发一款图片防盗用水印制作小工具
|
2天前
|
Linux 开发者 iOS开发
QT:基于QMediaPlayer制作的视频播放器(最下方有整合包,可直接运行)
QMediaPlayer是Qt多媒体模块中的一个核心类,它提供了播放音频和视频内容的功能。这个类的设计旨在简化跨平台的媒体播放,使得开发者能够在多种操作系统(如Linux、Windows、macOS及移动平台)上轻松集成多媒体播放能力到他们的应用中,而无需关心底层实现细节。以下是关于QMediaPlayer的一些关键点:
|
4天前
|
Linux 开发者 iOS开发
QT:基于QMediaPlayer制作的视频播放器(最下方有整合包,可直接运行)
QMediaPlayer是Qt多媒体模块中的一个核心类,它提供了播放音频和视频内容的功能。这个类的设计旨在简化跨平台的媒体播放,使得开发者能够在多种操作系统(如Linux、Windows、macOS及移动平台)上轻松集成多媒体播放能力到他们的应用中,而无需关心底层实现细节。以下是关于QMediaPlayer的一些关键点:
|
18天前
|
关系型数据库 MySQL 项目管理
数据库大作业——基于qt开发的图书管理系统(四)项目目录的整理与绘制登录页面
数据库大作业——基于qt开发的图书管理系统(四)项目目录的整理与绘制登录页面
|
18天前
|
SQL 关系型数据库 MySQL
数据库大作业——基于qt开发的图书管理系统(三)Qt连接Mysql数据库
数据库大作业——基于qt开发的图书管理系统(三)Qt连接Mysql数据库
|
18天前
|
SQL 数据可视化 关系型数据库
数据库大作业——基于qt开发的图书管理系统(二) 相关表结构的设计
数据库大作业——基于qt开发的图书管理系统(二) 相关表结构的设计
|
18天前
|
安全 BI 数据库
数据库大作业——基于qt开发的图书管理系统 (一)环境的配置与项目需求的分析
数据库大作业——基于qt开发的图书管理系统 (一)环境的配置与项目需求的分析
|
2月前
|
JavaScript Java Maven
云效产品使用常见问题之android sdk 构建出aar后,上传到私有maven仓库失败如何解决
云效作为一款全面覆盖研发全生命周期管理的云端效能平台,致力于帮助企业实现高效协同、敏捷研发和持续交付。本合集收集整理了用户在使用云效过程中遇到的常见问题,问题涉及项目创建与管理、需求规划与迭代、代码托管与版本控制、自动化测试、持续集成与发布等方面。
|
9月前
|
API 开发工具 Android开发
解决 Android App 上架 Google play后 ,签名变更,第三方sdk无法登录
解决 Android App 上架 Google play后 ,签名变更,第三方sdk无法登录
186 0
|
2月前
|
安全 开发工具 Android开发
几个Flutter常见诊断错误与解决Android toolchain - develop for Android devices X Unable to locate Android SDK
几个Flutter常见诊断错误与解决Android toolchain - develop for Android devices X Unable to locate Android SDK
843 0