|
@@ -1,680 +0,0 @@
|
|
|
-#include "DecodeVedio.h"
|
|
|
-#include "spdlog/spdlog.h"
|
|
|
-
|
|
|
-#include <QImage>
|
|
|
-#include <QThread>
|
|
|
-
|
|
|
-extern "C"
|
|
|
-{
|
|
|
-#include <libavcodec/avcodec.h>
|
|
|
-#include <libavformat/avformat.h>
|
|
|
-#include <libswscale/swscale.h>
|
|
|
-#include <libavutil/imgutils.h>
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-DecodeVedio::DecodeVedio(QThread* thread, QObject* parent) : QObject(parent) , m_thread(thread)
|
|
|
-{
|
|
|
-
|
|
|
- this->moveToThread(thread);
|
|
|
- m_startThread.setSingleShot(true);
|
|
|
- connect(&m_startThread, &QTimer::timeout, this, &DecodeVedio::do_startDecodeVedio);
|
|
|
- thread->start();
|
|
|
-}
|
|
|
-
|
|
|
-DecodeVedio::~DecodeVedio()
|
|
|
-{
|
|
|
- exitThread();
|
|
|
- if(m_thread != nullptr)
|
|
|
- {
|
|
|
- if(m_thread->isRunning())
|
|
|
- {
|
|
|
- m_thread->quit();
|
|
|
- m_thread->wait();
|
|
|
- }
|
|
|
- }
|
|
|
- if(m_initFFmpeg)
|
|
|
- {
|
|
|
- freeFFmpeg();
|
|
|
- }
|
|
|
- if(!m_queueImage.isEmpty())
|
|
|
- {
|
|
|
- int size = m_queueImage.count();
|
|
|
- for(int i = 0; i < size; i++)
|
|
|
- {
|
|
|
- auto image = m_queueImage.dequeue();
|
|
|
- if (image)
|
|
|
- {
|
|
|
- delete image;
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-void DecodeVedio::startDecodeVedio()
|
|
|
-{
|
|
|
- if(m_isRunning)
|
|
|
- {
|
|
|
- return;
|
|
|
- }
|
|
|
- if(!m_initFFmpeg)
|
|
|
- {
|
|
|
- SPDLOG_WARN("未初始化FFMPEG...");
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- m_startThread.start(0);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-void DecodeVedio::stopDecodeVedio()
|
|
|
-{
|
|
|
- if(!m_isRunning)
|
|
|
- {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- m_isRunning = false;
|
|
|
- m_pauseDecode = false;
|
|
|
-
|
|
|
- m_condQueueNoFull.wakeAll();
|
|
|
-
|
|
|
- while(!m_threadStopped)
|
|
|
- {
|
|
|
-
|
|
|
- std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
|
|
- }
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
- * @brief 设置当前播放位置,单位是微秒
|
|
|
- * 这里需要去掉队列中已有的图片数目对应的时长
|
|
|
- *
|
|
|
- * @param pos
|
|
|
- */
|
|
|
-void DecodeVedio::setCurrentPos(quint64 pos)
|
|
|
-{
|
|
|
-
|
|
|
-
|
|
|
- m_pauseDecode = true;
|
|
|
-
|
|
|
- while (m_decodeStatus) {
|
|
|
-
|
|
|
- m_condQueueNoFull.wakeAll();
|
|
|
- std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
|
|
- }
|
|
|
- m_isSeek = true;
|
|
|
-
|
|
|
- if(pos > 9223372036854775807)
|
|
|
- {
|
|
|
- pos = 0;
|
|
|
- }
|
|
|
-
|
|
|
- qint64 queueNumFPS = m_queueImage.count() * ( 1000.0f / m_fps ) * 1000 ;
|
|
|
- qint64 target_pos = m_startPos + pos - queueNumFPS;
|
|
|
- qint64 end_pos = m_startPos + m_duration;
|
|
|
-
|
|
|
- if(target_pos > end_pos)
|
|
|
- {
|
|
|
-
|
|
|
- target_pos = end_pos;
|
|
|
-
|
|
|
- }
|
|
|
- if(target_pos < m_startPos)
|
|
|
- {
|
|
|
- target_pos = m_startPos;
|
|
|
-
|
|
|
- }
|
|
|
- m_currentPos = target_pos;
|
|
|
- SPDLOG_DEBUG("设置播放位置:{}",target_pos);
|
|
|
-
|
|
|
- int ret = av_seek_frame(m_pFormatContext, -1, target_pos, AVSEEK_FLAG_BACKWARD);
|
|
|
-
|
|
|
- avcodec_flush_buffers(m_pCodecCtx);
|
|
|
- if(ret < 0)
|
|
|
- {
|
|
|
- SPDLOG_WARN("跳转失败...");
|
|
|
- }
|
|
|
-
|
|
|
- m_mutexQueue.lock();
|
|
|
- int size = m_queueImage.count();
|
|
|
- for(int i = 0; i < size; i++)
|
|
|
- {
|
|
|
- auto image = m_queueImage.dequeue();
|
|
|
- if (image)
|
|
|
- {
|
|
|
- delete image;
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
- m_mutexQueue.unlock();
|
|
|
- m_condQueueNoFull.wakeAll();
|
|
|
- SPDLOG_INFO("跳转完成 , queue count {}", m_queueImage.count());
|
|
|
-
|
|
|
- m_pauseDecode = false;
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-qint64 DecodeVedio::getCurrentPos()
|
|
|
-{
|
|
|
-
|
|
|
- return m_currentPos - m_startPos;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-qint64 DecodeVedio::getDuration()
|
|
|
-{
|
|
|
- return m_duration;
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-void DecodeVedio::wakeUpCondQueueNoEmpty()
|
|
|
-{
|
|
|
- m_condQueueNoFull.wakeAll();
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
- * @brief 获取一帧图像,队列为空就返回nullptr,这个函数应该是运行在UI线程中的
|
|
|
- * @warning 传出这个指针后,队列就出队了,内存需要外面获取的实例释放
|
|
|
- * @return QImage* 一帧图像的指针
|
|
|
- */
|
|
|
-QImage* DecodeVedio::getOneImage()
|
|
|
-{
|
|
|
- if(m_queueImage.count() == 0)
|
|
|
- {
|
|
|
-
|
|
|
- return nullptr;
|
|
|
- }
|
|
|
-
|
|
|
- m_mutexQueue.lock();
|
|
|
- auto image = m_queueImage.dequeue();
|
|
|
- m_mutexQueue.unlock();
|
|
|
-
|
|
|
- if(m_queueImage.count() < 20)
|
|
|
- {
|
|
|
- m_condQueueNoFull.wakeAll();
|
|
|
- }
|
|
|
- return image;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-QImage* DecodeVedio::getOneImageUntilHave()
|
|
|
-{
|
|
|
- QImage* image = nullptr;
|
|
|
- if(m_queueImage.count() == 0)
|
|
|
- {
|
|
|
- m_mutexQueue.lock();
|
|
|
- m_condQueueNoEmpty.wait(&m_mutexQueue);
|
|
|
- image = m_queueImage.dequeue();
|
|
|
- m_mutexQueue.unlock();
|
|
|
- }
|
|
|
-
|
|
|
- return image;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
- * @brief 获取每秒的帧数
|
|
|
- *
|
|
|
- * @return int 正值表示帧数,-1表示未知,-2表示HEVC
|
|
|
-
|
|
|
- */
|
|
|
-int DecodeVedio::getFrameCount()
|
|
|
-{
|
|
|
- AVFormatContext *pFormatCtx = NULL;
|
|
|
- avformat_open_input(&pFormatCtx, m_fileName.toStdString().c_str(), NULL, NULL);
|
|
|
- avformat_find_stream_info(pFormatCtx, NULL);
|
|
|
-
|
|
|
- int videoStreamIndex = -1;
|
|
|
- for (int i = 0; i < pFormatCtx->nb_streams; i++)
|
|
|
- {
|
|
|
- if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
|
|
- videoStreamIndex = i;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- enum AVCodecID codecID = pFormatCtx->streams[videoStreamIndex]->codecpar->codec_id;
|
|
|
- if (codecID == AV_CODEC_ID_HEVC)
|
|
|
- {
|
|
|
- SPDLOG_DEBUG("视频格式是HEVC");
|
|
|
- m_fps = -2;
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- }
|
|
|
- else if(codecID == AV_CODEC_ID_H264)
|
|
|
- {
|
|
|
- SPDLOG_DEBUG("视频格式是H.264");
|
|
|
-
|
|
|
- AVRational frameRate = pFormatCtx->streams[videoStreamIndex]->avg_frame_rate;
|
|
|
- m_fps = frameRate.num*1.0 / frameRate.den;
|
|
|
-
|
|
|
- }else
|
|
|
- {
|
|
|
- m_fps = 30;
|
|
|
- }
|
|
|
-
|
|
|
- avformat_close_input(&pFormatCtx);
|
|
|
-
|
|
|
- return m_fps;
|
|
|
-}
|
|
|
-
|
|
|
- * @brief 设置图像宽度和高度
|
|
|
- * 注意:目前不好用,建议使用Qt的图片缩放
|
|
|
- *
|
|
|
- * @param width
|
|
|
- * @param height
|
|
|
- */
|
|
|
-void DecodeVedio::setVideoSize(int width, int height)
|
|
|
-{
|
|
|
- m_width = width;
|
|
|
- m_height = height;
|
|
|
-
|
|
|
- if(m_sws_ctx != nullptr)
|
|
|
- {
|
|
|
-
|
|
|
- pauseDecode();
|
|
|
- sws_freeContext(m_sws_ctx);
|
|
|
- }
|
|
|
-
|
|
|
- m_sws_ctx = sws_getContext( m_pCodecCtx->width, m_pCodecCtx->height, m_pCodecCtx->pix_fmt,
|
|
|
- m_width, m_height, AV_PIX_FMT_RGB24,
|
|
|
- SWS_BICUBIC,
|
|
|
- nullptr,
|
|
|
- nullptr,
|
|
|
- nullptr);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-void DecodeVedio::initFFmpeg(const QString& fileName)
|
|
|
-{
|
|
|
- if(m_initFFmpeg)
|
|
|
- {
|
|
|
- return;
|
|
|
- }
|
|
|
- m_fileName = fileName;
|
|
|
-
|
|
|
- int size = m_queueImage.count();
|
|
|
- for(int i = 0; i < size; i++)
|
|
|
- {
|
|
|
- auto image = m_queueImage.dequeue();
|
|
|
- if (image)
|
|
|
- {
|
|
|
- delete image;
|
|
|
- }
|
|
|
- }
|
|
|
- m_queueImage.clear();
|
|
|
-
|
|
|
- SPDLOG_DEBUG("开始初始化FFMPEG");
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- int ret = avformat_open_input(&m_pFormatContext, m_fileName.toStdString().c_str(), nullptr, nullptr);
|
|
|
- if(ret != 0)
|
|
|
- {
|
|
|
- SPDLOG_WARN("打开视频文件错误,错误代码:{}",ret);
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- ret = 0;
|
|
|
-
|
|
|
- * 这个会补充avformat_open_input()没有获取到的信息 */
|
|
|
- ret = avformat_find_stream_info(m_pFormatContext, nullptr);
|
|
|
- if(ret < 0)
|
|
|
- {
|
|
|
- SPDLOG_WARN("获取视频流错误,错误代码:{}",ret);
|
|
|
- return;
|
|
|
- }
|
|
|
- m_duration = m_pFormatContext->duration;
|
|
|
- m_currentPos = 0;
|
|
|
- m_startPos = m_pFormatContext->start_time;
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- av_dump_format(m_pFormatContext, 0, m_fileName.toStdString().c_str(), 0);
|
|
|
-
|
|
|
-
|
|
|
- int i = 0;
|
|
|
- AVCodecParameters *pCodecCtxOrig = nullptr;
|
|
|
-
|
|
|
- for(i = 0;i < m_pFormatContext->nb_streams; i++)
|
|
|
- {
|
|
|
- if(m_pFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
|
|
|
- {
|
|
|
- m_videoStream = i;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- if(m_videoStream == -1)
|
|
|
- {
|
|
|
- SPDLOG_WARN("没有找到视频流");
|
|
|
- return;
|
|
|
- }
|
|
|
- SPDLOG_INFO("找到视频流");
|
|
|
-
|
|
|
- pCodecCtxOrig = m_pFormatContext->streams[m_videoStream]->codecpar;
|
|
|
- SPDLOG_INFO("获取视频流参数成功!");
|
|
|
-
|
|
|
- AVCodec *pCodec = nullptr;
|
|
|
-
|
|
|
- pCodec = avcodec_find_decoder(pCodecCtxOrig->codec_id);
|
|
|
- if(pCodec == nullptr)
|
|
|
- {
|
|
|
- SPDLOG_WARN("没有找到解码器");
|
|
|
- return;
|
|
|
- }
|
|
|
- SPDLOG_TRACE("找到解码器");
|
|
|
-
|
|
|
- m_pCodecCtx = avcodec_alloc_context3(pCodec);
|
|
|
- SPDLOG_TRACE("分配空间成功!");
|
|
|
-
|
|
|
- if(avcodec_parameters_to_context(m_pCodecCtx, pCodecCtxOrig) != 0)
|
|
|
- {
|
|
|
- SPDLOG_WARN("复制上下文错误");
|
|
|
- return;
|
|
|
- }
|
|
|
- SPDLOG_INFO("复制上下文成功!");
|
|
|
- if(avcodec_open2(m_pCodecCtx, pCodec, nullptr) < 0)
|
|
|
- {
|
|
|
- SPDLOG_ERROR("打开解码器错误");
|
|
|
- return;
|
|
|
- }
|
|
|
- SPDLOG_TRACE("打开编码器成功!");
|
|
|
-
|
|
|
-
|
|
|
- m_packet = av_packet_alloc();
|
|
|
-
|
|
|
- av_new_packet(m_packet, m_pCodecCtx->width * m_pCodecCtx->height);
|
|
|
-
|
|
|
-
|
|
|
- m_pFrame = av_frame_alloc();
|
|
|
- if(m_pFrame == nullptr)
|
|
|
- {
|
|
|
- SPDLOG_ERROR("创建pFrame错误");
|
|
|
- return;
|
|
|
- }
|
|
|
- m_pFrameRGB = av_frame_alloc();
|
|
|
- if(m_pFrameRGB == nullptr)
|
|
|
- {
|
|
|
- SPDLOG_ERROR("创建pFrameRGB错误");
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- int numBytes = 0;
|
|
|
-
|
|
|
- numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, m_pCodecCtx->width, m_pCodecCtx->height, 1);
|
|
|
- m_buffer = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t));
|
|
|
-
|
|
|
- m_width = m_srcWidth = m_pCodecCtx->width;
|
|
|
- m_height = m_srcHeight = m_pCodecCtx->height;
|
|
|
- m_frameCount = m_pFormatContext->streams[m_videoStream]->nb_frames;
|
|
|
-
|
|
|
-
|
|
|
- av_image_fill_arrays(m_pFrameRGB->data, m_pFrameRGB->linesize, m_buffer, AV_PIX_FMT_RGB24, m_pCodecCtx->width, m_pCodecCtx->height, 1);
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- m_sws_ctx = sws_getContext( m_pCodecCtx->width, m_pCodecCtx->height, m_pCodecCtx->pix_fmt,
|
|
|
- m_srcWidth, m_srcHeight, AV_PIX_FMT_RGB24,
|
|
|
- SWS_BILINEAR,
|
|
|
- nullptr,
|
|
|
- nullptr,
|
|
|
- nullptr);
|
|
|
-
|
|
|
- m_initFFmpeg = true;
|
|
|
- SPDLOG_INFO("FFMPEG初始化完成!");
|
|
|
-
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-void DecodeVedio::unInitFFmpeg()
|
|
|
-{
|
|
|
- stopDecodeVedio();
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-void DecodeVedio::freeFFmpeg()
|
|
|
-{
|
|
|
-
|
|
|
- av_free(m_buffer);
|
|
|
- m_buffer = nullptr;
|
|
|
- av_free(m_pFrameRGB);
|
|
|
- m_pFrameRGB = nullptr;
|
|
|
-
|
|
|
- av_free(m_pFrame);
|
|
|
- m_pFrame = nullptr;
|
|
|
- av_packet_free(&m_packet);
|
|
|
-
|
|
|
-
|
|
|
- avcodec_close(m_pCodecCtx);
|
|
|
-
|
|
|
- avformat_close_input(&m_pFormatContext);
|
|
|
-
|
|
|
- QString m_fileName = QString();
|
|
|
- int m_videoStream = -1;
|
|
|
- m_initFFmpeg = false;
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
- * @brief 进入之后就会一直解码,完成一个帧就会发送新一个信号
|
|
|
- *
|
|
|
- */
|
|
|
-void DecodeVedio::decodeVedio()
|
|
|
-{
|
|
|
- int ret = 0;
|
|
|
- int retFrame = 0;
|
|
|
- int retPacket = 0;
|
|
|
- m_pauseDecode = false;
|
|
|
- m_decodeStatus = true;
|
|
|
- while(m_isRunning)
|
|
|
- {
|
|
|
-
|
|
|
- while(m_pauseDecode)
|
|
|
- {
|
|
|
- m_decodeStatus = false;
|
|
|
- std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
|
|
- }
|
|
|
- m_decodeStatus = true;
|
|
|
-
|
|
|
-
|
|
|
- retPacket = av_read_frame(m_pFormatContext, m_packet);
|
|
|
-
|
|
|
-
|
|
|
- if(retPacket == AVERROR_EOF)
|
|
|
- {
|
|
|
- SPDLOG_INFO("读取到文件末尾...");
|
|
|
- emit signal_playCompleted();
|
|
|
-
|
|
|
- m_pauseDecode = true;
|
|
|
- while(m_pauseDecode)
|
|
|
- {
|
|
|
- m_decodeStatus = false;
|
|
|
- std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
|
|
- }
|
|
|
- }
|
|
|
- else if(retPacket < 0)
|
|
|
- {
|
|
|
- SPDLOG_WARN("读取帧错误...");
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- if(m_packet->stream_index == m_videoStream)
|
|
|
- {
|
|
|
-
|
|
|
- auto tmpPos = m_packet->pts * av_q2d(m_pFormatContext->streams[m_videoStream]->time_base) * AV_TIME_BASE;
|
|
|
-
|
|
|
- if(m_isSeek)
|
|
|
- {
|
|
|
- if( std::abs(m_currentPos - tmpPos) > AV_TIME_BASE)
|
|
|
- {
|
|
|
- SPDLOG_DEBUG("currentPos:{}, tmpPos:{}",m_currentPos,tmpPos);
|
|
|
- av_packet_unref(m_packet);
|
|
|
- continue;
|
|
|
- }
|
|
|
- }
|
|
|
- m_isSeek = false;
|
|
|
- m_currentPos = tmpPos;
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- ret = avcodec_send_packet(m_pCodecCtx, m_packet);
|
|
|
-
|
|
|
- if(ret < 0)
|
|
|
- {
|
|
|
- SPDLOG_ERROR("发送数据包错误...");
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- while (m_isRunning)
|
|
|
- {
|
|
|
-
|
|
|
- retFrame = avcodec_receive_frame(m_pCodecCtx, m_pFrame);
|
|
|
- std::chrono::steady_clock::time_point t5 = std::chrono::steady_clock::now();
|
|
|
-
|
|
|
-
|
|
|
- if (retFrame == 0)
|
|
|
- {
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- sws_scale(m_sws_ctx, (uint8_t const * const *)m_pFrame->data, m_pFrame->linesize, 0, m_pCodecCtx->height,
|
|
|
- m_pFrameRGB->data, m_pFrameRGB->linesize);
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- auto image = new QImage(m_pFrameRGB->data[0], m_width, m_height, QImage::Format_RGB888);
|
|
|
-
|
|
|
- m_mutexQueue.lock();
|
|
|
- if(m_queueImage.count() >= m_queueMaxNum)
|
|
|
- {
|
|
|
-
|
|
|
- m_condQueueNoFull.wait(&m_mutexQueue);
|
|
|
- }
|
|
|
- m_queueImage.enqueue(image);
|
|
|
- m_mutexQueue.unlock();
|
|
|
-
|
|
|
- m_condQueueNoEmpty.wakeAll();
|
|
|
-
|
|
|
- emit signal_oneImage();
|
|
|
-
|
|
|
- retFrame = -1;
|
|
|
- }
|
|
|
- else if(retFrame < 0)
|
|
|
- {
|
|
|
- if( retFrame == AVERROR(EAGAIN) )
|
|
|
- {
|
|
|
-
|
|
|
- }
|
|
|
- else if(retFrame == AVERROR_EOF)
|
|
|
- {
|
|
|
-
|
|
|
- }else
|
|
|
- {
|
|
|
-
|
|
|
- }
|
|
|
- av_frame_unref(m_pFrame);
|
|
|
- break;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- SPDLOG_TRACE("其他错误...{}",retFrame);
|
|
|
- }
|
|
|
- av_frame_unref(m_pFrame);
|
|
|
- }
|
|
|
-
|
|
|
- }else
|
|
|
- {
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- av_packet_unref(m_packet);
|
|
|
- }
|
|
|
-
|
|
|
- freeFFmpeg();
|
|
|
-
|
|
|
- m_mutexQueue.lock();
|
|
|
- int count = m_queueImage.count();
|
|
|
- for (int i = 0; i < count; i++)
|
|
|
- {
|
|
|
- auto image = m_queueImage.dequeue();
|
|
|
- if (image)
|
|
|
- {
|
|
|
- delete image;
|
|
|
- image = nullptr;
|
|
|
- }
|
|
|
- }
|
|
|
- m_mutexQueue.unlock();
|
|
|
-
|
|
|
- m_threadStopped = true;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-void DecodeVedio::exitThread()
|
|
|
-{
|
|
|
- if(m_isRunning)
|
|
|
- {
|
|
|
- m_isRunning = false;
|
|
|
- }
|
|
|
- m_pauseDecode = false;
|
|
|
- m_condQueueNoFull.wakeAll();
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-void DecodeVedio::pauseDecode()
|
|
|
-{
|
|
|
- m_pauseDecode = true;
|
|
|
- while (m_decodeStatus) {
|
|
|
-
|
|
|
- m_condQueueNoFull.wakeAll();
|
|
|
- std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-void DecodeVedio::do_startDecodeVedio()
|
|
|
-{
|
|
|
- SPDLOG_DEBUG("线程ID:{}",QThread::currentThreadId());
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- m_isRunning = true;
|
|
|
- m_threadStopped = false;
|
|
|
- m_pauseDecode = false;
|
|
|
-
|
|
|
- decodeVedio();
|
|
|
- SPDLOG_TRACE("解码线程退出。");
|
|
|
-
|
|
|
-}
|