zhuizhu 8 månader sedan
förälder
incheckning
b0b0f9bad2

+ 293 - 133
AV/code/player/player_core_v2.cpp

@@ -49,55 +49,63 @@ PlayerCoreV2::PlayerCoreV2(const SyncConfigV2& syncConfig)
             return;
         }
         
-        // 创建分离的视频和音频包队列
-        m_videoPacketQueue = av::utils::PacketQueueFactory::createStandardQueue(1000);  // 视频包队列
+        // 创建分离的视频和音频包队列 - 使用高容量队列以避免丢帧
+        m_videoPacketQueue = av::utils::PacketQueueFactory::createHighCapacityQueue(2000);  // 视频包队列,增大容量
         if (!m_videoPacketQueue) {
             Logger::instance().error("Failed to create video packet queue");
             setState(PlayerState::Error);
             return;
         }
+        // 禁用丢包策略
+        m_videoPacketQueue->setDropPolicy(false, true);
         
-        m_audioPacketQueue = av::utils::PacketQueueFactory::createStandardQueue(1000);  // 音频包队列
+        m_audioPacketQueue = av::utils::PacketQueueFactory::createHighCapacityQueue(2000);  // 音频包队列,增大容量
         if (!m_audioPacketQueue) {
             Logger::instance().error("Failed to create audio packet queue");
             setState(PlayerState::Error);
             return;
         }
+        // 禁用丢包策略
+        m_audioPacketQueue->setDropPolicy(false, true);
         
-        m_videoFrameQueue = av::utils::FrameQueueFactory::createStandardQueue(50); // 增加视频帧队列
+        m_videoFrameQueue = av::utils::FrameQueueFactory::createHighCapacityQueue(100); // 增加视频帧队列容量并禁用丢帧
         if (!m_videoFrameQueue) {
             Logger::instance().error("Failed to create video frame queue");
             setState(PlayerState::Error);
             return;
         }
+        // 禁用丢帧策略
+        m_videoFrameQueue->setDropPolicy(false, true);
         
-        m_audioFrameQueue = av::utils::FrameQueueFactory::createStandardQueue(200); // 增加音频帧队列
+        m_audioFrameQueue = av::utils::FrameQueueFactory::createHighCapacityQueue(400); // 增加音频帧队列容量并禁用丢帧
         if (!m_audioFrameQueue) {
             Logger::instance().error("Failed to create audio frame queue");
             setState(PlayerState::Error);
             return;
         }
+        // 禁用丢帧策略
+        m_audioFrameQueue->setDropPolicy(false, true);
         
         // 创建改进的同步器
-        // m_synchronizer = std::make_unique<Synchronizer>(syncConfig);
-        // if (!m_synchronizer) {
-        //     Logger::instance().error("Failed to create synchronizer");
-        //     setState(PlayerState::Error);
-        //     return;
-        // }
+        m_synchronizer = std::make_unique<SynchronizerV2>(syncConfig);
+        if (!m_synchronizer) {
+            Logger::instance().error("Failed to create synchronizer");
+            setState(PlayerState::Error);
+            return;
+        }
 
         // 设置同步器回调
-        // m_synchronizer->setSyncErrorCallback([this](double error, const std::string& reason) {
-        //     handleSyncError(error, reason);
-        // });
-
-        // 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) {
-        //         m_eventCallback->onFrameDropped(m_stats.droppedFrames);
-        //     }
-        // });
+        m_synchronizer->setSyncErrorCallback([this](double error, const std::string& reason) {
+            handleSyncError(error, reason);
+        });
+
+        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) {
+                m_eventCallback->onFrameDropped(m_stats.droppedFrames);
+            }
+        });
 
         // 创建解码器
         m_videoDecoder = std::make_unique<VideoDecoder>();
@@ -240,10 +248,10 @@ ErrorCode PlayerCoreV2::play() {
     }
     
     // 启动同步器
-    // if (m_synchronizer->start() != ErrorCode::SUCCESS) {
-    //     Logger::instance().error("Failed to start synchronizer");
-    //     return ErrorCode::SYNC_ERROR;
-    // }
+    if (m_synchronizer && m_synchronizer->start() != ErrorCode::SUCCESS) {
+        Logger::instance().error("Failed to start synchronizer");
+        return ErrorCode::SYNC_ERROR;
+    }
 
     // 记录播放开始时间
     m_playStartTime = std::chrono::steady_clock::now();
@@ -299,12 +307,12 @@ ErrorCode PlayerCoreV2::play() {
         return ErrorCode::THREAD_ERROR;
     }
     
