zhuizhu пре 8 месеци
родитељ
комит
8153072aed
41 измењених фајлова са 4674 додато и 637 уклоњено
  1. 1 0
      .gitignore
  2. 10 0
      .xmake/windows/x64/cache/config
  3. 0 0
      .xmake/windows/x64/cache/cxxmodules
  4. 32 18
      .xmake/windows/x64/cache/detect
  5. 17 0
      .xmake/windows/x64/cache/history
  6. 0 0
      .xmake/windows/x64/cache/option
  7. 0 0
      .xmake/windows/x64/cache/package
  8. 0 0
      .xmake/windows/x64/cache/project
  9. 12 24
      .xmake/windows/x64/cache/toolchain
  10. 2 2
      .xmake/windows/x64/xmake.conf
  11. 0 7
      AV/.xmake/windows/x64/cache/config
  12. 0 69
      AV/.xmake/windows/x64/cache/history
  13. 0 0
      AV/.xmake/windows/x64/project.lock
  14. 2 1
      AV/AV.pri
  15. 0 105
      AV/CMakeLists.txt
  16. 0 67
      AV/build_and_test.bat
  17. 2 1
      AV/code/base/media_common.h
  18. 2 2
      AV/code/capture/capture_audio_capturer.cpp
  19. 7 7
      AV/code/codec/codec_video_encoder.cpp
  20. 2 2
      AV/code/muxer/muxer_file_muxer.cpp
  21. 346 0
      AV/code/player/SimplePlayerWindow.cpp
  22. 83 0
      AV/code/player/SimplePlayerWindow.h
  23. 361 0
      AV/code/player/audio_output.cpp
  24. 150 0
      AV/code/player/audio_output.h
  25. 15 0
      AV/code/player/player.pri
  26. 325 0
      AV/code/player/player_adapter.cpp
  27. 195 0
      AV/code/player/player_adapter.h
  28. 753 0
      AV/code/player/player_core.cpp
  29. 227 0
      AV/code/player/player_core.h
  30. 590 0
      AV/code/player/thread_manager.cpp
  31. 295 0
      AV/code/player/thread_manager.h
  32. 299 0
      AV/code/player/video_renderer.cpp
  33. 150 0
      AV/code/player/video_renderer.h
  34. 0 130
      AV/codec_test_log.txt
  35. 31 0
      AV/integration_example.cpp
  36. 0 133
      AV/output.txt
  37. 330 0
      AV/test_player.cpp
  38. 347 0
      AV/utils_test_log.txt
  39. 18 56
      AV/xmake.lua
  40. 69 13
      AV_REFACTOR_PLAN.md
  41. 1 0
      xmake.lua

+ 1 - 0
.gitignore

@@ -15,3 +15,4 @@
 /bin/translations/*.qm
 /bin_debug
 /AV/build
+/AV/.xmake

+ 10 - 0
.xmake/windows/x64/cache/config

@@ -0,0 +1,10 @@
+{
+    options = {
+        qt = [[D:\Qt\5.15.2\msvc2019_64]]
+    },
+    mtimes = {
+        ["xmake.lua"] = 1753559920,
+        ["AV\\xmake.lua"] = 1753559657
+    },
+    recheck = false
+}

+ 0 - 0
AV/.xmake/windows/x64/cache/cxxmodules → .xmake/windows/x64/cache/cxxmodules


+ 32 - 18
AV/.xmake/windows/x64/cache/detect → .xmake/windows/x64/cache/detect

@@ -1,31 +1,45 @@
 {
-    find_program_msvc_arch_x64_plat_windows_checktoolld = {
-        ["link.exe"] = [[C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.39.33519\bin\HostX64\x64\link.exe]]
-    },
-    find_programver = {
-        ["C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Tools\\MSVC\\14.39.33519\\bin\\HostX64\\x64\\cl.exe"] = "19.39.33523"
-    },
     ["lib.detect.has_flags"] = {
-        ["windows_x64_C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Tools\\MSVC\\14.39.33519\\bin\\HostX64\\x64\\cl.exe_19.39.33523_cxx_cxflags_-nologo_/utf-8"] = true,
-        ["windows_x64_C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Tools\\MSVC\\14.39.33519\\bin\\HostX64\\x64\\cl.exe_19.39.33523_cxx_cxflags_-nologo_-DNDEBUG"] = true,
-        ["windows_x64_C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Tools\\MSVC\\14.39.33519\\bin\\HostX64\\x64\\cl.exe_19.39.33523_cxx__-nologo_-O2"] = true,
+        ["windows_x64_C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Tools\\MSVC\\14.39.33519\\bin\\HostX64\\x64\\cl.exe_19.39.33523_cxx_cxflags_-nologo_cl_external_includedir"] = true,
+        ["windows_x64_C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Tools\\MSVC\\14.39.33519\\bin\\HostX64\\x64\\cl.exe_19.39.33523_cxx_cxflags_-nologo_/W3"] = true,
         ["windows_x64_C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Tools\\MSVC\\14.39.33519\\bin\\HostX64\\x64\\cl.exe_19.39.33523_cxx_cxflags_-nologo_cl_sourceDependencies"] = true,
-        ["windows_x64_C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Tools\\MSVC\\14.39.33519\\bin\\HostX64\\x64\\cl.exe_19.39.33523_cxx_cxflags_-nologo_/W3"] = true
+        ["windows_x64_C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Tools\\MSVC\\14.39.33519\\bin\\HostX64\\x64\\cl.exe_19.39.33523_cxx__-nologo_-O2"] = true,
+        ["windows_x64_C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Tools\\MSVC\\14.39.33519\\bin\\HostX64\\x64\\cl.exe_19.39.33523_cxx_cxflags_-nologo_/utf-8"] = true,
+        ["windows_x64_C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Tools\\MSVC\\14.39.33519\\bin\\HostX64\\x64\\cl.exe_19.39.33523_cxx_cxflags_-nologo_-DNDEBUG"] = true
+    },
+    find_program_msvc_arch_x64_plat_windows_checktoolcc = {
+        ["cl.exe"] = [[C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.39.33519\bin\HostX64\x64\cl.exe]]
     },
     find_program = {
-        git = [[C:\Program Files\Git\cmd\git.exe]],
-        ["C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Tools\\MSVC\\14.39.33519\\bin\\HostX64\\x64\\cl.exe"] = [[C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.39.33519\bin\HostX64\x64\cl.exe]],
+        ["cl.exe"] = [[C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.39.33519\bin\HostX64\x64\cl.exe]],
         nim = false,
-        ping = "ping",
-        ["cl.exe"] = [[C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.39.33519\bin\HostX64\x64\cl.exe]]
+        ["C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Tools\\MSVC\\14.39.33519\\bin\\HostX64\\x64\\cl.exe"] = [[C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.39.33519\bin\HostX64\x64\cl.exe]]
     },
-    find_program_msvc_arch_x64_plat_windows_checktoolar = {
-        ["link.exe"] = [[C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.39.33519\bin\HostX64\x64\link.exe]]
+    ["detect.sdks.find_qt"] = {
+        qt = {
+            bindir_host = "D:/Qt/5.15.2/msvc2019_64/bin",
+            includedir = "D:/Qt/5.15.2/msvc2019_64/include",
+            bindir = "D:/Qt/5.15.2/msvc2019_64/bin",
+            sdkdir = "D:/Qt/5.15.2/msvc2019_64",
+            libexecdir = "D:/Qt/5.15.2/msvc2019_64/bin",
+            libdir = "D:/Qt/5.15.2/msvc2019_64/lib",
+            qmldir = "D:/Qt/5.15.2/msvc2019_64/qml",
+            mkspecsdir = [[D:\Qt\5.15.2\msvc2019_64\mkspecs]],
+            pluginsdir = "D:/Qt/5.15.2/msvc2019_64/plugins",
+            sdkver = "5.15.2"
+        },
+        ["D:\\Qt\\5.15.2\\msvc2019_64"] = ref("detect.sdks.find_qt")
     },
-    find_program_msvc_arch_x64_plat_windows_checktoolcc = {
-        ["cl.exe"] = [[C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.39.33519\bin\HostX64\x64\cl.exe]]
+    find_programver = {
+        ["C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Tools\\MSVC\\14.39.33519\\bin\\HostX64\\x64\\cl.exe"] = "19.39.33523"
     },
     find_program_msvc_arch_x64_plat_windows_checktoolcxx = {
         ["cl.exe"] = [[C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.39.33519\bin\HostX64\x64\cl.exe]]
+    },
+    find_program_msvc_arch_x64_plat_windows_checktoolar = {
+        ["link.exe"] = [[C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.39.33519\bin\HostX64\x64\link.exe]]
+    },
+    find_program_msvc_arch_x64_plat_windows_checktoolld = {
+        ["link.exe"] = [[C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.39.33519\bin\HostX64\x64\link.exe]]
     }
 }

+ 17 - 0
.xmake/windows/x64/cache/history

@@ -0,0 +1,17 @@
+{
+    cmdlines = {
+        "xmake ",
+        [[xmake f --qt=D:\Qt\5.15.2\msvc2019_64]],
+        "xmake ",
+        "xmake ",
+        "xmake ",
+        "xmake ",
+        "xmake ",
+        "xmake build",
+        "xmake build",
+        "xmake build",
+        "xmake build",
+        "xmake build",
+        "xmake build"
+    }
+}

+ 0 - 0
AV/.xmake/windows/x64/cache/option → .xmake/windows/x64/cache/option


+ 0 - 0
AV/.xmake/windows/x64/cache/package → .xmake/windows/x64/cache/package


+ 0 - 0
AV/.xmake/windows/x64/cache/project → .xmake/windows/x64/cache/project


Разлика између датотеке није приказан због своје велике величине
+ 12 - 24
.xmake/windows/x64/cache/toolchain


+ 2 - 2
AV/.xmake/windows/x64/xmake.conf → .xmake/windows/x64/xmake.conf

@@ -14,8 +14,6 @@
     buildir = "build",
     ccache = true,
     clean = true,
-    enable_examples = false,
-    enable_tests = true,
     host = "windows",
     kind = "static",
     mode = "release",
@@ -27,6 +25,8 @@
     plat = "windows",
     proxy = "http://192.168.3.28:20171",
     proxy_pac = "pac.lua",
+    qt = [[D:\Qt\5.15.2\msvc2019_64]],
+    qt_sdkver = "5.15.2",
     theme = "default",
     vs = "2022"
 }

+ 0 - 7
AV/.xmake/windows/x64/cache/config

@@ -1,7 +0,0 @@
-{
-    mtimes = {
-        ["xmake.lua"] = 1753545176
-    },
-    recheck = false,
-    options = { }
-}

+ 0 - 69
AV/.xmake/windows/x64/cache/history

@@ -1,69 +0,0 @@
-{
-    cmdlines = {
-        "xmake build av_utils",
-        "xmake build av_utils",
-        "xmake build av_utils",
-        "xmake build av_utils",
-        "xmake build av_utils",
-        "xmake build av_utils",
-        "xmake build av_utils",
-        "xmake build av_utils",
-        "xmake build av_utils",
-        "xmake build av_utils",
-        "xmake build av_utils",
-        "xmake build av_utils",
-        "xmake build av_utils",
-        "xmake build av_utils",
-        "xmake build av_utils",
-        "xmake build av_utils",
-        "xmake build av_utils",
-        "xmake build av_utils",
-        "xmake build av_utils",
-        "xmake build av_utils",
-        "xmake build av_utils",
-        "xmake build",
-        "xmake build test_utils",
-        "xmake build test_utils",
-        "xmake build test_utils",
-        "xmake build",
-        "xmake build test_utils",
-        "xmake build test_utils",
-        "xmake build test_utils",
-        "xmake build test_utils",
-        "xmake build av_muxer",
-        "xmake build av_muxer",
-        "xmake build av_muxer",
-        "xmake build av_muxer",
-        [[xmake lua "D:\\\\Program Files\\\\xmake\\\\modules\\\\private\\\\utils\\\\statistics.lua"]],
-        [[xmake lua "D:\\\\Program Files\\\\xmake\\\\actions\\\\build\\\\cleaner.lua"]],
-        "xmake build av_muxer",
-        "xmake build av_muxer",
-        "xmake build av_muxer",
-        "xmake build av_muxer",
-        "xmake build av_muxer",
-        "xmake build av_muxer",
-        "xmake build test_muxer",
-        "xmake build test_muxer",
-        "xmake build test_muxer",
-        "xmake build test_muxer",
-        "xmake build test_muxer",
-        "xmake build av_muxer",
-        "xmake run test_muxer",
-        "xmake run test_muxer",
-        "xmake build test_muxer",
-        "xmake build test_muxer",
-        "xmake build test_muxer",
-        "xmake build test_muxer",
-        "xmake build test_muxer",
-        "xmake run test_muxer",
-        "xmake build test_muxer",
-        "xmake run test_muxer",
-        "xmake build test_muxer",
-        "xmake run test_muxer",
-        "xmake build test_muxer",
-        "xmake build test_muxer",
-        "xmake run test_muxer",
-        "xmake build test_muxer",
-        "xmake run test_muxer"
-    }
-}

+ 0 - 0
AV/.xmake/windows/x64/project.lock


+ 2 - 1
AV/AV.pri

@@ -41,6 +41,7 @@ SOURCES += \
     $$PWD/code/utils/utils_synchronizer.cpp \
     $$PWD/code/utils/utils_thread_pool.cpp
 
+include($$PWD/code/player/player.pri)
 
 # SOURCES += $$PWD/test_basic.cpp
 # SOURCES += $$PWD/test_codec.cpp
@@ -49,7 +50,7 @@ SOURCES += \
 # SOURCES += $$PWD/test_window_capture.cpp
 # SOURCES += $$PWD/test_utils.cpp
 
-SOURCES += $$PWD/test_muxer.cpp
+SOURCES += $$PWD/integration_example.cpp
 
 
 

+ 0 - 105
AV/CMakeLists.txt

@@ -1,105 +0,0 @@
-cmake_minimum_required(VERSION 3.16)
-project(AV_Framework)
-
-# 设置C++标准
-set(CMAKE_CXX_STANDARD 17)
-set(CMAKE_CXX_STANDARD_REQUIRED ON)
-
-# 设置编译选项
-if(MSVC)
-    add_compile_options(/W3)
-else()
-    add_compile_options(-Wall -Wextra)
-endif()
-
-# 查找线程库
-find_package(Threads REQUIRED)
-
-# 查找FFmpeg库
-find_package(PkgConfig REQUIRED)
-pkg_check_modules(FFMPEG REQUIRED
-    libavcodec
-    libavformat
-    libavutil
-    libswscale
-    libswresample
-)
-
-# 基础库源文件
-set(BASE_SOURCES
-    code/base/logger.cpp
-    code/base/media_thread_base.cpp
-    code/base/media_common.cpp
-)
-
-# 基础库头文件
-set(BASE_HEADERS
-    code/base/types.h
-    code/base/logger.h
-    code/base/media_thread_base.h
-    code/base/media_common.h
-)
-
-# 编解码库源文件
-set(CODEC_SOURCES
-    code/codec/codec_abstract_codec.cpp
-    code/codec/codec_video_encoder.cpp
-    code/codec/codec_audio_encoder.cpp
-)
-
-# 编解码库头文件
-set(CODEC_HEADERS
-    code/codec/codec_abstract_codec.h
-    code/codec/codec_video_encoder.h
-    code/codec/codec_audio_encoder.h
-)
-
-# 创建基础库
-add_library(av_base STATIC ${BASE_SOURCES} ${BASE_HEADERS})
-target_include_directories(av_base PUBLIC .)
-target_link_libraries(av_base PUBLIC Threads::Threads)
-
-# 创建编解码库
-add_library(av_codec STATIC ${CODEC_SOURCES} ${CODEC_HEADERS})
-target_include_directories(av_codec PUBLIC . ${FFMPEG_INCLUDE_DIRS})
-target_link_libraries(av_codec PUBLIC av_base ${FFMPEG_LIBRARIES})
-target_compile_options(av_codec PRIVATE ${FFMPEG_CFLAGS_OTHER})
-
-# 创建完整的AV库
-add_library(av_framework STATIC)
-target_link_libraries(av_framework PUBLIC av_base av_codec)
-
-# 测试程序
-add_executable(test_basic test_basic.cpp)
-target_link_libraries(test_basic av_base)
-
-# 编解码测试程序
-add_executable(test_codec test_codec.cpp)
-target_link_libraries(test_codec av_framework)
-
-# 设置输出目录
-set_target_properties(test_basic test_codec PROPERTIES
-    RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
-)
-
-# 如果是Windows,复制运行时库
-if(WIN32)
-    set_target_properties(test_basic test_codec PROPERTIES
-        VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/bin
-    )
-endif()
-
-# 安装规则
-install(TARGETS av_framework av_base av_codec
-    ARCHIVE DESTINATION lib
-    LIBRARY DESTINATION lib
-    RUNTIME DESTINATION bin
-)
-
-install(FILES ${BASE_HEADERS}
-    DESTINATION include/av/base
-)
-
-install(FILES ${CODEC_HEADERS}
-    DESTINATION include/av/codec
-)

+ 0 - 67
AV/build_and_test.bat

@@ -1,67 +0,0 @@
-@echo off
-echo ===== AV解码器测试构建脚本 =====
-
-:: 设置编码为UTF-8
-chcp 65001 > nul
-
-:: 检查CMake是否存在
-cmake --version > nul 2>&1
-if %errorlevel% neq 0 (
-    echo 错误: 未找到CMake,请先安装CMake
-    pause
-    exit /b 1
-)
-
-:: 创建构建目录
-if not exist "build_test" (
-    mkdir build_test
-)
-
-cd build_test
-
-echo.
-echo 正在配置CMake项目...
-:: 使用CMakeLists_test.txt作为CMakeLists.txt
-copy /Y "..\CMakeLists_test.txt" "CMakeLists.txt" > nul
-
-:: 配置项目
-cmake .. -G "Visual Studio 16 2019" -A x64
-if %errorlevel% neq 0 (
-    echo 错误: CMake配置失败
-    echo 请检查:
-    echo 1. FFmpeg是否正确安装
-    echo 2. 环境变量FFMPEG_ROOT是否设置
-    echo 3. Visual Studio是否正确安装
-    pause
-    exit /b 1
-)
-
-echo.
-echo 正在编译项目...
-:: 编译项目
-cmake --build . --config Release
-if %errorlevel% neq 0 (
-    echo 错误: 编译失败
-    echo 请检查编译错误信息
-    pause
-    exit /b 1
-)
-
-echo.
-echo 编译成功!正在运行测试...
-echo.
-
-:: 运行测试
-if exist "bin\Release\test_decoder.exe" (
-    bin\Release\test_decoder.exe
-) else if exist "Release\test_decoder.exe" (
-    Release\test_decoder.exe
-) else (
-    echo 错误: 找不到测试可执行文件
-    pause
-    exit /b 1
-)
-
-echo.
-echo 测试完成!
-pause

+ 2 - 1
AV/code/base/media_common.h

@@ -7,6 +7,7 @@
 #include <memory>
 #include <functional>
 #include <chrono>
+#include <limits>
 
 namespace av {
 
@@ -275,4 +276,4 @@ ResourceGuard<Resource, Deleter> makeResourceGuard(Resource resource, Deleter de
         AV_LOGGER_INFOF("{} took {} ms", name, _timer.elapsedMs()); \
     } while(0)
 
-#endif // AV_BASE_COMMON_H
+#endif // AV_BASE_MEDIA_COMMON_H

+ 2 - 2
AV/code/capture/capture_audio_capturer.cpp

@@ -265,7 +265,7 @@ ErrorCode AudioCapturer::setNoiseReduction(bool enable) {
     noiseReductionEnabled_ = enable;
     audioParams_.enableNoiseReduction = enable;
     
-    AV_LOGGER_INFOF("降噪已{}", enable ? "启用" : "禁用");
+    AV_LOGGER_INFOF("Noise reduction {}", enable ? "enabled" : "disabled");
     
     return ErrorCode::OK;
 }
@@ -274,7 +274,7 @@ ErrorCode AudioCapturer::setEchoCancellation(bool enable) {
     echoCancellationEnabled_ = enable;
     audioParams_.enableEchoCancellation = enable;
     
-    AV_LOGGER_INFOF("回声消除已{}", enable ? "启用" : "禁用");
+    AV_LOGGER_INFOF("Echo cancellation {}", enable ? "enabled" : "disabled");
     
     return ErrorCode::OK;
 }

+ 7 - 7
AV/code/codec/codec_video_encoder.cpp

@@ -388,27 +388,27 @@ ErrorCode VideoEncoder::setupEncoderParams() {
         // NVENC 特定参数 - 使用更保守的设置
         int ret;
         ret = av_opt_set(codecCtx_->priv_data, "preset", "medium", 0);
-        AV_LOGGER_INFOF("设置preset=medium: {}", ret == 0 ? "成功" : "失败");
+        AV_LOGGER_INFOF("Set preset=medium: {}", ret == 0 ? "success" : "failed");
         
         ret = av_opt_set(codecCtx_->priv_data, "profile", "main", 0);
-        AV_LOGGER_INFOF("设置profile=main: {}", ret == 0 ? "成功" : "失败");
+        AV_LOGGER_INFOF("Set profile=main: {}", ret == 0 ? "success" : "failed");
         
         ret = av_opt_set(codecCtx_->priv_data, "rc", "vbr", 0);
-        AV_LOGGER_INFOF("设置rc=vbr: {}", ret == 0 ? "成功" : "失败");
+        AV_LOGGER_INFOF("Set rc=vbr: {}", ret == 0 ? "success" : "failed");
         
         ret = av_opt_set_int(codecCtx_->priv_data, "surfaces", 16, 0);
-        AV_LOGGER_INFOF("设置surfaces=16: {}", ret == 0 ? "成功" : "失败");
+        AV_LOGGER_INFOF("Set surfaces=16: {}", ret == 0 ? "success" : "failed");
         
         ret = av_opt_set_int(codecCtx_->priv_data, "delay", 0, 0);
-        AV_LOGGER_INFOF("设置delay=0: {}", ret == 0 ? "成功" : "失败");
+        AV_LOGGER_INFOF("Set delay=0: {}", ret == 0 ? "success" : "failed");
         
         if (videoParams_.lowLatency) {
             AV_LOGGER_INFO("启用低延迟模式");
             ret = av_opt_set(codecCtx_->priv_data, "preset", "fast", 0);
-            AV_LOGGER_INFOF("设置preset=fast: {}", ret == 0 ? "成功" : "失败");
+            AV_LOGGER_INFOF("Set preset=fast: {}", ret == 0 ? "success" : "failed");
             
             ret = av_opt_set(codecCtx_->priv_data, "tune", "ll", 0);
-            AV_LOGGER_INFOF("设置tune=ll: {}", ret == 0 ? "成功" : "失败");
+            AV_LOGGER_INFOF("Set tune=ll: {}", ret == 0 ? "success" : "failed");
         }
     } else if (videoParams_.codecName == "h264_qsv") {
         // QSV 特定参数

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

@@ -310,7 +310,7 @@ ErrorCode FileMuxer::enableSegmentation(bool enable, int duration) {
     fileMuxerParams_.enableSegmentation = enable;
     fileMuxerParams_.segmentDuration = duration;
     
-    AV_LOGGER_INFOF("分段已{}: 时长={}秒", enable ? "启用" : "禁用", duration);
+    AV_LOGGER_INFOF("Segmentation {}: duration={}s", enable ? "enabled" : "disabled", duration);
     
     return ErrorCode::OK;
 }
@@ -342,7 +342,7 @@ ErrorCode FileMuxer::setFastStart(bool enable) {
         fileMuxerParams_.movFlags &= ~0x01;
     }
     
-    AV_LOGGER_INFOF("快速开始已{}", enable ? "启用" : "禁用");
+    AV_LOGGER_INFOF("Fast start {}", enable ? "enabled" : "disabled");
     
     return ErrorCode::OK;
 }

+ 346 - 0
AV/code/player/SimplePlayerWindow.cpp

@@ -0,0 +1,346 @@
+#include "SimplePlayerWindow.h"
+#include <QFileDialog>
+#include <QMessageBox>
+#include <QDebug>
+#include <QFileInfo>
+
+SimplePlayerWindow::SimplePlayerWindow(QWidget *parent)
+    : QMainWindow(parent)
+    , m_playerAdapter(PlayerAdapterFactory::create(this))
+    , m_videoRenderer(nullptr)
+{
+    setupUI();
+    connectSignals();
+    updateUI();
+    
+    // 设置视频渲染器
+    if (m_videoRenderer && m_playerAdapter) {
+        m_playerAdapter->setVideoRenderer(m_videoRenderer);
+    }
+    
+    setWindowTitle("Simple Media Player");
+    resize(800, 600);
+}
+
+SimplePlayerWindow::~SimplePlayerWindow()
+{
+    if (m_playerAdapter) {
+        m_playerAdapter->stop();
+    }
+}
+
+void SimplePlayerWindow::openFile()
+{
+    QString filename = QFileDialog::getOpenFileName(
+        this,
+        "Open Media File",
+        "",
+        "Media Files (*.mp4 *.avi *.mkv *.mov *.wmv *.flv *.webm *.mp3 *.wav *.aac *.flac *.ogg);;All Files (*.*)"
+    );
+    
+    if (!filename.isEmpty()) {
+        av::ErrorCode result = m_playerAdapter->openFile(filename);
+        if (result != av::ErrorCode::OK) {
+            QMessageBox::critical(this, "Error", "Failed to open file: " + filename);
+        } else {
+            m_fileLabel->setText("File: " + QFileInfo(filename).fileName());
+        }
+    }
+}
+
+void SimplePlayerWindow::playPause()
+{
+    PlayerState state = m_playerAdapter->getState();
+    
+    if (state == PlayerState::Playing) {
+        m_playerAdapter->pause();
+    } else if (state == PlayerState::Paused || state == PlayerState::Stopped) {
+        m_playerAdapter->play();
+    }
+}
+
+void SimplePlayerWindow::stop()
+{
+    m_playerAdapter->stop();
+}
+
+void SimplePlayerWindow::seek()
+{
+    if (m_seeking) {
+        qint64 duration = m_playerAdapter->getDuration();
+        qint64 position = (duration * m_positionSlider->value()) / 1000;
+        m_playerAdapter->seek(position);
+    }
+}
+
+void SimplePlayerWindow::setVolume()
+{
+    double volume = m_volumeSlider->value() / 100.0;
+    m_playerAdapter->setVolume(volume);
+    m_volumeLabel->setText(QString("Volume: %1%").arg(m_volumeSlider->value()));
+}
+
+void SimplePlayerWindow::toggleMute()
+{
+    bool muted = m_playerAdapter->isMuted();
+    m_playerAdapter->setMuted(!muted);
+}
+
+void SimplePlayerWindow::setPlaybackSpeed()
+{
+    double speed = m_speedSlider->value() / 100.0;
+    m_playerAdapter->setPlaybackSpeed(speed);
+    m_speedLabel->setText(QString("Speed: %1x").arg(speed, 0, 'f', 2));
+}
+
+void SimplePlayerWindow::onStateChanged(PlayerState state)
+{
+    QString stateText;
+    switch (state) {
+        case PlayerState::Idle:
+            stateText = "Idle";
+            break;
+        // case PlayerState::Loading:
+        //     stateText = "Loading";
+        //     break;
+        case PlayerState::Playing:
+            stateText = "Playing";
+            break;
+        case PlayerState::Paused:
+            stateText = "Paused";
+            break;
+        case PlayerState::Stopped:
+            stateText = "Stopped";
+            break;
+        case PlayerState::Error:
+            stateText = "Error";
+            break;
+    }
+    
+    m_stateLabel->setText("State: " + stateText);
+    updateUI();
+}
+
+void SimplePlayerWindow::onMediaInfoChanged(const MediaInfo& info)
+{
+    QString infoText = QString("Duration: %1 | Video: %2x%3 | Audio: %4 Hz")
+                           .arg(formatTime(info.duration))
+                           .arg(info.width)
+                           .arg(info.height)
+                           .arg(info.audioSampleRate);
+
+    m_infoLabel->setText(infoText);
+}
+
+void SimplePlayerWindow::onPositionChanged(qint64 position)
+{
+    if (!m_seeking) {
+        qint64 duration = m_playerAdapter->getDuration();
+        if (duration > 0) {
+            int sliderValue = (position * 1000) / duration;
+            m_positionSlider->setValue(sliderValue);
+        }
+        
+        QString timeText = QString("%1 / %2")
+                               .arg(formatTime(position))
+                               .arg(formatTime(duration));
+        m_timeLabel->setText(timeText);
+    }
+}
+
+void SimplePlayerWindow::onVolumeChanged(double volume)
+{
+    int volumePercent = static_cast<int>(volume * 100);
+    m_volumeSlider->setValue(volumePercent);
+    m_volumeLabel->setText(QString("Volume: %1%").arg(volumePercent));
+}
+
+void SimplePlayerWindow::onMutedChanged(bool muted)
+{
+    m_muteButton->setText(muted ? "Unmute" : "Mute");
+}
+
+void SimplePlayerWindow::onPlaybackSpeedChanged(double speed)
+{
+    int speedPercent = static_cast<int>(speed * 100);
+    m_speedSlider->setValue(speedPercent);
+    m_speedLabel->setText(QString("Speed: %1x").arg(speed, 0, 'f', 2));
+}
+
+void SimplePlayerWindow::onErrorOccurred(const QString& error)
+{
+    QMessageBox::critical(this, "Player Error", error);
+    qDebug() << "Player error:" << error;
+}
+
+void SimplePlayerWindow::onStatsUpdated(const PlaybackStats& stats)
+{
+    QString statsText = QString("Packets: %1 | Video Frames: %2 | Audio Frames: %3")
+                            .arg(stats.queuedPackets)
+                            .arg(stats.queuedVideoFrames)
+                            .arg(stats.queuedAudioFrames);
+    
+    m_statsLabel->setText(statsText);
+}
+
+void SimplePlayerWindow::setupUI()
+{
+    auto* centralWidget = new QWidget(this);
+    setCentralWidget(centralWidget);
+
+    auto* mainLayout = new QVBoxLayout(centralWidget);
+
+    // 文件信息
+    m_fileLabel = new QLabel("No file loaded");
+    m_stateLabel = new QLabel("State: Idle");
+    m_infoLabel = new QLabel("Media info will appear here");
+
+    mainLayout->addWidget(m_fileLabel);
+    mainLayout->addWidget(m_stateLabel);
+    mainLayout->addWidget(m_infoLabel);
+    
+    // 视频渲染器
+    m_videoRenderer = new VideoRenderer(this);
+    m_videoRenderer->setMinimumSize(640, 480);
+    m_videoRenderer->setStyleSheet("border: 1px solid gray;");
+    mainLayout->addWidget(m_videoRenderer);
+
+    // 控制按钮
+    auto* buttonLayout = new QHBoxLayout();
+
+    m_openButton = new QPushButton("Open File");
+    m_playPauseButton = new QPushButton("Play");
+    m_stopButton = new QPushButton("Stop");
+
+    buttonLayout->addWidget(m_openButton);
+    buttonLayout->addWidget(m_playPauseButton);
+    buttonLayout->addWidget(m_stopButton);
+    buttonLayout->addStretch();
+
+    mainLayout->addLayout(buttonLayout);
+
+    // 进度控制
+    auto* progressLayout = new QHBoxLayout();
+
+    m_timeLabel = new QLabel("00:00 / 00:00");
+    m_positionSlider = new QSlider(Qt::Horizontal);
+    m_positionSlider->setRange(0, 1000);
+
+    progressLayout->addWidget(m_timeLabel);
+    progressLayout->addWidget(m_positionSlider);
+
+    mainLayout->addLayout(progressLayout);
+
+    // 音量控制
+    auto* volumeLayout = new QHBoxLayout();
+
+    m_volumeLabel = new QLabel("Volume: 100%");
+    m_volumeSlider = new QSlider(Qt::Horizontal);
+    m_volumeSlider->setRange(0, 100);
+    m_volumeSlider->setValue(100);
+    m_muteButton = new QPushButton("Mute");
+
+    volumeLayout->addWidget(m_volumeLabel);
+    volumeLayout->addWidget(m_volumeSlider);
+    volumeLayout->addWidget(m_muteButton);
+
+    mainLayout->addLayout(volumeLayout);
+
+    // 播放速度控制
+    auto* speedLayout = new QHBoxLayout();
+
+    m_speedLabel = new QLabel("Speed: 1.00x");
+    m_speedSlider = new QSlider(Qt::Horizontal);
+    m_speedSlider->setRange(25, 400); // 0.25x to 4.0x
+    m_speedSlider->setValue(100);
+
+    speedLayout->addWidget(m_speedLabel);
+    speedLayout->addWidget(m_speedSlider);
+
+    mainLayout->addLayout(speedLayout);
+
+    // 统计信息
+    m_statsLabel = new QLabel("Statistics will appear here");
+    mainLayout->addWidget(m_statsLabel);
+
+    mainLayout->addStretch();
+}
+
+void SimplePlayerWindow::connectSignals()
+{
+    // UI信号
+    connect(m_openButton, &QPushButton::clicked, this, &SimplePlayerWindow::openFile);
+    connect(m_playPauseButton, &QPushButton::clicked, this, &SimplePlayerWindow::playPause);
+    connect(m_stopButton, &QPushButton::clicked, this, &SimplePlayerWindow::stop);
+
+    connect(m_positionSlider, &QSlider::sliderPressed, [this]() { m_seeking = true; });
+    connect(m_positionSlider, &QSlider::sliderReleased, [this]() {
+        seek();
+        m_seeking = false;
+    });
+
+    connect(m_volumeSlider, &QSlider::valueChanged, this, &SimplePlayerWindow::setVolume);
+    connect(m_muteButton, &QPushButton::clicked, this, &SimplePlayerWindow::toggleMute);
+    connect(m_speedSlider, &QSlider::valueChanged, this, &SimplePlayerWindow::setPlaybackSpeed);
+
+    // 播放器信号
+    connect(m_playerAdapter.get(),
+            &PlayerAdapter::stateChanged,
+            this,
+            &SimplePlayerWindow::onStateChanged);
+    connect(m_playerAdapter.get(),
+            &PlayerAdapter::mediaInfoChanged,
+            this,
+            &SimplePlayerWindow::onMediaInfoChanged);
+    connect(m_playerAdapter.get(),
+            &PlayerAdapter::positionChanged,
+            this,
+            &SimplePlayerWindow::onPositionChanged);
+    connect(m_playerAdapter.get(),
+            &PlayerAdapter::volumeChanged,
+            this,
+            &SimplePlayerWindow::onVolumeChanged);
+    connect(m_playerAdapter.get(),
+            &PlayerAdapter::mutedChanged,
+            this,
+            &SimplePlayerWindow::onMutedChanged);
+    connect(m_playerAdapter.get(),
+            &PlayerAdapter::playbackSpeedChanged,
+            this,
+            &SimplePlayerWindow::onPlaybackSpeedChanged);
+    connect(m_playerAdapter.get(),
+            &PlayerAdapter::errorOccurred,
+            this,
+            &SimplePlayerWindow::onErrorOccurred);
+    connect(m_playerAdapter.get(),
+            &PlayerAdapter::statsUpdated,
+            this,
+            &SimplePlayerWindow::onStatsUpdated);
+}
+
+void SimplePlayerWindow::updateUI()
+{
+    PlayerState state = m_playerAdapter->getState();
+
+    // 更新播放/暂停按钮
+    if (state == PlayerState::Playing) {
+        m_playPauseButton->setText("Pause");
+    } else {
+        m_playPauseButton->setText("Play");
+    }
+
+    // 更新按钮可用状态
+    bool hasMedia = (state != PlayerState::Idle);
+    m_playPauseButton->setEnabled(hasMedia);
+    m_stopButton->setEnabled(hasMedia);
+    m_positionSlider->setEnabled(hasMedia);
+}
+
+QString SimplePlayerWindow::formatTime(qint64 microseconds)
+{
+    qint64 seconds = microseconds / 1000000;
+    qint64 minutes = seconds / 60;
+    seconds %= 60;
+
+    return QString("%1:%2").arg(minutes, 2, 10, QChar('0')).arg(seconds, 2, 10, QChar('0'));
+}

+ 83 - 0
AV/code/player/SimplePlayerWindow.h

@@ -0,0 +1,83 @@
+#ifndef SIMPLEPLAYERWINDOW_H
+#define SIMPLEPLAYERWINDOW_H
+
+#include <QApplication>
+#include <QDebug>
+#include <QFileDialog>
+#include <QHBoxLayout>
+#include <QLabel>
+#include <QMainWindow>
+#include <QMessageBox>
+#include <QPushButton>
+#include <QSlider>
+#include <QTimer>
+#include <QVBoxLayout>
+#include "player_adapter.h"
+#include "video_renderer.h"
+
+using namespace av::player;
+
+/**
+ * @brief 简单的播放器UI示例
+ * 
+ * 这个类展示了如何使用新的PlayerAdapter来构建播放器UI
+ */
+class SimplePlayerWindow : public QMainWindow
+{
+    Q_OBJECT
+
+public:
+    explicit SimplePlayerWindow(QWidget* parent = nullptr);
+    ~SimplePlayerWindow();
+private slots:
+    void openFile();
+    void playPause();
+    void stop();
+    void seek();
+    void setVolume();
+    void toggleMute();
+    void setPlaybackSpeed();
+
+    // 播放器事件处理
+    void onStateChanged(PlayerState state);
+    void onMediaInfoChanged(const MediaInfo& info);
+    void onPositionChanged(qint64 position);
+    void onVolumeChanged(double volume);
+    void onMutedChanged(bool muted);
+    void onPlaybackSpeedChanged(double speed);
+    void onErrorOccurred(const QString& error);
+
+    void onStatsUpdated(const PlaybackStats& stats);
+
+private:
+    void setupUI();
+    void connectSignals();
+    void updateUI();
+    QString formatTime(qint64 microseconds);
+
+private:
+    std::unique_ptr<PlayerAdapter> m_playerAdapter;
+    VideoRenderer* m_videoRenderer;
+
+    // UI组件
+    QLabel* m_fileLabel;
+    QLabel* m_stateLabel;
+    QLabel* m_infoLabel;
+    QLabel* m_timeLabel;
+    QLabel* m_volumeLabel;
+    QLabel* m_speedLabel;
+    QLabel* m_statsLabel;
+
+    QPushButton* m_openButton;
+    QPushButton* m_playPauseButton;
+    QPushButton* m_stopButton;
+    QPushButton* m_muteButton;
+
+    QSlider* m_positionSlider;
+    QSlider* m_volumeSlider;
+    QSlider* m_speedSlider;
+
+    bool m_seeking = false;
+};
+
+#endif // SIMPLEPLAYERWINDOW_H

