Fix double stop in ANSVideoPlayer
This commit is contained in:
@@ -47,9 +47,6 @@ namespace ANSCENTER {
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||||
try {
|
||||
if (_hwPlayer) {
|
||||
try { _hwPlayer->stop(); } catch (...) {}
|
||||
}
|
||||
hwPlayerToClose = std::move(_hwPlayer);
|
||||
_hwDecodeActive = false;
|
||||
_hwGpuIndex = -1;
|
||||
@@ -80,9 +77,10 @@ namespace ANSCENTER {
|
||||
}
|
||||
} // end lock scope
|
||||
|
||||
// CUDA cleanup happens here, outside the mutex
|
||||
// CUDA cleanup happens here, outside the mutex.
|
||||
// Destructor calls close() once — do not call stop()/close() explicitly
|
||||
// beforehand (double-close re-enters torn-down decoder state).
|
||||
if (hwPlayerToClose) {
|
||||
try { hwPlayerToClose->close(); } catch (...) {}
|
||||
hwPlayerToClose.reset();
|
||||
}
|
||||
}
|
||||
@@ -201,13 +199,10 @@ namespace ANSCENTER {
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||||
_isPlaying = false; // GetImage() returns cached frame while we reconnect
|
||||
if (_hwPlayer) {
|
||||
try { _hwPlayer->stop(); } catch (...) {}
|
||||
hwPlayerToClose = std::move(_hwPlayer);
|
||||
}
|
||||
hwPlayerToClose = std::move(_hwPlayer);
|
||||
}
|
||||
// Destructor calls close() exactly once — single teardown.
|
||||
if (hwPlayerToClose) {
|
||||
try { hwPlayerToClose->close(); } catch (...) {}
|
||||
hwPlayerToClose.reset();
|
||||
}
|
||||
|
||||
@@ -241,11 +236,24 @@ namespace ANSCENTER {
|
||||
bool ANSVIDEOPLAYER::Start() {
|
||||
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||||
try {
|
||||
// Re-initialize after a prior Stop(): _hwPlayer was released and
|
||||
// cap was closed. Setup() reopens whichever backend applies.
|
||||
// Why: CFilePlayer::stop() == close(), which frees m_pFormatContext.
|
||||
// Calling play() on a closed player dereferences NULL and crashes.
|
||||
if (!_hwPlayer && !cap.isOpened()) {
|
||||
if (!Setup()) {
|
||||
this->_logger.LogError("ANSVIDEOPLAYER::Start. Exception occurred:",
|
||||
"Setup() failed on restart", __FILE__, __LINE__);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// --- HW decode path ---
|
||||
if (_hwDecodeActive && _hwPlayer) {
|
||||
_hwPlayer->play(); // starts read/video/audio threads
|
||||
_hwEOF = false;
|
||||
_hwFrameCount = 0;
|
||||
_hwLastPts = 0;
|
||||
_isPlaying = true;
|
||||
|
||||
// Wait for first frame outside the mutex to let decode threads run
|
||||
@@ -284,15 +292,26 @@ namespace ANSCENTER {
|
||||
}
|
||||
}
|
||||
bool ANSVIDEOPLAYER::Stop() {
|
||||
decltype(_hwPlayer.get()) hwPlayer = nullptr;
|
||||
// Move HW player out of lock scope — CFilePlayer::stop() == close(),
|
||||
// which does CUDA cleanup that must not run under _mutex to avoid
|
||||
// deadlocking with the nvcuda64 SRW lock held by inference.
|
||||
decltype(_hwPlayer) hwPlayerToClose;
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||||
try {
|
||||
// --- HW decode path ---
|
||||
if (_hwDecodeActive && _hwPlayer) {
|
||||
_isPlaying = false;
|
||||
hwPlayer = _hwPlayer.get();
|
||||
// stop() called outside the lock below; skip cap path
|
||||
// Release the player completely — CFilePlayer::stop() == close(),
|
||||
// which frees m_pFormatContext. Keeping the unique_ptr alive after
|
||||
// this point is a landmine: a later play() would deref NULL.
|
||||
hwPlayerToClose = std::move(_hwPlayer);
|
||||
_hwDecodeActive = false;
|
||||
_hwGpuIndex = -1;
|
||||
_hwCudaAccel = false;
|
||||
_hwEOF = false;
|
||||
_hwFrameCount = 0;
|
||||
_hwLastPts = 0;
|
||||
}
|
||||
else {
|
||||
// --- cv::VideoCapture fallback ---
|
||||
@@ -322,8 +341,12 @@ namespace ANSCENTER {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (hwPlayer) {
|
||||
hwPlayer->stop();
|
||||
// CUDA cleanup happens here, outside the mutex.
|
||||
// Rely on the destructor to call close() exactly once. Calling stop()
|
||||
// (== close()) explicitly would double-close the CFilePlayer, which
|
||||
// re-enters decoder Stop/flush on an already-torn-down decoder.
|
||||
if (hwPlayerToClose) {
|
||||
hwPlayerToClose.reset();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user