Browse Source

V0.8.1
1、修改了解码线程函数的一些问题,修复了一些其他bug

Apple 2 days ago
parent
commit
5c3bac313c

+ 2 - 2
demo/OpenGLWidgetLibrary/OpenGLWidgetAPI.cpp

@@ -71,9 +71,9 @@ void refreshYUV420Image(QWidget* widget, Image_YUV420P* yuvData)
         return;
     }
     
-    if(yuvData == nullptr || !yuvData->isValid())
+    if(yuvData == nullptr)
     {
-        SPDLOG_WARN("refreshYUV420Image: yuvData is nullptr or invalid");
+        SPDLOG_WARN("refreshYUV420Image: yuvData is nullptr");
         return;
     }
     

+ 15 - 0
demo/OpenGLWidgetTest/widget.cpp

@@ -56,6 +56,21 @@ void Widget::on_pBtn_play_clicked()
     m_player->play();
 }
 
+void Widget::on_pBtn_playNetwork_clicked()
+{
+    QString url = ui->lineEdit->text();
+    if (url.isEmpty()) {
+        SPDLOG_WARN("未输入网络视频地址");
+        return;
+    }
+    if(!m_player->openPlayVedio(url))
+    {
+        SPDLOG_ERROR("打开网络视频失败: {}", url.toStdString());
+        return;
+    }
+    m_player->play();
+    SPDLOG_INFO("播放网络视频: {}", url.toStdString());
+}
 
 void Widget::resizeEvent(QResizeEvent *event) 
 {

+ 2 - 0
demo/OpenGLWidgetTest/widget.h

@@ -27,6 +27,8 @@ public slots:
 
     void on_pBtn_play_clicked();
 
+    void on_pBtn_playNetwork_clicked();
+
 private slots:
 
 protected:

+ 17 - 0
demo/OpenGLWidgetTest/widget.ui

@@ -55,6 +55,23 @@
         </property>
        </widget>
       </item>
+      <item>
+       <widget class="QLineEdit" name="lineEdit">
+        <property name="minimumSize">
+         <size>
+          <width>240</width>
+          <height>0</height>
+         </size>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QPushButton" name="pBtn_playNetwork">
+        <property name="text">
+         <string>播放网络视频</string>
+        </property>
+       </widget>
+      </item>
       <item>
        <spacer name="horizontalSpacer">
         <property name="orientation">

+ 29 - 18
demo/VideoPlayerLibrary/VideoPlayer/DecodeVedio.cpp

@@ -962,35 +962,40 @@ label_ThreadDecodeExit:
 }
 
 
-/* 对生成的图像进行格式转换,并添加到环形队列中 */
+/**
+ * @brief 对生成的图像进行格式转换,并添加到环形队列中
+ *        1、YUVJ420P格式是全色YUV格式,范围是[0-255],而YUV420P格式是限色YUV格式,范围是[16-235]。
+ *        2、判断视频格式,如果是RGB类型的转换成RGBA格式,如果是yuv类型的,转换成YUVJ420P格式
+ * @param pFrame 
+ */
 void DecodeVedio::convertImageFormatAndPushToQueue(AVFrame* pFrame)
 {
     /* 判断视频帧格式 */
-    if(pFrame->format == AV_PIX_FMT_YUV420P)
+    if((pFrame->format == AV_PIX_FMT_YUV420P) || (pFrame->format == AV_PIX_FMT_YUVJ420P))
     {
-        m_frameFormat = EFrameFormat::Frame_YUV420P;
         /* 是yuv420p格式, */
         Frame_YUV420P* frame = new Frame_YUV420P();
-        convertYUV420PToImage(pFrame, frame->frameData);
+        convertToYUV420P(pFrame, frame->frameData);
         m_queueFrame.push(frame);
-    } else
+        return;
+    }
+
+    /* 判断视频格式,如果是RGB类型的转换成RGBA格式,如果是yuv类型的,转换成YUVJ420P格式 */
+    /* 不是420p,转换成RGBA格式 */
+    Frame_RGBA8888* frame = new Frame_RGBA8888();
+    convertToRGBA(pFrame, frame->frameData);
+    if(frame->frameData == nullptr)
     {
-        /* 不是420p,转换成RGBA格式 */
-        m_frameFormat = EFrameFormat::Frame_RGBA8888;
-        convertToRGBA(pFrame);
-        if(m_buffer != nullptr)
-        {
-            Frame_RGBA8888* frame = new Frame_RGBA8888();
-            /* 将数据拷贝到QImage中 */
-            frame->frameData = new QImage(m_buffer, m_srcSize.width(), m_srcSize.height(), QImage::Format_RGBA8888);
-            /* 如果队列满,线程会阻塞在这里 */
-            m_queueFrame.push(frame);
-        }
+        SPDLOG_ERROR("转换成RGBA格式失败,可能是解码器不支持该格式: {}", av_get_pix_fmt_name((AVPixelFormat)pFrame->format));
+        delete frame;  /* 释放空间 */
+        return;
     }
