Browse Source

V0.2.10
1、拷贝了最新的VideoPlayer

Apple 6 months ago
parent
commit
d92a980dd1

+ 118 - 71
common/VedioPlayer/DecodeVedio.cpp → common/VideoPlayer/DecodeVedio.cpp

@@ -76,18 +76,17 @@ void DecodeVedio::stopDecodeVedio()
     {
         return;
     }
+    
     m_isRunning = false;
-    m_fileName = QString();
+    m_pauseDecode = false;
+    /* 唤醒阻塞住的解码线程 */
+    m_condQueueNoFull.wakeAll();
     // /* 等待线程执行结束 */
-    // while(true)
-    // {
-    //     if(m_threadStopped)
-    //     {
-    //         break;
-    //     }
-    //     /* 睡眠10ms */
-    //     std::this_thread::sleep_for(std::chrono::milliseconds(10));
-    // }
+    while(!m_threadStopped)
+    {
+        /* 睡眠10ms */
+        std::this_thread::sleep_for(std::chrono::milliseconds(10));
+    }
     
 }
 
@@ -102,12 +101,22 @@ void DecodeVedio::setCurrentPos(quint64 pos)
     
     /* 暂停解码 */
     m_pauseDecode = true;
-    /* 去掉队列中已有的图片数目对应的时长 */
-    int queueNumFPS = m_queueImage.count() * 1000.0 / m_fps;
+    // SPDLOG_DEBUG("setCurrentPos threadID:{}",QThread::currentThreadId());
+    while (m_decodeStatus) {
+        /* 需要唤醒阻塞住的线程 */
+        m_condQueueNoFull.wakeAll();
+        std::this_thread::sleep_for(std::chrono::milliseconds(1));
+    }
+    m_isSeek = true;
+    /* 去掉队列中已有的图片数目对应的时长,单位是us */
+    int queueNumFPS = m_queueImage.count() * ( 1000.0f / m_fps ) * 1000 ;
     qint64 target_pos = m_startPos + pos - queueNumFPS;
+    m_currentPos = target_pos;
     SPDLOG_DEBUG("设置播放位置:{}",target_pos);
     /* 第二个参数设置为-1,表示所有流都跳转 */
     int ret = av_seek_frame(m_pFormatContext, -1, target_pos, AVSEEK_FLAG_BACKWARD);
+    /* 清空缓存 */
+    avcodec_flush_buffers(m_pCodecCtx);
     if(ret < 0)
     {
         SPDLOG_WARN("跳转失败...");
@@ -253,14 +262,24 @@ int DecodeVedio::getFrameCount()
 
     return m_fps;
 }
