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

+ 2 - 1
AV/AV.pri

@@ -50,7 +50,8 @@ include($$PWD/code/player/player.pri)
 # SOURCES += $$PWD/test_audio_encoder.cpp
 # SOURCES += $$PWD/test_window_capture.cpp
 # SOURCES += $$PWD/test_utils.cpp
-SOURCES += $$PWD/test_audio_debug.cpp
+# SOURCES += $$PWD/test_audio_debug.cpp
+SOURCES += $$PWD/test_player_with_ui.cpp
 
 # Example files for PlayerV2 (uncomment to enable)
 # SOURCES += $$PWD/code/examples/player_v2_example.cpp

+ 48 - 5
AV/code/codec/codec_video_decoder.cpp

@@ -47,6 +47,28 @@ ErrorCode VideoDecoder::initialize(const CodecParams& params) {
     return ErrorCode::SUCCESS;
 }
 
+ErrorCode VideoDecoder::setStreamParameters(const AVCodecParameters* codecpar) {
+    if (!codecpar) {
+        AV_LOGGER_ERROR("流参数为空");
+        return ErrorCode::INVALID_PARAMS;
+    }
+    
+    if (codecpar->codec_type != AVMEDIA_TYPE_VIDEO) {
+        AV_LOGGER_ERROR("流类型不是视频");
+        return ErrorCode::INVALID_PARAMS;
+    }
+    
+    // 保存流参数以便后续使用
+    streamCodecpar_ = codecpar;
+    
+    AV_LOGGER_INFOF("设置流参数: 编解码器ID={}, 尺寸={}x{}, 格式={}", 
+                   static_cast<int>(codecpar->codec_id),
+                   codecpar->width, codecpar->height, 
+                   static_cast<int>(codecpar->format));
+    
+    return ErrorCode::SUCCESS;
+}
+
 ErrorCode VideoDecoder::open(const CodecParams& params) {
     std::lock_guard<std::mutex> lock(decodeMutex_);
     
@@ -187,6 +209,16 @@ ErrorCode VideoDecoder::initDecoder() {
         return ErrorCode::MEMORY_ALLOC_FAILED;
     }
     
+    // 如果有流参数,复制到解码器上下文
+    if (streamCodecpar_) {
+        int ret = avcodec_parameters_to_context(codecCtx_.get(), streamCodecpar_);
+        if (ret < 0) {
+            AV_LOGGER_ERRORF("复制流参数到解码器上下文失败: {}", ffmpeg_utils::errorToString(ret));
+            return static_cast<ErrorCode>(ret);
+        }
+        AV_LOGGER_INFO("成功复制流参数到解码器上下文");
+    }
+    
     // 设置硬件加速
     if (videoParams_.hardwareAccel && isHardwareDecoder(videoParams_.codecName)) {
         ErrorCode result = setupHardwareAcceleration();
@@ -250,24 +282,31 @@ ErrorCode VideoDecoder::setupDecoderParams() {
     if (videoParams_.width > 0 && videoParams_.height > 0) {
         codecCtx_->width = videoParams_.width;
         codecCtx_->height = videoParams_.height;
+        AV_LOGGER_INFOF("设置视频尺寸: {}x{}", videoParams_.width, videoParams_.height);
+    }
+    
+    // 设置像素格式(如果指定)
+    if (videoParams_.pixelFormat != AV_PIX_FMT_NONE) {
+        codecCtx_->pix_fmt = videoParams_.pixelFormat;
+        AV_LOGGER_INFOF("设置像素格式: {}", static_cast<int>(videoParams_.pixelFormat));
     }
     
     // 设置线程数
     if (videoParams_.threadCount > 0) {
         codecCtx_->thread_count = videoParams_.threadCount;
     } else {
-        codecCtx_->thread_count = std::thread::hardware_concurrency();
+        codecCtx_->thread_count = std::min(static_cast<int>(std::thread::hardware_concurrency()), 8);
     }
+    AV_LOGGER_INFOF("设置解码线程数: {}", codecCtx_->thread_count);
     
-    // 设置像素格式(如果指定)
-    if (videoParams_.pixelFormat != AV_PIX_FMT_NONE) {
-        codecCtx_->pix_fmt = videoParams_.pixelFormat;
-    }
+    // 设置解码器类型
+    codecCtx_->codec_type = AVMEDIA_TYPE_VIDEO;
     
     // 低延迟设置
     if (videoParams_.lowLatency) {
         codecCtx_->flags |= AV_CODEC_FLAG_LOW_DELAY;
         codecCtx_->flags2 |= AV_CODEC_FLAG2_FAST;
+        AV_LOGGER_INFO("启用低延迟模式");
     }
     
     // 针对不同解码器设置特定参数
@@ -287,6 +326,10 @@ ErrorCode VideoDecoder::setupDecoderParams() {
         }
     }
     
+    AV_LOGGER_INFOF("解码器参数设置完成: 尺寸={}x{}, 格式={}, 线程数={}", 
+                   codecCtx_->width, codecCtx_->height, 
+                   static_cast<int>(codecCtx_->pix_fmt), codecCtx_->thread_count);
+    
     return ErrorCode::SUCCESS;
 }
 

+ 6 - 0
AV/code/codec/codec_video_decoder.h

@@ -39,6 +39,9 @@ public:
     // 初始化方法
     ErrorCode initialize(const CodecParams& params);
     
+    // 从流参数设置解码器
+    ErrorCode setStreamParameters(const AVCodecParameters* codecpar);
+    
     // 解码接口
     ErrorCode decode(const AVPacketPtr& packet, std::vector<AVFramePtr>& frames) override;
     ErrorCode finishDecode(std::vector<AVFramePtr>& frames) override;
@@ -81,6 +84,9 @@ private:
     ErrorCode setupHardwareAcceleration();
     ErrorCode setupHardwareFrameContext();
     
+    // 流参数
+    const AVCodecParameters* streamCodecpar_ = nullptr;
+    
     ErrorCode decodeFrame(const AVPacketPtr& packet, std::vector<AVFramePtr>& frames);
     ErrorCode receiveFrames(std::vector<AVFramePtr>& frames);
     

+ 94 - 17
AV/code/player/audio_output.cpp

@@ -153,7 +153,7 @@ void AudioOutput::start()
     
     // 尝试多次启动音频设备
     int retryCount = 0;
-    const int maxRetries = 3;
+    const int maxRetries = 5; // 增加重试次数
     bool deviceStarted = false;
     
     while (retryCount < maxRetries && !deviceStarted) {
@@ -162,10 +162,14 @@ void AudioOutput::start()
             
             // 重新创建音频输出设备
             if (m_audioOutput) {
+                m_audioOutput->stop();
                 delete m_audioOutput;
                 m_audioOutput = nullptr;
             }
             
+            // 等待更长时间让系统释放音频资源
+            std::this_thread::sleep_for(std::chrono::milliseconds(500));
+            
             m_audioOutput = new QAudioOutput(m_audioFormat, this);
             if (!m_audioOutput) {
                 av::Logger::instance().error("Failed to recreate audio output device");
@@ -174,11 +178,16 @@ void AudioOutput::start()
             
             m_audioOutput->setBufferSize(32768);
             connect(m_audioOutput, &QAudioOutput::stateChanged, this, &AudioOutput::onStateChanged);
-            
-            // 等待一段时间再重试
-            std::this_thread::sleep_for(std::chrono::milliseconds(200));
         }
         
+        // 检查音频设备可用性
+        QAudioDeviceInfo deviceInfo = QAudioDeviceInfo::defaultOutputDevice();
+        if (deviceInfo.isNull()) {
+            av::Logger::instance().error("No audio output device available");
+            return;
+        }
+        
+        av::Logger::instance().debug("Starting audio device (attempt " + std::to_string(retryCount + 1) + ")");
         m_audioDevice = m_audioOutput->start();
         if (!m_audioDevice) {
             av::Logger::instance().warning("Failed to start audio output device (attempt " + std::to_string(retryCount + 1) + ")");
@@ -189,27 +198,38 @@ void AudioOutput::start()
         av::Logger::instance().debug("Audio device started, waiting for active state...");
         
         // 写入一些静音数据来激活设备
-        QByteArray silentData(1024, 0); // 1KB的静音数据
-        m_audioDevice->write(silentData);
+        QByteArray silentData(2048, 0); // 增加静音数据大小
+        qint64 written = m_audioDevice->write(silentData);
+        av::Logger::instance().debug("Written silent data: " + std::to_string(written) + " bytes");
         
         // 等待音频设备进入活动状态
-        int maxWaitMs = 1000; // 减少等待时间到1
+        int maxWaitMs = 2000; // 增加等待时间到2
         int waitMs = 0;
         while (m_audioOutput->state() != QAudio::ActiveState && waitMs < maxWaitMs) {
-            std::this_thread::sleep_for(std::chrono::milliseconds(50));
-            waitMs += 50;
+            std::this_thread::sleep_for(std::chrono::milliseconds(100));
+            waitMs += 100;
             
-            if (waitMs % 200 == 0) {
+            if (waitMs % 500 == 0) {
                 av::Logger::instance().debug("Audio output state: " + std::to_string(m_audioOutput->state()) + 
                     " (waited " + std::to_string(waitMs) + "ms)");
+                
+                // 尝试再次写入数据激活设备
+                if (m_audioDevice && m_audioOutput->state() == QAudio::IdleState) {
+                    QByteArray moreData(1024, 0);
+                    m_audioDevice->write(moreData);
+                }
             }
         }
         
         if (m_audioOutput->state() == QAudio::ActiveState) {
             deviceStarted = true;
             av::Logger::instance().info("Audio device successfully entered active state");
+        } else if (m_audioOutput->state() == QAudio::IdleState) {
+            // IdleState也可以接受,表示设备已准备好但暂时没有数据
+            deviceStarted = true;
+            av::Logger::instance().info("Audio device in idle state, ready for playback");
         } else {
-            av::Logger::instance().warning("Audio device failed to enter active state: " + std::to_string(m_audioOutput->state()) + " (attempt " + std::to_string(retryCount + 1) + ")");
+            av::Logger::instance().warning("Audio device failed to enter active/idle state: " + std::to_string(m_audioOutput->state()) + " (attempt " + std::to_string(retryCount + 1) + ")");
             m_audioDevice = nullptr;
             retryCount++;
         }
@@ -217,6 +237,7 @@ void AudioOutput::start()
     
     if (!deviceStarted) {
         av::Logger::instance().error("Failed to start audio device after " + std::to_string(maxRetries) + " attempts");
+        m_initialized = false;
         return;
     }
     
@@ -288,10 +309,43 @@ bool AudioOutput::writeFrame(const AVFramePtr& frame)
         return false;
     }
     
-    // 检查音频设备状态
-    if (m_audioOutput && m_audioOutput->state() != QAudio::ActiveState) {
-        av::Logger::instance().warning("Audio device not in active state: " + std::to_string(m_audioOutput->state()));
-        return false;
+    // 检查是否是EOF帧,EOF帧不需要处理,直接返回成功
+    if (!frame->data[0] && frame->nb_samples == 0) {
+        av::Logger::instance().debug("Received EOF frame in audio output, ignoring");
+        return true;
+    }
+    
+    // 检查音频设备状态 - 允许ActiveState和IdleState
+    if (m_audioOutput) {
+        QAudio::State currentState = m_audioOutput->state();
+        if (currentState != QAudio::ActiveState && currentState != QAudio::IdleState) {
+            av::Logger::instance().warning("Audio device not in playable state: " + std::to_string(currentState));
+            
+            // 尝试重新启动设备
+            if (currentState == QAudio::StoppedState) {
+                av::Logger::instance().info("Attempting to restart stopped audio device");
+                m_audioDevice = m_audioOutput->start();
+                if (!m_audioDevice) {
+                    av::Logger::instance().error("Failed to restart audio device");
+                    return false;
+                }
+                
+                // 写入静音数据激活设备
+                QByteArray silentData(1024, 0);
+                m_audioDevice->write(silentData);
+                
+                // 短暂等待设备状态更新
+                std::this_thread::sleep_for(std::chrono::milliseconds(50));
+                
+                currentState = m_audioOutput->state();
+                if (currentState != QAudio::ActiveState && currentState != QAudio::IdleState) {
+                    av::Logger::instance().error("Audio device restart failed, state: " + std::to_string(currentState));
+                    return false;
+                }
+            } else {
+                return false;
+            }
+        }
     }
     
     // 使用Synchronizer进行时间同步
@@ -491,23 +545,37 @@ void AudioOutput::cleanupResampler()
 QByteArray AudioOutput::convertFrame(const AVFramePtr& frame)
 {
     if (!frame) {
+        av::Logger::instance().error("convertFrame: null frame pointer");
         return QByteArray();
     }
     
+    // 检查帧数据有效性
+    if (!frame->data[0] || frame->nb_samples <= 0) {
+        av::Logger::instance().error("convertFrame: invalid frame data, nb_samples=" + std::to_string(frame->nb_samples));
+        return QByteArray();
+    }
+    
+    av::Logger::instance().debug("convertFrame: input samples=" + std::to_string(frame->nb_samples) + 
+                                ", channels=" + std::to_string(m_channels) + 
+                                ", format=" + std::to_string(m_inputFormat) + 
+                                ", need_resampling=" + std::to_string(m_needResampling));
+    
     if (!m_needResampling) {
         // 直接复制数据
         int dataSize = frame->nb_samples * m_channels * sizeof(int16_t);
+        av::Logger::instance().debug("convertFrame: direct copy, size=" + std::to_string(dataSize));
         return QByteArray(reinterpret_cast<const char*>(frame->data[0]), dataSize);
     }
     
     if (!m_swrContext) {
-        av::Logger::instance().error("Resampler not initialized");
+        av::Logger::instance().error("convertFrame: resampler not initialized");
         return QByteArray();
     }
     
     // 计算输出采样数
     int outputSamples = swr_get_out_samples(m_swrContext, frame->nb_samples);
     if (outputSamples <= 0) {
+        av::Logger::instance().error("convertFrame: invalid output samples=" + std::to_string(outputSamples));
         return QByteArray();
     }
     
@@ -518,13 +586,19 @@ QByteArray AudioOutput::convertFrame(const AVFramePtr& frame)
     
     uint8_t* outputBuffer = reinterpret_cast<uint8_t*>(outputData.data());
     
+    av::Logger::instance().debug("convertFrame: resampling " + std::to_string(frame->nb_samples) + 
+                                " -> " + std::to_string(outputSamples) + " samples");
+    
     // 执行重采样
     int convertedSamples = swr_convert(m_swrContext,
                                       &outputBuffer, outputSamples,
                                       const_cast<const uint8_t**>(frame->data), frame->nb_samples);
     
     if (convertedSamples < 0) {
-        av::Logger::instance().error("Audio resampling failed");
+        char errorBuf[256];
+        av_strerror(convertedSamples, errorBuf, sizeof(errorBuf));
+        av::Logger::instance().error("convertFrame: resampling failed with error " + 
+                                    std::to_string(convertedSamples) + ": " + std::string(errorBuf));
         return QByteArray();
     }
     
@@ -532,6 +606,9 @@ QByteArray AudioOutput::convertFrame(const AVFramePtr& frame)
     int actualDataSize = convertedSamples * outputChannels * sizeof(int16_t);
     outputData.resize(actualDataSize);
     
+    av::Logger::instance().debug("convertFrame: successfully converted " + std::to_string(convertedSamples) + 
+                                " samples, output size=" + std::to_string(actualDataSize));
+    
     return outputData;
 }
 

+ 151 - 115
AV/code/player/opengl_video_renderer.cpp

@@ -1,6 +1,6 @@
-#include "opengl_video_renderer.h"
+#include "../base/logger.h"
 
-// #include "../base/logger.h"
+#include "opengl_video_renderer.h"
 
 #include <QPainter>
 #include <QResizeEvent>
@@ -18,43 +18,33 @@ extern "C" {
 namespace av {
 namespace player {
 
-// 顶点着色器源码
+// 顶点着色器源码 - 参考yuvopenglwidget.cpp
 static const char* vertexShaderSource = R"(
-#version 330 core
-layout(location = 0) in vec2 position;
-layout(location = 1) in vec2 texCoord;
-
-out vec2 TexCoord;
+attribute vec4 vertexIn;
+attribute vec2 textureIn;
+varying vec2 TexCoord;
 
-uniform mat4 projection;
-
-void main() {
-    gl_Position = projection * vec4(position, 0.0, 1.0);
-    TexCoord = texCoord;
+void main(void) {
+    gl_Position = vertexIn;
+    TexCoord = textureIn;
 }
 )";
 
-// 片段着色器源码 (YUV420P)
+// 片段着色器源码 (YUV420P) - 参考yuvopenglwidget.cpp
 static const char* fragmentShaderSource = R"(
-#version 330 core
-in vec2 TexCoord;
-out vec4 FragColor;
-
+varying mediump vec2 TexCoord;
 uniform sampler2D yTexture;
 uniform sampler2D uTexture;
 uniform sampler2D vTexture;
 
-void main() {
-    float y = texture(yTexture, TexCoord).r;
-    float u = texture(uTexture, TexCoord).r - 0.5;
-    float v = texture(vTexture, TexCoord).r - 0.5;
-    
-    // YUV to RGB conversion
-    float r = y + 1.402 * v;
-    float g = y - 0.344 * u - 0.714 * v;
-    float b = y + 1.772 * u;
-    
-    FragColor = vec4(r, g, b, 1.0);
+void main(void) {
+    vec3 yuv;
+    vec3 rgb;
+    yuv.r = texture2D(yTexture, TexCoord).r;
+    yuv.g = texture2D(uTexture, TexCoord).r - 0.5;
+    yuv.b = texture2D(vTexture, TexCoord).r - 0.5;
+    rgb = mat3(1.0, 1.0, 1.0, 0.0, -0.138, 1.816, 1.540, -0.459, 0.0) * yuv;
+    gl_FragColor = vec4(rgb, 1.0);
 }
 )";
 
@@ -63,6 +53,10 @@ OpenGLVideoRenderer::OpenGLVideoRenderer(QWidget* parent)
     , m_videoWidth(0)
     , m_videoHeight(0)
     , m_inputFormat(AV_PIX_FMT_NONE)
+    , m_fps(25.0)
+    , m_textureY(0)
+    , m_textureU(0)
+    , m_textureV(0)
     , m_swsContext(nullptr)
     , m_yuvBuffer(nullptr)
     , m_yuvBufferSize(0)
@@ -96,7 +90,17 @@ OpenGLVideoRenderer::OpenGLVideoRenderer(QWidget* parent)
 
 OpenGLVideoRenderer::~OpenGLVideoRenderer()
 {
+    // 清理OpenGL资源
+    makeCurrent();
     cleanupOpenGLResources();
+    
+    // 删除纹理
+    if (m_textureY) glDeleteTextures(1, &m_textureY);
+    if (m_textureU) glDeleteTextures(1, &m_textureU);
+    if (m_textureV) glDeleteTextures(1, &m_textureV);
+    
+    doneCurrent();
+    
     if (m_swsContext) {
         sws_freeContext(m_swsContext);
         m_swsContext = nullptr;
@@ -233,11 +237,26 @@ bool OpenGLVideoRenderer::initialize(int width, int height, AVPixelFormat pixelF
 
 bool OpenGLVideoRenderer::renderFrame(const AVFramePtr& frame)
 {
-    qDebug() << "------->>>>>>>>>>>>>>>>>>-" << frame.get() << m_initialized.load();
+    // 使用Logger输出调试信息
+    std::string debugMsg = "[VideoRenderer] renderFrame called - frame: " + 
+                          std::to_string(reinterpret_cast<uintptr_t>(frame.get())) + 
+                          ", initialized: " + std::to_string(m_initialized.load()) + 
+                          ", glInitialized: " + std::to_string(m_glInitialized);
+    av::Logger::instance().debug(debugMsg);
+    
     if (!frame || !m_initialized) {
+        av::Logger::instance().warning("[VideoRenderer] renderFrame failed - frame or not initialized");
         return false;
     }
     
+    std::string frameInfo = "[VideoRenderer] Frame info - width: " + std::to_string(frame->width) + 
+                           ", height: " + std::to_string(frame->height) + 
+                           ", format: " + std::to_string(frame->format) + 
+                           ", linesize[0]: " + std::to_string(frame->linesize[0]) + 
+                           ", linesize[1]: " + std::to_string(frame->linesize[1]) + 
+                           ", linesize[2]: " + std::to_string(frame->linesize[2]);
+    av::Logger::instance().debug(frameInfo);
+    
     QMutexLocker locker(&m_mutex);
     
     // 更新纹理数据
@@ -252,6 +271,7 @@ bool OpenGLVideoRenderer::renderFrame(const AVFramePtr& frame)
         m_updateTimer->start(interval);
     }
     
+    av::Logger::instance().debug("[VideoRenderer] renderFrame completed successfully");
     return true;
 }
 
@@ -355,9 +375,8 @@ void OpenGLVideoRenderer::cleanupOpenGLResources()
     m_vertexBuffer.reset();
     m_indexBuffer.reset();
     m_vao.reset();
-    m_yTexture.reset();
-    m_uTexture.reset();
-    m_vTexture.reset();
+    
+    // 纹理在析构函数中删除,这里不需要处理
     
     m_glInitialized = false;
 }
@@ -378,6 +397,10 @@ bool OpenGLVideoRenderer::initializeShaders()
         return false;
     }
     
+    // 绑定属性位置 - 参考yuvopenglwidget.cpp
+    m_shaderProgram->bindAttributeLocation("vertexIn", 0);
+    m_shaderProgram->bindAttributeLocation("textureIn", 1);
+    
     // 链接着色器程序
     if (!m_shaderProgram->link()) {
         // av::Logger::instance().error("Failed to link shader program: " + m_shaderProgram->log().toStdString());
@@ -390,44 +413,20 @@ bool OpenGLVideoRenderer::initializeShaders()
 
 bool OpenGLVideoRenderer::initializeVertexData()
 {
-    // 顶点数据 (位置 + 纹理坐标)
-    static const float vertices[] = {
-        // 位置        // 纹理坐标
-        -1.0f, -1.0f,  0.0f, 1.0f,  // 左下
-         1.0f, -1.0f,  1.0f, 1.0f,  // 右下
-         1.0f,  1.0f,  1.0f, 0.0f,  // 右上
-        -1.0f,  1.0f,  0.0f, 0.0f   // 左上
-    };
-    
-    // 索引数据
-    static const unsigned int indices[] = {
-        0, 1, 2,  // 第一个三角形
-        2, 3, 0   // 第二个三角形
-    };
+    // 参考yuvopenglwidget.cpp的顶点数据设置
+    static const GLfloat vertices[] = {-1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f};
+    static const GLfloat texCoords[] = {0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f};
     
     // 创建VAO
     m_vao = std::make_unique<QOpenGLVertexArrayObject>();
     m_vao->create();
     m_vao->bind();
     
-    // 创建顶点缓冲区
-    m_vertexBuffer = std::make_unique<QOpenGLBuffer>(QOpenGLBuffer::VertexBuffer);
-    m_vertexBuffer->create();
-    m_vertexBuffer->bind();
-    m_vertexBuffer->allocate(vertices, sizeof(vertices));
-    
-    // 设置顶点属性
-    m_shaderProgram->enableAttributeArray(0);
-    m_shaderProgram->setAttributeBuffer(0, GL_FLOAT, 0, 2, 4 * sizeof(float));
-    
-    m_shaderProgram->enableAttributeArray(1);
-    m_shaderProgram->setAttributeBuffer(1, GL_FLOAT, 2 * sizeof(float), 2, 4 * sizeof(float));
-    
-    // 创建索引缓冲区
-    m_indexBuffer = std::make_unique<QOpenGLBuffer>(QOpenGLBuffer::IndexBuffer);
-    m_indexBuffer->create();
-    m_indexBuffer->bind();
-    m_indexBuffer->allocate(indices, sizeof(indices));
+    // 设置顶点,纹理数组并启用
+    glVertexAttribPointer(0, 2, GL_FLOAT, 0, 0, vertices);
+    glEnableVertexAttribArray(0);
+    glVertexAttribPointer(1, 2, GL_FLOAT, 0, 0, texCoords);
+    glEnableVertexAttribArray(1);
     
     m_vao->release();
 
@@ -437,38 +436,30 @@ bool OpenGLVideoRenderer::initializeVertexData()
 
 bool OpenGLVideoRenderer::createTextures()
 {
+    // 参考yuvopenglwidget.cpp创建纹理
     // 创建Y纹理
-    m_yTexture = std::make_unique<QOpenGLTexture>(QOpenGLTexture::Target2D);
-    m_yTexture->create();
-    m_yTexture->bind();
-    m_yTexture->setFormat(QOpenGLTexture::R8_UNorm);
-    m_yTexture->setSize(m_videoWidth, m_videoHeight);
-    m_yTexture->allocateStorage();
-    m_yTexture->setMinificationFilter(QOpenGLTexture::Linear);
-    m_yTexture->setMagnificationFilter(QOpenGLTexture::Linear);
-    m_yTexture->setWrapMode(QOpenGLTexture::ClampToEdge);
+    glGenTextures(1, &m_textureY);
+    glBindTexture(GL_TEXTURE_2D, m_textureY);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
     
     // 创建U纹理
-    m_uTexture = std::make_unique<QOpenGLTexture>(QOpenGLTexture::Target2D);
-    m_uTexture->create();
-    m_uTexture->bind();
-    m_uTexture->setFormat(QOpenGLTexture::R8_UNorm);
-    m_uTexture->setSize(m_videoWidth / 2, m_videoHeight / 2);
-    m_uTexture->allocateStorage();
-    m_uTexture->setMinificationFilter(QOpenGLTexture::Linear);
-    m_uTexture->setMagnificationFilter(QOpenGLTexture::Linear);
-    m_uTexture->setWrapMode(QOpenGLTexture::ClampToEdge);
+    glGenTextures(1, &m_textureU);
+    glBindTexture(GL_TEXTURE_2D, m_textureU);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
     
     // 创建V纹理
-    m_vTexture = std::make_unique<QOpenGLTexture>(QOpenGLTexture::Target2D);
-    m_vTexture->create();
-    m_vTexture->bind();
-    m_vTexture->setFormat(QOpenGLTexture::R8_UNorm);
-    m_vTexture->setSize(m_videoWidth / 2, m_videoHeight / 2);
-    m_vTexture->allocateStorage();
-    m_vTexture->setMinificationFilter(QOpenGLTexture::Linear);
-    m_vTexture->setMagnificationFilter(QOpenGLTexture::Linear);
-    m_vTexture->setWrapMode(QOpenGLTexture::ClampToEdge);
+    glGenTextures(1, &m_textureV);
+    glBindTexture(GL_TEXTURE_2D, m_textureV);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
 
     // av::Logger::instance().info("Textures created successfully");
     return true;
@@ -477,9 +468,19 @@ bool OpenGLVideoRenderer::createTextures()
 void OpenGLVideoRenderer::updateTextures(const AVFramePtr& frame)
 {
     if (!m_glInitialized || !frame) {
+        av::Logger::instance().warning("[VideoRenderer] updateTextures failed - glInitialized: " + 
+                                       std::to_string(m_glInitialized) + ", frame: " + 
+                                       std::to_string(reinterpret_cast<uintptr_t>(frame.get())));
         return;
     }
     
+    av::Logger::instance().debug("[VideoRenderer] updateTextures - video size: " + 
+                                std::to_string(m_videoWidth) + "x" + std::to_string(m_videoHeight) + 
+                                ", input format: " + std::to_string(m_inputFormat) + 
+                                ", frame format: " + std::to_string(frame->format) +
+                                ", linesize: [" + std::to_string(frame->linesize[0]) + ", " + 
+                                std::to_string(frame->linesize[1]) + ", " + std::to_string(frame->linesize[2]) + "]");
+    
     // 转换帧格式(如果需要)
     AVFrame* yuvFrame = frame.get();
     if (m_inputFormat != AV_PIX_FMT_YUV420P && m_swsContext) {
@@ -497,29 +498,60 @@ void OpenGLVideoRenderer::updateTextures(const AVFramePtr& frame)
         
         yuvFrame = tempFrame;
         
-        // 更新纹理数据
-        m_yTexture->bind();
-        m_yTexture->setData(QOpenGLTexture::Red, QOpenGLTexture::UInt8, yuvFrame->data[0], nullptr);
+        // 更新Y纹理数据
+        glActiveTexture(GL_TEXTURE0);
+        glBindTexture(GL_TEXTURE_2D, m_textureY);
+        glPixelStorei(GL_UNPACK_ROW_LENGTH, yuvFrame->linesize[0]);
+        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_videoWidth, m_videoHeight, 
+                       GL_RED, GL_UNSIGNED_BYTE, yuvFrame->data[0]);
         
-        m_uTexture->bind();
-        m_uTexture->setData(QOpenGLTexture::Red, QOpenGLTexture::UInt8, yuvFrame->data[1], nullptr);
+        // 更新U纹理数据
+        glActiveTexture(GL_TEXTURE1);
+        glBindTexture(GL_TEXTURE_2D, m_textureU);
+        glPixelStorei(GL_UNPACK_ROW_LENGTH, yuvFrame->linesize[1]);
+        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_videoWidth / 2, m_videoHeight / 2, 
+                       GL_RED, GL_UNSIGNED_BYTE, yuvFrame->data[1]);
         
-        m_vTexture->bind();
-        m_vTexture->setData(QOpenGLTexture::Red, QOpenGLTexture::UInt8, yuvFrame->data[2], nullptr);
+        // 更新V纹理数据
+        glActiveTexture(GL_TEXTURE2);
+        glBindTexture(GL_TEXTURE_2D, m_textureV);
+        glPixelStorei(GL_UNPACK_ROW_LENGTH, yuvFrame->linesize[2]);
+        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_videoWidth / 2, m_videoHeight / 2, 
+                       GL_RED, GL_UNSIGNED_BYTE, yuvFrame->data[2]);
+        
+        // 重置像素存储参数
+        glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
         
         av_frame_free(&tempFrame);
     } else {
-        // 直接更新纹理数据
-        m_yTexture->bind();
-        m_yTexture->setData(QOpenGLTexture::Red, QOpenGLTexture::UInt8, frame->data[0], nullptr);
+        // 参考yuvopenglwidget.cpp的纹理更新方式
+        av::Logger::instance().debug("[VideoRenderer] Updating textures for YUV420P format");
+        
+        // Y分量
+        glActiveTexture(GL_TEXTURE0);
+        glBindTexture(GL_TEXTURE_2D, m_textureY);
+        glPixelStorei(GL_UNPACK_ROW_LENGTH, frame->linesize[0]);
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, frame->width, frame->height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, frame->data[0]);
         
-        m_uTexture->bind();
-        m_uTexture->setData(QOpenGLTexture::Red, QOpenGLTexture::UInt8, frame->data[1], nullptr);
+        // U分量
+        glActiveTexture(GL_TEXTURE1);
+        glBindTexture(GL_TEXTURE_2D, m_textureU);
+        glPixelStorei(GL_UNPACK_ROW_LENGTH, frame->linesize[1]);
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, frame->width >> 1, frame->height >> 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, frame->data[1]);
         
-        m_vTexture->bind();
-        m_vTexture->setData(QOpenGLTexture::Red, QOpenGLTexture::UInt8, frame->data[2], nullptr);
+        // V分量
+        glActiveTexture(GL_TEXTURE2);
+        glBindTexture(GL_TEXTURE_2D, m_textureV);
+        glPixelStorei(GL_UNPACK_ROW_LENGTH, frame->linesize[2]);
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, frame->width >> 1, frame->height >> 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, frame->data[2]);
     }
     
+    // 重置像素存储参数
+    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+    
+    // 检查OpenGL错误
+    checkGLError("updateTextures");
+    
     // 强制更新显示
     update();
 }
@@ -579,17 +611,21 @@ void OpenGLVideoRenderer::renderCurrentFrame()
     m_shaderProgram->bind();
     m_vao->bind();
     
-    // 绑定纹理
-    m_yTexture->bind(0);
-    m_uTexture->bind(1);
-    m_vTexture->bind(2);
+    // 参考yuvopenglwidget.cpp的纹理绑定和uniform设置
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, m_textureY);
+    glUniform1i(m_shaderProgram->uniformLocation("yTexture"), 0);
+    
+    glActiveTexture(GL_TEXTURE1);
+    glBindTexture(GL_TEXTURE_2D, m_textureU);
+    glUniform1i(m_shaderProgram->uniformLocation("uTexture"), 1);
     
-    m_shaderProgram->setUniformValue("yTexture", 0);
-    m_shaderProgram->setUniformValue("uTexture", 1);
-    m_shaderProgram->setUniformValue("vTexture", 2);
+    glActiveTexture(GL_TEXTURE2);
+    glBindTexture(GL_TEXTURE_2D, m_textureV);
+    glUniform1i(m_shaderProgram->uniformLocation("vTexture"), 2);
     
-    // 绘制
-    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
+    // 参考yuvopenglwidget.cpp使用GL_TRIANGLE_STRIP绘制
+    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
     
     m_vao->release();
     m_shaderProgram->release();

+ 6 - 5
AV/code/player/opengl_video_renderer.h

@@ -7,6 +7,7 @@
 #include <QOpenGLShaderProgram>
 #include <QOpenGLBuffer>
 #include <QOpenGLVertexArrayObject>
+#include <QtOpenGL/qgl.h>
 #include <QMutex>
 #include <QTimer>
 #include <memory>
@@ -178,10 +179,10 @@ private:
     std::unique_ptr<QOpenGLBuffer> m_indexBuffer;
     std::unique_ptr<QOpenGLVertexArrayObject> m_vao;
     
-    // 纹理
-    std::unique_ptr<QOpenGLTexture> m_yTexture;
-    std::unique_ptr<QOpenGLTexture> m_uTexture;
-    std::unique_ptr<QOpenGLTexture> m_vTexture;
+    // 纹理 - 参考yuvopenglwidget.cpp
+    GLuint m_textureY;
+    GLuint m_textureU;
+    GLuint m_textureV;
     
     // 图像转换器
     SwsContext* m_swsContext;
@@ -219,4 +220,4 @@ private:
 } // namespace player
 } // namespace av
 
-#endif // AV_PLAYER_OPENGL_VIDEO_RENDERER_H 
+#endif // AV_PLAYER_OPENGL_VIDEO_RENDERER_H

+ 2 - 4
AV/code/player/player.pri

@@ -2,11 +2,9 @@
 HEADERS += \
     $$PWD/player_core_v2.h \
     $$PWD/audio_output.h \
-    $$PWD/opengl_video_renderer.h \
-    $$PWD/thread_manager.h
+    $$PWD/opengl_video_renderer.h
 
 SOURCES += \
     $$PWD/player_core_v2.cpp \
     $$PWD/audio_output.cpp \
-    $$PWD/opengl_video_renderer.cpp \
-    $$PWD/thread_manager.cpp
+    $$PWD/opengl_video_renderer.cpp

+ 190 - 80
AV/code/player/player_core_v2.cpp

@@ -92,15 +92,7 @@ PlayerCoreV2::PlayerCoreV2(const SyncConfigV2& syncConfig)
                 m_eventCallback->onFrameDropped(m_stats.droppedFrames);
             }
         });
