Fix double stops

This commit is contained in:
2026-04-22 10:19:03 +10:00
parent 57cc8e0a56
commit 0e203eef99
6 changed files with 33 additions and 14 deletions

View File

@@ -62,8 +62,11 @@ namespace ANSCENTER {
} }
clientToClose = std::move(_playerClient); 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) { if (clientToClose) {
clientToClose->close(); clientToClose.reset();
} }
} }
static void VerifyGlobalANSFLVLicense(const std::string& licenseKey) { static void VerifyGlobalANSFLVLicense(const std::string& licenseKey) {
@@ -144,7 +147,8 @@ namespace ANSCENTER {
std::lock_guard<std::recursive_mutex> lock(_mutex); std::lock_guard<std::recursive_mutex> lock(_mutex);
_isPlaying = false; _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<std::recursive_mutex> lock(_mutex); std::lock_guard<std::recursive_mutex> lock(_mutex);
Setup(); Setup();
_isPlaying = _playerClient->play(); _isPlaying = _playerClient->play();

View File

@@ -59,8 +59,11 @@ namespace ANSCENTER {
} }
clientToClose = std::move(_playerClient); 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) { if (clientToClose) {
clientToClose->close(); clientToClose.reset();
} }
} }
static void VerifyGlobalANSMJPEGLicense(const std::string& licenseKey) { static void VerifyGlobalANSMJPEGLicense(const std::string& licenseKey) {
@@ -141,7 +144,8 @@ namespace ANSCENTER {
std::lock_guard<std::recursive_mutex> lock(_mutex); std::lock_guard<std::recursive_mutex> lock(_mutex);
_isPlaying = false; _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<std::recursive_mutex> lock(_mutex); std::lock_guard<std::recursive_mutex> lock(_mutex);
Setup(); Setup();
_isPlaying = _playerClient->play(); _isPlaying = _playerClient->play();

View File

@@ -61,8 +61,11 @@ namespace ANSCENTER {
} }
clientToClose = std::move(_playerClient); 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) { if (clientToClose) {
clientToClose->close(); clientToClose.reset();
} }
} }
static void VerifyGlobalANSRTMPLicense(const std::string& licenseKey) { static void VerifyGlobalANSRTMPLicense(const std::string& licenseKey) {
@@ -138,7 +141,8 @@ namespace ANSCENTER {
std::lock_guard<std::recursive_mutex> lock(_mutex); std::lock_guard<std::recursive_mutex> lock(_mutex);
_isPlaying = false; _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<std::recursive_mutex> lock(_mutex); std::lock_guard<std::recursive_mutex> lock(_mutex);
Setup(); Setup();
_isPlaying = _playerClient->play(); _isPlaying = _playerClient->play();

View File

@@ -128,8 +128,11 @@ namespace ANSCENTER {
// close() destroys the NVDEC decoder ONLY. Pool slot buffers // close() destroys the NVDEC decoder ONLY. Pool slot buffers
// (regular cudaMallocPitch allocations) are untouched — they // (regular cudaMallocPitch allocations) are untouched — they
// belong to the global GpuNV12SlotPool, not the decoder. // 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) { if (clientToClose) {
clientToClose->close(); clientToClose.reset();
// Force CUDA runtime to release all cached memory from the destroyed // Force CUDA runtime to release all cached memory from the destroyed
// NVDEC decoder. Without this, cuMemFree returns memory to the CUDA // NVDEC decoder. Without this, cuMemFree returns memory to the CUDA

View File

@@ -61,8 +61,11 @@ namespace ANSCENTER {
} }
clientToClose = std::move(_playerClient); 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) { if (clientToClose) {
clientToClose->close(); clientToClose.reset();
} }
} }
static void VerifyGlobalANSSRTLicense(const std::string& licenseKey) { static void VerifyGlobalANSSRTLicense(const std::string& licenseKey) {
@@ -136,7 +139,8 @@ namespace ANSCENTER {
std::lock_guard<std::recursive_mutex> lock(_mutex); std::lock_guard<std::recursive_mutex> lock(_mutex);
_isPlaying = false; _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<std::recursive_mutex> lock(_mutex); std::lock_guard<std::recursive_mutex> lock(_mutex);
Setup(); Setup();
_isPlaying = _playerClient->play(); _isPlaying = _playerClient->play();

View File

@@ -849,11 +849,11 @@ int RSTPTestCVClient() {
while (true) { while (true) {
index++; index++;
std::cout << "Index=" << index << std::endl; std::cout << "Index=" << index << std::endl;
//if ((index == 200) || (index == 800) || (index == 1200)) { StopRTSP(&rtspClient); } if ((index == 200) || (index == 800) || (index == 1200)) { StopRTSP(&rtspClient); }
//if ((index == 400) || (index == 1000) || (index == 1500)) { StartRTSP(&rtspClient); } if ((index == 400) || (index == 1000) || (index == 1500)) { StartRTSP(&rtspClient); }
//if ((index == 1800) || (index == 2200) || (index == 2500)) { StartRTSP(&rtspClient); } //if ((index == 1800) || (index == 2200) || (index == 2500)) { StartRTSP(&rtspClient); }
//if ((index == 2000) || (index == 2300) || (index == 2700)) { 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(); auto start = std::chrono::system_clock::now();
cv::Mat* image = nullptr; // ✅ Use a pointer to hold the allocated image cv::Mat* image = nullptr; // ✅ Use a pointer to hold the allocated image
GetRTSPCVImage(&rtspClient, width, height, pts,&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. // so this works without the unit test having to link FFmpeg itself.
//ANSCV_PrintFFmpegLicense_S(); //ANSCV_PrintFFmpegLicense_S();
//FilePlayerClientDoubleDestroy(); //FilePlayerClientDoubleDestroy();
FilePlayerClientCVTest(); //FilePlayerClientCVTest();
//VideoPlayerClientTest(); //VideoPlayerClientTest();
//VideoPlayerClientDoubleDestroy(); //VideoPlayerClientDoubleDestroy();
// VideoPlayerClientTest(); // VideoPlayerClientTest();
@@ -1655,7 +1655,7 @@ int main()
// TestGetImage(); // TestGetImage();
//PureOpenCV(); //PureOpenCV();
// RSTPTestClient(); // RSTPTestClient();
//RSTPTestCVClient(); RSTPTestCVClient();
//TestCreateImageFromJpegStringFile(); //TestCreateImageFromJpegStringFile();
//TestCreateImageFromFile(); //TestCreateImageFromFile();
//for (int i = 0; i < 100; i++) { //for (int i = 0; i < 100; i++) {