-
+/**
+ * @brief 设置图像宽度和高度
+ *        注意:目前不好用,建议使用Qt的图片缩放
+ * 
+ * @param width 
+ * @param height 
+ */
 void DecodeVedio::setVideoSize(int width, int height)
 {
     m_width = width;
     m_height = height;
 
-    /* 重新初始化缩放参数 */
-    // sws_freeContext(m_sws_ctx);
+    if(m_sws_ctx != nullptr)
+    {
+        /* 先暂停解码器 */
+        pauseDecode();
+        sws_freeContext(m_sws_ctx);
+    }
     /* 初始化Sws Context,这是转换规则,转换成RGB */
     m_sws_ctx = sws_getContext( m_pCodecCtx->width, m_pCodecCtx->height, m_pCodecCtx->pix_fmt,    /* 原图像大小和格式 */
                                 m_width, m_height, AV_PIX_FMT_RGB24,      /* 目标图像的大小和格式 */
@@ -273,29 +292,11 @@ void DecodeVedio::setVideoSize(int width, int height)
 /* 初始化函数 */
 void DecodeVedio::initFFmpeg(const QString& fileName)
 {
-    if(fileName != m_fileName)
-    {
-        m_fileName = fileName;
-        if(m_initFFmpeg)
-        {
-            freeFFmpeg();
-        }
-    }else 
+    if(m_initFFmpeg)
     {
-        /* 清空队列 */
-        int size = m_queueImage.count();
-        for(int i = 0; i < size; i++)
-        {
-            auto image = m_queueImage.dequeue();
-            if (image)
-            {
-                delete image;
-            }
-                
-        }
-        m_queueImage.clear();
         return;
     }
+    m_fileName = fileName;
     /* 清空队列 */
     int size = m_queueImage.count();
     for(int i = 0; i < size; i++)
@@ -305,7 +306,6 @@ void DecodeVedio::initFFmpeg(const QString& fileName)
         {
             delete image;
         }
-            
     }
     m_queueImage.clear();
 
@@ -389,7 +389,8 @@ void DecodeVedio::initFFmpeg(const QString& fileName)
 
     /******** 读取数据(解码数据) ********/
     m_packet = av_packet_alloc();
-    av_init_packet(m_packet);
+    // av_init_packet(m_packet);
+    av_new_packet(m_packet, m_pCodecCtx->width * m_pCodecCtx->height);
 
     /********* 创建两个pFrame,一个存放原始数据,一个存放转换后的RGB数据 **********/
     m_pFrame = av_frame_alloc();
@@ -410,8 +411,8 @@ void DecodeVedio::initFFmpeg(const QString& fileName)
     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_pCodecCtx->width;
-    m_height = m_pCodecCtx->height;
+    m_width = m_srcWidth = m_pCodecCtx->width;
+    m_height = m_srcHeight = m_pCodecCtx->height;
     m_frameCount = m_pFormatContext->streams[m_videoStream]->nb_frames;
     
     /* 这个函数的实际作用是将buffer设置给pFrameRGB作为原始数据的内存区域 */
@@ -421,7 +422,7 @@ void DecodeVedio::initFFmpeg(const QString& fileName)
     
     /* 初始化Sws Context,这是转换规则,转换成RGB */
     m_sws_ctx = sws_getContext( m_pCodecCtx->width, m_pCodecCtx->height, m_pCodecCtx->pix_fmt,    /* 原图像大小和格式 */
-                                m_width, m_height, AV_PIX_FMT_RGB24,      /* 目标图像的大小和格式 */
+                                m_srcWidth, m_srcHeight, AV_PIX_FMT_RGB24,      /* 目标图像的大小和格式 */
                                 SWS_BILINEAR,           /* 双线性 */
                                 nullptr, 
                                 nullptr, 
@@ -433,6 +434,15 @@ void DecodeVedio::initFFmpeg(const QString& fileName)
     // avcodec_parameters_free(&pCodecCtxOrig);
 }
 
+
+/* 取消ffmpeg初始化函数 */
+void DecodeVedio::unInitFFmpeg()
+{
+    stopDecodeVedio();
+}
+
+
+
 /* 取消ffmpeg初始化函数 */
 void DecodeVedio::freeFFmpeg()
 {
@@ -453,7 +463,7 @@ void DecodeVedio::freeFFmpeg()
 
     QString m_fileName = QString();
     int m_videoStream = -1;                         /* 记录视频流是第几个流 */
-    bool m_initFFmpeg = false;
+    m_initFFmpeg = false;
     
 }
 
@@ -466,35 +476,62 @@ 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));
         }
-        std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+        m_decodeStatus = true;
+        // std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
         /* 读取一帧压缩码流,如果使用多线程解码,就从这里分发数据流的包 */
         retPacket = av_read_frame(m_pFormatContext, m_packet);
-        std::chrono::steady_clock::time_point t2 = std::chrono::steady_clock::now();
+        // std::chrono::steady_clock::time_point t2 = std::chrono::steady_clock::now();
         // SPDLOG_TRACE("======================================= 读取数据包耗时(us):{}",std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count());
         if(retPacket == AVERROR_EOF)
         {
             SPDLOG_INFO("读取到文件末尾...");
-            break;
+            emit signal_playCompleted();
+            /* 暂停解码 */
+            m_pauseDecode = true;
+            while(m_pauseDecode)
+            {
+                m_decodeStatus = false;
+                std::this_thread::sleep_for(std::chrono::milliseconds(5));
+            }
         }