+ 361 - 0
AV/code/player/audio_output.cpp

@@ -0,0 +1,361 @@
+#include "audio_output.h"
+#include "../base/logger.h"
+#include <QAudioDeviceInfo>
+#include <QDebug>
+#include <algorithm>
+#include <cstring>
+
+extern "C" {
+#include <libavutil/channel_layout.h>
+#include <libswresample/swresample.h>
+}
+
+namespace av {
+namespace player {
+
+AudioOutput::AudioOutput(QObject* parent)
+    : QObject(parent)
+    , m_audioOutput(nullptr)
+    , m_audioDevice(nullptr)
+    , m_sampleRate(44100)
+    , m_channels(2)
+    , m_inputFormat(AV_SAMPLE_FMT_S16)
+    , m_swrContext(nullptr)
+    , m_needResampling(false)
+    , m_volume(1.0)
+    , m_initialized(false)
+    , m_playing(false)
+{
+}
+
+AudioOutput::~AudioOutput()
+{
+    stop();
+    cleanupResampler();
+    
+    if (m_audioOutput) {
+        delete m_audioOutput;
+        m_audioOutput = nullptr;
+    }
+}
+
+bool AudioOutput::initialize(int sampleRate, int channels, AVSampleFormat sampleFormat)
+{
+    QMutexLocker locker(&m_mutex);
+    
+    if (m_initialized) {
+        av::Logger::instance().warning("Audio output already initialized");
+        return true;
+    }
+    
+    m_sampleRate = sampleRate;
+    m_channels = channels;
+    m_inputFormat = sampleFormat;
+    
+    // 设置Qt音频格式
+    m_audioFormat.setSampleRate(sampleRate);
+    m_audioFormat.setChannelCount(channels);
+    m_audioFormat.setSampleSize(16); // 输出16位
+    m_audioFormat.setCodec("audio/pcm");
+    m_audioFormat.setByteOrder(QAudioFormat::LittleEndian);
+    m_audioFormat.setSampleType(QAudioFormat::SignedInt);
+    
+    // 检查设备是否支持该格式
+    QAudioDeviceInfo deviceInfo = QAudioDeviceInfo::defaultOutputDevice();
+    if (!deviceInfo.isFormatSupported(m_audioFormat)) {
+        av::Logger::instance().warning("Audio format not supported, using nearest format");
+        m_audioFormat = deviceInfo.nearestFormat(m_audioFormat);
+    }
+    
+    // 创建音频输出设备
+    m_audioOutput = new QAudioOutput(m_audioFormat, this);
+    if (!m_audioOutput) {
+        av::Logger::instance().error("Failed to create audio output device");
+        return false;
+    }
+    
+    // 连接状态变化信号
+    connect(m_audioOutput, &QAudioOutput::stateChanged,
+            this, &AudioOutput::onStateChanged);
+    
+    // 初始化重采样器(如果需要)
+    if (!initResampler()) {
+        av::Logger::instance().error("Failed to initialize audio resampler");
+        return false;
+    }
+    
+    m_initialized = true;
+    av::Logger::instance().info("Audio output initialized successfully");
+    
+    return true;
+}
+
+void AudioOutput::start()
+{
+    QMutexLocker locker(&m_mutex);
+    
+    if (!m_initialized || !m_audioOutput) {
+        av::Logger::instance().error("Audio output not initialized");
+        return;
+    }
+    
+    if (m_playing) {
+        return;
+    }
+    
+    m_audioDevice = m_audioOutput->start();
+    if (!m_audioDevice) {
+        av::Logger::instance().error("Failed to start audio output device");
+        return;
+    }
+    
+    m_playing = true;
+    av::Logger::instance().info("Audio output started");
+}
+
+void AudioOutput::stop()
+{
+    QMutexLocker locker(&m_mutex);
+    
+    if (!m_playing || !m_audioOutput) {
+        return;
+    }
+    
+    m_audioOutput->stop();
+    m_audioDevice = nullptr;
+    m_playing = false;
+    
+    av::Logger::instance().info("Audio output stopped");
+}
+
+void AudioOutput::pause()
+{
+    QMutexLocker locker(&m_mutex);
+    
+    if (!m_playing || !m_audioOutput) {
+        return;
+    }
+    
+    m_audioOutput->suspend();
+    av::Logger::instance().info("Audio output paused");
+}
+
+void AudioOutput::resume()
+{
+    QMutexLocker locker(&m_mutex);
+    
+    if (!m_playing || !m_audioOutput) {
+        return;
+    }
+    
+    m_audioOutput->resume();
+    av::Logger::instance().info("Audio output resumed");
+}
+
+bool AudioOutput::writeFrame(const AVFramePtr& frame)
+{
+    if (!frame || !m_playing || !m_audioDevice) {
+        return false;
+    }
+    
+    // 转换音频帧格式
+    QByteArray audioData = convertFrame(frame);
+    if (audioData.isEmpty()) {
+        return false;
+    }
+    
+    // 应用音量控制
+    applyVolume(audioData);
+    
+    // 写入音频设备
+    qint64 bytesWritten = m_audioDevice->write(audioData);
+    if (bytesWritten != audioData.size()) {
+        av::Logger::instance().warning("Audio write incomplete");
+        return false;
+    }
+    
+    return true;
+}
+
+void AudioOutput::setVolume(double volume)
+{
+    m_volume = std::clamp(volume, 0.0, 1.0);
+    
+    if (m_audioOutput) {
+        m_audioOutput->setVolume(m_volume);
+    }
+}
+
+double AudioOutput::getVolume() const
+{
+    return m_volume;
+}
+
+void AudioOutput::flush()
+{
+    QMutexLocker locker(&m_mutex);
+    
+    if (m_audioOutput) {
+        m_audioOutput->reset();
+    }
+}
+
+int AudioOutput::getBufferSize() const
+{
+    if (m_audioOutput) {
+        return m_audioOutput->bufferSize() * 1000 / 
+               (m_audioFormat.sampleRate() * m_audioFormat.channelCount() * 
+                m_audioFormat.sampleSize() / 8);
+    }
+    return 0;
+}
+
+bool AudioOutput::isPlaying() const
+{
+    return m_playing;
+}
+
+void AudioOutput::onStateChanged(QAudio::State state)
+{
+    switch (state) {
+    case QAudio::ActiveState:
+        av::Logger::instance().debug("Audio output state: Active");
+        break;
+    case QAudio::SuspendedState:
+        av::Logger::instance().debug("Audio output state: Suspended");
+        break;
+    case QAudio::StoppedState:
+        av::Logger::instance().debug("Audio output state: Stopped");
+        break;
+    case QAudio::IdleState:
+        av::Logger::instance().debug("Audio output state: Idle");
+        break;
+    }
+}
+
+bool AudioOutput::initResampler()
+{
+    // 检查是否需要重采样
+    bool needSampleRateConversion = (m_audioFormat.sampleRate() != m_sampleRate);
+    bool needChannelConversion = (m_audioFormat.channelCount() != m_channels);
+    bool needFormatConversion = (m_inputFormat != AV_SAMPLE_FMT_S16);
+    
+    m_needResampling = needSampleRateConversion || needChannelConversion || needFormatConversion;
+    
+    if (!m_needResampling) {
+        av::Logger::instance().info("No audio resampling needed");
+        return true;
+    }
+    
+    // 创建重采样上下文
+    m_swrContext = swr_alloc();
+    if (!m_swrContext) {
+        av::Logger::instance().error("Failed to allocate resampler context");
+        return false;
+    }
+    
+    // 设置输入参数
+    AVChannelLayout inputLayout;
+    av_channel_layout_default(&inputLayout, m_channels);
+    
+    // 设置输出参数
+    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);
+    
+    if (ret < 0) {
+        av::Logger::instance().error("Failed to set resampler options");
+        swr_free(&m_swrContext);
+        return false;
+    }
+    
+    // 初始化重采样器
+    ret = swr_init(m_swrContext);
+    if (ret < 0) {
+        av::Logger::instance().error("Failed to initialize resampler");
+        swr_free(&m_swrContext);
+        return false;
+    }
+    
+    av::Logger::instance().info("Audio resampler initialized successfully");
+    return true;
+}
+
+void AudioOutput::cleanupResampler()
+{
+    if (m_swrContext) {
+        swr_free(&m_swrContext);
+        m_swrContext = nullptr;
+    }
+}
+
+QByteArray AudioOutput::convertFrame(const AVFramePtr& frame)
+{
+    if (!frame) {
+        return QByteArray();
+    }
+    
+    if (!m_needResampling) {
+        // 直接复制数据
+        int dataSize = frame->nb_samples * m_channels * sizeof(int16_t);
+        return QByteArray(reinterpret_cast<const char*>(frame->data[0]), dataSize);
+    }
+    
+    if (!m_swrContext) {
+        av::Logger::instance().error("Resampler not initialized");
+        return QByteArray();
+    }
+    
+    // 计算输出采样数
+    int outputSamples = swr_get_out_samples(m_swrContext, frame->nb_samples);
+    if (outputSamples <= 0) {
+        return QByteArray();
+    }
+    
+    // 分配输出缓冲区
+    int outputChannels = m_audioFormat.channelCount();
+    int outputDataSize = outputSamples * outputChannels * sizeof(int16_t);
+    QByteArray outputData(outputDataSize, 0);
+    
+    uint8_t* outputBuffer = reinterpret_cast<uint8_t*>(outputData.data());
+    
+    // 执行重采样
+    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");
+        return QByteArray();
+    }
+    
+    // 调整输出数据大小
+    int actualDataSize = convertedSamples * outputChannels * sizeof(int16_t);
+    outputData.resize(actualDataSize);
+    
+    return outputData;
+}
+
+void AudioOutput::applyVolume(QByteArray& data)
+{
+    if (std::abs(m_volume - 1.0) < 0.001) {
+        return; // 音量为1.0,无需调整
+    }
+    
+    int16_t* samples = reinterpret_cast<int16_t*>(data.data());
+    int sampleCount = data.size() / sizeof(int16_t);
+    
+    for (int i = 0; i < sampleCount; ++i) {
+        samples[i] = static_cast<int16_t>(samples[i] * m_volume);
+    }
+}
+
+} // namespace player
+} // namespace av
+
+#include "audio_output.moc"

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

