Fix NV12 crash issue when recreate camera object

This commit is contained in:
2026-04-02 22:07:27 +11:00
parent 4bedf3a3a2
commit 958cab6ae3
25 changed files with 1459 additions and 393 deletions

View File

@@ -40,33 +40,34 @@ namespace ANSCENTER {
catch (...) {}
}
void ANSVIDEOPLAYER::Destroy() {
std::lock_guard<std::recursive_mutex> lock(_mutex);
try {
// --- HW decode cleanup ---
if (_hwPlayer) {
try {
_hwPlayer->stop();
_hwPlayer->close();
} catch (...) {}
_hwPlayer.reset(); // releases CFilePlayer + HWDecoderPool slot
}
_hwDecodeActive = false;
_hwGpuIndex = -1;
_hwCudaAccel = false;
_hwEOF = false;
_hwFrameCount = 0;
// Move HW player out of lock scope — close() does CUDA cleanup
// (cuArrayDestroy/cuMemFree) which must not run under _mutex
// to avoid deadlocking with nvcuda64 SRW lock held by inference.
decltype(_hwPlayer) hwPlayerToClose;
{
std::lock_guard<std::recursive_mutex> lock(_mutex);
try {
if (_hwPlayer) {
try { _hwPlayer->stop(); } catch (...) {}
}
hwPlayerToClose = std::move(_hwPlayer);
_hwDecodeActive = false;
_hwGpuIndex = -1;
_hwCudaAccel = false;
_hwEOF = false;
_hwFrameCount = 0;
// --- cv::VideoCapture cleanup ---
_previousImage.release();
_inferenceImage.release();
_inferenceCloneCurr.release();
_inferenceClonePrev.release();
_lastJpegImage = "";
_isPlaying = false;
_resWidth = 0;
_resHeight = 0;
_currentFrame = 0;
_previousPTS = 0;
// --- cv::VideoCapture cleanup ---
_previousImage.release();
_inferenceImage.release();
_inferenceCloneCurr.release();
_inferenceClonePrev.release();
_lastJpegImage = "";
_isPlaying = false;
_resWidth = 0;
_resHeight = 0;
_currentFrame = 0;
_previousPTS = 0;
if (cap.isOpened()) {
cap.release();
}
@@ -77,6 +78,13 @@ namespace ANSCENTER {
catch (...) {
_logger.LogError("ANSVIDEOPLAYER::Destroy.", "Unknown exception", __FILE__, __LINE__);
}
} // end lock scope
// CUDA cleanup happens here, outside the mutex
if (hwPlayerToClose) {
try { hwPlayerToClose->close(); } catch (...) {}
hwPlayerToClose.reset();
}
}
static void VerifyGlobalANSVPLicense(const std::string& licenseKey) {
@@ -187,15 +195,25 @@ namespace ANSCENTER {
}
bool ANSVIDEOPLAYER::Reconnect() {
// HW decoder close() does CUDA cleanup — run outside _mutex
// to avoid deadlocking with nvcuda64 SRW lock held by inference.
decltype(_hwPlayer) hwPlayerToClose;
{
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);
}
}
if (hwPlayerToClose) {
try { hwPlayerToClose->close(); } catch (...) {}
hwPlayerToClose.reset();
}
std::lock_guard<std::recursive_mutex> lock(_mutex);
try {
_currentFrame = 0;
// --- HW decode: destroy and re-setup ---
if (_hwPlayer) {
try { _hwPlayer->stop(); _hwPlayer->close(); } catch (...) {}
_hwPlayer.reset();
}
_hwDecodeActive = false;
_hwGpuIndex = -1;
_hwCudaAccel = false;
@@ -266,41 +284,48 @@ namespace ANSCENTER {
}
}
bool ANSVIDEOPLAYER::Stop() {
std::lock_guard<std::recursive_mutex> lock(_mutex);
try {
// --- HW decode path ---
if (_hwDecodeActive && _hwPlayer) {
_hwPlayer->stop();
_isPlaying = false;
return true;
}
// --- cv::VideoCapture fallback ---
if (cap.isOpened()) {
try {
double frame_pos = cap.get(cv::CAP_PROP_POS_FRAMES);
if (frame_pos >= 0) {
_currentFrame = static_cast<int64_t>(frame_pos);
}
else {
_currentFrame = 0;
this->_logger.LogError("ANSVIDEOPLAYER::Stop. Exception occurred:", "Unable to retrieve current frame position", __FILE__, __LINE__);
}
decltype(_hwPlayer.get()) hwPlayer = nullptr;
{
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
}
catch (const std::exception& e) {
this->_logger.LogError("ANSVIDEOPLAYER::Stop. Exception occurred:", e.what(), __FILE__, __LINE__);
_currentFrame = 0;
else {
// --- cv::VideoCapture fallback ---
if (cap.isOpened()) {
try {
double frame_pos = cap.get(cv::CAP_PROP_POS_FRAMES);
if (frame_pos >= 0) {
_currentFrame = static_cast<int64_t>(frame_pos);
}
else {
_currentFrame = 0;
this->_logger.LogError("ANSVIDEOPLAYER::Stop. Exception occurred:", "Unable to retrieve current frame position", __FILE__, __LINE__);
}
}
catch (const std::exception& e) {
this->_logger.LogError("ANSVIDEOPLAYER::Stop. Exception occurred:", e.what(), __FILE__, __LINE__);
_currentFrame = 0;
}
cap.release();
}
_isPlaying = false;
return true;
}
cap.release();
}
_isPlaying = false;
return true;
catch (const std::exception& e) {
this->_logger.LogError("ANSVIDEOPLAYER::Stop. Exception occurred:", e.what(), __FILE__, __LINE__);
return false;
}
}
catch (const std::exception& e) {
this->_logger.LogError("ANSVIDEOPLAYER::Stop. Exception occurred:", e.what(), __FILE__, __LINE__);
return false;
if (hwPlayer) {
hwPlayer->stop();
}
return true;
}
void ANSVIDEOPLAYER::SetBBox(cv::Rect bbox) {
std::lock_guard<std::recursive_mutex> lock(_mutex);