readthread.cpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. #include "readthread.h"
  2. #include "videodecode.h"
  3. #include <QEventLoop>
  4. #include <QTimer>
  5. #include <QDebug>
  6. #include <qimage.h>
  7. ReadThread::ReadThread(QObject *parent) : QThread(parent)
  8. {
  9. m_videoDecode = new VideoDecode();
  10. qRegisterMetaType<PlayState>("PlayState"); // 注册自定义枚举类型,否则信号槽无法发送
  11. }
  12. ReadThread::~ReadThread()
  13. {
  14. if(m_videoDecode)
  15. {
  16. delete m_videoDecode;
  17. }
  18. }
  19. /**
  20. * @brief 传入播放的视频地址并开启线程
  21. * @param url
  22. */
  23. void ReadThread::open(const QString &url)
  24. {
  25. if(!this->isRunning())
  26. {
  27. m_url = url;
  28. emit this->start();
  29. }
  30. }
  31. /**
  32. * @brief 控制暂停、继续
  33. * @param flag true:暂停 fasle:继续
  34. */
  35. void ReadThread::pause(bool flag)
  36. {
  37. m_pause = flag;
  38. }
  39. /**
  40. * @brief 关闭播放
  41. */
  42. void ReadThread::close()
  43. {
  44. m_play = false;
  45. m_pause = false;
  46. }
  47. /**
  48. * @brief 返回当前播放的地址
  49. * @return
  50. */
  51. const QString &ReadThread::url()
  52. {
  53. return m_url;
  54. }
  55. /**
  56. * @brief 设置使用硬件解码
  57. * @param flag
  58. */
  59. void ReadThread::setHWDecoder(bool flag)
  60. {
  61. m_videoDecode->setHWDecoder(flag);
  62. }
  63. /**
  64. * @brief 非阻塞延时
  65. * @param msec 延时毫秒
  66. */
  67. void sleepMsec(int msec)
  68. {
  69. if(msec <= 0) return;
  70. QEventLoop loop; //定义一个新的事件循环
  71. QTimer::singleShot(msec, &loop, SLOT(quit()));//创建单次定时器,槽函数为事件循环的退出函数
  72. loop.exec(); //事件循环开始执行,程序会卡在这里,直到定时时间到,本循环被退出
  73. }
  74. void ReadThread::run()
  75. {
  76. bool ret = m_videoDecode->open(m_url); // 打开网络流时会比较慢,如果放到Ui线程会卡
  77. if(ret)
  78. {
  79. m_play = true;
  80. m_etime1.start();
  81. m_etime2.start();
  82. emit playState(play);
  83. }
  84. else
  85. {
  86. qWarning() << "打开失败!";
  87. }
  88. // 循环读取视频图像
  89. while (m_play)
  90. {
  91. // 暂停
  92. while (m_pause)
  93. {
  94. sleepMsec(200);
  95. }
  96. QImage image = m_videoDecode->read(); // 读取视频图像
  97. if(!image.isNull())
  98. {
  99. // 1倍速播放
  100. #if 0
  101. sleepMsec(int(m_decodeVideo->pts() - m_etime1.elapsed())); // 不支持后退
  102. #else
  103. sleepMsec(int(m_videoDecode->pts() - m_etime2.elapsed())); // 支持后退(如果能读取到视频,但一直不显示可以把这一行代码注释试试)
  104. #endif
  105. emit updateImage(image);
  106. }
  107. else
  108. {
  109. // 当前读取到无效图像时判断是否读取完成
  110. if(m_videoDecode->isEnd())
  111. {
  112. break;
  113. }
  114. sleepMsec(1); // 这里不能使用QThread::msleep()延时,否则会很不稳定
  115. }
  116. }
  117. qDebug() << "播放结束!";
  118. m_videoDecode->close();
  119. emit playState(end);
  120. }