Fix double stop in ANSVideoPlayer
This commit is contained in:
@@ -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));
|
||||
}
|
||||
|
||||
@@ -22,10 +22,17 @@
|
||||
// Defined in video_player.cpp; also incremented from FrameQueue here.
|
||||
extern std::atomic<int64_t> g_queueClones; // av_frame_clone from FrameQueue
|
||||
extern std::atomic<int64_t> g_queueFrees; // av_frame_free from FrameQueue
|
||||
extern std::atomic<int64_t> g_nv12Clones; // m_currentNV12Frame = av_frame_clone
|
||||
extern std::atomic<int64_t> g_nv12Frees; // av_frame_free(&m_currentNV12Frame)
|
||||
extern std::atomic<int64_t> g_cudaHWClones; // m_currentCudaHWFrame = clone
|
||||
extern std::atomic<int64_t> g_cudaHWFrees; // av_frame_free(&m_currentCudaHWFrame)
|
||||
extern std::atomic<int64_t> g_nv12Clones; // m_currentNV12Frame = av_frame_clone (INTERNAL replace-on-update)
|
||||
extern std::atomic<int64_t> g_nv12Frees; // av_frame_free(&m_currentNV12Frame) (INTERNAL)
|
||||
extern std::atomic<int64_t> g_nv12Escapes; // getNV12Frame() clones handed to callers (EXTERNAL — should be balanced by caller's av_frame_free)
|
||||
extern std::atomic<int64_t> g_cudaHWClones; // m_currentCudaHWFrame = clone (INTERNAL)
|
||||
extern std::atomic<int64_t> g_cudaHWFrees; // av_frame_free(&m_currentCudaHWFrame) (INTERNAL)
|
||||
extern std::atomic<int64_t> g_cudaHWEscapes; // getCudaHWFrame() clones handed to callers (EXTERNAL)
|
||||
// Inbound side: AVFrames pushed to pendingFree (drained by gpu_frame_evict_stale).
|
||||
// Incremented in ANSGpuFrameRegistry::pushPendingFree_locked — counts AVFrames that
|
||||
// callers relinquished back to the media layer for deferred freeing. If escapes grow
|
||||
// faster than pendingReturns, the escape path is leaking.
|
||||
extern std::atomic<int64_t> g_avframePendingReturns;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user