找回密码
 立即注册
  • QQ空间
  • 回复
  • 收藏

Qt实用技巧:使用OpenCV库的视频播放器(支持播放器操作,如暂停、恢复、停止、时间、进度条拽托等

admin 2019-11-29 17:05 390人围观 Qt相关

点击上方↑↑↑“OpenCV学堂”关注我

投稿作者: 红模仿_红胖子

研究方向:OpenCV/OpenGL/QT/软硬件结合

博客地址:https://blog.csdn.net/qq21497936

文字编辑:gloomyfish
需求
使用OpenCV库的视频播放器(支持播放器操作,如暂停、恢复、停止、时间、进度条拽托等)。

原理

 使用OpenCV打开视频文件,获取总帧数,根据当前帧数,刷新当前时间戳与预期的时间间隔,调用槽函数动态刷新播放内容。

注意

当前只测试了avi文件

运行效果



核心类代码

OpenCVPlayerManager.h
#ifndef OPENCVPLAYERMANAGER_H
#define OPENCVPLAYERMANAGER_H

/************************************************************\
 * 控件名称:OpenCVPlayerManager,OpenCV管理类
 * 控件描述:
 *          1.OpenCV打开视频文件
 *          2.播放器操作:播放、暂停、停止
 *          3.播放时显示:当前时间、总时间
 *          4.设置当前播放的时间点
 *
 * 作者:红模仿    联系方式:QQ21497936
 * 博客地址:https://blog.csdn.net/qq21497936
 *       日期                版本               描述
 *   2019年11月25日      v1.0.0         opencv打开文件
\************************************************************/

#include <QObject>
#include <QImage>
#include <QTimer>
#include <QElapsedTimer>
// opencv
#include "opencv/highgui.h"
#include "opencv/cxcore.h"
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/opencv.hpp"

class OpenCVPlayerManager : public QObject
{
    Q_OBJECT
public:
    enum PLAY_STATE {
        PLAY_STATE_PLAYING,
        PLAY_STATE_PAUSE,
        PLAY_STATE_STOP
    };

public:
    explicit OpenCVPlayerManager(QObject *parent = 0);
    ~OpenCVPlayerManager();

public:
    QString getWindowTitle() const;

public:
    void setWindowTitle(const QString &windowTitle);

signals:
    void signal_captureOneFrame(cv::Mat mat);           // 接收图像后抛出信号
    void signal_playStateChanged(OpenCVPlayerManager::PLAY_STATE playState);
                                                        // 播放器状态
    void signal_durationChanged(qint64 duration);       // 视频总长度
    void signal_positionChanged(qint64 position);       // 当前位置

public:
    bool startPlay(QString filePath, int width = 480, int height = 320);
    void pause();                       // 暂停
    void resume();                      // 恢复播放
    void stopPlay();                    // 停止播放
    void setPosition(qint64 position);  // 切换到播放位置

public slots:
    bool slot_start();                  // 开启线程
    bool stop();                        // 关闭线程

protected slots:
    void slot_captrueFrame();           // 消息循环获取图像
    void slot_stopPlay();               // 停止播放
    void slot_setPosition(qint64 position);

public:
    static QImage cvMat2QImage(const cv::Mat &mat);

private:
    cv::VideoCapture *_pVideoCapture;   // 播放文件实例
    QString _filePath;                  // 播放文件路径

    bool _running;                      // 线程是否运行

    int _totalFrames;                   // 总帧数
    int _fps;                           // 每秒帧数
    int _currentFrame;                  // 当前帧数
    int _width;                         // 高度
    int _height;                        // 宽度

    QElapsedTimer _elapsedTimer;        // 计时器
    qint64 _pauseMs;                    // 暂停的毫秒
    qint64 _duration;                   // 视频总长度(毫秒)

    PLAY_STATE _playState;              // 播放器状态

    int _position;                      // 改变到的播放位置
    bool _setPostion;                   // 播放位置修改标志

private:
    QString _windowTitle;
};
#endif // OPENCVPLAYERMANAGER_H


OpenCVPlayerManager.cpp
#include "OpenCVPlayerManager.h"

#include <QDebug>

OpenCVPlayerManager::OpenCVPlayerManager(QObject *parent)
    : QObject(parent),
      _pVideoCapture(0),
      _totalFrames(0),
      _currentFrame(0),
      _playState(PLAY_STATE_STOP),
      _pauseMs(0),
      _duration(0)
{
    QString version = "v1.0.0";
    _windowTitle = QString("OpenCVPlayer %1(红模仿-红胖子 QQ21497936 博客地址: blog.csdn.net/qq21497936").arg(version);
}

OpenCVPlayerManager::~OpenCVPlayerManager()
{

}

bool OpenCVPlayerManager::startPlay(QString filePath, int width, int height)
{
    // 状态判断
    switch (_playState)
    {
    case PLAY_STATE_PAUSE:
        resume();
    case PLAY_STATE_PLAYING:
        return true;
        break;
    case PLAY_STATE_STOP:
        break;
    default:
        break;
    }
    if(!_pVideoCapture->open(filePath.toStdString()))
    {
        qDebug() << __FILE__ << __LINE__ << "Failed to start video :" << filePath;
        return false;
    }
    _width = width;
    _height = height;
    _pVideoCapture->set(CV_CAP_PROP_FRAME_WIDTH, _width);
    _pVideoCapture->set(CV_CAP_PROP_FRAME_HEIGHT, _height);
    _width = _pVideoCapture->get(CV_CAP_PROP_FRAME_WIDTH);
    _height = _pVideoCapture->get(CV_CAP_PROP_FRAME_HEIGHT);
    _fps = _pVideoCapture->get(CV_CAP_PROP_FPS);
    _totalFrames = _pVideoCapture->get(CV_CAP_PROP_FRAME_COUNT);
    qDebug() << __FILE__ << __LINE__ << "width =" << width;
    qDebug() << __FILE__ << __LINE__ << "height =" << height;
    qDebug() << __FILE__ << __LINE__ << "_width =" << _width;
    qDebug() << __FILE__ << __LINE__ << "_height =" << _height;
    qDebug() << __FILE__ << __LINE__ << "_fps =" << _fps;
    qDebug() << __FILE__ << __LINE__ << "_totalFrames =" << _totalFrames;

    _currentFrame = 0;
    _pauseMs = 0;

    QTimer::singleShot(0, this, SLOT(slot_captrueFrame()));
    _elapsedTimer.start();

    _playState = PLAY_STATE_PLAYING;
    emit signal_playStateChanged(_playState);

    _duration = (_totalFrames - 1) * (1000.0f / _fps);
    emit signal_durationChanged(_duration);

    return true;
}

void OpenCVPlayerManager::pause()
{
    // 状态判断
    switch (_playState)
    {
    case PLAY_STATE_PAUSE:
    case PLAY_STATE_STOP:
        return;
        break;
    case PLAY_STATE_PLAYING:
        break;
    default:
        break;
    }
    _playState = PLAY_STATE_PAUSE;
    emit signal_playStateChanged(_playState);
}

void OpenCVPlayerManager::resume()
{
    // 状态判断
    switch (_playState)
    {
    case PLAY_STATE_PLAYING:
    case PLAY_STATE_STOP:
        return;
        break;
    case PLAY_STATE_PAUSE:
        break;
    default:
        break;
    }
    QTimer::singleShot(0, this, SLOT(slot_captrueFrame()));
    _elapsedTimer.start();
    _playState = PLAY_STATE_PLAYING;
    emit signal_playStateChanged(_playState);
}

void OpenCVPlayerManager::stopPlay()
{
    // 状态判断
    switch (_playState)
    {
    case PLAY_STATE_STOP:
        return;
        break;
    case PLAY_STATE_PAUSE:
    case PLAY_STATE_PLAYING:
        break;
    default:
        break;
    }
    QTimer::singleShot(0, this, SLOT(slot_stopPlay()));
}

void OpenCVPlayerManager::setPosition(qint64 position)
{
    QMetaObject::invokeMethod(this, "slot_setPosition", Q_ARG(qint64, position));
}

void OpenCVPlayerManager::slot_setPosition(qint64 position)
{
    // 当前帧数
    _currentFrame = position / (1000.0f / _fps);
    _pauseMs = _currentFrame * (1000.0f / _fps);
     _pVideoCapture->set(CV_CAP_PROP_POS_FRAMES, _currentFrame);
    _elapsedTimer.start();
    qDebug() << __FILE__ << __LINE__
             << _