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

+ 3 - 2
AV/AV.pri

@@ -42,6 +42,7 @@ SOURCES += \
     $$PWD/code/utils/utils_thread_pool.cpp
 
 include($$PWD/code/player/player.pri)
+# include($$PWD/code/recorder/recorder.pri)
 
 # Test files (uncomment to enable)
 # SOURCES += $$PWD/test_basic.cpp
@@ -51,8 +52,8 @@ include($$PWD/code/player/player.pri)
 # SOURCES += $$PWD/test_window_capture.cpp
 # SOURCES += $$PWD/test_utils.cpp
 # SOURCES += $$PWD/test_audio_debug.cpp
-SOURCES += $$PWD/test_player_with_ui.cpp
-
+# SOURCES += $$PWD/test_player_with_ui.cpp
+# SOURCES += $$PWD/test_seek_pause_fixed.cpp
 # Example files for PlayerV2 (uncomment to enable)
 # SOURCES += $$PWD/code/examples/player_v2_example.cpp
 

+ 0 - 291
AV/OPENGL_PLAYER_README.md

@@ -1,291 +0,0 @@
-# OpenGL视频播放器改进
-
-## 概述
-
-本项目对AV目录的播放器进行了重大改进,主要包括:
-
-1. **使用QOpenGLWidget进行硬件加速渲染**
-2. **修复时间同步问题**
-3. **提供更好的播放体验**
-
-## 主要改进
-
-### 1. OpenGL硬件加速渲染
-
-#### 新增文件
-- `AV/code/player/opengl_video_renderer.h` - OpenGL渲染器头文件
-- `AV/code/player/opengl_video_renderer.cpp` - OpenGL渲染器实现
-- `AV/test_opengl_player.cpp` - OpenGL播放器测试程序
-
-#### 特性
-- **硬件加速**: 使用OpenGL 3.3进行GPU加速渲染
-- **YUV支持**: 原生支持YUV420P格式,其他格式自动转换
-- **高质量渲染**: 支持线性过滤和纹理优化
-- **宽高比保持**: 自动保持视频原始宽高比
-- **垂直同步**: 支持VSync防止画面撕裂
-- **性能优化**: 使用VAO和VBO优化渲染性能
-
-#### 着色器
-- **顶点着色器**: 处理位置和纹理坐标
-- **片段着色器**: YUV到RGB转换,支持高质量色彩还原
-
-### 2. 时间同步问题修复
-
-#### 发现的问题
-1. **时钟更新不够频繁**: 导致时钟漂移
-2. **缺乏自适应同步**: 无法根据实际播放情况调整
-3. **帧率计算不准确**: 使用固定帧率而非实际帧率
-4. **缓冲管理不足**: 没有动态调整缓冲区大小
-
-#### 改进方案
-- **自适应同步**: 根据时钟漂移动态调整同步参数
-- **高频时钟更新**: 提高时钟更新频率到1000Hz
-- **缓冲管理**: 动态调整缓冲区大小以平衡延迟和稳定性
-- **性能监控**: 实时监控播放性能并自动优化
-
-#### 新增文件
-- `AV/code/utils/utils_improved_synchronizer.h` - 改进的同步器
-
-### 3. 播放器核心改进
-
-#### 修改的文件
-- `AV/code/player/player_core.h` - 添加OpenGL渲染器支持
-- `AV/code/player/player_core.cpp` - 实现OpenGL渲染器集成
-- `AV/code/player/player_adapter.h` - 添加OpenGL渲染器支持
-- `AV/code/player/player_adapter.cpp` - 实现OpenGL渲染器集成
-- `AV/code/player/SimplePlayerWindow.h` - 添加OpenGL渲染器支持
-- `AV/code/player/SimplePlayerWindow.cpp` - 实现OpenGL渲染器集成
-
-#### 新增功能
-- **双渲染器支持**: 同时支持传统QLabel和OpenGL渲染器
-- **智能渲染器选择**: 优先使用OpenGL渲染器
-- **更好的错误处理**: 改进的错误处理和日志记录
-- **PlayerAdapter增强**: 支持OpenGL渲染器,提供渲染器类型切换功能
-- **SimplePlayerWindow增强**: 默认使用OpenGL渲染器,提供完整的播放器UI示例
-
-### 4. PlayerAdapter增强
-
-#### 新增方法
-- `setOpenGLVideoRenderer()` - 设置OpenGL渲染器
-- `getCurrentRendererType()` - 获取当前渲染器类型
-- `updateRendererType()` - 更新渲染器类型
-
-#### 新增信号
-- `openGLRendererInitialized()` - OpenGL渲染器初始化完成
-- `rendererTypeChanged()` - 渲染器类型改变
-
-#### 特性
-- **自动渲染器管理**: 自动跟踪和管理渲染器类型
-- **信号通知**: 提供渲染器状态变化的信号通知
-- **向后兼容**: 保持对传统QLabel渲染器的支持
-- **调试信息**: 提供详细的渲染器状态调试信息
-
-### 5. SimplePlayerWindow增强
-
-#### 修改内容
-- **默认OpenGL渲染器**: 优先使用OpenGL渲染器进行视频显示
-- **备用渲染器**: 保留传统QLabel渲染器作为备用选项
-- **渲染器状态显示**: 在窗口标题中显示当前使用的渲染器类型
-- **完整UI示例**: 提供完整的播放器UI实现示例
-
-#### 新增功能
-- `onRendererTypeChanged()` - 处理渲染器类型变化
-- `onOpenGLRendererInitialized()` - 处理OpenGL渲染器初始化完成
-- **智能渲染器选择**: 自动选择最佳渲染器
-
-## 使用方法
-
-### 编译要求
-- Qt 5.12+ (支持QOpenGLWidget)
-- OpenGL 3.3+
-- FFmpeg 4.0+
-- C++17编译器
-
-### 编译步骤
-```bash
-# 在AV目录下
-qmake AV.pri
-make
-```
-
-### 运行测试程序
-```bash
-# 编译OpenGL播放器测试程序
-g++ -o test_opengl_player test_opengl_player.cpp -I. -lQt5Core -lQt5Widgets -lQt5OpenGL
-
-# 编译PlayerAdapter测试程序
-g++ -o test_player_adapter test_player_adapter.cpp -I. -lQt5Core -lQt5Widgets -lQt5OpenGL
-
-# 编译SimplePlayerWindow测试程序
-g++ -o test_simple_player test_simple_player.cpp -I. -lQt5Core -lQt5Widgets -lQt5OpenGL
-
-# 运行
-./test_opengl_player
-./test_player_adapter
-./test_simple_player
-```
-
-### 在代码中使用
-
-#### 直接使用PlayerCore
-```cpp
-#include "code/player/player_core.h"
-#include "code/player/opengl_video_renderer.h"
-
-// 创建播放器
-auto player = std::make_unique<av::player::PlayerCore>();
-
-// 创建OpenGL渲染器
-auto renderer = new av::player::OpenGLVideoRenderer(parentWidget);
-
-// 设置渲染器
-player->setOpenGLVideoRenderer(renderer);
-
-// 打开文件并播放
-player->openFile("video.mp4");
-player->play();
-```
-
-#### 使用PlayerAdapter(推荐)
-```cpp
-#include "code/player/player_adapter.h"
-#include "code/player/opengl_video_renderer.h"
-
-// 创建播放器适配器
-auto adapter = std::make_unique<av::player::PlayerAdapter>();
-
-// 创建OpenGL渲染器
-auto renderer = new av::player::OpenGLVideoRenderer(parentWidget);
-
-// 设置渲染器
-adapter->setOpenGLVideoRenderer(renderer);
-
-// 连接信号
-connect(adapter.get(), &PlayerAdapter::stateChanged, this, &MyWidget::onStateChanged);
-connect(adapter.get(), &PlayerAdapter::openGLRendererInitialized, this, &MyWidget::onRendererReady);
-
-// 打开文件并播放
-adapter->openFile("video.mp4");
-adapter->play();
-```
-
-#### 使用SimplePlayerWindow(完整UI示例)
-```cpp
-#include "code/player/SimplePlayerWindow.h"
-#include <QApplication>
-
-int main(int argc, char* argv[]) {
-    QApplication app(argc, argv);
-    
-    // 创建SimplePlayerWindow(默认使用OpenGL渲染器)
-    SimplePlayerWindow window;
-    window.show();
-    
-    return app.exec();
-}
-```
-
-## 性能对比
-
-### 传统渲染器 vs OpenGL渲染器
-
-| 特性 | 传统QLabel渲染器 | OpenGL渲染器 |
-|------|------------------|--------------|
-| CPU使用率 | 高 | 低 |
-| GPU使用率 | 无 | 中等 |
-| 渲染质量 | 中等 | 高 |
-| 内存使用 | 中等 | 低 |
-| 延迟 | 高 | 低 |
-| 支持格式 | 有限 | 全面 |
-
-### 同步性能改进
-
-| 指标 | 改进前 | 改进后 |
-|------|--------|--------|
-| 时钟更新频率 | 25Hz | 1000Hz |
-| 同步误差 | ±50ms | ±5ms |
-| 丢帧率 | 5-10% | <1% |
-| 缓冲延迟 | 200-500ms | 50-100ms |
-
-## 技术细节
-
-### OpenGL渲染器架构
-
-```
-OpenGLVideoRenderer
-├── 初始化阶段
-│   ├── OpenGL上下文初始化
-│   ├── 着色器程序编译
-│   ├── 顶点数据设置
-│   └── 纹理创建
-├── 渲染阶段
-│   ├── 帧数据更新
-│   ├── 纹理上传
-│   ├── 着色器渲染
-│   └── 显示输出
-└── 清理阶段
-    ├── 资源释放
-    └── 上下文清理
-```
-
-### 同步算法
-
-```
-改进的同步器
-├── 自适应同步
-│   ├── 时钟漂移检测
-│   ├── 频率调整
-│   └── 平滑处理
-├── 缓冲管理
-│   ├── 动态缓冲大小
-│   ├── 延迟控制
-│   └── 性能优化
-└── 性能监控
-    ├── 实时统计
-    ├── 性能评分
-    └── 自动调优
-```
-
-## 故障排除
-
-### 常见问题
-
-1. **OpenGL初始化失败**
-   - 检查显卡驱动是否支持OpenGL 3.3
-   - 确认Qt版本支持QOpenGLWidget
-
-2. **渲染黑屏**
-   - 检查视频格式是否支持
-   - 确认着色器编译成功
-
-3. **同步问题**
-   - 检查音频设备是否正常
-   - 确认系统时钟精度
-
-4. **性能问题**
-   - 降低视频分辨率
-   - 关闭垂直同步
-   - 调整缓冲大小
-
-### 调试信息
-
-启用详细日志:
-```cpp
-av::Logger::instance().setLevel(av::LogLevel::Debug);
-```
-
-## 未来计划
-
-1. **Vulkan支持**: 添加Vulkan渲染器选项
-2. **硬件解码**: 集成GPU硬件解码
-3. **流媒体支持**: 添加网络流播放功能
-4. **字幕支持**: 集成字幕渲染
-5. **滤镜系统**: 添加视频滤镜和特效
-
-## 贡献
-
-欢迎提交Issue和Pull Request来改进这个项目。
-
-## 许可证
-
-本项目采用MIT许可证。 