@@ -0,0 +1,150 @@
+#ifndef AV_PLAYER_AUDIO_OUTPUT_H
+#define AV_PLAYER_AUDIO_OUTPUT_H
+
+#include <QAudioOutput>
+#include <QAudioFormat>
+#include <QIODevice>
+#include <QMutex>
+#include <QWaitCondition>
+#include <QThread>
+#include <memory>
+#include <atomic>
+#include <queue>
+
+extern "C" {
+#include <libavutil/frame.h>
+#include <libavutil/samplefmt.h>
+#include <libswresample/swresample.h>
+}
+
+#include "../base/media_common.h"
+
+namespace av {
+namespace player {
+
+/**
+ * 音频输出设备类
+ * 负责将解码后的音频帧输出到扬声器
+ */
+class AudioOutput : public QObject
+{
+    Q_OBJECT
+
+public:
+    explicit AudioOutput(QObject* parent = nullptr);
+    ~AudioOutput();
+
+    /**
+     * 初始化音频输出设备
+     * @param sampleRate 采样率
+     * @param channels 声道数
+     * @param sampleFormat 采样格式
+     * @return 是否成功
+     */
+    bool initialize(int sampleRate, int channels, AVSampleFormat sampleFormat);
+
+    /**
+     * 开始播放
+     */
+    void start();
+
+    /**
+     * 停止播放
+     */
+    void stop();
+
+    /**
+     * 暂停播放
+     */
+    void pause();
+
+    /**
+     * 恢复播放
+     */
+    void resume();
+
+    /**
+     * 写入音频帧
+     * @param frame 音频帧
+     * @return 是否成功
+     */
+    bool writeFrame(const AVFramePtr& frame);
+
+    /**
+     * 设置音量
+     * @param volume 音量 (0.0 - 1.0)
+     */
+    void setVolume(double volume);
+
+    /**
+     * 获取音量
+     */
+    double getVolume() const;
+
+    /**
+     * 清空缓冲区
+     */
+    void flush();
+
+    /**
+     * 获取缓冲区大小(毫秒)
+     */
+    int getBufferSize() const;
+
+    /**
+     * 是否正在播放
+     */
+    bool isPlaying() const;
+
+private slots:
+    void onStateChanged(QAudio::State state);
+
+private:
+    /**
+     * 初始化重采样器
+     */
+    bool initResampler();
+
+    /**
+     * 清理重采样器
+     */
+    void cleanupResampler();
+
+    /**
+     * 转换音频帧格式
+     */
+    QByteArray convertFrame(const AVFramePtr& frame);
+
+    /**
+     * 应用音量控制
+     */
+    void applyVolume(QByteArray& data);
+
+private:
+    QAudioOutput* m_audioOutput;
+    QIODevice* m_audioDevice;
+    QAudioFormat m_audioFormat;
+    
+    // 音频参数
+    int m_sampleRate;
+    int m_channels;
+    AVSampleFormat m_inputFormat;
+    
+    // 重采样器
+    SwrContext* m_swrContext;
+    bool m_needResampling;
+    
+    // 音量控制
+    std::atomic<double> m_volume;
+    
+    // 状态
+    std::atomic<bool> m_initialized;
+    std::atomic<bool> m_playing;
+    
+    mutable QMutex m_mutex;
+};
+
+} // namespace player
+} // namespace av
+
+#endif // AV_PLAYER_AUDIO_OUTPUT_H

+ 15 - 0
AV/code/player/player.pri

@@ -0,0 +1,15 @@
+HEADERS += \
+    $$PWD/SimplePlayerWindow.h \
+    $$PWD/audio_output.h \
+    $$PWD/player_adapter.h \
+    $$PWD/player_core.h \
+    $$PWD/thread_manager.h \
+    $$PWD/video_renderer.h
+
+SOURCES += \
+    $$PWD/SimplePlayerWindow.cpp \
+    $$PWD/audio_output.cpp \
+    $$PWD/player_adapter.cpp \
+    $$PWD/player_core.cpp \
+    $$PWD/thread_manager.cpp \
+    $$PWD/video_renderer.cpp

+ 325 - 0
AV/code/player/player_adapter.cpp

@@ -0,0 +1,325 @@
+#include "player_adapter.h"
+#include "video_renderer.h"
+#include "../base/media_common.h"
+#include <QDebug>
+#include <QMetaType>
+
+namespace av {
+namespace player {
+
+// 注册Qt元类型
+static int registerMetaTypes() {
+    qRegisterMetaType<PlayerState>("PlayerState");
+    qRegisterMetaType<MediaInfo>("MediaInfo");
+    qRegisterMetaType<PlaybackStats>("PlaybackStats");
+    qRegisterMetaType<av::ErrorCode>("av::ErrorCode");
+    return 0;
+}
+static int dummy = registerMetaTypes();
+
+PlayerAdapter::PlayerAdapter(QObject* parent)
+    : QObject(parent)
+    , m_playerCore(std::make_unique<PlayerCore>())
+    , m_updateTimer(new QTimer(this))
+{
+    // 设置事件回调
+    m_playerCore->setEventCallback(this);
+    
+    // 连接更新定时器
+    connect(m_updateTimer, &QTimer::timeout, this, &PlayerAdapter::updatePlayer);
+    
+    qDebug() << "PlayerAdapter created";
+}
+
+PlayerAdapter::~PlayerAdapter()
+{
+    stopUpdateTimer();
+    qDebug() << "PlayerAdapter destroyed";
+}
+
+void PlayerAdapter::setVideoRenderer(VideoRenderer* renderer)
+{
+    if (m_playerCore) {
+        m_playerCore->setVideoRenderer(renderer);
+    }
+}
+
+av::ErrorCode PlayerAdapter::openFile(const QString& filename)
+{
+    std::string stdFilename = filename.toStdString();
+    av::ErrorCode result = m_playerCore->openFile(stdFilename);
+    
+    if (result == av::ErrorCode::OK) {
+        // 启动更新定时器
+        startUpdateTimer();
+    }
+    
+    return result;
+}
+
+av::ErrorCode PlayerAdapter::play()
+{
+    return m_playerCore->play();
+}
+
+av::ErrorCode PlayerAdapter::pause()
+{
+    return m_playerCore->pause();
+}
+
+av::ErrorCode PlayerAdapter::stop()
+{
+    av::ErrorCode result = m_playerCore->stop();
+    
+    if (result == av::ErrorCode::OK) {
+        // 停止更新定时器
+        stopUpdateTimer();
+    }
+    
+    return result;
+}
+
+av::ErrorCode PlayerAdapter::seek(qint64 timestamp)
+{
+    return m_playerCore->seek(timestamp);
+}
+
+av::ErrorCode PlayerAdapter::setPlaybackSpeed(double speed)
+{
+    av::ErrorCode result = m_playerCore->setPlaybackSpeed(speed);
+    
+    if (result == av::ErrorCode::OK && std::abs(m_lastPlaybackSpeed - speed) > 0.001) {
+        m_lastPlaybackSpeed = speed;
+        emit playbackSpeedChanged(speed);
+    }
+    
+    return result;
+}
+
+PlayerState PlayerAdapter::getState() const
+{
+    return m_playerCore->getState();
+}
+
+qint64 PlayerAdapter::getCurrentTime() const
+{
+    return m_playerCore->getCurrentTime();
+}
+
+qint64 PlayerAdapter::getDuration() const
+{
+    MediaInfo info = m_playerCore->getMediaInfo();
+    return info.duration;
+}
+
+double PlayerAdapter::getPlaybackSpeed() const
+{
+    return m_playerCore->getPlaybackSpeed();
+}
+
+void PlayerAdapter::setVolume(double volume)
+{
+    m_playerCore->setVolume(volume);
+    
+    if (std::abs(m_lastVolume - volume) > 0.001) {
+        m_lastVolume = volume;
+        emit volumeChanged(volume);
+    }
+}
+
+double PlayerAdapter::getVolume() const
+{
+    return m_playerCore->getVolume();
+}
+
+void PlayerAdapter::setMuted(bool muted)
+{
+    if (m_muted != muted) {
+        m_muted = muted;
+        
+        // 如果静音,设置音量为0;否则恢复之前的音量
+        if (muted) {
+            m_playerCore->setVolume(0.0);
+        } else {
+            m_playerCore->setVolume(m_lastVolume);
+        }
+        
+        emit mutedChanged(muted);
+    }
+}
+
+bool PlayerAdapter::isMuted() const
+{
+    return m_muted;
+}
+
+MediaInfo PlayerAdapter::getMediaInfo() const
+{
+    return m_playerCore->getMediaInfo();
+}
+
+PlaybackStats PlayerAdapter::getStats() const
+{
+    return m_playerCore->getStats();
+}
+
+AVFrame* PlayerAdapter::getNextVideoFrame()
+{
+    return m_playerCore->getNextVideoFrame();
+}
+
+AVFrame* PlayerAdapter::getNextAudioFrame()
+{
+    return m_playerCore->getNextAudioFrame();
+}
+
+void PlayerAdapter::releaseVideoFrame(AVFrame* frame)
+{
+    m_playerCore->releaseVideoFrame(frame);
+}
+
+void PlayerAdapter::releaseAudioFrame(AVFrame* frame)
+{
+    m_playerCore->releaseAudioFrame(frame);
+}
+
+void PlayerAdapter::startUpdateTimer(int intervalMs)
+{
+    if (!m_updateTimer->isActive()) {
+        m_updateTimer->start(intervalMs);
+        qDebug() << "Update timer started with interval:" << intervalMs << "ms";
+    }
+}
+
+void PlayerAdapter::stopUpdateTimer()
+{
+    if (m_updateTimer->isActive()) {
+        m_updateTimer->stop();
+        qDebug() << "Update timer stopped";
+    }
+}
+
+void PlayerAdapter::updatePlayer()
+{
+    // 更新播放器核心
+    m_playerCore->update();
+    
+    // 检查状态变化
+    PlayerState currentState = m_playerCore->getState();
+    if (currentState != m_lastState) {
+        m_lastState = currentState;
+        emit stateChanged(currentState);
+    }
+    
+    // 检查位置和时长变化
+    checkPositionChanged();
+    checkDurationChanged();
+    
+    // 发送统计信息更新
+    PlaybackStats stats = m_playerCore->getStats();
+    emit statsUpdated(stats);
+    
+    // 检查是否有新的视频帧
+    if (m_playerCore->getNextVideoFrame() != nullptr) {
+        emit videoFrameAvailable();
+    }
+    
+    // 检查是否有新的音频帧
+    if (m_playerCore->getNextAudioFrame() != nullptr) {
+        emit audioFrameAvailable();
+    }
+}
+
+void PlayerAdapter::onStateChanged(PlayerState state)
+{
+    // 在主线程中发送信号
+    QMetaObject::invokeMethod(this, [this, state]() {
+        if (state != m_lastState) {
+            m_lastState = state;
+            emit stateChanged(state);
+        }
+    }, Qt::QueuedConnection);
+}
+
+void PlayerAdapter::onMediaInfoChanged(const MediaInfo& info)
+{
+    // 在主线程中发送信号
+    QMetaObject::invokeMethod(this, [this, info]() {
+        emit mediaInfoChanged(info);
+        
+        // 检查时长变化
+        if (info.duration != m_lastDuration) {
+            m_lastDuration = info.duration;
+            emit durationChanged(info.duration);
+        }
+    }, Qt::QueuedConnection);
+}
+
+void PlayerAdapter::onPositionChanged(int64_t position)
+{
+    // 在主线程中发送信号
+    QMetaObject::invokeMethod(this, [this, position]() {
+        if (std::abs(position - m_lastPosition) > 100000) { // 100ms阈值(微秒)
+            m_lastPosition = position;
+            emit positionChanged(position);
+        }
+    }, Qt::QueuedConnection);
+}
+
+void PlayerAdapter::onErrorOccurred(const std::string& error)
+{
+    QString qError = toQString(error);
+    
+    // 在主线程中发送信号
+    QMetaObject::invokeMethod(this, [this, qError]() {
+        emit errorOccurred(qError);
+    }, Qt::QueuedConnection);
+}
+
+void PlayerAdapter::onEndOfFile()
+{
+    // 在主线程中发送信号
+    QMetaObject::invokeMethod(this, [this]() {
+        emit playbackFinished();
+        stopUpdateTimer();
+    }, Qt::QueuedConnection);
+}
+
+void PlayerAdapter::checkPositionChanged()
+{
+    qint64 currentPosition = getCurrentTime();
+    if (std::abs(currentPosition - m_lastPosition) > 100) { // 100ms阈值
+        m_lastPosition = currentPosition;
+        emit positionChanged(currentPosition);
+    }
+}
+
+void PlayerAdapter::checkDurationChanged()
+{
+    qint64 currentDuration = getDuration();
+    if (currentDuration != m_lastDuration) {
+        m_lastDuration = currentDuration;
+        emit durationChanged(currentDuration);
+    }
+}
+
+QString PlayerAdapter::toQString(const std::string& str) const
+{
+    return QString::fromStdString(str);
+}
+
+// PlayerAdapterFactory 实现
+std::unique_ptr<PlayerAdapter> PlayerAdapterFactory::create(QObject* parent)
+{
+    return std::make_unique<PlayerAdapter>(parent);
+}
+
+std::shared_ptr<PlayerAdapter> PlayerAdapterFactory::createShared(QObject* parent)
+{
+    return std::make_shared<PlayerAdapter>(parent);
+}
+
+} // namespace player
+} // namespace av
+
+#include "player_adapter.moc"

+ 195 - 0
AV/code/player/player_adapter.h

@@ -0,0 +1,195 @@
+#pragma once
+
+#include "player_core.h"
+
+#include <QObject>
+#include <QTimer>
+#include <memory>
+
+namespace av {
+namespace player {
+
+/**
+ * @brief 播放器适配器,用于将新的播放器核心与Qt UI进行集成
+ * 
+ * 这个类作为新播放器核心和现有AVPlayer2 UI之间的桥梁,
+ * 提供Qt信号槽机制,便于UI集成
+    */
+class PlayerAdapter : public QObject, public PlayerEventCallback
+{
+    Q_OBJECT
+public:
+    explicit PlayerAdapter(QObject* parent = nullptr);
+    ~PlayerAdapter() override;
+
+    /**
+     * @brief 获取播放器核心实例
+     */
+    PlayerCore* getPlayerCore() const { return m_playerCore.get(); }
+    
+    /**
+     * @brief 设置视频渲染器
+     */
+    void setVideoRenderer(VideoRenderer* renderer);
+    
+    // 播放控制接口
+    Q_INVOKABLE av::ErrorCode openFile(const QString& filename);
+    Q_INVOKABLE av::ErrorCode play();
+    Q_INVOKABLE av::ErrorCode pause();
+    Q_INVOKABLE av::ErrorCode stop();
+    Q_INVOKABLE av::ErrorCode seek(qint64 timestamp);
+    Q_INVOKABLE av::ErrorCode setPlaybackSpeed(double speed);
+    
+    // 状态查询接口
+    Q_INVOKABLE PlayerState getState() const;
+    Q_INVOKABLE qint64 getCurrentTime() const;
+    Q_INVOKABLE qint64 getDuration() const;
+    Q_INVOKABLE double getPlaybackSpeed() const;
+    
+    // 音量控制
+    Q_INVOKABLE void setVolume(double volume);
+    Q_INVOKABLE double getVolume() const;
+    Q_INVOKABLE void setMuted(bool muted);
+    Q_INVOKABLE bool isMuted() const;
+    
+    // 媒体信息
+    Q_INVOKABLE MediaInfo getMediaInfo() const;
+    Q_INVOKABLE PlaybackStats getStats() const;
+    
+    // 帧获取接口(用于视频渲染器)
+    AVFrame* getNextVideoFrame();
+    AVFrame* getNextAudioFrame();
+    void releaseVideoFrame(AVFrame* frame);
+    void releaseAudioFrame(AVFrame* frame);
+    
+    // 启动/停止更新定时器
+    void startUpdateTimer(int intervalMs = 16); // 默认60fps
+    void stopUpdateTimer();
+    
+public slots:
+    /**
+     * @brief 更新播放器状态(由定时器调用)
+     */
+    void updatePlayer();
+    
+signals:
+    /**
+     * @brief 播放器状态改变信号
+     */
+    void stateChanged(PlayerState state);
+    
+    /**
+     * @brief 媒体信息改变信号
+     */
+    void mediaInfoChanged(const MediaInfo& info);
+    
+    /**
+     * @brief 播放位置改变信号
+     */
+    void positionChanged(qint64 position);
+    
+    /**
+     * @brief 播放时长改变信号
+     */
+    void durationChanged(qint64 duration);
+    
+    /**
+     * @brief 音量改变信号
+     */
+    void volumeChanged(double volume);
+    
+    /**
+     * @brief 静音状态改变信号
+     */
+    void mutedChanged(bool muted);
+    
+    /**
+     * @brief 播放速度改变信号
+     */
+    void playbackSpeedChanged(double speed);
+    
+    /**
+     * @brief 错误发生信号
+     */
+    void errorOccurred(const QString& error);
+    
+    /**
+     * @brief 播放结束信号
+     */
+    void playbackFinished();
+    
+    /**
+     * @brief 统计信息更新信号
+     */
+    void statsUpdated(const PlaybackStats& stats);
+    
+    /**
+     * @brief 新视频帧可用信号
+     */
+    void videoFrameAvailable();
+    
+    /**
+     * @brief 新音频帧可用信号
+     */
+    void audioFrameAvailable();
+    
+protected:
+    // PlayerEventCallback 接口实现
+    void onStateChanged(PlayerState state) override;
+    void onMediaInfoChanged(const MediaInfo& info) override;
+    void onPositionChanged(int64_t position) override;
+    void onErrorOccurred(const std::string& error) override;
+    void onEndOfFile() override;
+    
+private:
+    std::unique_ptr<PlayerCore> m_playerCore;
+    QTimer* m_updateTimer;
+    
+    // 缓存的状态信息
+    PlayerState m_lastState = PlayerState::Idle;
+    qint64 m_lastPosition = 0;
+    qint64 m_lastDuration = 0;
+    double m_lastVolume = 1.0;
+    bool m_muted = false;
+    double m_lastPlaybackSpeed = 1.0;
+    
+    /**
+     * @brief 检查并发送位置变化信号
+     */
+    void checkPositionChanged();
+    
+    /**
+     * @brief 检查并发送时长变化信号
+     */
+    void checkDurationChanged();
+    
+    /**
+     * @brief 将std::string转换为QString
+     */
+    QString toQString(const std::string& str) const;
+};
+
+/**
+ * @brief 播放器适配器工厂类
+ */
+class PlayerAdapterFactory {
+public:
+    /**
+     * @brief 创建播放器适配器实例
+     */
+    static std::unique_ptr<PlayerAdapter> create(QObject* parent = nullptr);
+    
+    /**
+     * @brief 创建共享的播放器适配器实例
+     */
+    static std::shared_ptr<PlayerAdapter> createShared(QObject* parent = nullptr);
+};
+
+} // namespace player
+} // namespace av
+
+// 注册Qt元类型
+Q_DECLARE_METATYPE(av::player::PlayerState)
+Q_DECLARE_METATYPE(av::player::MediaInfo)
+Q_DECLARE_METATYPE(av::player::PlaybackStats)
+Q_DECLARE_METATYPE(av::ErrorCode)

+ 753 - 0
AV/code/player/player_core.cpp

