OpenCV|【OpenCV + Qt】 制作视频播放器

目录

一:视频播放器成果测试
1.1 点击开始播放按钮,能够播放视频
【OpenCV|【OpenCV + Qt】 制作视频播放器】1.2 点击暂停播放 视频停在某一帧画面 同时按钮文本改变为继续播放 以便用户继续播放视频 提高用户使用体验感
1.3 点击结束播放 就不再播放视频 同时结束播放按钮不可以再次点击
1.4 点击重新播放 可以播放新的一个视频
1.5 点击开始录制,从当前帧画面开始录制,并将录制视频保存在自己配置的文件夹目录下
1.6 点击中断录制,可以随时停止录制视频
1.7 进度条拖拽 视频画面也跟随进度条拖拽进度进行更新播放
二:完整代码

一:视频播放器成果测试 1.1 点击开始播放按钮,能够播放视频
OpenCV|【OpenCV + Qt】 制作视频播放器
文章图片

1.2 点击暂停播放 视频停在某一帧画面 同时按钮文本改变为继续播放 以便用户继续播放视频 提高用户使用体验感
点击暂停 停在某一帧画面
OpenCV|【OpenCV + Qt】 制作视频播放器
文章图片

点击继续 继续播放视频
OpenCV|【OpenCV + Qt】 制作视频播放器
文章图片

1.3 点击结束播放 就不再播放视频 同时结束播放按钮不可以再次点击
OpenCV|【OpenCV + Qt】 制作视频播放器
文章图片

1.4 点击重新播放 可以播放新的一个视频
OpenCV|【OpenCV + Qt】 制作视频播放器
文章图片

1.5 点击开始录制,从当前帧画面开始录制,并将录制视频保存在自己配置的文件夹目录下
点击录制,录制300ms
OpenCV|【OpenCV + Qt】 制作视频播放器
文章图片

去自己配置文件夹下,可以查看到自己刚才录制下来的视频 并且双击打开能够正常播放
OpenCV|【OpenCV + Qt】 制作视频播放器
文章图片

1.6 点击中断录制,可以随时停止录制视频
点击中断录制 只录制69ms
OpenCV|【OpenCV + Qt】 制作视频播放器
文章图片

同样能够在自己配置的文件夹目录下 查看到 自己中断录制前所录制下来的视频
OpenCV|【OpenCV + Qt】 制作视频播放器
文章图片

1.7 进度条拖拽 视频画面也跟随进度条拖拽进度进行更新播放
OpenCV|【OpenCV + Qt】 制作视频播放器
文章图片

经过以上的测试,大致完成了本次的视频播放器的基本业务流程。
二:完整代码

UI界面可以Qt可视化绘制
OpenCV|【OpenCV + Qt】 制作视频播放器
文章图片

源码:
OpenCV|【OpenCV + Qt】 制作视频播放器
文章图片

