zhuizhu 8 месяцев назад
Родитель
Сommit
3b242daffa

+ 56 - 37
AV/code/player/audio_output.cpp

@@ -5,6 +5,8 @@
 #include <QDebug>
 #include <algorithm>
 #include <cstring>
+#include <thread>
+#include <chrono>
 
 extern "C" {
 #include <libavutil/channel_layout.h>
@@ -243,16 +245,6 @@ void AudioOutput::start()
     
     av::Logger::instance().debug("Audio device entered active state");
     
-    // 初始化并启动Synchronizer
-    if (!m_synchronizer) {
-        av::utils::SyncConfigV2 syncConfig;
-        syncConfig.syncStrategy = av::utils::SyncStrategy::AUDIO_MASTER;
-        syncConfig.audioSyncThreshold = 0.04;  // 40ms,与AVPlayer2一致
-        syncConfig.videoSyncThreshold = 0.04;
-        m_synchronizer = std::make_shared<av::utils::SynchronizerV2>(syncConfig);
-        m_synchronizer->initialize();
-        m_synchronizer->start();
-    }
     m_playing = true;
     av::Logger::instance().info("Audio output started successfully");
 }
@@ -269,11 +261,6 @@ void AudioOutput::stop()
     m_audioDevice = nullptr;
     m_playing = false;
     
-    // 停止Synchronizer
-    if (m_synchronizer) {
-        m_synchronizer->stop();
-    }
-    
     av::Logger::instance().info("Audio output stopped");
 }
 
@@ -350,16 +337,18 @@ bool AudioOutput::writeFrame(const AVFramePtr& frame)
     
     // 使用Synchronizer进行时间同步
     if (frame->pts != AV_NOPTS_VALUE && m_synchronizer) {
-        // 计算音频PTS(转换为秒)
-        double audioPts = (double)frame->pts / AV_TIME_BASE;
+        // 使用原始PTS值和时间基准
+        int64_t audioPts = frame->pts;
+        double timeBase = 1.0 / AV_TIME_BASE;  // 假设使用AV_TIME_BASE作为时间基准
         
         // 更新音频时钟
-        m_synchronizer->setAudioClock(audioPts);
+        m_synchronizer->setAudioClock(audioPts, timeBase);
         
         // 计算同步延迟
         double delay = 0.0;
-        ErrorCode result = m_synchronizer->shouldPlayAudioFrame(audioPts).action == av::utils::FrameAction::DISPLAY ? ErrorCode::SUCCESS : ErrorCode::PROCESSING_ERROR;
-        delay = m_synchronizer->shouldPlayAudioFrame(audioPts).delay;
+        auto decision = m_synchronizer->shouldPlayAudioFrame(audioPts, timeBase);
+        ErrorCode result = decision.action == av::utils::FrameAction::DISPLAY ? ErrorCode::SUCCESS : ErrorCode::PROCESSING_ERROR;
+        delay = decision.delay;
         
         if (result == ErrorCode::SUCCESS && delay > 0) {
             // 应用播放速度控制
@@ -373,7 +362,7 @@ bool AudioOutput::writeFrame(const AVFramePtr& frame)
             }
         }
         
-        m_lastAudioPts = audioPts;
+        m_lastAudioPts = audioPts * timeBase;  // 转换为秒用于记录
     }
     
     // 转换音频帧格式
@@ -386,25 +375,48 @@ bool AudioOutput::writeFrame(const AVFramePtr& frame)
     // 应用音量控制
     applyVolume(audioData);
     