@@ -0,0 +1,753 @@
+#include "player_core.h"
+#include "../base/media_common.h"
+#include "../base/logger.h"
+#include "../base/types.h"
+#include "thread_manager.h"
+#include "../codec/codec_video_decoder.h"
+#include "../codec/codec_audio_decoder.h"
+#include <chrono>
+#include <thread>
+
+namespace av {
+namespace player {
+
+PlayerCore::PlayerCore()
+    : m_eventCallback(nullptr)
+    , m_formatContext(nullptr)
+    , m_volume(1.0)
+    , m_playbackSpeed(1.0)
+    , m_seekTarget(-1)
+    , m_seeking(false)
+    , m_lastUpdateTime(0)
+    , m_initialized(false)
+    , m_state(PlayerState::Idle)
+    , m_frameCount(0)
+{
+    av::Logger::instance().info("PlayerCore created");
+    
+    // 初始化FFmpeg
+    if (!initializeFFmpeg()) {
+        av::Logger::instance().error("Failed to initialize FFmpeg");
+        setState(PlayerState::Error);
+        return;
+    }
+    
+    // 创建队列
+    m_packetQueue = av::utils::PacketQueueFactory::createStandardQueue(1000);  // 最多1000个包
+    m_videoFrameQueue = av::utils::FrameQueueFactory::createStandardQueue(30); // 最多30帧
+    m_audioFrameQueue = av::utils::FrameQueueFactory::createStandardQueue(100); // 最多100帧
+    
+    // 创建同步器
+    m_synchronizer = std::make_unique<Synchronizer>();
+    
+    // 创建线程管理器
+    m_threadManager = std::make_unique<ThreadManager>();
+    
+    // 创建解码器
+    m_videoDecoder = std::make_unique<VideoDecoder>();
+    m_audioDecoder = std::make_unique<AudioDecoder>();
+    
+    // 创建音频输出设备
+    m_audioOutput = std::make_unique<AudioOutput>();
+    
+    m_initialized = true;
+    av::Logger::instance().info("PlayerCore initialized successfully");
+}
+
+PlayerCore::~PlayerCore()
+{
+    av::Logger::instance().info("PlayerCore destroying...");
+    stop();
+    cleanup();
+    av::Logger::instance().info("PlayerCore destroyed");
+}
+
+void PlayerCore::setEventCallback(PlayerEventCallback* callback)
+{
+    std::lock_guard<std::mutex> lock(m_mutex);
+    m_eventCallback = callback;
+}
+
+ErrorCode PlayerCore::openFile(const std::string& filename)
+{
+    av::Logger::instance().info("Opening file: " + filename);
+    
+    if (!m_initialized) {
+        av::Logger::instance().error("PlayerCore not initialized");
+        return ErrorCode::NOT_INITIALIZED;
+    }
+    
+    // 如果正在播放,先停止
+    if (m_state != PlayerState::Idle) {
+        stop();
+    }
+    
+    setState(PlayerState::Opening);
+    
+    // 打开媒体文件
+    if (!openMediaFile(filename)) {
+        setState(PlayerState::Error);
+        notifyError("Failed to open media file: " + filename);
+        return ErrorCode::FILE_OPEN_FAILED;
+    }
+    
+    // 设置媒体信息
+    m_mediaInfo.filename = filename;
+    
+    // 设置解码器
+    if (m_mediaInfo.hasVideo && !setupVideoDecoder()) {
+        av::Logger::instance().error("Failed to setup video decoder");
+        setState(PlayerState::Error);
+        return ErrorCode::CODEC_OPEN_FAILED;
+    }
+    
+    if (m_mediaInfo.hasAudio && !setupAudioDecoder()) {
+        av::Logger::instance().error("Failed to setup audio decoder");
+        setState(PlayerState::Error);
+        return ErrorCode::CODEC_OPEN_FAILED;
+    }
+    
+    setState(PlayerState::Stopped);
+    
+    // 通知媒体信息变化
+    if (m_eventCallback) {
+        m_eventCallback->onMediaInfoChanged(m_mediaInfo);
+    }
+    
+    av::Logger::instance().info("File opened successfully: " + filename);
+    return ErrorCode::OK;
+}
+
+ErrorCode PlayerCore::play()
+{
+    av::Logger::instance().info("Starting playback");
+    
+    if (m_state == PlayerState::Playing) {
+        av::Logger::instance().debug("Already playing");
+        return ErrorCode::OK;
+    }
+    
+    if (m_state != PlayerState::Stopped && m_state != PlayerState::Paused) {
+        av::Logger::instance().error("Invalid state for play: " + std::to_string(static_cast<int>(m_state.load())));
+        return ErrorCode::INVALID_STATE;
+    }
+    
+    // 启动音频输出设备
+    if (m_audioOutput && m_mediaInfo.hasAudio) {
+        m_audioOutput->start();
+    }
+    
+    // 启动读取线程
+    if (!startReadThread()) {
+        av::Logger::instance().error("Failed to start read thread");
+        return ErrorCode::THREAD_ERROR;
+    }
+    
+    // 启动解码线程
+    if (!startDecodeThreads()) {
+        av::Logger::instance().error("Failed to start decode threads");
+        return ErrorCode::THREAD_ERROR;
+    }
+    
+    setState(PlayerState::Playing);
+    av::Logger::instance().info("Playback started");
+    return ErrorCode::OK;
+}
+
+ErrorCode PlayerCore::pause()
+{
+    av::Logger::instance().info("Pausing playback");
+    
+    if (m_state != PlayerState::Playing) {
+        av::Logger::instance().debug("Not playing, cannot pause");
+        return ErrorCode::INVALID_STATE;
+    }
+    
+    // 暂停音频输出
+    if (m_audioOutput) {
+        m_audioOutput->pause();
+    }
+    
+    setState(PlayerState::Paused);
+    av::Logger::instance().info("Playback paused");
+    return ErrorCode::OK;
+}
+
+ErrorCode PlayerCore::stop()
+{
+    av::Logger::instance().info("Stopping playback");
+    
+    if (m_state == PlayerState::Idle || m_state == PlayerState::Stopped) {
+        av::Logger::instance().debug("Already stopped");
+        return ErrorCode::OK;
+    }
+    
+    // 停止音频输出
+    if (m_audioOutput) {
+        m_audioOutput->stop();
+    }
+    
+    // 清空视频渲染器
+    if (m_videoRenderer) {
+        m_videoRenderer->clear();
+    }
+    
+    // 停止所有线程
+    stopAllThreads();
+    
+    // 重置解码器
+    resetDecoders();
+    
+    // 清空队列
+    if (m_packetQueue) m_packetQueue->clear();
+    if (m_videoFrameQueue) m_videoFrameQueue->clear();
+    if (m_audioFrameQueue) m_audioFrameQueue->clear();
+    
+    setState(PlayerState::Stopped);
+    av::Logger::instance().info("Playback stopped");
+    return ErrorCode::OK;
+}
+
+ErrorCode PlayerCore::seek(int64_t timestamp)
+{
+    av::Logger::instance().info("Seeking to: " + std::to_string(timestamp));
+    
+    if (m_state == PlayerState::Idle || m_state == PlayerState::Opening) {
+        av::Logger::instance().error("Invalid state for seek");
+        return ErrorCode::INVALID_STATE;
+    }
+    
+    std::lock_guard<std::mutex> lock(m_mutex);
+    m_seekTarget = timestamp;
+    m_seeking = true;
+    
+    // 清空队列
+    if (m_packetQueue) m_packetQueue->clear();
+    if (m_videoFrameQueue) m_videoFrameQueue->clear();
+    if (m_audioFrameQueue) m_audioFrameQueue->clear();
+    
+    setState(PlayerState::Seeking);
+    av::Logger::instance().info("Seek initiated");
+    return ErrorCode::OK;
+}
+
+ErrorCode PlayerCore::setPlaybackSpeed(double speed)
+{
+    if (speed <= 0.0 || speed > 4.0) {
+        av::Logger::instance().error("Invalid playback speed: " + std::to_string(speed));
+        return ErrorCode::INVALID_PARAMETER;
+    }
+    
+    std::lock_guard<std::mutex> lock(m_mutex);
+    m_playbackSpeed = speed;
+    
+    av::Logger::instance().info("Playback speed set to: " + std::to_string(speed));
+    return ErrorCode::OK;
+}
+
+MediaInfo PlayerCore::getMediaInfo() const
+{
+    std::lock_guard<std::mutex> lock(m_mutex);
+    return m_mediaInfo;
+}
+
+PlaybackStats PlayerCore::getStats() const
+{
+    std::lock_guard<std::mutex> lock(m_mutex);
+    return m_stats;
+}
+
+int64_t PlayerCore::getCurrentTime() const
+{
+    std::lock_guard<std::mutex> lock(m_mutex);
+    return m_stats.currentTime;
+}
+
+double PlayerCore::getPlaybackSpeed() const
+{
+    std::lock_guard<std::mutex> lock(m_mutex);
+    return m_playbackSpeed;
+}
+
+void PlayerCore::setVolume(double volume)
+{
+    volume = std::max(0.0, std::min(1.0, volume));
+    std::lock_guard<std::mutex> lock(m_mutex);
+    m_volume = volume;
+    
+    // 同时设置音频输出设备的音量
+    if (m_audioOutput) {
+        m_audioOutput->setVolume(volume);
+    }
+    
+    av::Logger::instance().debug("Volume set to: " + std::to_string(volume));
+}
+
+AVFrame* PlayerCore::getNextVideoFrame()
+{
+    if (m_videoFrameQueue) {
+        return m_videoFrameQueue->dequeueFrame(1);
+    }
+    return nullptr;
+}
+
+AVFrame* PlayerCore::getNextAudioFrame()
+{
+    if (m_audioFrameQueue) {
+        return m_audioFrameQueue->dequeueFrame(1);
+    }
+    return nullptr;
+}
+
+void PlayerCore::releaseVideoFrame(AVFrame* frame)
+{
+    if (frame) {
+        av_frame_free(&frame);
+    }
+}
+
+void PlayerCore::releaseAudioFrame(AVFrame* frame)
+{
+    if (frame) {
+        av_frame_free(&frame);
+    }
+}
+
+void PlayerCore::update()
+{
+    // 更新统计信息
+    updateStats();
+    
+    // 处理跳转
+    if (m_seeking.load()) {
+        // 跳转逻辑
+        // TODO: 实现跳转处理
+        m_seeking = false;
+        setState(PlayerState::Playing);
+    }
+    
+    // 检查是否播放结束
+    if (m_state == PlayerState::Playing) {
+        // TODO: 检查EOF条件
+    }
+}
+
+bool PlayerCore::initializeFFmpeg()
+{
+    static bool initialized = false;
+    if (!initialized) {
+        av_log_set_level(AV_LOG_INFO);
+        initialized = true;
+        av::Logger::instance().info("FFmpeg initialized");
+    }
+    return true;
+}
+
+void PlayerCore::cleanup()
+{
+    stopAllThreads();
+    closeMediaFile();
+    resetDecoders();
+}
+
+bool PlayerCore::openMediaFile(const std::string& filename)
+{
+    // 打开输入文件
+    int ret = avformat_open_input(&m_formatContext, filename.c_str(), nullptr, nullptr);
+    if (ret < 0) {
+        av::Logger::instance().error("Could not open input file: " + filename);
+        return false;
+    }
+    
+    // 查找流信息
+    ret = avformat_find_stream_info(m_formatContext, nullptr);
+    if (ret < 0) {
+        av::Logger::instance().error("Could not find stream information");
+        return false;
+    }
+    
+    // 分析流信息
+    m_mediaInfo.duration = m_formatContext->duration;
+    
+    for (unsigned int i = 0; i < m_formatContext->nb_streams; i++) {
+        AVStream* stream = m_formatContext->streams[i];
+        AVCodecParameters* codecpar = stream->codecpar;
+        
+        if (codecpar->codec_type == AVMEDIA_TYPE_VIDEO && m_mediaInfo.videoStreamIndex == -1) {
+            m_mediaInfo.videoStreamIndex = i;
+            m_mediaInfo.hasVideo = true;
+            m_mediaInfo.width = codecpar->width;
+            m_mediaInfo.height = codecpar->height;
+            m_mediaInfo.fps = av_q2d(stream->avg_frame_rate);
+        }
+        else if (codecpar->codec_type == AVMEDIA_TYPE_AUDIO && m_mediaInfo.audioStreamIndex == -1) {
+            m_mediaInfo.audioStreamIndex = i;
+            m_mediaInfo.hasAudio = true;
+            m_mediaInfo.audioSampleRate = codecpar->sample_rate;
+            m_mediaInfo.audioChannels = codecpar->ch_layout.nb_channels;
+        }
+        else if (codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE && m_mediaInfo.subtitleStreamIndex == -1) {
+            m_mediaInfo.subtitleStreamIndex = i;
+            m_mediaInfo.hasSubtitle = true;
+        }
+    }
+    
+    av::Logger::instance().info("Media file opened successfully");
+    av::Logger::instance().info("Duration: " + std::to_string(m_mediaInfo.duration));
+    av::Logger::instance().info("Has video: " + std::to_string(m_mediaInfo.hasVideo));
+    av::Logger::instance().info("Has audio: " + std::to_string(m_mediaInfo.hasAudio));
+    
+    return true;
+}
+
+void PlayerCore::closeMediaFile()
+{
+    if (m_formatContext) {
+        avformat_close_input(&m_formatContext);
+        m_formatContext = nullptr;
+    av::Logger::instance().info("Media file closed");
+    }
+}
+
+bool PlayerCore::startReadThread()
+{
+    if (!m_threadManager) {
+        m_threadManager = std::make_unique<ThreadManager>();
+    }
+    
+    return m_threadManager->createReadThread(
+        m_formatContext,
+        m_packetQueue.get(),
+        m_mediaInfo.videoStreamIndex,
+        m_mediaInfo.audioStreamIndex
+    );
+}
+
+bool PlayerCore::startDecodeThreads()
+{
+    if (!m_threadManager) {
+        m_threadManager = std::make_unique<ThreadManager>();
+    }
+    
+    bool success = true;
+    
+    if (m_mediaInfo.hasVideo) {
+        AVStream* videoStream = m_formatContext->streams[m_mediaInfo.videoStreamIndex];
+        success &= m_threadManager->createVideoDecodeThread(
+            m_packetQueue.get(),
+            m_videoFrameQueue.get(),
+            m_videoDecoder.get(),
+            m_synchronizer.get(),
+            m_mediaInfo.videoStreamIndex,
+            videoStream->codecpar
+        );
+    }
+    
+    if (m_mediaInfo.hasAudio) {
+        success &= m_threadManager->createAudioDecodeThread(
+            m_packetQueue.get(),
+            m_audioFrameQueue.get(),
+            m_audioDecoder.get(),
+            m_synchronizer.get(),
+            m_mediaInfo.audioStreamIndex
+        );
+    }
+    
+    if (success) {
+        success = m_threadManager->startAll();
+    }
+    
+    return success;
+}
+
+void PlayerCore::stopAllThreads()
+{
+    if (m_threadManager) {
+        m_threadManager->stopAll();
+        m_threadManager.reset();
+    }
+    av::Logger::instance().info("All threads stopped");
+}
+
+void PlayerCore::readThreadFunc()
+{
+    // 读取线程实现
+    while (m_state != PlayerState::Stopped && m_state != PlayerState::Error) {
+        if (m_state == PlayerState::Paused) {
+            std::this_thread::sleep_for(std::chrono::milliseconds(10));
+            continue;
+        }
+        
+        AVPacket* packet = av_packet_alloc();
+        if (!packet) {
+            break;
+        }
+        
+        int ret = av_read_frame(m_formatContext, packet);
+        if (ret < 0) {
+            av_packet_free(&packet);
+            if (ret == AVERROR_EOF) {
+                // 文件结束
+                if (m_eventCallback) {
+                    m_eventCallback->onEndOfFile();
+                }
+            }
+            break;
+        }
+        
+        // 将数据包放入队列
+        if (m_packetQueue) {
+            if (m_packetQueue->enqueue(packet) != av::ErrorCode::OK) {
+                av_packet_free(&packet);
+            }
+        } else {
+            av_packet_free(&packet);
+        }
+    }
+}
+
+void PlayerCore::videoDecodeThreadFunc()
+{
+    // 视频解码线程实现
+    while (m_state != PlayerState::Stopped && m_state != PlayerState::Error) {
+        if (m_state == PlayerState::Paused) {
+            std::this_thread::sleep_for(std::chrono::milliseconds(10));
+            continue;
+        }
+        
+        AVPacket* packet = nullptr;
+        packet = m_packetQueue ? m_packetQueue->dequeuePacket(1) : nullptr;
+        if (packet) {
+            if (m_videoDecoder) {
+                AVPacketPtr packetPtr(packet);
+                std::vector<AVFramePtr> frames;
+                ErrorCode result = m_videoDecoder->decode(packetPtr, frames);
+                if (result == ErrorCode::OK) {
+                    for (auto& frame : frames) {
+                        // 直接渲染到视频渲染器
+                        if (m_videoRenderer && frame) {
+                            m_videoRenderer->renderFrame(frame);
+                        }
+                        
+                        // 同时放入队列供其他用途
+                        if (m_videoFrameQueue) {
+                            m_videoFrameQueue->enqueue(frame.release());
+                        }
+                    }
+                }
+            } else {
+                av_packet_free(&packet);
+            }
+        } else {
+            std::this_thread::sleep_for(std::chrono::milliseconds(1));
+        }
+    }
+}
+
+void PlayerCore::audioDecodeThreadFunc()
+{
+    // 音频解码线程实现
+    while (m_state != PlayerState::Stopped && m_state != PlayerState::Error) {
+        if (m_state == PlayerState::Paused) {
+            std::this_thread::sleep_for(std::chrono::milliseconds(10));
+            continue;
+        }
+        
+        AVPacket* packet = nullptr;
+        packet = m_packetQueue ? m_packetQueue->dequeuePacket(1) : nullptr;
+        if (packet) {
+            if (m_audioDecoder) {
+                AVPacketPtr packetPtr(packet);
+                std::vector<AVFramePtr> frames;
+                ErrorCode result = m_audioDecoder->decode(packetPtr, frames);
+                if (result == ErrorCode::OK) {
+                    for (auto& frame : frames) {
+                        // 直接输出到音频设备
+                        if (m_audioOutput && frame && m_state == PlayerState::Playing) {
+                            m_audioOutput->writeFrame(frame);
+                        }
+                        
+                        // 同时放入队列供其他用途
+                        if (m_audioFrameQueue) {
+                            m_audioFrameQueue->enqueue(frame.release());
+                        }
+                    }
+                }
+            } else {
+                av_packet_free(&packet);
+            }
+        } else {
+            std::this_thread::sleep_for(std::chrono::milliseconds(1));
+        }
+    }
+}
+
+bool PlayerCore::setupVideoDecoder()
+{
+    if (!m_mediaInfo.hasVideo) {
+        return true;
+    }
+    
+    AVStream* videoStream = m_formatContext->streams[m_mediaInfo.videoStreamIndex];
+    const AVCodec* codec = avcodec_find_decoder(videoStream->codecpar->codec_id);
+    
+    if (!codec) {
+        av::Logger::instance().error("Video codec not found");
+        return false;
+    }
+    
+    // 创建视频解码器
+    m_videoDecoder = std::make_unique<VideoDecoder>();
+    
+    av::codec::VideoDecoderParams params;
+    params.codecName = codec->name;
+    params.pixelFormat = static_cast<AVPixelFormat>(videoStream->codecpar->format);
+    params.hardwareAccel = false; // 默认软件解码
+    params.threadCount = 4;
+    
+    ErrorCode result = m_videoDecoder->open(params);
+    if (result != ErrorCode::OK) {
+        av::Logger::instance().error("Failed to open video decoder");
+        return false;
+    }
+    
+    av::Logger::instance().info("Video decoder setup successfully");
+    return true;
+}
+
+bool PlayerCore::setupAudioDecoder()
+{
+    if (!m_mediaInfo.hasAudio) {
+        return true;
+    }
+    
+    AVStream* audioStream = m_formatContext->streams[m_mediaInfo.audioStreamIndex];
+    const AVCodec* codec = avcodec_find_decoder(audioStream->codecpar->codec_id);
+    
+    if (!codec) {
+        av::Logger::instance().error("Audio codec not found");
+        return false;
+    }
+    
+    // 创建音频解码器
+    m_audioDecoder = std::make_unique<AudioDecoder>();
+    
+    av::codec::AudioDecoderParams params;
+    params.codecName = codec->name;
+    params.sampleRate = audioStream->codecpar->sample_rate;
+    params.channels = audioStream->codecpar->ch_layout.nb_channels;
+    params.sampleFormat = static_cast<AVSampleFormat>(audioStream->codecpar->format);
+    params.enableResampling = true;
+    
+    ErrorCode result = m_audioDecoder->open(params);
+    if (result != ErrorCode::OK) {
+        av::Logger::instance().error("Failed to open audio decoder");
+        return false;
+    }
+    
+    // 初始化音频输出设备
+    if (m_audioOutput) {
+        bool audioInitResult = m_audioOutput->initialize(
+            audioStream->codecpar->sample_rate,
+            audioStream->codecpar->ch_layout.nb_channels,
+            static_cast<AVSampleFormat>(audioStream->codecpar->format)
+        );
+        if (!audioInitResult) {
+            av::Logger::instance().error("Failed to initialize audio output");
+            return false;
+        }
+    }
+    
+    av::Logger::instance().info("Audio decoder setup successfully");
+    return true;
+}
+
+void PlayerCore::resetDecoders()
+{
+    if (m_videoDecoder) {
+        m_videoDecoder->close();
+        m_videoDecoder.reset();
+    }
+    
+    if (m_audioDecoder) {
+        m_audioDecoder->close();
+        m_audioDecoder.reset();
+    }
+    
+    av::Logger::instance().info("Decoders reset");
+}
+
+void PlayerCore::updateSynchronization()
+{
+    // TODO: 实现同步逻辑
+}
+
+int64_t PlayerCore::getCurrentPlayTime()
+{
+    // TODO: 实现当前播放时间计算
+    return 0;
+}
+
+void PlayerCore::setState(PlayerState newState)
+{
+    PlayerState oldState = m_state.exchange(newState);
+    if (oldState != newState) {
+        av::Logger::instance().debug("State changed: " + std::to_string(static_cast<int>(oldState)) + 
+                 " -> " + std::to_string(static_cast<int>(newState)));
+        notifyStateChanged(newState);
+    }
+}
+
+void PlayerCore::updateStats()
+{
+    std::lock_guard<std::mutex> lock(m_mutex);
+    
+    // 更新队列统计
+    if (m_packetQueue) {
+        m_stats.queuedPackets = m_packetQueue->size();
+    }
+    if (m_videoFrameQueue) {
+        m_stats.queuedVideoFrames = m_videoFrameQueue->size();
+    }
+    if (m_audioFrameQueue) {
+        m_stats.queuedAudioFrames = m_audioFrameQueue->size();
+    }
+    
+    m_stats.playbackSpeed = m_playbackSpeed;
+    m_stats.currentTime = getCurrentPlayTime();
+}
+
+void PlayerCore::notifyStateChanged(PlayerState newState)
+{
+    if (m_eventCallback) {
+        m_eventCallback->onStateChanged(newState);
+    }
+}
+
+void PlayerCore::notifyError(const std::string& error)
+{
+    if (m_eventCallback) {
+        m_eventCallback->onErrorOccurred(error);
+    }
+}
+
+void PlayerCore::setVideoRenderer(VideoRenderer* renderer)
+{
+    std::lock_guard<std::mutex> lock(m_mutex);
+    m_videoRenderer = renderer;
+    
+    // 如果已有媒体信息且视频渲染器可用,初始化渲染器
+    if (m_videoRenderer && m_mediaInfo.hasVideo) {
+        AVStream* videoStream = m_formatContext->streams[m_mediaInfo.videoStreamIndex];
+        m_videoRenderer->initialize(
+            videoStream->codecpar->width,
+            videoStream->codecpar->height,
+            static_cast<AVPixelFormat>(videoStream->codecpar->format)
+        );
+    }
+    
+    av::Logger::instance().info("Video renderer set");
+}
+
+} // namespace player
+} // namespace av

+ 227 - 0
AV/code/player/player_core.h