-        if(retPacket < 0)
+        else if(retPacket < 0)
         {
             SPDLOG_WARN("读取帧错误...");
             break;
         }
+        
         /* 判断是否是视频帧 */
         if(m_packet->stream_index == m_videoStream)
         {
-            std::chrono::steady_clock::time_point t3 = std::chrono::steady_clock::now();
+            /* 现在的位置,转换成时间,乘上AV_TIME_BASE后,单位是微秒 */
+            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;
+            // SPDLOG_DEBUG("======== 当前位置:{} ========",m_currentPos);
+            // std::chrono::steady_clock::time_point t3 = std::chrono::steady_clock::now();
             /* 解码视频帧,现在使用新的API */
             ret  = avcodec_send_packet(m_pCodecCtx, m_packet);
-            std::chrono::steady_clock::time_point t4 = std::chrono::steady_clock::now();
+            // std::chrono::steady_clock::time_point t4 = std::chrono::steady_clock::now();
             if(ret < 0)
             {
                 SPDLOG_ERROR("发送数据包错误...");
@@ -507,30 +544,19 @@ void DecodeVedio::decodeVedio()
                 retFrame = avcodec_receive_frame(m_pCodecCtx, m_pFrame);
                 std::chrono::steady_clock::time_point t5 = std::chrono::steady_clock::now();
                 // SPDLOG_TRACE("======================================= 接收帧耗时:{}",std::chrono::duration_cast<std::chrono::milliseconds>(t5 - t4).count());
-                if(retFrame == AVERROR(EAGAIN) || retFrame == AVERROR_EOF)
-                {
-                    // SPDLOG_TRACE("没有更多的帧可以输出,跳出循环。");
-                    break;
-                }
-                if(retFrame < 0)
-                {
-                    SPDLOG_ERROR("解码错误...");
-                    break;
-                }
+                
                 if (retFrame == 0)
                 {
-                    /* 现在的位置,转换成时间,乘上AV_TIME_BASE后,单位是微秒 */
-                    m_currentPos = m_pFrame->pts * av_q2d(m_pFormatContext->streams[m_videoStream]->time_base) * AV_TIME_BASE;
-                    SPDLOG_DEBUG("======== 当前位置:{} ========",m_currentPos);
                     /* 成功接收到一帧,处理解码后的帧 */
-                    std::chrono::steady_clock::time_point t6 = std::chrono::steady_clock::now();
+                    // std::chrono::steady_clock::time_point t6 = std::chrono::steady_clock::now();
                     /* 将帧转换为RGB */
                     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);
-                    std::chrono::steady_clock::time_point t7 = std::chrono::steady_clock::now();
+                    // std::chrono::steady_clock::time_point t7 = std::chrono::steady_clock::now();
                     // SPDLOG_TRACE("======================================= 转换RGB耗时:{}",std::chrono::duration_cast<std::chrono::milliseconds>(t7 - t6).count());
                     /* 一帧图像入队 */
                     auto image = new QImage(m_pFrameRGB->data[0], m_width, m_height, QImage::Format_RGB888);
+                    // SPDLOG_DEBUG("队列中图片个数:{} ",m_queueImage.count());
                     m_mutexQueue.lock();
                     if(m_queueImage.count() >= m_queueMaxNum)
                     {
@@ -543,20 +569,30 @@ void DecodeVedio::decodeVedio()
                     m_condQueueNoEmpty.wakeAll();
                     /* 同时发送信号 */
                     emit signal_oneImage();
-                } 
-                else if (retFrame == AVERROR(EAGAIN) || ret == AVERROR_EOF) 
+
+                    retFrame = -1;
+                }
+                else if(retFrame < 0)
                 {
-                    // 没有更多的帧可以输出,跳出循环
+                    if( retFrame == AVERROR(EAGAIN) )
+                    {
+                        // SPDLOG_TRACE("在此状态下输出不可用-用户必须尝试发送新的输入...");
+                    }
+                    else if(retFrame == AVERROR_EOF)
+                    {
+                        // SPDLOG_TRACE("读取到文件末尾...");
+                    }else
+                    {
+                        // SPDLOG_TRACE("其他解码错误...{}",retFrame);
+                    }
+                    av_frame_unref(m_pFrame);
                     break;
-                } 
-                else if (retFrame < 0)
+                }
+                else
                 {
-                    SPDLOG_TRACE("解码错误...");
-                    av_packet_unref(m_packet);
-                    break;
+                    SPDLOG_TRACE("其他错误...{}",retFrame);
                 }
                 av_frame_unref(m_pFrame);
