From 9f0a10a4c84aa0c29047666acd316b4a811cc8c8 Mon Sep 17 00:00:00 2001 From: Tuan Nghia Nguyen Date: Mon, 20 Apr 2026 12:18:43 +1000 Subject: [PATCH] =?UTF-8?q?Improve=20ANSCV=20with=20sotfware=20decoder:=20?= =?UTF-8?q?Thread-local=20staging=20Mat=20(video=5Fplayer.cpp:1400-1407)?= =?UTF-8?q?=20=E2=80=94=20single=20biggest=20win.=20Eliminates=20the=2012?= =?UTF-8?q?=20MB=20per-call=20malloc/free=20cycle.=20Contiguous=20get=5Fbu?= =?UTF-8?q?ffer2=20allocator=20(video=5Fdecoder.cpp:35-102)=20=E2=80=94=20?= =?UTF-8?q?keeps=20the=203=20bulk=20memcpys=20cache-friendly.=20Would=20al?= =?UTF-8?q?so=20enable=20FAST/zero-copy=20for=20resolutions=20where=20visi?= =?UTF-8?q?ble=5Fh=20%=2064=20=3D=3D=200.=20SW-decoder=20thread=20config?= =?UTF-8?q?=20(video=5Fdecoder.cpp:528-540)=20=E2=80=94=20thread=5Fcount?= =?UTF-8?q?=3D0,=20thread=5Ftype=3DFRAME|SLICE.=20FRAME=20is=20downgraded?= =?UTF-8?q?=20to=20SLICE-only=20by=20AV=5FCODEC=5FFLAG=5FLOW=5FDELAY,=20bu?= =?UTF-8?q?t=20decode=20throughput=20is=20sufficient=20for=20your=20input?= =?UTF-8?q?=20rate.=20SetTargetFPS(100)=20delivery=20throttle=20(already?= =?UTF-8?q?=20there)=20=E2=80=94=20caps=20onVideoFrame=20post-decode=20wor?= =?UTF-8?q?k=20at=2010=20FPS.=20Keeps=20the=20caller=20path=20warm-cached.?= =?UTF-8?q?=20Instrumentation=20=E2=80=94=20[MEDIA=5FDecInit]=20/=20[MEDIA?= =?UTF-8?q?=5FConvert]=20/=20[MEDIA=5FSWDec]=20/=20[MEDIA=5FTiming]=20/=20?= =?UTF-8?q?[MEDIA=5FJpegTiming]=20=E2=80=94=20always-on=20regression=20det?= =?UTF-8?q?ector,=20zero=20cost=20when=20ANSCORE=5FDEBUGVIEW=3DOFF.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .claude/settings.local.json | 189 +---------------------- .gitmodules | 3 + 3rdparty/libyuv | 1 + CMakeLists.txt | 41 ++++- MediaClient/media/video_decoder.cpp | 136 ++++++++++++++++ MediaClient/media/video_decoder.h | 9 ++ MediaClient/media/video_player.cpp | 196 +++++++++++++++++++++++- build_anscv_unittest.bat | 6 + build_ansutil.bat | 6 + build_ansutil_test.bat | 5 + core/ANSLicensingSystem/ANSLicense.h | 16 +- modules/ANSCV/CMakeLists.txt | 9 ++ tests/ANSCV-UnitTest/ANSCV-UnitTest.cpp | 15 +- 13 files changed, 431 insertions(+), 201 deletions(-) create mode 100644 .gitmodules create mode 160000 3rdparty/libyuv create mode 100644 build_anscv_unittest.bat create mode 100644 build_ansutil.bat create mode 100644 build_ansutil_test.bat diff --git a/.claude/settings.local.json b/.claude/settings.local.json index eb1bae1..1bef8a6 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -1,194 +1,7 @@ { "permissions": { "allow": [ - "Bash(find C:ProjectsCLionProjectsANSCORE -type f \\\\\\(-name *.h -o -name *.hpp -o -name *.cpp -o -name *.cc \\\\\\))", - "Bash(xargs grep:*)", - "Bash(grep -n \"~Engine\\\\|TRTEngineCache::release\\\\|EnginePoolManager::release\\\\|destructor\" /c/Projects/CLionProjects/ANSCORE/engines/TensorRTAPI/include/engine/*.inl /c/Projects/CLionProjects/ANSCORE/modules/ANSODEngine/*.h)", - "Bash(grep -l \"EnginePoolManager\" /c/Projects/CLionProjects/ANSCORE/modules/ANSODEngine/*.cpp)", - "Bash(grep -n \"g_processExiting\" /c/Projects/CLionProjects/ANSCORE/engines/TensorRTAPI/include/engine/*.h /c/Projects/CLionProjects/ANSCORE/modules/ANSODEngine/engine.h)", - "Bash(ssh -T git@anscenter.ddns.net -p 2222)", - "Bash(ssh-add -l)", - "Bash(dotnet build:*)", - "Bash(grep -n \"struct Object\\\\|class Object\" /c/Projects/CLionProjects/ANSCORE/modules/ANSLPR/*.h /c/Projects/CLionProjects/ANSCORE/modules/ANSLPR/include/*.h)", - "Bash(grep -n \"cudaStream\\\\|cudaMalloc\\\\|cudaFree\\\\|queue\\\\|Task\\\\|mutex\" /c/Projects/CLionProjects/ANSCORE/engines/TensorRTAPI/include/engine/*.inl)", - "Bash(grep -n \"~Engine\\\\|destructor\\\\|cleanup\\\\|~\" /c/Projects/CLionProjects/ANSCORE/engines/TensorRTAPI/include/engine/*.inl)", - "Bash(grep -n \"for.*cudaFree\\\\|m_buffers\\\\[\" /c/Projects/CLionProjects/ANSCORE/engines/TensorRTAPI/include/engine/*.inl)", - "Bash(find /c/Projects/CLionProjects/ANSCORE -name ANSGpuFrameRegistry* -type f)", - "Bash(ls -la /c/Projects/CLionProjects/ANSCORE/modules/ANSLPR/*.h)", - "Bash(\"C:\\\\Users\\\\nghia\\\\AppData\\\\Local\\\\Programs\\\\CLion 2026.1\\\\bin\\\\cmake\\\\win\\\\x64\\\\bin\\\\cmake.exe\" --build cmake-build-release --target all -j 30)", - "Bash(cmake --build build --target ANSLPR-UnitTest --config Release)", - "Bash(ls -d C:/Projects/CLionProjects/ANSCORE/cmake-build-*)", - "Bash(ls -d C:/Projects/CLionProjects/ANSCORE/out/*)", - "Bash(cmake --build C:/Projects/CLionProjects/ANSCORE/cmake-build-release --target ANSLPR-UnitTest --config Release)", - "Bash(cmake --build C:/Projects/CLionProjects/ANSCORE/cmake-build-release --target ANSLPR-UnitTest)", - "Bash('C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/Tools/VsDevCmd.bat' -arch=amd64)", - "Bash(cmake -B C:/Projects/CLionProjects/ANSCORE/cmake-build-release -S C:/Projects/CLionProjects/ANSCORE -G Ninja -DCMAKE_BUILD_TYPE=Release)", - "Bash(cmd //C \"call \"\"C:\\\\Program Files\\\\Microsoft Visual Studio\\\\2022\\\\Community\\\\VC\\\\Auxiliary\\\\Build\\\\vcvarsall.bat\"\" amd64 >nul 2>&1 && cmake --build C:\\\\Projects\\\\CLionProjects\\\\ANSCORE\\\\cmake-build-release --target ANSLPR-UnitTest\")", - "Bash(1 EOF cmd /C C:tmpbuild.bat)", - "Read(//tmp/**)", - "Bash(\"C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Auxiliary/Build/vcvarsall.bat\" amd64)", - "Bash(export INCLUDE=\"C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.44.35207/include;C:/Program Files \\(x86\\)/Windows Kits/10/Include/10.0.26100.0/ucrt;C:/Program Files \\(x86\\)/Windows Kits/10/Include/10.0.26100.0/um;C:/Program Files \\(x86\\)/Windows Kits/10/Include/10.0.26100.0/shared;C:/Program Files \\(x86\\)/Windows Kits/10/Include/10.0.26100.0/winrt;C:/Program Files \\(x86\\)/Windows Kits/10/Include/10.0.26100.0/cppwinrt\" export LIB=\"C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.44.35207/lib/x64;C:/Program Files \\(x86\\)/Windows Kits/10/Lib/10.0.26100.0/ucrt/x64;C:/Program Files \\(x86\\)/Windows Kits/10/Lib/10.0.26100.0/um/x64\" cmake --build \"C:/Projects/CLionProjects/ANSCORE/cmake-build-release\" --target ANSLPR-UnitTest)", - "Bash(tasklist)", - "Bash(taskkill /F /IM ANSLPR-UnitTest.exe)", - "Bash(export \"INCLUDE=C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.44.35207/include;C:/Program Files \\(x86\\)/Windows Kits/10/Include/10.0.26100.0/ucrt;C:/Program Files \\(x86\\)/Windows Kits/10/Include/10.0.26100.0/um;C:/Program Files \\(x86\\)/Windows Kits/10/Include/10.0.26100.0/shared;C:/Program Files \\(x86\\)/Windows Kits/10/Include/10.0.26100.0/winrt;C:/Program Files \\(x86\\)/Windows Kits/10/Include/10.0.26100.0/cppwinrt\")", - "Bash(export \"LIB=C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.44.35207/lib/x64;C:/Program Files \\(x86\\)/Windows Kits/10/Lib/10.0.26100.0/ucrt/x64;C:/Program Files \\(x86\\)/Windows Kits/10/Lib/10.0.26100.0/um/x64\")", - "Bash(grep -E \"\\\\.\\(cpp|h|hpp\\)$\")", - "Bash(find /c/Projects/CLionProjects/ANSCORE -name *Logger* -type f)", - "Bash(find /c/Projects/CLionProjects/ANSCORE -name *SPDLogger* -o -name *ANSLogger*)", - "Read(//c/Users/nghia/Downloads/**)", - "Bash(find C:ProjectsCLionProjectsANSCORE -name *NV12* -type f)", - "Bash(find C:ProjectsCLionProjectsANSCORE -name *GpuFrame* -type f)", - "mcp__desktop-commander__get_file_info", - "mcp__desktop-commander__interact_with_process", - "Bash(sort -t= -k2 -rn)", - "Bash(sort -t= -k3 -rn)", - "Bash(powershell -Command \"Get-Content ''C:\\\\Users\\\\nghia\\\\Downloads\\\\logdebug.txt'' | Select-Object -Last 30\")", - "Bash(powershell -Command \"\\(Select-String -Path ''C:\\\\Users\\\\nghia\\\\Downloads\\\\logdebug.txt'' -Pattern ''POOL FULL''\\).Count\")", - "Bash(powershell -Command \"\\(Select-String -Path ''C:\\\\Users\\\\nghia\\\\Downloads\\\\logdebug.txt'' -Pattern ''Cam\\(\\\\d+\\)'' -AllMatches | ForEach-Object { $_Matches } | ForEach-Object { $_Groups[1].Value } | Sort-Object -Unique\\)\")", - "Bash(powershell -Command \"Select-String -Path ''C:\\\\Users\\\\nghia\\\\Downloads\\\\logdebug.txt'' -Pattern ''Cam\\(\\\\d+\\)'' -AllMatches | ForEach-Object { $_Matches[0].Groups[1].Value } | Sort-Object | Get-Unique\")", - "Bash(powershell -Command \"$lines = Get-Content ''C:\\\\Users\\\\nghia\\\\Downloads\\\\logdebug.txt''; $first = \\($lines | Select-String ''07:1'' | Select-Object -First 1\\).Line; $last = \\($lines | Select-String ''07:1'' | Select-Object -Last 1\\).Line; Write-Host ''First: '' $first; Write-Host ''Last: '' $last; Write-Host ''Total lines: '' $lines.Count\")", - "Bash(powershell -Command \"$c = \\(Get-Content ''C:\\\\Users\\\\nghia\\\\Downloads\\\\logdebug.txt''\\).Count; Write-Host ''Total lines:'' $c\")", - "Bash(powershell -Command \"\\(Get-Content ''C:\\\\Users\\\\nghia\\\\Downloads\\\\logdebug1.txt''\\).Count\")", - "Bash(powershell -Command \"\\(Get-Content ''C:\\\\Users\\\\nghia\\\\Downloads\\\\ANSLEGION20.log''\\).Count\")", - "Bash(powershell -Command \"\\(Get-Content ''C:\\\\Users\\\\nghia\\\\Downloads\\\\ANSLEGION21.log''\\).Count\")", - "Bash(powershell -Command \"Select-String ''NEW slot'' ''C:\\\\Users\\\\nghia\\\\Downloads\\\\ANSLEGION22.log'' | ForEach-Object { if \\($_-match ''\\(\\\\d+x\\\\d+\\)''\\) { $matches[1] } } | Group-Object | Sort-Object Count -Descending | Format-Table Name, Count\")", - "Bash(ls -la /c/Projects/CLionProjects/ANSCORE/modules/ANSODEngine/*.cpp /c/Projects/CLionProjects/ANSCORE/modules/ANSODEngine/*.h)", - "Bash(grep -r \"cudaMalloc\\\\|cudaFree\\\\|cudaStreamCreate\\\\|cudaStreamDestroy\" /c/Projects/CLionProjects/ANSCORE/modules/ANSODEngine/*.cpp)", - "Bash(grep -n \"cudaStreamCreate\\\\|cudaEventCreate\\\\|cudaEventDestroy\\\\|cudaStreamDestroy\\\\|cudaStreamSynchronize\" /c/Projects/CLionProjects/ANSCORE/engines/TensorRTAPI/include/engine/*.inl)", - "Bash(dir \"C:\\\\Projects\\\\CLionProjects\\\\ANSCORE\\\\engines\\\\TensorRTAPI\\\\include\\\\engine\\\\*.h\" /b)", - "Bash(powershell -Command \"\\(Get-Content ''C:\\\\Users\\\\nghia\\\\Downloads\\\\ANSLEGION26.log''\\).Count\")", - "Bash(powershell -Command \"\\(Get-Content ''C:\\\\Users\\\\nghia\\\\Downloads\\\\ANSLEGION27.log''\\).Count\")", - "Bash(powershell -Command \"\\(Get-Content ''C:\\\\Users\\\\nghia\\\\Downloads\\\\ANSLEGION28.log''\\).Count\")", - "Bash(powershell -Command \"\\(Get-Content ''C:\\\\Users\\\\nghia\\\\Downloads\\\\ANSLEGION29.log''\\).Count\")", - "Bash(powershell -Command \"\\(Get-Content ''C:\\\\Users\\\\nghia\\\\Downloads\\\\ANSLEGION30.log''\\).Count\")", - "Bash(powershell -Command \"\\(Get-Content ''C:\\\\Users\\\\nghia\\\\Downloads\\\\logging4.txt''\\).Count\")", - "Bash(powershell -Command \"\\(Get-Content ''C:\\\\Users\\\\nghia\\\\Downloads\\\\ANSLEGION31.log''\\).Count\")", - "Bash(powershell -Command \"\\(Get-Content ''C:\\\\Users\\\\nghia\\\\Downloads\\\\loging5.txt''\\).Count\")", - "Bash(powershell -Command \"\\(Get-Content ''C:\\\\Users\\\\nghia\\\\Downloads\\\\ANSLEGION32.log''\\).Count\")", - "Bash(powershell -Command \"\\(Get-Content ''C:\\\\Users\\\\nghia\\\\Downloads\\\\ANSLEGION33.log''\\).Count\")", - "Bash(powershell -Command \"\\(Get-Content ''C:\\\\Users\\\\nghia\\\\Downloads\\\\ANSLEGION34.log''\\).Count\")", - "Bash(powershell -Command \"\\(Get-Content ''C:\\\\Users\\\\nghia\\\\Downloads\\\\ANSLEGION35.log''\\).Count\")", - "Bash(powershell -Command \"\\(Get-Content ''C:\\\\Users\\\\nghia\\\\Downloads\\\\ANSLEGION36.log''\\).Count\")", - "Bash(powershell -Command \"\\(Get-Content ''C:\\\\Users\\\\nghia\\\\Downloads\\\\ANSLEGION37.log''\\).Count\")", - "Bash(powershell -Command \"\\(Get-Content ''C:\\\\Users\\\\nghia\\\\Downloads\\\\ANSLEGION38.log''\\).Count\")", - "Bash(powershell -Command \"\\(Get-Content ''C:\\\\Users\\\\nghia\\\\Downloads\\\\ANSLEGION39.log''\\).Count\")", - "Bash(powershell -Command \"\\(Get-Content ''C:\\\\Users\\\\nghia\\\\Downloads\\\\ANSLEGION40.log''\\).Count\")", - "Bash(python -c \":*)", - "Bash(find /c/Projects/CLionProjects/ANSCORE -type d -name *ANSODEngine*)", - "Bash(powershell -Command \"\\(Get-Content ''C:\\\\Users\\\\nghia\\\\Downloads\\\\ANSLEGION41.log''\\).Count\")", - "Bash(powershell -Command \"\\(Get-Content ''C:\\\\Users\\\\nghia\\\\Downloads\\\\ANSLEGION42.log''\\).Count\")", - "Bash(grep -rn \"ApplyTracking\\\\|_trackerEnabled\" /c/Projects/CLionProjects/ANSCORE/modules/ANSODEngine/*.cpp)", - "Bash(cmake --build build --target ANSUtilities)", - "Bash(ls -d /c/Projects/CLionProjects/ANSCORE/cmake-build-* /c/Projects/CLionProjects/ANSCORE/out/*)", - "Bash(cmake --build /c/Projects/CLionProjects/ANSCORE/cmake-build-release --target ANSUtilities)", - "Bash(find /c/Projects/CLionProjects/ANSCORE -name *json* -o -name *Json*)", - "Bash(grep -n \"CreateANSALPRHandle\\\\|LoadANSALPREngineHandle\\\\|CreateANSRTSPHandle\\\\|ReleaseANSALPRHandle\\\\|ANSALPR_RunInference\" C:ProjectsCLionProjectsANSCOREsrc*)", - "Bash(find C:ProjectsCLionProjectsANSCORE -name ANSLibsLoader* -type f)", - "Bash(find \"/c/Projects/CLionProjects/ANSCORE\" -type f \\\\\\( -name \"*.cpp\" -o -name \"*.h\" \\\\\\) -exec grep -l \"DML\\\\|DirectML\" {} \\\\;)", - "Read(//c/ANSLibs/onnxruntime/lib//**)", - "Read(//c/ANSLibs/onnxruntime/include//**)", - "Read(//c/ANSLibs/onnxruntime/lib/**)", - "Read(//c/ANSLibs/onnxruntime/**)", - "Bash(python -c ':*)", - "Bash(grep -oE \"WATCHDOG-[0-9-]+\\\\.dmp|Minidump\\\\\\\\\\\\\\\\[0-9-]+\\\\.dmp\" \"C:\\\\Users\\\\nghia\\\\Downloads\\\\AMDeventlog3.xml\")", - "Bash(grep -oE \"\\\\\\\\\\\\\\\\Minidump\\\\\\\\\\\\\\\\[^<]+\\\\.dmp\" \"C:\\\\Users\\\\nghia\\\\Downloads\\\\AMDeventlog3.xml\")", - "mcp__desktop-commander__start_search", - "mcp__desktop-commander__get_more_search_results", - "mcp__desktop-commander__list_searches", - "Bash(grep -oE \"Faulting[^<]{1,500}|APPLICATION CRASHING[^<]{1,300}|EventID[^>]*>1000[^<]*|ExceptionCode[^<]{1,100}|onnxruntime[^<]{1,300}\" \"C:\\\\Users\\\\nghia\\\\Downloads\\\\Evenlog.xml\")", - "mcp__desktop-commander__start_process", - "Bash(grep -oE \"Faulting[^<]{1,600}|ExceptionCode[^<]{1,100}|FaultingOffset[^<]{1,60}|FaultingModule[^<]{1,200}\" \"C:\\\\Users\\\\nghia\\\\Downloads\\\\Evenlog2.xml\")", - "Bash(grep -aoE \"Faulting[^<]{1,600}\" \"C:\\\\Users\\\\nghia\\\\Downloads\\\\Evenlog2.xml\")", - "Bash(where python:*)", - "Bash(grep -aoE \"Faulting[^<]{1,700}|ExceptionCode'[^<]{1,60}|FaultingOffset'[^<]{1,60}\" 'C:/Users/nghia/Downloads/Evenlog3.xml')", - "Bash(ls modules/ANSLPR/*.cpp modules/ANSLPR/*.h)", - "Bash(grep -l \"ANSALPR_RT\\\\|ANSALPR_OV\" modules/ANSLPR/*.vcxproj)", - "Bash(grep -l \"anscv_vendor_gate::IsNvidiaGpuAvailable\\\\|ANSCVVendorGate.h\" modules/ANSCV/*.cpp modules/ANSCV/*.h)", - "Bash(grep -l \"CUDA_V2\\\\|CUDAExecutionProvider\" modules/ANSODEngine/*.cpp)", - "Bash(python3 -c \"x=3522082959360; print\\('bytes:', x\\); print\\('/3:', x//3\\); print\\('sqrt\\(x/3\\):', int\\(\\(x//3\\)**0.5\\)\\); print\\('/\\(640*3\\):', x//\\(640*3\\)\\); print\\('/\\(640*640*3\\):', x//\\(640*640*3\\)\\); print\\('hex:', hex\\(x\\)\\)\")", - "Bash(grep -rn \"catch.*cv::Exception\" modules/ANSODEngine/*.cpp)", - "Bash(grep -l \"ANS_DBG\" modules/ANSLPR/*.cpp modules/ANSCV/*.cpp modules/ANSODEngine/*.cpp)", - "Bash(grep -h \"ANS_DBG\\(\\\\\"\" modules/ANSLPR/*.cpp modules/ANSCV/ANSRTSP.cpp modules/ANSODEngine/ANSONNXYOLO.cpp modules/ANSODEngine/ANSRTYOLO.cpp modules/ANSODEngine/NV12PreprocessHelper.cpp)", - "Bash(grep -v \"DNError\\\\|ViewerConfigPath\\\\|Failed to get\\\\|RecursiveDirectory\\\\|qt.qpa\\\\|DispBroker\\\\|SyncInvokeTable\\\\|Created new AppDomain\\\\|Destroying AppDomain\\\\|Trace Start\\\\|ExpandNode\\\\|PublisherMetadata\\\\|at System\\\\.\\\\|at NationalInstruments\\\\|at Mscorlib\\\\|Parameter name\\\\|^[[:space:]]*$\\\\|ArgumentException\\\\|Wrong type\\\\|Concerning target\\\\|Unable to get\\\\|RenderEventToBuffer\\\\|Getting next\\\\|Fetching Next\\\\|Image.Dispose\\\\|Graphics.Dispose\\\\|Image.FromStream\\\\|Inner Exception\\\\|FontFamily\\\\|InitHash\\\\|get_Item\\\\|MethodHandle.InvokeMethod\\\\|RuntimeMethodInfo\\\\|TargetInvocationException\\\\|Hashtable\\\\|LookupControl\\\\|RemoveControl\\\\|CloseInstance\\\\|FreeInstance\\\\|CrossDomainServer\" \"C:/Users/nghia/Downloads/AVNET-8845HS1.log\")", - "Bash(grep -E \"\\\\.\\(h|cpp\\)$\")", - "WebSearch", - "WebFetch(domain:forums.ni.com)", - "WebFetch(domain:www.ni.com)", - "WebFetch(domain:lavag.org)", - "Read(//c/ProgramData/**)", - "Read(//c/Users/nghia/**)", - "Bash(dir /s /b \"C:\\\\Program Files\\\\National Instruments\\\\*NIImage*\" \"C:\\\\Program Files\\\\National Instruments\\\\*OpenCV*\")", - "Bash(dir /s /b \"C:\\\\Program Files \\(x86\\)\\\\National Instruments\\\\Vision\\\\*OpenCV*\")", - "Bash(dir /s /b \"C:\\\\Program Files \\(x86\\)\\\\National Instruments\\\\Vision\\\\Help\\\\*\")", - "Bash(findstr /i \"opencv\")", - "WebFetch(domain:documentation.help)", - "Bash(python /tmp/apply_guards.py)", - "Bash(python /tmp/apply_all_guards.py)", - "Bash(python /tmp/cleanup_redundant_checks.py)", - "Bash(python /tmp/final_cleanup.py)", - "Bash(grep -n \"ANSFRBase\" /c/Projects/CLionProjects/ANSCORE/modules/ANSODEngine/*.h /c/Projects/CLionProjects/ANSCORE/modules/ANSODEngine/*.cpp)", - "Bash(grep -n \"class.*public ANSFRBase\\\\|class.*: public ANSFRBase\" /c/Projects/CLionProjects/ANSCORE/modules/ANSODEngine/*.h)", - "Bash(grep -n \"class.*public.*FaceDetector\\\\|class.*public ANSFDBase\\\\|struct.*public\" /c/Projects/CLionProjects/ANSCORE/modules/ANSODEngine/*.h)", - "Bash(grep -l \"ANSFRBase\" /c/Projects/CLionProjects/ANSCORE/modules/ANSODEngine/*.h)", - "Bash(grep -rn \"public ANSFRBase\" /c/Projects/CLionProjects/ANSCORE/modules/ANSODEngine/*.h)", - "Bash(python /tmp/apply_fd_guards.py)", - "Bash(python /tmp/apply_fd_precheck.py)", - "Bash(ls /c/Projects/CLionProjects/ANSCORE/modules/ANSFR/*.cpp /c/Projects/CLionProjects/ANSCORE/modules/ANSFR/*.h)", - "Bash(grep -rn \"lock_guard.*_mutex\\\\|lock_guard.*mutex\" /c/Projects/CLionProjects/ANSCORE/modules/ANSFR/*.cpp)", - "Bash(grep -l \"TensorRT\\\\|tensorrt_provider_factory\\\\|OrtTensorRTProviderOptionsV2\\\\|CreateTensorRTProviderOptions\\\\|UpdateTensorRTProviderOptions\" \"C:/ANSLibs/onnxruntime/include/\"*.h)", - "Bash(cmake --build . --target ONNXEngine ANSOCR ANSLPR ANSLPR-UnitTest --config Release -- -j 4)", - "Bash(cmake --build . --target help)", - "Bash(cmake --build . --target ANSLPR-UnitTest)", - "Bash(cmd.exe /c \"call \\\\\"C:\\\\\\\\Program Files\\\\\\\\Microsoft Visual Studio\\\\\\\\2022\\\\\\\\Community\\\\\\\\VC\\\\\\\\Auxiliary\\\\\\\\Build\\\\\\\\vcvars64.bat\\\\\" >nul 2>&1 && cmake --build . --target ANSLPR-UnitTest 2>&1\")", - "Bash(cmd.exe //c \"cd /d C:\\\\\\\\Projects\\\\\\\\CLionProjects\\\\\\\\ANSCORE\\\\\\\\cmake-build-release && call \\\\\"C:\\\\\\\\Program Files\\\\\\\\Microsoft Visual Studio\\\\\\\\2022\\\\\\\\Community\\\\\\\\VC\\\\\\\\Auxiliary\\\\\\\\Build\\\\\\\\vcvars64.bat\\\\\" && cmake --build . --target ANSLPR-UnitTest\")", - "Bash(cmd.exe //c \"C:\\\\\\\\Projects\\\\\\\\CLionProjects\\\\\\\\ANSCORE\\\\\\\\cmake-build-release\\\\\\\\__build_check.bat\")", - "Bash(cmd.exe //c \"tasklist\")", - "Bash(cmd.exe //c \"taskkill /F /PID 45704\")", - "Bash(ls CMakeLists.txt cmake-build-* build)", - "Bash(cmake --build . --target ANSOCR)", - "Bash(cmd.exe /c '\"C:\\\\Program Files\\\\Microsoft Visual Studio\\\\2022\\\\Community\\\\VC\\\\Auxiliary\\\\Build\\\\vcvars64.bat\" >nul 2>&1 && cd cmake-build-release && cmake --build . --target ANSOCR 2>&1')", - "Bash(cmd.exe /c 'call \"C:\\\\Program Files\\\\Microsoft Visual Studio\\\\2022\\\\Community\\\\VC\\\\Auxiliary\\\\Build\\\\vcvars64.bat\" && cd cmake-build-release && cmake --build . --target ANSOCR 2>&1')", - "Bash(powershell -Command '& { & '\\\\''C:\\\\Program Files\\\\Microsoft Visual Studio\\\\2022\\\\Community\\\\Common7\\\\Tools\\\\Launch-VsDevShell.ps1'\\\\'' -Arch amd64 -HostArch amd64 > $null 2>&1; Set-Location '\\\\''C:\\\\Projects\\\\CLionProjects\\\\ANSCORE\\\\cmake-build-release'\\\\''; cmake --build . --target ANSOCR 2>&1 | Select-Object -Last 60 }')", - "Bash(powershell -Command '& { & '\\\\''C:\\\\Program Files\\\\Microsoft Visual Studio\\\\2022\\\\Community\\\\Common7\\\\Tools\\\\Launch-VsDevShell.ps1'\\\\'' -Arch amd64 -HostArch amd64 > $null 2>&1; Set-Location '\\\\''C:\\\\Projects\\\\CLionProjects\\\\ANSCORE\\\\cmake-build-release'\\\\''; cmake --build . --target ANSLPR 2>&1 | Select-Object -Last 40 }')", - "Bash(powershell -Command '& { & '\\\\''C:\\\\Program Files\\\\Microsoft Visual Studio\\\\2022\\\\Community\\\\Common7\\\\Tools\\\\Launch-VsDevShell.ps1'\\\\'' -Arch amd64 -HostArch amd64 > $null 2>&1; Set-Location '\\\\''C:\\\\Projects\\\\CLionProjects\\\\ANSCORE\\\\cmake-build-release'\\\\''; cmake --build . --target ANSLPR 2>&1 | Select-Object -Last 30 }')", - "Bash(powershell -Command '& { & '\\\\''C:\\\\Program Files\\\\Microsoft Visual Studio\\\\2022\\\\Community\\\\Common7\\\\Tools\\\\Launch-VsDevShell.ps1'\\\\'' -Arch amd64 -HostArch amd64 > $null 2>&1; dumpbin /exports '\\\\''C:\\\\Projects\\\\CLionProjects\\\\ANSCORE\\\\cmake-build-release\\\\bin\\\\ANSLPR.dll'\\\\'' 2>&1 | Select-String '\\\\''RunInferencesBatch'\\\\'' }')", - "Bash(powershell -Command '& { & '\\\\''C:\\\\Program Files\\\\Microsoft Visual Studio\\\\2022\\\\Community\\\\Common7\\\\Tools\\\\Launch-VsDevShell.ps1'\\\\'' -Arch amd64 -HostArch amd64 > $null 2>&1; dumpbin /exports '\\\\''C:\\\\Projects\\\\CLionProjects\\\\ANSCORE\\\\cmake-build-release\\\\bin\\\\ANSLPR.dll'\\\\'' 2>&1 | Select-String '\\\\''RunInferencesBatch|RectifyPlateROI|RecoverKanaFromBottomHalf'\\\\'' }')", - "Bash(powershell -Command '& { & '\\\\''C:\\\\Program Files\\\\Microsoft Visual Studio\\\\2022\\\\Community\\\\Common7\\\\Tools\\\\Launch-VsDevShell.ps1'\\\\'' -Arch amd64 -HostArch amd64 > $null 2>&1; Set-Location '\\\\''C:\\\\Projects\\\\CLionProjects\\\\ANSCORE\\\\cmake-build-release'\\\\''; cmake --build . --target ANSLPR 2>&1 | Select-Object -Last 20 }')", - "Bash(powershell -Command '& { & '\\\\''C:\\\\Program Files\\\\Microsoft Visual Studio\\\\2022\\\\Community\\\\Common7\\\\Tools\\\\Launch-VsDevShell.ps1'\\\\'' -Arch amd64 -HostArch amd64 > $null 2>&1; Set-Location '\\\\''C:\\\\Projects\\\\CLionProjects\\\\ANSCORE\\\\cmake-build-release'\\\\''; \\(Get-Item '\\\\''C:\\\\Projects\\\\CLionProjects\\\\ANSCORE\\\\modules\\\\ANSLPR\\\\ANSLPR_OCR.cpp'\\\\''\\).LastWriteTime; \\(Get-Item '\\\\''.\\\\bin\\\\ANSLPR.dll'\\\\''\\).LastWriteTime }')", - "Bash(powershell -Command \"\\(Get-Item 'C:\\\\Projects\\\\CLionProjects\\\\ANSCORE\\\\modules\\\\ANSLPR\\\\ANSLPR_OCR.cpp'\\).LastWriteTime = Get-Date\")", - "Bash(powershell -Command '& { & '\\\\''C:\\\\Program Files\\\\Microsoft Visual Studio\\\\2022\\\\Community\\\\Common7\\\\Tools\\\\Launch-VsDevShell.ps1'\\\\'' -Arch amd64 -HostArch amd64 > $null 2>&1; Set-Location '\\\\''C:\\\\Projects\\\\CLionProjects\\\\ANSCORE\\\\cmake-build-release'\\\\''; cmake --build . --target ANSLPR 2>&1 | Select-Object -Last 8 }')", - "Bash(powershell -Command '& { & '\\\\''C:\\\\Program Files\\\\Microsoft Visual Studio\\\\2022\\\\Community\\\\Common7\\\\Tools\\\\Launch-VsDevShell.ps1'\\\\'' -Arch amd64 -HostArch amd64 > $null 2>&1; Set-Location '\\\\''C:\\\\Projects\\\\CLionProjects\\\\ANSCORE\\\\cmake-build-release'\\\\''; cmake --build . --target ANSLPR 2>&1 | Select-Object -Last 6 }')", - "Bash(tasklist /M ANSLPR.dll)", - "Bash(cmd.exe /c \"tasklist /M ANSLPR.dll\")", - "Read(//c/ANSLibs/**)", - "Read(//c/ANSLibs/ffmpeg/**)", - "Bash(where ffmpeg:*)", - "Bash(grep -n \"ImagesToMP4FF\\\\|//bool ANSOPENCV::ImagesToMP4\" \"C:/Projects/CLionProjects/ANSCORE/modules/ANSCV/ANSOpenCV.cpp\")", - "Read(//c/Windows/System32/**)", - "Read(//c//**)", - "Bash(\"C:/ANSLibs/ffmpeg-n8.1/bin/ffmpeg.exe\" -version)", - "Bash(\"C:/ANSLibs/ffmpeg-n8.1/bin/ffmpeg.exe\" -hide_banner -encoders)", - "Bash(find \"C:/Projects/CLionProjects/ANSCORE/MediaClient\" -name \"*.h\" -exec grep -l \"AVFrame\\\\|AVCodec[A-Z]\\\\|AVFormatContext\\\\|AVPacket\\\\|AVStream\\\\b\" {} \\\\;)", - "Bash(grep -l \"AVFrame\\\\|AVCodecContext\\\\|AVFormatContext\\\\|AVPacket\\\\|AVStream\" \"C:/Projects/CLionProjects/ANSCORE/MediaClient/media/\"*.h)", - "Bash(\"C:/ANSLibs/ffmpeg-n8.1/bin/ffmpeg.exe\" -hide_banner -decoders)", - "Bash(\"C:/ANSLibs/ffmpeg-n8.1/bin/ffmpeg.exe\" -hide_banner -protocols)", - "Bash(\"C:/ANSLibs/ffmpeg-n8.1/bin/ffmpeg.exe\" -hide_banner -formats)", - "Bash(grep -c '\\\\\\\\n\",$' modules/ANSUtilities/dllmain.cpp)", - "Bash(grep -c '\\\\\\\\n\", ' modules/ANSUtilities/dllmain.cpp)", - "Bash(grep -nP '\\\\\\\\n\",' dllmain.cpp)", - "Bash(awk '/\\\\[ANSTRE\\\\]/{tre++} /\\\\[ANSMOT\\\\]/{mot++} /\\\\[ANSOD\\\\]/{od++} /\\\\[ANSLPR\\\\]/{lpr++} /\\\\[ANSFR\\\\]/{fr++} /\\\\[ANSLLM\\\\]/{llm++} /\\\\[ANSOCR\\\\]/{ocr++} /\\\\[ANSUTIL\\\\]/{util++} /\\\\[ANSAWS\\\\]/{aws++} END{print \"TRE=\"tre, \"MOT=\"mot, \"OD=\"od, \"LPR=\"lpr, \"FR=\"fr, \"LLM=\"llm, \"OCR=\"ocr, \"UTIL=\"util, \"AWS=\"aws}' \"C:\\\\Users\\\\nghia\\\\Downloads\\\\ANSLEGION.log\")", - "Bash(awk -v target=5122 'NR>=target-30 && NR<=target+5 && /42332/' \"C:\\\\Users\\\\nghia\\\\Downloads\\\\ANSLEGION.log\")", - "Bash(awk -v target=5156 'NR>=target-30 && NR<=target+5 && /42332/' \"C:\\\\Users\\\\nghia\\\\Downloads\\\\ANSLEGION.log\")", - "Bash(awk '/\\\\[ANSOD\\\\]/{ split\\($0, a, \"\\\\t\"\\); pid=a[3]; counts[pid]++ } END { for \\(p in counts\\) print p, counts[p] }' \"C:\\\\Users\\\\nghia\\\\Downloads\\\\ANSLEGION.log\")", - "Bash(awk -F'\\\\t' '/UnregisterODHandle/ || /\\\\[ANSOD\\\\] Unregister/ || /\\\\[ANSOD\\\\] Acquire/ { print NR, $0 }' \"C:\\\\Users\\\\nghia\\\\Downloads\\\\ANSLEGION.log\")", - "Bash(awk -F'\\\\t' '/\\\\[ANSMOT\\\\]/ { sub\\(/^[ \\\\t]+|[ \\\\t]+$/, \"\", $4\\); print $4 }' \"C:\\\\Users\\\\nghia\\\\Downloads\\\\ANSLEGION.log\")", - "Bash(awk -F'\\\\t' '/\\\\[ANSUTIL\\\\]/ { msg=$4; sub\\(/[ ]*HandlePtr=.*$/, \"\", msg\\); sub\\(/[ ]*handle=.*$/, \"\", msg\\); sub\\(/[ ]*\\\\\\([0-9]+ entries.*\\\\\\)/, \"\", msg\\); print msg }' \"C:\\\\Users\\\\nghia\\\\Downloads\\\\ANSLEGION.log\")", - "Bash(awk -F'\\\\t' '/\\\\[ANSAWS\\\\]/ { msg=$4; sub\\(/HandlePtr=.*$/, \"\", msg\\); sub\\(/handle=.*$/, \"\", msg\\); sub\\(/file=.*$/, \"\", msg\\); sub\\(/[ ]+/, \" \", msg\\); print msg }' \"C:\\\\Users\\\\nghia\\\\Downloads\\\\ANSLEGION.log\")", - "Bash(awk '/\\\\[ANSTRE\\\\]/{tre++} /\\\\[ANSMOT\\\\]/{mot++} /\\\\[ANSOD\\\\]/{od++} /\\\\[ANSLPR\\\\]/{lpr++} /\\\\[ANSFR\\\\]/{fr++} /\\\\[ANSLLM\\\\]/{llm++} /\\\\[ANSOCR\\\\]/{ocr++} /\\\\[ANSUTIL\\\\]/{util++} /\\\\[ANSAWS\\\\]/{aws++} END{print \"TRE=\"tre, \"MOT=\"mot, \"OD=\"od, \"LPR=\"lpr, \"FR=\"fr, \"LLM=\"llm, \"OCR=\"ocr, \"UTIL=\"util, \"AWS=\"aws}' \"C:\\\\Users\\\\nghia\\\\Downloads\\\\ANSLEGION1.log\")", - "Bash(awk '/\\\\[ANSOD\\\\]/{ split\\($0, a, \"\\\\t\"\\); pid=a[3]; counts[pid]++ } END { for \\(p in counts\\) print \"OD PID \"p\": \"counts[p] }' \"C:\\\\Users\\\\nghia\\\\Downloads\\\\ANSLEGION1.log\")", - "Bash(awk '/\\\\[ANSAWS\\\\]/{ split\\($0, a, \"\\\\t\"\\); pid=a[3]; counts[pid]++ } END { for \\(p in counts\\) print \"AWS PID \"p\": \"counts[p] }' \"C:\\\\Users\\\\nghia\\\\Downloads\\\\ANSLEGION1.log\")", - "Bash(awk -F'\\\\t' '{print NR, $4}')", - "Bash(awk 'NR>=26275 && NR<=26285' \"C:\\\\Users\\\\nghia\\\\Downloads\\\\ANSLEGION1.log\")" + "Bash(cmake -B cmake-build-release -S .)" ] } } diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..b7b6643 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "3rdparty/libyuv"] + path = 3rdparty/libyuv + url = https://chromium.googlesource.com/libyuv/libyuv diff --git a/3rdparty/libyuv b/3rdparty/libyuv new file mode 160000 index 0000000..ddc6764 --- /dev/null +++ b/3rdparty/libyuv @@ -0,0 +1 @@ +Subproject commit ddc6764d1392fb2e3ff5752b12c73786a989473e diff --git a/CMakeLists.txt b/CMakeLists.txt index 25000d1..95dd4b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,11 +51,19 @@ if(MSVC) "$<$:/W3>" "$<$:/utf-8>" "$<$,$>>:/Zi>" + # RelWithDebInfo: keep /O2 but disable inlining so debuggers can land + # breakpoints on small dispatch functions (e.g. avframeToCVMat). + "$<$,$>:/Ob0>" ) add_link_options( "$<$>:/DEBUG:FULL>" - "$<$>:/OPT:REF>" - "$<$>:/OPT:ICF>" + # /OPT:REF and /OPT:ICF improve Release size/perf but confuse the + # debugger (folds identical functions, strips unused ones). Apply + # them to Release only, not RelWithDebInfo. + "$<$:/OPT:REF>" + "$<$:/OPT:ICF>" + "$<$:/OPT:NOREF>" + "$<$:/OPT:NOICF>" ) add_compile_definitions(_CRT_SECURE_NO_WARNINGS _WINSOCK_DEPRECATED_NO_WARNINGS) elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU") @@ -89,6 +97,35 @@ else() message(STATUS "ANSCORE_DEBUGVIEW = OFF — ANS_DBG verbose logging disabled (production)") endif() +# ── Vendored libyuv (submodule: 3rdparty/libyuv) ──────────────── +# SIMD-optimized YUV conversion library. Only genuinely fast on toolchains +# that understand GCC inline assembly (Clang/clang-cl/GCC) — 144 of its +# SIMD row functions live in row_gcc.cc. MSVC (cl.exe) can only compile the +# 8 routines in row_win.cc, so on MSVC libyuv silently falls back to the +# scalar C code in row_common.cc and runs ~10× slower than OpenCV+IPP's +# cv::cvtColor(COLOR_YUV2BGR_I420). Do NOT enable on MSVC builds. +# +# Default: OFF. Enable with `-DANSCORE_USE_LIBYUV=ON` only after switching +# the project's compiler to clang-cl / clang / gcc. +option(ANSCORE_USE_LIBYUV "Use libyuv for YUV→BGR conversion (only effective on Clang/GCC, NOT MSVC)" OFF) +if(ANSCORE_USE_LIBYUV AND EXISTS "${CMAKE_SOURCE_DIR}/3rdparty/libyuv/CMakeLists.txt") + if(MSVC AND NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + message(WARNING "ANSCORE_USE_LIBYUV=ON but compiler is MSVC cl.exe — " + "libyuv's SIMD paths (row_gcc.cc) won't compile. " + "Expect ~10× slowdown vs cv::cvtColor. " + "Use clang-cl (LLVM) instead, or keep ANSCORE_USE_LIBYUV=OFF.") + endif() + # Prevent libyuv from finding a system libjpeg and enabling HAVE_JPEG + # (we don't use libyuv's MJPEG codepaths; avoids an unnecessary runtime dep). + set(CMAKE_DISABLE_FIND_PACKAGE_JPEG TRUE) + add_subdirectory(3rdparty/libyuv EXCLUDE_FROM_ALL) + set(ANSCORE_HAS_LIBYUV ON) + message(STATUS "libyuv: ENABLED (vendored from 3rdparty/libyuv, static target 'yuv')") +else() + set(ANSCORE_HAS_LIBYUV OFF) + message(STATUS "libyuv: DISABLED — using cv::cvtColor+IPP path (fast on MSVC)") +endif() + # ── External Dependencies ─────────────────────────────────────── include(cmake/Dependencies.cmake) diff --git a/MediaClient/media/video_decoder.cpp b/MediaClient/media/video_decoder.cpp index 6b66bfb..8d8f39b 100644 --- a/MediaClient/media/video_decoder.cpp +++ b/MediaClient/media/video_decoder.cpp @@ -6,10 +6,101 @@ #include "media_parse.h" #include +#include "ANSLicense.h" // ANS_DBG macro (gated by ANSCORE_DEBUGVIEW) + +extern "C" { +#include "libavutil/imgutils.h" +#include "libavutil/buffer.h" +#include "libavutil/mem.h" +} + +// --------------------------------------------------------------------------- +// Contiguous YUV420P allocator — trims per-call malloc overhead and enables +// the zero-copy fast path in avframeYUV420PToCvMat for resolutions where the +// codec's aligned height happens to equal the visible height. +// (4K HEVC at 2160 rows still needs 2176-row alignment → one 16-row gap +// between Y and U remains; the fast path stays off for that case but the +// single-block layout still improves cache behaviour for the bulk memcpy.) +// --------------------------------------------------------------------------- +namespace { + void anscore_contiguous_free(void* /*opaque*/, uint8_t* data) { + av_free(data); + } +} + uint32 g_hw_decoder_nums = 0; uint32 g_hw_decoder_max = 4; // Hardware decoding resources are limited, Limit up to 4 hardware decoding sessions void* g_hw_decoder_mutex = sys_os_create_mutex(); +int CVideoDecoder::contiguousGetBuffer2(AVCodecContext* s, AVFrame* frame, int flags) { + // Never touch HW surfaces — those are owned by the hwframe pool. + if (s->hw_frames_ctx) { + return avcodec_default_get_buffer2(s, frame, flags); + } + // Only pack planar 8-bit 4:2:0. Everything else (NV12 from unpackers, 10-bit + // YUV, 4:2:2, 4:4:4, RGB, paletted, …) goes through the stock allocator. + if (frame->format != AV_PIX_FMT_YUV420P && frame->format != AV_PIX_FMT_YUVJ420P) { + return avcodec_default_get_buffer2(s, frame, flags); + } + if (frame->width <= 0 || frame->height <= 0) { + return avcodec_default_get_buffer2(s, frame, flags); + } + + // Ask the codec for the minimum aligned dimensions it needs. For HEVC + // this typically rounds up to a multiple of 64 (the CTU size); for H.264 + // to a multiple of 16. stride_align[i] is the per-plane linesize alignment. + int aligned_w = frame->width; + int aligned_h = frame->height; + int stride_align[AV_NUM_DATA_POINTERS] = {0}; + avcodec_align_dimensions2(s, &aligned_w, &aligned_h, stride_align); + + // Round up to the strictest stride_align across all planes (simpler and + // safe — FFmpeg only asks for alignment, not exact equality). + int max_align = 32; + for (int i = 0; i < AV_NUM_DATA_POINTERS; ++i) { + if (stride_align[i] > max_align) max_align = stride_align[i]; + } + + auto align_up = [](int v, int a) { return (v + a - 1) & ~(a - 1); }; + + const int y_stride = align_up(aligned_w, max_align); + const int uv_stride = align_up(aligned_w / 2, max_align / 2 > 0 ? max_align / 2 : 16); + const int y_h = aligned_h; + const int uv_h = (aligned_h + 1) / 2; + + const size_t y_sz = (size_t)y_stride * y_h; + const size_t uv_sz = (size_t)uv_stride * uv_h; + const size_t total = y_sz + 2 * uv_sz + AV_INPUT_BUFFER_PADDING_SIZE; + + uint8_t* buf = (uint8_t*)av_mallocz(total); + if (!buf) { + return AVERROR(ENOMEM); + } + + AVBufferRef* ref = av_buffer_create(buf, (int)total, + anscore_contiguous_free, nullptr, 0); + if (!ref) { + av_free(buf); + return AVERROR(ENOMEM); + } + + for (int i = 0; i < AV_NUM_DATA_POINTERS; ++i) { + frame->buf[i] = nullptr; + frame->data[i] = nullptr; + frame->linesize[i] = 0; + } + frame->buf[0] = ref; + frame->data[0] = buf; + frame->data[1] = buf + y_sz; + frame->data[2] = buf + y_sz + uv_sz; + frame->linesize[0] = y_stride; + frame->linesize[1] = uv_stride; + frame->linesize[2] = uv_stride; + frame->extended_data = frame->data; + + return 0; +} + // --------------------------------------------------------------------------- // HWDecoderPool implementation // --------------------------------------------------------------------------- @@ -424,6 +515,30 @@ BOOL CVideoDecoder::init(enum AVCodecID codec, uint8* extradata, int extradata_s } } + // Configure multi-threading for the SOFTWARE decoder. + // Hardware decoders (NVDEC, DXVA2/D3D11VA, QSV, VideoToolbox) do their + // own parallelism inside the GPU/fixed-function block and ignore these + // fields — so we only enable threading when HW init was skipped (hwMode + // == HW_DECODING_DISABLE) or failed (fell back to SW). + // + // Without this, libavcodec's HEVC/H.264 decoder runs on a single core, + // which on 4K HEVC streams is ~80–120 ms per frame. Frame + slice + // threading on a 24-thread CPU typically brings that down to 10–20 ms. + // thread_count = 0 lets FFmpeg auto-pick (capped internally ~16). + if (!m_bHardwareDecoderEnabled) { + m_pContext->thread_count = 0; + m_pContext->thread_type = FF_THREAD_FRAME | FF_THREAD_SLICE; + + // Install contiguous Y+U+V allocator. This packs all three planes + // into a single av_malloc block so the BGR-conversion fast path + // (avframeYUV420PToCvMat) can either wrap the frame zero-copy, or + // at minimum hit a tight 3-call bulk memcpy with good cache locality + // instead of per-row copies into a freshly allocated staging Mat. + // HW decoders must NEVER have get_buffer2 overridden — they use + // hw_frames_ctx for surface management. + m_pContext->get_buffer2 = &CVideoDecoder::contiguousGetBuffer2; + } + // FIXED: Use avcodec_open2 instead of avcodec_thread_open if (avcodec_open2(m_pContext, m_pCodec, NULL) < 0) { @@ -432,6 +547,27 @@ BOOL CVideoDecoder::init(enum AVCodecID codec, uint8* extradata, int extradata_s return FALSE; } + // Debug: one-shot visibility into which decoder actually got opened. + // m_bHardwareDecoderEnabled is set by hwDecoderInit() on success; when + // hwMode == HW_DECODING_DISABLE or hwDecoderInit failed, it stays FALSE + // and the SW decoder (avcodec_find_decoder) is used. + // active_thread_type is what FFmpeg actually negotiated after open2 + // (bit 1 = FF_THREAD_FRAME, bit 2 = FF_THREAD_SLICE). + ANS_DBG("MEDIA_DecInit", + "avcodec_open2 OK codec=%s(%s) %dx%d hwMode=%d hwEnabled=%d cudaHW=%d gpu=%d " + "threads=%d thread_type_req=0x%x active=0x%x -> %s decoder", + m_pCodec->name ? m_pCodec->name : "?", + m_pCodec->long_name ? m_pCodec->long_name : "?", + m_pContext->width, m_pContext->height, + hwMode, + (int)m_bHardwareDecoderEnabled, + (int)m_bCudaHWAccel, + m_hwGpuIndex, + m_pContext->thread_count, + m_pContext->thread_type, + m_pContext->active_thread_type, + m_bHardwareDecoderEnabled ? "HARDWARE" : "SOFTWARE"); + m_pFrame = av_frame_alloc(); if (NULL == m_pFrame) { diff --git a/MediaClient/media/video_decoder.h b/MediaClient/media/video_decoder.h index 608e06e..2d964d5 100644 --- a/MediaClient/media/video_decoder.h +++ b/MediaClient/media/video_decoder.h @@ -147,6 +147,15 @@ public: AVCodecContext* getAVCodeContext() { return m_pContext; } + + // Custom AVCodecContext::get_buffer2 callback used by the SOFTWARE decoder. + // Allocates Y, U, and V planes of YUV420P / YUVJ420P frames in a SINGLE + // contiguous av_malloc block so that CVideoPlayer::avframeYUV420PToCvMat + // can wrap them zero-copy into an I420 cv::Mat when the allocated height + // matches the visible height (i.e. no codec padding rows between planes). + // For unhandled formats (HW surfaces, 10-bit, 4:2:2, 4:4:4, planar-alpha, + // …) it delegates to avcodec_default_get_buffer2, preserving correctness. + static int contiguousGetBuffer2(AVCodecContext* s, AVFrame* frame, int flags); private: BOOL readFrame(); int render(AVFrame* frame); diff --git a/MediaClient/media/video_player.cpp b/MediaClient/media/video_player.cpp index 02d8839..7b1ef57 100644 --- a/MediaClient/media/video_player.cpp +++ b/MediaClient/media/video_player.cpp @@ -28,12 +28,24 @@ extern "C" #include #include #include +#include #include #if defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) #include #define HAS_SSE2 1 #endif +#include "ANSLicense.h" // ANS_DBG macro (gated by ANSCORE_DEBUGVIEW) + +// libyuv: SIMD-accelerated YUV↔RGB conversion with native strided-plane input. +// Replaces the memcpy-into-staging + cv::cvtColor(COLOR_YUV2BGR_I420) chain +// in avframeYUV420PToCvMat with a direct I420→RGB24 (== OpenCV BGR memory +// order) call. When the submodule isn't checked out, ANSCORE_HAS_LIBYUV is +// not defined and we fall back to the pre-libyuv path. +#if defined(ANSCORE_HAS_LIBYUV) && ANSCORE_HAS_LIBYUV +#include "libyuv/convert_argb.h" // libyuv::I420ToRGB24 +#endif + void VideoDecoderCallback(AVFrame* frame, void* userdata) @@ -1284,6 +1296,71 @@ cv::Mat CVideoPlayer::avframeYUV420PToCvMat(const AVFrame* frame) { const int width = frame->width; const int height = frame->height; + // Debug: confirm this SW-decode conversion is actually hit. + // Throttled to ~1 log/sec at 30 fps to keep DebugView readable. + // Gated by ANSCORE_DEBUGVIEW — compiles to nothing in production. + { + static std::atomic s_swCallCount{0}; + uint64_t n = s_swCallCount.fetch_add(1, std::memory_order_relaxed); + if ((n % 30) == 0) { + const char* fmtName = av_get_pix_fmt_name((AVPixelFormat)frame->format); + const bool contig = + (frame->linesize[0] == width && + frame->linesize[1] == width / 2 && + frame->linesize[2] == width / 2 && + frame->data[1] == frame->data[0] + width * height && + frame->data[2] == frame->data[1] + (width / 2) * (height / 2)); + // Report the codec's allocated Y-plane height (inferred from + // the Y/U pointer spacing and Y stride). Lets us see whether + // our custom get_buffer2 achieved alloc_h == visible_h. + const int yStrideDbg = frame->linesize[0] > 0 ? frame->linesize[0] : 1; + const int alloc_h_y = (int)((frame->data[1] - frame->data[0]) / yStrideDbg); +#if defined(ANSCORE_HAS_LIBYUV) && ANSCORE_HAS_LIBYUV + const char* pathLabel = "LIBYUV/I420ToRGB24"; +#else + const char* pathLabel = + contig ? "FAST/zero-copy" : + (frame->linesize[0] == width) ? "SLOW/bulk-memcpy" : + "SLOW/per-row-copy"; +#endif + (void)contig; // silence unused warning when libyuv is on + ANS_DBG("MEDIA_SWDec", + "avframeYUV420PToCvMat ENTRY call#%llu fmt=%s visible=%dx%d alloc_h_y=%d " + "linesize=[%d,%d,%d] path=%s (this=%p)", + (unsigned long long)n, + fmtName ? fmtName : "?", + width, height, alloc_h_y, + frame->linesize[0], frame->linesize[1], frame->linesize[2], + pathLabel, + (void*)this); + } + } + +#if defined(ANSCORE_HAS_LIBYUV) && ANSCORE_HAS_LIBYUV + // libyuv path: direct I420 (3 strided planes) → RGB24 (== BGR in memory + // order for libyuv, matches cv::Mat CV_8UC3 default). No staging buffer, + // no memcpy, no cv::cvtColor — one SIMD-optimized sweep. + // + // libyuv's "RGB24" is B,G,R per pixel in memory (see RGB24ToARGBRow_C + // in libyuv/source/row_common.cc where src[0]=b, src[1]=g, src[2]=r). + // That matches OpenCV's BGR layout — safe to wrap in CV_8UC3. + cv::Mat bgrImage(height, width, CV_8UC3); + int ret = libyuv::I420ToRGB24( + frame->data[0], frame->linesize[0], + frame->data[1], frame->linesize[1], + frame->data[2], frame->linesize[2], + bgrImage.data, static_cast(bgrImage.step), + width, height); + if (ret != 0) { + std::cerr << "libyuv::I420ToRGB24 failed with ret=" << ret << std::endl; + return cv::Mat(); + } + if (m_nImageQuality == 1) { + bgrImage.convertTo(bgrImage, -1, 255.0 / 219.0, -16.0 * 255.0 / 219.0); + } + return bgrImage; +#else + // YUV420P has 3 separate planes: Y (full res), U (half), V (half). // OpenCV's cvtColor(COLOR_YUV2BGR_I420) expects a single contiguous buffer // with Y on top (H rows) and U,V stacked below (H/2 rows total). @@ -1309,12 +1386,25 @@ cv::Mat CVideoPlayer::avframeYUV420PToCvMat(const AVFrame* frame) { return bgrImage; } - // Slow path: planes have padding (linesize > width) — copy to contiguous buffer + // Slow path: planes have padding (linesize > width) OR Y/U/V live in + // non-adjacent buffers. Copy into a single I420-layout staging buffer + // so cvtColor(COLOR_YUV2BGR_I420) can process it in one SIMD sweep. const int uvWidth = width / 2; const int uvHeight = height / 2; const int totalSize = width * height + uvWidth * uvHeight * 2; - cv::Mat yuv(height * 3 / 2, width, CV_8UC1); + // Thread-local staging Mat — reused across calls to avoid a 12 MB malloc + // on every 4K frame. Each decoder runs on its own worker thread, so + // thread_local is the right granularity (no cross-thread sharing, no + // locking). The Mat reallocates only when dimensions change. + static thread_local cv::Mat s_yuvStaging; + if (s_yuvStaging.rows != height * 3 / 2 || + s_yuvStaging.cols != width || + s_yuvStaging.type() != CV_8UC1 || + !s_yuvStaging.isContinuous()) { + s_yuvStaging.create(height * 3 / 2, width, CV_8UC1); + } + cv::Mat& yuv = s_yuvStaging; uint8_t* dst = yuv.data; // Copy Y plane (line by line if stride != width) @@ -1352,6 +1442,7 @@ cv::Mat CVideoPlayer::avframeYUV420PToCvMat(const AVFrame* frame) { bgrImage.convertTo(bgrImage, -1, 255.0 / 219.0, -16.0 * 255.0 / 219.0); } return bgrImage; +#endif // ANSCORE_HAS_LIBYUV } catch (const std::exception& e) { std::cerr << "Exception in avframeYUV420PToCvMat: " << e.what() << std::endl; @@ -1371,13 +1462,54 @@ cv::Mat CVideoPlayer::avframeToCVMat(const AVFrame* pFrame) { return cv::Mat(); } + // One-shot diagnostic: print the pixel format the first time through so + // we can see which branch of the switch below is taken. Remove after use. + static bool s_loggedFmt = false; + if (!s_loggedFmt) { + s_loggedFmt = true; + const char* name = av_get_pix_fmt_name((AVPixelFormat)pFrame->format); + fprintf(stderr, "[avframeToCVMat] first frame format=%d (%s) %dx%d\n", + pFrame->format, name ? name : "?", pFrame->width, pFrame->height); + ANS_DBG("MEDIA_Convert", + "avframeToCVMat FIRST-FRAME fmt=%d(%s) %dx%d HWDecoding=%d (this=%p)", + pFrame->format, name ? name : "?", + pFrame->width, pFrame->height, + m_nHWDecoding, (void*)this); + } + + // Per-branch throttled trace so we can see the dispatch at runtime. + // Gated by ANSCORE_DEBUGVIEW — zero overhead in production. + static std::atomic s_dispatchCount{0}; + const uint64_t dispN = s_dispatchCount.fetch_add(1, std::memory_order_relaxed); + const bool logThis = ((dispN % 30) == 0); + switch (pFrame->format) { case AV_PIX_FMT_NV12: + if (logThis) { + ANS_DBG("MEDIA_Convert", + "DISPATCH call#%llu fmt=NV12 %dx%d -> avframeNV12ToCvMat (HW-decode path)", + (unsigned long long)dispN, pFrame->width, pFrame->height); + } return avframeNV12ToCvMat(pFrame); case AV_PIX_FMT_YUV420P: case AV_PIX_FMT_YUVJ420P: + if (logThis) { + ANS_DBG("MEDIA_Convert", + "DISPATCH call#%llu fmt=%s %dx%d -> avframeYUV420PToCvMat (SW-decode path)", + (unsigned long long)dispN, + (pFrame->format == AV_PIX_FMT_YUVJ420P) ? "YUVJ420P" : "YUV420P", + pFrame->width, pFrame->height); + } return avframeYUV420PToCvMat(pFrame); default: + if (logThis) { + const char* name = av_get_pix_fmt_name((AVPixelFormat)pFrame->format); + ANS_DBG("MEDIA_Convert", + "DISPATCH call#%llu fmt=%d(%s) %dx%d -> avframeAnyToCvmat (sws_scale fallback)", + (unsigned long long)dispN, + pFrame->format, name ? name : "?", + pFrame->width, pFrame->height); + } return avframeAnyToCvmat(pFrame); } @@ -2239,6 +2371,12 @@ cv::Mat CVideoPlayer::getImage(int& width, int& height, int64_t& pts) { AVFrame* frameToProcess = nullptr; uint64_t currentSeq = 0; + // Timing breakdown — gated by ANSCORE_DEBUGVIEW (zero overhead in production). + // t0 = entry, t1 = after pulling frame from queue, t2 = after YUV->BGR, + // t3 = after publish. Throttled to every 30 full-path calls (~1/sec @30fps). + using clk = std::chrono::steady_clock; + const auto t0 = clk::now(); + // --- Phase 1: short locked section — examine state, pull latest frame --- { std::lock_guard lock(_mutex); @@ -2289,6 +2427,7 @@ cv::Mat CVideoPlayer::getImage(int& width, int& height, int64_t& pts) { // At 4K NV12, cvtColorTwoPlane takes ~100–300 ms on CPU; during that // window the decoder callback (onVideoFrame) is free to push the next // frame and the CUDA HW capture path can run in parallel. + const auto t1 = clk::now(); cv::Mat converted; try { @@ -2297,6 +2436,7 @@ cv::Mat CVideoPlayer::getImage(int& width, int& height, int64_t& pts) { catch (const std::exception& e) { std::cerr << "Exception while converting AVFrame to cv::Mat: " << e.what() << std::endl; } + const auto t2 = clk::now(); // --- Phase 2: short locked section — publish new frame state --- cv::Mat result; // Snapshot taken under the lock, returned after release. @@ -2327,6 +2467,26 @@ cv::Mat CVideoPlayer::getImage(int& width, int& height, int64_t& pts) { av_frame_free(&frameToProcess); + // Emit timing breakdown. Throttled so DebugView / stderr stay readable. + { + static std::atomic s_timingCount{0}; + const uint64_t n = s_timingCount.fetch_add(1, std::memory_order_relaxed); + if ((n % 30) == 0) { + const auto t3 = clk::now(); + auto ms = [](clk::time_point a, clk::time_point b) { + return std::chrono::duration(b - a).count(); + }; + ANS_DBG("MEDIA_Timing", + "getImage call#%llu pull=%.2fms convert=%.2fms publish=%.2fms total=%.2fms " + "size=%dx%d seq=%llu (this=%p)", + (unsigned long long)n, + ms(t0, t1), ms(t1, t2), ms(t2, t3), ms(t0, t3), + width, height, + (unsigned long long)currentSeq, + (void*)this); + } + } + return result; } catch (const std::exception& e) { @@ -2342,9 +2502,14 @@ cv::Mat CVideoPlayer::getImage(int& width, int& height, int64_t& pts) { std::string CVideoPlayer::getJpegImage(int& width, int& height, int64_t& pts) { try { + // Timing breakdown — gated by ANSCORE_DEBUGVIEW (zero overhead in production). + using clk = std::chrono::steady_clock; + const auto t0 = clk::now(); + // Use same _mutex as getImage() to protect shared state consistently // recursive_mutex allows nested calls to avframeToJpegString → _mutex std::lock_guard lock(_mutex); + const auto t1 = clk::now(); // While waiting for keyframe or during settle period after restart, // return the last good cached JPEG to avoid showing corrupted frames @@ -2359,6 +2524,10 @@ std::string CVideoPlayer::getJpegImage(int& width, int& height, int64_t& pts) { if (!frameToProcess) { return m_lastJpegImage; // Return the last valid JPEG image if no frame is available } + const auto t2 = clk::now(); + const int frameFmt = frameToProcess->format; + const int frameW = frameToProcess->width; + const int frameH = frameToProcess->height; try { if (frameToProcess->format == AV_PIX_FMT_NV12) { @@ -2373,6 +2542,7 @@ std::string CVideoPlayer::getJpegImage(int& width, int& height, int64_t& pts) { av_frame_free(&frameToProcess); return m_lastJpegImage; } + const auto t3 = clk::now(); av_frame_free(&frameToProcess); @@ -2392,6 +2562,28 @@ std::string CVideoPlayer::getJpegImage(int& width, int& height, int64_t& pts) { m_lastJpegImage = std::move(m_jpegImage); // Move instead of copy } + // Throttled timing breakdown for the JPEG hot path. + { + static std::atomic s_jpegTimingCount{0}; + const uint64_t n = s_jpegTimingCount.fetch_add(1, std::memory_order_relaxed); + if ((n % 30) == 0) { + const auto t4 = clk::now(); + auto ms = [](clk::time_point a, clk::time_point b) { + return std::chrono::duration(b - a).count(); + }; + const char* fmtName = av_get_pix_fmt_name((AVPixelFormat)frameFmt); + ANS_DBG("MEDIA_JpegTiming", + "getJpegImage call#%llu lock=%.2fms pull=%.2fms encode=%.2fms publish=%.2fms " + "total=%.2fms src_fmt=%s %dx%d jpeg_bytes=%zu (this=%p)", + (unsigned long long)n, + ms(t0, t1), ms(t1, t2), ms(t2, t3), ms(t3, t4), ms(t0, t4), + fmtName ? fmtName : "?", + frameW, frameH, + m_lastJpegImage.size(), + (void*)this); + } + } + // Return the most recent valid JPEG image return m_lastJpegImage; } diff --git a/build_anscv_unittest.bat b/build_anscv_unittest.bat new file mode 100644 index 0000000..92a110e --- /dev/null +++ b/build_anscv_unittest.bat @@ -0,0 +1,6 @@ +@echo off +call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat" x64 +set CUDAHOSTCXX=C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\bin\Hostx64\x64\cl.exe +cd /d C:\Projects\CLionProjects\ANSCORE\cmake-build-release +ninja ANSCV-UnitTest -j 20 +echo BUILD_EXIT_CODE=%ERRORLEVEL% diff --git a/build_ansutil.bat b/build_ansutil.bat new file mode 100644 index 0000000..5b863e5 --- /dev/null +++ b/build_ansutil.bat @@ -0,0 +1,6 @@ +@echo off +call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat" x64 +set CUDAHOSTCXX=C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\bin\Hostx64\x64\cl.exe +cd /d C:\Projects\CLionProjects\ANSCORE\cmake-build-release +ninja ANSUtilities -j 20 +echo BUILD_EXIT_CODE=%ERRORLEVEL% diff --git a/build_ansutil_test.bat b/build_ansutil_test.bat new file mode 100644 index 0000000..459fb06 --- /dev/null +++ b/build_ansutil_test.bat @@ -0,0 +1,5 @@ +@echo off +call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat" x64 +cd /d C:\Projects\CLionProjects\ANSCORE\cmake-build-release +ninja ANSUtilities-UnitTest -j 20 +echo BUILD_EXIT_CODE=%ERRORLEVEL% diff --git a/core/ANSLicensingSystem/ANSLicense.h b/core/ANSLicensingSystem/ANSLicense.h index 7497409..c03c43a 100644 --- a/core/ANSLicensingSystem/ANSLicense.h +++ b/core/ANSLicensingSystem/ANSLicense.h @@ -8,7 +8,7 @@ // Set to 0 for production builds to eliminate all debug output overhead. // ============================================================================ #ifndef ANSCORE_DEBUGVIEW -#define ANSCORE_DEBUGVIEW 0 // 1 = enabled (debug), 0 = disabled (production) +#define ANSCORE_DEBUGVIEW 1 // 1 = enabled (debug), 0 = disabled (production) #endif // ANS_DBG: Debug logging macro for DebugView (OutputDebugStringA on Windows). @@ -19,10 +19,24 @@ // conflicts. Instead, forward-declare OutputDebugStringA directly. #if ANSCORE_DEBUGVIEW && defined(_WIN32) extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA(const char* lpOutputString); +// Emit to BOTH DebugView (OutputDebugStringA) AND stderr so console apps +// (ANSCV-UnitTest, ANSLPR-UnitTest, ANSUtilities_test, etc.) show the message +// without needing to attach DebugView. fputs + fflush keeps lines atomic even +// when multiple threads log concurrently. #define ANS_DBG(tag, fmt, ...) do { \ char _ans_dbg_buf[1024]; \ snprintf(_ans_dbg_buf, sizeof(_ans_dbg_buf), "[" tag "] " fmt "\n", ##__VA_ARGS__); \ OutputDebugStringA(_ans_dbg_buf); \ + fputs(_ans_dbg_buf, stderr); \ + fflush(stderr); \ +} while(0) +#elif ANSCORE_DEBUGVIEW +// Non-Windows: stderr only. +#define ANS_DBG(tag, fmt, ...) do { \ + char _ans_dbg_buf[1024]; \ + snprintf(_ans_dbg_buf, sizeof(_ans_dbg_buf), "[" tag "] " fmt "\n", ##__VA_ARGS__); \ + fputs(_ans_dbg_buf, stderr); \ + fflush(stderr); \ } while(0) #else #define ANS_DBG(tag, fmt, ...) ((void)0) diff --git a/modules/ANSCV/CMakeLists.txt b/modules/ANSCV/CMakeLists.txt index bf1458f..c9522ec 100644 --- a/modules/ANSCV/CMakeLists.txt +++ b/modules/ANSCV/CMakeLists.txt @@ -89,6 +89,15 @@ target_link_libraries(ANSCV PRIVATE CUDA::nvjpeg ) +# libyuv — vendored at 3rdparty/libyuv (added by top-level CMakeLists when +# the submodule is present). Provides SIMD-accelerated I420→RGB24 used by +# CVideoPlayer::avframeYUV420PToCvMat for the SW-decode fast path. +if(ANSCORE_HAS_LIBYUV) + target_link_libraries(ANSCV PRIVATE yuv) + target_include_directories(ANSCV PRIVATE ${CMAKE_SOURCE_DIR}/3rdparty/libyuv/include) + target_compile_definitions(ANSCV PRIVATE ANSCORE_HAS_LIBYUV=1) +endif() + # Platform-specific libs if(WIN32) target_link_directories(ANSCV PRIVATE diff --git a/tests/ANSCV-UnitTest/ANSCV-UnitTest.cpp b/tests/ANSCV-UnitTest/ANSCV-UnitTest.cpp index 2dd2eb0..28874e4 100644 --- a/tests/ANSCV-UnitTest/ANSCV-UnitTest.cpp +++ b/tests/ANSCV-UnitTest/ANSCV-UnitTest.cpp @@ -883,12 +883,11 @@ int RSTPTestCVClient() { while (true) { index++; std::cout << "Index=" << index << std::endl; - if ((index == 200) || (index == 800) || (index == 1200)) { StopRTSP(&rtspClient); } - if ((index == 400) || (index == 1000) || (index == 1500)) { StartRTSP(&rtspClient); } - if ((index == 1800) || (index == 2200) || (index == 2500)) { StartRTSP(&rtspClient); } - if ((index == 2000) || (index == 2300) || (index == 2700)) { StartRTSP(&rtspClient); } - - if (index > 20000) break; + //if ((index == 200) || (index == 800) || (index == 1200)) { StopRTSP(&rtspClient); } + //if ((index == 400) || (index == 1000) || (index == 1500)) { StartRTSP(&rtspClient); } + //if ((index == 1800) || (index == 2200) || (index == 2500)) { StartRTSP(&rtspClient); } + //if ((index == 2000) || (index == 2300) || (index == 2700)) { StartRTSP(&rtspClient); } + //if (index > 20000) break; auto start = std::chrono::system_clock::now(); cv::Mat* image = nullptr; // ✅ Use a pointer to hold the allocated image GetRTSPCVImage(&rtspClient, width, height, pts,&image); @@ -1485,12 +1484,12 @@ int main() //OpenCVFunctionTest(); - GenerateVideo(); + //GenerateVideo(); //VideoTestClient(); // TestGetImage(); //PureOpenCV(); // RSTPTestClient(); - //RSTPTestCVClient(); + RSTPTestCVClient(); //TestCreateImageFromJpegStringFile(); //TestCreateImageFromFile(); //for (int i = 0; i < 100; i++) {