@@ -0,0 +1,227 @@
+#ifndef AV_PLAYER_CORE_H
+#define AV_PLAYER_CORE_H
+
+#pragma once
+
+#include "../base/logger.h"
+#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_synchronizer.h"
+#include "thread_manager.h"
+#include "audio_output.h"
+#include "video_renderer.h"
+
+#include <memory>
+#include <atomic>
+#include <mutex>
+#include <string>
+#include <functional>
+
+extern "C" {
+#include <libavformat/avformat.h>
+#include <libavcodec/avcodec.h>
+#include <libavutil/avutil.h>
+}
+
+namespace av {
+namespace player {
+
+using VideoDecoder = av::codec::VideoDecoder;
+using AudioDecoder = av::codec::AudioDecoder;
+
+using Synchronizer = av::utils::Synchronizer;
+
+/**
+ * 播放器状态枚举
+ */
+enum class PlayerState {
+    Idle,           // 空闲
+    Opening,        // 正在打开文件
+    Playing,        // 播放中
+    Paused,         // 暂停
+    Seeking,        // 跳转中
+    Stopped,        // 已停止
+    Error           // 错误状态
+};
+
+/**
+ * 媒体信息结构
+ */
+struct MediaInfo {
+    std::string filename;
+    int64_t duration = 0;           // 总时长(微秒)
+    int width = 0;
+    int height = 0;
+    double fps = 0.0;
+    int audioSampleRate = 0;
+    int audioChannels = 0;
+    bool hasVideo = false;
+    bool hasAudio = false;
+    bool hasSubtitle = false;
+    
+    // 流索引
+    int videoStreamIndex = -1;
+    int audioStreamIndex = -1;
+    int subtitleStreamIndex = -1;
+};
+
+/**
+ * 播放统计信息
+ */
+struct PlaybackStats {
+    int64_t currentTime = 0;        // 当前播放时间(微秒)
+    int64_t totalFrames = 0;        // 总帧数
+    int64_t droppedFrames = 0;      // 丢帧数
+    double playbackSpeed = 1.0;     // 播放速度
+    int queuedVideoFrames = 0;      // 视频帧队列大小
+    int queuedAudioFrames = 0;      // 音频帧队列大小
+    int queuedPackets = 0;          // 数据包队列大小
+};
+
+/**
+ * 播放器事件回调接口
+ */
+class PlayerEventCallback {
+public:
+    virtual ~PlayerEventCallback() = default;
+    
+    virtual void onStateChanged(PlayerState newState) = 0;
+    virtual void onMediaInfoChanged(const MediaInfo& info) = 0;
+    virtual void onPositionChanged(int64_t position) = 0;  // 微秒
+    virtual void onErrorOccurred(const std::string& error) = 0;
+    virtual void onEndOfFile() = 0;
+};
+
+/**
+ * 播放器核心类 - 使用新的AV核心库
+ * 负责媒体文件的解码和播放控制,但不涉及UI渲染
+ * 这是一个纯C++实现,不依赖Qt
+ */
+class PlayerCore
+{
+public:
+    explicit PlayerCore();
+    ~PlayerCore();
+
+    // 事件回调设置
+    void setEventCallback(PlayerEventCallback* callback);
+    
+    // 播放控制接口
+    ErrorCode openFile(const std::string& filename);
+    ErrorCode play();
+    ErrorCode pause();
+    ErrorCode stop();
+    ErrorCode seek(int64_t timestamp);  // 微秒
+    ErrorCode setPlaybackSpeed(double speed);
+    
+    // 状态查询
+    PlayerState getState() const { return m_state.load(); }
+    MediaInfo getMediaInfo() const;
+    PlaybackStats getStats() const;
+    int64_t getCurrentTime() const;
+    double getPlaybackSpeed() const;
+    
+    // 音量控制
+    void setVolume(double volume);  // 0.0 - 1.0
+    double getVolume() const { return m_volume; }
+    
+    // 输出设备设置
+    void setVideoRenderer(VideoRenderer* renderer);
+    VideoRenderer* getVideoRenderer() const { return m_videoRenderer; }
+    
+    // 帧获取接口(供UI渲染使用)
+    AVFrame* getNextVideoFrame();   // 获取下一个视频帧
+    AVFrame* getNextAudioFrame();   // 获取下一个音频帧
+    void releaseVideoFrame(AVFrame* frame);  // 释放视频帧
+    void releaseAudioFrame(AVFrame* frame);  // 释放音频帧
+    
+    // 线程安全的更新接口
+    void update();  // 定期调用以更新播放状态
+
+private:
+    // 初始化和清理
+    bool initializeFFmpeg();
+    void cleanup();
+    bool openMediaFile(const std::string& filename);
+    void closeMediaFile();
+    
+    // 线程管理
+    bool startReadThread();
+    bool startDecodeThreads();
+    void stopAllThreads();
+    
+    // 解码器管理
+    bool setupVideoDecoder();
+    bool setupAudioDecoder();
+    void resetDecoders();
+    
+    // 同步控制
+    void updateSynchronization();
+    int64_t getCurrentPlayTime();
+    
+    // 状态管理
+    void setState(PlayerState newState);
+    void updateStats();
+    void notifyStateChanged(PlayerState newState);
+    void notifyError(const std::string& error);
+    
+    // 线程函数
+    void readThreadFunc();
+    void videoDecodeThreadFunc();
+    void audioDecodeThreadFunc();
+    
+private:
+    // 状态变量
+    std::atomic<PlayerState> m_state{PlayerState::Idle};
+    mutable std::mutex m_mutex;
+    
+    // 事件回调
+    PlayerEventCallback* m_eventCallback = nullptr;
+    
+    // 媒体信息
+    MediaInfo m_mediaInfo;
+    PlaybackStats m_stats;
+    
+    // FFmpeg相关
+    AVFormatContext* m_formatContext = nullptr;
+    
+    // 解码器
+    std::unique_ptr<VideoDecoder> m_videoDecoder;
+    std::unique_ptr<AudioDecoder> m_audioDecoder;
+    
+    // 队列管理
+    std::unique_ptr<av::utils::PacketQueue> m_packetQueue;
+    std::unique_ptr<av::utils::FrameQueue> m_videoFrameQueue;
+    std::unique_ptr<av::utils::FrameQueue> m_audioFrameQueue;
+    
+    // 同步器
+    std::unique_ptr<Synchronizer> m_synchronizer;
+    
+    // 线程管理器
+    std::unique_ptr<ThreadManager> m_threadManager;
+    
+    // 输出设备
+    std::unique_ptr<AudioOutput> m_audioOutput;
+    VideoRenderer* m_videoRenderer = nullptr;  // 外部提供的视频渲染器
+    
+    // 播放控制
+    double m_volume = 1.0;
+    double m_playbackSpeed = 1.0;
+    int64_t m_seekTarget = -1;
+    std::atomic<bool> m_seeking{false};
+    
+    // 性能统计
+    int64_t m_lastUpdateTime = 0;
+    int64_t m_frameCount = 0;
+    
+    // 初始化标志
+    bool m_initialized = false;
+};
+
+} // namespace player
+} // namespace av
+
+#endif // AV_PLAYER_CORE_H

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

@@ -0,0 +1,590 @@
+#include "thread_manager.h"
+
+#include "../utils/utils_packet_queue.h"
+#include "../utils/utils_frame_queue.h"
+#include "thread_manager.h"
+#include "../base/logger.h"
+#include "../base/media_common.h"
+#include "../codec/codec_video_decoder.h"
+#include "../codec/codec_audio_decoder.h"
+#include "../utils/utils_packet_queue.h"
+#include "../utils/utils_frame_queue.h"
+#include "../utils/utils_synchronizer.h"
+#include <thread>
+#include <chrono>
+#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::OK) {
+            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::Synchronizer* synchronizer,
+                                      int streamIndex,
+                                      AVCodecParameters* codecParams)
+    : ThreadBase("VideoDecodeThread")
+    , m_packetQueue(packetQueue)
+    , m_frameQueue(frameQueue)
+    , m_decoder(decoder)
+    , m_synchronizer(synchronizer)
+    , m_streamIndex(streamIndex)
+    , m_bsfContext(nullptr)
+{
+    if (codecParams) {
+        initBitStreamFilter(codecParams);
+    }
+}
+
+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::OK) {
+        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) {
+            // 需要获取时间基,这里暂时使用默认值
+            double pts = frame->pts * 0.000040; // 临时值,需要从解码器获取正确的时间基
+            m_synchronizer->setVideoClock(pts);
+        }
+        
+        // 添加到帧队列
+        if (m_frameQueue->enqueue(frame.release()) != av::ErrorCode::OK) {
+            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::Synchronizer* synchronizer,
+                                      int streamIndex)
+    : ThreadBase("AudioDecodeThread")
+    , m_packetQueue(packetQueue)
+    , m_frameQueue(frameQueue)
+    , m_decoder(decoder)
+    , m_synchronizer(synchronizer)
+    , m_streamIndex(streamIndex)
+{
+}
+
+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::OK) {
+        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) {
+            // 需要获取时间基,这里暂时使用默认值
+            double pts = frame->pts * 0.000023; // 临时值,需要从解码器获取正确的时间基
+            m_synchronizer->setAudioClock(pts);
+        }
+        
+        // 添加到帧队列
+        if (m_frameQueue->enqueue(frame.release()) != av::ErrorCode::OK) {
+            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::Synchronizer* synchronizer,
+                                            int streamIndex,
+                                            AVCodecParameters* codecParams)
+{
+    if (m_videoDecodeThread) {
+        av::Logger::instance().warning("VideoDecodeThread already exists");
+        return false;
+    }
+    
+    m_videoDecodeThread = std::make_unique<VideoDecodeThread>(packetQueue, frameQueue,
+                                                              decoder, synchronizer, streamIndex, codecParams);
+    av::Logger::instance().info("VideoDecodeThread created");
+    return true;
+}
+
+bool ThreadManager::createAudioDecodeThread(av::utils::PacketQueue* packetQueue,
+                                            av::utils::FrameQueue* frameQueue,
+                                            AudioDecoder* decoder,
+                                            av::utils::Synchronizer* synchronizer,
+                                            int streamIndex)
+{
+    if (m_audioDecodeThread) {
+        av::Logger::instance().warning("AudioDecodeThread already exists");
+        return false;
+    }
+    
+    m_audioDecodeThread = std::make_unique<AudioDecodeThread>(packetQueue, frameQueue,
+                                                              decoder, synchronizer, streamIndex);
+    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

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

@@ -0,0 +1,295 @@
+#pragma once
+
+#include <thread>
+#include <atomic>
+#include <memory>
+#include <functional>
+#include <mutex>
+
+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 Synchronizer;
+}
+
+namespace utils {
+class PacketQueue;
+class FrameQueue;
+}
+
+namespace player {
+
+// 使用codec命名空间中的解码器
+using VideoDecoder = av::codec::VideoDecoder;
+using AudioDecoder = av::codec::AudioDecoder;
+
+/**
+ * @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::Synchronizer* synchronizer,
+                       int streamIndex,
+                       AVCodecParameters* codecParams = nullptr);
+    
+    ~VideoDecodeThread() override;
+    
+protected:
+    void run() override;
+    
+private:
+    av::utils::PacketQueue* m_packetQueue;
+    av::utils::FrameQueue* m_frameQueue;
+    VideoDecoder* m_decoder;
+    av::utils::Synchronizer* m_synchronizer;
+    int m_streamIndex;
+    AVBSFContext* m_bsfContext;
+    
+    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::Synchronizer* synchronizer,
+                       int streamIndex);
+    
+    ~AudioDecodeThread() override = default;
+    
+protected:
+    void run() override;
+    
+private:
+    av::utils::PacketQueue* m_packetQueue;
+    av::utils::FrameQueue* m_frameQueue;
+    AudioDecoder* m_decoder;
+    av::utils::Synchronizer* m_synchronizer;
+    int m_streamIndex;
+    
+    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::Synchronizer* synchronizer,
+                                  int streamIndex,
+                                  AVCodecParameters* codecParams = nullptr);
+    
+    /**
+     * @brief 创建音频解码线程
+     */
+    bool createAudioDecodeThread(av::utils::PacketQueue* packetQueue,
+                                  av::utils::FrameQueue* frameQueue,
+                                  AudioDecoder* decoder,
+                                  av::utils::Synchronizer* synchronizer,
+                                  int streamIndex);
+    
+    /**
+     * @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

+ 299 - 0
AV/code/player/video_renderer.cpp

@@ -0,0 +1,299 @@
+#include "video_renderer.h"
+#include "../base/logger.h"
+#include <QPainter>
+#include <QResizeEvent>
+#include <QApplication>
+#include <QDebug>
+#include <algorithm>
+
+extern "C" {
+#include <libavutil/imgutils.h>
+#include <libswscale/swscale.h>
+}
+
+namespace av {
+namespace player {
+
+VideoRenderer::VideoRenderer(QWidget* parent)
+    : QLabel(parent)
+    , m_videoWidth(0)
+    , m_videoHeight(0)
+    , m_inputFormat(AV_PIX_FMT_NONE)
+    , m_swsContext(nullptr)
+    , m_rgbBuffer(nullptr)
+    , m_rgbBufferSize(0)
+    , m_backgroundColor(Qt::black)
+    , m_keepAspectRatio(true)
+    , m_initialized(false)
+    , m_updateTimer(new QTimer(this))
+{
+    // 设置基本属性
+    setAlignment(Qt::AlignCenter);
+    setStyleSheet("background-color: black;");
+    setMinimumSize(320, 240);
+    
+    // 连接更新定时器
+    connect(m_updateTimer, &QTimer::timeout, this, &VideoRenderer::updateDisplay);
+    m_updateTimer->setSingleShot(true);
+}
+
+VideoRenderer::~VideoRenderer()
+{
+    cleanupConverter();
+}
+
+bool VideoRenderer::initialize(int width, int height, AVPixelFormat pixelFormat)
+{
+    QMutexLocker locker(&m_mutex);
+    
+    if (m_initialized) {
+        av::Logger::instance().warning("Video renderer already initialized");
+        return true;
+    }
+    
+    if (width <= 0 || height <= 0) {
+        av::Logger::instance().error("Invalid video dimensions");
+        return false;
+    }
+    
+    m_videoWidth = width;
+    m_videoHeight = height;
+    m_inputFormat = pixelFormat;
+    
+    // 初始化图像转换器
+    if (!initConverter()) {
+        av::Logger::instance().error("Failed to initialize video converter");
+        return false;
+    }
+    
+    // 设置控件大小提示
+    setMinimumSize(m_videoWidth / 4, m_videoHeight / 4);
+    
+    m_initialized = true;
+    av::Logger::instance().info(
+        QString("Video renderer initialized: %1x%2").arg(width).arg(height).toStdString());
+
+    return true;
+}
+
+bool VideoRenderer::renderFrame(const AVFramePtr& frame)
+{
+    if (!frame || !m_initialized) {
+        return false;
+    }
+    
+    // 转换帧为QImage
+    QImage image = convertFrameToImage(frame);
+    if (image.isNull()) {
+        return false;
+    }
+    
+    // 缩放图像
+    QPixmap pixmap = scaleImage(image);
+    
+    {
+        QMutexLocker locker(&m_mutex);
+        m_currentPixmap = pixmap;
+    }
+    
+    // 触发更新显示
+    if (!m_updateTimer->isActive()) {
+        m_updateTimer->start(16); // �?0fps
+    }
+    
+    return true;
+}
+
+void VideoRenderer::clear()
+{
+    QMutexLocker locker(&m_mutex);
+    m_currentPixmap = QPixmap();
+    QLabel::clear();
+    update();
+}
+
+void VideoRenderer::setKeepAspectRatio(bool keepAspectRatio)
+{
+    if (m_keepAspectRatio != keepAspectRatio) {
+        m_keepAspectRatio = keepAspectRatio;
+        update();
+    }
+}
+
+bool VideoRenderer::getKeepAspectRatio() const
+{
+    return m_keepAspectRatio;
+}
+
+void VideoRenderer::setBackgroundColor(const QColor& color)
+{
+    if (m_backgroundColor != color) {
+        m_backgroundColor = color;
+        setStyleSheet(QString("background-color: %1;").arg(color.name()));
+        update();
+    }
+}
+
+QSize VideoRenderer::getVideoSize() const
+{
+    return QSize(m_videoWidth, m_videoHeight);
+}
+
+QSize VideoRenderer::getDisplaySize() const
+{
+    return size();
+}
+
+bool VideoRenderer::isInitialized() const
+{
+    return m_initialized;
+}
+
+void VideoRenderer::paintEvent(QPaintEvent* event)
+{
+    QPainter painter(this);
+    painter.fillRect(rect(), m_backgroundColor);
+    
+    QMutexLocker locker(&m_mutex);
+    if (!m_currentPixmap.isNull()) {
+        QRect displayRect = calculateDisplayRect();
+        painter.drawPixmap(displayRect, m_currentPixmap);
+    }
+    
+    QLabel::paintEvent(event);
+}
+
+void VideoRenderer::resizeEvent(QResizeEvent* event)
+{
+    QLabel::resizeEvent(event);
+    update();
+}
+
+void VideoRenderer::updateDisplay()
+{
+    update();
+}
+
+bool VideoRenderer::initConverter()
+{
+    // 创建图像转换上下文
+    m_swsContext = sws_getContext(
+        m_videoWidth, m_videoHeight, m_inputFormat,
+        m_videoWidth, m_videoHeight, AV_PIX_FMT_RGB24,
+        SWS_BILINEAR, nullptr, nullptr, nullptr
+    );
+    
+    if (!m_swsContext) {
+        av::Logger::instance().error("Failed to create image converter context");
+        return false;
+    }
+    
+    // 分配RGB缓冲区
+    m_rgbBufferSize = av_image_get_buffer_size(AV_PIX_FMT_RGB24, m_videoWidth, m_videoHeight, 1);
+    m_rgbBuffer = static_cast<uint8_t*>(av_malloc(m_rgbBufferSize));
+    
+    if (!m_rgbBuffer) {
+        av::Logger::instance().error("Failed to allocate RGB buffer");
+        sws_freeContext(m_swsContext);
+        m_swsContext = nullptr;
+        return false;
+    }
+    
+    av::Logger::instance().info("Video converter initialized successfully");
+    return true;
+}
+
+void VideoRenderer::cleanupConverter()
+{
+    if (m_swsContext) {
+        sws_freeContext(m_swsContext);
+        m_swsContext = nullptr;
+    }
+    
+    if (m_rgbBuffer) {
+        av_free(m_rgbBuffer);
+        m_rgbBuffer = nullptr;
+        m_rgbBufferSize = 0;
+    }
+}
+
+QImage VideoRenderer::convertFrameToImage(const AVFramePtr& frame)
+{
+    if (!frame || !m_swsContext || !m_rgbBuffer) {
+        return QImage();
+    }
+    
+    // 设置输出缓冲区
+    uint8_t* dstData[4] = { m_rgbBuffer, nullptr, nullptr, nullptr };
+    int dstLinesize[4] = { m_videoWidth * 3, 0, 0, 0 };
+    
+    // 执行图像转换
+    int result = sws_scale(
+        m_swsContext,
+        frame->data, frame->linesize,
+        0, m_videoHeight,
+        dstData, dstLinesize
+    );
+    
+    if (result != m_videoHeight) {
+        av::Logger::instance().error("Image conversion failed");
+        return QImage();
+    }
+    
+    // 创建QImage
+    QImage image(m_rgbBuffer, m_videoWidth, m_videoHeight, QImage::Format_RGB888);
+    return image.copy(); // 复制数据,避免缓冲区被覆盖
+}
+
+QRect VideoRenderer::calculateDisplayRect() const
+{
+    if (m_videoWidth <= 0 || m_videoHeight <= 0) {
+        return rect();
+    }
+    
+    QSize widgetSize = size();
+    QSize videoSize(m_videoWidth, m_videoHeight);
+    
+    if (!m_keepAspectRatio) {
+        return rect();
+    }
+    
+    // 计算保持宽高比的显示矩形
+    QSize scaledSize = videoSize.scaled(widgetSize, Qt::KeepAspectRatio);
+    
+    int x = (widgetSize.width() - scaledSize.width()) / 2;
+    int y = (widgetSize.height() - scaledSize.height()) / 2;
+    
+    return QRect(x, y, scaledSize.width(), scaledSize.height());
+}
+
+QPixmap VideoRenderer::scaleImage(const QImage& image) const
+{
+    if (image.isNull()) {
+        return QPixmap();
+    }
+    
+    QSize displaySize = size();
+    if (displaySize.isEmpty()) {
+        return QPixmap::fromImage(image);
+    }
+    
+    QSize targetSize;
+    if (m_keepAspectRatio) {
+        targetSize = image.size().scaled(displaySize, Qt::KeepAspectRatio);
+    } else {
+        targetSize = displaySize;
+    }
+    
+    if (targetSize == image.size()) {
+        return QPixmap::fromImage(image);
+    }
+    
+    QImage scaledImage = image.scaled(targetSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+    return QPixmap::fromImage(scaledImage);
+}
+
+} // namespace player
+} // namespace av
+
+#include "video_renderer.moc"

+ 150 - 0
AV/code/player/video_renderer.h

@@ -0,0 +1,150 @@
+#ifndef AV_PLAYER_VIDEO_RENDERER_H
+#define AV_PLAYER_VIDEO_RENDERER_H
+
+#include <QWidget>
+#include <QLabel>
+#include <QPixmap>
+#include <QMutex>
+#include <QTimer>
+#include <memory>
+#include <atomic>
+
+extern "C" {
+#include <libavutil/frame.h>
+#include <libavutil/pixfmt.h>
+#include <libswscale/swscale.h>
+}
+
+#include "../base/media_common.h"
+
+namespace av {
+namespace player {
+
+/**
+ * 视频渲染器类
+/**
+ * 负责将解码后的视频帧渲染到Qt控件上
+ */
+class VideoRenderer : public QLabel
+{
+    Q_OBJECT
+
+public:
+    explicit VideoRenderer(QWidget* parent = nullptr);
+    ~VideoRenderer();
+
+    /**
+     * 初始化视频渲染器
+     * @param width 视频宽度
+     * @param height 视频高度
+     * @param pixelFormat 像素格式
+     * @return 是否成功
+     */
+    bool initialize(int width, int height, AVPixelFormat pixelFormat);
+
+    /**
+     * 渲染视频帧
+     * @param frame 视频帧
+     * @return 是否成功
+     */
+    bool renderFrame(const AVFramePtr& frame);
+
+    /**
+     * 清空显示
+     */
+    void clear();
+
+    /**
+     * 设置保持宽高比
+     * @param keepAspectRatio 是否保持宽高比
+     */
+    void setKeepAspectRatio(bool keepAspectRatio);
+
+    /**
+     * 获取是否保持宽高比
+     */
+    bool getKeepAspectRatio() const;
+
+    /**
+     * 设置背景颜色
+     * @param color 背景颜色
+     */
+    void setBackgroundColor(const QColor& color);
+
+    /**
+     * 获取视频尺寸
+     */
+    QSize getVideoSize() const;
+
+    /**
+     * 获取显示尺寸
+     */
+    QSize getDisplaySize() const;
+
+    /**
+     * 是否已初始化
+     */
+    bool isInitialized() const;
+
+protected:
+    void paintEvent(QPaintEvent* event) override;
+    void resizeEvent(QResizeEvent* event) override;
+
+private slots:
+    void updateDisplay();
+
+private:
+    /**
+     * 初始化图像转换器
+     */
+    bool initConverter();
+
+    /**
+     * 清理图像转换器
+     */
+    void cleanupConverter();
+
+    /**
+     * 转换视频帧为QImage
+     */
+    QImage convertFrameToImage(const AVFramePtr& frame);
+
+    /**
+     * 计算显示矩形
+     */
+    QRect calculateDisplayRect() const;
+
+    /**
+     * 缩放图像
+     */
+    QPixmap scaleImage(const QImage& image) const;
+
+private:
+    // 视频参数
+    int m_videoWidth;
+    int m_videoHeight;
+    AVPixelFormat m_inputFormat;
+    
+    // 图像转换器
+    SwsContext* m_swsContext;
+    uint8_t* m_rgbBuffer;
+    int m_rgbBufferSize;
+    
+    // 显示相关
+    QPixmap m_currentPixmap;
+    QColor m_backgroundColor;
+    bool m_keepAspectRatio;
+    
+    // 状态
+    std::atomic<bool> m_initialized;
+    
+    // 更新定时器
+    QTimer* m_updateTimer;
+    
+    mutable QMutex m_mutex;
+};
+
+} // namespace player
+} // namespace av
+
+#endif // AV_PLAYER_VIDEO_RENDERER_H

+ 0 - 130
AV/codec_test_log.txt