-                retFrame = -1;
             }
             
         }else
@@ -596,6 +632,17 @@ void DecodeVedio::exitThread()
     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()

+ 18 - 5
common/VedioPlayer/DecodeVedio.h → common/VideoPlayer/DecodeVedio.h

@@ -36,6 +36,9 @@ public:
 
     // void setFileName(const QString& fileName) { m_fileName = fileName; }
     void initFFmpeg(const QString& fileName);       /* 初始化函数 */
+    void unInitFFmpeg();                            /* 取消ffmpeg初始化函数 */
+    bool isInitFFmpeg() { return m_initFFmpeg; }     /* 获取ffmpeg初始化状态 */
+    
     void startDecodeVedio();                        /* 开始解码视频,开始前先设置视频名称 */
     void stopDecodeVedio();                         /* 停止解码视频,也是停止线程 */
     void setCurrentPos(quint64 pos);                /* 设置当前播放位置 */
@@ -47,17 +50,23 @@ public:
     QImage* getOneImage();                          /* 获取一帧图像 */
     QImage* getOneImageUntilHave();                 /* 获取一帧图像,直到有图像为止 */
 
-    int getFrameCount();                            /* 获取帧数 */
-    int getVideoWidth() const {return m_width;}     /* 获取图像宽度 */
-    int getVideoHeight() const {return m_height;}   /* 获取图像高度 */
-    void setVideoSize(int width,int height);        /* 设置图像宽度和高度 */
+    /* 获取帧数 */
+    int getFrameCount();                            
+    /* 获取图像宽度 */
+    int getSrcVideoWidth() const {return m_srcWidth;}
+    /* 获取图像高度 */
+    int getSrcVideoHeight() const {return m_srcHeight;}
+    /* 设置图像宽度和高度 */
+    void setVideoSize(int width,int height);
 
 signals:
     void signal_oneImage();                         /* 一帧图像信号 */
+    void signal_playCompleted();                    /* 播放完成信号 */
 private:
     void freeFFmpeg();                              /* 取消ffmpeg初始化函数 */
     void decodeVedio();                             /* 解码视频的工作函数,这个就是新线程 */
     void exitThread();                              /* 退出线程 */
+    void pauseDecode();                             /* 暂停解码 */
 
 private slots:
     void do_startDecodeVedio();                     /* 开启解码 */
@@ -69,6 +78,8 @@ private:
     std::atomic_bool m_initFFmpeg = false;          /* ffmpeg初始化标志 */
     std::atomic_bool m_threadStopped = false;       /* 停止线程 */
     std::atomic_bool m_pauseDecode = false;         /* 暂停解码 */
+    std::atomic_bool m_decodeStatus = false;        /* 解码状态,这里主要是检测是否暂停解码 */
+    std::atomic_bool m_isSeek = false;              /* 是否跳转 */
 
     QString m_fileName;                             /* 解码的视频文件名称 */
     AVFormatContext *m_pFormatContext = nullptr;    /* 格式上下文,贯穿全局 */
@@ -80,6 +91,8 @@ private:
     uint8_t *m_buffer = nullptr;                    /* 存储解码后的一帧数据,RGB格式 */
     int m_videoStream = -1;                         /* 记录视频流是第几个流 */
 
