diff --git a/modules/ANSCV/ANSFLV.cpp b/modules/ANSCV/ANSFLV.cpp index 1079e80..af8bab0 100644 --- a/modules/ANSCV/ANSFLV.cpp +++ b/modules/ANSCV/ANSFLV.cpp @@ -62,8 +62,11 @@ namespace ANSCENTER { } clientToClose = std::move(_playerClient); } + // reset() runs the destructor which calls close() exactly once. + // Do NOT call close() explicitly before reset() — second close would + // re-enter decoder Stop/flush on already-torn-down state. if (clientToClose) { - clientToClose->close(); + clientToClose.reset(); } } static void VerifyGlobalANSFLVLicense(const std::string& licenseKey) { @@ -144,7 +147,8 @@ namespace ANSCENTER { std::lock_guard lock(_mutex); _isPlaying = false; } - _playerClient->close(); + // CHttpFlvPlayer::open() calls close() internally at the top — + // no need to close explicitly (would be a double-close). std::lock_guard lock(_mutex); Setup(); _isPlaying = _playerClient->play(); diff --git a/modules/ANSCV/ANSMJPEG.cpp b/modules/ANSCV/ANSMJPEG.cpp index cee454e..191179a 100644 --- a/modules/ANSCV/ANSMJPEG.cpp +++ b/modules/ANSCV/ANSMJPEG.cpp @@ -59,8 +59,11 @@ namespace ANSCENTER { } clientToClose = std::move(_playerClient); } + // reset() runs the destructor which calls close() exactly once. + // Do NOT call close() explicitly before reset() — second close would + // re-enter decoder Stop/flush on already-torn-down state. if (clientToClose) { - clientToClose->close(); + clientToClose.reset(); } } static void VerifyGlobalANSMJPEGLicense(const std::string& licenseKey) { @@ -141,7 +144,8 @@ namespace ANSCENTER { std::lock_guard lock(_mutex); _isPlaying = false; } - _playerClient->close(); + // CHttpMjpegPlayer::open() calls close() internally at the top — + // no need to close explicitly (would be a double-close). std::lock_guard lock(_mutex); Setup(); _isPlaying = _playerClient->play(); diff --git a/modules/ANSCV/ANSRTMP.cpp b/modules/ANSCV/ANSRTMP.cpp index b88f655..a679bca 100644 --- a/modules/ANSCV/ANSRTMP.cpp +++ b/modules/ANSCV/ANSRTMP.cpp @@ -61,8 +61,11 @@ namespace ANSCENTER { } clientToClose = std::move(_playerClient); } + // reset() runs the destructor which calls close() exactly once. + // Do NOT call close() explicitly before reset() — second close would + // re-enter decoder Stop/flush on already-torn-down state. if (clientToClose) { - clientToClose->close(); + clientToClose.reset(); } } static void VerifyGlobalANSRTMPLicense(const std::string& licenseKey) { @@ -138,7 +141,8 @@ namespace ANSCENTER { std::lock_guard lock(_mutex); _isPlaying = false; } - _playerClient->close(); + // CRtmpPlayer::open() calls close() internally at the top — + // no need to close explicitly (would be a double-close). std::lock_guard lock(_mutex); Setup(); _isPlaying = _playerClient->play(); diff --git a/modules/ANSCV/ANSRTSP.cpp b/modules/ANSCV/ANSRTSP.cpp index b793a16..cccdb0f 100644 --- a/modules/ANSCV/ANSRTSP.cpp +++ b/modules/ANSCV/ANSRTSP.cpp @@ -128,8 +128,11 @@ namespace ANSCENTER { // close() destroys the NVDEC decoder ONLY. Pool slot buffers // (regular cudaMallocPitch allocations) are untouched — they // belong to the global GpuNV12SlotPool, not the decoder. + // reset() runs ~CRtspPlayer which calls close() exactly once — + // do NOT call close() explicitly here (the destructor would call + // it again, which re-enters torn-down decoder state). if (clientToClose) { - clientToClose->close(); + clientToClose.reset(); // Force CUDA runtime to release all cached memory from the destroyed // NVDEC decoder. Without this, cuMemFree returns memory to the CUDA diff --git a/modules/ANSCV/ANSSRT.cpp b/modules/ANSCV/ANSSRT.cpp index 01621d3..af04c0f 100644 --- a/modules/ANSCV/ANSSRT.cpp +++ b/modules/ANSCV/ANSSRT.cpp @@ -61,8 +61,11 @@ namespace ANSCENTER { } clientToClose = std::move(_playerClient); } + // reset() runs the destructor which calls close() exactly once. + // Do NOT call close() explicitly before reset() — second close would + // re-enter decoder Stop/flush on already-torn-down state. if (clientToClose) { - clientToClose->close(); + clientToClose.reset(); } } static void VerifyGlobalANSSRTLicense(const std::string& licenseKey) { @@ -136,7 +139,8 @@ namespace ANSCENTER { std::lock_guard lock(_mutex); _isPlaying = false; } - _playerClient->close(); + // CSrtPlayer::open() calls close() internally at the top — + // no need to close explicitly (would be a double-close). std::lock_guard lock(_mutex); Setup(); _isPlaying = _playerClient->play(); diff --git a/tests/ANSCV-UnitTest/ANSCV-UnitTest.cpp b/tests/ANSCV-UnitTest/ANSCV-UnitTest.cpp index 7afdff7..da22b30 100644 --- a/tests/ANSCV-UnitTest/ANSCV-UnitTest.cpp +++ b/tests/ANSCV-UnitTest/ANSCV-UnitTest.cpp @@ -849,11 +849,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 == 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 > 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); @@ -1645,7 +1645,7 @@ int main() // so this works without the unit test having to link FFmpeg itself. //ANSCV_PrintFFmpegLicense_S(); //FilePlayerClientDoubleDestroy(); - FilePlayerClientCVTest(); + //FilePlayerClientCVTest(); //VideoPlayerClientTest(); //VideoPlayerClientDoubleDestroy(); // VideoPlayerClientTest(); @@ -1655,7 +1655,7 @@ int main() // TestGetImage(); //PureOpenCV(); // RSTPTestClient(); - //RSTPTestCVClient(); + RSTPTestCVClient(); //TestCreateImageFromJpegStringFile(); //TestCreateImageFromFile(); //for (int i = 0; i < 100; i++) {