@@ -1,130 +0,0 @@
-2025-07-26 21:45:04.463 [INFO] AV Logger initialized
-2025-07-26 21:45:04.463 [INFO] FFmpeg initialized successfully
-2025-07-26 21:45:04.463 [INFO] 1. 测试视频编码器支持...
-2025-07-26 21:45:04.463 [INFO] 查找可用的视频编码器...
-2025-07-26 21:45:04.464 [INFO] 找到硬件编码器: h264_nvenc
-2025-07-26 21:45:04.464 [INFO] 找到硬件编码器: h264_qsv
-2025-07-26 21:45:04.464 [INFO] 找到硬件编码器: h264_amf
-2025-07-26 21:45:04.464 [INFO] 找到软件编码器: libx264
-2025-07-26 21:45:04.464 [INFO] 找到软件编码器: libx265
-2025-07-26 21:45:04.464 [INFO] 总共找到 5 个可用的视频编码器
-2025-07-26 21:45:04.464 [INFO] 支持的视频编码器数量: 5
-2025-07-26 21:45:04.464 [INFO]   - h264_nvenc (硬件: 是)
-2025-07-26 21:45:04.467 [INFO]   - h264_qsv (硬件: 是)
-2025-07-26 21:45:04.467 [INFO]   - h264_amf (硬件: 是)
-2025-07-26 21:45:04.467 [INFO]   - libx264 (硬件: 否)
-2025-07-26 21:45:04.467 [INFO]   - libx265 (硬件: 否)
-2025-07-26 21:45:04.467 [INFO] 推荐的视频编码器: h264_nvenc
-2025-07-26 21:45:04.467 [INFO] 2. 测试音频编码器支持...
-2025-07-26 21:45:04.467 [INFO] 查找可用的音频编码器...
-2025-07-26 21:45:04.467 [INFO] 找到音频编码器: aac
-2025-07-26 21:45:04.467 [INFO] 找到音频编码器: libmp3lame
-2025-07-26 21:45:04.467 [INFO] 找到音频编码器: opus
-2025-07-26 21:45:04.468 [INFO] 找到音频编码器: libopus
-2025-07-26 21:45:04.468 [INFO] 找到音频编码器: vorbis
-2025-07-26 21:45:04.468 [INFO] 找到音频编码器: libvorbis
-2025-07-26 21:45:04.468 [INFO] 找到音频编码器: flac
-2025-07-26 21:45:04.468 [INFO] 找到音频编码器: pcm_s16le
-2025-07-26 21:45:04.468 [INFO] 找到音频编码器: pcm_s24le
-2025-07-26 21:45:04.468 [INFO] 找到音频编码器: pcm_s32le
-2025-07-26 21:45:04.468 [INFO] 总共找到 10 个可用的音频编码器
-2025-07-26 21:45:04.468 [INFO] 支持的音频编码器数量: 10
-2025-07-26 21:45:04.468 [INFO]   - aac
-2025-07-26 21:45:04.469 [INFO]   - libmp3lame
-2025-07-26 21:45:04.469 [INFO]   - opus
-2025-07-26 21:45:04.469 [INFO]   - libopus
-2025-07-26 21:45:04.469 [INFO]   - vorbis
-2025-07-26 21:45:04.469 [INFO]   - libvorbis
-2025-07-26 21:45:04.469 [INFO]   - flac
-2025-07-26 21:45:04.469 [INFO]   - pcm_s16le
-2025-07-26 21:45:04.469 [INFO]   - pcm_s24le
-2025-07-26 21:45:04.469 [INFO]   - pcm_s32le
-2025-07-26 21:45:04.469 [INFO] 推荐的音频编码器: aac
-2025-07-26 21:45:04.469 [INFO] 3. 测试视频编码器创建...
-2025-07-26 21:45:04.470 [DEBUG] 创建编码编解码器, 媒体类型: 2
-2025-07-26 21:45:04.470 [DEBUG] 创建视频编码器
-2025-07-26 21:45:04.470 [INFO] 视频编码器创建成功
-2025-07-26 21:45:04.470 [INFO] 开始设置硬件加速: 编码器=h264_nvenc, 设备类型=2
-2025-07-26 21:45:04.470 [INFO] 检查CUDA设备可用性...
-2025-07-26 21:45:04.470 [INFO] 创建硬件设备上下文...
-2025-07-26 21:45:04.574 [INFO] 硬件设备上下文创建成功: h264_nvenc
-2025-07-26 21:45:04.574 [INFO] 设置硬件帧上下文: 1280x720, 硬件格式: 117, 软件格式: 23, 池大小: 8
-2025-07-26 21:45:04.575 [INFO] 硬件帧上下文初始化成功
-2025-07-26 21:45:04.575 [INFO] 设置硬件编码器像素格式: 117 (cuda)
-2025-07-26 21:45:04.575 [INFO] 设置NVENC编码器参数...
-2025-07-26 21:45:04.576 [INFO] 设置preset=medium: 成功
-2025-07-26 21:45:04.576 [INFO] 设置profile=main: 成功
-2025-07-26 21:45:04.576 [INFO] 设置rc=vbr: 成功
-2025-07-26 21:45:04.576 [INFO] 设置surfaces=16: 成功
-2025-07-26 21:45:04.576 [INFO] 设置delay=0: 成功
-2025-07-26 21:45:04.576 [INFO] 启用低延迟模式
-2025-07-26 21:45:04.576 [INFO] 设置preset=fast: 成功
-2025-07-26 21:45:04.576 [INFO] 设置tune=ll: 成功
-2025-07-26 21:45:04.576 [INFO] 准备打开编码器: h264_nvenc
-2025-07-26 21:45:04.576 [INFO] 编码器参数: 1280x720, 比特率: 2000000, 帧率: 30, 像素格式: 117
-2025-07-26 21:45:04.576 [INFO] 硬件编码器状态: 设备上下文=已创建, 帧上下文=已设置
-2025-07-26 21:45:04.622 [INFO] 编码器打开成功: h264_nvenc
-2025-07-26 21:45:04.622 [DEBUG] 编解码器状态变更: 0 -> 1
-2025-07-26 21:45:04.622 [INFO] 视频编码器已打开: h264_nvenc (1280x720 @ 30fps)
-2025-07-26 21:45:04.622 [INFO] 视频编码器打开成功
-2025-07-26 21:45:04.622 [INFO] 编码器状态: 1
-2025-07-26 21:45:04.622 [INFO] 是否已打开: 是
-2025-07-26 21:45:04.650 [DEBUG] 编解码器状态变更: 1 -> 4
-2025-07-26 21:45:04.650 [DEBUG] 视频编码器已关闭
-2025-07-26 21:45:04.651 [INFO] 视频编码器已关闭
-2025-07-26 21:45:04.651 [DEBUG] 视频编码器已销毁
-2025-07-26 21:45:04.651 [DEBUG] 编解码器已析构
-2025-07-26 21:45:04.651 [INFO] 4. 测试音频编码器创建...
-2025-07-26 21:45:04.651 [DEBUG] 创建编码编解码器, 媒体类型: 1
-2025-07-26 21:45:04.651 [DEBUG] 创建音频编码器
-2025-07-26 21:45:04.651 [INFO] 音频编码器创建成功
-2025-07-26 21:45:04.652 [DEBUG] 编解码器状态变更: 0 -> 1
-2025-07-26 21:45:04.652 [INFO] 音频编码器已打开: aac (44100Hz, 2ch, 128kbps)
-2025-07-26 21:45:04.652 [INFO] 音频编码器打开成功
-2025-07-26 21:45:04.652 [INFO] 编码器状态: 1
-2025-07-26 21:45:04.653 [INFO] 是否已打开: 是
-2025-07-26 21:45:04.653 [DEBUG] 编解码器状态变更: 1 -> 4
-2025-07-26 21:45:04.653 [DEBUG] 音频编码器已关闭
-2025-07-26 21:45:04.653 [INFO] 音频编码器已关闭
-2025-07-26 21:45:04.653 [DEBUG] 音频编码器已销毁
-2025-07-26 21:45:04.653 [DEBUG] 编解码器已析构
-2025-07-26 21:45:04.653 [INFO] 5. 测试编码器工厂...
-2025-07-26 21:45:04.653 [DEBUG] 创建编码编解码器, 媒体类型: 2
-2025-07-26 21:45:04.653 [DEBUG] 创建视频编码器
-2025-07-26 21:45:04.654 [INFO] 最佳视频编码器创建成功(硬件优先)
-2025-07-26 21:45:04.654 [DEBUG] 创建编码编解码器, 媒体类型: 2
-2025-07-26 21:45:04.654 [DEBUG] 创建视频编码器
-2025-07-26 21:45:04.654 [INFO] 最佳视频编码器创建成功(软件优先)
-2025-07-26 21:45:04.654 [DEBUG] 创建编码编解码器, 媒体类型: 1
-2025-07-26 21:45:04.654 [DEBUG] 创建音频编码器
-2025-07-26 21:45:04.654 [INFO] 最佳音频编码器创建成功
-2025-07-26 21:45:04.654 [DEBUG] 创建编码编解码器, 媒体类型: 1
-2025-07-26 21:45:04.654 [DEBUG] 创建音频编码器
-2025-07-26 21:45:04.655 [INFO] 无损音频编码器创建成功
-2025-07-26 21:45:04.655 [INFO] 6. 测试编码器能力查询...
-2025-07-26 21:45:04.655 [INFO] 编码器 aac 支持:
-2025-07-26 21:45:04.655 [INFO]   - FLTP格式: 是
-2025-07-26 21:45:04.655 [INFO]   - 44100Hz: 是
-2025-07-26 21:45:04.655 [INFO]   - 立体声: 是
-2025-07-26 21:45:04.655 [INFO] 7. 测试编码器统计信息...
-2025-07-26 21:45:04.655 [DEBUG] 创建编码编解码器, 媒体类型: 2
-2025-07-26 21:45:04.655 [DEBUG] 创建视频编码器
-2025-07-26 21:45:04.655 [INFO] 编码器统计信息:
-2025-07-26 21:45:04.656 [INFO]   - 处理帧数: 0
-2025-07-26 21:45:04.656 [INFO]   - 丢弃帧数: 0
-2025-07-26 21:45:04.656 [INFO]   - 错误次数: 0
-2025-07-26 21:45:04.656 [INFO]   - 平均处理时间: {:.2f}ms
-2025-07-26 21:45:04.656 [INFO]   - 总字节数: 0
-2025-07-26 21:45:04.656 [DEBUG] 视频编码器已销毁
-2025-07-26 21:45:04.656 [DEBUG] 编解码器已析构
-2025-07-26 21:45:04.656 [INFO] === 所有编解码测试完成 ===
-2025-07-26 21:45:04.656 [INFO] 测试完成,请查看 codec_test_log.txt 文件
-2025-07-26 21:45:04.656 [DEBUG] 音频编码器已销毁
-2025-07-26 21:45:04.656 [DEBUG] 编解码器已析构
-2025-07-26 21:45:04.657 [DEBUG] 音频编码器已销毁
-2025-07-26 21:45:04.657 [DEBUG] 编解码器已析构
-2025-07-26 21:45:04.657 [DEBUG] 视频编码器已销毁
-2025-07-26 21:45:04.657 [DEBUG] 编解码器已析构
-2025-07-26 21:45:04.657 [DEBUG] 视频编码器已销毁
-2025-07-26 21:45:04.657 [DEBUG] 编解码器已析构
-2025-07-26 21:45:04.657 [INFO] FFmpeg cleanup completed

+ 31 - 0
AV/integration_example.cpp

@@ -0,0 +1,31 @@
+#include <QApplication>
+#include <QDebug>
+#include <QFileDialog>
+#include <QHBoxLayout>
+#include <QLabel>
+#include <QMainWindow>
+#include <QMessageBox>
+#include <QPushButton>
+#include <QSlider>
+#include <QTimer>
+#include <QVBoxLayout>
+
+#include "code/base/logger.h"
+
+#include "code/player/SimplePlayerWindow.h"
+
+int main(int argc, char* argv[])
+{
+    av::Logger::initialize("test_log.txt", av::LogLevel::DEBUG, false, true);
+
+    QApplication app(argc, argv);
+
+    // 创建并显示播放器窗口
+    SimplePlayerWindow window;
+    window.show();
+    
+    qDebug() << "AV Player Integration Example Started";
+    qDebug() << "This example demonstrates how to integrate the new player core with Qt UI";
+    
+    return app.exec();
+}

+ 0 - 133
AV/output.txt

@@ -1,133 +0,0 @@
-
-20:14:48: Starting F:\A_QT\im\LearningSmartClient\bin_debug\LearningSmartClientd.exe...
-"2025-07-26 20:14:49.830 [INFO] AV Logger initialized"
-"2025-07-26 20:14:49.832 [INFO] FFmpeg initialized successfully"
-"2025-07-26 20:14:49.832 [INFO] 1. 测试视频编码器支持..."
-"2025-07-26 20:14:49.832 [INFO] 查找可用的视频编码器..."
-"2025-07-26 20:14:49.832 [INFO] 找到硬件编码器: h264_nvenc"
-"2025-07-26 20:14:49.833 [INFO] 找到硬件编码器: h264_qsv"
-"2025-07-26 20:14:49.833 [INFO] 找到硬件编码器: h264_amf"
-"2025-07-26 20:14:49.833 [INFO] 找到软件编码器: libx264"
-"2025-07-26 20:14:49.833 [INFO] 找到软件编码器: libx265"
-"2025-07-26 20:14:49.833 [INFO] 总共找到 5 个可用的视频编码器"
-"2025-07-26 20:14:49.833 [INFO] 支持的视频编码器数量: 5"
-"2025-07-26 20:14:49.833 [INFO]   - h264_nvenc (硬件: 是)"
-"2025-07-26 20:14:49.833 [INFO]   - h264_qsv (硬件: 是)"
-"2025-07-26 20:14:49.833 [INFO]   - h264_amf (硬件: 是)"
-"2025-07-26 20:14:49.833 [INFO]   - libx264 (硬件: 否)"
-"2025-07-26 20:14:49.833 [INFO]   - libx265 (硬件: 否)"
-"2025-07-26 20:14:49.833 [INFO] 推荐的视频编码器: h264_nvenc"
-"2025-07-26 20:14:49.834 [INFO] 2. 测试音频编码器支持..."
-"2025-07-26 20:14:49.834 [INFO] 查找可用的音频编码器..."
-"2025-07-26 20:14:49.834 [INFO] 找到音频编码器: aac"
-"2025-07-26 20:14:49.834 [INFO] 找到音频编码器: libmp3lame"
-"2025-07-26 20:14:49.834 [INFO] 找到音频编码器: opus"
-"2025-07-26 20:14:49.834 [INFO] 找到音频编码器: libopus"
-"2025-07-26 20:14:49.834 [INFO] 找到音频编码器: vorbis"
-"2025-07-26 20:14:49.834 [INFO] 找到音频编码器: libvorbis"
-"2025-07-26 20:14:49.834 [INFO] 找到音频编码器: flac"
-"2025-07-26 20:14:49.834 [INFO] 找到音频编码器: pcm_s16le"
-"2025-07-26 20:14:49.834 [INFO] 找到音频编码器: pcm_s24le"
-"2025-07-26 20:14:49.834 [INFO] 找到音频编码器: pcm_s32le"
-"2025-07-26 20:14:49.835 [INFO] 总共找到 10 个可用的音频编码器"
-"2025-07-26 20:14:49.835 [INFO] 支持的音频编码器数量: 10"
-"2025-07-26 20:14:49.835 [INFO]   - aac"
-"2025-07-26 20:14:49.835 [INFO]   - libmp3lame"
-"2025-07-26 20:14:49.835 [INFO]   - opus"
-"2025-07-26 20:14:49.835 [INFO]   - libopus"
-"2025-07-26 20:14:49.835 [INFO]   - vorbis"
-"2025-07-26 20:14:49.835 [INFO]   - libvorbis"
-"2025-07-26 20:14:49.835 [INFO]   - flac"
-"2025-07-26 20:14:49.835 [INFO]   - pcm_s16le"
-"2025-07-26 20:14:49.835 [INFO]   - pcm_s24le"
-"2025-07-26 20:14:49.835 [INFO]   - pcm_s32le"
-"2025-07-26 20:14:49.835 [INFO] 推荐的音频编码器: aac"
-"2025-07-26 20:14:49.836 [INFO] 3. 测试视频编码器创建..."
-"2025-07-26 20:14:49.836 [DEBUG] 创建编码编解码器, 媒体类型: 1"
-"2025-07-26 20:14:49.836 [DEBUG] 创建视频编码器"
-"2025-07-26 20:14:49.836 [INFO] 视频编码器创建成功"
-"2025-07-26 20:14:49.836 [INFO] 开始设置硬件加速: 编码器=h264_nvenc, 设备类型=2"
-"2025-07-26 20:14:49.836 [INFO] 检查CUDA设备可用性..."
-"2025-07-26 20:14:49.836 [INFO] 创建硬件设备上下文..."
-"2025-07-26 20:14:49.941 [INFO] 硬件设备上下文创建成功: h264_nvenc"
-"2025-07-26 20:14:49.941 [INFO] 设置硬件帧上下文: 1280x720, 硬件格式: 117, 软件格式: 23, 池大小: 8"
-"2025-07-26 20:14:49.943 [INFO] 硬件帧上下文初始化成功"
-"2025-07-26 20:14:49.943 [INFO] 设置硬件编码器像素格式: 117 (cuda)"
-"2025-07-26 20:14:49.943 [INFO] 设置NVENC编码器参数..."
-"2025-07-26 20:14:49.943 [INFO] 设置preset=medium: 成功"
-"2025-07-26 20:14:49.943 [INFO] 设置profile=main: 成功"
-"2025-07-26 20:14:49.943 [INFO] 设置rc=vbr: 成功"
-"2025-07-26 20:14:49.943 [INFO] 设置surfaces=16: 成功"
-"2025-07-26 20:14:49.943 [INFO] 设置delay=0: 成功"
-"2025-07-26 20:14:49.943 [INFO] 启用低延迟模式"
-"2025-07-26 20:14:49.943 [INFO] 设置preset=fast: 成功"
-"2025-07-26 20:14:49.943 [INFO] 设置tune=ll: 成功"
-"2025-07-26 20:14:49.943 [INFO] 准备打开编码器: h264_nvenc"
-"2025-07-26 20:14:49.944 [INFO] 编码器参数: 1280x720, 比特率: 2000000, 帧率: 30, 像素格式: 117"
-"2025-07-26 20:14:49.944 [INFO] 硬件编码器状态: 设备上下文=已创建, 帧上下文=已设置"
-"2025-07-26 20:14:49.998 [INFO] 编码器打开成功: h264_nvenc"
-"2025-07-26 20:14:49.998 [DEBUG] 编解码器状态变更: 0 -> 1"
-"2025-07-26 20:14:49.999 [INFO] 视频编码器已打开: h264_nvenc (1280x720 @ 30fps)"
-"2025-07-26 20:14:49.999 [INFO] 视频编码器打开成功"
-"2025-07-26 20:14:49.999 [INFO] 编码器状态: 1"
-"2025-07-26 20:14:49.999 [INFO] 是否已打开: 是"
-"2025-07-26 20:14:50.026 [DEBUG] 编解码器状态变更: 1 -> 4"
-"2025-07-26 20:14:50.026 [DEBUG] 视频编码器已关闭"
-"2025-07-26 20:14:50.026 [INFO] 视频编码器已关闭"
-"2025-07-26 20:14:50.026 [DEBUG] 视频编码器已销毁"
-"2025-07-26 20:14:50.026 [DEBUG] 编解码器已析构"
-"2025-07-26 20:14:50.026 [INFO] 4. 测试音频编码器创建..."
-"2025-07-26 20:14:50.026 [DEBUG] 创建编码编解码器, 媒体类型: 0"
-"2025-07-26 20:14:50.026 [DEBUG] 创建音频编码器"
-"2025-07-26 20:14:50.026 [INFO] 音频编码器创建成功"
-"2025-07-26 20:14:50.027 [DEBUG] 编解码器状态变更: 0 -> 1"
-"2025-07-26 20:14:50.027 [INFO] 音频编码器已打开: aac (44100Hz, 2ch, 128kbps)"
-"2025-07-26 20:14:50.027 [INFO] 音频编码器打开成功"
-"2025-07-26 20:14:50.027 [INFO] 编码器状态: 1"
-"2025-07-26 20:14:50.027 [INFO] 是否已打开: 是"
-"2025-07-26 20:14:50.027 [DEBUG] 编解码器状态变更: 1 -> 4"
-"2025-07-26 20:14:50.028 [DEBUG] 音频编码器已关闭"
-"2025-07-26 20:14:50.028 [INFO] 音频编码器已关闭"
-"2025-07-26 20:14:50.028 [DEBUG] 音频编码器已销毁"
-"2025-07-26 20:14:50.028 [DEBUG] 编解码器已析构"
-"2025-07-26 20:14:50.028 [INFO] 5. 测试编码器工厂..."
-"2025-07-26 20:14:50.028 [DEBUG] 创建编码编解码器, 媒体类型: 1"
-"2025-07-26 20:14:50.028 [DEBUG] 创建视频编码器"
-"2025-07-26 20:14:50.028 [INFO] 最佳视频编码器创建成功(硬件优先)"
-"2025-07-26 20:14:50.028 [DEBUG] 创建编码编解码器, 媒体类型: 1"
-"2025-07-26 20:14:50.029 [DEBUG] 创建视频编码器"
-"2025-07-26 20:14:50.029 [INFO] 最佳视频编码器创建成功(软件优先)"
-"2025-07-26 20:14:50.029 [DEBUG] 创建编码编解码器, 媒体类型: 0"
-"2025-07-26 20:14:50.029 [DEBUG] 创建音频编码器"
-"2025-07-26 20:14:50.029 [INFO] 最佳音频编码器创建成功"
-"2025-07-26 20:14:50.029 [DEBUG] 创建编码编解码器, 媒体类型: 0"
-"2025-07-26 20:14:50.029 [DEBUG] 创建音频编码器"
-"2025-07-26 20:14:50.029 [INFO] 无损音频编码器创建成功"
-"2025-07-26 20:14:50.029 [INFO] 6. 测试编码器能力查询..."
-"2025-07-26 20:14:50.029 [INFO] 编码器 aac 支持:"
-"2025-07-26 20:14:50.029 [INFO]   - FLTP格式: 是"
-"2025-07-26 20:14:50.029 [INFO]   - 44100Hz: 是"
-"2025-07-26 20:14:50.029 [INFO]   - 立体声: 是"
-"2025-07-26 20:14:50.029 [INFO] 7. 测试编码器统计信息..."
-"2025-07-26 20:14:50.030 [DEBUG] 创建编码编解码器, 媒体类型: 1"
-"2025-07-26 20:14:50.030 [DEBUG] 创建视频编码器"
-"2025-07-26 20:14:50.030 [INFO] 编码器统计信息:"
-"2025-07-26 20:14:50.030 [INFO]   - 处理帧数: 0"
-"2025-07-26 20:14:50.030 [INFO]   - 丢弃帧数: 0"
-"2025-07-26 20:14:50.030 [INFO]   - 错误次数: 0"
-"2025-07-26 20:14:50.030 [INFO]   - 平均处理时间: {:.2f}ms"
-"2025-07-26 20:14:50.030 [INFO]   - 总字节数: 0"
-"2025-07-26 20:14:50.030 [DEBUG] 视频编码器已销毁"
-"2025-07-26 20:14:50.030 [DEBUG] 编解码器已析构"
-"2025-07-26 20:14:50.030 [INFO] === 所有编解码测试完成 ==="
-"2025-07-26 20:14:50.030 [INFO] 测试完成,请查看 codec_test_log.txt 文件"
-"2025-07-26 20:14:50.030 [DEBUG] 音频编码器已销毁"
-"2025-07-26 20:14:50.030 [DEBUG] 编解码器已析构"
-"2025-07-26 20:14:50.031 [DEBUG] 音频编码器已销毁"
-"2025-07-26 20:14:50.031 [DEBUG] 编解码器已析构"
-"2025-07-26 20:14:50.031 [DEBUG] 视频编码器已销毁"
-"2025-07-26 20:14:50.031 [DEBUG] 编解码器已析构"
-"2025-07-26 20:14:50.031 [DEBUG] 视频编码器已销毁"
-"2025-07-26 20:14:50.031 [DEBUG] 编解码器已析构"
-"2025-07-26 20:14:50.031 [INFO] FFmpeg cleanup completed"
-20:14:50: The command "F:\A_QT\im\LearningSmartClient\bin_debug\LearningSmartClientd.exe" finished successfully.

+ 330 - 0
AV/test_player.cpp