+    int m_srcWidth = 0;                             /* 图片原本宽度 */
+    int m_srcHeight = 0;                            /* 图片原本高度 */
     int m_width = 0;                                /* 图像宽度 */
     int m_height = 0;                               /* 图像高度 */
     int m_frameCount = 0;                           /* 帧数 */
@@ -89,7 +102,7 @@ private:
     qint64 m_startPos = 0;                          /* 起始位置,后续操作都需要在这各基础上操作 */
 
     // QImage *m_image = nullptr;
-    int m_queueMaxNum = 30;                         /* 这里不是环形队列,最大设置为30帧图像 */
+    int m_queueMaxNum = 10;                         /* 这里不是环形队列,最大设置为30帧图像 */
     QQueue<QImage*> m_queueImage;                   /* 视频帧队列 */
     QMutex m_mutexQueue;                            /* 队列互斥锁 */
     QWaitCondition m_condQueueNoFull;               /* 队列不满,可以入队 */

+ 119 - 21
common/VedioPlayer/VideoPlayer.cpp → common/VideoPlayer/VideoPlayer.cpp

@@ -24,6 +24,7 @@ VideoPlayer::VideoPlayer(QWidget *parent) : QWidget(parent)
     connect(&m_timerRefreshUI, &QTimer::timeout, this, &VideoPlayer::do_refreshUI);
 
     connect(m_decodeVedio, &DecodeVedio::signal_oneImage, this, &VideoPlayer::do_refreshOneUI);
+    connect(m_decodeVedio, &DecodeVedio::signal_playCompleted, this, &VideoPlayer::do_playCompleted);
     SPDLOG_TRACE("UI线程ID:{}", QThread::currentThreadId());
 }
 
@@ -49,17 +50,25 @@ VideoPlayer::~VideoPlayer()
  */
 void VideoPlayer::setPlayVedio(const QString& fileName)
 {
+    if(isSetVedioFile)
+    {
+        isSetVedioFile = false;
+    }
+    if(m_decodeVedio->isInitFFmpeg())
+    {
+        m_decodeVedio->unInitFFmpeg();
+    }
     m_fileName = fileName;
     isSetVedioFile = true;
     m_decodeVedio->initFFmpeg(m_fileName);
+    // m_decodeVedio->setVideoSize(this->width(), this->height());
     /* 获取原始视频信息 */
-    m_srcWidth = m_decodeVedio->getVideoWidth();
-    m_srcHeight = m_decodeVedio->getVideoHeight();
+    m_srcWidth = m_decodeVedio->getSrcVideoWidth();
+    m_srcHeight = m_decodeVedio->getSrcVideoHeight();
     m_frameCount = m_decodeVedio->getFrameCount();
     SPDLOG_DEBUG("视频宽:{} 高:{} 帧数:{}", m_srcWidth, m_srcHeight, m_frameCount);
     /* 设置视频宽和高的最小大小 */
     this->setMinimumSize(160,90);
-
     /* 开启定时器刷新 */
     if(m_frameCount < 0)
     {
@@ -80,7 +89,7 @@ void VideoPlayer::setPlayVedio(const QString& fileName)
 
     /* 开启解码,手动刷新第一帧 */
     m_decodeVedio->startDecodeVedio();
-    m_semRefresh->release(1);
+    m_semRefresh->release(2);
     // m_timerRefreshUI.setSingleShot(true);
     // m_timerRefreshUI.start(500);
 }
@@ -123,24 +132,27 @@ void VideoPlayer::pause()
     m_playStatus = false;
 }
 
