Sfoglia il codice sorgente

V2.1.3

1.修复上个版本加入FunctionTransfer类引起的播放器停止出现死锁,导致卡死的问题
2.修复部分电脑SDL打开失败的问题。
3.修复部分音频文件播放快速播放完毕的问题。
huihui 5 anni fa
parent
commit
d26225bfb9

BIN
bin32/VideoPlayer.exe


+ 8 - 0
module/VideoPlayer/src/VideoPlayer/Audio/VideoPlayer_AudioThread.cpp

@@ -151,6 +151,11 @@ int VideoPlayer::decodeAudioFrame(bool isBlock)
         int got_frame = 0;
         int size = avcodec_decode_audio4(aCodecCtx, aFrame, &got_frame, &packet);
 
+//保存重采样之前的一个声道的数据方法
+//size_t unpadded_linesize = aFrame->nb_samples * av_get_bytes_per_sample((AVSampleFormat) aFrame->format);
+//static FILE * fp = fopen("out.pcm", "wb");
+//fwrite(aFrame->extended_data[0], 1, unpadded_linesize, fp);
+
         av_packet_unref(&packet);
 
         if (got_frame)
@@ -160,7 +165,10 @@ int VideoPlayer::decodeAudioFrame(bool isBlock)
             if (aFrame_ReSample == NULL)
             {
                 aFrame_ReSample = av_frame_alloc();
+            }
 
+            if (aFrame_ReSample->nb_samples != aFrame->nb_samples)
+            {
                 aFrame_ReSample->nb_samples = av_rescale_rnd(swr_get_delay(swrCtx, out_sample_rate) + aFrame->nb_samples,
                             out_sample_rate, in_sample_rate, AV_ROUND_UP);
 

+ 16 - 5
module/VideoPlayer/src/VideoPlayer/VideoPlayer.cpp

@@ -35,11 +35,12 @@ bool VideoPlayer::initPlayer()
     av_register_all(); //初始化FFMPEG  调用了这个才能正常使用编码器和解码器
     avformat_network_init(); //支持打开网络文件
 
-    if (SDL_Init(SDL_INIT_AUDIO))
-    {
-        fprintf(stderr, "Could not initialize SDL - %s. \n", SDL_GetError());
-        return false;
-    }
+//SDL初始化需要放入子线程中,否则有些电脑会有问题。
+//    if (SDL_Init(SDL_INIT_AUDIO))
+//    {
+//        fprintf(stderr, "Could not initialize SDL - %s. \n", SDL_GetError());
+//        return false;
+//    }
 
     return true;
 }
@@ -211,6 +212,14 @@ void VideoPlayer::closeSDL()
 
 void VideoPlayer::readVideoFile()
 {
+    ///SDL初始化需要放入子线程中,否则有些电脑会有问题。
+    if (SDL_Init(SDL_INIT_AUDIO))
+    {
+        doOpenSdlFailed(-100);
+        fprintf(stderr, "Could not initialize SDL - %s. \n", SDL_GetError());
+        return;
+    }
+
     mIsReadThreadFinished = false;
     mIsReadFinished = false;
 
@@ -595,6 +604,8 @@ end:
     avformat_close_input(&pFormatCtx);
     avformat_free_context(pFormatCtx);
 
+    SDL_Quit();
+
     doPlayerStateChanged(VideoPlayer_Stop, mVideoStream != nullptr, mAudioStream != nullptr);
 
     mIsReadThreadFinished = true;

+ 1 - 1
src/AppConfig.cpp

@@ -43,7 +43,7 @@ void Sleep(long mSeconds)
 
 QString AppConfig::APPID = "{a1db97ad-b8ed-11e9-a297-0235d2b38928}";
 int AppConfig::VERSION = 1;
-QString AppConfig::VERSION_NAME = "2.1.2";
+QString AppConfig::VERSION_NAME = "2.1.3";
 
 MainWindow *AppConfig::gMainWindow = NULL;
 QRect AppConfig::gMainWindowRect;

+ 36 - 8
src/Base/FunctionTransfer.cpp

@@ -6,10 +6,16 @@
 Qt::HANDLE FunctionTransfer::gMainThreadId = nullptr;
 FunctionTransfer *FunctionTransfer::main_thread_forward = nullptr;
 
+Q_DECLARE_METATYPE(std::function<void()>)
+
 FunctionTransfer::FunctionTransfer(QObject *parent) :
     QObject(parent)
 {
-    connect(this, SIGNAL(comming(std::function<void()>)), this, SLOT(exec(std::function<void()>)), Qt::BlockingQueuedConnection);
+    //因为std::function<void()>是自定义的类型 要跨线程传递需要先注册一下
+    qRegisterMetaType<std::function<void()>>();
+
+    connect(this, SIGNAL(comming(std::function<void()>)), this, SLOT(slotExec(std::function<void()>)), Qt::BlockingQueuedConnection);
+    connect(this, SIGNAL(comming_noBlock(std::function<void()>)), this, SLOT(slotExec(std::function<void()>)), Qt::QueuedConnection);
 }
 
 FunctionTransfer::~FunctionTransfer()
@@ -41,20 +47,42 @@ bool FunctionTransfer::isMainThread()
     }
 }
 
