123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290 |
- #include "VideoPlayer.h"
- #include "DecodeVedio.h"
- #include <QPainter>
- #include <QResizeEvent>
- #include <QEventLoop>
- #include "spdlog/spdlog.h"
- VideoPlayer::VideoPlayer(QWidget *parent) : QWidget(parent)
- {
- /* 初始化解码线程 */
- m_threadDecode = new QThread(this);
- m_decodeVedio = new DecodeVedio(m_threadDecode);
- m_semRefresh = new QSemaphore(30);
- m_semRefresh->release(30);
- m_timerRefreshUI.setSingleShot(false);
- /* 设置精度毫秒级 */
- m_timerRefreshUI.setTimerType(Qt::PreciseTimer);
- connect(&m_timerRefreshUI, &QTimer::timeout, this, &VideoPlayer::do_refreshUI);
- connect(m_decodeVedio, &DecodeVedio::signal_oneImage, this, &VideoPlayer::do_refreshOneUI);
- SPDLOG_TRACE("UI线程ID:{}", QThread::currentThreadId());
- }
- VideoPlayer::~VideoPlayer()
- {
- if(m_timerRefreshUI.isActive())
- {
- m_timerRefreshUI.stop();
- }
- delete m_decodeVedio;
- if(m_image)
- {
- delete m_image;
- }
- }
- /**
- * @brief 设置播放视频,启动定时器,定时器间隔决定播放的速度
- * 视频的宽和高使用QImage进行缩放
- * 视频大小在直接设置这个类的resize即可,有最小大小限制
- *
- * @param fileName
- */
- void VideoPlayer::setPlayVedio(const QString& fileName)
- {
- m_fileName = fileName;
- isSetVedioFile = true;
- m_decodeVedio->initFFmpeg(m_fileName);
- /* 获取原始视频信息 */
- m_srcWidth = m_decodeVedio->getVideoWidth();
- m_srcHeight = m_decodeVedio->getVideoHeight();
- m_frameCount = m_decodeVedio->getFrameCount();
- SPDLOG_DEBUG("视频宽:{} 高:{} 帧数:{}", m_srcWidth, m_srcHeight, m_frameCount);
- /* 设置视频宽和高的最小大小 */
- this->setMinimumSize(160,90);
- /* 开启定时器刷新 */
- if(m_frameCount < 0)
- {
- /* HEVC帧率,获取不到,就按照24帧来刷新 */
- if(m_frameCount == -2)
- {
- m_frameCount = 24;
- }
- else {
- m_frameCount = 25;
- }
- }
- else if(m_frameCount == 0)
- {
- m_frameCount = 25;
- }
- SPDLOG_INFO("帧率:{}", m_frameCount);
- /* 开启解码,手动刷新第一帧 */
- m_decodeVedio->startDecodeVedio();
- m_semRefresh->release(1);
- // m_timerRefreshUI.setSingleShot(true);
- // m_timerRefreshUI.start(500);
- }
- /* 播放视频 */
- bool VideoPlayer::play()
- {
- if(!isSetVedioFile)
- {
- SPDLOG_ERROR("文件名为空");
- return false;
- }
- if(m_playStatus)
- {
- return false;
- }
-
- /* 设置刷新时间 */
- m_timerRefreshUI.setSingleShot(false);
- m_interval = 1000/m_frameCount;
- if(1000 % m_frameCount > 5)
- {
- m_frameCount += 1;
- }
- SPDLOG_TRACE("刷新UI的定时间隔:{}",m_interval);
- m_timerRefreshUI.start(m_interval);
- m_playStatus = true;
-
- return true;
- }
- /* 暂停播放 */
- void VideoPlayer::pause()
- {
- if(!m_playStatus)
- {
- return;
- }
- m_timerRefreshUI.stop();
- m_playStatus = false;
- }
- /* 停止播放,停止后停止解码,清空队列,渲染一帧黑屏 */
- void VideoPlayer::stop()
- {
- SPDLOG_DEBUG("...停止播放...");
- m_fileName = QString();
- if(m_timerRefreshUI.isActive())
- {
- m_timerRefreshUI.stop();
- }
- SPDLOG_DEBUG("...停止解码...");
- m_decodeVedio->stopDecodeVedio();
- /* 绘制黑帧 */
- SPDLOG_DEBUG("绘制黑帧");
- m_image = new QImage(m_nowWidth, m_nowHeight, QImage::Format_RGB32);
- m_image->fill(Qt::black);
- update();
- m_playStatus = false;
- isSetVedioFile = false;
- }
- /* 获取视频时长 */
- qint64 VideoPlayer::getDuration()
- {
- return m_decodeVedio->getDuration();
- }
- /* 获取当前播放位置 */
- qint64 VideoPlayer::getCurrentPos()
- {
- return m_decodeVedio->getCurrentPos();
- }
- /* 设置当前播放位置 */
- void VideoPlayer::setCurrentPos(quint64 pos)
- {
- /* 先停止播放 */
- bool temp = m_playStatus;
- if(m_playStatus)
- {
- m_timerRefreshUI.stop();
- m_playStatus = false;
- }
- m_decodeVedio->setCurrentPos(pos);
- /* 继续播放 */
- if(temp)
- {
- m_timerRefreshUI.start(m_interval);
- m_playStatus = true;
- }else
- {
- /* 刷新三张照片,防止第一张是跳转前的时间段 */
- m_semRefresh->release(3);
- }
- }
- void VideoPlayer::paintEvent(QPaintEvent *event)
- {
- if(m_image)
- {
- // SPDLOG_TRACE("开始绘制画面...");
- QPainter painter(this);
- painter.drawImage(0, 0, *m_image);
- }
- }
- void VideoPlayer::resizeEvent(QResizeEvent *event)
- {
- SPDLOG_TRACE("窗口大小改变...");
- m_nowWidth = event->size().width();
- m_nowHeight = event->size().height();
- QWidget::resizeEvent(event);
- }
- /* 刷新一张图片,直到有图片为止 */
- void VideoPlayer::refreshOneUIUntilHave()
- {
- if(m_decodeVedio != nullptr)
- {
- // SPDLOG_DEBUG("取出一帧图片...");
- /* 删除上一帧图片 */
- if(m_image != nullptr)
- {
- delete m_image;
- m_image = nullptr;
- }
- /* 如果没有图片,这个函数会阻塞 */
- m_image = m_decodeVedio->getOneImageUntilHave();
-
- if(m_image)
- {
- if(m_srcWidth != m_nowWidth || m_srcHeight != m_nowHeight)
- {
- *m_image = m_image->scaled(m_nowWidth, m_nowHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation);
- }
- // SPDLOG_DEBUG("绘制画面...");
- update();
- }
- m_decodeVedio->wakeUpCondQueueNoEmpty();
- }
- }
- /* 取出画面,刷新UI */
- void VideoPlayer::do_refreshUI()
- {
- if(m_decodeVedio != nullptr)
- {
- // SPDLOG_DEBUG("取出一帧图片...");
- /* 删除上一帧图片 */
- if(m_image != nullptr)
- {
- delete m_image;
- m_image = nullptr;
- }
- m_image = m_decodeVedio->getOneImage();
-
- if(m_image)
- {
- if(m_srcWidth != m_nowWidth || m_srcHeight != m_nowHeight)
- {
- *m_image = m_image->scaled(m_nowWidth, m_nowHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation);
- }
- // SPDLOG_DEBUG("绘制画面...");
- update();
- }
- m_decodeVedio->wakeUpCondQueueNoEmpty();
- }
- }
- /* 通过信号刷新第一张图片 */
- void VideoPlayer::do_refreshOneUI()
- {
- if(!m_semRefresh->tryAcquire(1))
- {
- return;
- }
- /* 取出第一张 */
- if(m_decodeVedio != nullptr)
- {
- // SPDLOG_DEBUG("取出一帧图片...");
- /* 删除上一帧图片 */
- if(m_image != nullptr)
- {
- delete m_image;
- m_image = nullptr;
- }
- m_image = m_decodeVedio->getOneImage();
-
- if(m_image)
- {
- if(m_srcWidth != m_nowWidth || m_srcHeight != m_nowHeight)
- {
- *m_image = m_image->scaled(m_nowWidth, m_nowHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation);
- }
- // SPDLOG_DEBUG("绘制画面...");
- update();
- }
- m_decodeVedio->wakeUpCondQueueNoEmpty();
- }
- }
|