-/* 停止播放,停止后停止解码,清空队列,渲染一帧黑屏 */
+/* 停止播放,停止后停止解码,将时间等复位到开始时间 */
 void VideoPlayer::stop()
 {
     SPDLOG_DEBUG("...停止播放...");
-    m_fileName = QString();
+    // m_fileName = QString();
     if(m_timerRefreshUI.isActive())
     {
         m_timerRefreshUI.stop();
     }
-    SPDLOG_DEBUG("...停止解码...");
-    m_decodeVedio->stopDecodeVedio();
+    // SPDLOG_DEBUG("...停止解码...");
+    
+    /* 重新设置播放视频 */
+    setPlayVedio(m_fileName);
+
     /* 绘制黑帧 */
-    SPDLOG_DEBUG("绘制黑帧");
-    m_image = new QImage(m_nowWidth, m_nowHeight, QImage::Format_RGB32);
-    m_image->fill(Qt::black);
-    update();
+    // SPDLOG_DEBUG("绘制黑帧");
+    // m_image = new QImage(m_nowWidth, m_nowHeight, QImage::Format_RGB32);
+    // m_image->fill(Qt::black);
+    // update();
     m_playStatus = false;
-    isSetVedioFile = false;
+    // isSetVedioFile = false;
 }
 
 /* 获取视频时长 */
@@ -169,23 +181,77 @@ void VideoPlayer::setCurrentPos(quint64 pos)
     /* 继续播放 */
     if(temp)
     {
+        // SPDLOG_INFO("..........开启定时器..........");
         m_timerRefreshUI.start(m_interval);
         m_playStatus = true;
     }else
     {
-        /* 刷新10张照片,防止第一张是跳转前的时间段 */
-        m_semRefresh->release(10);
+        /* 刷新5张照片,防止第一张是跳转前的时间段 */
+        m_semRefresh->release(5);
     }
 }
 
+/* 设置播放视频大小 */
+void VideoPlayer::setPlayVedioSize(int width,int height)
+{
+    /* 对宽和高就行缩放,保持比例,同时将其居中放置
+     * 先计算出比例,和16/9相对比
+     * 大于16/9,以高为最大极限,计算出宽度和x坐标
+     * 小于16/9,以宽为最大极限,计算出高度和y坐标 */
+    double srcRatio = m_srcWidth*1.0 / m_srcHeight;
+    double ratio = width*1.0 / height;
+    long w1 = 0, h1 = 0;
+    int srcX = this->pos().rx(), srcY = this->pos().ry();
+    int x1 = srcX, y1 = srcY;
+    if(ratio > srcRatio)
+    {
+        w1 = height * srcRatio;
+        x1 = (width - w1) / 2;
+        h1 = height;
+        y1 = srcY;
+    }
+    else if(ratio < srcRatio)
+    {
+        h1 = width / srcRatio;
+        y1 = (height - h1) / 2;
+        w1 = width;
+        x1 = srcX;
+    }else {
+        w1 = width;
+        h1 = height;
+        x1 = srcX;
+        y1 = srcY;
+    }
+    this->move(x1, y1);
+    
+    m_nowWidth = w1;
+    m_nowHeight = h1;
+    this->resize(w1, h1);
+    // SPDLOG_DEBUG("设置窗口位置:{}x{}, 大小:{}x{}, 传入大小:{}x{}", x1, y1, w1, h1, width, height);
+    SPDLOG_DEBUG("现在位置和大小:{}x{}, {}x{}", this->pos().rx(), this->pos().ry(), this->width(), this->height());
+}
+
+/* 设置播放回调函数 */
+void VideoPlayer::setPlayCallBack(std::function<Play_CallBack> playCallBack,void* context)
+{
+    m_funcPlayCB = playCallBack;
+    m_context = context;
+}
+
 
 void VideoPlayer::paintEvent(QPaintEvent *event)
 {
     if(m_image)
     {
         // SPDLOG_TRACE("开始绘制画面...");
+        /* 对图像进行缩放 */
+        QImage image;
+        if(m_srcWidth != m_nowWidth || m_srcHeight != m_nowHeight)
+        {
+            image = m_image->scaled(m_nowWidth, m_nowHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation);
+        }
         QPainter painter(this);
-        painter.drawImage(0, 0, *m_image);
+        painter.drawImage(0, 0, image);
     }
 }
 