-void FunctionTransfer::runInMainThread(std::function<void()> f)
-{
-    FunctionTransfer::main_thread_forward->exec(f);
-}
-
-void FunctionTransfer::exec(std::function<void()> f)
+void FunctionTransfer::runInMainThread(std::function<void()> f, bool isBlock)
 {
+//    FunctionTransfer::main_thread_forward->exec(f, isBlock);
     if(FunctionTransfer::isMainThread())
     {
         f();
     }
     else
     {
-        Q_EMIT this->comming(f);
+        if (isBlock)
+        {
+            Q_EMIT FunctionTransfer::main_thread_forward->comming(f);
+        }
+        else
+        {
+            Q_EMIT FunctionTransfer::main_thread_forward->comming_noBlock(f);
+        }
     }
+}
 
+void FunctionTransfer::slotExec(std::function<void()> f)
+{
+    f();
+//    if(FunctionTransfer::isMainThread())
+//    {
+//        f();
+//    }
+//    else
+//    {
+//        if (isBlock)
+//        {
+//            Q_EMIT this->comming(f);
+//        }
+//        else
+//        {
+//            Q_EMIT this->comming_noBlock(f);
+//        }
+//    }
 }

+ 4 - 3
src/Base/FunctionTransfer.h

@@ -26,7 +26,7 @@ public:
 
 public:
     ///@brief 制定函数f在main中执行
-    static void runInMainThread(std::function<void()> f);
+    static void runInMainThread(std::function<void()> f, bool isBlock = false);
 
 private:
     static Qt::HANDLE gMainThreadId;
@@ -37,10 +37,11 @@ private:
 Q_SIGNALS:
     ///@brief 在别的线程有函数对象传来
     void comming(std::function<void()> f);
+    void comming_noBlock(std::function<void()> f);
 
-public Q_SLOTS:
+private Q_SLOTS:
     ///@brief 执行函数对象
-    void exec(std::function<void()> f);
+    void slotExec(std::function<void()> f);
 
 };
 

+ 4 - 4
src/MainWindow.cpp

@@ -231,7 +231,7 @@ void MainWindow::slotBtnClick(bool isChecked)
 ///打开文件失败
 void MainWindow::onOpenVideoFileFailed(const int &code)
 {
-    FunctionTransfer::runInMainThread([&]()
+    FunctionTransfer::runInMainThread([=]()
     {
         QMessageBox::critical(NULL, "tips", QString("open file failed %1").arg(code));
     });
@@ -240,7 +240,7 @@ void MainWindow::onOpenVideoFileFailed(const int &code)
 ///打开SDL失败的时候回调此函数
 void MainWindow::onOpenSdlFailed(const int &code)
 {
-    FunctionTransfer::runInMainThread([&]()
+    FunctionTransfer::runInMainThread([=]()
     {
         QMessageBox::critical(NULL, "tips", QString("open Sdl failed %1").arg(code));
     });
@@ -249,7 +249,7 @@ void MainWindow::onOpenSdlFailed(const int &code)
 ///获取到视频时长的时候调用此函数
 void MainWindow::onTotalTimeChanged(const int64_t &uSec)
 {
-    FunctionTransfer::runInMainThread([&]()
+    FunctionTransfer::runInMainThread([=]()
     {
         qint64 Sec = uSec/1000000;
 
@@ -267,7 +267,7 @@ void MainWindow::onTotalTimeChanged(const int64_t &uSec)
 ///播放器状态改变的时候回调此函数
 void MainWindow::onPlayerStateChanged(const VideoPlayerState &state, const bool &hasVideo, const bool &hasAudio)
 {
-    FunctionTransfer::runInMainThread([&]()
+    FunctionTransfer::runInMainThread([=]()
     {
         if (state == VideoPlayer_Stop)
         {