123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- #include "readthread.h"
- #include "videodecode.h"
- #include <QEventLoop>
- #include <QTimer>
- #include <QDebug>
- #include <qimage.h>
- ReadThread::ReadThread(QObject *parent) : QThread(parent)
- {
- m_videoDecode = new VideoDecode();
- qRegisterMetaType<PlayState>("PlayState"); // 注册自定义枚举类型,否则信号槽无法发送
- }
- ReadThread::~ReadThread()
- {
- if(m_videoDecode)
- {
- delete m_videoDecode;
- }
- }
- /**
- * @brief 传入播放的视频地址并开启线程
- * @param url
- */
- void ReadThread::open(const QString &url)
- {
- if(!this->isRunning())
- {
- m_url = url;
- emit this->start();
- }
- }
- /**
- * @brief 控制暂停、继续
- * @param flag true:暂停 fasle:继续
- */
- void ReadThread::pause(bool flag)
- {
- m_pause = flag;
- }
- /**
- * @brief 关闭播放
- */
- void ReadThread::close()
- {
- m_play = false;
- m_pause = false;
- }
- /**
- * @brief 返回当前播放的地址
- * @return
- */
- const QString &ReadThread::url()
- {
- return m_url;
- }
- /**
- * @brief 设置使用硬件解码
- * @param flag
- */
- void ReadThread::setHWDecoder(bool flag)
- {
- m_videoDecode->setHWDecoder(flag);
- }
- /**
- * @brief 非阻塞延时
- * @param msec 延时毫秒
- */
- void sleepMsec(int msec)
- {
- if(msec <= 0) return;
- QEventLoop loop; //定义一个新的事件循环
- QTimer::singleShot(msec, &loop, SLOT(quit()));//创建单次定时器,槽函数为事件循环的退出函数
- loop.exec(); //事件循环开始执行,程序会卡在这里,直到定时时间到,本循环被退出
- }
- void ReadThread::run()
- {
- bool ret = m_videoDecode->open(m_url); // 打开网络流时会比较慢,如果放到Ui线程会卡
- if(ret)
- {
- m_play = true;
- m_etime1.start();
- m_etime2.start();
- emit playState(play);
- }
- else
- {
- qWarning() << "打开失败!";
- }
- // 循环读取视频图像
- while (m_play)
- {
- // 暂停
- while (m_pause)
- {
- sleepMsec(200);
- }
- QImage image = m_videoDecode->read(); // 读取视频图像
- if(!image.isNull())
- {
- // 1倍速播放
- #if 0
- sleepMsec(int(m_decodeVideo->pts() - m_etime1.elapsed())); // 不支持后退
- #else
- sleepMsec(int(m_videoDecode->pts() - m_etime2.elapsed())); // 支持后退(如果能读取到视频,但一直不显示可以把这一行代码注释试试)
- #endif
- emit updateImage(image);
- }
- else
- {
- // 当前读取到无效图像时判断是否读取完成
- if(m_videoDecode->isEnd())
- {
- break;
- }
- sleepMsec(1); // 这里不能使用QThread::msleep()延时,否则会很不稳定
- }
- }
- qDebug() << "播放结束!";
- m_videoDecode->close();
- emit playState(end);
- }
|