@@ -0,0 +1,330 @@
+/**
+ * @file test_player.cpp
+ * @brief 播放器模块测试程序
+ * @author AI Assistant
+ * @date 2024
+ */
+
+#include "code/player/player_core.h"
+#include "code/base/media_common.h"
+#include <iostream>
+#include <thread>
+#include <chrono>
+#include <string>
+
+using namespace av;
+using namespace av::player;
+
+/**
+ * @brief 播放器事件回调实现
+ */
+class TestPlayerCallback : public PlayerEventCallback {
+public:
+    void onStateChanged(PlayerState state) override {
+        std::cout << "[EVENT] State changed to: " << static_cast<int>(state) << std::endl;
+    }
+    
+    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 << 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.audioSampleRate << " Hz, " 
+                      << info.audioChannels << " channels" << std::endl;
+        }
+    }
+    
+    void onErrorOccurred(const std::string& error) override {
+        std::cout << "[ERROR] " << error << std::endl;
+    }
+    
+    void onPlaybackFinished() override {
+        std::cout << "[EVENT] Playback finished" << std::endl;
+    }
+};
+
+/**
+ * @brief 测试播放器基本功能
+ */
+bool testPlayerBasicFunctions() {
+    std::cout << "\n=== Testing Player Basic Functions ===" << std::endl;
+    
+    // 创建播放器
+    PlayerCore player;
+    TestPlayerCallback callback;
+    player.setEventCallback(&callback);
+    
+    // 测试初始状态
+    if (player.getState() != PlayerState::Idle) {
+        std::cout << "[FAIL] Initial state should be Idle" << std::endl;
+        return false;
+    }
+    
+    // 测试音量设置
+    player.setVolume(0.5);
+    if (std::abs(player.getVolume() - 0.5) > 0.001) {
+        std::cout << "[FAIL] Volume setting failed" << std::endl;
+        return false;
+    }
+    
+    // 测试播放速度设置
+    ErrorCode result = player.setPlaybackSpeed(1.5);
+    if (result != ErrorCode::OK) {
+        std::cout << "[FAIL] Playback speed setting failed" << std::endl;
+        return false;
+    }
+    
+    // 测试无效播放速度
+    result = player.setPlaybackSpeed(-1.0);
+    if (result == ErrorCode::OK) {
+        std::cout << "[FAIL] Should reject invalid playback speed" << std::endl;
+        return false;
+    }
+    
+    std::cout << "[PASS] Player basic functions test passed" << std::endl;
+    return true;
+}
+
+/**
+ * @brief 测试播放器状态转换
+ */
+bool testPlayerStateTransitions() {
+    std::cout << "\n=== Testing Player State Transitions ===" << std::endl;
+    
+    PlayerCore player;
+    TestPlayerCallback callback;
+    player.setEventCallback(&callback);
+    
+    // 测试在Idle状态下播放(应该失败)
+    ErrorCode result = player.play();
+    if (result == ErrorCode::OK) {
+        std::cout << "[FAIL] Should not be able to play in Idle state" << std::endl;
+        return false;
+    }
+    
+    // 测试在Idle状态下暂停(应该失败)
+    result = player.pause();
+    if (result == ErrorCode::OK) {
+        std::cout << "[FAIL] Should not be able to pause in Idle state" << std::endl;
+        return false;
+    }
+    
+    // 测试停止(应该成功,因为已经是停止状态)
+    result = player.stop();
+    if (result != ErrorCode::OK) {
+        std::cout << "[FAIL] Stop should always succeed" << std::endl;
+        return false;
+    }
+    
+    std::cout << "[PASS] Player state transitions test passed" << std::endl;
+    return true;
+}
+
+/**
+ * @brief 测试媒体文件打开(使用不存在的文件)
+ */
+bool testMediaFileHandling() {
+    std::cout << "\n=== Testing Media File Handling ===" << std::endl;
+    
+    PlayerCore player;
+    TestPlayerCallback callback;
+    player.setEventCallback(&callback);
+    
+    // 测试打开不存在的文件
+    ErrorCode result = player.openFile("nonexistent_file.mp4");
+    if (result == ErrorCode::OK) {
+        std::cout << "[FAIL] Should fail to open nonexistent file" << std::endl;
+        return false;
+    }
+    
+    // 测试打开空文件名
+    result = player.openFile("");
+    if (result == ErrorCode::OK) {
+        std::cout << "[FAIL] Should fail to open empty filename" << std::endl;
+        return false;
+    }
+    
+    std::cout << "[PASS] Media file handling test passed" << std::endl;
+    return true;
+}
+
+/**
+ * @brief 测试播放器统计信息
+ */
+bool testPlayerStats() {
+    std::cout << "\n=== Testing Player Stats ===" << std::endl;
+    
+    PlayerCore player;
+    
+    // 获取初始统计信息
+    PlaybackStats stats = player.getStats();
+    
+    // 验证初始值
+    if (stats.currentTime != 0 || stats.playbackSpeed != 1.0) {
+        std::cout << "[FAIL] Initial stats values incorrect" << std::endl;
+        return false;
+    }
+    
+    // 设置播放速度并验证统计信息
+    player.setPlaybackSpeed(2.0);
+    stats = player.getStats();
+    
+    if (std::abs(stats.playbackSpeed - 2.0) > 0.001) {
+        std::cout << "[FAIL] Stats playback speed not updated" << std::endl;
+        return false;
+    }
+    
+    std::cout << "[PASS] Player stats test passed" << std::endl;
+    return true;
+}
+
+/**
+ * @brief 测试帧获取接口
+ */
+bool testFrameInterface() {
+    std::cout << "\n=== Testing Frame Interface ===" << std::endl;
+    
+    PlayerCore player;
+    
+    // 测试在没有媒体的情况下获取帧
+    AVFrame* videoFrame = player.getNextVideoFrame();
+    if (videoFrame != nullptr) {
+        std::cout << "[FAIL] Should return null when no media loaded" << std::endl;
+        return false;
+    }
+    
+    AVFrame* audioFrame = player.getNextAudioFrame();
+    if (audioFrame != nullptr) {
+        std::cout << "[FAIL] Should return null when no media loaded" << std::endl;
+        return false;
+    }
+    
+    // 测试释放空帧(应该安全)
+    player.releaseVideoFrame(nullptr);
+    player.releaseAudioFrame(nullptr);
+    
+    std::cout << "[PASS] Frame interface test passed" << std::endl;
+    return true;
+}
+
+/**
+ * @brief 测试播放器更新循环
+ */
+bool testPlayerUpdate() {
+    std::cout << "\n=== Testing Player Update ===" << std::endl;
+    
+    PlayerCore player;
+    
+    // 调用更新函数(应该安全)
+    player.update();
+    
+    // 多次调用更新
+    for (int i = 0; i < 10; ++i) {
+        player.update();
+        std::this_thread::sleep_for(std::chrono::milliseconds(1));
+    }
+    
+    std::cout << "[PASS] Player update test passed" << std::endl;
+    return true;
+}
+
+/**
+ * @brief 测试播放器多实例
+ */
+bool testMultiplePlayerInstances() {
+    std::cout << "\n=== Testing Multiple Player Instances ===" << std::endl;
+    
+    // 创建多个播放器实例
+    std::vector<std::unique_ptr<PlayerCore>> players;
+    std::vector<std::unique_ptr<TestPlayerCallback>> callbacks;
+    
+    for (int i = 0; i < 3; ++i) {
+        auto player = std::make_unique<PlayerCore>();
+        auto callback = std::make_unique<TestPlayerCallback>();
+        
+        player->setEventCallback(callback.get());
+        player->setVolume(0.1 * (i + 1));
+        
+        players.push_back(std::move(player));
+        callbacks.push_back(std::move(callback));
+    }
+    
+    // 验证每个播放器的状态
+    for (size_t i = 0; i < players.size(); ++i) {
+        if (players[i]->getState() != PlayerState::Idle) {
+            std::cout << "[FAIL] Player " << i << " state incorrect" << std::endl;
+            return false;
+        }
+        
+        double expectedVolume = 0.1 * (i + 1);
+        if (std::abs(players[i]->getVolume() - expectedVolume) > 0.001) {
+            std::cout << "[FAIL] Player " << i << " volume incorrect" << std::endl;
+            return false;
+        }
+    }
+    
+    std::cout << "[PASS] Multiple player instances test passed" << std::endl;
+    return true;
+}
+
+/**
+ * @brief 运行所有测试
+ */
+int main() {
+    std::cout << "Starting Player Module Tests..." << std::endl;
+    
+    int passedTests = 0;
+    int totalTests = 0;
+    
+    // 运行所有测试
+    struct TestCase {
+        const char* name;
+        bool (*func)();
+    };
+    
+    TestCase tests[] = {
+        {"Player Basic Functions", testPlayerBasicFunctions},
+        {"Player State Transitions", testPlayerStateTransitions},
+        {"Media File Handling", testMediaFileHandling},
+        {"Player Stats", testPlayerStats},
+        {"Frame Interface", testFrameInterface},
+        {"Player Update", testPlayerUpdate},
+        {"Multiple Player Instances", testMultiplePlayerInstances}
+    };
+    
+    for (const auto& test : tests) {
+        totalTests++;
+        try {
+            if (test.func()) {
+                passedTests++;
+            }
+        }
+        catch (const std::exception& e) {
+            std::cout << "[EXCEPTION] Test " << test.name << " threw: " << e.what() << std::endl;
+        }
+        catch (...) {
+            std::cout << "[EXCEPTION] Test " << test.name << " threw unknown exception" << std::endl;
+        }
+    }
+    
+    // 输出测试结果
+    std::cout << "\n=== Test Results ===" << std::endl;
+    std::cout << "Passed: " << passedTests << "/" << totalTests << std::endl;
+    std::cout << "Success Rate: " << (100.0 * passedTests / totalTests) << "%" << std::endl;
+    
+    if (passedTests == totalTests) {
+        std::cout << "\n🎉 All tests passed!" << std::endl;
+        return 0;
+    } else {
+        std::cout << "\n❌ Some tests failed!" << std::endl;
+        return 1;
+    }
+}

+ 347 - 0
AV/utils_test_log.txt

