Fix double stop in ANSVideoPlayer

This commit is contained in:
2026-04-22 10:10:16 +10:00
parent 97d814936d
commit 57cc8e0a56
14 changed files with 492 additions and 70 deletions

View File

@@ -46,8 +46,11 @@ std::atomic<int64_t> g_queueClones{0};
std::atomic<int64_t> g_queueFrees{0};
std::atomic<int64_t> g_nv12Clones{0};
std::atomic<int64_t> g_nv12Frees{0};
std::atomic<int64_t> g_nv12Escapes{0};
std::atomic<int64_t> g_cudaHWClones{0};
std::atomic<int64_t> g_cudaHWFrees{0};
std::atomic<int64_t> g_cudaHWEscapes{0};
std::atomic<int64_t> g_avframePendingReturns{0};
extern std::atomic<int64_t> g_contiguousAllocs;
extern std::atomic<int64_t> g_contiguousFrees;
@@ -1621,7 +1624,9 @@ AVFrame* CVideoPlayer::getNV12Frame() {
// (Previously used ownership transfer — only the first caller got NV12,
// and the second caller fell back to BGR.)
std::lock_guard<std::recursive_mutex> lock(_mutex);
return m_currentNV12Frame ? av_frame_clone(m_currentNV12Frame) : nullptr;
AVFrame* clone = m_currentNV12Frame ? av_frame_clone(m_currentNV12Frame) : nullptr;
if (clone) g_nv12Escapes.fetch_add(1, std::memory_order_relaxed);
return clone;
}
AVFrame* CVideoPlayer::getCudaHWFrame() {
@@ -1632,7 +1637,9 @@ AVFrame* CVideoPlayer::getCudaHWFrame() {
// extra_hw_frames=2 in the decoder provides surface pool headroom
// for the 3 concurrent clones (decoder + player + registry).
std::lock_guard<std::recursive_mutex> lock(_mutex);
return m_currentCudaHWFrame ? av_frame_clone(m_currentCudaHWFrame) : nullptr;
AVFrame* clone = m_currentCudaHWFrame ? av_frame_clone(m_currentCudaHWFrame) : nullptr;
if (clone) g_cudaHWEscapes.fetch_add(1, std::memory_order_relaxed);
return clone;
}
bool CVideoPlayer::isCudaHWAccel() const {
@@ -2516,20 +2523,29 @@ cv::Mat CVideoPlayer::getImage(int& width, int& height, int64_t& pts) {
const int64_t qF = g_queueFrees.load(std::memory_order_relaxed);
const int64_t nvA = g_nv12Clones.load(std::memory_order_relaxed);
const int64_t nvF = g_nv12Frees.load(std::memory_order_relaxed);
const int64_t nvE = g_nv12Escapes.load(std::memory_order_relaxed);
const int64_t cuA = g_cudaHWClones.load(std::memory_order_relaxed);
const int64_t cuF = g_cudaHWFrees.load(std::memory_order_relaxed);
const int64_t cuE = g_cudaHWEscapes.load(std::memory_order_relaxed);
const int64_t pR = g_avframePendingReturns.load(std::memory_order_relaxed);
const int64_t cgA = g_contiguousAllocs.load(std::memory_order_relaxed);
const int64_t cgF = g_contiguousFrees.load(std::memory_order_relaxed);
const int64_t cgB = g_contiguousBytesInFlight.load(std::memory_order_relaxed);
// escapeBalance = (nv12Esc + cuHWEsc) - pendingReturns.
// Positive growing value = external callers hold clones they
// never returned to the pendingFree drain → escape-path leak.
const int64_t escBal = (nvE + cuE) - pR;
ANS_DBG("MEDIA_Leak",
"queue(C=%lld F=%lld net=%lld depth=%zu) "
"nv12(C=%lld F=%lld net=%lld) "
"cudaHW(C=%lld F=%lld net=%lld) "
"nv12(C=%lld F=%lld net=%lld esc=%lld) "
"cudaHW(C=%lld F=%lld net=%lld esc=%lld) "
"pendingReturns=%lld escBal=%lld "
"contig(A=%lld F=%lld net=%lld bytesMB=%.1f)",
(long long)qA, (long long)qF, (long long)(qA - qF),
g_frameQueue.size(),
(long long)nvA, (long long)nvF, (long long)(nvA - nvF),
(long long)cuA, (long long)cuF, (long long)(cuA - cuF),
(long long)nvA, (long long)nvF, (long long)(nvA - nvF), (long long)nvE,
(long long)cuA, (long long)cuF, (long long)(cuA - cuF), (long long)cuE,
(long long)pR, (long long)escBal,
(long long)cgA, (long long)cgF, (long long)(cgA - cgF),
(double)cgB / (1024.0 * 1024.0));
}