@@ -195,6 +261,9 @@ void VideoPlayer::resizeEvent(QResizeEvent *event)
     m_nowWidth = event->size().width();
     m_nowHeight = event->size().height();
 
+    /* 传递给解码器 */
+    // m_decodeVedio->setVideoSize(m_nowWidth, m_nowHeight);
+
     QWidget::resizeEvent(event);
 }
 
@@ -215,10 +284,10 @@ void VideoPlayer::refreshOneUIUntilHave()
         
         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);
-            }
+            // 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();
         }
@@ -226,6 +295,22 @@ void VideoPlayer::refreshOneUIUntilHave()
     }
 }
 
+
+/* 双击事件函数 */
+void VideoPlayer::mouseDoubleClickEvent(QMouseEvent *event)
+{
+    if(event->button() == Qt::LeftButton)
+    {
+        // SPDLOG_DEBUG("双击事件...");
+        if(m_funcPlayCB != nullptr)
+        {
+            m_funcPlayCB(this, 5, nullptr, 0, m_context);
+        }else {
+            SPDLOG_INFO("没有设置回调函数");
+        }
+    }
+}
+
 /* 取出画面,刷新UI */
 void VideoPlayer::do_refreshUI()
 {
@@ -279,11 +364,24 @@ void VideoPlayer::do_refreshOneUI()
             {
                 *m_image = m_image->scaled(m_nowWidth, m_nowHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation);
             }
-            // SPDLOG_DEBUG("绘制画面...");
+            SPDLOG_DEBUG("绘制预览画面...");
             update();
         }
         m_decodeVedio->wakeUpCondQueueNoEmpty();
     }
 }
 
+/* 播放完成 */
+void VideoPlayer::do_playCompleted()
+{
+    SPDLOG_INFO("播放完成...");
+    m_timerRefreshUI.stop();
+    m_playStatus = false;
+    if(m_funcPlayCB != nullptr)
+    {
+        /* 播放完成的回调函数 */
+        m_funcPlayCB(this, 2, nullptr, 0, m_context);
+    }
+}
+
 

+ 10 - 1
common/VedioPlayer/VideoPlayer.h → common/VideoPlayer/VideoPlayer.h

@@ -6,6 +6,8 @@
 #include <QTimer>
 #include <QSemaphore>
 
+#include "globalInfo.h"
+
 class DecodeVedio;
 
 class VideoPlayer : public QWidget
@@ -23,16 +25,20 @@ public:
     qint64 getDuration();                           /* 获取视频时长 */
     qint64 getCurrentPos();                         /* 获取当前播放位置 */
     void setCurrentPos(quint64 pos);                /* 设置当前播放位置 */
+    void setPlayVedioSize(int width,int height);    /* 设置播放视频大小 */
 
-
+    void setPlayCallBack(std::function<Play_CallBack> playCallBack,void* context);  /* 设置播放回调函数 */
 protected:
     void paintEvent(QPaintEvent *event) override;
     void resizeEvent(QResizeEvent *event) override;
     void refreshOneUIUntilHave();                   /* 刷新一张图片,直到有图片为止 */
+    /* 双击事件函数 */
+    void mouseDoubleClickEvent(QMouseEvent *event) override;
 
 private slots:
     void do_refreshUI();                            /* 取出画面,刷新UI */
     void do_refreshOneUI();                         /* 通过信号刷新第一张图片 */
+    void do_playCompleted();                        /* 播放完成 */
 
 private:
     QString m_fileName;
@@ -50,6 +56,9 @@ private:
     bool m_playStatus = false;                      /* 是否正在播放 */
     bool isSetVedioFile = false;                    /* 是否设置了视频文件 */
     QSemaphore* m_semRefresh = nullptr;             /* 刷新信号量 */
+
+    std::function<Play_CallBack> m_funcPlayCB = nullptr;  /* 播放回调函数 */
+    void* m_context = nullptr;                      /* 上下文 */
 };