+    /* 如果队列满,线程会阻塞在这里 */
+    m_queueFrame.push(frame);
 }
 
 /* 将yuv420p的uint8_t数组缓存转换成Image_YUV420P结构体 */
-void DecodeVedio::convertYUV420PToImage(AVFrame* pFrame, Image_YUV420P* image)
+void DecodeVedio::convertToYUV420P(AVFrame* pFrame, Image_YUV420P* image)
 {
     if(pFrame == nullptr || image == nullptr)
     {
@@ -1010,7 +1015,7 @@ void DecodeVedio::convertYUV420PToImage(AVFrame* pFrame, Image_YUV420P* image)
 }
 
 /* 转换成RGBA格式 */
-void DecodeVedio::convertToRGBA(AVFrame* pFrame)
+void DecodeVedio::convertToRGBA(AVFrame* pFrame, QImage* image)
 {
     /* 转换解码后的帧格式,转换成RGBA格式,Qt可以识别 */
     if(m_sws_ctx == nullptr)
@@ -1047,6 +1052,12 @@ void DecodeVedio::convertToRGBA(AVFrame* pFrame)
                 pFrame->height,         /* 处理的行数(通常为图像高度) */
                 &m_buffer,              /* 目标图像数据指针数组(packed格式只用[0]) */
                 lines);                 /* 目标图像每行字节数数组 */
+    if(m_buffer != nullptr)
+    {
+        /* 将数据拷贝到QImage中 */
+        *image = QImage(m_buffer, m_srcSize.width(), m_srcSize.height(), QImage::Format_RGBA8888);
+    }
+    
 }
 
 /* 暂停解码,会阻塞到线程暂停为止 */

+ 3 - 3
demo/VideoPlayerLibrary/VideoPlayer/DecodeVedio.h

@@ -114,9 +114,9 @@ private:
     /* 对生成的图像进行格式转换,并添加到环形队列中 */
     inline void convertImageFormatAndPushToQueue(AVFrame* pFrame);
     /* 将yuv420p的uint8_t数组缓存转换成Image_YUV420P结构体 */
-    inline void convertYUV420PToImage(AVFrame* pFrame, Image_YUV420P* image);
+    inline void convertToYUV420P(AVFrame* pFrame, Image_YUV420P* image);
     /* 转换成RGBA格式 */
-    inline void convertToRGBA(AVFrame* pFrame);
+    inline void convertToRGBA(AVFrame* pFrame, QImage* image);
     /* 退出线程 */      
     void exitThread();
     /* 暂停解码 */
@@ -172,7 +172,7 @@ private:
     qint64 m_currentFrame = 0;                      /* 当前已播放的帧数 */
     QString m_decoderName;                          /* 解码器名称 */
 
-    EFrameFormat m_frameFormat = EFrameFormat::Frame_YUV420P; /* 视频帧格式,默认是YUV420P */
+    // EFrameFormat m_frameFormat = EFrameFormat::Frame_YUV420P; /* 视频帧格式,默认是YUV420P */
     RingQueue<FrameBase*> m_queueFrame;             /* 环形队列,存储生成的图像 */
 };
 

