Forráskód Böngészése

新增支持开关pcm播放功能(减少SDL依赖)

huihui 3 hónapja
szülő
commit
7fe4155b93

+ 1 - 1
CMakeLists.txt

@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 3.13)
 
-# set(PRODUCT_NAME TransCodeIpcAudio)
+# set(PRODUCT_NAME VideoPlayer)
 
 #直接获取cmakelists.txt所在目录名 赋值给PRODUCT_NAME
 get_filename_component(PRODUCT_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME)

+ 11 - 1
module/VideoPlayer/CMakeLists.txt

@@ -1,6 +1,8 @@
 
 cmake_minimum_required(VERSION 3.13)
 
+set(USE_PCM_PLAYER 1)
+
 add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/lib)
 
 file(GLOB_RECURSE ALL_SOURCE
@@ -8,10 +10,18 @@ file(GLOB_RECURSE ALL_SOURCE
         ${CMAKE_CURRENT_SOURCE_DIR}/src/VideoPlayer/*.cpp
         )
 
-message("ALL_SOURCE:"${ALL_SOURCE})
 #排除main.cpp
 list(REMOVE_ITEM ALL_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp)
 
+if (USE_PCM_PLAYER)
+    add_definitions(-DUSE_PCM_PLAYER -DENABLE_SDL)
+else()
+    #排除PcmPlayer
+    list(REMOVE_ITEM ALL_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/src/PcmPlayer/PcmPlayer_SDL.cpp)
+endif()
+
+message("ALL_SOURCE:"${ALL_SOURCE})
+
 # 后来你决定添加新的源代码
 # 使用target_sources添加文件
 target_sources(${PROJECT_NAME} PRIVATE ${ALL_SOURCE})

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

@@ -6,7 +6,9 @@
 
 #include "VideoPlayer.h"
 
+#ifdef USE_PCM_PLAYER
 #include "PcmPlayer/PcmPlayer_SDL.h"
+#endif
 
 #include <stdio.h>
 #include <iostream>
@@ -20,10 +22,10 @@ VideoPlayer::VideoPlayer()
     mIsNeedPause = false;
 
     mVolume = 1;
-
+#ifdef USE_PCM_PLAYER
     m_pcm_player = new PcmPlayer_SDL();
     m_pcm_player->setSpeed(m_speed);
-
+#endif
     this->setSingleMode(true);
 
     m_thread_video = new Thread();
@@ -178,13 +180,17 @@ void VideoPlayer::setAbility(bool video_decode, bool encoded_video_callback, boo
 void VideoPlayer::setMute(bool isMute)
 {
     mIsMute = isMute;
+#ifdef USE_PCM_PLAYER
     m_pcm_player->setMute(isMute);
+#endif
 }
 
 void VideoPlayer::setVolume(float value)
 {
     mVolume = value;
+#ifdef USE_PCM_PLAYER
     m_pcm_player->setVolume(value);
+#endif
 }
 
 uint64_t VideoPlayer::getCurrentTime()
@@ -809,10 +815,10 @@ end:
 fprintf(stderr, "%s:%d mIsVideoThreadFinished=%d mIsAudioThreadFinished=%d \n", __FILE__, __LINE__, mIsVideoThreadFinished, mIsAudioThreadFinished);
         mSleep(10);
     } //确保视频线程结束后 再销毁队列
-
+#ifdef USE_PCM_PLAYER
     m_pcm_player->stopPlay();
     m_pcm_player->clearFrame();
-
+#endif
     if (bsf_ctx)
     {
         av_bsf_free(&bsf_ctx);
@@ -852,7 +858,7 @@ fprintf(stderr, "%s:%d mIsVideoThreadFinished=%d mIsAudioThreadFinished=%d \n",
     avformat_close_input(&pFormatCtx);
     avformat_free_context(pFormatCtx);
 
-    SDL_Quit();
+    // SDL_Quit();
 
     if (mIsReadError && !mIsQuit)
     {
@@ -915,7 +921,9 @@ void VideoPlayer::clearAudioQuene()
         av_packet_unref(&pkt);
     }
     m_audio_pkt_list.clear();
+#ifdef USE_PCM_PLAYER
     m_pcm_player->clearFrame();
+#endif
 }
 
 ///当使用界面类继承了本类之后,以下函数不会执行

+ 2 - 5
module/VideoPlayer/src/VideoPlayer/VideoPlayer.h

@@ -246,12 +246,9 @@ private:
     bool m_enable_audio_play = true; //是否播放音频
     bool m_enable_encoded_audio_callback = false; //是否回调解码之前的音频数据
 
-//    ///本播放器中SDL仅用于播放音频,不用做别的用途
-//    ///SDL播放音频相关
-//    SDL_AudioDeviceID mAudioID;
-//    int openSDL();
-//    void closeSDL();
+#ifdef USE_PCM_PLAYER
     PcmPlayer *m_pcm_player = nullptr;
+#endif
 
     int configure_filtergraph(AVFilterGraph *graph, const char *filtergraph, AVFilterContext *source_ctx, AVFilterContext *sink_ctx);
     int configure_video_filters(AVFilterGraph *graph, const char *vfilters, AVFrame *frame);

+ 6 - 198
module/VideoPlayer/src/VideoPlayer/VideoPlayer_AudioThread.cpp

@@ -186,7 +186,7 @@ void VideoPlayer::decodeAudioThread()
                seek_flag_audio = 0;
            }
         }
-
+#ifdef USE_PCM_PLAYER
         ///直播流为了保证降低延迟,当音频播放队列过大时,会提高播放的采样率
         ///因此,非直播流,不能一次性把所有音频塞入队列,需要限制播放队列中的数据量
         if (!m_is_live_mode)
@@ -196,7 +196,7 @@ void VideoPlayer::decodeAudioThread()
                 mSleep(5);
             }
         }
-
+#endif
         //解码AVPacket->AVFrame
         if (int ret = avcodec_send_packet(aCodecCtx, packet) && ret != 0)
         {
@@ -294,7 +294,7 @@ void VideoPlayer::decodeAudioThread()
                     PCMFramePtr pcmFramePtr = std::make_shared<PCMFrame>();
                     pcmFramePtr->setFrameBuffer(audio_buf, resampled_data_size);
                     pcmFramePtr->setFrameInfo(m_out_sample_rate, audio_tgt_channels, pts_ms);
-
+#ifdef USE_PCM_PLAYER
                     int audio_frame_size = m_pcm_player->inputPCMFrame(pcmFramePtr);
 
                     if (audio_frame_size > 0) //大于0 表示音频播放设备处于打开状态
@@ -302,7 +302,7 @@ void VideoPlayer::decodeAudioThread()
                         // std::lock_guard<std::mutex> lck(m_mutex_audio_clk);
                         audio_clock = m_pcm_player->getCurrentPts();
                     }
-                    
+#endif
 // std::cout<<resampled_data_size<<" "<<audio_frame_size<<" "<<audio_clock<<" "<<pts_ms<<std::endl;
                 }
             }
@@ -310,205 +310,13 @@ void VideoPlayer::decodeAudioThread()
 
         av_packet_unref(packet);
     }
-
+#ifdef USE_PCM_PLAYER
     ///等待播放完成
     while (m_pcm_player->getPcmFrameSize() > 0)
     {
         mSleep(5);
     }
-
+#endif
     mIsAudioThreadFinished = true;
     fprintf(stderr, "%s finished \n", __FUNCTION__);
 }
-
-
-// int VideoPlayer::decodeAudioFrame(bool isBlock)
-// {
-//     int audioBufferSize = 0;
-//     float pts_s = 0.0f; //时间戳(秒)
-
-//     while(1)
-//     {
-//         if (mIsQuit)
-//         {
-//             mIsAudioThreadFinished = true;
-//             clearAudioQuene(); //清空队列
-//             break;
-//         }
-
-//         if (mIsPause == true) //判断暂停
-//         {
-//             break;
-//         }
-
-//         mConditon_Audio->Lock();
-// int audio_list_size = mAudioPacktList.size();
-// //fprintf(stderr, "mAudioPacktList.size()=%d \n", audio_list_size);
-//         // if (mAudioPacktList.size() <= 0)
-//         // {
-//         //     if (isBlock)
-//         //     {
-//         //         mConditon_Audio->Wait();
-//         //     }
-//         //     else
-//         //     {
-//         //         mConditon_Audio->Unlock();
-//         //         break;
-//         //     }
-//         // }
-
-//         AVPacket packet = mAudioPacktList.front();
-//         mAudioPacktList.pop_front();
-// //qDebug()<<__FUNCTION__<<mAudioPacktList.size();
-//         mConditon_Audio->Unlock();
-
-//         AVPacket *pkt = &packet;
-
-//         /* if update, update the audio clock w/pts */
-//         if (packet->pts != AV_NOPTS_VALUE)
-//         {
-//             pts_s = av_q2d(mAudioStream->time_base) * packet->pts;
-//         }
-
-//         //收到这个数据 说明刚刚执行过跳转 现在需要把解码器的数据 清除一下
-//         if(strcmp((char*)packet->data,FLUSH_DATA) == 0)
-//         {
-//             avcodec_flush_buffers(aCodecCtx);
-//             av_packet_unref(pkt);
-//             continue;
-//         }
-
-//         if (seek_flag_audio)
-//         {
-//             //发生了跳转 则跳过关键帧到目的时间的这几帧
-//            if (pts_s < seek_time)
-//            {
-//                continue;
-//            }
-//            else
-//            {
-//                seek_flag_audio = 0;
-//            }
-//         }
-
-//         int got_frame = 0;
-
-//         //解码AVPacket->AVFrame
-//         if (int ret = avcodec_send_packet(aCodecCtx, &packet) && ret != 0)
-//         {
-//            char buffer[1024] = {0};
-//            av_strerror(ret, buffer, 1024);
-//            fprintf(stderr, "input AVPacket to decoder failed! ret = %d %s\n", ret, buffer);
-//         }
-//         else
-//         {
-//             while(1)
-//             {
-//                 int ret = avcodec_receive_frame(aCodecCtx, aFrame);
-//                 if (ret != 0)
-//                 {
-//         //            char buffer[1024] = {0};
-//         //            av_strerror(ret, buffer, 1024);
-//         //            fprintf(stderr, "avcodec_receive_frame = %d %s\n", ret, buffer);
-//                     break;
-//                 }
-
-//                 /* if update, update the audio clock w/pts */
-//                 if (packet.pts != AV_NOPTS_VALUE)
-//                 {
-//                     audio_clock = 1000 * av_q2d(mAudioStream->time_base) * packet.pts;
-//                 }
-
-//                 int out_sample_rate = m_out_sample_rate;
-
-//                 /// ffmpeg解码之后得到的音频数据不是SDL想要的,
-//                 /// 因此这里需要重采样成44100 双声道 AV_SAMPLE_FMT_S16
-
-//                 /// 需要保证重采样后音频的时间是相同的,不同采样率下同样时间采集的数据采样点个数肯定不一样。
-//                 /// 因此就需要重新计算采样点个数(使用下面的函数)
-//                 /// 将in_sample_rate的采样次数换算成out_sample_rate对应的采样次数
-//                 int nb_samples = av_rescale_rnd(swr_get_delay(swrCtx, out_sample_rate) + aFrame->nb_samples, out_sample_rate, m_in_sample_rate, AV_ROUND_UP);
-//     //qDebug()<<swr_get_delay(swrCtx, out_sample_rate) + aFrame->nb_samples<<aFrame->nb_samples<<nb_samples;
-//     //            int nb_samples = av_rescale_rnd(aFrame->nb_samples, out_sample_rate, m_in_sample_rate, AV_ROUND_INF);
-//                 if (aFrame_ReSample != nullptr)
-//                 {
-//                     if (aFrame_ReSample->nb_samples != nb_samples || aFrame_ReSample->sample_rate != out_sample_rate)
-//                     {
-//                         av_frame_free(&aFrame_ReSample);
-//                         aFrame_ReSample = nullptr;
-//                     }
-//                 }
-
-//                 ///解码一帧后才能获取到采样率等信息,因此将初始化放到这里
-//                 if (aFrame_ReSample == nullptr)
-//                 {
-//                     aFrame_ReSample = av_frame_alloc();
-
-//                     aFrame_ReSample->format = out_sample_fmt;
-//                     aFrame_ReSample->channel_layout = out_ch_layout;
-//                     aFrame_ReSample->sample_rate = out_sample_rate;
-//                     aFrame_ReSample->nb_samples = nb_samples;
-
-//                     int ret = av_samples_fill_arrays(aFrame_ReSample->data, aFrame_ReSample->linesize, audio_buf, audio_tgt_channels, aFrame_ReSample->nb_samples, out_sample_fmt, 0);
-//     //                int ret = av_frame_get_buffer(aFrame_ReSample, 0);
-//                     if (ret < 0)
-//                     {
-//                         fprintf(stderr, "Error allocating an audio buffer\n");
-//     //                        exit(1);
-//                     }
-//                 }
-
-//                 ///2024-09-16
-//                 //当重采样的采样率不一致的时候,原先的方法会存在杂音问题,解决方法如下:
-//                 // 1) 如果没有提供足够的空间用于保存输出数据,采样数据会缓存在swr中。可以通过 swr_get_out_samples()来获取下一次调用swr_convert在给定输入样本数量下输出样本数量的上限,来提供足够的空间。
-//                 // 2)如果是采样频率转换,转换完成后采样数据可能会缓存在swr中,它希望你能给它更多的输入数据。
-//                 // 3)如果实际上并不需要更多输入数据,通过调用swr_convert(),其中参数in_count设置为0来获取缓存在swr中的数据。
-//                 // 4)转换结束之后需要冲刷swr_context的缓冲区,通过调用swr_convert(),其中参数in设置为NULL,参数in_count设置为0。
-//                 for(int i=0;i<2;i++)
-//                 {
-//                     ///执行重采样
-//                     int len2;
-
-//                     if (i == 0)
-//                     {
-//                         len2 = swr_convert(swrCtx, aFrame_ReSample->data, aFrame_ReSample->nb_samples, (const uint8_t**)aFrame->data, aFrame->nb_samples);
-//                     }
-//                     else
-//                     {
-//                         len2 = swr_convert(swrCtx, aFrame_ReSample->data, aFrame_ReSample->nb_samples, NULL, 0);
-//                     }
-
-//                     if (len2 <= 0)
-//                     {
-//                         break;
-//                     }
-
-//                     ///必须根据swr_convert实际返回的值计算数据大小
-//                     int resampled_data_size = len2 * audio_tgt_channels * av_get_bytes_per_sample(out_sample_fmt);
-//                     int OneChannelDataSize = resampled_data_size / audio_tgt_channels;
-
-//                     audioBufferSize = resampled_data_size;
-
-//                     PCMFramePtr pcmFramePtr = std::make_shared<PCMFrame>();
-//                     pcmFramePtr->setFrameBuffer(audio_buf, resampled_data_size);
-//                     pcmFramePtr->setFrameInfo(m_out_sample_rate, audio_tgt_channels, pts_s*1000);
-
-//                     int audio_frame_size = m_pcm_player->inputPCMFrame(pcmFramePtr);
-// //qDebug()<<resampled_data_size<<audio_frame_size;
-//                     audio_clock = m_pcm_player->getCurrentPts() / 1000.0;
-//                 }
-
-//                 got_frame = 1;
-//             }
-//         }
-
-//         av_packet_unref(&packet);
-
-//         if (got_frame)
-//         {
-//             break;
-//         }
-//     }
-
-//     return audioBufferSize;
-// }

+ 10 - 2
module/VideoPlayer/src/VideoPlayer/VideoPlayer_VideoThread.cpp

@@ -261,9 +261,17 @@ void VideoPlayer::decodeVideoThread()
                 break;
             }
 
-            if (mAudioStream != NULL && !mIsAudioThreadFinished && !m_pcm_player->deviceOpenFailed())
+            if (mAudioStream != NULL && !mIsAudioThreadFinished 
+#ifdef USE_PCM_PLAYER
+            && !m_pcm_player->deviceOpenFailed()
+#endif
+            )
             {
-                if (mIsReadFinished && m_audio_pkt_list.size() <= 0 && m_pcm_player->getPcmFrameSize() <= 0)
+                if (mIsReadFinished && m_audio_pkt_list.size() <= 0 
+#ifdef USE_PCM_PLAYER
+                && m_pcm_player->getPcmFrameSize() <= 0
+#endif
+                )
                 {//读取完了 且音频数据也播放完了 就剩下视频数据了  直接显示出来了 不用同步了
                     break;
                 }