@@ -0,0 +1,347 @@
+2025-07-27 01:27:27.259 [INFO] AV Logger initialized
+2025-07-27 01:27:27.260 [INFO] === AV工具类模块测试套件 ===
+2025-07-27 01:27:27.261 [INFO] 开始运行所有工具类测试...
+2025-07-27 01:27:27.261 [INFO] 
+=== 运行测试: 线程池基本功能 ===
+2025-07-27 01:27:27.261 [INFO] [测试] 线程池基本功能...
+2025-07-27 01:27:27.261 [INFO] Thread pool initialized with 2 min threads, 4 max threads
+2025-07-27 01:27:27.261 [INFO] Thread pool started with 2 threads
+2025-07-27 01:27:27.261 [INFO] 线程池启动成功
+2025-07-27 01:27:27.261 [DEBUG] Created new worker thread, total: %zu
+2025-07-27 01:27:27.261 [DEBUG] Created new worker thread, total: %zu
+2025-07-27 01:27:27.262 [DEBUG] Worker thread %zu started
+2025-07-27 01:27:27.264 [DEBUG] Worker thread %zu started
+2025-07-27 01:27:27.264 [DEBUG] Worker thread %zu started
+2025-07-27 01:27:27.264 [DEBUG] Worker thread %zu started
+2025-07-27 01:27:27.289 [INFO] 任务 9 完成
+2025-07-27 01:27:27.289 [INFO] 任务 6 完成
+2025-07-27 01:27:27.289 [INFO] 任务 0 完成
+2025-07-27 01:27:27.289 [INFO] 任务 2 完成
+2025-07-27 01:27:27.305 [INFO] 任务 4 完成
+2025-07-27 01:27:27.305 [INFO] 任务 7 完成
+2025-07-27 01:27:27.305 [INFO] 任务 8 完成
+2025-07-27 01:27:27.305 [INFO] 任务 5 完成
+2025-07-27 01:27:27.320 [INFO] 任务 1 完成
+2025-07-27 01:27:27.320 [INFO] 任务 3 完成
+2025-07-27 01:27:27.320 [INFO] 线程池统计: 总线程数=4, 完成任务数=10
+2025-07-27 01:27:27.320 [DEBUG] Worker thread %zu stopped
+2025-07-27 01:27:27.320 [DEBUG] Worker thread %zu stopped
+2025-07-27 01:27:27.320 [DEBUG] Worker thread %zu stopped
+2025-07-27 01:27:27.320 [DEBUG] Worker thread %zu stopped
+2025-07-27 01:27:27.321 [INFO] Thread pool stopped
+2025-07-27 01:27:27.321 [INFO] [成功] 线程池基本功能测试通过
+2025-07-27 01:27:27.321 [INFO] ✓ 线程池基本功能 测试通过
+2025-07-27 01:27:27.321 [INFO] 
+=== 运行测试: 线程池优先级功能 ===
+2025-07-27 01:27:27.321 [INFO] [测试] 线程池优先级功能...
+2025-07-27 01:27:27.321 [INFO] Thread pool initialized with 1 min threads, 1 max threads
+2025-07-27 01:27:27.321 [INFO] Thread pool started with 1 threads
+2025-07-27 01:27:27.321 [DEBUG] Worker thread %zu started
+2025-07-27 01:27:27.321 [INFO] 关键优先级任务执行
+2025-07-27 01:27:27.321 [INFO] 高优先级任务执行
+2025-07-27 01:27:27.322 [INFO] 普通优先级任务执行
+2025-07-27 01:27:27.322 [INFO] 低优先级任务执行
+2025-07-27 01:27:27.322 [INFO] 任务执行顺序:
+2025-07-27 01:27:27.322 [INFO]   第1个执行的任务ID: 4
+2025-07-27 01:27:27.322 [INFO]   第2个执行的任务ID: 3
+2025-07-27 01:27:27.322 [INFO]   第3个执行的任务ID: 2
+2025-07-27 01:27:27.322 [INFO]   第4个执行的任务ID: 1
+2025-07-27 01:27:27.322 [DEBUG] Worker thread %zu stopped
+2025-07-27 01:27:27.322 [INFO] Thread pool stopped
+2025-07-27 01:27:27.322 [INFO] [成功] 线程池优先级功能测试通过
+2025-07-27 01:27:27.322 [INFO] ✓ 线程池优先级功能 测试通过
+2025-07-27 01:27:27.323 [INFO] 
+=== 运行测试: 帧队列功能 ===
+2025-07-27 01:27:27.323 [INFO] [测试] 帧队列功能...
+2025-07-27 01:27:27.323 [DEBUG] FrameQueue created with max size: 10
+2025-07-27 01:27:27.323 [INFO] 队列大小: 5
+2025-07-27 01:27:27.323 [INFO] [成功] 帧队列功能测试通过
+2025-07-27 01:27:27.323 [DEBUG] Frame queue cleared
+2025-07-27 01:27:27.323 [DEBUG] FrameQueue destroyed
+2025-07-27 01:27:27.323 [INFO] ✓ 帧队列功能 测试通过
+2025-07-27 01:27:27.323 [INFO] 
+=== 运行测试: 数据包队列功能 ===
+2025-07-27 01:27:27.323 [INFO] [测试] 数据包队列功能...
+2025-07-27 01:27:27.324 [DEBUG] PacketQueue created with max size: 20, max bytes: 52428800
+2025-07-27 01:27:27.324 [INFO] 队列大小: 10
+2025-07-27 01:27:27.324 [INFO] [成功] 数据包队列功能测试通过
+2025-07-27 01:27:27.324 [DEBUG] Packet queue cleared
+2025-07-27 01:27:27.324 [DEBUG] PacketQueue destroyed
+2025-07-27 01:27:27.324 [INFO] ✓ 数据包队列功能 测试通过
+2025-07-27 01:27:27.324 [INFO] 
+=== 运行测试: 性能监控功能 ===
+2025-07-27 01:27:27.324 [INFO] [测试] 性能监控功能...
+2025-07-27 01:27:27.324 [DEBUG] Registered metric: system.cpu_usage (type: 1)
+2025-07-27 01:27:27.325 [DEBUG] Registered metric: system.memory_usage (type: 1)
+2025-07-27 01:27:27.325 [DEBUG] Registered metric: system.disk_usage (type: 1)
+2025-07-27 01:27:27.325 [DEBUG] Registered metric: performance.frame_rate (type: 4)
+2025-07-27 01:27:27.325 [DEBUG] Registered metric: performance.latency (type: 2)
+2025-07-27 01:27:27.325 [DEBUG] Registered metric: performance.throughput (type: 4)
+2025-07-27 01:27:27.325 [INFO] Performance monitor initialized successfully
+2025-07-27 01:27:27.325 [DEBUG] Registered metric: frames_processed (type: 0)
+2025-07-27 01:27:27.325 [DEBUG] Registered metric: bytes_processed (type: 0)
+2025-07-27 01:27:27.325 [INFO] Performance monitor started
+2025-07-27 01:27:27.325 [DEBUG] Metric updated: frames_processed = 1
+2025-07-27 01:27:27.326 [DEBUG] Metric updated: bytes_processed = 1024
+2025-07-27 01:27:27.336 [DEBUG] Metric updated: frames_processed = 2
+2025-07-27 01:27:27.336 [DEBUG] Metric updated: bytes_processed = 2048
+2025-07-27 01:27:27.352 [DEBUG] Metric updated: frames_processed = 3
+2025-07-27 01:27:27.352 [DEBUG] Metric updated: bytes_processed = 3072
+2025-07-27 01:27:27.368 [DEBUG] Metric updated: frames_processed = 4
+2025-07-27 01:27:27.368 [DEBUG] Metric updated: bytes_processed = 4096
+2025-07-27 01:27:27.384 [DEBUG] Metric updated: frames_processed = 5
+2025-07-27 01:27:27.384 [DEBUG] Metric updated: bytes_processed = 5120
+2025-07-27 01:27:27.400 [DEBUG] Metric updated: frames_processed = 6
+2025-07-27 01:27:27.400 [DEBUG] Metric updated: bytes_processed = 6144
+2025-07-27 01:27:27.415 [DEBUG] Metric updated: frames_processed = 7
+2025-07-27 01:27:27.415 [DEBUG] Metric updated: bytes_processed = 7168
+2025-07-27 01:27:27.431 [DEBUG] Metric updated: frames_processed = 8
+2025-07-27 01:27:27.431 [DEBUG] Metric updated: bytes_processed = 8192
+2025-07-27 01:27:27.447 [DEBUG] Metric updated: frames_processed = 9
+2025-07-27 01:27:27.447 [DEBUG] Metric updated: bytes_processed = 9216
+2025-07-27 01:27:27.463 [DEBUG] Metric updated: frames_processed = 10
+2025-07-27 01:27:27.463 [DEBUG] Metric updated: bytes_processed = 10240
+2025-07-27 01:27:27.479 [DEBUG] Metric updated: frames_processed = 11
+2025-07-27 01:27:27.479 [DEBUG] Metric updated: bytes_processed = 11264
+2025-07-27 01:27:27.494 [DEBUG] Metric updated: frames_processed = 12
+2025-07-27 01:27:27.494 [DEBUG] Metric updated: bytes_processed = 12288
+2025-07-27 01:27:27.509 [DEBUG] Metric updated: frames_processed = 13
+2025-07-27 01:27:27.509 [DEBUG] Metric updated: bytes_processed = 13312
+2025-07-27 01:27:27.524 [DEBUG] Metric updated: frames_processed = 14
+2025-07-27 01:27:27.524 [DEBUG] Metric updated: bytes_processed = 14336
+2025-07-27 01:27:27.539 [DEBUG] Metric updated: frames_processed = 15
+2025-07-27 01:27:27.539 [DEBUG] Metric updated: bytes_processed = 15360
+2025-07-27 01:27:27.555 [DEBUG] Metric updated: frames_processed = 16
+2025-07-27 01:27:27.555 [DEBUG] Metric updated: bytes_processed = 16384
+2025-07-27 01:27:27.571 [DEBUG] Metric updated: frames_processed = 17
+2025-07-27 01:27:27.571 [DEBUG] Metric updated: bytes_processed = 17408
+2025-07-27 01:27:27.586 [DEBUG] Metric updated: frames_processed = 18
+2025-07-27 01:27:27.586 [DEBUG] Metric updated: bytes_processed = 18432
+2025-07-27 01:27:27.601 [DEBUG] Metric updated: frames_processed = 19
+2025-07-27 01:27:27.601 [DEBUG] Metric updated: bytes_processed = 19456
+2025-07-27 01:27:27.617 [DEBUG] Metric updated: frames_processed = 20
+2025-07-27 01:27:27.617 [DEBUG] Metric updated: bytes_processed = 20480
+2025-07-27 01:27:27.633 [DEBUG] Metric updated: frames_processed = 21
+2025-07-27 01:27:27.633 [DEBUG] Metric updated: bytes_processed = 21504
+2025-07-27 01:27:27.649 [DEBUG] Metric updated: frames_processed = 22
+2025-07-27 01:27:27.649 [DEBUG] Metric updated: bytes_processed = 22528
+2025-07-27 01:27:27.665 [DEBUG] Metric updated: frames_processed = 23
+2025-07-27 01:27:27.665 [DEBUG] Metric updated: bytes_processed = 23552
+2025-07-27 01:27:27.681 [DEBUG] Metric updated: frames_processed = 24
+2025-07-27 01:27:27.681 [DEBUG] Metric updated: bytes_processed = 24576
+2025-07-27 01:27:27.697 [DEBUG] Metric updated: frames_processed = 25
+2025-07-27 01:27:27.697 [DEBUG] Metric updated: bytes_processed = 25600
+2025-07-27 01:27:27.712 [DEBUG] Metric updated: frames_processed = 26
+2025-07-27 01:27:27.712 [DEBUG] Metric updated: bytes_processed = 26624
+2025-07-27 01:27:27.727 [DEBUG] Metric updated: frames_processed = 27
+2025-07-27 01:27:27.727 [DEBUG] Metric updated: bytes_processed = 27648
+2025-07-27 01:27:27.743 [DEBUG] Metric updated: frames_processed = 28
+2025-07-27 01:27:27.743 [DEBUG] Metric updated: bytes_processed = 28672
+2025-07-27 01:27:27.759 [DEBUG] Metric updated: frames_processed = 29
+2025-07-27 01:27:27.759 [DEBUG] Metric updated: bytes_processed = 29696
+2025-07-27 01:27:27.775 [DEBUG] Metric updated: frames_processed = 30
+2025-07-27 01:27:27.775 [DEBUG] Metric updated: bytes_processed = 30720
+2025-07-27 01:27:27.791 [DEBUG] Metric updated: frames_processed = 31
+2025-07-27 01:27:27.791 [DEBUG] Metric updated: bytes_processed = 31744
+2025-07-27 01:27:27.807 [DEBUG] Metric updated: frames_processed = 32
+2025-07-27 01:27:27.807 [DEBUG] Metric updated: bytes_processed = 32768
+2025-07-27 01:27:27.823 [DEBUG] Metric updated: frames_processed = 33
+2025-07-27 01:27:27.823 [DEBUG] Metric updated: bytes_processed = 33792
+2025-07-27 01:27:27.839 [DEBUG] Metric updated: frames_processed = 34
+2025-07-27 01:27:27.839 [DEBUG] Metric updated: bytes_processed = 34816
+2025-07-27 01:27:27.855 [DEBUG] Metric updated: frames_processed = 35
+2025-07-27 01:27:27.855 [DEBUG] Metric updated: bytes_processed = 35840
+2025-07-27 01:27:27.871 [DEBUG] Metric updated: frames_processed = 36
+2025-07-27 01:27:27.871 [DEBUG] Metric updated: bytes_processed = 36864
+2025-07-27 01:27:27.887 [DEBUG] Metric updated: frames_processed = 37
+2025-07-27 01:27:27.887 [DEBUG] Metric updated: bytes_processed = 37888
+2025-07-27 01:27:27.903 [DEBUG] Metric updated: frames_processed = 38
+2025-07-27 01:27:27.903 [DEBUG] Metric updated: bytes_processed = 38912
+2025-07-27 01:27:27.918 [DEBUG] Metric updated: frames_processed = 39
+2025-07-27 01:27:27.918 [DEBUG] Metric updated: bytes_processed = 39936
+2025-07-27 01:27:27.934 [DEBUG] Metric updated: frames_processed = 40
+2025-07-27 01:27:27.934 [DEBUG] Metric updated: bytes_processed = 40960
+2025-07-27 01:27:27.950 [DEBUG] Metric updated: frames_processed = 41
+2025-07-27 01:27:27.950 [DEBUG] Metric updated: bytes_processed = 41984
+2025-07-27 01:27:27.966 [DEBUG] Metric updated: frames_processed = 42
+2025-07-27 01:27:27.966 [DEBUG] Metric updated: bytes_processed = 43008
+2025-07-27 01:27:27.982 [DEBUG] Metric updated: frames_processed = 43
+2025-07-27 01:27:27.982 [DEBUG] Metric updated: bytes_processed = 44032
+2025-07-27 01:27:27.998 [DEBUG] Metric updated: frames_processed = 44
+2025-07-27 01:27:27.998 [DEBUG] Metric updated: bytes_processed = 45056
+2025-07-27 01:27:28.014 [DEBUG] Metric updated: frames_processed = 45
+2025-07-27 01:27:28.014 [DEBUG] Metric updated: bytes_processed = 46080
+2025-07-27 01:27:28.029 [DEBUG] Metric updated: frames_processed = 46
+2025-07-27 01:27:28.030 [DEBUG] Metric updated: bytes_processed = 47104
+2025-07-27 01:27:28.044 [DEBUG] Metric updated: frames_processed = 47
+2025-07-27 01:27:28.045 [DEBUG] Metric updated: bytes_processed = 48128
+2025-07-27 01:27:28.060 [DEBUG] Metric updated: frames_processed = 48
+2025-07-27 01:27:28.060 [DEBUG] Metric updated: bytes_processed = 49152
+2025-07-27 01:27:28.076 [DEBUG] Metric updated: frames_processed = 49
+2025-07-27 01:27:28.076 [DEBUG] Metric updated: bytes_processed = 50176
+2025-07-27 01:27:28.091 [DEBUG] Metric updated: frames_processed = 50
+2025-07-27 01:27:28.091 [DEBUG] Metric updated: bytes_processed = 51200
+2025-07-27 01:27:28.106 [DEBUG] Metric updated: frames_processed = 51
+2025-07-27 01:27:28.106 [DEBUG] Metric updated: bytes_processed = 52224
+2025-07-27 01:27:28.121 [DEBUG] Metric updated: frames_processed = 52
+2025-07-27 01:27:28.121 [DEBUG] Metric updated: bytes_processed = 53248
+2025-07-27 01:27:28.137 [DEBUG] Metric updated: frames_processed = 53
+2025-07-27 01:27:28.137 [DEBUG] Metric updated: bytes_processed = 54272
+2025-07-27 01:27:28.153 [DEBUG] Metric updated: frames_processed = 54
+2025-07-27 01:27:28.153 [DEBUG] Metric updated: bytes_processed = 55296
+2025-07-27 01:27:28.168 [DEBUG] Metric updated: frames_processed = 55
+2025-07-27 01:27:28.168 [DEBUG] Metric updated: bytes_processed = 56320
+2025-07-27 01:27:28.183 [DEBUG] Metric updated: frames_processed = 56
+2025-07-27 01:27:28.183 [DEBUG] Metric updated: bytes_processed = 57344
+2025-07-27 01:27:28.199 [DEBUG] Metric updated: frames_processed = 57
+2025-07-27 01:27:28.199 [DEBUG] Metric updated: bytes_processed = 58368
+2025-07-27 01:27:28.214 [DEBUG] Metric updated: frames_processed = 58
+2025-07-27 01:27:28.215 [DEBUG] Metric updated: bytes_processed = 59392
+2025-07-27 01:27:28.230 [DEBUG] Metric updated: frames_processed = 59
+2025-07-27 01:27:28.230 [DEBUG] Metric updated: bytes_processed = 60416
+2025-07-27 01:27:28.245 [DEBUG] Metric updated: frames_processed = 60
+2025-07-27 01:27:28.245 [DEBUG] Metric updated: bytes_processed = 61440
+2025-07-27 01:27:28.260 [DEBUG] Metric updated: frames_processed = 61
+2025-07-27 01:27:28.260 [DEBUG] Metric updated: bytes_processed = 62464
+2025-07-27 01:27:28.275 [DEBUG] Metric updated: frames_processed = 62
+2025-07-27 01:27:28.275 [DEBUG] Metric updated: bytes_processed = 63488
+2025-07-27 01:27:28.291 [DEBUG] Metric updated: frames_processed = 63
+2025-07-27 01:27:28.291 [DEBUG] Metric updated: bytes_processed = 64512
+2025-07-27 01:27:28.306 [DEBUG] Metric updated: frames_processed = 64
+2025-07-27 01:27:28.307 [DEBUG] Metric updated: bytes_processed = 65536
+2025-07-27 01:27:28.322 [DEBUG] Metric updated: frames_processed = 65
+2025-07-27 01:27:28.322 [DEBUG] Metric updated: bytes_processed = 66560
+2025-07-27 01:27:28.337 [DEBUG] Metric updated: frames_processed = 66
+2025-07-27 01:27:28.337 [DEBUG] Metric updated: bytes_processed = 67584
+2025-07-27 01:27:28.353 [DEBUG] Metric updated: frames_processed = 67
+2025-07-27 01:27:28.353 [DEBUG] Metric updated: bytes_processed = 68608
+2025-07-27 01:27:28.369 [DEBUG] Metric updated: frames_processed = 68
+2025-07-27 01:27:28.369 [DEBUG] Metric updated: bytes_processed = 69632
+2025-07-27 01:27:28.385 [DEBUG] Metric updated: frames_processed = 69
+2025-07-27 01:27:28.385 [DEBUG] Metric updated: bytes_processed = 70656
+2025-07-27 01:27:28.400 [DEBUG] Metric updated: frames_processed = 70
+2025-07-27 01:27:28.400 [DEBUG] Metric updated: bytes_processed = 71680
+2025-07-27 01:27:28.415 [DEBUG] Metric updated: frames_processed = 71
+2025-07-27 01:27:28.415 [DEBUG] Metric updated: bytes_processed = 72704
+2025-07-27 01:27:28.430 [DEBUG] Metric updated: frames_processed = 72
+2025-07-27 01:27:28.430 [DEBUG] Metric updated: bytes_processed = 73728
+2025-07-27 01:27:28.445 [DEBUG] Metric updated: frames_processed = 73
+2025-07-27 01:27:28.445 [DEBUG] Metric updated: bytes_processed = 74752
+2025-07-27 01:27:28.461 [DEBUG] Metric updated: frames_processed = 74
+2025-07-27 01:27:28.461 [DEBUG] Metric updated: bytes_processed = 75776
+2025-07-27 01:27:28.477 [DEBUG] Metric updated: frames_processed = 75
+2025-07-27 01:27:28.477 [DEBUG] Metric updated: bytes_processed = 76800
+2025-07-27 01:27:28.493 [DEBUG] Metric updated: frames_processed = 76
+2025-07-27 01:27:28.493 [DEBUG] Metric updated: bytes_processed = 77824
+2025-07-27 01:27:28.509 [DEBUG] Metric updated: frames_processed = 77
+2025-07-27 01:27:28.509 [DEBUG] Metric updated: bytes_processed = 78848
+2025-07-27 01:27:28.525 [DEBUG] Metric updated: frames_processed = 78
+2025-07-27 01:27:28.525 [DEBUG] Metric updated: bytes_processed = 79872
+2025-07-27 01:27:28.541 [DEBUG] Metric updated: frames_processed = 79
+2025-07-27 01:27:28.541 [DEBUG] Metric updated: bytes_processed = 80896
+2025-07-27 01:27:28.557 [DEBUG] Metric updated: frames_processed = 80
+2025-07-27 01:27:28.557 [DEBUG] Metric updated: bytes_processed = 81920
+2025-07-27 01:27:28.573 [DEBUG] Metric updated: frames_processed = 81
+2025-07-27 01:27:28.573 [DEBUG] Metric updated: bytes_processed = 82944
+2025-07-27 01:27:28.589 [DEBUG] Metric updated: frames_processed = 82
+2025-07-27 01:27:28.589 [DEBUG] Metric updated: bytes_processed = 83968
+2025-07-27 01:27:28.605 [DEBUG] Metric updated: frames_processed = 83
+2025-07-27 01:27:28.605 [DEBUG] Metric updated: bytes_processed = 84992
+2025-07-27 01:27:28.620 [DEBUG] Metric updated: frames_processed = 84
+2025-07-27 01:27:28.620 [DEBUG] Metric updated: bytes_processed = 86016
+2025-07-27 01:27:28.635 [DEBUG] Metric updated: frames_processed = 85
+2025-07-27 01:27:28.635 [DEBUG] Metric updated: bytes_processed = 87040
+2025-07-27 01:27:28.650 [DEBUG] Metric updated: frames_processed = 86
+2025-07-27 01:27:28.650 [DEBUG] Metric updated: bytes_processed = 88064
+2025-07-27 01:27:28.665 [DEBUG] Metric updated: frames_processed = 87
+2025-07-27 01:27:28.665 [DEBUG] Metric updated: bytes_processed = 89088
+2025-07-27 01:27:28.681 [DEBUG] Metric updated: frames_processed = 88
+2025-07-27 01:27:28.681 [DEBUG] Metric updated: bytes_processed = 90112
+2025-07-27 01:27:28.697 [DEBUG] Metric updated: frames_processed = 89
+2025-07-27 01:27:28.697 [DEBUG] Metric updated: bytes_processed = 91136
+2025-07-27 01:27:28.712 [DEBUG] Metric updated: frames_processed = 90
+2025-07-27 01:27:28.712 [DEBUG] Metric updated: bytes_processed = 92160
+2025-07-27 01:27:28.727 [DEBUG] Metric updated: frames_processed = 91
+2025-07-27 01:27:28.727 [DEBUG] Metric updated: bytes_processed = 93184
+2025-07-27 01:27:28.743 [DEBUG] Metric updated: frames_processed = 92
+2025-07-27 01:27:28.743 [DEBUG] Metric updated: bytes_processed = 94208
+2025-07-27 01:27:28.759 [DEBUG] Metric updated: frames_processed = 93
+2025-07-27 01:27:28.759 [DEBUG] Metric updated: bytes_processed = 95232
+2025-07-27 01:27:28.774 [DEBUG] Metric updated: frames_processed = 94
+2025-07-27 01:27:28.774 [DEBUG] Metric updated: bytes_processed = 96256
+2025-07-27 01:27:28.789 [DEBUG] Metric updated: frames_processed = 95
+2025-07-27 01:27:28.789 [DEBUG] Metric updated: bytes_processed = 97280
+2025-07-27 01:27:28.805 [DEBUG] Metric updated: frames_processed = 96
+2025-07-27 01:27:28.805 [DEBUG] Metric updated: bytes_processed = 98304
+2025-07-27 01:27:28.821 [DEBUG] Metric updated: frames_processed = 97
+2025-07-27 01:27:28.821 [DEBUG] Metric updated: bytes_processed = 99328
+2025-07-27 01:27:28.836 [DEBUG] Metric updated: frames_processed = 98
+2025-07-27 01:27:28.836 [DEBUG] Metric updated: bytes_processed = 100352
+2025-07-27 01:27:28.851 [DEBUG] Metric updated: frames_processed = 99
+2025-07-27 01:27:28.851 [DEBUG] Metric updated: bytes_processed = 101376
+2025-07-27 01:27:28.867 [DEBUG] Metric updated: frames_processed = 100
+2025-07-27 01:27:28.867 [DEBUG] Metric updated: bytes_processed = 102400
+2025-07-27 01:27:28.882 [INFO] Performance monitor stopped
+2025-07-27 01:27:28.882 [INFO] 性能统计:
+2025-07-27 01:27:28.882 [INFO]   处理帧数: 100
+2025-07-27 01:27:28.882 [INFO]   处理字节数: 102400
+2025-07-27 01:27:28.883 [INFO] [成功] 性能监控功能测试通过
+2025-07-27 01:27:28.883 [INFO] Performance monitor closed
+2025-07-27 01:27:28.883 [INFO] ✓ 性能监控功能 测试通过
+2025-07-27 01:27:28.883 [INFO] 
+=== 运行测试: 同步器功能 ===
+2025-07-27 01:27:28.883 [INFO] [测试] 同步器功能...
+2025-07-27 01:27:28.883 [DEBUG] Synchronizer created with strategy: 0
+2025-07-27 01:27:28.883 [INFO] 视频延迟: {:.2f} ms
+2025-07-27 01:27:28.883 [INFO] 音频延迟: {:.2f} ms
+2025-07-27 01:27:28.883 [INFO] 音视频同步状态: 不同步
+2025-07-27 01:27:28.884 [INFO] 同步误差: {:.2f} ms
+2025-07-27 01:27:28.884 [INFO] [成功] 同步器功能测试通过
+2025-07-27 01:27:28.884 [INFO] Synchronizer closed
+2025-07-27 01:27:28.884 [DEBUG] Synchronizer destroyed
+2025-07-27 01:27:28.884 [INFO] ✓ 同步器功能 测试通过
+2025-07-27 01:27:28.884 [INFO] 
+=== 运行测试: 线程池工厂功能 ===
+2025-07-27 01:27:28.884 [INFO] [测试] 线程池工厂功能...
+2025-07-27 01:27:28.884 [INFO] Thread pool initialized with 2 min threads, 24 max threads
+2025-07-27 01:27:28.884 [INFO] Thread pool started with 2 threads
+2025-07-27 01:27:28.884 [DEBUG] Worker thread %zu started
+2025-07-27 01:27:28.884 [DEBUG] Worker thread %zu started
+2025-07-27 01:27:28.885 [DEBUG] Worker thread %zu stopped
+2025-07-27 01:27:28.885 [DEBUG] Worker thread %zu stopped
+2025-07-27 01:27:28.885 [INFO] Thread pool stopped
+2025-07-27 01:27:28.885 [INFO] CPU核心数: 24
+2025-07-27 01:27:28.885 [INFO] 推荐线程数: 24
+2025-07-27 01:27:28.885 [INFO] [成功] 线程池工厂功能测试通过
+2025-07-27 01:27:28.885 [INFO] ✓ 线程池工厂功能 测试通过
+2025-07-27 01:27:28.885 [INFO] 
+=== 运行测试: 线程池管理器功能 ===
+2025-07-27 01:27:28.885 [INFO] [测试] 线程池管理器功能...
+2025-07-27 01:27:28.885 [INFO] Thread pool initialized with 2 min threads, 24 max threads
+2025-07-27 01:27:28.885 [INFO] Thread pool started with 2 threads
+2025-07-27 01:27:28.886 [DEBUG] Worker thread %zu started
+2025-07-27 01:27:28.886 [DEBUG] Worker thread %zu started
+2025-07-27 01:27:28.886 [INFO] Thread pool initialized with 2 min threads, 4 max threads
+2025-07-27 01:27:28.886 [INFO] Thread pool started with 2 threads
+2025-07-27 01:27:28.886 [DEBUG] Worker thread %zu started
+2025-07-27 01:27:28.886 [DEBUG] Worker thread %zu started
+2025-07-27 01:27:28.886 [INFO] Created thread pool: test_pool
+2025-07-27 01:27:28.886 [INFO] 线程池数量: 1
+2025-07-27 01:27:28.886 [INFO]   - test_pool
+2025-07-27 01:27:28.886 [INFO] Cleared 0 pending tasks
+2025-07-27 01:27:28.886 [DEBUG] Worker thread %zu stopped
+2025-07-27 01:27:28.886 [DEBUG] Worker thread %zu stopped
+2025-07-27 01:27:28.887 [INFO] Thread pool stopped
+2025-07-27 01:27:28.887 [INFO] Destroyed thread pool: test_pool
+2025-07-27 01:27:28.887 [INFO] [成功] 线程池管理器功能测试通过
+2025-07-27 01:27:28.887 [INFO] ✓ 线程池管理器功能 测试通过
+2025-07-27 01:27:28.887 [INFO] 
+=== 测试结果汇总 ===
+2025-07-27 01:27:28.887 [INFO] 通过测试: 8/8
+2025-07-27 01:27:28.887 [INFO] 成功率: 100%
+2025-07-27 01:27:28.887 [INFO] 所有工具类测试通过
+2025-07-27 01:27:28.887 [INFO] Cleared 0 pending tasks
+2025-07-27 01:27:28.887 [DEBUG] Worker thread %zu stopped
+2025-07-27 01:27:28.888 [DEBUG] Worker thread %zu stopped
+2025-07-27 01:27:28.888 [INFO] Thread pool stopped
+2025-07-27 01:27:28.888 [INFO] All thread pools shutdown

+ 18 - 56
AV/xmake.lua

@@ -111,6 +111,24 @@ target("av_utils")
 --     add_deps("av_base", "av_codec", "av_capture", "av_muxer", "av_utils")
 --     add_includedirs(".", {public = true})
 
+target("player")
+    set_kind("binary")
+    add_rules("qt.static")
+    set_runtimes("MT")
+    add_files("integration_example.cpp", {rules = "qt.moc"})
+    add_deps("av_base", "av_codec", "av_capture", "av_muxer", "av_utils")
+    add_includedirs(".", {public = true})
+    add_files("code/player/*.cpp", {rules = "qt.moc"})
+    add_headerfiles("code/player/*.h", {rules = "qt.moc"})
+    add_frameworks("QtNetwork", "QtGui", "QtCore", "QtWidgets", "QtMultimedia")
+        -- FFmpeg库链接
+    if is_plat("windows") then
+        add_includedirs("E:/AAA/ffmpeg-7.0.2-full_build-shared/include")
+        add_linkdirs("E:/AAA/ffmpeg-7.0.2-full_build-shared/lib")
+        add_links("avcodec", "avformat", "avutil", "swscale", "swresample")
+        add_links("avdevice", "avfilter", "postproc")
+    end
+
 -- 基础测试程序
 target("test_basic")
     set_kind("binary")
@@ -156,34 +174,6 @@ target("test_decoder")
         add_links("avdevice", "avfilter", "postproc")
     end
     
-    -- Windows下复制FFmpeg DLL
-    if is_plat("windows") then
-        after_build(function (target)
-            local ffmpeg_bin = "E:/AAA/ffmpeg-7.0.2-full_build-shared/bin"
-            local target_dir = target:targetdir()
-            
-            -- 复制FFmpeg DLL文件
-            local dlls = {
-                "avcodec-60.dll",
-                "avformat-60.dll", 
-                "avutil-58.dll",
-                "swscale-7.dll",
-                "swresample-4.dll",
-                "avdevice-60.dll",
-                "avfilter-9.dll",
-                "postproc-57.dll"
-            }
-            
-            for _, dll in ipairs(dlls) do
-                local src = path.join(ffmpeg_bin, dll)
-                local dst = path.join(target_dir, dll)
-                if os.exists(src) then
-                    os.cp(src, dst)
-                    print("Copied: " .. dll)
-                end
-            end
-        end)
-    end
 
 -- 音频编码器测试程序
 target("test_audio_encoder")
@@ -200,34 +190,6 @@ target("test_audio_encoder")
         add_links("avdevice", "avfilter", "postproc")
     end
     
-    -- Windows下复制FFmpeg DLL
-    if is_plat("windows") then
-        after_build(function (target)
-            local ffmpeg_bin = "E:/AAA/ffmpeg-7.0.2-full_build-shared/bin"
-            local target_dir = target:targetdir()
-            
-            -- 复制FFmpeg DLL文件
-            local dlls = {
-                "avcodec-60.dll",
-                "avformat-60.dll", 
-                "avutil-58.dll",
-                "swscale-7.dll",
-                "swresample-4.dll",
-                "avdevice-60.dll",
-                "avfilter-9.dll",
-                "postproc-57.dll"
-            }
-            
-            for _, dll in ipairs(dlls) do
-                local src = path.join(ffmpeg_bin, dll)
-                local dst = path.join(target_dir, dll)
-                if os.exists(src) then
-                    os.cp(src, dst)
-                    print("Copied: " .. dll)
-                end
-            end
-        end)
-    end
 
 -- 窗口采集测试程序
 target("test_window_capture")

+ 69 - 13
AV_REFACTOR_PLAN.md

@@ -219,19 +219,75 @@ public:
 - [x] 编解码测试程序 (`test_codec.cpp`)
 - [x] CMake构建系统配置
 
-### 第三阶段:解码器模块 🔄
-- [ ] 视频解码器实现
-- [ ] 音频解码器实现
-- [ ] 解码器测试程序
-
-### 第四阶段:采集和复用模块 ⏳
-- [ ] 视频采集模块
-- [ ] 音频采集模块
-- [ ] 媒体复用器模块
-- [ ] 流媒体支持
-
-### 第五阶段:项目整合和优化 ⏳
-- [ ] 原项目迁移适配
+### 第三阶段:解码器模块 ✅
+- [x] 视频解码器实现 (`codec_video_decoder.h/cpp`)
+  - [x] 硬件加速支持检测
+  - [x] 多种视频格式支持 (H.264, H.265, VP8, VP9等)
+  - [x] 像素格式转换
+  - [x] 低延迟模式
+  - [x] 统计信息收集
+- [x] 音频解码器实现 (`codec_audio_decoder.h/cpp`)
+  - [x] 音频重采样支持
+  - [x] 多种音频格式支持 (AAC, MP3, Opus, FLAC等)
+  - [x] 声道布局处理
+  - [x] 采样率转换
+- [x] 解码器测试程序 (`test_decoder.cpp`)
+
+### 第四阶段:采集和复用模块 ✅
+- [x] 视频采集模块 (`capture_video_capturer.h/cpp`)
+  - [x] 屏幕采集支持
+  - [x] 窗口采集支持
+  - [x] 摄像头采集支持
+- [x] 音频采集模块 (`capture_audio_capturer.h/cpp`)
+  - [x] 系统音频采集
+  - [x] 麦克风采集
+  - [x] 音频混合支持
+- [x] 媒体复用器模块 (`muxer_*.h/cpp`)
+  - [x] 文件复用器 (MP4, AVI, MKV等)
+  - [x] 流媒体复用器 (RTMP, HLS等)
+  - [x] 分段录制支持
+- [x] 工具类模块 (`utils_*.h/cpp`)
+  - [x] 帧队列管理
+  - [x] 数据包队列管理
+  - [x] 同步辅助类
+  - [x] 性能监控
+  - [x] 线程池管理
+
+### 第五阶段:播放器核心模块 ✅
+- [x] 播放器核心类实现 (`player_core.h/cpp`)
+  - [x] 媒体文件打开和解析
+  - [x] 播放控制接口 (播放、暂停、停止、跳转)
+  - [x] 音视频同步
+  - [x] 播放速度控制
+  - [x] 音量控制
+  - [x] 播放状态管理
+  - [x] 事件回调机制
+- [x] 队列管理模块 (`queue_manager.h/cpp`)
+  - [x] 数据包队列 (PacketQueue)
+  - [x] 帧队列 (FrameQueue)
+  - [x] 音视频同步器 (Synchronizer)
+  - [x] 线程安全设计
+- [x] 线程管理模块 (`thread_manager.h/cpp`)
+  - [x] 读取线程 (ReadThread)
+  - [x] 视频解码线程 (VideoDecodeThread)
+  - [x] 音频解码线程 (AudioDecodeThread)
+  - [x] 线程管理器 (ThreadManager)
+- [x] Qt集成适配器 (`player_adapter.h/cpp`)
+  - [x] PlayerAdapter类设计和实现
+  - [x] Qt信号槽接口
+  - [x] 线程安全的事件回调
+  - [x] PlayerAdapterFactory工厂类
+- [x] 播放器测试程序 (`test_player.cpp`)
+- [x] 集成示例和文档
+  - [x] integration_example.cpp集成示例
+  - [x] INTEGRATION_GUIDE.md集成指南
+  - [x] API对比和迁移指南
+  - [x] 完整的UI示例实现
+- [x] CMake构建系统配置
+
+### 第六阶段:项目整合和优化 🔄
+- [ ] AVPlayer2重构 (使用新的核心库)
+- [ ] AvRecorder重构 (使用新的核心库)
 - [ ] 性能优化
 - [ ] 文档完善
 - [ ] 单元测试

+ 1 - 0
xmake.lua

@@ -0,0 +1 @@
+includes("AV")

Неке датотеке нису приказане због велике количине промена