#include "VideoPlayer.h" #include "DecodeVedio.h" #include #include #include #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(); } }