+ 76 - 13
AV/code/capture/capture_audio_capturer.cpp

@@ -368,6 +368,9 @@ ErrorCode AudioCapturer::openInputDevice() {
     // 设置缓冲区大小
     av_dict_set(&options, "audio_buffer_size", std::to_string(audioParams_.bufferSize).c_str(), 0);
     
+    // 尝试列出可用设备
+    av_dict_set(&options, "list_devices", "true", 0);
+    
     // 打开输入
     int ret = avformat_open_input(&formatCtx_, deviceName.c_str(), inputFormat, &options);
     av_dict_free(&options);
@@ -375,7 +378,26 @@ ErrorCode AudioCapturer::openInputDevice() {
     if (ret < 0) {
         AV_LOGGER_ERRORF("打开音频输入设备失败: {} (设备: {})", 
                         ffmpeg_utils::errorToString(ret), deviceName);
-        return static_cast<ErrorCode>(ret);
+        
+        // 如果是设备不存在错误,尝试使用默认设备
+        if (ret == AVERROR(EIO) || ret == AVERROR(ENOENT)) {
+            AV_LOGGER_WARNING("尝试使用默认音频设备");
+            AVDictionary* defaultOptions = nullptr;
+            av_dict_set(&defaultOptions, "sample_rate", std::to_string(audioParams_.sampleRate).c_str(), 0);
+            av_dict_set(&defaultOptions, "channels", std::to_string(audioParams_.channels).c_str(), 0);
+            
+            ret = avformat_open_input(&formatCtx_, "audio=default", inputFormat, &defaultOptions);
+            av_dict_free(&defaultOptions);
+            
+            if (ret < 0) {
+                AV_LOGGER_ERRORF("打开默认音频设备也失败: {}", ffmpeg_utils::errorToString(ret));
+                return static_cast<ErrorCode>(ret);
+            }
+            
+            AV_LOGGER_INFO("成功打开默认音频设备");
+        } else {
+            return static_cast<ErrorCode>(ret);
+        }
     }
     
     // 查找流信息
@@ -776,7 +798,12 @@ std::string AudioCapturer::getPlatformDeviceName() const {
         if (!audioParams_.deviceName.empty()) {
             return "audio=" + audioParams_.deviceName;
         } else {
-            return "audio=" + std::to_string(audioParams_.micIndex);
+            // 优先尝试默认设备,如果失败再尝试索引设备
+            if (audioParams_.micIndex == 0) {
+                return "audio=default";
+            } else {
+                return "audio=" + std::to_string(audioParams_.micIndex);
+            }
         }
     } else {
         return "audio=" + (audioParams_.audioDevice.empty() ? "@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\\wave_{00000000-0000-0000-0000-000000000000}" : audioParams_.audioDevice);
@@ -806,26 +833,62 @@ std::string AudioCapturer::getPlatformDeviceName() const {
 std::vector<AudioDeviceInfo> AudioCapturer::enumerateDirectSoundDevices() const {
     std::vector<AudioDeviceInfo> devices;
     
-    // 简化的DirectSound设备枚举
-    AudioDeviceInfo device;
-    device.id = "0";
-    device.name = "默认麦克风";
-    device.description = "DirectSound麦克风设备";
-    device.isDefault = true;
-    device.isInput = true;
+    // 尝试使用FFmpeg的设备枚举功能
+    const AVInputFormat* inputFormat = av_find_input_format("dshow");
+    if (!inputFormat) {
+        AV_LOGGER_WARNING("DirectShow输入格式不可用");
+        return devices;
+    }
+    
+    AVFormatContext* formatCtx = nullptr;
+    AVDictionary* options = nullptr;
+    
+    // 设置列出设备选项
+    av_dict_set(&options, "list_devices", "true", 0);
+    
+    // 尝试列出音频设备
+    int ret = avformat_open_input(&formatCtx, "audio=dummy", inputFormat, &options);
+    av_dict_free(&options);
+    
+    if (formatCtx) {
+        avformat_close_input(&formatCtx);
+    }
+    
+    // 添加默认设备作为后备
+    AudioDeviceInfo defaultDevice;
+    defaultDevice.id = "default";
+    defaultDevice.name = "默认音频设备";
+    defaultDevice.description = "系统默认音频输入设备";
+    defaultDevice.isDefault = true;
+    defaultDevice.isInput = true;
     
     // 添加常见采样率
-    device.supportedSampleRates = {8000, 16000, 22050, 44100, 48000};
+    defaultDevice.supportedSampleRates = {8000, 16000, 22050, 44100, 48000};
     
     // 添加常见声道数
-    device.supportedChannels = {1, 2};
+    defaultDevice.supportedChannels = {1, 2};
     
     // 添加支持的采样格式
-    device.supportedFormats = {
+    defaultDevice.supportedFormats = {
         AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLT
     };
     
-    devices.push_back(device);
+    devices.push_back(defaultDevice);
+    
+    // 如果没有找到其他设备,至少提供一个编号设备
+    if (devices.size() == 1) {
+        AudioDeviceInfo device;
+        device.id = "0";
+        device.name = "音频设备 0";
+        device.description = "DirectShow音频设备 0";
+        device.isDefault = false;
+        device.isInput = true;
+        device.supportedSampleRates = {8000, 16000, 22050, 44100, 48000};
+        device.supportedChannels = {1, 2};
+        device.supportedFormats = {AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLT};
+        
+        devices.push_back(device);
+    }
     
     return devices;
 }

+ 51 - 4
AV/code/codec/codec_video_encoder.cpp

@@ -6,6 +6,7 @@
 extern "C" {
 #include <libswscale/swscale.h>
 #include <libavutil/imgutils.h>
+#include <libavutil/pixdesc.h>
 }
 
 namespace av {
@@ -49,7 +50,10 @@ bool PixelFormatConverter::setSize(int width, int height) {
     );
     
     if (!swsCtx_) {
-        AV_LOGGER_ERROR("创建像素格式转换器失败");
+        AV_LOGGER_ERRORF("创建像素格式转换器失败: {}x{} format:{} -> {}",
+                         width, height,
+                         static_cast<int>(srcFormat_),
+                         static_cast<int>(dstFormat_));
         return false;
     }
     
@@ -532,42 +536,85 @@ ErrorCode VideoEncoder::setupHardwareFrameContext() {
 
 AVFramePtr VideoEncoder::convertFrame(const AVFramePtr& frame) {
     if (!frame) {
+        AV_LOGGER_ERROR("输入帧为空");
         return nullptr;
     }
     
+    // 对于YUV420P格式,直接使用软件编码,避免不必要的格式转换
+    // 让OpenGL直接处理原始YUV数据进行显示
+    if (frame->format == AV_PIX_FMT_YUV420P) {
+        // AV_LOGGER_DEBUG("检测到YUV420P格式,直接使用软件编码,避免格式转换");
+
+        // 创建一个新的帧来返回
+        AVFramePtr resultFrame = makeAVFrame();
+        if (!resultFrame) {
+            AV_LOGGER_ERROR("创建结果帧失败");
+            return nullptr;
+        }
+        
+        // 复制帧数据
+        if (av_frame_ref(resultFrame.get(), frame.get()) < 0) {
+            AV_LOGGER_ERROR("复制帧数据失败");
+            return nullptr;
+        }
+        
+        return resultFrame;
+    }
+    
     AVPixelFormat targetFormat;
     if (isHardwareEncoder_) {
-        // 硬件编码器统一使用NV12格式,与硬件帧上下文保持一致
-        targetFormat = AV_PIX_FMT_NV12;
+        // 对于硬件编码器,暂时使用软件编码避免格式转换问题
+        AV_LOGGER_WARNING("硬件编码器检测到,但为避免格式转换问题,使用软件编码");
+        targetFormat = static_cast<AVPixelFormat>(frame->format); // 使用输入格式
     } else {
         targetFormat = videoParams_.pixelFormat;
     }
     
+    AV_LOGGER_DEBUGF("帧格式转换: {}x{} format:{} -> {}", 
+                     frame->width, frame->height,
+                     static_cast<int>(frame->format),
+                     static_cast<int>(targetFormat));
+    
     // 如果格式已经匹配,创建新帧返回
     if (frame->format == targetFormat) {
         // 创建一个新的帧来返回,避免拷贝构造
         AVFramePtr resultFrame = makeAVFrame();
         if (!resultFrame) {
+            AV_LOGGER_ERROR("创建结果帧失败");
             return nullptr;
         }
         
         // 复制帧数据
         if (av_frame_ref(resultFrame.get(), frame.get()) < 0) {
+            AV_LOGGER_ERROR("复制帧数据失败");
             return nullptr;
         }
         
         return resultFrame;
     }
     
+    // 对于其他格式转换需求,仅在必要时进行
+    AV_LOGGER_WARNING("检测到格式转换需求,建议优化数据流避免不必要的转换");
+
     // 创建转换器
     if (!converter_ || 
         converter_->srcFormat_ != static_cast<AVPixelFormat>(frame->format) ||
         converter_->dstFormat_ != targetFormat) {
+        AV_LOGGER_DEBUGF("创建新的像素格式转换器: {} -> {}",
+                         static_cast<int>(frame->format),
+                         static_cast<int>(targetFormat));
         converter_ = std::make_unique<PixelFormatConverter>(
             static_cast<AVPixelFormat>(frame->format), targetFormat);
     }
     
-    return converter_->convert(frame);
+    auto result = converter_->convert(frame);
+    if (!result) {
+        AV_LOGGER_ERRORF("像素格式转换失败: {} -> {}",
+                         static_cast<int>(frame->format),
+                         static_cast<int>(targetFormat));
+    }
+    
+    return result;
 }
 
 AVFramePtr VideoEncoder::transferToHardware(const AVFramePtr& frame) {

+ 12 - 2
AV/code/muxer/muxer_file_muxer.cpp

@@ -224,6 +224,16 @@ ErrorCode FileMuxer::flush() {
     
     std::lock_guard<std::mutex> lock(fileMutex_);
     
+    return flushInternal();
+}
+
+ErrorCode FileMuxer::flushInternal() {
+    if (!formatCtx_) {
+        return ErrorCode::SUCCESS;
+    }
+    
+    // 注意:此方法假设调用者已经持有fileMutex_锁
+    
     int ret = av_write_frame(formatCtx_, nullptr); // 刷新
     if (ret < 0) {
         AV_LOGGER_ERRORF("刷新复用器失败: {}", ffmpeg_utils::errorToString(ret));
@@ -634,12 +644,12 @@ ErrorCode FileMuxer::writePacketInternal(AVPacket* packet) {
     double writeTime = std::chrono::duration<double, std::milli>(endTime - startTime).count();
     averageWriteTime_ = (averageWriteTime_ * 0.9) + (writeTime * 0.1);
     
-    // 定期刷新
+    // 定期刷新 - 使用内部刷新方法避免死锁
     if (!fileMuxerParams_.syncMode) {
         auto now = std::chrono::steady_clock::now();
         auto elapsed = std::chrono::duration<double>(now - lastFlushTime_).count();
         if (elapsed >= fileMuxerParams_.flushInterval) {
-            flush();
+            flushInternal();
         }
     }
     

+ 2 - 1
AV/code/muxer/muxer_file_muxer.h

@@ -142,9 +142,10 @@ protected:
     ErrorCode setupStreams();
     AVStream* createAVStream(const StreamInfo& streamInfo);
     
-    // 包处理
+    // 内部方法
     ErrorCode processPacket(AVPacket* packet);
     ErrorCode writePacketInternal(AVPacket* packet);
+    ErrorCode flushInternal(); // 内部刷新方法,假设已持有锁
     
     // 线程函数
     void writeThreadFunc();

+ 66 - 15
AV/code/player/audio_output.cpp

@@ -1,17 +1,19 @@
 #include "audio_output.h"
-#include "../base/logger.h"
-#include "../utils/utils_synchronizer_v2.h"
 #include <QAudioDeviceInfo>
 #include <QDebug>
+#include "../base/logger.h"
+#include "../utils/utils_synchronizer_v2.h"
+#include "AV/code/base/media_common.h"
 #include <algorithm>
+#include <chrono>
 #include <cstring>
 #include <thread>
-#include <chrono>
 
 extern "C" {
 #include <libavutil/channel_layout.h>
 #include <libavutil/avutil.h>
 #include <libavutil/time.h>
+#include <libavutil/opt.h>
 #include <libswresample/swresample.h>
 }
 
@@ -73,6 +75,24 @@ bool AudioOutput::initialize(int sampleRate, int channels, AVSampleFormat sample
         av::Logger::instance().warning("Audio format not supported, using nearest format");
         m_audioFormat = deviceInfo.nearestFormat(m_audioFormat);
         
+        // 验证获取的格式是否有效
+        if (m_audioFormat.sampleRate() <= 0 || m_audioFormat.channelCount() <= 0) {
+            av::Logger::instance().warning("Device returned invalid audio format, using fallback");
+            av::Logger::instance().warningf("Invalid format: {}Hz, {}ch", 
+                                           m_audioFormat.sampleRate(), 
+                                           m_audioFormat.channelCount());
+            
+            // 使用默认格式作为后备
+            m_audioFormat.setSampleRate(44100);
+            m_audioFormat.setChannelCount(2);
+            m_audioFormat.setSampleSize(16);
+            m_audioFormat.setCodec("audio/pcm");
+            m_audioFormat.setByteOrder(QAudioFormat::LittleEndian);
+            m_audioFormat.setSampleType(QAudioFormat::SignedInt);
+            
+            av::Logger::instance().info("Using fallback audio format: 44100Hz, 2ch, 16bit");
+        }
+        
         // 记录实际使用的格式
         av::Logger::instance().info("Using audio format: " + 
             std::to_string(m_audioFormat.sampleRate()) + "Hz, " +
@@ -481,6 +501,33 @@ bool AudioOutput::initResampler()
         return true;
     }
     
+    // 参数验证
+    if (m_sampleRate <= 0 || m_sampleRate > 192000) {
+        av::Logger::instance().errorf("Invalid input sample rate: {}", m_sampleRate);
+        return false;
+    }
+    
+    if (m_audioFormat.sampleRate() <= 0 || m_audioFormat.sampleRate() > 192000) {
+        av::Logger::instance().errorf("Invalid output sample rate: {}", m_audioFormat.sampleRate());
+        return false;
+    }
+    
+    if (m_channels <= 0 || m_channels > 32) {
+        av::Logger::instance().errorf("Invalid input channels: {}", m_channels);
+        return false;
+    }
+    
+    if (m_audioFormat.channelCount() <= 0 || m_audioFormat.channelCount() > 32) {
+        av::Logger::instance().errorf("Invalid output channels: {}", m_audioFormat.channelCount());
+        return false;
+    }
+    
+    // 记录参数信息用于调试
+    av::Logger::instance().infof("Resampler config: {}Hz,{}ch,{} -> {}Hz,{}ch,S16",
+                                m_sampleRate, m_channels, 
+                                av_get_sample_fmt_name(m_inputFormat),
+                                m_audioFormat.sampleRate(), m_audioFormat.channelCount());
+    
     // 创建重采样上下文
     m_swrContext = swr_alloc();
     if (!m_swrContext) {
@@ -496,22 +543,26 @@ bool AudioOutput::initResampler()
     AVChannelLayout outputLayout;
     av_channel_layout_default(&outputLayout, m_audioFormat.channelCount());
     
-    // 配置重采样器
-    int ret = swr_alloc_set_opts2(&m_swrContext,
-                                  &outputLayout, AV_SAMPLE_FMT_S16, m_audioFormat.sampleRate(),
-                                  &inputLayout, m_inputFormat, m_sampleRate,
-                                  0, nullptr);
+    // 使用分步设置方式替代swr_alloc_set_opts2
+    av_opt_set_chlayout(m_swrContext, "in_chlayout", &inputLayout, 0);
+    av_opt_set_int(m_swrContext, "in_sample_rate", m_sampleRate, 0);
+    av_opt_set_sample_fmt(m_swrContext, "in_sample_fmt", m_inputFormat, 0);
     
-    if (ret < 0) {
-        av::Logger::instance().error("Failed to set resampler options");
-        swr_free(&m_swrContext);
-        return false;
-    }
+    av_opt_set_chlayout(m_swrContext, "out_chlayout", &outputLayout, 0);
+    av_opt_set_int(m_swrContext, "out_sample_rate", m_audioFormat.sampleRate(), 0);
+    av_opt_set_sample_fmt(m_swrContext, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
     
     // 初始化重采样器
-    ret = swr_init(m_swrContext);
+    int ret = swr_init(m_swrContext);
     if (ret < 0) {
-        av::Logger::instance().error("Failed to initialize resampler");
+        av::Logger::instance().errorf("Failed to initialize resampler: {}", 
+                                      ffmpeg_utils::errorToString(ret));
+        av::Logger::instance().errorf("Input: {}Hz, {}ch, {}", 
+                                      m_sampleRate, m_channels, 
+                                      av_get_sample_fmt_name(m_inputFormat));
+        av::Logger::instance().errorf("Output: {}Hz, {}ch, S16", 
+                                      m_audioFormat.sampleRate(), 
+                                      m_audioFormat.channelCount());
         swr_free(&m_swrContext);
         return false;
     }

+ 0 - 93
AV/code/utils/test_synchronizer_v2.cpp

@@ -1,93 +0,0 @@
-#include "utils_synchronizer_v2.h"
-#include <iostream>
-#include <thread>
-#include <chrono>
-
-using namespace av::utils;
-
-int main() {
-    std::cout << "=== SynchronizerV2 Test ===\n";
-    
-    // 创建同步器
-    SyncConfigV2 config;
-    config.strategy = SyncStrategy::AUDIO_MASTER;
-    
-    SynchronizerV2 sync(config);
-    
-    // 初始化和启动
-    auto result = sync.initialize();
-    if (result != ErrorCode::SUCCESS) {
-        std::cout << "Failed to initialize synchronizer\n";
-        return -1;
-    }
-    
-    sync.setStreamInfo(true, true); // 有音频和视频流
-    
-    result = sync.start();
-    if (result != ErrorCode::SUCCESS) {
-        std::cout << "Failed to start synchronizer\n";
-        return -1;
-    }
-    
-    std::cout << "Synchronizer started successfully\n";
-    
-    // 模拟音视频时钟更新
-    double audioTime = 0.0;
-    double videoTime = 0.0;
-    double frame_last_duration = 0.033;
-
-    for (int i = 0; i < 10; ++i) {
-        // 更新音频时钟
-        sync.setClock(ClockType::AUDIO, audioTime, i);
-        
-        // 更新视频时钟(稍微不同步)
-        videoTime = audioTime + 0.02; // 20ms ahead
-        sync.setClock(ClockType::VIDEO, videoTime, i);
-        
-        std::cout << "\nFrame " << i << ":\n";
-        std::cout << "  Audio Clock: " << sync.getClock(ClockType::AUDIO) << "s\n";
-        std::cout << "  Video Clock: " << sync.getClock(ClockType::VIDEO) << "s\n";
-        std::cout << "  Master Clock: " << sync.getMasterClock() << "s\n";
-        
-        // 测试视频帧延迟计算
-        double delay = sync.computeTargetDelay(frame_last_duration, videoTime);
-        std::cout << "  Computed video delay: " << delay << "s\n";
-
-        // 模拟音频同步
-        short audio_buffer[2048];
-        int original_size = 1920;
-        int synced_size = sync.synchronizeAudio(audio_buffer, original_size, audioTime);
-        std::cout << "  Original audio size: " << original_size << ", Synced audio size: " << synced_size << "\n";
-
-        audioTime += 0.033; // 30fps interval
-        
-        // 短暂延迟
-        std::this_thread::sleep_for(std::chrono::milliseconds(10));
-    }
-    
-    // 测试暂停和恢复
-    std::cout << "\nTesting pause/resume...\n";
-    sync.pause();
-    // std::cout << "Paused: " << (sync.isPaused() ? "true" : "false") << "\n";
-    
-    sync.resume();
-    // std::cout << "Resumed: " << (sync.isPaused() ? "false" : "true") << "\n";
-    
-    // 测试同步策略切换
-    std::cout << "\nTesting sync strategy change...\n";
-    sync.setSyncStrategy(SyncStrategy::VIDEO_MASTER);
-    std::cout << "New strategy: " << static_cast<int>(sync.getSyncStrategy()) << "\n";
-    // std::cout << "Master clock type: " << static_cast<int>(sync.getMasterClockType()) << "\n";
-    
-    // 测试播放速度
-    std::cout << "\nTesting playback speed...\n";
-    sync.setClockSpeed(ClockType::AUDIO, 1.5);
-    // std::cout << "Playback speed: " << sync.getPlaybackSpeed() << "\n";
-    
-    // 停止同步器
-    sync.stop();
-    std::cout << "\nSynchronizer stopped\n";
-    
-    std::cout << "\n=== Test Completed ===\n";
-    return 0;
-}

+ 16 - 34
AV/xmake.lua

@@ -1,21 +1,3 @@
--- xmake.lua for AV Framework
-
--- 设置项目信息
-set_project("AV_Framework")
-set_version("1.0.0")
-set_languages("c++17")
-
--- 设置编译模式
-add_rules("mode.debug", "mode.release")
-
--- 设置编译选项
-if is_plat("windows") then
-    add_cxflags("/W3", "/utf-8")
-    add_defines("_CRT_SECURE_NO_WARNINGS")
-else
-    add_cxflags("-Wall", "-Wextra")
-end
-
 -- FFmpeg库路径配置 - 支持环境变量和默认路径
 local ffmpeg_path = os.getenv("FFMPEG_PATH") or "E:/AAA/ffmpeg-7.0.2-full_build-shared"
 local ffmpeg_include = ffmpeg_path .. "/include"
@@ -199,21 +181,6 @@ target("test_audio_encoder")
         add_links("avdevice", "avfilter", "postproc")
     end
 
--- 同步器测试程序
-target("test_synchronizer_v2")
-    set_kind("binary")
-    add_files("code/utils/test_synchronizer_v2.cpp")
-    add_deps("av_utils")
-    set_targetdir("$(buildir)/bin")
-    
-    -- 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
-    
 
 -- 窗口采集测试程序
 target("test_window_capture")
@@ -302,4 +269,19 @@ target("test_player_with_ui")
     end
     
     
-
+-- 混流器测试程序
+target("test_seek_pause_fixed")
+    set_kind("binary")
+    add_rules("qt.widgetapp")
+    add_files("test_seek_pause_fixed.cpp")
+    add_deps("av_base", "av_codec", "av_utils")
+    add_includedirs(".", {public = true})
+    set_targetdir("$(buildir)/bin")
+    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

+ 133 - 0
AvRecorder/capturer/audio/audio_capturer.cpp

@@ -34,6 +34,15 @@ bool AudioCapturer::Init(Type deviceType)
 bool AudioCapturer::Start()
 {
     __CheckBool(_isInit);
+    
+    // 如果是麦克风设备,启动静音播放器确保音频引擎活跃
+    if (_deviceType == Microphone) {
+        if (!_InitializeSilencePlayer()) {
+            // 静音播放器初始化失败不影响主要功能,只记录日志
+            // qDebug() << "Failed to initialize silence player for microphone";
+        }
+    }
+    
     _loopFlag = true;
     // PlaySoundA("./rc/mute.wav", nullptr, SND_FILENAME | SND_ASYNC | SND_LOOP);
     _captureThread = new std::thread(
@@ -46,6 +55,10 @@ void AudioCapturer::Stop()
     // CoUninitialize();
     _isInit = false;
     _loopFlag = false;
+    
+    // 清理静音播放器
+    _CleanupSilencePlayer();
+    
     Free(_captureThread, [this] {
         _captureThread->join();
         delete _captureThread;
@@ -200,3 +213,123 @@ int AudioCapturer::readAudioData(char* buf, int maxLen)
     }
     return toRead;
 }
+
+// 静音播放器实现
+bool AudioCapturer::_InitializeSilencePlayer()
+{
+    HRESULT hr;
+    
+    // 获取默认音频渲染设备
+    hr = _pDeviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &_pSilenceDevice);
+    if (FAILED(hr)) {
+        return false;
+    }
+    
+    // 激活音频客户端
+    hr = _pSilenceDevice->Activate(__uuidof(IAudioClient), CLSCTX_ALL, nullptr, (void**)&_pSilenceAudioClient);
+    if (FAILED(hr)) {
+        return false;
+    }
+    
+    // 获取混音格式
+    WAVEFORMATEX* pSilenceFormat = nullptr;
+    hr = _pSilenceAudioClient->GetMixFormat(&pSilenceFormat);
+    if (FAILED(hr)) {
+        return false;
+    }
+    
+    // 初始化音频客户端(共享模式)
+    hr = _pSilenceAudioClient->Initialize(
+        AUDCLNT_SHAREMODE_SHARED,
+        0,
+        10000000,  // 1秒缓冲区
+        0,
+        pSilenceFormat,
+        nullptr
+    );
+    
+    CoTaskMemFree(pSilenceFormat);
+    
+    if (FAILED(hr)) {
+        return false;
+    }
+    
+    // 获取渲染客户端
+    hr = _pSilenceAudioClient->GetService(__uuidof(IAudioRenderClient), (void**)&_pSilenceRenderClient);
+    if (FAILED(hr)) {
+        return false;
+    }
+    
+    // 启动音频客户端
+    hr = _pSilenceAudioClient->Start();
+    if (FAILED(hr)) {
+        return false;
+    }
+    
+    // 启动静音播放线程
+    _silencePlayerRunning = true;
+    _silencePlayerThread = new std::thread([this] { _SilencePlayerThreadFunc(); });
+    
+    return true;
+}
+
+void AudioCapturer::_CleanupSilencePlayer()
+{
+    // 停止静音播放线程
+    if (_silencePlayerRunning) {
+        _silencePlayerRunning = false;
+        if (_silencePlayerThread && _silencePlayerThread->joinable()) {
+            _silencePlayerThread->join();
+            delete _silencePlayerThread;
+            _silencePlayerThread = nullptr;
+        }
+    }
+    
+    // 清理 WASAPI 资源
+    if (_pSilenceAudioClient) {
+        _pSilenceAudioClient->Stop();
+        _pSilenceAudioClient->Release();
+        _pSilenceAudioClient = nullptr;
+    }
+    
+    if (_pSilenceRenderClient) {
+        _pSilenceRenderClient->Release();
+        _pSilenceRenderClient = nullptr;
+    }
+    
+    if (_pSilenceDevice) {
+        _pSilenceDevice->Release();
+        _pSilenceDevice = nullptr;
+    }
+}
+
+void AudioCapturer::_SilencePlayerThreadFunc()
+{
+    UINT32 bufferFrameCount;
+    HRESULT hr = _pSilenceAudioClient->GetBufferSize(&bufferFrameCount);
+    if (FAILED(hr)) {
+        return;
+    }
+    
+    while (_silencePlayerRunning) {
+        UINT32 numFramesPadding;
+        hr = _pSilenceAudioClient->GetCurrentPadding(&numFramesPadding);
+        if (FAILED(hr)) {
+            break;
+        }
+        
+        UINT32 numFramesAvailable = bufferFrameCount - numFramesPadding;
+        
+        if (numFramesAvailable > 0) {
+            BYTE* pData;
+            hr = _pSilenceRenderClient->GetBuffer(numFramesAvailable, &pData);
+            if (SUCCEEDED(hr)) {
+                // 填充静音数据(全零)
+                memset(pData, 0, numFramesAvailable * sizeof(float) * 2); // 假设立体声
+                hr = _pSilenceRenderClient->ReleaseBuffer(numFramesAvailable, 0);
+            }
+        }
+        
+        Sleep(10); // 10ms 间隔
+    }
+}

+ 12 - 0
AvRecorder/capturer/audio/audio_capturer.h

@@ -36,6 +36,13 @@ private:
     WAVEFORMATEXTENSIBLE _formatex;
     std::vector<char> _buffer;
     std::mutex _bufferMutex;
+    
+    // 静音播放器相关成员
+    std::atomic<bool> _silencePlayerRunning{false};
+    std::thread* _silencePlayerThread = nullptr;
+    IMMDevice* _pSilenceDevice = nullptr;
+    IAudioClient* _pSilenceAudioClient = nullptr;
+    IAudioRenderClient* _pSilenceRenderClient = nullptr;
 
     bool _CreateDeviceEnumerator(IMMDeviceEnumerator** enumerator);
     bool _CreateDevice(IMMDeviceEnumerator* enumerator, IMMDevice** device);
@@ -49,6 +56,11 @@ private:
         IAudioCaptureClient** audioCaptureClient);
     bool _ThreadRun(IAudioClient* audio_client,
         IAudioCaptureClient* audio_capture_client);
+    
+    // 静音播放器方法
+    bool _InitializeSilencePlayer();
+    void _CleanupSilencePlayer();
+    void _SilencePlayerThreadFunc();
 };
 
 #endif

+ 156 - 0
AvRecorder/capturer/audio/wasapi_loopback_capturer.cpp

@@ -17,6 +17,8 @@ public:
     }
     ~WASAPILoopbackCapturerPrivate()
     {
+        cleanupSilencePlayer();
+        
         if (pwfx)
             CoTaskMemFree(pwfx);
         if (pCaptureClient)
@@ -207,6 +209,18 @@ public:
     WAVEFORMATEX* pwfx = nullptr;
 
     WAVEFORMATEXTENSIBLE _formatex;
+    
+    // 静音播放器相关成员
+    std::atomic<bool> m_silencePlayerRunning{false};
+    std::thread m_silencePlayerThread;
+    IMMDevice* pSilenceDevice = nullptr;
+    IAudioClient* pSilenceAudioClient = nullptr;
+    IAudioRenderClient* pSilenceRenderClient = nullptr;
+    
+    // 静音播放器方法
+    bool initializeSilencePlayer();
+    void cleanupSilencePlayer();
+    void silencePlayerThreadFunc();
 };
 
 WASAPILoopbackCapturer::WASAPILoopbackCapturer(QObject* parent)
@@ -285,6 +299,14 @@ bool WASAPILoopbackCapturer::Start()
     if (m_running)
         return false;
         
+    // 如果是扬声器设备,启动静音播放器确保音频引擎活跃
+    if (m_deviceType == Type::Speaker) {
+        if (!d->initializeSilencePlayer()) {
+            qDebug() << "Failed to initialize silence player";
+            return false;
+        }
+    }
+        
     if (!d->setupCaptureClient()) {
         return false;
     }
@@ -355,3 +377,137 @@ void WASAPILoopbackCapturer::captureThreadFunc()
 
     qDebug() << "WASAPI Loopback capture stopped";
 }
+
+// 静音播放器实现
+bool WASAPILoopbackCapturerPrivate::initializeSilencePlayer()
+{
+    HRESULT hr;
+    
+    // 获取默认音频渲染设备
+    hr = pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pSilenceDevice);
+    if (FAILED(hr)) {
+        qDebug() << "Failed to get default audio render endpoint for silence player";
+        return false;
+    }
+    
+    // 激活音频客户端
+    hr = pSilenceDevice->Activate(__uuidof(IAudioClient), CLSCTX_ALL, nullptr, (void**)&pSilenceAudioClient);
+    if (FAILED(hr)) {
+        qDebug() << "Failed to activate audio client for silence player";
+        return false;
+    }
+    
+    // 获取混音格式
+    WAVEFORMATEX* pSilenceFormat = nullptr;
+    hr = pSilenceAudioClient->GetMixFormat(&pSilenceFormat);
+    if (FAILED(hr)) {
+        qDebug() << "Failed to get mix format for silence player";
+        return false;
+    }
+    
+    // 初始化音频客户端(共享模式)
+    hr = pSilenceAudioClient->Initialize(
+        AUDCLNT_SHAREMODE_SHARED,
+        0,
+        10000000,  // 1秒缓冲区
+        0,
+        pSilenceFormat,
+        nullptr
+    );
+    
+    CoTaskMemFree(pSilenceFormat);
+    
+    if (FAILED(hr)) {
+        qDebug() << "Failed to initialize audio client for silence player";
+        return false;
+    }
+    
+    // 获取渲染客户端
+    hr = pSilenceAudioClient->GetService(__uuidof(IAudioRenderClient), (void**)&pSilenceRenderClient);
+    if (FAILED(hr)) {
+        qDebug() << "Failed to get render client for silence player";
+        return false;
+    }
+    
+    // 启动音频客户端
+    hr = pSilenceAudioClient->Start();
+    if (FAILED(hr)) {
+        qDebug() << "Failed to start audio client for silence player";
+        return false;
+    }
+    
+    // 启动静音播放线程
+    m_silencePlayerRunning = true;
+    m_silencePlayerThread = std::thread(&WASAPILoopbackCapturerPrivate::silencePlayerThreadFunc, this);
+    
+    qDebug() << "Silence player initialized successfully";
+    return true;
+}
+
+void WASAPILoopbackCapturerPrivate::cleanupSilencePlayer()
+{
+    // 停止静音播放线程
+    if (m_silencePlayerRunning) {
+        m_silencePlayerRunning = false;
+        if (m_silencePlayerThread.joinable()) {
+            m_silencePlayerThread.join();
+        }
+    }
+    
+    // 清理 WASAPI 资源
+    if (pSilenceAudioClient) {
+        pSilenceAudioClient->Stop();
+        pSilenceAudioClient->Release();
+        pSilenceAudioClient = nullptr;
+    }
+    
+    if (pSilenceRenderClient) {
+        pSilenceRenderClient->Release();
+        pSilenceRenderClient = nullptr;
+    }
+    
+    if (pSilenceDevice) {
+        pSilenceDevice->Release();
+        pSilenceDevice = nullptr;
+    }
+}
+
+void WASAPILoopbackCapturerPrivate::silencePlayerThreadFunc()
+{
+    qDebug() << "Silence player thread started";
+    
+    UINT32 bufferFrameCount;
+    HRESULT hr = pSilenceAudioClient->GetBufferSize(&bufferFrameCount);
+    if (FAILED(hr)) {
+        qDebug() << "Failed to get buffer size for silence player";
+        return;
+    }
+    
+    while (m_silencePlayerRunning) {
+        UINT32 numFramesPadding;
+        hr = pSilenceAudioClient->GetCurrentPadding(&numFramesPadding);
+        if (FAILED(hr)) {
+            qDebug() << "Failed to get current padding for silence player";
+            break;
+        }
+        
+        UINT32 numFramesAvailable = bufferFrameCount - numFramesPadding;
+        
+        if (numFramesAvailable > 0) {
+            BYTE* pData;
+            hr = pSilenceRenderClient->GetBuffer(numFramesAvailable, &pData);
+            if (SUCCEEDED(hr)) {
+                // 填充静音数据(全零)
+                memset(pData, 0, numFramesAvailable * sizeof(float) * 2); // 假设立体声
+                hr = pSilenceRenderClient->ReleaseBuffer(numFramesAvailable, 0);
+                if (FAILED(hr)) {
+                    qDebug() << "Failed to release buffer for silence player";
+                }
+            }
+        }
+        
+        Sleep(10); // 10ms 间隔
+    }
+    
+    qDebug() << "Silence player thread stopped";
+}

+ 0 - 11
bin/VideoPlayer.ini

@@ -1,11 +0,0 @@
-[%General]
-hidePlayContrl=1
-fullScreen=0
-openDXVA2=0
-loopPlay=1
-style=
-volume=0.8
-
-[Info]
-software=Video player
-author=Steven Huang

+ 101 - 385
main.cpp

@@ -1,385 +1,101 @@
-// #include "AV/code/base/logger.h"
-// #include "AV/code/player/player_core_v2.h"
-// #include <chrono>
-// #include <iostream>
-// #include <string>
-// #include <thread>
-
-// using namespace av::player;
-// using namespace av::utils;
-
-// // 示例事件回调类
-// class ExamplePlayerCallback : public PlayerEventCallback
-// {
-// public:
-//     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;
-//         }
-//         std::cout << "[EVENT] State changed to: " << stateStr << std::endl;
-//     }
-
-//     void onPositionChanged(int64_t position) override
-//     {
-//         // 每秒更新一次位置信息
-//         static auto lastUpdate = std::chrono::steady_clock::now();
-//         auto now = std::chrono::steady_clock::now();
-//         if (std::chrono::duration_cast<std::chrono::seconds>(now - lastUpdate).count() >= 1) {
-//             double seconds = position / 1000000.0;
-//             std::cout << "[EVENT] Position: " << std::fixed << std::setprecision(2) << seconds
-//                       << "s" << std::endl;
-//             lastUpdate = now;
-//         }
-//     }
-
-//     void onMediaInfoChanged(const MediaInfo& info) override
-//     {
-//         std::cout << "[EVENT] Media info changed:" << std::endl;
-//         std::cout << "  File: " << info.filename << std::endl;
-//         std::cout << "  Duration: " << (info.duration / 1000000.0) << "s" << std::endl;
-//         std::cout << "  Has Video: " << (info.hasVideo ? "Yes" : "No") << std::endl;
-//         std::cout << "  Has Audio: " << (info.hasAudio ? "Yes" : "No") << std::endl;
-
-//         if (info.hasVideo) {
-//             std::cout << "  Video: " << info.width << "x" << info.height << " @ " << info.fps
-//                       << " fps" << std::endl;
-//         }
-
-//         if (info.hasAudio) {
-//             std::cout << "  Audio: " << info.sampleRate << " Hz, " << info.channels << " channels"
-//                       << std::endl;
-//         }
-//     }
-
-//     void onErrorOccurred(const std::string& error) override
-//     {
-//         std::cout << "[ERROR] " << error << std::endl;
-//     }
-
-//     void onFrameDropped(int64_t totalDropped) override
-//     {
-//         std::cout << "[WARNING] Frame dropped, total: " << totalDropped << std::endl;
-//     }
-
-//     void onSyncError(double error, const std::string& reason) override
-//     {
-//         std::cout << "[WARNING] Sync error: " << (error * 1000) << "ms, reason: " << reason
-//                   << std::endl;
-//     }
-
-//     void onEndOfFile() override { std::cout << "[EVENT] End of file reached" << std::endl; }
-// };
-
-// // 简单的命令行界面
-// class SimplePlayerUI
-// {
-// public:
-//     SimplePlayerUI(PlayerCoreV2* player)
-//         : m_player(player)
-//         , m_running(true)
-//     {}
-
-//     void run()
-//     {
-//         std::cout << "\n=== PlayerCoreV2 Example ===" << std::endl;
-//         std::cout << "Commands:" << std::endl;
-//         std::cout << "  open <filename>  - Open media file" << std::endl;
-//         std::cout << "  play             - Start playback" << std::endl;
-//         std::cout << "  pause            - Pause playback" << std::endl;
-//         std::cout << "  stop             - Stop playback" << std::endl;
-//         std::cout << "  seek <seconds>   - Seek to position" << std::endl;
-//         std::cout << "  speed <rate>     - Set playback speed (0.5-4.0)" << std::endl;
-//         std::cout << "  volume <level>   - Set volume (0.0-1.0)" << std::endl;
-//         std::cout << "  stats            - Show playback statistics" << std::endl;
-//         std::cout << "  debug            - Show debug information" << std::endl;
-//         std::cout << "  config           - Show sync configuration" << std::endl;
-//         std::cout << "  quit             - Exit program" << std::endl;
-//         std::cout << "============================\n" << std::endl;
-
-//         std::string line;
-//         while (m_running && std::getline(std::cin, line)) {
-//             processCommand(line);
-//         }
-//     }
-
-// private:
-//     void processCommand(const std::string& line)
-//     {
-//         std::istringstream iss(line);
-//         std::string command;
-//         iss >> command;
-
-//         if (command == "open") {
-//             std::string filename;
-//             iss >> filename;
-//             if (!filename.empty()) {
-//                 auto result = m_player->openFile(filename);
-//                 if (result == ErrorCode::SUCCESS) {
-//                     std::cout << "File opened successfully" << std::endl;
-//                 } else {
-//                     std::cout << "Failed to open file: " << static_cast<int>(result) << std::endl;
-//                 }
-//             } else {
-//                 std::cout << "Usage: open <filename>" << std::endl;
-//             }
-//         } else if (command == "play") {
-//             auto result = m_player->play();
-//             if (result == ErrorCode::SUCCESS) {
-//                 std::cout << "Playback started" << std::endl;
-//             } else {
-//                 std::cout << "Failed to start playback: " << static_cast<int>(result) << std::endl;
-//             }
-//         } else if (command == "pause") {
-//             auto result = m_player->pause();
-//             if (result == ErrorCode::SUCCESS) {
-//                 std::cout << "Playback paused" << std::endl;
-//             } else {
-//                 std::cout << "Failed to pause playback: " << static_cast<int>(result) << std::endl;
-//             }
-//         } else if (command == "stop") {
-//             auto result = m_player->stop();
-//             if (result == ErrorCode::SUCCESS) {
-//                 std::cout << "Playback stopped" << std::endl;
-//             } else {
-//                 std::cout << "Failed to stop playback: " << static_cast<int>(result) << std::endl;
-//             }
-//         } else if (command == "seek") {
-//             double seconds;
-//             iss >> seconds;
-//             if (iss) {
-//                 int64_t timestamp = static_cast<int64_t>(seconds * 1000000); // 转换为微秒
-//                 auto result = m_player->seek(timestamp);
-//                 if (result == ErrorCode::SUCCESS) {
-//                     std::cout << "Seeking to " << seconds << "s" << std::endl;
-//                 } else {
-//                     std::cout << "Failed to seek: " << static_cast<int>(result) << std::endl;
-//                 }
-//             } else {
-//                 std::cout << "Usage: seek <seconds>" << std::endl;
-//             }
-//         } else if (command == "speed") {
-//             double speed;
-//             iss >> speed;
-//             if (iss) {
-//                 auto result = m_player->setPlaybackSpeed(speed);
-//                 if (result == ErrorCode::SUCCESS) {
-//                     std::cout << "Playback speed set to " << speed << "x" << std::endl;
-//                 } else {
-//                     std::cout << "Failed to set playback speed: " << static_cast<int>(result)
-//                               << std::endl;
-//                 }
-//             } else {
-//                 std::cout << "Usage: speed <rate>" << std::endl;
-//             }
-//         } else if (command == "volume") {
-//             double volume;
-//             iss >> volume;
-//             if (iss) {
-//                 m_player->setVolume(volume);
-//                 std::cout << "Volume set to " << volume << std::endl;
-//             } else {
-//                 std::cout << "Usage: volume <level>" << std::endl;
-//             }
-//         } else if (command == "stats") {
-//             showStats();
-//         } else if (command == "debug") {
-//             std::cout << m_player->getDebugInfo() << std::endl;
-//         } else if (command == "config") {
-//             showSyncConfig();
-//         } else if (command == "quit" || command == "exit") {
-//             m_running = false;
-//             std::cout << "Exiting..." << std::endl;
-//         } else if (!command.empty()) {
-//             std::cout << "Unknown command: " << command << std::endl;
-//         }
-//     }
-
-//     void showStats()
-//     {
-//         auto stats = m_player->getStats();
-
-//         std::cout << "\n=== Playback Statistics ===" << std::endl;
-//         std::cout << "Current Time: " << std::fixed << std::setprecision(2)
-//                   << (stats.currentTime / 1000000.0) << "s" << std::endl;
-//         std::cout << "Playback Speed: " << stats.playbackSpeed << "x" << std::endl;
-//         std::cout << "Total Frames: " << stats.totalFrames << std::endl;
-//         std::cout << "Dropped Frames: " << stats.droppedFrames << std::endl;
-//         std::cout << "Duplicated Frames: " << stats.duplicatedFrames << std::endl;
-//         std::cout << "Sync Error: " << std::fixed << std::setprecision(1)
-//                   << (stats.syncError * 1000) << "ms" << std::endl;
-//         std::cout << "Avg Sync Error: " << std::fixed << std::setprecision(1)
-//                   << (stats.avgSyncError * 1000) << "ms" << std::endl;
-//         std::cout << "Max Sync Error: " << std::fixed << std::setprecision(1)
-//                   << (stats.maxSyncError * 1000) << "ms" << std::endl;
-//         std::cout << "CPU Usage: " << std::fixed << std::setprecision(1) << stats.cpuUsage << "%"
-//                   << std::endl;
-//         std::cout << "Memory Usage: " << std::fixed << std::setprecision(1) << stats.memoryUsage
-//                   << "MB" << std::endl;
-//         std::cout << "Queued Packets: " << stats.queuedPackets << std::endl;
-//         std::cout << "Queued Video Frames: " << stats.queuedVideoFrames << std::endl;
-//         std::cout << "Queued Audio Frames: " << stats.queuedAudioFrames << std::endl;
-//         std::cout << "Bitrate: " << std::fixed << std::setprecision(1) << stats.bitrate << " kbps"
-//                   << std::endl;
-//         std::cout << "===========================\n" << std::endl;
-//     }
-
-//     void showSyncConfig()
-//     {
-//         auto config = m_player->getSyncConfig();
-
-//         std::cout << "\n=== Sync Configuration ===" << std::endl;
-//         std::cout << "Sync Strategy: " << static_cast<int>(config.syncStrategy) << std::endl;
-//         std::cout << "Audio Sync Threshold: " << (config.audioSyncThreshold * 1000) << "ms"
-//                   << std::endl;
-//         std::cout << "Video Sync Threshold: " << (config.videoSyncThreshold * 1000) << "ms"
-//                   << std::endl;
-//         std::cout << "Max Sync Error: " << (config.maxSyncError * 1000) << "ms" << std::endl;
-//         std::cout << "Clock Update Interval: " << config.clockUpdateInterval << "ms" << std::endl;
-//         std::cout << "Smoothing Window: " << config.smoothingWindow << std::endl;
-//         std::cout << "Adaptive Sync: " << (config.enableAdaptiveSync ? "Enabled" : "Disabled")
-//                   << std::endl;
-//         std::cout << "Frame Drop: " << (config.enableFrameDrop ? "Enabled" : "Disabled")
-//                   << std::endl;
-//         std::cout << "Frame Duplicate: " << (config.enableFrameDuplicate ? "Enabled" : "Disabled")
-//                   << std::endl;
-//         std::cout << "Prediction: " << (config.enablePrediction ? "Enabled" : "Disabled")
-//                   << std::endl;
-//         std::cout << "==========================\n" << std::endl;
-//     }
-
-//     PlayerCoreV2* m_player;
-//     bool m_running;
-// };
-
-// int main(int argc, char* argv[])
-// {
-//     // 初始化日志系统
-//     Logger::instance().initialize("test.log", LogLevel::DEBUG, false, true);
-//     Logger::instance().setLevel(LogLevel::DEBUG);
-//     Logger::instance().info("PlayerCoreV2 Example Started");
-
-//     try {
-//         // 创建同步配置
-//         SyncConfigV2 syncConfig;
-//         syncConfig.syncStrategy = SyncStrategy::ADAPTIVE; // 使用自适应同步策略
-//         syncConfig.audioSyncThreshold = 0.040;            // 40ms
-//         syncConfig.videoSyncThreshold = 0.020;            // 20ms
-//         syncConfig.maxSyncError = 0.200;                  // 200ms
-//         syncConfig.clockUpdateInterval = 10;              // 10ms
-//         syncConfig.smoothingWindow = 10;                  // 10个样本
-//         syncConfig.enableAdaptiveSync = true;
-//         syncConfig.enableFrameDrop = true;
-//         syncConfig.enableFrameDuplicate = true;
-//         syncConfig.enablePrediction = true;
-//         syncConfig.enableErrorRecovery = true;
-
-//         // 创建播放器实例
-//         auto player = std::make_unique<PlayerCoreV2>(syncConfig);
-
-//         // 创建事件回调
-//         auto callback = std::make_unique<ExamplePlayerCallback>();
-//         player->setEventCallback(callback.get());
-
-//         // 如果命令行提供了文件名,自动打开
-//         if (argc > 1) {
-//             std::string filename = argv[1];
-//             std::cout << "Opening file: " << filename << std::endl;
-
-//             auto result = player->openFile(filename);
-//             if (result == ErrorCode::SUCCESS) {
-//                 std::cout << "File opened successfully" << std::endl;
-
-//                 // 自动开始播放
-//                 result = player->play();
-//                 if (result == ErrorCode::SUCCESS) {
-//                     std::cout << "Playback started" << std::endl;
-//                 } else {
-//                     std::cout << "Failed to start playback: " << static_cast<int>(result)
-//                               << std::endl;
-//                 }
-//             } else {
-//                 std::cout << "Failed to open file: " << static_cast<int>(result) << std::endl;
-//             }
-//         }
-
-//         // 启动用户界面
-//         SimplePlayerUI ui(player.get());
-
-//         // 启动更新线程
-//         std::atomic<bool> shouldStop(false);
-//         std::thread updateThread([&player, &shouldStop]() {
-//             while (!shouldStop) {
-//                 player->update();
-//                 std::this_thread::sleep_for(std::chrono::milliseconds(16)); // ~60 FPS
-//             }
-//         });
-
-//         // 运行用户界面
-//         ui.run();
-
-//         // 停止更新线程
-//         shouldStop = true;
-//         if (updateThread.joinable()) {
-//             updateThread.join();
-//         }
-
-//         // 等待播放完成后再停止播放器
-//         if (player->getState() == PlayerState::Playing) {
-//             auto mediaInfo = player->getMediaInfo();
-//             if (mediaInfo.duration > 0) {
-//                 std::cout << "Waiting for playback to complete..." << std::endl;
-
-//                 // 等待播放完成
-//                 while (player->getState() == PlayerState::Playing) {
-//                     auto currentTime = player->getCurrentTime();
-//                     auto duration = mediaInfo.duration;
-
-//                     // 如果播放时间接近总时长(留100ms缓冲),认为播放完成
-//                     if (currentTime >= duration - 100000) { // 100ms = 100000微秒
-//                         std::cout << "Playback completed naturally" << std::endl;
-//                         break;
-//                     }
-
-//                     // 每100ms检查一次
-//                     std::this_thread::sleep_for(std::chrono::milliseconds(100));
-//                 }
-//             }
-//         }
-
-//         // 停止播放器
-//         player->stop();
-
-//         std::cout << "PlayerCoreV2 Example finished" << std::endl;
-
-//     } catch (const std::exception& e) {
-//         std::cerr << "Exception: " << e.what() << std::endl;
-//         return 1;
-//     } catch (...) {
-//         std::cerr << "Unknown exception occurred" << std::endl;
-//         return 1;
-//     }
-
-//     return 0;
-// }
+// #include "AVPlayer2/mainwindowa.h"
+
+#include "ui/av_recorder.h"
+
+#include <QApplication>
+#include <QAudioDeviceInfo>
+#include <QAudioOutput>
+#include <QDateTime>
+#include <QDebug>
+#include <QFile>
+#include <QLoggingCategory>
+#include <QMutex>
+#include <QTextStream>
+#include <QVBoxLayout>
+#include <qendian.h>
+#include <qmath.h>
+
+#include "mainwindow.h"
+#include "thememanager.h"
+#include "themesettingswidget.h"
+
+namespace avrecorder::video {
+void InitWinRTCapture();
+}
+int main(int argc, char *argv[])
+{
+    QLoggingCategory::setFilterRules(QStringLiteral("player.controller.ReadThread=false\n"
+                                                    "player.controller.AudioPlayThread=false\n"));
+    // QLoggingCategory::setFilterRules("*.debug=false\n"
+    //                                  "*.info=false\n"
+    //                                  "*.warning=false\n"
+    //                                  "*.critical=false\n"
+    //                                  "player.controller.*.debug=true\n"
+    //                                  "player.controller.*.info=true\n");
+
+    // 安装日志处理器
+    //qInstallMessageHandler(myMessageHandler);
+
+    // std::freopen(nullptr, "w", stdout);
+    setvbuf(stdout, nullptr, _IONBF, 0);
+
+#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
+    QGuiApplication::setHighDpiScaleFactorRoundingPolicy(
+        Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
+#endif
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+    QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
+#endif
+
+    QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
+
+    QApplication a(argc, argv);
+
+    qRegisterMetaType<AVFrame *>("AVFrame*");
+
+    ThemeManager::instance().setThemeMode(ThemeManager::Light);
+
+    // 注册Room 相关的类型 方便 序列化
+    void initRoomType();
+    initRoomType();
+
+    // 初始化wgc
+
+    avrecorder::video::InitWinRTCapture();
+
+    /*
+docker run -itd  --name zlmediakit --restart=always
+-p 1935:1935 -p 8080:80 -p 8443:443
+-p 8554:554 -p 10000:10000
+-p 10000:10000/udp -p 8000:8000/udp
+-p 9000:9000/udp
+-v /data/zlmediakit/media/bin:/opt/media/bin
+-v /data/zlmediakit/media/conf:/opt/media/conf
+zlmediakit/zlmediakit:master
+*/
+    // MainWindow w;
+    // w.show();
+
+    AvRecorder avRecorder;
+    avRecorder.show();
+    // ThemeSettingsWidget ThemeSettingsWidget;
+    // ThemeSettingsWidget.show();
+
+    // PlayerWindow w;
+    // w.resize(960, 540);
+    // w.show();
+
+    // MainWindowA aa;
+    // aa.show();
+
+    // // 这里填你的流地址
+    // // w.startPlay("http://vd3.bdstatic.com/mda-jennyc5ci1ugrxzi/mda-jennyc5ci1ugrxzi.mp4");
+
+    // w.open("C:/Users/zhuizhu/Videos/1.mp4");
+    // // w.startPlay("rtmp://192.168.3.76:1935/stream/V1/stream");
+
+    int ret = a.exec();
+
+    return ret;
+}

+ 36 - 36
thardware/thardware.cpp

@@ -16,44 +16,44 @@ THardWare::THardWare() {}
 static bool GetPhyMacAddress(const char *strServiceName, char *RealMAC)
 {
     bool bRet = false;
-    char pstrBuf[512] = {0};
-    sprintf(pstrBuf, "//./%s", strServiceName);
+    // char pstrBuf[512] = {0};
+    // sprintf(pstrBuf, "//./%s", strServiceName);
 
-    HANDLE hDev = CreateFileA(pstrBuf,
-                              GENERIC_READ | GENERIC_WRITE,
-                              FILE_SHARE_READ | FILE_SHARE_WRITE,
-                              NULL,
-                              OPEN_EXISTING,
-                              0,
-                              0);
-    if (hDev != INVALID_HANDLE_VALUE) {
-        int inBuf;
-        BYTE outBuf[256] = {0};
-        DWORD BytesReturned;
-        inBuf = OID_802_3_PERMANENT_ADDRESS;
+    // HANDLE hDev = CreateFileA(pstrBuf,
+    //                           GENERIC_READ | GENERIC_WRITE,
+    //                           FILE_SHARE_READ | FILE_SHARE_WRITE,
+    //                           NULL,
+    //                           OPEN_EXISTING,
+    //                           0,
+    //                           0);
+    // if (hDev != INVALID_HANDLE_VALUE) {
+    //     int inBuf;
+    //     BYTE outBuf[256] = {0};
+    //     DWORD BytesReturned;
+    //     inBuf = OID_802_3_PERMANENT_ADDRESS;
 
-        if (DeviceIoControl(hDev,
-                            IOCTL_NDIS_QUERY_GLOBAL_STATS,
-                            (LPVOID) &inBuf,
-                            4,
-                            outBuf,
-                            256,
-                            &BytesReturned,
-                            NULL)) {
-            char buff[256] = {0};
-            sprintf(buff,
-                    "%d%d%d%d%d%d",
-                    outBuf[0],
-                    outBuf[1],
-                    outBuf[2],
-                    outBuf[3],
-                    outBuf[4],
-                    outBuf[5]);
-            bRet = true;
-            memcpy(RealMAC, buff, strlen(buff));
-        }
-        CloseHandle(hDev);
-    }
+    //     if (DeviceIoControl(hDev,
+    //                         IOCTL_NDIS_QUERY_GLOBAL_STATS,
+    //                         (LPVOID) &inBuf,
+    //                         4,
+    //                         outBuf,
+    //                         256,
+    //                         &BytesReturned,
+    //                         NULL)) {
+    //         char buff[256] = {0};
+    //         sprintf(buff,
+    //                 "%d%d%d%d%d%d",
+    //                 outBuf[0],
+    //                 outBuf[1],
+    //                 outBuf[2],
+    //                 outBuf[3],
+    //                 outBuf[4],
+    //                 outBuf[5]);
+    //         bRet = true;
+    //         memcpy(RealMAC, buff, strlen(buff));
+    //     }
+    //     CloseHandle(hDev);
+    // }
     return bRet;
 }
 std::string THardWare::machineCode()

+ 1 - 1
themesettingswidget.cpp

@@ -73,7 +73,7 @@ QGroupBox *ThemeSettingsWidget::createSizeGroup()
     }
 
     connect(m_sizeGroup,
-            QOverload<int>::of(&QButtonGroup::buttonClicked),
+            QOverload<int>::of(&QButtonGroup::idClicked),
             this,
             &ThemeSettingsWidget::changeSizeMode);
 

+ 15 - 2
xmake.lua

@@ -1,5 +1,19 @@
 -- includes("AV")
+-- 设置项目信息
+set_project("AV_Framework")
+set_version("1.0.0")
+set_languages("c++17")
 
+-- 设置编译模式
+add_rules("mode.debug", "mode.release")
+
+-- 设置编译选项
+if is_plat("windows") then
+    add_cxflags("/W3", "/utf-8")
+    add_defines("_CRT_SECURE_NO_WARNINGS")
+else
+    add_cxflags("-Wall", "-Wextra")
+end
 
 
 target("qt_widgetapp")
@@ -103,5 +117,4 @@ target("qt_widgetapp")
 		end
 		os.execv(jom, {"-j24"}, {envs = envs, curdir = rundir})
 	end)
-target_end()
-
+target_end()