-    // 写入音频设备 - 添加异常处理
-    try {
-        qint64 bytesWritten = m_audioDevice->write(audioData);
-        if (bytesWritten != audioData.size()) {
-            av::Logger::instance().warning("Audio write incomplete: " + 
+    // 写入音频设备 - 添加重试机制和异常处理
+    const int maxRetries = 10;
+    const int retryDelayMs = 5;
+    
+    for (int retry = 0; retry < maxRetries; ++retry) {
+        try {
+            qint64 bytesWritten = m_audioDevice->write(audioData);
+            if (bytesWritten == audioData.size()) {
+                av::Logger::instance().debug("Audio frame written successfully: " + 
+                    std::to_string(audioData.size()) + " bytes");
+                return true;
+            }
+            
+            // 写入不完整,记录警告并重试
+            av::Logger::instance().warning("Audio write incomplete (attempt " + 
+                std::to_string(retry + 1) + "/" + std::to_string(maxRetries) + "): " + 
                 std::to_string(bytesWritten) + "/" + std::to_string(audioData.size()));
-            return false;
+            
+            // 如果不是最后一次重试,等待一段时间再重试
+            if (retry < maxRetries - 1) {
+                std::this_thread::sleep_for(std::chrono::milliseconds(retryDelayMs));
+            }
+            
+        } catch (const std::exception& e) {
+            av::Logger::instance().error("Exception during audio write (attempt " + 
+                std::to_string(retry + 1) + "): " + std::string(e.what()));
+            
+            if (retry < maxRetries - 1) {
+                std::this_thread::sleep_for(std::chrono::milliseconds(retryDelayMs));
+            }
+        } catch (...) {
+            av::Logger::instance().error("Unknown exception during audio write (attempt " + 
+                std::to_string(retry + 1) + ")");
+            
+            if (retry < maxRetries - 1) {
+                std::this_thread::sleep_for(std::chrono::milliseconds(retryDelayMs));
+            }
         }
-        
-        av::Logger::instance().debug("Audio frame written successfully: " + 
-            std::to_string(audioData.size()) + " bytes");
-        return true;
-    } catch (const std::exception& e) {
-        av::Logger::instance().error("Exception during audio write: " + std::string(e.what()));
-        return false;
-    } catch (...) {
-        av::Logger::instance().error("Unknown exception during audio write");
-        return false;
     }
+    
+    av::Logger::instance().error("Audio write failed after " + std::to_string(maxRetries) + " attempts");
+    return false;
 }
 
 void AudioOutput::setVolume(double volume)
@@ -463,6 +475,13 @@ bool AudioOutput::isPlaying() const
     return m_playing;
 }
 
+void AudioOutput::setSynchronizer(std::shared_ptr<av::utils::SynchronizerV2> synchronizer)
+{
+    QMutexLocker locker(&m_mutex);
+    m_synchronizer = synchronizer;
+    av::Logger::instance().info("Audio output synchronizer set");
+}
+
 void AudioOutput::onStateChanged(QAudio::State state)
 {
     switch (state) {

+ 6 - 0
AV/code/player/audio_output.h

@@ -110,6 +110,12 @@ public:
      */
     bool isPlaying() const;
 
+    /**
+     * 设置同步器
+     * @param synchronizer 外部同步器实例
+     */
+    void setSynchronizer(std::shared_ptr<av::utils::SynchronizerV2> synchronizer);
+
 private slots:
     void onStateChanged(QAudio::State state);
 

+ 151 - 78
AV/code/player/player_core_v2.cpp

@@ -50,10 +50,17 @@ PlayerCoreV2::PlayerCoreV2(const SyncConfigV2& syncConfig)
             return;
         }
         
-        // 创建队列
-        m_packetQueue = av::utils::PacketQueueFactory::createStandardQueue(2000);  // 增加队列大小
-        if (!m_packetQueue) {
-            Logger::instance().error("Failed to create packet queue");
+        // 创建分离的视频和音频包队列
+        m_videoPacketQueue = av::utils::PacketQueueFactory::createStandardQueue(1000);  // 视频包队列
+        if (!m_videoPacketQueue) {
+            Logger::instance().error("Failed to create video packet queue");
+            setState(PlayerState::Error);
+            return;
+        }
+        
+        m_audioPacketQueue = av::utils::PacketQueueFactory::createStandardQueue(1000);  // 音频包队列
+        if (!m_audioPacketQueue) {
+            Logger::instance().error("Failed to create audio packet queue");
             setState(PlayerState::Error);
             return;
         }
@@ -85,7 +92,7 @@ PlayerCoreV2::PlayerCoreV2(const SyncConfigV2& syncConfig)
             handleSyncError(error, reason);
         });
         
-        m_synchronizer->setFrameDropCallback([this](av::utils::ClockType type, double pts) {
+        m_synchronizer->setFrameDropCallback([this](av::utils::ClockType type, int64_t pts) {
             std::lock_guard<std::mutex> lock(m_mutex);
             m_stats.droppedFrames++;
             if (m_eventCallback) {
@@ -190,12 +197,8 @@ ErrorCode PlayerCoreV2::openFile(const std::string& filename) {
         return ErrorCode::CODEC_OPEN_FAILED;
     }
     
-    // 初始化同步器
-    if (m_synchronizer->initialize() != ErrorCode::SUCCESS) {
-        Logger::instance().error("Failed to initialize synchronizer");
-        setState(PlayerState::Error);
-        return ErrorCode::SYNC_ERROR;
-    }
+    // 注意:同步器的初始化已经在openMediaFile()中完成,这里不需要重复调用
+    // 因为initialize()会重新选择主时钟,可能覆盖之前设置的流信息
     
     setState(PlayerState::Stopped);
     
@@ -376,7 +379,8 @@ ErrorCode PlayerCoreV2::stop() {
     resetDecoders();
     
     // 清空队列
-    if (m_packetQueue) m_packetQueue->clear();
+    if (m_videoPacketQueue) m_videoPacketQueue->clear();
+    if (m_audioPacketQueue) m_audioPacketQueue->clear();
     if (m_videoFrameQueue) m_videoFrameQueue->clear();
     if (m_audioFrameQueue) m_audioFrameQueue->clear();
     
@@ -463,7 +467,8 @@ PlaybackStats PlayerCoreV2::getStats() const {
     stats.currentTime = getCurrentTime();
     
     // 更新队列大小
-    if (m_packetQueue) stats.queuedPackets = m_packetQueue->size();
+    if (m_videoPacketQueue) stats.queuedPackets += m_videoPacketQueue->size();
+    if (m_audioPacketQueue) stats.queuedPackets += m_audioPacketQueue->size();
     if (m_videoFrameQueue) stats.queuedVideoFrames = m_videoFrameQueue->size();
     if (m_audioFrameQueue) stats.queuedAudioFrames = m_audioFrameQueue->size();
     
@@ -705,6 +710,13 @@ bool PlayerCoreV2::openMediaFile(const std::string& filename) {
         m_synchronizer->setStreamInfo(m_mediaInfo.hasAudio, m_mediaInfo.hasVideo);
         Logger::instance().info("Synchronizer stream info set: hasAudio=" + std::to_string(m_mediaInfo.hasAudio) + 
                                ", hasVideo=" + std::to_string(m_mediaInfo.hasVideo));
+        
+        // 在设置流信息后初始化同步器,确保主时钟选择基于正确的流信息
+        if (m_synchronizer->initialize() != ErrorCode::SUCCESS) {
+            Logger::instance().error("Failed to initialize synchronizer");
+            return false;
+        }
+        Logger::instance().info("Synchronizer initialized with correct stream info");
     }
     
     Logger::instance().info("Media file opened successfully: " + filename);
@@ -832,6 +844,12 @@ bool PlayerCoreV2::setupAudioDecoder() {
         return false;
     }
     
+    // 设置音频输出的同步器
+    if (m_audioOutput && m_synchronizer) {
+        m_audioOutput->setSynchronizer(std::shared_ptr<SynchronizerV2>(m_synchronizer.get(), [](SynchronizerV2*) {}));
+        Logger::instance().info("Audio output synchronizer set");
+    }
+    
     // 释放解码器上下文
     avcodec_free_context(&codecContext);
     
@@ -1067,7 +1085,8 @@ void PlayerCoreV2::stopAllThreads() {
 }
 
 void PlayerCoreV2::flushBuffers() {
-    if (m_packetQueue) m_packetQueue->clear();
+    if (m_videoPacketQueue) m_videoPacketQueue->clear();
+    if (m_audioPacketQueue) m_audioPacketQueue->clear();
     if (m_videoFrameQueue) m_videoFrameQueue->clear();
     if (m_audioFrameQueue) m_audioFrameQueue->clear();
 }
@@ -1110,7 +1129,9 @@ void PlayerCoreV2::readThreadFunc() {
         }
         
         // 检查队列是否已满
-        if (m_packetQueue && m_packetQueue->size() > 1000) {
+        bool videoQueueFull = m_videoPacketQueue && m_videoPacketQueue->size() > 500;
+        bool audioQueueFull = m_audioPacketQueue && m_audioPacketQueue->size() > 500;
+        if (videoQueueFull && audioQueueFull) {
             std::this_thread::sleep_for(std::chrono::milliseconds(10));
             continue;
         }
@@ -1121,16 +1142,26 @@ void PlayerCoreV2::readThreadFunc() {
             if (ret == AVERROR_EOF) {
                 Logger::instance().info("End of file reached, sending EOF packets to queues");
                 
-                // 向队列发送EOF标记,让解码线程知道文件结束
-                if (m_packetQueue) {
-                    // 创建EOF标记包
+                // 向视频和音频队列分别发送EOF标记,让解码线程知道文件结束
+                if (m_videoPacketQueue && m_mediaInfo.hasVideo) {
                     AVPacket* eofPacket = av_packet_alloc();
                     if (eofPacket) {
                         eofPacket->data = nullptr;
                         eofPacket->size = 0;
                         eofPacket->stream_index = -1; // 特殊标记表示EOF
-                        m_packetQueue->push(eofPacket);
-                        Logger::instance().info("EOF packet sent to queue");
+                        m_videoPacketQueue->push(eofPacket);
+                        Logger::instance().info("EOF packet sent to video queue");
+                    }
+                }
+                
+                if (m_audioPacketQueue && m_mediaInfo.hasAudio) {
+                    AVPacket* eofPacket = av_packet_alloc();
+                    if (eofPacket) {
+                        eofPacket->data = nullptr;
+                        eofPacket->size = 0;
+                        eofPacket->stream_index = -1; // 特殊标记表示EOF
+                        m_audioPacketQueue->push(eofPacket);
+                        Logger::instance().info("EOF packet sent to audio queue");
                     }
                 }
                 break;
@@ -1141,14 +1172,23 @@ void PlayerCoreV2::readThreadFunc() {
             }
         }
         
-        // 将数据包放入队列
-        if (packet->stream_index == m_mediaInfo.videoStreamIndex ||
-            packet->stream_index == m_mediaInfo.audioStreamIndex) {
-            
-            if (m_packetQueue) {
+        // 根据流索引将数据包分发到对应队列
+        if (packet->stream_index == m_mediaInfo.videoStreamIndex) {
+            // 视频包放入视频队列
+            if (m_videoPacketQueue && (!videoQueueFull || m_videoPacketQueue->size() < 500)) {
                 AVPacket* packetCopy = av_packet_alloc();
                 if (packetCopy && av_packet_ref(packetCopy, packet) == 0) {
-                    m_packetQueue->push(packetCopy);
+                    m_videoPacketQueue->push(packetCopy);
+                } else {
+                    av_packet_free(&packetCopy);
+                }
+            }
+        } else if (packet->stream_index == m_mediaInfo.audioStreamIndex) {
+            // 音频包放入音频队列
+            if (m_audioPacketQueue && (!audioQueueFull || m_audioPacketQueue->size() < 500)) {
+                AVPacket* packetCopy = av_packet_alloc();
+                if (packetCopy && av_packet_ref(packetCopy, packet) == 0) {
+                    m_audioPacketQueue->push(packetCopy);
                 } else {
                     av_packet_free(&packetCopy);
                 }
@@ -1168,15 +1208,15 @@ void PlayerCoreV2::videoDecodeThreadFunc() {
     int packetCount = 0;
     int frameCount = 0;
     while (!m_threadsShouldStop) {
-        if (!m_packetQueue || !m_videoFrameQueue || !m_videoDecoder) {
+        if (!m_videoPacketQueue || !m_videoFrameQueue || !m_videoDecoder) {
             std::this_thread::sleep_for(std::chrono::milliseconds(10));
             continue;
         }
         
-        // 从包队列获取视频
+        // 从视频包队列获取包
         AVPacket* packet = nullptr;
         while (!m_threadsShouldStop && !packet) {
-            packet = m_packetQueue->pop();
+            packet = m_videoPacketQueue->pop();
             if (packet) {
                 // 检查是否是EOF标记
                 if (packet->stream_index == -1 && packet->data == nullptr) {
@@ -1200,13 +1240,6 @@ void PlayerCoreV2::videoDecodeThreadFunc() {
                     Logger::instance().info("Video decode thread finishing due to EOF");
                     return;
                 }
-                
-                if (packet->stream_index != m_mediaInfo.videoStreamIndex) {
-                    Logger::instance().debug("Skipping non-video packet, stream_index=" + std::to_string(packet->stream_index) + 
-                                            ", expected=" + std::to_string(m_mediaInfo.videoStreamIndex));
-                    av_packet_free(&packet);
-                    packet = nullptr;
-                }
             }
             if (!packet) {
                 std::this_thread::sleep_for(std::chrono::milliseconds(5));
@@ -1240,12 +1273,9 @@ void PlayerCoreV2::videoDecodeThreadFunc() {
                                             ", height=" + std::to_string(framePtr->height) + 
                                             ", pts=" + std::to_string(framePtr->pts));
                     
-                    // 设置帧的时间戳
+                    // 设置帧的时间戳(保持原始PTS,在播放时再转换)
                     if (framePtr->pts != AV_NOPTS_VALUE) {
-                        AVStream* stream = m_formatContext->streams[m_mediaInfo.videoStreamIndex];
-                        double pts = framePtr->pts * av_q2d(stream->time_base) * 1000000; // 转换为微秒
-                        framePtr->pts = static_cast<int64_t>(pts);
-                        Logger::instance().debug("Frame PTS converted to: " + std::to_string(framePtr->pts) + " microseconds");
+                        Logger::instance().debug("Frame PTS: " + std::to_string(framePtr->pts));
                     }
                     
                     // 将帧放入队列
@@ -1276,15 +1306,15 @@ void PlayerCoreV2::audioDecodeThreadFunc() {
     int packetCount = 0;
     int frameCount = 0;
     while (!m_threadsShouldStop) {
-        if (!m_packetQueue || !m_audioFrameQueue || !m_audioDecoder) {
+        if (!m_audioPacketQueue || !m_audioFrameQueue || !m_audioDecoder) {
             std::this_thread::sleep_for(std::chrono::milliseconds(10));
             continue;
         }
         
-        // 从包队列获取音频
+        // 从音频包队列获取包
         AVPacket* packet = nullptr;
         while (!m_threadsShouldStop && !packet) {
-            packet = m_packetQueue->pop();
+            packet = m_audioPacketQueue->pop();
             if (packet) {
                 // 检查是否是EOF标记
                 if (packet->stream_index == -1 && packet->data == nullptr) {
@@ -1307,13 +1337,6 @@ void PlayerCoreV2::audioDecodeThreadFunc() {
                     Logger::instance().info("Audio decode thread finishing due to EOF");
                     return;
                 }
-                
-                if (packet->stream_index != m_mediaInfo.audioStreamIndex) {
-                    Logger::instance().debug("Skipping non-audio packet, stream_index=" + std::to_string(packet->stream_index) + 
-                                            ", expected=" + std::to_string(m_mediaInfo.audioStreamIndex));
-                    av_packet_free(&packet);
-                    packet = nullptr;
-                }
             }
             if (!packet) {
                 std::this_thread::sleep_for(std::chrono::milliseconds(5));
@@ -1346,12 +1369,9 @@ void PlayerCoreV2::audioDecodeThreadFunc() {
                                             ", nb_samples=" + std::to_string(framePtr->nb_samples) + 
                                             ", pts=" + std::to_string(framePtr->pts));
                     
-                    // 设置帧的时间戳
+                    // 设置帧的时间戳(保持原始PTS,在播放时再转换)
                     if (framePtr->pts != AV_NOPTS_VALUE) {
-                        AVStream* stream = m_formatContext->streams[m_mediaInfo.audioStreamIndex];
-                        double pts = framePtr->pts * av_q2d(stream->time_base) * 1000000; // 转换为微秒
-                        framePtr->pts = static_cast<int64_t>(pts);
-                        Logger::instance().debug("Frame PTS converted to: " + std::to_string(framePtr->pts) + " microseconds");
+                        Logger::instance().debug("Audio Frame PTS: " + std::to_string(framePtr->pts));
                     }
                     
                     // 将帧放入队列
@@ -1399,13 +1419,25 @@ void PlayerCoreV2::videoPlayThreadFunc() {
         
         Logger::instance().debug("Video play thread got frame, pts=" + std::to_string(frame->pts));
         
-        // 更新视频时钟
+        // 获取视频流的时间基准
+        double timeBase = 0.0;
         if (frame->pts != AV_NOPTS_VALUE) {
-            m_synchronizer->setVideoClock(frame->pts / 1000000.0); // 转换为秒
+            AVStream* videoStream = m_formatContext->streams[m_mediaInfo.videoStreamIndex];
+            timeBase = av_q2d(videoStream->time_base);
         }
         
-        // 检查是否应该显示这一帧
-        auto decision = m_synchronizer->shouldDisplayVideoFrame(frame->pts / 1000000.0);
+        // 检查是否应该显示这一帧 (直接传递原始PTS和时间基准)
+        auto decision = m_synchronizer->shouldDisplayVideoFrame(frame->pts, timeBase);
+        
+        // 记录视频帧决策日志
+        Logger::instance().debug("Video frame decision: action=" + std::to_string(static_cast<int>(decision.action)) + 
+                                ", delay=" + std::to_string(decision.delay) + 
+                                ", syncError=" + std::to_string(decision.syncError));
+        
+        // 只有在决定显示帧时才更新视频时钟
+        if (decision.action == av::utils::FrameAction::DISPLAY && frame->pts != AV_NOPTS_VALUE) {
+            m_synchronizer->setVideoClock(frame->pts, timeBase);
+        }
         
         // 创建智能指针管理帧内存
         AVFramePtr framePtr(frame);
@@ -1417,10 +1449,13 @@ void PlayerCoreV2::videoPlayThreadFunc() {
                     m_openGLVideoRenderer->Render(framePtr.get());
                 }
                 
-                // 计算下一帧的延迟
+                // 计算下一帧的延迟 - 使用FFmpeg的精确延迟
                 if (decision.delay > 0) {
-                    auto delayMs = static_cast<int>(decision.delay * 1000);
-                    std::this_thread::sleep_for(std::chrono::milliseconds(delayMs));
+                    // 限制最大延迟时间,避免异常情况
+                    const double MAX_DELAY = 0.1;  // 100ms
+                    double actualDelay = std::min(decision.delay, MAX_DELAY);
+                    int delayUs = static_cast<int>(actualDelay * 1000000);
+                    av_usleep(delayUs);
                 }
                 break;
                 
@@ -1437,11 +1472,15 @@ void PlayerCoreV2::videoPlayThreadFunc() {
                 break;
                 
             case av::utils::FrameAction::DELAY:
-                // 延迟显示
-                auto delayMs = static_cast<int>(decision.delay * 1000);
-                std::this_thread::sleep_for(std::chrono::milliseconds(delayMs));
-                if (m_openGLVideoRenderer) {
-                    m_openGLVideoRenderer->Render(framePtr.get());
+                // 延迟显示 - 使用FFmpeg的精确延迟
+                {
+                    const double MAX_DELAY = 0.1;  // 100ms
+                    double actualDelay = std::min(decision.delay, MAX_DELAY);
+                    int delayUs = static_cast<int>(actualDelay * 1000000);
+                    av_usleep(delayUs);
+                    if (m_openGLVideoRenderer) {
+                        m_openGLVideoRenderer->Render(framePtr.get());
+                    }
                 }
                 break;
         }
@@ -1491,13 +1530,24 @@ void PlayerCoreV2::audioPlayThreadFunc() {
                                 ", pts=" + std::to_string(frame->pts) + 
                                 ", nb_samples=" + std::to_string(frame->nb_samples));
         
-        // 更新音频时钟
+        // 获取音频流的时间基准
+        double timeBase = 0.0;
         if (frame->pts != AV_NOPTS_VALUE) {
-            m_synchronizer->setAudioClock(frame->pts / 1000000.0); // 转换为秒
+            AVStream* audioStream = m_formatContext->streams[m_mediaInfo.audioStreamIndex];
+            timeBase = av_q2d(audioStream->time_base);
+            
+            // 添加调试信息
+            Logger::instance().debug("Audio PTS info: pts=" + std::to_string(frame->pts) + 
+                                   ", time_base=" + std::to_string(timeBase));
         }
         
-        // 检查是否应该播放这一帧
-        auto decision = m_synchronizer->shouldPlayAudioFrame(frame->pts / 1000000.0);
+        // 检查是否应该播放这一帧 (直接传递原始PTS和时间基准)
+        auto decision = m_synchronizer->shouldPlayAudioFrame(frame->pts, timeBase);
+        
+        // 只有在决定播放帧时才更新音频时钟
+        if (decision.action == av::utils::FrameAction::DISPLAY && frame->pts != AV_NOPTS_VALUE) {
+            m_synchronizer->setAudioClock(frame->pts, timeBase);
+        }
         
         Logger::instance().debug("Audio frame decision: action=" + std::to_string(static_cast<int>(decision.action)) + 
                                 ", delay=" + std::to_string(decision.delay));
@@ -1512,12 +1562,20 @@ void PlayerCoreV2::audioPlayThreadFunc() {
                     Logger::instance().debug("Writing audio frame to output device");
                     bool writeResult = m_audioOutput->writeFrame(framePtr);
                     Logger::instance().debug("Audio frame write result: " + std::to_string(writeResult));
+                    
+                    // 如果写入失败,等待一段时间避免快速循环
+                    if (!writeResult) {
+                        Logger::instance().warning("Audio frame write failed, waiting before next frame");
+                        std::this_thread::sleep_for(std::chrono::milliseconds(10));
+                    }
                 }
                 
-                // 如果需要延迟
+                // 如果需要延迟 - 使用FFmpeg的精确延迟
                 if (decision.delay > 0) {
-                    auto delayMs = static_cast<int>(decision.delay * 1000);
-                    std::this_thread::sleep_for(std::chrono::milliseconds(delayMs));
+                    const double MAX_DELAY = 0.1;  // 100ms
+                    double actualDelay = std::min(decision.delay, MAX_DELAY);
+                    int delayUs = static_cast<int>(actualDelay * 1000000);
+                    av_usleep(delayUs);
                 }
                 break;
                 
@@ -1532,17 +1590,32 @@ void PlayerCoreV2::audioPlayThreadFunc() {
                     Logger::instance().debug("Duplicating audio frame");
                     bool writeResult = m_audioOutput->writeFrame(framePtr);
                     Logger::instance().debug("Audio frame duplicate write result: " + std::to_string(writeResult));
+                    
+                    // 如果写入失败,等待一段时间避免快速循环
+                    if (!writeResult) {
+                        Logger::instance().warning("Audio frame duplicate write failed, waiting before next frame");
+                        std::this_thread::sleep_for(std::chrono::milliseconds(10));
+                    }
                 }
                 break;
                 
             case av::utils::FrameAction::DELAY:
-                // 延迟播放
-                auto delayMs = static_cast<int>(decision.delay * 1000);
-                std::this_thread::sleep_for(std::chrono::milliseconds(delayMs));
+                // 延迟播放 - 使用FFmpeg的精确延迟
                 {
+                    const double MAX_DELAY = 0.1;  // 100ms
+                    double actualDelay = std::min(decision.delay, MAX_DELAY);
+                    int delayUs = static_cast<int>(actualDelay * 1000000);
+                    av_usleep(delayUs);
+                    
                     Logger::instance().debug("Writing delayed audio frame to output device");
                     bool writeResult = m_audioOutput->writeFrame(framePtr);
                     Logger::instance().debug("Audio frame delayed write result: " + std::to_string(writeResult));
+                    
+                    // 如果写入失败,等待一段时间避免快速循环
+                    if (!writeResult) {
+                        Logger::instance().warning("Audio frame delayed write failed, waiting before next frame");
+                        av_usleep(10000);  // 10ms
+                    }
                 }
                 break;
         }

+ 3 - 2
AV/code/player/player_core_v2.h

@@ -260,8 +260,9 @@ private:
     std::unique_ptr<VideoDecoder> m_videoDecoder;
     std::unique_ptr<AudioDecoder> m_audioDecoder;
     
-    // 队列管理
-    std::unique_ptr<av::utils::PacketQueue> m_packetQueue;
+    // 队列管理 - 分离视频和音频包队列以提高效率
+    std::unique_ptr<av::utils::PacketQueue> m_videoPacketQueue;
+    std::unique_ptr<av::utils::PacketQueue> m_audioPacketQueue;
     std::unique_ptr<av::utils::FrameQueue> m_videoFrameQueue;
     std::unique_ptr<av::utils::FrameQueue> m_audioFrameQueue;
     

Разница между файлами не показана из-за своего большого размера
+ 573 - 182
AV/code/utils/utils_synchronizer_v2.cpp


+ 61 - 45
AV/code/utils/utils_synchronizer_v2.h

@@ -11,6 +11,7 @@
 #include <chrono>
 #include <deque>
 #include <functional>
+#include <limits>
 
 extern "C" {
 #include <libavutil/avutil.h>
@@ -57,36 +58,42 @@ enum class SyncState {
 };
 
 /**
- * 时钟信息结构
+ * 时钟信息结构 - 与packets_sync.cpp的Clock结构保持一致
  */
 struct ClockInfo {
-    double pts = 0.0;                                           // 当前PTS
+    double pts = std::numeric_limits<double>::quiet_NaN(); // 当前PTS,以秒为单位(与packets_sync.cpp一致)
+    double pts_drift = 0.0;      // clock base minus time at which we updated the clock
+    double lastUpdate = 0.0;     // 最后更新时间
+    double speed = 1.0;          // 播放速度
+    int serial = 0;              // 序列号  clock is based on a packet with this serial
+    bool paused = false;         // 是否暂停
+
+    // SynchronizerV2特有的扩展字段(保持向后兼容)
     double time = 0.0;                                          // 系统时间
-    double speed = 1.0;                                         // 播放速度
-    int serial = 0;                                             // 序列号
-    bool paused = false;                                        // 是否暂停
-    std::chrono::steady_clock::time_point lastUpdate;          // 最后更新时间
-    double drift = 0.0;                                         // 时钟漂移
-    double smoothedPts = 0.0;                                   // 平滑后的PTS
-    
-    ClockInfo() {
-        lastUpdate = std::chrono::steady_clock::now();
+    double drift = 0.0;                                         // 时钟漂移(兼容字段)
+    int64_t smoothedPts = AV_NOPTS_VALUE;                       // 平滑后的PTS
+
+    ClockInfo() { 
+        double currentTime = av_gettime_relative() / 1000000.0;
+        lastUpdate = currentTime;
+        time = currentTime;
     }
 };
 
 /**
- * 同步配置
+ * 同步配置 - 基于AVPlayer2的packets_sync.cpp优化
  */
 struct SyncConfigV2 {
     SyncStrategy syncStrategy = SyncStrategy::ADAPTIVE;  // 同步策略
     
-    // 同步阈值
-    double syncThreshold = 0.04;           // 40ms - 基本同步阈值
+    // 同步阈值 - 参考packets_sync.h的定义
+    double syncThreshold = 0.04;           // AV_SYNC_THRESHOLD_MIN - 40ms
     double audioSyncThreshold = 0.04;      // 40ms - 音频同步阈值
     double videoSyncThreshold = 0.04;      // 40ms - 视频同步阈值
-    double maxSyncError = 0.1;             // 100ms - 最大允许误差
+    double maxSyncError = 0.1;              // AV_SYNC_THRESHOLD_MAX - 100ms
     double frameDropThreshold = 0.05;      // 50ms - 丢帧阈值
-    double frameDupThreshold = 0.1;        // 100ms - 重复帧阈值
+    double frameDupThreshold = 0.1;        // AV_SYNC_FRAMEDUP_THRESHOLD - 100ms
+    double noSyncThreshold = 10.0;         // AV_NOSYNC_THRESHOLD - 10s,超过此值不进行同步
     
     // 帧控制
     bool enableFrameDrop = true;           // 启用丢帧
@@ -164,8 +171,8 @@ enum class FrameAction {
 struct FrameDecision {
     FrameAction action = FrameAction::DISPLAY;
     double delay = 0.0;                     // 延迟时间
-    double targetPts = 0.0;                 // 目标PTS
-    double actualPts = 0.0;                 // 实际PTS
+    int64_t targetPts = AV_NOPTS_VALUE;     // 目标PTS (FFmpeg原生格式)
+    int64_t actualPts = AV_NOPTS_VALUE;     // 实际PTS (FFmpeg原生格式)
     double syncError = 0.0;                 // 同步误差
     std::string reason;                     // 决策原因
 };
@@ -174,8 +181,8 @@ struct FrameDecision {
  * 回调函数类型
  */
 using SyncEventCallback = std::function<void(SyncState oldState, SyncState newState)>;
-using FrameDropCallback = std::function<void(ClockType clockType, double pts)>;
-using FrameDuplicateCallback = std::function<void(ClockType clockType, double pts)>;
+using FrameDropCallback = std::function<void(ClockType clockType, int64_t pts)>;
+using FrameDuplicateCallback = std::function<void(ClockType clockType, int64_t pts)>;
 using SyncErrorCallback = std::function<void(double error, const std::string& reason)>;
 
 /**
@@ -205,29 +212,29 @@ public:
     void setStreamInfo(bool hasAudio, bool hasVideo);
     ErrorCode close();
     
-    // 时钟设置 - 改进的接口
-    ErrorCode setAudioClock(double pts, double time = -1, int serial = 0);
-    ErrorCode setVideoClock(double pts, double time = -1, int serial = 0);
-    ErrorCode setExternalClock(double time = -1, int serial = 0);
+    // 时钟设置与获取
+    ErrorCode setAudioClock(int64_t pts, double timeBase, int serial = 0);
+    ErrorCode setVideoClock(int64_t pts, double timeBase, int serial = 0);
+    ErrorCode setExternalClock(int64_t pts, double timeBase, int serial = 0);
     
     // 时钟获取 - 支持预测
-    double getAudioClock(bool predict = false) const;
-    double getVideoClock(bool predict = false) const;
-    double getExternalClock(bool predict = false) const;
-    double getMasterClock(bool predict = false) const;
+    int64_t getAudioClock(bool predict = false) const;
+    int64_t getVideoClock(bool predict = false) const;
+    int64_t getExternalClock(bool predict = false) const;
+    int64_t getMasterClock(bool predict = false) const;
     ClockType getMasterClockType() const { return masterClockType_; }
     
-    // 同步决策 - 核心功能
-    FrameDecision shouldDisplayVideoFrame(double pts, double duration = 0.0);
-    FrameDecision shouldPlayAudioFrame(double pts, double duration = 0.0);
-    double calculateTargetDelay(double pts, ClockType clockType);
+    // 同步决策 - 核心功能 (需要传入时间基准进行转换)
+    FrameDecision shouldDisplayVideoFrame(int64_t pts, double timeBase, double duration = 0.0);
+    FrameDecision shouldPlayAudioFrame(int64_t pts, double timeBase, double duration = 0.0);
+    double calculateTargetDelay(int64_t pts, double timeBase, ClockType clockType);
     
     // 同步控制
-    bool shouldDropFrame(double pts, ClockType clockType);
-    bool shouldDuplicateFrame(double pts, ClockType clockType);
+    bool shouldDropFrame(int64_t pts, double timeBase, ClockType clockType);
+    bool shouldDuplicateFrame(int64_t pts, double timeBase, ClockType clockType);
     double calculateSyncError() const;
-    double calculateAudioDelay(double pts) const;
-    double calculateVideoDelay(double pts) const;
+    double calculateAudioDelay(int64_t pts, double timeBase) const;
+    double calculateVideoDelay(int64_t pts, double timeBase) const;
     
     // 配置管理
     void setConfig(const SyncConfigV2& config);
@@ -265,10 +272,15 @@ public:
 
 private:
     // 内部时钟管理
-    ErrorCode updateClock(ClockType type, double pts, double time, int serial);
-    double getClock(ClockType type, bool predict = false) const;
+    ErrorCode updateClock(ClockType type, int64_t pts, double timeBase, int serial);
+    int64_t getClock(ClockType type, bool predict = false) const;
     void resetClock(ClockType type);
     void pauseClock(ClockType type, bool pause);
+    void syncClockToSlave(ClockInfo* slave, const ClockInfo* master);
+    
+    // PTS转换辅助方法
+    double ptsToSeconds(int64_t pts, double timeBase) const;
+    int64_t secondsToPts(double seconds, double timeBase) const;
     
     // 同步算法
     void updateMasterClock();
@@ -277,9 +289,9 @@ private:
     void updateStats();
     
     // 平滑和预测
-    double smoothClock(ClockType type, double newPts);
-    double predictClock(ClockType type, double futureTime) const;
-    void updateClockHistory(ClockType type, double pts);
+    int64_t smoothClock(ClockType type, int64_t newPts);
+    int64_t predictClock(ClockType type, double futureTime) const;
+    void updateClockHistory(ClockType type, int64_t pts);
     
     // 自适应算法
     void adaptiveSyncUpdate();
@@ -295,8 +307,8 @@ private:
     double getCurrentTime() const;
     double getSystemTime() const;
     void notifyStateChange(SyncState newState);
-    void notifyFrameDrop(ClockType type, double pts);
-    void notifyFrameDuplicate(ClockType type, double pts);
+    void notifyFrameDrop(ClockType type, int64_t pts);
+    void notifyFrameDuplicate(ClockType type, int64_t pts);
     void notifySyncError(double error, const std::string& reason);
     
     // 内部版本,假设调用者已经持有clockMutex_锁
@@ -321,8 +333,8 @@ private:
     mutable std::mutex clockMutex_;
     
     // 历史记录
-    std::deque<double> audioClockHistory_;
-    std::deque<double> videoClockHistory_;
+    std::deque<int64_t> audioClockHistory_;
+    std::deque<int64_t> videoClockHistory_;
     std::deque<double> syncErrorHistory_;
     mutable std::mutex historyMutex_;
     
@@ -338,8 +350,12 @@ private:
     // 自适应参数
     int recoveryAttempts_ = 0;
     double lastSyncError_ = 0.0;
+    double recoveryStartTime_ = 0.0;
     std::chrono::steady_clock::time_point lastRecoveryTime_;
     
+    // 状态变化回调
+    std::function<void(SyncState, ClockType)> stateChangeCallback_;
+    
     // 回调函数
     SyncEventCallback syncEventCallback_;
     FrameDropCallback frameDropCallback_;

Некоторые файлы не были показаны из-за большого количества измененных файлов