-        
-        // 创建线程管理器
-        m_threadManager = std::make_unique<ThreadManager>();
-        if (!m_threadManager) {
-            Logger::instance().error("Failed to create thread manager");
-            setState(PlayerState::Error);
-            return;
-        }
-        
+
         // 创建解码器
         m_videoDecoder = std::make_unique<VideoDecoder>();
         if (!m_videoDecoder) {
@@ -210,19 +202,16 @@ ErrorCode PlayerCoreV2::openFile(const std::string& filename) {
     // 如果已设置视频渲染器且有视频流,重新初始化渲染器
     if (m_mediaInfo.hasVideo && m_openGLVideoRenderer) {
         AVStream* videoStream = m_formatContext->streams[m_mediaInfo.videoStreamIndex];
-        double fps = m_mediaInfo.fps > 0 ? m_mediaInfo.fps : 25.0;
         
-        bool rendererInitResult = m_openGLVideoRenderer->initialize(
+        bool rendererInitResult = m_openGLVideoRenderer->Open(
             videoStream->codecpar->width,
-            videoStream->codecpar->height,
-            static_cast<AVPixelFormat>(videoStream->codecpar->format),
-            fps
+            videoStream->codecpar->height
         );
         
         if (!rendererInitResult) {
             Logger::instance().warning("Failed to initialize OpenGL video renderer");
         } else {
-            Logger::instance().info("OpenGL video renderer initialized successfully with fps: " + std::to_string(fps));
+            Logger::instance().info("OpenGL video renderer initialized successfully");
         }
     }
     
@@ -274,15 +263,25 @@ ErrorCode PlayerCoreV2::play() {
         if (m_state == PlayerState::Paused) {
             m_audioOutput->resume();
         } else {
+            Logger::instance().info("Starting audio output device...");
             m_audioOutput->start();
+            
+            // 检查音频设备是否成功启动
+            if (!m_audioOutput->isPlaying()) {
+                Logger::instance().error("Audio output device failed to start");
+                // 不要因为音频失败而停止整个播放,继续播放视频
+                Logger::instance().warning("Continuing playback without audio");
+            } else {
+                Logger::instance().info("Audio output device started successfully");
+            }
         }
         
         // 设置音频参数
         m_audioOutput->setVolume(m_volume);
         m_audioOutput->setPlaybackSpeed(m_playbackSpeed);
         
-        // 给音频输出设备时间初始化
-        std::this_thread::sleep_for(std::chrono::milliseconds(50));
+        // 给音频输出设备更多时间初始化
+        std::this_thread::sleep_for(std::chrono::milliseconds(100));
     }
     
     // 启动线程
@@ -367,7 +366,7 @@ ErrorCode PlayerCoreV2::stop() {
     
     // 清空OpenGL视频渲染器
     if (m_openGLVideoRenderer) {
-        m_openGLVideoRenderer->clear();
+        m_openGLVideoRenderer->Close();
     }
     
     // 停止所有线程
@@ -530,7 +529,7 @@ SyncConfigV2 PlayerCoreV2::getSyncConfig() const {
     return SyncConfigV2();
 }
 
-void PlayerCoreV2::setOpenGLVideoRenderer(OpenGLVideoRenderer* renderer) {
+void PlayerCoreV2::setOpenGLVideoRenderer(OpenGLVideoWidget* renderer) {
     m_openGLVideoRenderer = renderer;
 }
 
@@ -726,40 +725,39 @@ bool PlayerCoreV2::setupVideoDecoder() {
         return false;
     }
     
-    // 分配解码器上下文
-    AVCodecContext* codecContext = avcodec_alloc_context3(codec);
-    if (!codecContext) {
-        Logger::instance().error("Failed to allocate video codec context");
-        return false;
-    }
-    
-    // 复制流参数到解码器上下文
-    if (avcodec_parameters_to_context(codecContext, videoStream->codecpar) < 0) {
-        Logger::instance().error("Failed to copy video codec parameters");
-        avcodec_free_context(&codecContext);
-        return false;
-    }
-    
-    // 打开解码器
-    if (avcodec_open2(codecContext, codec, nullptr) < 0) {
-        Logger::instance().error("Failed to open video codec");
-        avcodec_free_context(&codecContext);
-        return false;
-    }
+    Logger::instance().info("Found video codec: " + std::string(codec->name));
+    Logger::instance().info("Video stream info: width=" + std::to_string(videoStream->codecpar->width) + 
+                           ", height=" + std::to_string(videoStream->codecpar->height) + 
+                           ", format=" + std::to_string(videoStream->codecpar->format));
     
     // 创建视频解码器参数
     VideoDecoderParams videoParams;
     videoParams.codecName = codec->name;
-    videoParams.width = codecContext->width;
-    videoParams.height = codecContext->height;
-    videoParams.pixelFormat = codecContext->pix_fmt;
-    videoParams.hardwareAccel = true;
+    videoParams.width = videoStream->codecpar->width;
+    videoParams.height = videoStream->codecpar->height;
+    videoParams.pixelFormat = static_cast<AVPixelFormat>(videoStream->codecpar->format);
+    videoParams.hardwareAccel = false; // 先禁用硬件加速来排除问题
     videoParams.lowLatency = false;
     
+    Logger::instance().info("Video decoder params: codec=" + videoParams.codecName + 
+                           ", size=" + std::to_string(videoParams.width) + "x" + std::to_string(videoParams.height) + 
+                           ", format=" + std::to_string(static_cast<int>(videoParams.pixelFormat)));
+    
     // 初始化视频解码器
     if (m_videoDecoder->initialize(videoParams) != ErrorCode::SUCCESS) {
         Logger::instance().error("Failed to initialize video decoder");
-        avcodec_free_context(&codecContext);
+        return false;
+    }
+    
+    // 设置流参数
+    if (m_videoDecoder->setStreamParameters(videoStream->codecpar) != ErrorCode::SUCCESS) {
+        Logger::instance().error("Failed to set video decoder stream parameters");
+        return false;
+    }
+    
+    // 打开视频解码器
+    if (m_videoDecoder->open(videoParams) != ErrorCode::SUCCESS) {
+        Logger::instance().error("Failed to open video decoder");
         return false;
     }
     
@@ -1105,8 +1103,8 @@ void PlayerCoreV2::readThreadFunc() {
             }
             
             m_seeking = false;
-            setState(m_state == PlayerState::Seeking ? PlayerState::Playing : m_state);
-            
+            setState(m_state == PlayerState::Seeking ? PlayerState::Playing : m_state.load());
+
             lock.unlock();
             m_seekCondition.notify_all();
         }
@@ -1121,8 +1119,20 @@ void PlayerCoreV2::readThreadFunc() {
         int ret = av_read_frame(m_formatContext, packet);
         if (ret < 0) {
             if (ret == AVERROR_EOF) {
-                Logger::instance().info("End of file reached");
-                // 文件结束,可以选择循环播放或停止
+                Logger::instance().info("End of file reached, sending EOF packets to queues");
+                
+                // 向队列发送EOF标记,让解码线程知道文件结束
+                if (m_packetQueue) {
+                    // 创建EOF标记包
+                    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");
+                    }
+                }
                 break;
             } else {
                 Logger::instance().error("Error reading frame: " + std::to_string(ret));
@@ -1155,6 +1165,8 @@ void PlayerCoreV2::readThreadFunc() {
 void PlayerCoreV2::videoDecodeThreadFunc() {
     Logger::instance().info("Video decode thread started");
     
+    int packetCount = 0;
+    int frameCount = 0;
     while (!m_threadsShouldStop) {
         if (!m_packetQueue || !m_videoFrameQueue || !m_videoDecoder) {
             std::this_thread::sleep_for(std::chrono::milliseconds(10));
@@ -1165,43 +1177,97 @@ void PlayerCoreV2::videoDecodeThreadFunc() {
         AVPacket* packet = nullptr;
         while (!m_threadsShouldStop && !packet) {
             packet = m_packetQueue->pop();
-            if (packet && packet->stream_index != m_mediaInfo.videoStreamIndex) {
-                // packet已经被packetPtr管理,不需要手动释放
-                packet = nullptr;
+            if (packet) {
+                // 检查是否是EOF标记
+                if (packet->stream_index == -1 && packet->data == nullptr) {
+                    Logger::instance().info("Video decode thread received EOF packet");
+                    av_packet_free(&packet);
+                    
+                    // 向视频帧队列发送EOF标记
+                    if (m_videoFrameQueue) {
+                        AVFrame* eofFrame = av_frame_alloc();
+                        if (eofFrame) {
+                            eofFrame->data[0] = nullptr;
+                            eofFrame->width = 0;
+                            eofFrame->height = 0;
+                            eofFrame->pts = AV_NOPTS_VALUE;
+                            m_videoFrameQueue->push(eofFrame);
+                            Logger::instance().info("EOF frame sent to video frame queue");
+                        }
+                    }
+                    
+                    // 视频解码线程结束
+                    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));
             }
         }
         
-        if (!packet) continue;
+        if (!packet) {
+            Logger::instance().debug("Video decode thread: no more packets available");
+            continue;
+        }
+        
+        packetCount++;
+        Logger::instance().debug("Video decode thread got packet #" + std::to_string(packetCount) + 
+                                ", size=" + std::to_string(packet->size) + 
+                                ", pts=" + std::to_string(packet->pts));
         
         // 解码视频帧
         AVPacketPtr packetPtr(packet);
         std::vector<AVFramePtr> frames;
-        if (m_videoDecoder->decode(packetPtr, frames) == ErrorCode::SUCCESS) {
-            for (const auto& framePtr : frames) {
+        ErrorCode decodeResult = m_videoDecoder->decode(packetPtr, frames);
+        
+        Logger::instance().debug("Video decode result: " + std::to_string(static_cast<int>(decodeResult)) + 
+                                ", frames count: " + std::to_string(frames.size()));
+        
+        if (decodeResult == ErrorCode::SUCCESS) {
+            for (auto& framePtr : frames) {
                 if (framePtr && !m_threadsShouldStop) {
+                    frameCount++;
+                    Logger::instance().debug("Processing video frame #" + std::to_string(frameCount) + 
+                                            ", width=" + std::to_string(framePtr->width) + 
+                                            ", height=" + std::to_string(framePtr->height) + 
+                                            ", pts=" + std::to_string(framePtr->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");
                     }
                     
                     // 将帧放入队列
                     if (m_videoFrameQueue->size() < 30) { // 限制队列大小
-                        m_videoFrameQueue->push(framePtr.get());
+                        // 释放智能指针的所有权,让队列管理帧的生命周期
+                        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");
                     }
                 }
             }
+        } else {
+            Logger::instance().warning("Video decode failed with error: " + std::to_string(static_cast<int>(decodeResult)));
         }
         
         // packet已经被packetPtr管理,不需要手动释放
     }
     
-    Logger::instance().info("Video decode thread finished");
+    Logger::instance().info("Video decode thread finished, packets processed: " + std::to_string(packetCount) + 
+                           ", frames decoded: " + std::to_string(frameCount));
 }
 
 void PlayerCoreV2::audioDecodeThreadFunc() {
@@ -1219,11 +1285,35 @@ void PlayerCoreV2::audioDecodeThreadFunc() {
         AVPacket* packet = nullptr;
         while (!m_threadsShouldStop && !packet) {
             packet = m_packetQueue->pop();
-            if (packet && 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) {
+                // 检查是否是EOF标记
+                if (packet->stream_index == -1 && packet->data == nullptr) {
+                    Logger::instance().info("Audio decode thread received EOF packet");
+                    av_packet_free(&packet);
+                    
+                    // 向音频帧队列发送EOF标记
+                    if (m_audioFrameQueue) {
+                        AVFrame* eofFrame = av_frame_alloc();
+                        if (eofFrame) {
+                            eofFrame->data[0] = nullptr;
+                            eofFrame->nb_samples = 0;
+                            eofFrame->pts = AV_NOPTS_VALUE;
+                            m_audioFrameQueue->push(eofFrame);
+                            Logger::instance().info("EOF frame sent to audio frame queue");
+                        }
+                    }
+                    
+                    // 音频解码线程结束
+                    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));
@@ -1249,7 +1339,7 @@ void PlayerCoreV2::audioDecodeThreadFunc() {
                                 ", frames count: " + std::to_string(frames.size()));
         
         if (decodeResult == ErrorCode::SUCCESS) {
-            for (const auto& framePtr : frames) {
+            for (auto& framePtr : frames) {
                 if (framePtr && !m_threadsShouldStop) {
                     frameCount++;
                     Logger::instance().debug("Processing audio frame #" + std::to_string(frameCount) + 
@@ -1266,7 +1356,8 @@ void PlayerCoreV2::audioDecodeThreadFunc() {
                     
                     // 将帧放入队列
                     if (m_audioFrameQueue->size() < 100) { // 限制队列大小
-                        m_audioFrameQueue->push(framePtr.get());
+                        // 释放智能指针的所有权,让队列管理帧的生命周期
+                        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");
@@ -1296,13 +1387,18 @@ void PlayerCoreV2::videoPlayThreadFunc() {
             continue;
         }
         
-        // 获取视频帧
-        AVFrame* frame = m_videoFrameQueue->pop();
+        // 获取视频帧,使用超时避免无限阻塞
+        AVFrame* frame = m_videoFrameQueue->pop(100); // 100ms超时
         if (!frame) {
-            std::this_thread::sleep_for(std::chrono::milliseconds(5));
+            // 检查是否应该继续等待
+            if (m_threadsShouldStop) {
+                break;
+            }
             continue;
         }
         
+        Logger::instance().debug("Video play thread got frame, pts=" + std::to_string(frame->pts));
+        
         // 更新视频时钟
         if (frame->pts != AV_NOPTS_VALUE) {
             m_synchronizer->setVideoClock(frame->pts / 1000000.0); // 转换为秒
@@ -1311,12 +1407,14 @@ void PlayerCoreV2::videoPlayThreadFunc() {
         // 检查是否应该显示这一帧
         auto decision = m_synchronizer->shouldDisplayVideoFrame(frame->pts / 1000000.0);
         
+        // 创建智能指针管理帧内存
+        AVFramePtr framePtr(frame);
+        
         switch (decision.action) {
             case av::utils::FrameAction::DISPLAY:
                 // 显示帧
                 if (m_openGLVideoRenderer) {
-                    AVFramePtr framePtr(frame);
-                    m_openGLVideoRenderer->renderFrame(framePtr);
+                    m_openGLVideoRenderer->Render(framePtr.get());
                 }
                 
                 // 计算下一帧的延迟
@@ -1334,8 +1432,7 @@ void PlayerCoreV2::videoPlayThreadFunc() {
             case av::utils::FrameAction::Frame_DUPLICATE:
                 // 重复显示上一帧(这里简化处理)
                 if (m_openGLVideoRenderer) {
-                    AVFramePtr framePtr(frame);
-                    m_openGLVideoRenderer->renderFrame(framePtr);
+                    m_openGLVideoRenderer->Render(framePtr.get());
                 }
                 break;
                 
@@ -1344,13 +1441,12 @@ void PlayerCoreV2::videoPlayThreadFunc() {
                 auto delayMs = static_cast<int>(decision.delay * 1000);
                 std::this_thread::sleep_for(std::chrono::milliseconds(delayMs));
                 if (m_openGLVideoRenderer) {
-                    AVFramePtr framePtr(frame);
-                    m_openGLVideoRenderer->renderFrame(framePtr);
+                    m_openGLVideoRenderer->Render(framePtr.get());
                 }
                 break;
         }
         
-        av_frame_free(&frame);
+        // framePtr 会自动释放内存,无需手动调用 av_frame_free
         
         // 更新帧时间
         lastFrameTime = std::chrono::steady_clock::now();
@@ -1369,13 +1465,27 @@ void PlayerCoreV2::audioPlayThreadFunc() {
             continue;
         }
         
-        // 获取音频帧
-        AVFrame* frame = m_audioFrameQueue->pop();
+        // 获取音频帧,使用较长的超时时间以确保能接收到EOF帧
+        AVFrame* frame = m_audioFrameQueue->pop(100); // 100ms超时
         if (!frame) {
-            std::this_thread::sleep_for(std::chrono::milliseconds(5));
+            // 检查是否应该继续等待
+            if (m_threadsShouldStop) {
+                break;
+            }
             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) + 
@@ -1392,12 +1502,14 @@ void PlayerCoreV2::audioPlayThreadFunc() {
         Logger::instance().debug("Audio frame decision: action=" + std::to_string(static_cast<int>(decision.action)) + 
                                 ", delay=" + std::to_string(decision.delay));
         
+        // 创建智能指针管理帧内存
+        AVFramePtr framePtr(frame);
+        
         switch (decision.action) {
             case av::utils::FrameAction::DISPLAY:
                 // 播放音频帧
                 {
                     Logger::instance().debug("Writing audio frame to output device");
-                    AVFramePtr framePtr(frame);
                     bool writeResult = m_audioOutput->writeFrame(framePtr);
                     Logger::instance().debug("Audio frame write result: " + std::to_string(writeResult));
                 }
@@ -1418,7 +1530,6 @@ void PlayerCoreV2::audioPlayThreadFunc() {
                 // 重复播放(音频中较少使用)
                 {
                     Logger::instance().debug("Duplicating audio frame");
-                    AVFramePtr framePtr(frame);
                     bool writeResult = m_audioOutput->writeFrame(framePtr);
                     Logger::instance().debug("Audio frame duplicate write result: " + std::to_string(writeResult));
                 }
@@ -1430,14 +1541,13 @@ void PlayerCoreV2::audioPlayThreadFunc() {
                 std::this_thread::sleep_for(std::chrono::milliseconds(delayMs));
                 {
                     Logger::instance().debug("Writing delayed audio frame to output device");
-                    AVFramePtr framePtr(frame);
                     bool writeResult = m_audioOutput->writeFrame(framePtr);
                     Logger::instance().debug("Audio frame delayed write result: " + std::to_string(writeResult));
                 }
                 break;
         }
         
-        av_frame_free(&frame);
+        // framePtr 会自动释放内存,无需手动调用 av_frame_free
     }
     
     Logger::instance().info("Audio play thread finished, total frames processed: " + std::to_string(frameCount));

+ 7 - 11
AV/code/player/player_core_v2.h

@@ -7,12 +7,11 @@
 #include "../base/types.h"
 #include "../codec/codec_audio_decoder.h"
 #include "../codec/codec_video_decoder.h"
-#include "../utils/utils_packet_queue.h"
 #include "../utils/utils_frame_queue.h"
+#include "../utils/utils_packet_queue.h"
 #include "../utils/utils_synchronizer_v2.h"
-#include "thread_manager.h"
 #include "audio_output.h"
-#include "opengl_video_renderer.h"
+#include "../../AvRecorder/ui/opengl_video_widget.h"
 
 #include <memory>
 #include <atomic>
@@ -169,8 +168,8 @@ public:
     SyncConfigV2 getSyncConfig() const;
     
     // OpenGL渲染器设置
-    void setOpenGLVideoRenderer(OpenGLVideoRenderer* renderer);
-    OpenGLVideoRenderer* getOpenGLVideoRenderer() const { return m_openGLVideoRenderer; }
+    void setOpenGLVideoRenderer(OpenGLVideoWidget* renderer);
+    OpenGLVideoWidget* getOpenGLVideoRenderer() const { return m_openGLVideoRenderer; }
     
     // 帧获取接口(供UI渲染使用)
     AVFrame* getNextVideoFrame();   // 获取下一个视频帧
@@ -268,15 +267,12 @@ private:
     
     // 改进的同步器
     std::unique_ptr<SynchronizerV2> m_synchronizer;
-    
-    // 线程管理
-    std::unique_ptr<ThreadManager> m_threadManager;
-    
+
     // 音频输出
     std::unique_ptr<AudioOutput> m_audioOutput;
     
     // 视频渲染
-    OpenGLVideoRenderer* m_openGLVideoRenderer = nullptr;
+    OpenGLVideoWidget* m_openGLVideoRenderer = nullptr;
     
     // 播放控制
     std::atomic<double> m_volume{1.0};
@@ -328,4 +324,4 @@ private:
 } // namespace player
 } // namespace av
 
-#endif // AV_PLAYER_CORE_V2_H
+#endif // AV_PLAYER_CORE_V2_H

+ 0 - 622
AV/code/player/thread_manager.cpp

@@ -1,622 +0,0 @@
-#include "thread_manager.h"
-
-#include "../base/logger.h"
-#include "../base/media_common.h"
-#include "../codec/codec_audio_decoder.h"
-#include "../codec/codec_video_decoder.h"
-#include "../utils/utils_frame_queue.h"
-#include "../utils/utils_packet_queue.h"
-#include "../utils/utils_synchronizer_v2.h"
-#include "thread_manager.h"
-#include <chrono>
-#include <thread>
-#include <vector>
-
-namespace av {
-namespace player {
-
-// ThreadBase 实现
-ThreadBase::ThreadBase(const std::string& name) : m_name(name)
-{
-    av::Logger::instance().debug("Thread created: " + m_name);
-}
-
-ThreadBase::~ThreadBase()
-{
-    stop();
-    join();
-    av::Logger::instance().debug("Thread destroyed: " + m_name);
-}
-
-bool ThreadBase::start()
-{
-    if (m_running.load()) {
-        av::Logger::instance().warning("Thread already running: " + m_name);
-        return false;
-    }
-    
-    m_shouldStop = false;
-    m_thread = std::make_unique<std::thread>(&ThreadBase::threadEntry, this);
-    
-    av::Logger::instance().info("Thread started: " + m_name);
-    return true;
-}
-
-void ThreadBase::stop()
-{
-    if (!m_running.load()) {
-        return;
-    }
-    
-    m_shouldStop = true;
-    av::Logger::instance().info("Thread stop requested: " + m_name);
-}
-
-void ThreadBase::join()
-{
-    if (m_thread && m_thread->joinable()) {
-        m_thread->join();
-        m_thread.reset();
-        av::Logger::instance().info("Thread joined: " + m_name);
-    }
-}
-
-bool ThreadBase::isRunning() const
-{
-    return m_running.load();
-}
-
-void ThreadBase::threadEntry()
-{
-    m_running = true;
-    
-    try {
-        av::Logger::instance().info("Thread running: " + m_name);
-        run();
-    }
-    catch (const std::exception& e) {
-        av::Logger::instance().error("Thread exception in " + m_name + ": " + e.what());
-    }
-    catch (...) {
-        av::Logger::instance().error("Unknown exception in thread: " + m_name);
-    }
-    
-    m_running = false;
-    av::Logger::instance().info("Thread finished: " + m_name);
-}
-
-// ReadThread 实现
-ReadThread::ReadThread(AVFormatContext* formatContext,
-                       av::utils::PacketQueue* packetQueue,
-                       int videoStreamIndex,
-                       int audioStreamIndex)
-    : ThreadBase("ReadThread")
-    , m_formatContext(formatContext)
-    , m_packetQueue(packetQueue)
-    , m_videoStreamIndex(videoStreamIndex)
-    , m_audioStreamIndex(audioStreamIndex)
-{
-}
-
-void ReadThread::seek(int64_t timestamp)
-{
-    m_seekTarget = timestamp;
-    m_seeking = true;
-    av::Logger::instance().info("Seek requested to: " + std::to_string(timestamp));
-}
-
-void ReadThread::run()
-{
-    if (!m_formatContext || !m_packetQueue) {
-        av::Logger::instance().error("Invalid parameters for ReadThread");
-        return;
-    }
-    
-    while (!shouldStop()) {
-        // 处理跳转
-        if (m_seeking.load()) {
-            handleSeek();
-            continue;
-        }
-        
-        // 检查队列是否已满
-        if (m_packetQueue->full()) {
-            std::this_thread::sleep_for(std::chrono::milliseconds(10));
-            continue;
-        }
-        
-        // 读取数据包
-        if (!readPacket()) {
-            // 读取结束或出错
-            // EOF处理由队列内部管理
-            break;
-        }
-    }
-
-    av::Logger::instance().info("ReadThread finished");
-}
-
-bool ReadThread::readPacket()
-{
-    AVPacket* packet = av_packet_alloc();
-    if (!packet) {
-        av::Logger::instance().error("Failed to allocate packet");
-        return false;
-    }
-    
-    int ret = av_read_frame(m_formatContext, packet);
-    if (ret < 0) {
-        av_packet_free(&packet);
-        if (ret == AVERROR_EOF) {
-            av::Logger::instance().info("End of file reached");
-        } else {
-            av::Logger::instance().error("Error reading frame: " + std::to_string(ret));
-        }
-        return false;
-    }
-    
-    // 只处理我们关心的流
-    if (packet->stream_index == m_videoStreamIndex || 
-        packet->stream_index == m_audioStreamIndex) {
-        if (m_packetQueue->enqueue(packet) != av::ErrorCode::SUCCESS) {
-            av_packet_free(&packet);
-            return false;
-        }
-    } else {
-        av_packet_free(&packet);
-    }
-    
-    return true;
-}
-
-void ReadThread::handleSeek()
-{
-    int64_t seekTarget = m_seekTarget.load();
-    
-    // 执行跳转
-    int ret = av_seek_frame(m_formatContext, -1, seekTarget, AVSEEK_FLAG_BACKWARD);
-    if (ret < 0) {
-        av::Logger::instance().error("Seek failed: " + std::to_string(ret));
-    } else {
-        av::Logger::instance().info("Seek completed to: " + std::to_string(seekTarget));
-        // 清空队列
-        m_packetQueue->clear();
-    }
-    
-    m_seeking = false;
-}
-
-// VideoDecodeThread 实现
-VideoDecodeThread::VideoDecodeThread(av::utils::PacketQueue* packetQueue,
-                                     av::utils::FrameQueue* frameQueue,
-                                     VideoDecoder* decoder,
-                                     av::utils::SynchronizerV2* synchronizer,
-                                     int streamIndex,
-                                     AVCodecParameters* codecParams,
-                                     AVRational timeBase)
-    : ThreadBase("VideoDecodeThread")
-    , m_packetQueue(packetQueue)
-    , m_frameQueue(frameQueue)
-    , m_decoder(decoder)
-    , m_synchronizer(synchronizer)
-    , m_streamIndex(streamIndex)
-    , m_bsfContext(nullptr)
-    , m_frameOutputCallback(nullptr)
-    , m_timeBase(timeBase)
-{
-    if (codecParams) {
-        initBitStreamFilter(codecParams);
-    }
-}
-
-void VideoDecodeThread::setFrameOutputCallback(FrameOutputCallback callback)
-{
-    m_frameOutputCallback = callback;
-}
-
-VideoDecodeThread::~VideoDecodeThread()
-{
-    cleanupBitStreamFilter();
-}
-
-void VideoDecodeThread::run()
-{
-    if (!m_packetQueue || !m_frameQueue || !m_decoder) {
-        av::Logger::instance().error("Invalid parameters for VideoDecodeThread");
-        return;
-    }
-    
-    while (!shouldStop()) {
-        // 检查帧队列是否已满
-        if (m_frameQueue->full()) {
-            std::this_thread::sleep_for(std::chrono::milliseconds(10));
-            continue;
-        }
-        
-        // 解码帧
-        if (!decodeFrame()) {
-            if (m_packetQueue->empty()) {
-            break;
-        }
-            std::this_thread::sleep_for(std::chrono::milliseconds(1));
-        }
-    }
-    
-    av::Logger::instance().info("VideoDecodeThread finished");
-}
-
-bool VideoDecodeThread::decodeFrame()
-{
-    // 获取数据包
-    AVPacket* packet = m_packetQueue->dequeuePacket(10); // 10ms超时
-    if (!packet) {
-        return false;
-    }
-    
-    // 检查是否是视频包
-    if (packet->stream_index != m_streamIndex) {
-        av_packet_free(&packet);
-        return true;
-    }
-    
-    // 如果有比特流过滤器,先过滤数据包
-    AVPacket* filteredPacket = packet;
-    if (m_bsfContext) {
-        int ret = av_bsf_send_packet(m_bsfContext, packet);
-        if (ret < 0) {
-            av::Logger::instance().errorf("Failed to send packet to bitstream filter: {}",
-                                      av::ffmpeg_utils::errorToString(ret));
-            av_packet_free(&packet);
-            return false;
-        }
-        
-        AVPacket* outputPacket = av_packet_alloc();
-        ret = av_bsf_receive_packet(m_bsfContext, outputPacket);
-        if (ret < 0) {
-            if (ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) {
-                av::Logger::instance().errorf("Failed to receive packet from bitstream filter: {}",
-                                          av::ffmpeg_utils::errorToString(ret));
-            }
-            av_packet_free(&packet);
-            av_packet_free(&outputPacket);
-            return false;
-        }
-        
-        av_packet_free(&packet);
-        filteredPacket = outputPacket;
-    }
-    
-    // 解码
-    std::vector<AVFramePtr> frames;
-    AVPacketPtr packetPtr(filteredPacket);
-    ErrorCode result = m_decoder->decode(packetPtr, frames);
-    
-    if (result != ErrorCode::SUCCESS) {
-        av::Logger::instance().errorf("Video decode failed with error: {}", static_cast<int>(result));
-        return false;
-    }
-    
-    if (frames.empty()) {
-        // 这是正常情况,解码器可能需要更多输入
-        return true;
-    }
-    
-    av::Logger::instance().debugf("Successfully decoded {} video frames", frames.size());
-    
-    // 处理解码后的帧
-    for (auto& frame : frames) {
-        // 更新视频时钟
-        if (m_synchronizer && frame->pts != AV_NOPTS_VALUE) {
-            // 使用正确的时间基计算PTS
-            double pts = frame->pts * av_q2d(m_timeBase);
-            m_synchronizer->setVideoClock(pts);
-        }
-        
-        // 调用输出回调函数(用于视频渲染)
-        if (m_frameOutputCallback && frame) {
-            m_frameOutputCallback(frame);
-        }
-        
-        // 添加到帧队列
-        if (m_frameQueue->enqueue(frame.release()) != av::ErrorCode::SUCCESS) {
-            return false;
-        }
-    }
-    
-    return true;
-}
-
-bool VideoDecodeThread::initBitStreamFilter(AVCodecParameters* codecParams)
-{
-    if (!codecParams || codecParams->codec_id != AV_CODEC_ID_H264) {
-        return true; // 不需要比特流过滤器
-    }
-    
-    const AVBitStreamFilter* bsf = av_bsf_get_by_name("h264_mp4toannexb");
-    if (!bsf) {
-        av::Logger::instance().error("Failed to find h264_mp4toannexb bitstream filter");
-        return false;
-    }
-    
-    int ret = av_bsf_alloc(bsf, &m_bsfContext);
-    if (ret < 0) {
-        av::Logger::instance().errorf("Failed to allocate bitstream filter context: {}",
-                                  av::ffmpeg_utils::errorToString(ret));
-        return false;
-    }
-    
-    ret = avcodec_parameters_copy(m_bsfContext->par_in, codecParams);
-    if (ret < 0) {
-        av::Logger::instance().errorf("Failed to copy codec parameters to bitstream filter: {}",
-                                  av::ffmpeg_utils::errorToString(ret));
-        av_bsf_free(&m_bsfContext);
-        return false;
-    }
-    
-    ret = av_bsf_init(m_bsfContext);
-    if (ret < 0) {
-        av::Logger::instance().errorf("Failed to initialize bitstream filter: {}",
-                                  av::ffmpeg_utils::errorToString(ret));
-        av_bsf_free(&m_bsfContext);
-        return false;
-    }
-    
-    av::Logger::instance().info("H.264 bitstream filter initialized successfully");
-    return true;
-}
-
-void VideoDecodeThread::cleanupBitStreamFilter()
-{
-    if (m_bsfContext) {
-        av_bsf_free(&m_bsfContext);
-        m_bsfContext = nullptr;
-    }
-}
-
-// AudioDecodeThread 实现
-AudioDecodeThread::AudioDecodeThread(av::utils::PacketQueue* packetQueue,
-                                     av::utils::FrameQueue* frameQueue,
-                                     AudioDecoder* decoder,
-                                     av::utils::SynchronizerV2* synchronizer,
-                                     int streamIndex,
-                                     AVRational timeBase)
-    : ThreadBase("AudioDecodeThread")
-    , m_packetQueue(packetQueue)
-    , m_frameQueue(frameQueue)
-    , m_decoder(decoder)
-    , m_synchronizer(synchronizer)
-    , m_streamIndex(streamIndex)
-    , m_frameOutputCallback(nullptr)
-    , m_timeBase(timeBase)
-{
-}
-
-void AudioDecodeThread::setFrameOutputCallback(FrameOutputCallback callback)
-{
-    m_frameOutputCallback = callback;
-}
-
-void AudioDecodeThread::run()
-{
-    if (!m_packetQueue || !m_frameQueue || !m_decoder) {
-        av::Logger::instance().error("Invalid parameters for AudioDecodeThread");
-        return;
-    }
-    
-    while (!shouldStop()) {
-        // 检查帧队列是否已满
-        if (m_frameQueue->full()) {
-            std::this_thread::sleep_for(std::chrono::milliseconds(10));
-            continue;
-        }
-        
-        // 解码帧
-        if (!decodeFrame()) {
-            if (m_packetQueue->empty()) {
-                break;
-            }
-            std::this_thread::sleep_for(std::chrono::milliseconds(1));
-        }
-    }
-    
-    av::Logger::instance().info("AudioDecodeThread finished");
-}
-
-bool AudioDecodeThread::decodeFrame()
-{
-    // 获取数据包
-    AVPacket* packet = m_packetQueue->dequeuePacket(10); // 10ms超时
-    if (!packet) {
-        return false;
-    }
-    
-    // 检查是否是音频包
-    if (packet->stream_index != m_streamIndex) {
-        av_packet_free(&packet);
-        return true;
-    }
-    
-    // 解码
-    std::vector<AVFramePtr> frames;
-    AVPacketPtr packetPtr(packet);
-    ErrorCode result = m_decoder->decode(packetPtr, frames);
-    
-    if (result != ErrorCode::SUCCESS) {
-        av::Logger::instance().errorf("Audio decode failed with error: {}", static_cast<int>(result));
-        return false;
-    }
-    
-    if (frames.empty()) {
-        // 这是正常情况,解码器可能需要更多输入
-        return true;
-    }
-    
-    av::Logger::instance().debugf("Successfully decoded {} audio frames", frames.size());
-    
-    // 处理解码后的帧
-    for (auto& frame : frames) {
-        // 更新音频时钟
-        if (m_synchronizer && frame->pts != AV_NOPTS_VALUE) {
-            // 使用正确的时间基计算PTS
-            double pts = frame->pts * av_q2d(m_timeBase);
-            m_synchronizer->setAudioClock(pts);
-        }
-        
-        // 调用输出回调函数(用于音频输出)
-        if (m_frameOutputCallback && frame) {
-            try {
-                m_frameOutputCallback(frame);
-            } catch (const std::exception& e) {
-                av::Logger::instance().error("Exception in audio frame output callback: " + std::string(e.what()));
-            } catch (...) {
-                av::Logger::instance().error("Unknown exception in audio frame output callback");
-            }
-        }
-        
-        // 添加到帧队列
-        if (m_frameQueue->enqueue(frame.release()) != av::ErrorCode::SUCCESS) {
-            return false;
-        }
-    }
-    
-    return true;
-}
-
-// ThreadManager 实现
-ThreadManager::ThreadManager()
-{
-    av::Logger::instance().debug("ThreadManager created");
-}
-
-ThreadManager::~ThreadManager()
-{
-    stopAll();
-    joinAll();
-    av::Logger::instance().debug("ThreadManager destroyed");
-}
-
-bool ThreadManager::createReadThread(AVFormatContext* formatContext,
-                                     av::utils::PacketQueue* packetQueue,
-                                     int videoStreamIndex,
-                                     int audioStreamIndex)
-{
-    if (m_readThread) {
-        av::Logger::instance().warning("ReadThread already exists");
-        return false;
-    }
-    
-    m_readThread = std::make_unique<ReadThread>(formatContext, packetQueue, 
-                                                videoStreamIndex, audioStreamIndex);
-    av::Logger::instance().info("ReadThread created");
-    return true;
-}
-
-bool ThreadManager::createVideoDecodeThread(av::utils::PacketQueue* packetQueue,
-                                            av::utils::FrameQueue* frameQueue,
-                                            VideoDecoder* decoder,
-                                            av::utils::SynchronizerV2* synchronizer,
-                                            int streamIndex,
-                                            AVCodecParameters* codecParams,
-                                            AVRational timeBase)
-{
-    if (m_videoDecodeThread) {
-        av::Logger::instance().warning("VideoDecodeThread already exists");
-        return false;
-    }
-    
-    m_videoDecodeThread = std::make_unique<VideoDecodeThread>(packetQueue, frameQueue,
-                                                              decoder, synchronizer, streamIndex, codecParams, timeBase);
-    av::Logger::instance().info("VideoDecodeThread created");
-    return true;
-}
-
-bool ThreadManager::createAudioDecodeThread(av::utils::PacketQueue* packetQueue,
-                                            av::utils::FrameQueue* frameQueue,
-                                            AudioDecoder* decoder,
-                                            av::utils::SynchronizerV2* synchronizer,
-                                            int streamIndex,
-                                            AVRational timeBase)
-{
-    if (m_audioDecodeThread) {
-        av::Logger::instance().warning("AudioDecodeThread already exists");
-        return false;
-    }
-    
-    m_audioDecodeThread = std::make_unique<AudioDecodeThread>(packetQueue, frameQueue,
-                                                              decoder, synchronizer, streamIndex, timeBase);
-    av::Logger::instance().info("AudioDecodeThread created");
-    return true;
-}
-
-bool ThreadManager::startAll()
-{
-    bool success = true;
-    
-    if (m_readThread && !m_readThread->start()) {
-        av::Logger::instance().error("Failed to start ReadThread");
-        success = false;
-    }
-    
-    if (m_videoDecodeThread && !m_videoDecodeThread->start()) {
-        av::Logger::instance().error("Failed to start VideoDecodeThread");
-        success = false;
-    }
-    
-    if (m_audioDecodeThread && !m_audioDecodeThread->start()) {
-        av::Logger::instance().error("Failed to start AudioDecodeThread");
-        success = false;
-    }
-    
-    if (success) {
-        av::Logger::instance().info("All threads started successfully");
-    }
-    
-    return success;
-}
-
-void ThreadManager::stopAll()
-{
-    if (m_readThread) {
-        m_readThread->stop();
-    }
-    
-    if (m_videoDecodeThread) {
-        m_videoDecodeThread->stop();
-    }
-    
-    if (m_audioDecodeThread) {
-        m_audioDecodeThread->stop();
-    }
-    
-    av::Logger::instance().info("All threads stop requested");
-}
-
-void ThreadManager::joinAll()
-{
-    if (m_readThread) {
-        m_readThread->join();
-        m_readThread.reset();
-    }
-    
-    if (m_videoDecodeThread) {
-        m_videoDecodeThread->join();
-        m_videoDecodeThread.reset();
-    }
-    
-    if (m_audioDecodeThread) {
-        m_audioDecodeThread->join();
-        m_audioDecodeThread.reset();
-    }
-    
-    av::Logger::instance().info("All threads joined");
-}
-
-bool ThreadManager::hasRunningThreads() const
-{
-    return (m_readThread && m_readThread->isRunning()) ||
-           (m_videoDecodeThread && m_videoDecodeThread->isRunning()) ||
-           (m_audioDecodeThread && m_audioDecodeThread->isRunning());
-}
-
-} // namespace player
-} // namespace av

+ 0 - 317
AV/code/player/thread_manager.h

@@ -1,317 +0,0 @@
-#pragma once
-
-#include <thread>
-#include <atomic>
-#include <memory>
-#include <functional>
-#include <mutex>
-#include "../base/types.h"
-
-extern "C" {
-#include <libavformat/avformat.h>
-#include <libavcodec/avcodec.h>
-#include <libavcodec/bsf.h>
-}
-
-namespace av {
-
-// 前向声明codec命名空间中的类
-namespace codec {
-    class VideoDecoder;
-    class AudioDecoder;
-}
-
-namespace player {
-
-}
-
-namespace utils {
-class SynchronizerV2;
-}
-
-namespace utils {
-class PacketQueue;
-class FrameQueue;
-}
-
-namespace player {
-
-// 使用codec命名空间中的解码器
-using VideoDecoder = av::codec::VideoDecoder;
-using AudioDecoder = av::codec::AudioDecoder;
-
-// 帧输出回调函数类型定义
-using FrameOutputCallback = std::function<void(const AVFramePtr&)>;
-
-/**
- * @brief 线程基类
- */
-class ThreadBase {
-public:
-    ThreadBase(const std::string& name);
-    virtual ~ThreadBase();
-    
-    // 禁用拷贝
-    ThreadBase(const ThreadBase&) = delete;
-    ThreadBase& operator=(const ThreadBase&) = delete;
-    
-    /**
-     * @brief 启动线程
-     */
-    bool start();
-    
-    /**
-     * @brief 停止线程
-     */
-    void stop();
-    
-    /**
-     * @brief 等待线程结束
-     */
-    void join();
-    
-    /**
-     * @brief 检查线程是否正在运行
-     */
-    bool isRunning() const;
-    
-    /**
-     * @brief 获取线程名称
-     */
-    const std::string& getName() const { return m_name; }
-    
-protected:
-    /**
-     * @brief 线程主函数,子类需要实现
-     */
-    virtual void run() = 0;
-    
-    /**
-     * @brief 检查是否应该停止
-     */
-    bool shouldStop() const { return m_shouldStop.load(); }
-    
-private:
-    std::string m_name;
-    std::unique_ptr<std::thread> m_thread;
-    std::atomic<bool> m_running{false};
-    std::atomic<bool> m_shouldStop{false};
-    
-    void threadEntry();
-};
-
-/**
- * @brief 读取线程,负责从媒体文件读取数据包
- */
-class ReadThread : public ThreadBase {
-public:
-    ReadThread(AVFormatContext* formatContext, 
-               av::utils::PacketQueue* packetQueue,
-               int videoStreamIndex = -1,
-               int audioStreamIndex = -1);
-    
-    ~ReadThread() override = default;
-    
-    /**
-     * @brief 设置跳转目标
-     */
-    void seek(int64_t timestamp);
-    
-protected:
-    void run() override;
-    
-private:
-    AVFormatContext* m_formatContext;
-    av::utils::PacketQueue* m_packetQueue;
-    int m_videoStreamIndex;
-    int m_audioStreamIndex;
-    std::atomic<int64_t> m_seekTarget{-1};
-    std::atomic<bool> m_seeking{false};
-    
-    bool readPacket();
-    void handleSeek();
-};
-
-/**
- * @brief 视频解码线程
- */
-class VideoDecodeThread : public ThreadBase {
-public:
-    VideoDecodeThread(av::utils::PacketQueue* packetQueue,
-                      av::utils::FrameQueue* frameQueue,
-                      VideoDecoder* decoder,
-                      av::utils::SynchronizerV2* synchronizer,
-                      int streamIndex,
-                      AVCodecParameters* codecParams = nullptr,
-                      AVRational timeBase = {1, 1000000});
-
-    ~VideoDecodeThread() override;
-
-    /**
-     * @brief 设置帧输出回调函数
-     */
-    void setFrameOutputCallback(FrameOutputCallback callback);
-    
-protected:
-    void run() override;
-    
-private:
-    av::utils::PacketQueue* m_packetQueue;
-    av::utils::FrameQueue* m_frameQueue;
-    VideoDecoder* m_decoder;
-    av::utils::SynchronizerV2* m_synchronizer;
-    int m_streamIndex;
-    AVBSFContext* m_bsfContext;
-    FrameOutputCallback m_frameOutputCallback;
-    AVRational m_timeBase;
-    
-    bool decodeFrame();
-    bool initBitStreamFilter(AVCodecParameters* codecParams);
-    void cleanupBitStreamFilter();
-};
-
-/**
- * @brief 音频解码线程
- */
-class AudioDecodeThread : public ThreadBase {
-public:
-    AudioDecodeThread(av::utils::PacketQueue* packetQueue,
-                      av::utils::FrameQueue* frameQueue,
-                      AudioDecoder* decoder,
-                      av::utils::SynchronizerV2* synchronizer,
-                      int streamIndex,
-                      AVRational timeBase = {1, 1000000});
-
-    ~AudioDecodeThread() override = default;
-
-    /**
-     * @brief 设置帧输出回调函数
-     */
-    void setFrameOutputCallback(FrameOutputCallback callback);
-    
-protected:
-    void run() override;
-    
-private:
-    av::utils::PacketQueue* m_packetQueue;
-    av::utils::FrameQueue* m_frameQueue;
-    AudioDecoder* m_decoder;
-    av::utils::SynchronizerV2* m_synchronizer;
-    int m_streamIndex;
-    FrameOutputCallback m_frameOutputCallback;
-    AVRational m_timeBase;
-    
-    bool decodeFrame();
-};
-
-/**
- * @brief 线程管理器,统一管理所有播放相关线程
- */
-class ThreadManager {
-public:
-    ThreadManager();
-    ~ThreadManager();
-    
-    // 禁用拷贝
-    ThreadManager(const ThreadManager&) = delete;
-    ThreadManager& operator=(const ThreadManager&) = delete;
-    
-    /**
-     * @brief 创建读取线程
-     */
-    bool createReadThread(AVFormatContext* formatContext,
-                          av::utils::PacketQueue* packetQueue,
-                          int videoStreamIndex = -1,
-                          int audioStreamIndex = -1);
-    
-    /**
-     * @brief 创建视频解码线程
-     */
-    bool createVideoDecodeThread(av::utils::PacketQueue* packetQueue,
-                                 av::utils::FrameQueue* frameQueue,
-                                 VideoDecoder* decoder,
-                                 av::utils::SynchronizerV2* synchronizer,
-                                 int streamIndex,
-                                 AVCodecParameters* codecParams = nullptr,
-                                 AVRational timeBase = {1, 1000000});
-
-    /**
-     * @brief 创建音频解码线程
-     */
-    bool createAudioDecodeThread(av::utils::PacketQueue* packetQueue,
-                                 av::utils::FrameQueue* frameQueue,
-                                 AudioDecoder* decoder,
-                                 av::utils::SynchronizerV2* synchronizer,
-                                 int streamIndex,
-                                 AVRational timeBase = {1, 1000000});
-
-    /**
-     * @brief 启动所有线程
-     */
-    bool startAll();
-    
-    /**
-     * @brief 停止所有线程
-     */
-    void stopAll();
-    
-    /**
-     * @brief 等待所有线程结束
-     */
-    void joinAll();
-    
-    /**
-     * @brief 检查是否有线程正在运行
-     */
-    bool hasRunningThreads() const;
-    
-    /**
-     * @brief 获取读取线程
-     */
-    ReadThread* getReadThread() const { return m_readThread.get(); }
-    
-    /**
-     * @brief 获取视频解码线程
-     */
-    VideoDecodeThread* getVideoDecodeThread() const { return m_videoDecodeThread.get(); }
-    
-    /**
-     * @brief 获取音频解码线程
-     */
-    AudioDecodeThread* getAudioDecodeThread() const { return m_audioDecodeThread.get(); }
-    
-private:
-    std::unique_ptr<ReadThread> m_readThread;
-    std::unique_ptr<VideoDecodeThread> m_videoDecodeThread;
-    std::unique_ptr<AudioDecodeThread> m_audioDecodeThread;
-};
-
-/**
- * @brief 线程安全的回调函数包装器
- */
-template<typename Func>
-class ThreadSafeCallback {
-public:
-    ThreadSafeCallback(Func&& func) : m_func(std::forward<Func>(func)) {}
-    
-    template<typename... Args>
-    auto operator()(Args&&... args) -> decltype(m_func(std::forward<Args>(args)...)) {
-        std::lock_guard<std::mutex> lock(m_mutex);
-        return m_func(std::forward<Args>(args)...);
-    }
-    
-private:
-    Func m_func;
-    mutable std::mutex m_mutex;
-};
-
-/**
-     * @brief 创建线程安全的回调函数
-     */
-template<typename Func>
-auto makeThreadSafeCallback(Func&& func) {
-    return ThreadSafeCallback<Func>(std::forward<Func>(func));
-}
-
-} // namespace player
-} // namespace av

+ 89 - 56
AV/code/utils/utils_synchronizer_v2.cpp

@@ -674,59 +674,62 @@ ErrorCode SynchronizerV2::updateClock(ClockType type, double pts, double time, i
         return ErrorCode::NOT_INITIALIZED;
     }
     
-    std::lock_guard<std::mutex> lock(clockMutex_);
-    
-    ClockInfo* clock = nullptr;
-    switch (type) {
-        case ClockType::AUDIO:
-            clock = &audioClock_;
-            break;
-        case ClockType::VIDEO:
-            clock = &videoClock_;
-            break;
-        case ClockType::EXTERNAL:
-            clock = &externalClock_;
-            break;
-        default:
-            return ErrorCode::INVALID_PARAMS;
-    }
-    
-    if (time < 0) {
-        time = getCurrentTime();
-    }
-    
-    // 检查序列号
-    if (serial != 0 && clock->serial != serial) {
-        // 序列号不匹配,可能是seek操作,重置时钟
-        resetClock(type);
-        clock->serial = serial;
-    }
-    
-    // 更新时钟
-    clock->pts = pts;
-    clock->time = time;
-    clock->lastUpdate = std::chrono::steady_clock::now();
-    
-    // 平滑处理
-    if (config_.smoothingWindow > 1) {
-        clock->smoothedPts = smoothClock(type, pts);
-    } else {
-        clock->smoothedPts = pts;
-    }
-    
-    // 更新历史记录
-    updateClockHistory(type, pts);
+    // 在锁内更新时钟数据
+    {
+        std::lock_guard<std::mutex> lock(clockMutex_);
+        
+        ClockInfo* clock = nullptr;
+        switch (type) {
+            case ClockType::AUDIO:
+                clock = &audioClock_;
+                break;
+            case ClockType::VIDEO:
+                clock = &videoClock_;
+                break;
+            case ClockType::EXTERNAL:
+                clock = &externalClock_;
+                break;
+            default:
+                return ErrorCode::INVALID_PARAMS;
+        }
+        
+        if (time < 0) {
+            time = getCurrentTime();
+        }
+        
+        // 检查序列号
+        if (serial != 0 && clock->serial != serial) {
+            // 序列号不匹配,可能是seek操作,重置时钟
+            resetClock(type);
+            clock->serial = serial;
+        }
+        
+        // 更新时钟
+        clock->pts = pts;
+        clock->time = time;
+        clock->lastUpdate = std::chrono::steady_clock::now();
+        
+        // 平滑处理
+        if (config_.smoothingWindow > 1) {
+            clock->smoothedPts = smoothClock(type, pts);
+        } else {
+            clock->smoothedPts = pts;
+        }
+        
+        // 更新历史记录
+        updateClockHistory(type, pts);
+        
+        // 定期更新统计信息
+        auto now = std::chrono::steady_clock::now();
+        if (std::chrono::duration_cast<std::chrono::milliseconds>(now - lastStatsUpdate_).count() > 100) {
+            updateStats();
+            lastStatsUpdate_ = now;
+        }
+    } // 释放clockMutex_锁
     
-    // 更新同步状态
+    // 在锁外更新同步状态,避免死锁
     updateSyncState();
     
-    // 定期更新统计信息
-    auto now = std::chrono::steady_clock::now();
-    if (std::chrono::duration_cast<std::chrono::milliseconds>(now - lastStatsUpdate_).count() > 100) {
-        updateStats();
-        lastStatsUpdate_ = now;
-    }
-    
     return ErrorCode::SUCCESS;
 }
 
@@ -871,6 +874,7 @@ void SynchronizerV2::updateSyncState() {
     double syncError = calculateSyncErrorInternal();
     
     SyncState newState = state_;
+    bool needRecovery = false;
     
     if (syncError <= config_.syncThreshold) {
         newState = SyncState::SYNCHRONIZED;
@@ -881,9 +885,9 @@ void SynchronizerV2::updateSyncState() {
         newState = SyncState::ERROR;
     } else {
         newState = SyncState::ERROR;
-        // 尝试恢复
+        // 标记需要恢复,但不在这里直接调用attemptRecovery避免死锁
         if (recoveryAttempts_ < config_.maxRecoveryAttempts) {
-            attemptRecovery();
+            needRecovery = true;
             newState = SyncState::RECOVERING;
         }
     }
@@ -896,6 +900,11 @@ void SynchronizerV2::updateSyncState() {
         Logger::instance().info("Sync state changed from " + std::to_string(static_cast<int>(oldState)) + 
                                " to " + std::to_string(static_cast<int>(newState)));
     }
+    
+    // 如果需要恢复,现在可以安全地调用恢复操作(因为updateSyncState现在在锁外被调用)
+    if (needRecovery) {
+        performDelayedRecovery();
+    }
 }
 
 void SynchronizerV2::updateStats() {
@@ -985,10 +994,34 @@ void SynchronizerV2::attemptRecovery() {
     Logger::instance().warning("Attempting sync recovery, attempt: " + std::to_string(recoveryAttempts_));
     
     // 重置时钟漂移
-    std::lock_guard<std::mutex> lock(clockMutex_);
-    audioClock_.drift = 0.0;
-    videoClock_.drift = 0.0;
-    externalClock_.drift = 0.0;
+    {
+        std::lock_guard<std::mutex> lock(clockMutex_);
+        audioClock_.drift = 0.0;
+        videoClock_.drift = 0.0;
+        externalClock_.drift = 0.0;
+    }
+    
+    // 可能需要重新选择主时钟(在锁外面调用避免死锁)
+    if (config_.enableAdaptiveSync) {
+        selectMasterClock();
+    }
+}
+
+void SynchronizerV2::performDelayedRecovery() {
+    // 这个方法在不持有clockMutex_的情况下被调用
+    // 执行实际的恢复操作
+    recoveryAttempts_++;
+    lastRecoveryTime_ = std::chrono::steady_clock::now();
+    
+    Logger::instance().warning("Performing delayed sync recovery, attempt: " + std::to_string(recoveryAttempts_));
+    
+    // 重置时钟漂移
+    {
+        std::lock_guard<std::mutex> lock(clockMutex_);
+        audioClock_.drift = 0.0;
+        videoClock_.drift = 0.0;
+        externalClock_.drift = 0.0;
+    }
     
     // 可能需要重新选择主时钟
     if (config_.enableAdaptiveSync) {

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

@@ -288,6 +288,7 @@ private:
     
     // 错误恢复
     void attemptRecovery();
+    void performDelayedRecovery();
     void resetSyncState();
     
     // 工具函数

+ 8 - 14
AV/test_audio_debug.cpp

@@ -216,7 +216,7 @@ int main(int argc, char* argv[]) {
         // testQtAudioOutput();
 
         Logger::instance().info("\n=== PlayerCoreV2音频测试 ===");
-        
+
         // 创建同步配置
         SyncConfigV2 syncConfig;
         syncConfig.syncStrategy = SyncStrategy::ADAPTIVE;
@@ -240,9 +240,9 @@ int main(int argc, char* argv[]) {
         
         // 测试音频文件路径
         std::string audioFile = "C:\\Windows\\Media\\notify.wav";
-        
+
         Logger::instance().info("测试音频文件: " + audioFile);
-        
+
         // 打开音频文件
         auto result = player->openFile(audioFile);
         if (result != ErrorCode::SUCCESS) {
@@ -289,7 +289,7 @@ int main(int argc, char* argv[]) {
         double totalDuration = mediaInfo.duration / 1000000.0;
         Logger::instance().info("等待播放完成 (" + std::to_string(totalDuration) + " 秒)...");
         
-        // 监控播放状态
+        // 监控播放状态 - 让播放器自然结束
         auto startTime = std::chrono::steady_clock::now();
         while (true) {
             auto currentTime = std::chrono::steady_clock::now();
@@ -302,19 +302,13 @@ int main(int argc, char* argv[]) {
             
             // 如果播放完成或出错,退出
             if (state == PlayerState::Stopped || state == PlayerState::Error) {
+                Logger::instance().info("播放器自然停止,状态: " + std::to_string(static_cast<int>(state)));
                 break;
             }
             
-            // 如果播放时间接近总时长,停止播放
-            if (currentPos >= totalDuration - 0.1) {
-                Logger::instance().info("播放完成,正在停止...");
-                player->stop();
-                break;
-            }
-            
-            // 超时保护
-            if (elapsed > totalDuration + 5) {
-                Logger::instance().warningf("超时,停止播放...");
+            // 超时保护 - 增加更长的超时时间
+            if (elapsed > totalDuration + 10) {
+                Logger::instance().warningf("超时保护触发,停止播放...");
                 player->stop();
                 break;
             }

+ 490 - 0
AV/test_player_with_ui.cpp

@@ -0,0 +1,490 @@
+/**
+ * @file test_player_with_ui.cpp
+ * @brief 带有视频播放界面的综合测试程序
+ * @author AI Assistant
+ * @date 2024
+ */
+
+#include <chrono>
+#include <string>
+#include <thread>
+#include <iomanip>
+
+#include "code/base/logger.h"
+#include "code/player/player_core_v2.h"
+#include "code/player/opengl_video_renderer.h"
+
+#include <QApplication>
+#include <QWidget>
+#include <QVBoxLayout>
+#include <QHBoxLayout>
+#include <QPushButton>
+#include <QLabel>
+#include <QSlider>
+#include <QFileDialog>
+#include <QMessageBox>
+#include <QTimer>
+#include <QProgressBar>
+#include <QGroupBox>
+#include <QSpinBox>
+#include <QCheckBox>
+#include <QComboBox>
+#include <QTextEdit>
+#include <QSplitter>
+#include <QDebug>
+
+using namespace av::player;
+using namespace av::utils;
+
+// 播放器事件回调类
+class UIPlayerCallback : public PlayerEventCallback {
+public:
+    UIPlayerCallback(QWidget* parent) : m_parent(parent) {}
+    
+    void onStateChanged(PlayerState newState) override {
+        std::string stateStr;
+        switch (newState) {
+            case PlayerState::Idle: stateStr = "Idle"; break;
+            case PlayerState::Opening: stateStr = "Opening"; break;
+            case PlayerState::Stopped: stateStr = "Stopped"; break;
+            case PlayerState::Playing: stateStr = "Playing"; break;
+            case PlayerState::Paused: stateStr = "Paused"; break;
+            case PlayerState::Seeking: stateStr = "Seeking"; break;
+            case PlayerState::Error: stateStr = "Error"; break;
+        }
+        Logger::instance().info("[EVENT] State changed to: " + stateStr);
+        
+        // 发送信号到UI线程
+        QMetaObject::invokeMethod(m_parent, "onPlayerStateChanged", Qt::QueuedConnection,
+                                Q_ARG(int, static_cast<int>(newState)));
+    }
+    
+    void onPositionChanged(int64_t position) override {
+        // 发送位置更新到UI线程
+        QMetaObject::invokeMethod(m_parent, "onPlayerPositionChanged", Qt::QueuedConnection,
+                                Q_ARG(qint64, position));
+    }
+    
+    void onMediaInfoChanged(const MediaInfo& info) override {
+        Logger::instance().info("[EVENT] Media info changed:");
+        Logger::instance().info("  File: " + info.filename);
+        Logger::instance().info("  Duration: " + std::to_string(info.duration / 1000000.0) + "s");
+        Logger::instance().info("  Has Video: " + std::string(info.hasVideo ? "Yes" : "No"));
+        Logger::instance().info("  Has Audio: " + std::string(info.hasAudio ? "Yes" : "No"));
+        
+        if (info.hasVideo) {
+            Logger::instance().info("  Video: " + std::to_string(info.width) + "x" + std::to_string(info.height) + " @ " + std::to_string(info.fps) + " fps");
+        }
+        
+        if (info.hasAudio) {
+            Logger::instance().info("  Audio: " + std::to_string(info.sampleRate) + " Hz, " + std::to_string(info.channels) + " channels");
+        }
+        
+        // 发送媒体信息到UI线程
+        QMetaObject::invokeMethod(m_parent, "onMediaInfoChanged", Qt::QueuedConnection);
+    }
+    
+    void onErrorOccurred(const std::string& error) override {
+        Logger::instance().error("[ERROR] " + error);
+        QMetaObject::invokeMethod(m_parent, "onPlayerError", Qt::QueuedConnection,
+                                Q_ARG(QString, QString::fromStdString(error)));
+    }
+    
+    void onFrameDropped(int64_t totalDropped) override {
+        Logger::instance().warning("[WARNING] Frame dropped, total: " + std::to_string(totalDropped));
+    }
+    
+    void onSyncError(double error, const std::string& reason) override {
+        Logger::instance().warning("[WARNING] Sync error: " + std::to_string(error * 1000) + "ms, reason: " + reason);
+    }
+
+    void onEndOfFile() override {
+        Logger::instance().info("[EVENT] End of file reached");
+        QMetaObject::invokeMethod(m_parent, "onPlayerEndOfFile", Qt::QueuedConnection);
+    }
+    
+private:
+    QWidget* m_parent;
+};
+
+// 主播放器窗口类
+class PlayerWindow : public QWidget {
+    Q_OBJECT
+    
+public:
+    PlayerWindow(QWidget* parent = nullptr) : QWidget(parent) {
+        setupUI();
+        setupPlayer();
+        connectSignals();
+        
+        // 设置窗口属性
+        setWindowTitle("AV Player Test with UI");
+        resize(1200, 800);
+        
+        // 启动更新定时器
+        m_updateTimer = new QTimer(this);
+        connect(m_updateTimer, &QTimer::timeout, this, &PlayerWindow::updateUI);
+        m_updateTimer->start(100); // 100ms更新一次
+
+        m_player->openFile("C:/Users/zhuizhu/Videos/2.mp4");
+        // playPause();
+    }
+    
+    ~PlayerWindow() {
+        if (m_player) {
+            m_player->stop();
+        }
+    }
+    
+public slots:
+    void onPlayerStateChanged(int state) {
+        PlayerState playerState = static_cast<PlayerState>(state);
+        
+        switch (playerState) {
+            case PlayerState::Idle:
+                m_stateLabel->setText("状态: 空闲");
+                m_playButton->setText("播放");
+                m_playButton->setEnabled(false);
+                break;
+            case PlayerState::Opening:
+                m_stateLabel->setText("状态: 打开中...");
+                m_playButton->setEnabled(false);
+                break;
+            case PlayerState::Stopped:
+                m_stateLabel->setText("状态: 已停止");
+                m_playButton->setText("播放");
+                m_playButton->setEnabled(true);
+                break;
+            case PlayerState::Playing:
+                m_stateLabel->setText("状态: 播放中");
+                m_playButton->setText("暂停");
+                m_playButton->setEnabled(true);
+                break;
+            case PlayerState::Paused:
+                m_stateLabel->setText("状态: 已暂停");
+                m_playButton->setText("播放");
+                m_playButton->setEnabled(true);
+                break;
+            case PlayerState::Seeking:
+                m_stateLabel->setText("状态: 跳转中...");
+                break;
+            case PlayerState::Error:
+                m_stateLabel->setText("状态: 错误");
+                m_playButton->setEnabled(false);
+                break;
+        }
+    }
+    
+    void onPlayerPositionChanged(qint64 position) {
+        if (!m_seeking) {
+            double seconds = position / 1000000.0;
+            m_positionLabel->setText(QString("位置: %1s").arg(seconds, 0, 'f', 2));
+            
+            if (m_duration > 0) {
+                int progress = static_cast<int>((position * 100) / m_duration);
+                m_progressSlider->setValue(progress);
+            }
+        }
+    }
+    
+    void onMediaInfoChanged() {
+        if (m_player) {
+            auto info = m_player->getMediaInfo();
+            m_duration = info.duration;
+            
+            QString infoText = QString("文件: %1\n")
+                              .arg(QString::fromStdString(info.filename));
+            
+            if (info.duration > 0) {
+                double durationSec = info.duration / 1000000.0;
+                infoText += QString("时长: %1s\n").arg(durationSec, 0, 'f', 2);
+            }
+            
+            if (info.hasVideo) {
+                infoText += QString("视频: %1x%2 @ %3fps\n")
+                           .arg(info.width).arg(info.height).arg(info.fps, 0, 'f', 2);
+                           
+                // 初始化视频渲染器
+                // if (m_videoRenderer && !m_videoRenderer->isInitialized()) {
+                //     m_videoRenderer->initialize(info.width, info.height, AV_PIX_FMT_YUV420P, info.fps);
+                // }
+            }
+            
+            if (info.hasAudio) {
+                infoText += QString("音频: %1Hz, %2ch\n")
+                           .arg(info.sampleRate).arg(info.channels);
+            }
+            
+            m_infoLabel->setText(infoText);
+            m_playButton->setEnabled(true);
+        }
+    }
+    
+    void onPlayerError(const QString& error) {
+        QMessageBox::critical(this, "播放器错误", error);
+    }
+    
+    void onPlayerEndOfFile() {
+        m_playButton->setText("播放");
+    }
+    
+private slots:
+    void openFile() {
+        QString fileName = QFileDialog::getOpenFileName(this,
+            "选择媒体文件", "",
+            "媒体文件 (*.mp4 *.avi *.mkv *.mov *.wmv *.flv *.webm *.mp3 *.wav *.aac *.flac);;所有文件 (*.*)");
+            
+        if (!fileName.isEmpty()) {
+            loadFile(fileName.toStdString());
+        }
+    }
+    
+    void playPause() {
+        if (!m_player) return;
+        
+        auto state = m_player->getState();
+        if (state == PlayerState::Playing) {
+            m_player->pause();
+        } else if (state == PlayerState::Paused || state == PlayerState::Stopped) {
+            m_player->play();
+        }
+    }
+    
+    void stop() {
+        if (m_player) {
+            m_player->stop();
+        }
+    }
+    
+    void onProgressSliderPressed() {
+        m_seeking = true;
+    }
+    
+    void onProgressSliderReleased() {
+        if (m_player && m_duration > 0) {
+            int value = m_progressSlider->value();
+            int64_t position = (m_duration * value) / 100;
+            m_player->seek(position);
+        }
+        m_seeking = false;
+    }
+    
+    void onVolumeChanged(int value) {
+        if (m_player) {
+            double volume = value / 100.0;
+            m_player->setVolume(volume);
+            m_volumeLabel->setText(QString("音量: %1%").arg(value));
+        }
+    }
+    
+    void updateUI() {
+        if (m_player) {
+            // 更新统计信息
+            auto stats = m_player->getStats();
+            QString statsText = QString("帧数: %1\n丢帧: %2\n重复帧: %3\n速度: %4x")
+                               .arg(stats.totalFrames)
+                               .arg(stats.droppedFrames)
+                               .arg(stats.duplicatedFrames)
+                               .arg(stats.playbackSpeed, 0, 'f', 2);
+            m_statsLabel->setText(statsText);
+        }
+    }
+    
+private:
+    void setupUI() {
+        auto* mainLayout = new QHBoxLayout(this);
+        
+        // 左侧视频区域
+        auto* leftWidget = new QWidget;
+        auto* leftLayout = new QVBoxLayout(leftWidget);
+        
+        // 视频渲染器
+        m_videoRenderer = new OpenGLVideoWidget;
+        m_videoRenderer->setMinimumSize(640, 480);
+        leftLayout->addWidget(m_videoRenderer, 1);
+        
+        // 控制按钮
+        auto* controlLayout = new QHBoxLayout;
+        m_openButton = new QPushButton("打开文件");
+        m_playButton = new QPushButton("播放");
+        m_stopButton = new QPushButton("停止");
+        m_playButton->setEnabled(false);
+        
+        controlLayout->addWidget(m_openButton);
+        controlLayout->addWidget(m_playButton);
+        controlLayout->addWidget(m_stopButton);
+        controlLayout->addStretch();
+        
+        leftLayout->addLayout(controlLayout);
+        
+        // 进度条
+        m_progressSlider = new QSlider(Qt::Horizontal);
+        m_progressSlider->setRange(0, 100);
+        leftLayout->addWidget(m_progressSlider);
+        
+        // 音量控制
+        auto* volumeLayout = new QHBoxLayout;
+        volumeLayout->addWidget(new QLabel("音量:"));
+        m_volumeSlider = new QSlider(Qt::Horizontal);
+        m_volumeSlider->setRange(0, 100);
+        m_volumeSlider->setValue(100);
+        m_volumeSlider->setMaximumWidth(200);
+        m_volumeLabel = new QLabel("音量: 100%");
+        volumeLayout->addWidget(m_volumeSlider);
+        volumeLayout->addWidget(m_volumeLabel);
+        volumeLayout->addStretch();
+        leftLayout->addLayout(volumeLayout);
+        
+        mainLayout->addWidget(leftWidget, 2);
+        
+        // 右侧信息面板
+        auto* rightWidget = new QWidget;
+        auto* rightLayout = new QVBoxLayout(rightWidget);
+        rightWidget->setMaximumWidth(300);
+        
+        // 状态信息
+        auto* statusGroup = new QGroupBox("状态信息");
+        auto* statusLayout = new QVBoxLayout(statusGroup);
+        m_stateLabel = new QLabel("状态: 空闲");
+        m_positionLabel = new QLabel("位置: 0s");
+        statusLayout->addWidget(m_stateLabel);
+        statusLayout->addWidget(m_positionLabel);
+        rightLayout->addWidget(statusGroup);
+        
+        // 媒体信息
+        auto* infoGroup = new QGroupBox("媒体信息");
+        auto* infoLayout = new QVBoxLayout(infoGroup);
+        m_infoLabel = new QLabel("未加载文件");
+        m_infoLabel->setWordWrap(true);
+        infoLayout->addWidget(m_infoLabel);
+        rightLayout->addWidget(infoGroup);
+        
+        // 统计信息
+        auto* statsGroup = new QGroupBox("播放统计");
+        auto* statsLayout = new QVBoxLayout(statsGroup);
+        m_statsLabel = new QLabel("帧数: 0\n丢帧: 0\n重复帧: 0\n速度: 1.0x");
+        statsLayout->addWidget(m_statsLabel);
+        rightLayout->addWidget(statsGroup);
+        
+        rightLayout->addStretch();
+        mainLayout->addWidget(rightWidget);
+    }
+    
+    void setupPlayer() {
+        // 创建同步配置
+        SyncConfigV2 syncConfig;
+        syncConfig.syncStrategy = SyncStrategy::ADAPTIVE;
+        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;
+        
+        // 创建播放器实例
+        m_player = std::make_unique<PlayerCoreV2>(syncConfig);
+        
+        // 设置视频渲染器
+        m_player->setOpenGLVideoRenderer(m_videoRenderer);
+        
+        // 创建事件回调
+        m_callback = std::make_unique<UIPlayerCallback>(this);
+        m_player->setEventCallback(m_callback.get());
+        
+        m_duration = 0;
+        m_seeking = false;
+    }
+    
+    void connectSignals() {
+        connect(m_openButton, &QPushButton::clicked, this, &PlayerWindow::openFile);
+        connect(m_playButton, &QPushButton::clicked, this, &PlayerWindow::playPause);
+        connect(m_stopButton, &QPushButton::clicked, this, &PlayerWindow::stop);
+        
+        connect(m_progressSlider, &QSlider::sliderPressed, this, &PlayerWindow::onProgressSliderPressed);
+        connect(m_progressSlider, &QSlider::sliderReleased, this, &PlayerWindow::onProgressSliderReleased);
+        
+        connect(m_volumeSlider, &QSlider::valueChanged, this, &PlayerWindow::onVolumeChanged);
+    }
+    
+    void loadFile(const std::string& filename) {
+        if (!m_player) return;
+        
+        Logger::instance().info("Loading file: " + filename);
+        
+        auto result = m_player->openFile(filename);
+        if (result != ErrorCode::SUCCESS) {
+            QString error = QString("无法打开文件: %1\n错误代码: %2")
+                           .arg(QString::fromStdString(filename))
+                           .arg(static_cast<int>(result));
+            QMessageBox::critical(this, "文件打开失败", error);
+            Logger::instance().error("Failed to open file: " + std::to_string(static_cast<int>(result)));
+        }
+    }
+    
+private:
+    // UI组件
+    OpenGLVideoWidget* m_videoRenderer;
+    QPushButton* m_openButton;
+    QPushButton* m_playButton;
+    QPushButton* m_stopButton;
+    QSlider* m_progressSlider;
+    QSlider* m_volumeSlider;
+    QLabel* m_stateLabel;
+    QLabel* m_positionLabel;
+    QLabel* m_infoLabel;
+    QLabel* m_statsLabel;
+    QLabel* m_volumeLabel;
+    QTimer* m_updateTimer;
+    
+    // 播放器相关
+    std::unique_ptr<PlayerCoreV2> m_player;
+    std::unique_ptr<UIPlayerCallback> m_callback;
+    int64_t m_duration;
+    bool m_seeking;
+};
+
+int main(int argc, char* argv[]) {
+    QApplication app(argc, argv);
+    
+    // 初始化日志系统
+    Logger::instance().initialize("test.log", LogLevel::DEBUG, false, false);
+    Logger::instance().info("PlayerCoreV2 Example Started");
+    
+    try {
+        // 创建播放器窗口
+        PlayerWindow window;
+        window.show();
+        
+        // 如果有命令行参数,自动加载文件
+        // if (argc > 1) {
+        //     QTimer::singleShot(500, [&window, argv]() {
+        //         QMetaObject::invokeMethod(&window, "loadFile", Qt::QueuedConnection,
+        //                                 Q_ARG(std::string, std::string(argv[1])));
+        //     });
+        // } else {
+        //     // 默认加载测试文件
+        //     QTimer::singleShot(500, [&window]() {
+        //         std::string testFile = "C:/Users/zhuizhu/Videos/2.mp4";
+        //         QMetaObject::invokeMethod(&window, "loadFile", Qt::QueuedConnection,
+        //                                 Q_ARG(std::string, testFile));
+        //     });
+        // }
+
+        return app.exec();
+        
+    } catch (const std::exception& e) {
+        Logger::instance().error("Exception: " + std::string(e.what()));
+        QMessageBox::critical(nullptr, "错误", QString("发生异常: %1").arg(e.what()));
+        return 1;
+    } catch (...) {
+        Logger::instance().error("Unknown exception occurred");
+        QMessageBox::critical(nullptr, "错误", "发生未知异常");
+        return 1;
+    }
+}
+
+#include "test_player_with_ui.moc"

+ 41 - 0
AV/xmake.lua

@@ -244,6 +244,47 @@ target("test_muxer")
         add_links("avcodec", "avformat", "avutil", "swscale", "swresample")
         add_links("avdevice", "avfilter", "postproc")
     end
+
+-- 音频调试测试程序
+target("test_audio_debug")
+    set_kind("binary")
+    add_files("test_audio_debug.cpp")
+    add_deps("av_base", "av_codec", "av_utils")
+    add_files("code/player/player_core_v2.cpp")
+    add_files("code/player/audio_output.cpp")
+    add_files("code/player/thread_manager.cpp")
+    add_headerfiles("code/player/*.h")
+    set_targetdir("$(buildir)/bin")
+    
+    add_rules("qt.widgetapp")
+    add_frameworks("QtCore", "QtWidgets", "QtMultimedia")
+    
+    -- FFmpeg库链接
+    if is_plat("windows") then
+        add_includedirs(ffmpeg_include)
+        add_linkdirs(ffmpeg_lib)
+        add_links("avcodec", "avformat", "avutil", "swscale", "swresample")
+        add_links("avdevice", "avfilter", "postproc")
+    end
+
+-- 带UI的播放器测试程序
+target("test_player_with_ui")
+    add_rules("qt.widgetapp")
+    set_targetdir("$(buildir)/bin")
+    add_files("test_player_with_ui.cpp", {rules = "qt.moc"})
+    add_deps("av_base", "av_codec", "av_utils")
+    add_files("code/player/*.cpp")
+    add_headerfiles("code/player/*.h")
+    add_files("code/player/*.h", {rules = "qt.moc"})
+    add_frameworks("QtNetwork", "QtGui", "QtCore", "QtWidgets", "QtMultimedia", "QtOpenGL")
+    
+    -- FFmpeg库链接
+    if is_plat("windows") then
+        add_includedirs(ffmpeg_include)
+        add_linkdirs(ffmpeg_lib)
+        add_links("avcodec", "avformat", "avutil", "swscale", "swresample")
+        add_links("avdevice", "avfilter", "postproc")
+    end