-    if (m_mediaInfo.hasVideo && !startVideoPlayThread()) {
+    if (m_mediaInfo.hasVideo && m_videoStreamEnabled && !startVideoPlayThread()) {
         Logger::instance().error("Failed to start video play thread");
         return ErrorCode::THREAD_ERROR;
     }
     
-    if (m_mediaInfo.hasAudio && !startAudioPlayThread()) {
+    if (m_mediaInfo.hasAudio && m_audioStreamEnabled && !startAudioPlayThread()) {
         Logger::instance().error("Failed to start audio play thread");
         return ErrorCode::THREAD_ERROR;
     }
@@ -324,10 +332,10 @@ ErrorCode PlayerCoreV2::pause() {
         return ErrorCode::INVALID_STATE;
     }
 
-    // // 暂停同步器
-    // if (m_synchronizer->pause() != ErrorCode::SUCCESS) {
-    //     Logger::instance().warning("Failed to pause synchronizer");
-    // }
+    // 暂停同步器
+    if (m_synchronizer && m_synchronizer->pause() != ErrorCode::SUCCESS) {
+        Logger::instance().warning("Failed to pause synchronizer");
+    }
 
     // 记录暂停时的播放时间
     if (m_playStartTime.time_since_epoch().count() != 0) {
@@ -356,10 +364,10 @@ ErrorCode PlayerCoreV2::stop() {
         return ErrorCode::SUCCESS;
     }
 
-    // // 停止同步器
-    // if (m_synchronizer) {
-    //     m_synchronizer->stop();
-    // }
+    // 停止同步器
+    if (m_synchronizer) {
+        m_synchronizer->stop();
+    }
 
     // 停止音频输出
     if (m_audioOutput) {
@@ -410,10 +418,10 @@ ErrorCode PlayerCoreV2::seek(int64_t timestamp) {
     m_baseTime = timestamp;
     m_playStartTime = std::chrono::steady_clock::now();
 
-    // // 重置同步器
-    // if (m_synchronizer) {
-    //     m_synchronizer->reset();
-    // }
+    // 重置同步器
+    if (m_synchronizer) {
+        m_synchronizer->reset();
+    }
 
     // 清空队列
     flushBuffers();
@@ -436,10 +444,10 @@ ErrorCode PlayerCoreV2::setPlaybackSpeed(double speed) {
     std::lock_guard<std::mutex> lock(m_mutex);
     m_playbackSpeed = speed;
 
-    // // 设置同步器的播放速度
-    // if (m_synchronizer) {
-    //     m_synchronizer->setPlaybackSpeed(speed);
-    // }
+    // 设置同步器的播放速度
+    if (m_synchronizer) {
+        m_synchronizer->setPlaybackSpeed(speed);
+    }
 
     // 设置音频输出的播放速度
     if (m_audioOutput) {
@@ -471,15 +479,15 @@ PlaybackStats PlayerCoreV2::getStats() const {
     if (m_videoFrameQueue) stats.queuedVideoFrames = m_videoFrameQueue->size();
     if (m_audioFrameQueue) stats.queuedAudioFrames = m_audioFrameQueue->size();
 
-    // // 更新同步统计
-    // if (m_synchronizer) {
-    //     auto syncStats = m_synchronizer->getStats();
-    //     stats.syncError = syncStats.syncError;
-    //     // stats.avgSyncError = syncStats.avgSyncError;
-    //     // stats.maxSyncError = syncStats.maxSyncError;
-    //     stats.droppedFrames = syncStats.droppedFrames;
-    //     stats.duplicatedFrames = syncStats.duplicatedFrames;
-    // }
+    // 更新同步统计
+    if (m_synchronizer) {
+        auto syncStats = m_synchronizer->getStats();
+        stats.syncError = syncStats.audioVideoSyncError;
+        stats.avgSyncError = syncStats.avgSyncError;
+        stats.maxSyncError = syncStats.maxSyncError;
+        stats.droppedFrames = syncStats.droppedFrames;
+        stats.duplicatedFrames = syncStats.duplicatedFrames;
+    }
 
     return stats;
 }
@@ -520,18 +528,79 @@ void PlayerCoreV2::setVolume(double volume) {
     Logger::instance().debug("Volume set to: " + std::to_string(volume));
 }
 
-// void PlayerCore::setSyncConfig(const SyncConfig& config) {
-//     // if (m_synchronizer) {
-//     //     m_synchronizer->setConfig(config);
-//     // }
-// }
+// 流控制接口实现
+void PlayerCoreV2::enableVideoStream(bool enable) {
+    if (m_videoStreamEnabled == enable) {
+        return; // 状态未变,不需要处理
+    }
+    
+    m_videoStreamEnabled = enable;
+    Logger::instance().info("Video stream " + std::string(enable ? "enabled" : "disabled"));
+    
+    // 如果播放器已经打开文件,需要更新同步器的流信息
+    if (m_formatContext && m_synchronizer) {
+        bool useAudio = m_mediaInfo.hasAudio && m_audioStreamEnabled;
+        bool useVideo = m_mediaInfo.hasVideo && m_videoStreamEnabled;
+        m_synchronizer->setStreamInfo(useAudio, useVideo);
+
+        // 如果正在播放,需要重新启动播放
+        if (m_state == PlayerState::Playing || m_state == PlayerState::Paused) {
+            // 停止当前播放
+            PlayerState oldState = m_state;
+            stop();
+            // 重新开始播放
+            openFile(m_mediaInfo.filename);
+            if (oldState == PlayerState::Playing) {
+                play();
+            }
+        }
+    }
+}
+
+void PlayerCoreV2::enableAudioStream(bool enable) {
+    if (m_audioStreamEnabled == enable) {
+        return; // 状态未变,不需要处理
+    }
+    
+    m_audioStreamEnabled = enable;
+    Logger::instance().info("Audio stream " + std::string(enable ? "enabled" : "disabled"));
+    
+    // 如果播放器已经打开文件,需要更新同步器的流信息
+    if (m_formatContext && m_synchronizer) {
+        bool useAudio = m_mediaInfo.hasAudio && m_audioStreamEnabled;
+        bool useVideo = m_mediaInfo.hasVideo && m_videoStreamEnabled;
+        m_synchronizer->setStreamInfo(useAudio, useVideo);
+        
+        // 如果正在播放,需要重新启动播放
+        if (m_state == PlayerState::Playing) {
+            // 暂停当前播放
+            pause();
+            // 重新开始播放
+            play();
+        }
+    }
+}
+
+bool PlayerCoreV2::isVideoStreamEnabled() const {
+    return m_videoStreamEnabled;
+}
+
+bool PlayerCoreV2::isAudioStreamEnabled() const {
+    return m_audioStreamEnabled;
+}
+
+void PlayerCoreV2::setSyncConfig(const SyncConfigV2& config) {
+    if (m_synchronizer) {
+        m_synchronizer->setConfig(config);
+    }
+}
 
-// SyncConfig PlayerCoreV2::getSyncConfig() const {
-//     if (m_synchronizer) {
-//         return m_synchronizer->getConfig();
-//     }
-//     return SyncConfig();
-// }
+SyncConfigV2 PlayerCoreV2::getSyncConfig() const {
+    if (m_synchronizer) {
+        return m_synchronizer->getConfig();
+    }
+    return SyncConfigV2();
+}
 
 void PlayerCoreV2::setOpenGLVideoRenderer(OpenGLVideoWidget* renderer) {
     m_openGLVideoRenderer = renderer;
@@ -605,9 +674,9 @@ std::string PlayerCoreV2::getDebugInfo() const {
     oss << "  Volume: " << m_volume << "\n";
     oss << "  Error Count: " << m_errorCount << "\n";
 
-    // if (m_synchronizer) {
-    //     oss << "\n" << m_synchronizer->getDebugInfo();
-    // }
+    if (m_synchronizer) {
+        oss << "\n" << m_synchronizer->getDebugInfo();
+    }
 
     return oss.str();
 }
@@ -704,19 +773,21 @@ bool PlayerCoreV2::openMediaFile(const std::string& filename) {
                                std::to_string(m_mediaInfo.channels) + " channels");
     }
 
-    // // 设置同步器的流信息
-    // if (m_synchronizer) {
-    //     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");
-    // }
+    // 设置同步器的流信息
+    if (m_synchronizer) {
+        bool useAudio = m_mediaInfo.hasAudio && m_audioStreamEnabled;
+        bool useVideo = m_mediaInfo.hasVideo && m_videoStreamEnabled;
+        m_synchronizer->setStreamInfo(useAudio, useVideo);
+        Logger::instance().info("Synchronizer stream info set: hasAudio=" + std::to_string(useAudio) +
+                               ", hasVideo=" + std::to_string(useVideo));
+
+        // 在设置流信息后初始化同步器,确保主时钟选择基于正确的流信息
+        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);
     return true;
@@ -1000,12 +1071,22 @@ void PlayerCoreV2::handleError(const std::string& error) {
 }
 
 void PlayerCoreV2::updateSynchronization() {
-    // if (!m_synchronizer || !m_threadsRunning) {
-    //     return;
-    // }
+    if (!m_synchronizer || !m_threadsRunning) {
+        return;
+    }
 
     // 同步器会在内部自动更新
-    // 这里可以添加额外的同步逻辑
+    // 更新同步器统计信息
+    //m_synchronizer->updateStats();
+
+    // 获取同步器统计信息并更新播放器统计
+    std::lock_guard<std::mutex> lock(m_mutex);
+    auto syncStats = m_synchronizer->getStats();
+    m_stats.syncError = syncStats.audioVideoSyncError;
+    m_stats.avgSyncError = syncStats.avgSyncError;
+    m_stats.maxSyncError = syncStats.maxSyncError;
+    m_stats.droppedFrames = syncStats.droppedFrames;
+    m_stats.duplicatedFrames = syncStats.duplicatedFrames;
 }
 
 void PlayerCoreV2::updateStats() {
@@ -1120,11 +1201,16 @@ void PlayerCoreV2::readThreadFunc() {
             m_seekCondition.notify_all();
         }
         
-        // 检查队列是否已满
-        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));
+        // 检查队列是否接近容量上限 - 使用队列容量的90%作为警告阈值,但不丢弃包
+        bool videoQueueNearFull = m_videoPacketQueue && m_videoPacketQueue->size() > 1800; // 2000的90%
+        bool audioQueueNearFull = m_audioPacketQueue && m_audioPacketQueue->size() > 1800; // 2000的90%
+        if (videoQueueNearFull || audioQueueNearFull) { 
+            // 队列接近满,暂停一段时间让解码线程处理
+            Logger::instance().warning("Packet queue is getting large: Video=" + 
+                                    std::to_string(m_videoPacketQueue ? m_videoPacketQueue->size() : 0) + 
+                                    ", Audio=" + std::to_string(m_audioPacketQueue ? m_audioPacketQueue->size() : 0) + 
+                                    ". Slowing down read thread.");
+            std::this_thread::sleep_for(std::chrono::milliseconds(50));
             continue;
         }
         
@@ -1165,28 +1251,38 @@ void PlayerCoreV2::readThreadFunc() {
         }
         
         // 根据流索引将数据包分发到对应队列
-        if (packet->stream_index == m_mediaInfo.videoStreamIndex) {
-            // 视频包放入视频队列
-            if (m_videoPacketQueue && (!videoQueueFull || m_videoPacketQueue->size() < 500)) {
+        if (packet->stream_index == m_mediaInfo.videoStreamIndex && m_videoStreamEnabled) {
+            // 视频包放入视频队列 - 不考虑队列是否已满,确保不丢包
+            if (m_videoPacketQueue) {
                 AVPacket* packetCopy = av_packet_alloc();
                 if (packetCopy && av_packet_ref(packetCopy, packet) == 0) {
                     m_videoPacketQueue->push(packetCopy);
+                    
+                    // 记录队列大小,用于监控
+                    if (m_videoPacketQueue->size() % 100 == 0) {
+                        Logger::instance().debug("Video packet queue size: " + std::to_string(m_videoPacketQueue->size()));
+                    }
                 } else {
                     av_packet_free(&packetCopy);
                 }
             }
-        } else if (packet->stream_index == m_mediaInfo.audioStreamIndex) {
-            // 音频包放入音频队列
-            if (m_audioPacketQueue && (!audioQueueFull || m_audioPacketQueue->size() < 500)) {
+        } else if (packet->stream_index == m_mediaInfo.audioStreamIndex && m_audioStreamEnabled) {
+            // 音频包放入音频队列 - 不考虑队列是否已满,确保不丢包
+            if (m_audioPacketQueue) {
                 AVPacket* packetCopy = av_packet_alloc();
                 if (packetCopy && av_packet_ref(packetCopy, packet) == 0) {
                     m_audioPacketQueue->push(packetCopy);
+                    
+                    // 记录队列大小,用于监控
+                    if (m_audioPacketQueue->size() % 100 == 0) {
+                        Logger::instance().debug("Audio packet queue size: " + std::to_string(m_audioPacketQueue->size()));
+                    }
                 } else {
                     av_packet_free(&packetCopy);
                 }
             }
         }
-        
+
         av_packet_unref(packet);
     }
     
@@ -1270,14 +1366,16 @@ void PlayerCoreV2::videoDecodeThreadFunc() {
                         Logger::instance().debug("Frame PTS: " + std::to_string(framePtr->pts));
                     }
                     
-                    // 将帧放入队列
-                    if (m_videoFrameQueue->size() < 30) { // 限制队列大小
-                        // 释放智能指针的所有权,让队列管理帧的生命周期
-                        m_videoFrameQueue->push(framePtr.release());
-                        m_frameCount++;
-                        Logger::instance().debug("Video frame pushed to queue, queue size: " + std::to_string(m_videoFrameQueue->size()));
-                    } else {
-                        Logger::instance().warning("Video frame queue full, dropping frame");
+                    // 将帧放入队列 - 不丢弃任何帧
+                    // 释放智能指针的所有权,让队列管理帧的生命周期
+                    m_videoFrameQueue->push(framePtr.release());
+                    m_frameCount++;
+                    Logger::instance().debug("Video frame pushed to queue, queue size: " + std::to_string(m_videoFrameQueue->size()));
+                    
+                    // 如果队列大小超过警告阈值,记录警告但不丢弃
+                    if (m_videoFrameQueue->size() > 80) {
+                        Logger::instance().warning("Video frame queue is getting large: " + std::to_string(m_videoFrameQueue->size()) + 
+                                                " frames. Performance may be affected.");
                     }
                 }
             }
@@ -1366,13 +1464,15 @@ void PlayerCoreV2::audioDecodeThreadFunc() {
                         Logger::instance().debug("Audio Frame PTS: " + std::to_string(framePtr->pts));
                     }
                     
-                    // 将帧放入队列
-                    if (m_audioFrameQueue->size() < 100) { // 限制队列大小
-                        // 释放智能指针的所有权,让队列管理帧的生命周期
-                        m_audioFrameQueue->push(framePtr.release());
-                        Logger::instance().debug("Audio frame pushed to queue, queue size: " + std::to_string(m_audioFrameQueue->size()));
-                    } else {
-                        Logger::instance().warning("Audio frame queue full, dropping frame");
+                    // 将帧放入队列 - 不丢弃任何帧
+                    // 释放智能指针的所有权,让队列管理帧的生命周期
+                    m_audioFrameQueue->push(framePtr.release());
+                    Logger::instance().debug("Audio frame pushed to queue, queue size: " + std::to_string(m_audioFrameQueue->size()));
+                    
+                    // 如果队列大小超过警告阈值,记录警告但不丢弃
+                    if (m_audioFrameQueue->size() > 300) {
+                        Logger::instance().warning("Audio frame queue is getting large: " + std::to_string(m_audioFrameQueue->size()) + 
+                                                " frames. Performance may be affected.");
                     }
                 }
             }
@@ -1390,8 +1490,11 @@ void PlayerCoreV2::audioDecodeThreadFunc() {
 void PlayerCoreV2::videoPlayThreadFunc() {
     Logger::instance().info("Video play thread started");
 
+    // 用于计算帧持续时间的变量
+    AVFrame* lastFrame = nullptr;
+
     while (!m_threadsShouldStop) {
-        if (!m_videoFrameQueue /*|| !m_synchronizer*/) {
+        if (!m_videoFrameQueue || !m_synchronizer) {
             std::this_thread::sleep_for(std::chrono::milliseconds(10));
             continue;
         }
@@ -1408,32 +1511,69 @@ void PlayerCoreV2::videoPlayThreadFunc() {
         
         Logger::instance().debug("Video play thread got frame, pts=" + std::to_string(frame->pts));
 
-        // 尝试获取下一帧的PTS来计算精确的帧持续时间
-        double nextPts = AV_NOPTS_VALUE;
-        if (m_videoFrameQueue->size() > 0) {
-            AVFrame* nextFrame = m_videoFrameQueue->peekFrame();
-            if (nextFrame && nextFrame->pts != AV_NOPTS_VALUE) {
-                nextPts = nextFrame->pts;
+        // 创建智能指针管理帧内存
+        AVFramePtr framePtr(frame);
+        
+        // 使用同步器计算视频帧显示时间
+        double pts = frame->pts * av_q2d(m_formatContext->streams[m_mediaInfo.videoStreamIndex]->time_base);
+        
+        // 更新视频时钟
+        m_synchronizer->setClock(av::utils::ClockType::VIDEO, pts, 0);
+        
+        // 计算帧持续时间
+        double last_duration = 0.0;
+        if (lastFrame && lastFrame->pts != AV_NOPTS_VALUE && frame->pts != AV_NOPTS_VALUE) {
+            // 计算两帧之间的时间差
+            double last_pts = lastFrame->pts * av_q2d(m_formatContext->streams[m_mediaInfo.videoStreamIndex]->time_base);
+            last_duration = pts - last_pts;
+            if (last_duration < 0 || last_duration > 10.0) {
+                // 如果持续时间不合理,使用帧率的倒数作为默认值
+                last_duration = 1.0 / m_mediaInfo.fps;
             }
+        } else {
+            // 如果没有上一帧,使用帧率的倒数作为默认值
+            last_duration = 1.0 / m_mediaInfo.fps;
         }
+        
+        // 计算视频帧延迟并决定是否显示
+        FrameDecision decision = m_synchronizer->synchronizeVideo(pts, 0, last_duration);
 
-        // 创建智能指针管理帧内存
-        AVFramePtr framePtr(frame);
-        // 显示帧
-        if (m_openGLVideoRenderer) {
-            m_openGLVideoRenderer->Render(framePtr.get());
+        if (decision.action == FrameAction::DISPLAY) {
+            // 如果需要延迟显示,等待指定时间
+            if (decision.delay > 0.0) {
+                std::this_thread::sleep_for(std::chrono::microseconds(static_cast<int64_t>(decision.delay * 1000000)));
+            }
+            
+            // 显示帧
+            if (m_openGLVideoRenderer) {
+                m_openGLVideoRenderer->Render(framePtr.get());
+                Logger::instance().debug("Video frame displayed, pts=" + std::to_string(pts) + ", delay=" + std::to_string(decision.delay));
+            }
+            
+            // 更新上一帧指针
+            if (lastFrame) {
+                av_frame_free(&lastFrame);
+            }
+            lastFrame = av_frame_clone(frame);
+        } else if (decision.action == FrameAction::DROP) {
+            Logger::instance().debug("Video frame dropped due to sync, pts=" + std::to_string(pts) + ", error=" + std::to_string(decision.syncError));
         }
     }
 
+    // 清理最后一帧
+    if (lastFrame) {
+        av_frame_free(&lastFrame);
+    }
+
     Logger::instance().info("Video play thread finished");
 }
 
 void PlayerCoreV2::audioPlayThreadFunc() {
     Logger::instance().info("Audio play thread started");
-    
+
     int frameCount = 0;
     while (!m_threadsShouldStop) {
-        if (!m_audioFrameQueue || /* !m_synchronizer ||*/ !m_audioOutput) {
+        if (!m_audioFrameQueue || !m_synchronizer || !m_audioOutput) {
             std::this_thread::sleep_for(std::chrono::milliseconds(10));
             continue;
         }
@@ -1447,25 +1587,44 @@ void PlayerCoreV2::audioPlayThreadFunc() {
             }
             continue;
         }
-        
+
         // 检查是否是EOF帧
         if (frame->data[0] == nullptr && frame->nb_samples == 0) {
             Logger::instance().info("Audio play thread received EOF frame, playback completed");
             av_frame_free(&frame);
-            
+
             // 通知播放完成
             setState(PlayerState::Stopped);
             Logger::instance().info("Audio playback finished naturally");
             return;
         }
-        
+
         frameCount++;
-        Logger::instance().debug("Audio play thread got frame #" + std::to_string(frameCount) + 
-                                ", pts=" + std::to_string(frame->pts) + 
-                                ", nb_samples=" + std::to_string(frame->nb_samples));
+        Logger::instance().debug("Audio play thread got frame #" + std::to_string(frameCount)
+                                 + ", pts=" + std::to_string(frame->pts)
+                                 + ", nb_samples=" + std::to_string(frame->nb_samples));
 
         // 创建智能指针管理帧内存
         AVFramePtr framePtr(frame);
+
+        // 计算音频PTS
+        double pts = frame->pts
+                     * av_q2d(m_formatContext->streams[m_mediaInfo.audioStreamIndex]->time_base);
+
+        // 更新音频时钟
+        m_synchronizer->setClock(av::utils::ClockType::AUDIO, pts, 0);
+
+        // 同步音频样本数量
+        int originalSamples = frame->nb_samples;
+        int adjustedSamples = m_synchronizer->synchronizeAudio((short*) frame->data[0],
+                                                               frame->nb_samples,
+                                                               pts);
+
+        if (adjustedSamples != originalSamples) {
+            Logger::instance().debug("Audio samples adjusted from " + std::to_string(originalSamples)
+                                     + " to " + std::to_string(adjustedSamples) + " for sync");
+        }
+
         {
             Logger::instance().debug("Writing audio frame to output device");
             bool writeResult = m_audioOutput->writeFrame(framePtr);
@@ -1480,8 +1639,9 @@ void PlayerCoreV2::audioPlayThreadFunc() {
 
         // framePtr 会自动释放内存,无需手动调用 av_frame_free
     }
-    
-    Logger::instance().info("Audio play thread finished, total frames processed: " + std::to_string(frameCount));
+
+    Logger::instance().info("Audio play thread finished, total frames processed: "
+                            + std::to_string(frameCount));
 }
 
 } // namespace player

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

@@ -152,6 +152,12 @@ public:
     ErrorCode seek(int64_t timestamp);  // 微秒
     ErrorCode setPlaybackSpeed(double speed);
     
+    // 流控制接口
+    void enableVideoStream(bool enable);
+    void enableAudioStream(bool enable);
+    bool isVideoStreamEnabled() const;
+    bool isAudioStreamEnabled() const;
+    
     // 状态查询
     PlayerState getState() const { return m_state.load(); }
     MediaInfo getMediaInfo() const;
@@ -164,8 +170,8 @@ public:
     double getVolume() const { return m_volume; }
     
     // 同步控制
-    // void setSyncConfig(const SyncConfig& config);
-    // SyncConfig getSyncConfig() const;
+    void setSyncConfig(const SyncConfigV2& config);
+    SyncConfigV2 getSyncConfig() const;
 
     // OpenGL渲染器设置
     void setOpenGLVideoRenderer(OpenGLVideoWidget* renderer);
@@ -267,7 +273,7 @@ private:
     std::unique_ptr<av::utils::FrameQueue> m_audioFrameQueue;
     
     // 同步器
-    // std::unique_ptr<Synchronizer> m_synchronizer;
+    std::unique_ptr<SynchronizerV2> m_synchronizer;
 
     // 音频输出
     std::unique_ptr<AudioOutput> m_audioOutput;
@@ -285,6 +291,10 @@ private:
     std::mutex m_seekMutex;
     std::condition_variable m_seekCondition;
     
+    // 流控制
+    std::atomic<bool> m_videoStreamEnabled{true};
+    std::atomic<bool> m_audioStreamEnabled{true};
+    
     // 时间管理
     std::chrono::steady_clock::time_point m_playStartTime;
     std::atomic<int64_t> m_baseTime{0};

+ 753 - 0
AV/code/utils/utils_synchronizer_v2.cpp

@@ -0,0 +1,753 @@
+#include "utils_synchronizer_v2.h"
+#include <algorithm>
+#include <cmath>
+#include <iostream>
+#include <sstream>
+
+namespace av {
+namespace utils {
+
+// 构造函数
+SynchronizerV2::SynchronizerV2(const SyncConfigV2& config)
+    : m_config(config)
+    , m_syncStrategy(config.strategy)
+    , m_playbackSpeed(1.0)
+{
+    // 初始化时钟
+    initClock(m_audioClock, 0);
+    initClock(m_videoClock, 0);
+    initClock(m_externalClock, 0);
+    
+    // 初始化帧计时器
+    m_frameTimer = getCurrentTime();
+}
+
+// 析构函数
+SynchronizerV2::~SynchronizerV2() {
+    close();
+}
+
+// 初始化
+ErrorCode SynchronizerV2::initialize() {
+    if (m_initialized) {
+        return ErrorCode::SUCCESS;
+    }
+    
+    // 重置状态
+    m_initialized = true;
+    m_running = false;
+    m_paused = false;
+    
+    // 重置时钟
+    initClock(m_audioClock, 0);
+    initClock(m_videoClock, 0);
+    initClock(m_externalClock, 0);
+    
+    // 重置帧计时器
+    m_frameTimer = getCurrentTime();
+    
+    // 重置统计信息
+    std::lock_guard<std::mutex> lock(m_statsMutex);
+    m_stats = SyncStatsV2();
+    
+    return ErrorCode::SUCCESS;
+}
+
+// 关闭
+void SynchronizerV2::close() {
+    if (!m_initialized) {
+        return;
+    }
+    
+    stop();
+    m_initialized = false;
+}
+
+// 启动
+ErrorCode SynchronizerV2::start() {
+    if (!m_initialized) {
+        return ErrorCode::NOT_INITIALIZED;
+    }
+    
+    if (m_running) {
+        return ErrorCode::SUCCESS;
+    }
+    
+    // 重置帧计时器
+    m_frameTimer = getCurrentTime();
+    
+    // 更新外部时钟
+    updateExternalClock();
+    
+    m_running = true;
+    m_paused = false;
+    
+    return ErrorCode::SUCCESS;
+}
+
+// 停止
+ErrorCode SynchronizerV2::stop() {
+    if (!m_initialized || !m_running) {
+        return ErrorCode::SUCCESS;
+    }
+    
+    m_running = false;
+    m_paused = false;
+    
+    return ErrorCode::SUCCESS;
+}
+
+// 暂停
+ErrorCode SynchronizerV2::pause() {
+    if (!m_initialized || !m_running) {
+        return ErrorCode::NOT_STARTED;
+    }
+    
+    if (m_paused) {
+        return ErrorCode::SUCCESS;
+    }
+    
+    // 设置时钟暂停状态
+    std::lock_guard<std::mutex> lock(m_clockMutex);
+    m_audioClock.paused = true;
+    m_videoClock.paused = true;
+    m_externalClock.paused = true;
+    
+    m_paused = true;
+    
+    return ErrorCode::SUCCESS;
+}
+
+// 恢复
+ErrorCode SynchronizerV2::resume() {
+    if (!m_initialized || !m_running) {
+        return ErrorCode::NOT_STARTED;
+    }
+    
+    if (!m_paused) {
+        return ErrorCode::SUCCESS;
+    }
+    
+    // 恢复时钟暂停状态
+    std::lock_guard<std::mutex> lock(m_clockMutex);
+    m_audioClock.paused = false;
+    m_videoClock.paused = false;
+    m_externalClock.paused = false;
+    
+    // 更新外部时钟
+    updateExternalClock();
+    
+    m_paused = false;
+    
+    return ErrorCode::SUCCESS;
+}
+
+// 重置
+ErrorCode SynchronizerV2::reset() {
+    if (!m_initialized) {
+        return ErrorCode::NOT_INITIALIZED;
+    }
+    
+    // 重置时钟
+    std::lock_guard<std::mutex> lock(m_clockMutex);
+    initClock(m_audioClock, m_audioSerial);
+    initClock(m_videoClock, m_videoSerial);
+    initClock(m_externalClock, m_externalSerial);
+    
+    // 重置帧计时器
+    m_frameTimer = getCurrentTime();
+    
+    // 重置音频同步状态
+    m_audioDiffCum = 0.0;
+    m_audioDiffAvgCount = 0;
+    
+    // 重置统计信息
+    std::lock_guard<std::mutex> statsLock(m_statsMutex);
+    m_stats = SyncStatsV2();
+    m_stats.playbackSpeed = m_playbackSpeed;
+    
+    return ErrorCode::SUCCESS;
+}
+
+// 设置流信息
+void SynchronizerV2::setStreamInfo(bool hasAudio, bool hasVideo) {
+    m_hasAudio = hasAudio;
+    m_hasVideo = hasVideo;
+
+    // // 如果没有音频,但同步策略是音频主时钟,则切换到视频主时钟
+    // if (!hasAudio && m_syncStrategy == SyncStrategy::AUDIO_MASTER) {
+    //     if (hasVideo) {
+    //         setSyncStrategy(SyncStrategy::VIDEO_MASTER);
+    //     } else {
+    //         setSyncStrategy(SyncStrategy::EXTERNAL_MASTER);
+    //     }
+    // }
+
+    // // 如果没有视频,但同步策略是视频主时钟,则切换到音频主时钟
+    // if (!hasVideo && m_syncStrategy == SyncStrategy::VIDEO_MASTER) {
+    //     if (hasAudio) {
+    //         setSyncStrategy(SyncStrategy::AUDIO_MASTER);
+    //     } else {
+    //         setSyncStrategy(SyncStrategy::EXTERNAL_MASTER);
+    //     }
+    // }
+
+    // 根据可用流调整同步策略
+    if (hasAudio && hasVideo) {
+        // 两种流都有,使用音频优先
+        setSyncStrategy(SyncStrategy::AUDIO_MASTER);
+    } else if (hasVideo && !hasAudio) {
+        // 只有视频,强制使用视频主时钟
+        setSyncStrategy(SyncStrategy::VIDEO_MASTER);
+    } else if (hasAudio && !hasVideo) {
+        // 只有音频,强制使用音频主时钟
+        setSyncStrategy(SyncStrategy::AUDIO_MASTER);
+    } else {
+        // 两种流都没有,使用外部时钟
+        setSyncStrategy(SyncStrategy::EXTERNAL_MASTER);
+    }
+}
+
+// 获取时钟值
+double SynchronizerV2::getClock(ClockType type) const {
+    std::lock_guard<std::mutex> lock(m_clockMutex);
+    
+    const Clock* clock = nullptr;
+    switch (type) {
+        case ClockType::AUDIO:
+            clock = &m_audioClock;
+            break;
+        case ClockType::VIDEO:
+            clock = &m_videoClock;
+            break;
+        case ClockType::EXTERNAL:
+            clock = &m_externalClock;
+            break;
+    }
+    
+    if (!clock) {
+        return 0.0;
+    }
+    
+    // 如果时钟暂停,直接返回pts
+    if (clock->paused) {
+        return clock->pts;
+    }
+    
+    double time = getCurrentTime();
+    // 计算当前时钟时间 = pts + (当前时间 - 上次更新时间) * 速度
+    return clock->ptsDrift + (time - clock->lastUpdated) * clock->speed;
+}
+
+// 设置时钟
+void SynchronizerV2::setClock(ClockType type, double pts, int serial) {
+    setClockAt(type, pts, serial, getCurrentTime());
+}
+
+// 在指定时间设置时钟
+void SynchronizerV2::setClockAt(ClockType type, double pts, int serial, double time) {
+    std::lock_guard<std::mutex> lock(m_clockMutex);
+    
+    Clock* clock = nullptr;
+    switch (type) {
+        case ClockType::AUDIO:
+            clock = &m_audioClock;
+            break;
+        case ClockType::VIDEO:
+            clock = &m_videoClock;
+            break;
+        case ClockType::EXTERNAL:
+            clock = &m_externalClock;
+            break;
+    }
+    
+    if (!clock) {
+        return;
+    }
+    
+    // 更新时钟
+    clock->pts = pts;
+    clock->lastUpdated = time;
+    clock->ptsDrift = clock->pts - time;
+    clock->serial = serial;
+    
+    // 更新统计信息
+    //updateStats();
+}
+
+// 设置时钟速度
+void SynchronizerV2::setClockSpeed(ClockType type, double speed) {
+    //std::lock_guard<std::mutex> lock(m_clockMutex);
+
+    Clock* clock = nullptr;
+    switch (type) {
+        case ClockType::AUDIO:
+            clock = &m_audioClock;
+            break;
+        case ClockType::VIDEO:
+            clock = &m_videoClock;
+            break;
+        case ClockType::EXTERNAL:
+            clock = &m_externalClock;
+            break;
+    }
+    
+    if (!clock) {
+        return;
+    }
+    
+    // 设置时钟速度前先更新当前pts
+    double pts = getClock(type);
+    clock->pts = pts;
+    clock->lastUpdated = getCurrentTime();
+    clock->ptsDrift = clock->pts - clock->lastUpdated;
+    clock->speed = speed;
+}
+
+// 获取主时钟类型
+ClockType SynchronizerV2::getMasterClockType() const {
+    // 根据同步策略和流信息确定主时钟类型
+    switch (m_syncStrategy) {
+        case SyncStrategy::AUDIO_MASTER:
+            if (m_hasAudio) {
+                return ClockType::AUDIO;
+            }
+            break;
+        case SyncStrategy::VIDEO_MASTER:
+            if (m_hasVideo) {
+                return ClockType::VIDEO;
+            }
+            break;
+        case SyncStrategy::EXTERNAL_MASTER:
+            return ClockType::EXTERNAL;
+    }
+    
+    // 如果首选的主时钟不可用,则按优先级选择
+    if (m_hasAudio) {
+        return ClockType::AUDIO;
+    } else if (m_hasVideo) {
+        return ClockType::VIDEO;
+    } else {
+        return ClockType::EXTERNAL;
+    }
+}
+
+// 获取主时钟值
+double SynchronizerV2::getMasterClock() const {
+    ClockType masterType = getMasterClockType();
+    return getClock(masterType);
+}
+
+// 计算视频帧目标延迟
+double SynchronizerV2::computeTargetDelay(double frameDuration, double videoPts) const {
+    double delay = 0.0;
+    
+    // 如果不是视频主时钟,则需要与主时钟同步
+    if (getMasterClockType() != ClockType::VIDEO) {
+        // 计算视频时钟与主时钟的差异
+        double diff = videoPts - getMasterClock();
+        
+        // 如果差异太大(超过noSyncThreshold),则不进行同步
+        if (std::fabs(diff) < m_config.noSyncThreshold) {
+            // 如果视频落后于主时钟或超前太多,则调整延迟
+            if (diff <= -m_config.syncThresholdMin) {  // 视频落后,减少延迟
+                delay = std::max(0.0, delay + diff);
+            } else if (diff >= m_config.syncThresholdMax) {  // 视频超前太多,增加延迟
+                delay = delay + diff;
+            } else if (diff >= m_config.syncThresholdMin) {  // 视频略微超前,平滑调整
+                delay = (delay + diff) * 2.0 / 3.0;
+            }
+        }
+    }
+    
+    // 添加帧持续时间
+    delay += frameDuration;
+    
+    return delay;
+}
+
+// 同步视频帧
+FrameDecision SynchronizerV2::synchronizeVideo(double pts, int serial, double duration) const {
+    FrameDecision decision;
+    
+    // 如果没有视频流,直接显示
+    if (!m_hasVideo) {
+        decision.action = FrameAction::DISPLAY;
+        decision.delay = 0.0;
+        decision.reason = "No video stream";
+        return decision;
+    }
+    
+    // 如果暂停,直接显示
+    if (m_paused) {
+        decision.action = FrameAction::DISPLAY;
+        decision.delay = 0.0;
+        decision.reason = "Playback paused";
+        return decision;
+    }
+    
+    // 计算目标延迟
+    double delay = computeTargetDelay(duration, pts);
+    
+    // 获取当前时间
+    double time = getCurrentTime();
+    
+    // 计算实际延迟(相对于上一帧的显示时间)
+    double actualDelay = time - m_frameTimer;
+    
+    // 计算同步误差
+    double syncError = 0.0;
+    if (getMasterClockType() != ClockType::VIDEO) {
+        syncError = pts - getMasterClock();
+    }
+    
+    // 更新帧计时器
+    m_frameTimer += delay;
+    
+    // 如果实际延迟大于两倍目标延迟,说明系统可能卡顿,重置帧计时器
+    if (actualDelay > 2.0 * delay) {
+        m_frameTimer = time;
+    }
+    
+    // 决定帧处理动作
+    if (time < m_frameTimer) {
+        // 当前时间小于下一帧显示时间,需要等待
+        decision.action = FrameAction::DISPLAY;
+        decision.delay = m_frameTimer - time;  // 需要等待的时间
+        decision.syncError = syncError;
+        decision.reason = "Wait for next frame time";
+    } else {
+        // 当前时间已经超过下一帧显示时间
+        
+        // 如果延迟太大,可能需要丢帧
+        if (time > m_frameTimer + m_config.frameDropThreshold && getMasterClockType() != ClockType::VIDEO) {
+            decision.action = FrameAction::DROP;
+            decision.delay = 0.0;
+            decision.syncError = syncError;
+            decision.reason = "Frame too late, dropping";
+            
+            // 通知帧丢弃
+            notifyFrameDrop(ClockType::VIDEO, static_cast<int64_t>(pts * 1000));
+        } else {
+            // 正常显示
+            decision.action = FrameAction::DISPLAY;
+            decision.delay = 0.0;  // 立即显示
+            decision.syncError = syncError;
+            decision.reason = "Display immediately";
+        }
+    }
+    
+    // 通知同步误差
+    if (std::fabs(syncError) > m_config.syncThresholdMin) {
+        notifySyncError(syncError, decision.reason);
+    }
+    
+    return decision;
+}
+
+// 同步音频
+int SynchronizerV2::synchronizeAudio(short* samples, int samplesSize, double pts) {
+    // 如果没有音频流或者音频是主时钟,则不需要同步
+    if (!m_hasAudio || getMasterClockType() == ClockType::AUDIO || m_paused) {
+        return samplesSize;
+    }
+    
+    // 计算音频与主时钟的差异
+    double diff = getClock(ClockType::AUDIO) - getMasterClock();
+    
+    // 如果差异太大,则不进行同步
+    if (std::fabs(diff) > m_config.noSyncThreshold) {
+        // 重置音频差异累积
+        m_audioDiffCum = 0.0;
+        m_audioDiffAvgCount = 0;
+        return samplesSize;
+    }
+    
+    // 更新音频差异平均值
+    m_audioDiffCum = diff + m_audioDiffCum * (1.0 - m_config.audioDiffAvgCoef);
+    if (m_audioDiffAvgCount < m_config.audioDiffAvgCount) {
+        m_audioDiffAvgCount++;
+    } else {
+        double avgDiff = m_audioDiffCum / m_audioDiffAvgCount;
+        
+        // 根据差异调整音频样本数量
+        if (std::fabs(avgDiff) >= m_config.audioDiffThreshold) {
+            int wantedSamples = samplesSize;
+            int minSamples = samplesSize * (1.0 - m_config.audioDiffThreshold);
+            int maxSamples = samplesSize * (1.0 + m_config.audioDiffThreshold);
+            
+            // 计算调整后的样本数量
+            wantedSamples += static_cast<int>(diff * samplesSize);
+            wantedSamples = std::max(minSamples, std::min(wantedSamples, maxSamples));
+            
+            return wantedSamples;
+        }
+    }
+    
+    return samplesSize;
+}
+
+// 设置配置
+void SynchronizerV2::setConfig(const SyncConfigV2& config) {
+    m_config = config;
+    m_syncStrategy = config.strategy;
+}
+
+// 获取配置
+SyncConfigV2 SynchronizerV2::getConfig() const {
+    return m_config;
+}
+
+// 设置同步策略
+void SynchronizerV2::setSyncStrategy(SyncStrategy strategy) {
+    // 检查策略是否可用
+    if (strategy == SyncStrategy::AUDIO_MASTER && !m_hasAudio) {
+        if (m_hasVideo) {
+            strategy = SyncStrategy::VIDEO_MASTER;
+        } else {
+            strategy = SyncStrategy::EXTERNAL_MASTER;
+        }
+    } else if (strategy == SyncStrategy::VIDEO_MASTER && !m_hasVideo) {
+        if (m_hasAudio) {
+            strategy = SyncStrategy::AUDIO_MASTER;
+        } else {
+            strategy = SyncStrategy::EXTERNAL_MASTER;
+        }
+    }
+    
+    m_syncStrategy = strategy;
+    m_config.strategy = strategy;
+}
+
+// 获取同步策略
+SyncStrategy SynchronizerV2::getSyncStrategy() const {
+    return m_syncStrategy;
+}
+
+// 设置播放速度
+void SynchronizerV2::setPlaybackSpeed(double speed) {
+    // 限制速度范围
+    speed = std::max(m_config.clockSpeedMin, std::min(speed, m_config.clockSpeedMax));
+    
+    // 如果速度没有变化,则不需要更新
+    if (std::fabs(speed - m_playbackSpeed) < 0.01) {
+        return;
+    }
+    
+    // 更新播放速度
+    m_playbackSpeed = speed;
+    
+    // 更新所有时钟的速度
+    setClockSpeed(ClockType::AUDIO, speed);
+    setClockSpeed(ClockType::VIDEO, speed);
+    setClockSpeed(ClockType::EXTERNAL, speed);
+    
+    // 更新统计信息
+    std::lock_guard<std::mutex> lock(m_statsMutex);
+    m_stats.playbackSpeed = speed;
+}
+
+// 获取播放速度
+double SynchronizerV2::getPlaybackSpeed() const {
+    return m_playbackSpeed;
+}
+
+// 获取统计信息
+SyncStatsV2 SynchronizerV2::getStats() const {
+    std::lock_guard<std::mutex> lock(m_statsMutex);
+    return m_stats;
+}
+
+// 设置同步错误回调
+void SynchronizerV2::setSyncErrorCallback(const SyncErrorCallback& callback) {
+    std::lock_guard<std::mutex> lock(m_callbackMutex);
+    m_syncErrorCallback = callback;
+}
+
+// 设置帧丢弃回调
+void SynchronizerV2::setFrameDropCallback(const FrameDropCallback& callback) {
+    std::lock_guard<std::mutex> lock(m_callbackMutex);
+    m_frameDropCallback = callback;
+}
+
+// 获取调试信息
+std::string SynchronizerV2::getDebugInfo() const {
+    std::stringstream ss;
+    
+    // 获取当前状态
+    bool initialized = m_initialized;
+    bool running = m_running;
+    bool paused = m_paused;
+    
+    // 获取时钟值
+    double audioClock = getClock(ClockType::AUDIO);
+    double videoClock = getClock(ClockType::VIDEO);
+    double externalClock = getClock(ClockType::EXTERNAL);
+    double masterClock = getMasterClock();
+    
+    // 获取同步策略
+    SyncStrategy strategy = getSyncStrategy();
+    std::string strategyStr;
+    switch (strategy) {
+        case SyncStrategy::AUDIO_MASTER:
+            strategyStr = "AUDIO_MASTER";
+            break;
+        case SyncStrategy::VIDEO_MASTER:
+            strategyStr = "VIDEO_MASTER";
+            break;
+        case SyncStrategy::EXTERNAL_MASTER:
+            strategyStr = "EXTERNAL_MASTER";
+            break;
+    }
+    
+    // 获取主时钟类型
+    ClockType masterType = getMasterClockType();
+    std::string masterTypeStr;
+    switch (masterType) {
+        case ClockType::AUDIO:
+            masterTypeStr = "AUDIO";
+            break;
+        case ClockType::VIDEO:
+            masterTypeStr = "VIDEO";
+            break;
+        case ClockType::EXTERNAL:
+            masterTypeStr = "EXTERNAL";
+            break;
+    }
+    
+    // 获取统计信息
+    SyncStatsV2 stats = getStats();
+    
+    // 构建调试信息
+    ss << "SynchronizerV2 Debug Info:\n";
+    ss << "  State: " << (initialized ? "Initialized" : "Not Initialized")
+       << ", " << (running ? "Running" : "Stopped")
+       << ", " << (paused ? "Paused" : "Playing") << "\n";
+    ss << "  Streams: " << (m_hasAudio ? "Audio" : "No Audio")
+       << ", " << (m_hasVideo ? "Video" : "No Video") << "\n";
+    ss << "  Sync Strategy: " << strategyStr << "\n";
+    ss << "  Master Clock Type: " << masterTypeStr << "\n";
+    ss << "  Clocks (seconds):\n";
+    ss << "    Audio: " << audioClock << "\n";
+    ss << "    Video: " << videoClock << "\n";
+    ss << "    External: " << externalClock << "\n";
+    ss << "    Master: " << masterClock << "\n";
+    ss << "  Playback Speed: " << m_playbackSpeed << "\n";
+    ss << "  Stats:\n";
+    ss << "    Audio-Video Sync Error: " << stats.audioVideoSyncError << " seconds\n";
+    ss << "    Avg Sync Error: " << stats.avgSyncError << " seconds\n";
+    ss << "    Max Sync Error: " << stats.maxSyncError << " seconds\n";
+    ss << "    Dropped Frames: " << stats.droppedFrames << "\n";
+    ss << "    Duplicated Frames: " << stats.duplicatedFrames << "\n";
+    
+    return ss.str();
+}
+
+// 初始化时钟
+void SynchronizerV2::initClock(Clock& clock, int serial) {
+    clock.pts = 0.0;
+    clock.ptsDrift = 0.0;
+    clock.lastUpdated = getCurrentTime();
+    clock.speed = m_playbackSpeed;
+    clock.serial = serial;
+    clock.paused = false;
+    clock.queueSerial = serial;
+}
+
+// 将时钟同步到从属时钟
+void SynchronizerV2::syncClockToSlave(Clock& c, const Clock& slave) {
+    double clockDiff = getClock(ClockType::EXTERNAL) - getClock(ClockType::AUDIO);
+    double correction = 0.0;
+    
+    // 根据差异调整时钟速度
+    if (std::fabs(clockDiff) < m_config.noSyncThreshold) {
+        if (clockDiff <= -m_config.syncThresholdMin) {
+            // 外部时钟落后,加速
+            correction = -m_config.clockSpeedStep;
+        } else if (clockDiff >= m_config.syncThresholdMin) {
+            // 外部时钟超前,减速
+            correction = m_config.clockSpeedStep;
+        }
+        
+        // 应用速度调整
+        c.speed = m_playbackSpeed + correction;
+        c.speed = std::max(m_config.clockSpeedMin, std::min(c.speed, m_config.clockSpeedMax));
+    }
+}
+
+// 更新外部时钟
+void SynchronizerV2::updateExternalClock() {
+    // 更新外部时钟,使其与主时钟同步
+    if (getMasterClockType() != ClockType::EXTERNAL) {
+        double masterClock = getMasterClock();
+        setClock(ClockType::EXTERNAL, masterClock, m_externalSerial);
+    }
+}
+
+// 检查外部时钟速度
+void SynchronizerV2::checkExternalClockSpeed() {
+    if (m_hasAudio && getMasterClockType() == ClockType::EXTERNAL) {
+        // 将外部时钟同步到音频时钟
+        syncClockToSlave(m_externalClock, m_audioClock);
+    } else if (m_hasVideo && getMasterClockType() == ClockType::EXTERNAL) {
+        // 将外部时钟同步到视频时钟
+        syncClockToSlave(m_externalClock, m_videoClock);
+    }
+}
+
+// 获取当前时间(秒)
+double SynchronizerV2::getCurrentTime() const {
+    // 使用av_gettime_relative获取相对时间(微秒),转换为秒
+    return av_gettime_relative() / 1000000.0;
+}
+
+// 更新统计信息
+void SynchronizerV2::updateStats() {
+    std::lock_guard<std::mutex> lock(m_statsMutex);
+    
+    // 更新时钟值
+    m_stats.audioClock = getClock(ClockType::AUDIO);
+    m_stats.videoClock = getClock(ClockType::VIDEO);
+    m_stats.externalClock = getClock(ClockType::EXTERNAL);
+    m_stats.masterClock = getMasterClock();
+    
+    // 计算音视频同步误差
+    if (m_hasAudio && m_hasVideo) {
+        m_stats.audioVideoSyncError = m_stats.audioClock - m_stats.videoClock;
+        
+        // 更新平均同步误差
+        double absError = std::fabs(m_stats.audioVideoSyncError);
+        m_stats.avgSyncError = (m_stats.avgSyncError * 0.9) + (absError * 0.1);
+        
+        // 更新最大同步误差
+        if (absError > m_stats.maxSyncError) {
+            m_stats.maxSyncError = absError;
+        }
+    }
+    
+    // 更新播放速度
+    m_stats.playbackSpeed = m_playbackSpeed;
+}
+
+// 通知同步错误
+void SynchronizerV2::notifySyncError(double error, const std::string& reason) const {
+    std::lock_guard<std::mutex> lock(m_callbackMutex);
+    if (m_syncErrorCallback) {
+        m_syncErrorCallback(error, reason);
+    }
+}
+
+// 通知帧丢弃
+void SynchronizerV2::notifyFrameDrop(ClockType type, int64_t pts) const {
+    std::lock_guard<std::mutex> lock(m_callbackMutex);
+    if (m_frameDropCallback) {
+        m_frameDropCallback(type, pts);
+    }
+    
+    // 更新统计信息
+    std::lock_guard<std::mutex> statsLock(m_statsMutex);
+    m_stats.droppedFrames++;
+}
+
+} // namespace utils
+} // namespace av

+ 213 - 0
AV/code/utils/utils_synchronizer_v2.h

@@ -11,6 +11,7 @@
 #include <limits>
 #include <memory>
 #include <mutex>
+#include <string>
 
 extern "C" {
 #include <libavutil/avutil.h>
@@ -20,6 +21,218 @@ extern "C" {
 namespace av {
 namespace utils {
 
+// 同步策略枚举
+enum class SyncStrategy {
+    AUDIO_MASTER,    // 音频作为主时钟源
+    VIDEO_MASTER,    // 视频作为主时钟源
+    EXTERNAL_MASTER  // 外部时钟作为主时钟源
+};
+
+// 时钟类型枚举
+enum class ClockType {
+    AUDIO,      // 音频时钟
+    VIDEO,      // 视频时钟
+    EXTERNAL    // 外部时钟
+};
+
+// 帧处理决策枚举
+enum class FrameAction {
+    DISPLAY,    // 显示帧
+    DROP,       // 丢弃帧
+    DUPLICATE,  // 重复帧
+    WAIT        // 等待
+};
+
+// 帧决策结构体
+struct FrameDecision {
+    FrameAction action = FrameAction::DISPLAY;
+    double delay = 0.0;        // 延迟时间(秒)
+    double syncError = 0.0;    // 同步误差(秒)
+    std::string reason;        // 决策原因
+};
+
+// 同步器配置结构体
+struct SyncConfigV2 {
+    SyncStrategy strategy = SyncStrategy::AUDIO_MASTER;  // 同步策略
+    
+    // 同步阈值(秒)
+    double syncThresholdMin = 0.04;  // 最小同步阈值
+    double syncThresholdMax = 0.1;   // 最大同步阈值
+    
+    // 帧处理阈值
+    double frameDropThreshold = 0.1;  // 丢帧阈值
+    double frameDupThreshold = 0.1;   // 重复帧阈值
+    
+    // 音频同步参数
+    double audioDiffThreshold = 0.1;  // 音频差异阈值
+    double audioDiffAvgCoef = 0.01;   // 音频差异平均系数
+    int audioDiffAvgCount = 20;       // 音频差异平均计数
+    
+    // 时钟速度调整参数
+    double clockSpeedMin = 0.9;       // 最小时钟速度
+    double clockSpeedMax = 1.1;       // 最大时钟速度
+    double clockSpeedStep = 0.001;    // 时钟速度调整步长
+    
+    // 缓冲区控制参数
+    int minFramesForSync = 2;         // 同步所需最小帧数
+    int maxFramesForSync = 10;        // 同步所需最大帧数
+    
+    // 无同步阈值(秒)
+    double noSyncThreshold = 10.0;    // 超过此阈值不进行同步
+};
+
+// 同步器统计信息结构体
+struct SyncStatsV2 {
+    double audioClock = 0.0;           // 音频时钟(秒)
+    double videoClock = 0.0;           // 视频时钟(秒)
+    double externalClock = 0.0;        // 外部时钟(秒)
+    double masterClock = 0.0;          // 主时钟(秒)
+    
+    double audioVideoSyncError = 0.0;  // 音视频同步误差(秒)
+    double avgSyncError = 0.0;         // 平均同步误差(秒)
+    double maxSyncError = 0.0;         // 最大同步误差(秒)
+    
+    int64_t droppedFrames = 0;         // 丢弃的帧数
+    int64_t duplicatedFrames = 0;       // 重复的帧数
+    
+    double playbackSpeed = 1.0;        // 播放速度
+};
+
+// 时钟结构体(基于ffplay.c中的Clock结构体)
+struct Clock {
+    double pts = 0.0;           // 时钟基准
+    double ptsDrift = 0.0;       // 时钟基准减去更新时间
+    double lastUpdated = 0.0;    // 最后更新时间
+    double speed = 1.0;          // 时钟速度
+    int serial = -1;             // 时钟基于此序列号的包
+    bool paused = false;         // 是否暂停
+    int queueSerial = -1;        // 当前包队列序列号,用于检测过时的时钟
+};
+
+// 前向声明
+namespace av {
+namespace player {
+class PlayerCoreV2;
+}
+}
+
+// 同步器类(基于ffplay.c实现)
+class SynchronizerV2 {
+    friend class av::player::PlayerCoreV2; // 声明PlayerCoreV2为友元类
+public:
+    // 构造函数和析构函数
+    explicit SynchronizerV2(const SyncConfigV2& config = SyncConfigV2());
+    ~SynchronizerV2();
+    
+    // 初始化和清理
+    ErrorCode initialize();
+    void close();
+    
+    // 控制接口
+    ErrorCode start();
+    ErrorCode stop();
+    ErrorCode pause();
+    ErrorCode resume();
+    ErrorCode reset();
+    
+    // 流信息设置
+    void setStreamInfo(bool hasAudio, bool hasVideo);
+    
+    // 时钟操作
+    double getClock(ClockType type) const;
+    void setClock(ClockType type, double pts, int serial);
+    void setClockAt(ClockType type, double pts, int serial, double time);
+    void setClockSpeed(ClockType type, double speed);
+    
+    // 主时钟操作
+    ClockType getMasterClockType() const;
+    double getMasterClock() const;
+    
+    // 同步操作
+    double computeTargetDelay(double frameDuration, double videoPts) const;
+    FrameDecision synchronizeVideo(double pts, int serial, double duration) const;
+    int synchronizeAudio(short* samples, int samplesSize, double pts);
+    
+    // 配置操作
+    void setConfig(const SyncConfigV2& config);
+    SyncConfigV2 getConfig() const;
+    void setSyncStrategy(SyncStrategy strategy);
+    SyncStrategy getSyncStrategy() const;
+    
+    // 播放速度控制
+    void setPlaybackSpeed(double speed);
+    double getPlaybackSpeed() const;
+    
+    // 统计信息
+    SyncStatsV2 getStats() const;
+    
+    // 回调设置
+    using SyncErrorCallback = std::function<void(double error, const std::string& reason)>;
+    using FrameDropCallback = std::function<void(ClockType type, int64_t pts)>;
+    
+    void setSyncErrorCallback(const SyncErrorCallback& callback);
+    void setFrameDropCallback(const FrameDropCallback& callback);
+    
+    // 调试信息
+    std::string getDebugInfo() const;
+    
+private:
+    // 内部时钟操作
+    void initClock(Clock& clock, int serial);
+    void syncClockToSlave(Clock& c, const Clock& slave);
+    void updateExternalClock();
+    void checkExternalClockSpeed();
+    
+    // 内部状态
+    std::atomic<bool> m_initialized{false};
+    std::atomic<bool> m_running{false};
+    std::atomic<bool> m_paused{false};
+    
+    // 配置
+    SyncConfigV2 m_config;
+    std::atomic<SyncStrategy> m_syncStrategy{SyncStrategy::AUDIO_MASTER};
+    
+    // 时钟
+    mutable std::mutex m_clockMutex;
+    Clock m_audioClock;
+    Clock m_videoClock;
+    Clock m_externalClock;
+    
+    // 流信息
+    std::atomic<bool> m_hasAudio{false};
+    std::atomic<bool> m_hasVideo{false};
+    
+    // 序列号
+    std::atomic<int> m_audioSerial{0};
+    std::atomic<int> m_videoSerial{0};
+    std::atomic<int> m_externalSerial{0};
+    
+    // 音频同步
+    double m_audioDiffCum{0.0};       // 用于音视频差异平均计算
+    int m_audioDiffAvgCount{0};
+    
+    // 播放控制
+    std::atomic<double> m_playbackSpeed{1.0};
+    
+    // 统计信息
+    mutable std::mutex m_statsMutex;
+    mutable SyncStatsV2 m_stats;
+    
+    // 回调
+    mutable std::mutex m_callbackMutex;
+    SyncErrorCallback m_syncErrorCallback;
+    FrameDropCallback m_frameDropCallback;
+    
+    // 帧计时器
+    mutable double m_frameTimer{0.0};
+    
+    // 辅助函数
+    double getCurrentTime() const;
+    void updateStats();
+    void notifySyncError(double error, const std::string& reason) const;
+    void notifyFrameDrop(ClockType type, int64_t pts) const;
+};
+
 } // namespace utils
 } // namespace av
 

+ 63 - 10
AV/test_player_with_ui.cpp

@@ -192,6 +192,12 @@ public slots:
                 infoText += QString("时长: %1s\n").arg(durationSec, 0, 'f', 2);
             }
             
+            // 更新视频流复选框状态
+            m_videoStreamCheckBox->setEnabled(info.hasVideo);
+            if (!info.hasVideo) {
+                m_videoStreamCheckBox->setChecked(false);
+            }
+            
             if (info.hasVideo) {
                 infoText += QString("视频: %1x%2 @ %3fps\n")
                            .arg(info.width).arg(info.height).arg(info.fps, 0, 'f', 2);
@@ -202,6 +208,12 @@ public slots:
                 // }
             }
             
+            // 更新音频流复选框状态
+            m_audioStreamCheckBox->setEnabled(info.hasAudio);
+            if (!info.hasAudio) {
+                m_audioStreamCheckBox->setChecked(false);
+            }
+            
             if (info.hasAudio) {
                 infoText += QString("音频: %1Hz, %2ch\n")
                            .arg(info.sampleRate).arg(info.channels);
@@ -282,6 +294,20 @@ private slots:
         }
     }
     
+    void onVideoStreamToggled(bool enabled) {
+        if (m_player) {
+            m_player->enableVideoStream(enabled);
+            Logger::instance().info(QString("视频流%1").arg(enabled ? "启用" : "禁用").toStdString());
+        }
+    }
+    
+    void onAudioStreamToggled(bool enabled) {
+        if (m_player) {
+            m_player->enableAudioStream(enabled);
+            Logger::instance().info(QString("音频流%1").arg(enabled ? "启用" : "禁用").toStdString());
+        }
+    }
+    
 private:
     void setupUI() {
         auto* mainLayout = new QHBoxLayout(this);
@@ -327,6 +353,17 @@ private:
         volumeLayout->addStretch();
         leftLayout->addLayout(volumeLayout);
         
+        // 流控制
+        auto* streamControlLayout = new QHBoxLayout;
+        m_videoStreamCheckBox = new QCheckBox("启用视频");
+        m_audioStreamCheckBox = new QCheckBox("启用音频");
+        m_videoStreamCheckBox->setChecked(true);
+        m_audioStreamCheckBox->setChecked(true);
+        streamControlLayout->addWidget(m_videoStreamCheckBox);
+        streamControlLayout->addWidget(m_audioStreamCheckBox);
+        streamControlLayout->addStretch();
+        leftLayout->addLayout(streamControlLayout);
+        
         mainLayout->addWidget(leftWidget, 2);
         
         // 右侧信息面板
@@ -366,16 +403,19 @@ private:
         // 创建同步配置
         SyncConfigV2 syncConfig;
         syncConfig.strategy = SyncStrategy::VIDEO_MASTER;
-        syncConfig.audioSyncThreshold = 0.040;
-        syncConfig.videoSyncThreshold = 0.020;
-        syncConfig.maxSyncError = 0.200;
-        syncConfig.clockUpdateInterval = 10;
-        syncConfig.smoothingWindow = 10;
-        syncConfig.enableAdaptiveSync = true;
-        syncConfig.enableFrameDrop = true;
-        syncConfig.enableFrameDuplicate = true;
-        syncConfig.enablePrediction = true;
-        syncConfig.enableErrorRecovery = true;
+        syncConfig.syncThresholdMin = 0.040;
+        syncConfig.syncThresholdMax = 0.100;
+        syncConfig.frameDropThreshold = 0.100;
+        syncConfig.frameDupThreshold = 0.100;
+        syncConfig.audioDiffThreshold = 0.100;
+        syncConfig.audioDiffAvgCoef = 0.01;
+        syncConfig.audioDiffAvgCount = 20;
+        syncConfig.clockSpeedMin = 0.9;
+        syncConfig.clockSpeedMax = 1.1;
+        syncConfig.clockSpeedStep = 0.001;
+        syncConfig.minFramesForSync = 2;
+        syncConfig.maxFramesForSync = 10;
+        syncConfig.noSyncThreshold = 10.0;
         
         // 创建播放器实例
         m_player = std::make_unique<PlayerCoreV2>(syncConfig);
@@ -383,6 +423,9 @@ private:
         // 设置视频渲染器
         m_player->setOpenGLVideoRenderer(m_videoRenderer);
         
+        // 设置初始音量
+        m_player->setVolume(m_volumeSlider->value() / 100.0);
+        
         // 创建事件回调
         m_callback = std::make_unique<UIPlayerCallback>(this);
         m_player->setEventCallback(m_callback.get());
@@ -400,6 +443,10 @@ private:
         connect(m_progressSlider, &QSlider::sliderReleased, this, &PlayerWindow::onProgressSliderReleased);
         
         connect(m_volumeSlider, &QSlider::valueChanged, this, &PlayerWindow::onVolumeChanged);
+        
+        // 连接流控制复选框信号
+        connect(m_videoStreamCheckBox, &QCheckBox::toggled, this, &PlayerWindow::onVideoStreamToggled);
+        connect(m_audioStreamCheckBox, &QCheckBox::toggled, this, &PlayerWindow::onAudioStreamToggled);
     }
     
     void loadFile(const std::string& filename) {
@@ -407,6 +454,10 @@ private:
         
         Logger::instance().info("Loading file: " + filename);
         
+        // 在打开文件前,根据复选框状态设置流启用状态
+        m_player->enableVideoStream(m_videoStreamCheckBox->isChecked());
+        m_player->enableAudioStream(m_audioStreamCheckBox->isChecked());
+        
         auto result = m_player->openFile(filename);
         if (result != ErrorCode::SUCCESS) {
             QString error = QString("无法打开文件: %1\n错误代码: %2")
@@ -430,6 +481,8 @@ private:
     QLabel* m_infoLabel;
     QLabel* m_statsLabel;
     QLabel* m_volumeLabel;
+    QCheckBox* m_videoStreamCheckBox;
+    QCheckBox* m_audioStreamCheckBox;
     QTimer* m_updateTimer;
     
     // 播放器相关