+ 2 - 2
demo/VideoPlayerLibrary/VideoPlayer/FrameFormat.cpp

@@ -20,7 +20,7 @@ Frame_YUV420P::~Frame_YUV420P()
     }
 }
 
-Frame_RGBA8888::Frame_RGBA8888()
+Frame_RGBA8888::Frame_RGBA8888() : FrameBase(EFrameFormat::Frame_RGBA8888)
 {
     frameData = new QImage();
 }
@@ -39,7 +39,7 @@ bool deleteOneFrame(FrameBase* frame)
 {
     if(frame == nullptr)
     {
-        SPDLOG_WARN("传入的帧指针为空,无法删除");
+        SPDLOG_DEBUG("传入的帧指针为空,无法删除");
         return false;
     }
     if(frame->frameFormat() == EFrameFormat::Frame_YUV420P)

+ 19 - 6
demo/VideoPlayerLibrary/VideoPlayer/VideoPlayer.cpp

@@ -105,13 +105,13 @@ bool VideoPlayer::openPlayVedio(const QString& fileName)
         return false;
     }
     m_fileName = fileName;
-    m_isOpenFile = true;
     m_isLocalFile = isLocalFile(fileName);
 
     if(!m_decodeVedio->openVedio(fileName))
     {
         return false;
     }
+    m_isOpenFile = true;
     /* 获取原始视频信息 */
     m_srcWidth = m_decodeVedio->getSrcVideoSize().width();
     m_srcHeight = m_decodeVedio->getSrcVideoSize().height();
@@ -535,16 +535,18 @@ void VideoPlayer::refreshFrame(FrameBase* frame)
 
     if(m_image->frameFormat() == EFrameFormat::Frame_RGBA8888)
     {
-        QImage* rgbaImage = static_cast<Frame_RGBA8888*>(m_image)->frameData;
-        if(rgbaImage != nullptr && !rgbaImage->isNull())
+        // SPDLOG_INFO("刷新一帧,RGBA8888格式的图片");
+        auto rgbaImage = static_cast<Frame_RGBA8888*>(m_image);
+        if(rgbaImage != nullptr && rgbaImage->frameData != nullptr)
         {
-            refreshRGBAImage(m_playWidget, *rgbaImage);
+            refreshRGBAImage(m_playWidget, *rgbaImage->frameData);
         }else {
             SPDLOG_WARN("刷新一帧,RGBA图片为空");
         }
     }
     else if(m_image->frameFormat() == EFrameFormat::Frame_YUV420P)
     {
+        // SPDLOG_INFO("刷新一帧,YUV420P格式的图片");
         /* YUV420P格式的图片 */
         Frame_YUV420P* yuvImage = static_cast<Frame_YUV420P*>(m_image);
         if(yuvImage != nullptr && yuvImage->frameData != nullptr)
@@ -578,7 +580,13 @@ void VideoPlayer::do_refreshUI()
     if(m_decodeVedio != nullptr)
     {
         // SPDLOG_DEBUG("取出一帧图片...");
-        refreshFrame(m_decodeVedio->getOneImage());
+        auto image = m_decodeVedio->getOneImage();
+        if(image == nullptr)
+        {
+            SPDLOG_DEBUG("没有取到图片,可能是解码器没有解码完毕,或者视频播放完毕");
+            return;
+        }
+        refreshFrame(image);
     }
 }
 
@@ -650,7 +658,12 @@ void VideoPlayer::do_playCompleted()
             // }
             // // SPDLOG_DEBUG("绘制画面...");
             // refreshRGBAImage(m_playWidget, *m_image);
-            refreshFrame(m_decodeVedio->getOneImage());
+            auto image = m_decodeVedio->getOneImage();
+            if(image == nullptr)
+            {
+                break;
+            }
+            refreshFrame(image);
         }
     }
     m_playStatus = false;