窗口类
#ifndef WIDGET_H #define WIDGET_H#include #include #include #include #include"videothread.h"using namespace cv; using namespace std; namespace Ui { class Widget; }class Widget : public QWidget { Q_OBJECTpublic: explicit Widget(QWidget *parent = 0); ~Widget(); void paintEvent(QPaintEvent *arg); void videoinit(char *path); private: Ui::Widget *ui; QImage img; VideoThread *thread; //线程对象 public slots: void ChangeData(int current,Mat frame); private slots: void on_startButton_clicked(); //开始播放 void on_pauseButton_clicked(); //结束 void on_stopButton_clicked(); //暂停 void on_replayButton_clicked(); //重新播放 void on_startRecordButton_clicked(); //开始录制 void on_stopRecordButton_clicked(); //中断录制 void on_horizontalSlider_sliderPressed(); //按下进度条 void on_horizontalSlider_sliderReleased(); //松开进度条 }; #endif // WIDGET_H

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); videoinit("D:/000000000000000ffmpeg/那些年,我们一起追的女孩.mp4"); }Widget::~Widget() { delete ui; }void Widget::videoinit(char *path) { //线程播放视频 this->thread = new VideoThread(path); //进度条的初始化 ui->horizontalSlider->setMinimum(0); ui->horizontalSlider->setMaximum(this->thread->getTotalpage()); //进度条拖动范围 ui->horizontalSlider->setRange(0,this->thread->getTotalpage()); //进度条步长 ui->horizontalSlider->setSingleStep(1); ui->horizontalSlider->setValue(0); //label初始化 ui->totalPage->setText(QString::number(this->thread->getTotalpage())); ui->currentPage->setText(QString::number(0)); connect(this->thread,SIGNAL(send2UI(int,Mat)),this,SLOT(ChangeData(int,Mat)),Qt::BlockingQueuedConnection); }void Widget::paintEvent(QPaintEvent *arg) { //视频播放显示 ui->label->setPixmap(QPixmap::fromImage(this->img)); }void Widget::ChangeData(int current, Mat frame) { this->img = QImage(frame.data,frame.cols,frame.rows,QImage::Format_RGB888); this->img = this->img.scaled(ui->label->width(),ui->label->height()); ui->currentPage->setText(QString::number(current)); ui->horizontalSlider->setValue(current); this->update(); }void Widget::on_startButton_clicked() { this->thread->start(); this->thread->setIsRun(true); qDebug()<<"thread start"; }void Widget::on_pauseButton_clicked() { //如果当前的线程没有在执行 if(this->thread->getIsRun() == false) { //继续执行线程 this->thread->resumeThread(); ui->pauseButton->setText("暂停播放"); } else { //点击暂停播放视频的按钮 this->thread->pauseThread(); //要设置可继续播放视频的按钮 ui->pauseButton->setText("继续播放"); } }//点击结束播放 void Widget::on_stopButton_clicked() { this->thread->stopThread(); if(this->thread->isRunning() == false && this->thread != NULL) { //解除信号槽的绑定 disconnect(this->thread,SIGNAL(send2UI(int,Mat)), this,SLOT(ChangeData(int,Mat))); delete this->thread; this->thread = NULL; //设置不可以点击 ui->stopButton->setEnabled(false); } }//重新播放 void Widget::on_replayButton_clicked() { this->thread->stopThread(); //QThread::sleep(1); if(this->thread->isRunning() == false) { //解除信号槽的绑定 disconnect(this->thread,SIGNAL(send2UI(int,Mat)), this,SLOT(ChangeData(int,Mat))); delete this->thread; //播放新的一个视频 videoinit("D:/000000000000000ffmpeg/中国合伙人.avi"); this->thread->start(); this->thread->setIsRun(true); } }//开始录制 void Widget::on_startRecordButton_clicked() { this->thread->setIsRecord(true); }//中断录制 void Widget::on_stopRecordButton_clicked() { this->thread->setIsRecord(false); }//进度条按下 void Widget::on_horizontalSlider_sliderPressed() { //暂停当前线程 this->thread->pauseThread(); }//进度条释放 void Widget::on_horizontalSlider_sliderReleased() { //改变当前帧进度 this->thread->setCurrentpage(ui->horizontalSlider->value()); //继续线程 this->thread->resumeThread(); }

视频线程类
#ifndef VIDEOTHREAD_H #define VIDEOTHREAD_H #include #include #include #include #includeusing namespace cv; using namespace std; class VideoThread : public QThread { Q_OBJECT public: VideoThread(char *path); //总帧数 int getTotalpage() const; void setTotalpage(int value); //当前帧进度 int getCurrentpage() const; void setCurrentpage(int value); //录制 bool getIsRecord() const; void setIsRecord(bool value); void run(); //运行 void pauseThread(); //暂停 void resumeThread(); //继续 void stopThread(); //停止 bool getIsRun() const; void setIsRun(bool value); private: VideoCapture cap; //视频对象 VideoWriter writer; //写视频对象 Mat frame; //当前每一帧的画面一帧画面 int totalpage; //视频总帧数 int currentpage; //视频正在播放的当前帧数 int pagenum; //录制的帧数 int frame_width; //帧宽 int frame_height; //帧高 //暂停方法:1.锁对象QMutex 2.条件变量 3.标志位bool 是线程暂停 bool isRun; //控线线程暂停 bool isStop; //控制结束 bool isRecord; //控制线程什么时候开始/结束录制 signals: void send2UI(int current,Mat frame); }; #endif // VIDEOTHREAD_H

#include "videothread.h"VideoThread::VideoThread(char *path):QThread() { if(this->cap.open(path)) { qDebug()<<"Video is open"; //cap对象创建成功 路径成功 就可获取到视频总帧数 this->totalpage = cap.get(CV_CAP_PROP_FRAME_COUNT); qDebug()<<"Video totalpage ="<totalpage; //帧宽 帧高 的获取 this->frame_width = cap.get(CV_CAP_PROP_FRAME_WIDTH); this->frame_height = cap.get(CV_CAP_PROP_FRAME_HEIGHT); } //当前帧 this->currentpage = 0; //录制视频帧 this->pagenum = 0; //运行 this->isRun = false; //结束 this->isStop = false; //录制 this->isRecord = false; }int VideoThread::getTotalpage() const { return totalpage; }void VideoThread::setTotalpage(int value) { totalpage = value; }int VideoThread::getCurrentpage() const { return currentpage; }void VideoThread::setCurrentpage(int value) { currentpage = value; //拖动进度条 改变画面 this->cap.set(CV_CAP_PROP_POS_FRAMES,this->currentpage); }bool VideoThread::getIsRecord() const { return isRecord; }void VideoThread::setIsRecord(bool value) { isRecord = value; //开始录制 if(this->isRecord == true) { QDateTime current_date_time = QDateTime::currentDateTime(); QString filename = "./video/"; filename += current_date_time.toString("yyyy_MM_dd_hh_mm_ss"); filename += ".avi"; qDebug()<<"filename = "<writer.open(filename.toStdString(),//视频文件名 VideoWriter::fourcc('M','J','P','G'),//编码类型 25,//帧率 Size(this->frame_width,this->frame_height),//尺寸大小 true); //彩色格式为true 灰度为false } }void VideoThread::run() { //控制线程停止 while (this->isStop == false) { //控线线程的暂停和继续 if(this->isRun == true) { //如果读到一帧 if(cap.read(frame)) { //当前帧数递增 this->currentpage++; cvtColor(frame,frame,CV_BGR2RGB); emit send2UI(this->currentpage,frame); //开始录制 if(this->isRecord == true) { cvtColor(frame,frame,CV_BGR2RGB); //录制300ms if(this->pagenum<300) { this->writer.write(frame); this->pagenum++; qDebug()<<"Record pagenum = "pagenum = 0; this->isRecord = false; } } else{ //录制保存 this->writer.release(); this->pagenum = 0; } } //播放设置1ms 25帧 msleep(40); } } cap.release(); qDebug()<<"thread move away"; }//暂停视频播放 void VideoThread::pauseThread() { qDebug()<<"pauseThread "; //如果当前线程正在执行 if(QThread::isRunning()&&this->isRun == true) { this->isRun = false; } }//继续播放 void VideoThread::resumeThread() { qDebug()<<"resumeThread "; //如果当前线程正在执行 if(QThread::isRunning()&&this->isRun == false) { this->isRun = true; } }//结束播放 void VideoThread::stopThread() { qDebug()<<"stopThread"; //如果当前线程正在执行 if(QThread::isRunning()&&this->isStop == false) { this->isStop = true; QThread::quit(); QThread::wait(); QThread::exit(); //QThread::terminate(); } }bool VideoThread::getIsRun() const { return isRun; }void VideoThread::setIsRun(bool value) { isRun = value; }

主入口测试
#include "widget.h" #include int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.show(); return a.exec(); }

以上就是本次视频播放器的全部制作流程啦!欢迎一起学习!
OpenCV|【OpenCV + Qt】 制作视频播放器
文章图片

    推荐阅读