Player ID logging

This commit is contained in:
2025-10-11 03:47:22 +09:00
parent ff6b753dfe
commit 51f7762748
9 changed files with 121 additions and 56 deletions

View File

@@ -25,16 +25,21 @@ using namespace winrt::Microsoft::UI::Xaml::Controls;
namespace winrt::Vav2Player::implementation
{
// Initialize static instance counter
std::atomic<int> VideoPlayerControl2::s_instanceCounter{0};
VideoPlayerControl2::VideoPlayerControl2()
: m_instanceId(s_instanceCounter.fetch_add(1))
{
try {
LogMgr::GetInstance().LogInfo(L"VideoPlayerControl2", L"Constructor START - creating core components");
std::wstring logPrefix = L"[Player#" + std::to_wstring(m_instanceId) + L"] ";
LogMgr::GetInstance().LogInfo(L"VideoPlayerControl2", logPrefix + L"Constructor START - creating core components");
// Create core components
m_playbackController = std::make_unique<::Vav2Player::PlaybackController>();
m_frameProcessor = std::make_unique<::Vav2Player::FrameProcessor>();
LogMgr::GetInstance().LogInfo(L"VideoPlayerControl2", L"Constructor END - core components created successfully");
LogMgr::GetInstance().LogInfo(L"VideoPlayerControl2", logPrefix + L"Constructor END - core components created successfully");
}
catch (const std::exception& e) {
std::wstring error = L"Constructor exception: " + std::wstring(e.what(), e.what() + strlen(e.what()));
@@ -66,7 +71,8 @@ namespace winrt::Vav2Player::implementation
void VideoPlayerControl2::UserControl_Loaded(IInspectable const&, RoutedEventArgs const&)
{
LogMgr::GetInstance().LogInfo(L"VideoPlayerControl2", L"UserControl_Loaded");
std::wstring logPrefix = L"[Player#" + std::to_wstring(m_instanceId) + L"] ";
LogMgr::GetInstance().LogInfo(L"VideoPlayerControl2", logPrefix + L"UserControl_Loaded");
try {
// Initialize renderer with SwapChainPanel
@@ -74,9 +80,10 @@ namespace winrt::Vav2Player::implementation
// Connect FrameProcessor to renderer and dispatcher
if (m_frameProcessor && m_gpuRenderer) {
m_frameProcessor->SetPlayerInstanceId(m_instanceId); // Set Player ID for logging
m_frameProcessor->SetRenderer(m_gpuRenderer.get());
m_frameProcessor->SetDispatcherQueue(DispatcherQueue());
LogMgr::GetInstance().LogInfo(L"VideoPlayerControl2", L"FrameProcessor configured");
LogMgr::GetInstance().LogInfo(L"VideoPlayerControl2", logPrefix + L"FrameProcessor configured");
}
m_initialized = true;
@@ -97,7 +104,8 @@ namespace winrt::Vav2Player::implementation
void VideoPlayerControl2::UserControl_Unloaded(IInspectable const&, RoutedEventArgs const&)
{
LogMgr::GetInstance().LogInfo(L"VideoPlayerControl2", L"UserControl_Unloaded");
std::wstring logPrefix = L"[Player#" + std::to_wstring(m_instanceId) + L"] ";
LogMgr::GetInstance().LogInfo(L"VideoPlayerControl2", logPrefix + L"UserControl_Unloaded");
// Stop playback
if (m_playbackController) {
@@ -122,8 +130,9 @@ namespace winrt::Vav2Player::implementation
return;
}
std::wstring logPrefix = L"[Player#" + std::to_wstring(m_instanceId) + L"] ";
LogMgr::GetInstance().LogInfo(L"VideoPlayerControl2",
L"SizeChanged: " + std::to_wstring((int)newSize.Width) + L"x" + std::to_wstring((int)newSize.Height));
logPrefix + L"SizeChanged: " + std::to_wstring((int)newSize.Width) + L"x" + std::to_wstring((int)newSize.Height));
// Update renderer size
if (m_gpuRenderer && m_gpuRenderer->IsInitialized()) {
@@ -267,12 +276,14 @@ namespace winrt::Vav2Player::implementation
void VideoPlayerControl2::LoadVideo(winrt::hstring const& filePath)
{
std::wstring logPrefix = L"[Player#" + std::to_wstring(m_instanceId) + L"] ";
if (!m_initialized) {
LogMgr::GetInstance().LogError(L"VideoPlayerControl2", L"Cannot load video: not initialized");
LogMgr::GetInstance().LogError(L"VideoPlayerControl2", logPrefix + L"Cannot load video: not initialized");
return;
}
LogMgr::GetInstance().LogInfo(L"VideoPlayerControl2", L"Loading video: " + std::wstring(filePath));
LogMgr::GetInstance().LogInfo(L"VideoPlayerControl2", logPrefix + L"Loading video: " + std::wstring(filePath));
UpdateStatus(L"Loading...");
// Stop current playback
@@ -344,12 +355,14 @@ namespace winrt::Vav2Player::implementation
void VideoPlayerControl2::Play()
{
std::wstring logPrefix = L"[Player#" + std::to_wstring(m_instanceId) + L"] ";
if (!m_initialized || !m_playbackController->IsLoaded()) {
LogMgr::GetInstance().LogError(L"VideoPlayerControl2", L"Cannot play: video not loaded");
LogMgr::GetInstance().LogError(L"VideoPlayerControl2", logPrefix + L"Cannot play: video not loaded");
return;
}
LogMgr::GetInstance().LogInfo(L"VideoPlayerControl2", L"Starting playback");
LogMgr::GetInstance().LogInfo(L"VideoPlayerControl2", logPrefix + L"Starting playback");
// Start playback with frame-ready callback
auto weakThis = get_weak();
@@ -364,14 +377,16 @@ namespace winrt::Vav2Player::implementation
void VideoPlayerControl2::Pause()
{
LogMgr::GetInstance().LogInfo(L"VideoPlayerControl2", L"Pausing playback");
std::wstring logPrefix = L"[Player#" + std::to_wstring(m_instanceId) + L"] ";
LogMgr::GetInstance().LogInfo(L"VideoPlayerControl2", logPrefix + L"Pausing playback");
m_playbackController->Pause();
UpdateStatus(L"Paused");
}
void VideoPlayerControl2::Stop()
{
LogMgr::GetInstance().LogInfo(L"VideoPlayerControl2", L"Stopping playback");
std::wstring logPrefix = L"[Player#" + std::to_wstring(m_instanceId) + L"] ";
LogMgr::GetInstance().LogInfo(L"VideoPlayerControl2", logPrefix + L"Stopping playback");
m_playbackController->Stop();
UpdateStatus(L"Stopped");
}
@@ -429,19 +444,21 @@ namespace winrt::Vav2Player::implementation
void VideoPlayerControl2::InitializeRenderer()
{
std::wstring logPrefix = L"[Player#" + std::to_wstring(m_instanceId) + L"] ";
// Cleanup existing renderer if not properly initialized
if (m_gpuRenderer) {
if (m_gpuRenderer->IsInitialized()) {
LogMgr::GetInstance().LogInfo(L"VideoPlayerControl2", L"Renderer already initialized");
LogMgr::GetInstance().LogInfo(L"VideoPlayerControl2", logPrefix + L"Renderer already initialized");
return;
} else {
LogMgr::GetInstance().LogWarning(L"VideoPlayerControl2",
L"Cleaning up partially initialized renderer");
logPrefix + L"Cleaning up partially initialized renderer");
CleanupRenderer();
}
}
LogMgr::GetInstance().LogInfo(L"VideoPlayerControl2", L"Initializing renderer");
LogMgr::GetInstance().LogInfo(L"VideoPlayerControl2", logPrefix + L"Initializing renderer");
m_gpuRenderer = std::make_unique<::Vav2Player::D3D12VideoRenderer>();
@@ -458,17 +475,19 @@ namespace winrt::Vav2Player::implementation
);
if (SUCCEEDED(hr)) {
LogMgr::GetInstance().LogInfo(L"VideoPlayerControl2", L"Renderer initialized successfully");
LogMgr::GetInstance().LogInfo(L"VideoPlayerControl2", logPrefix + L"Renderer initialized successfully");
} else {
LogMgr::GetInstance().LogError(L"VideoPlayerControl2", L"Failed to initialize renderer");
LogMgr::GetInstance().LogError(L"VideoPlayerControl2", logPrefix + L"Failed to initialize renderer");
m_gpuRenderer.reset();
}
}
void VideoPlayerControl2::CleanupRenderer()
{
std::wstring logPrefix = L"[Player#" + std::to_wstring(m_instanceId) + L"] ";
if (m_gpuRenderer) {
LogMgr::GetInstance().LogInfo(L"VideoPlayerControl2", L"Cleaning up renderer");
LogMgr::GetInstance().LogInfo(L"VideoPlayerControl2", logPrefix + L"Cleaning up renderer");
m_gpuRenderer->Shutdown();
m_gpuRenderer.reset();
}

View File

@@ -8,6 +8,7 @@
#include <memory>
#include <string>
#include <atomic>
namespace winrt::Vav2Player::implementation
{
@@ -16,6 +17,9 @@ namespace winrt::Vav2Player::implementation
VideoPlayerControl2();
~VideoPlayerControl2();
// Get unique instance ID for logging
int GetInstanceId() const { return m_instanceId; }
// XAML event handlers
void UserControl_Loaded(winrt::Windows::Foundation::IInspectable const& sender,
winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
@@ -58,6 +62,12 @@ namespace winrt::Vav2Player::implementation
double PlaybackSpeed();
private:
// Static instance counter for unique IDs
static std::atomic<int> s_instanceCounter;
// Unique instance ID for logging
int m_instanceId;
// Core components (composition)
std::unique_ptr<::Vav2Player::PlaybackController> m_playbackController;
std::unique_ptr<::Vav2Player::FrameProcessor> m_frameProcessor;

View File

@@ -0,0 +1,12 @@
#pragma once
// VideoPlayerControl2 Configuration Constants
// Shared across FrameProcessor, RGBASurfaceBackend, and other components
namespace Vav2Player {
// Triple buffering configuration for smooth rendering
// Textures: 0 (rendering), 1 (next decode), 2 (idle/previously decoded)
constexpr int VAV2PLAYER_TRIPLE_BUFFER_SIZE = 3;
} // namespace Vav2Player

View File

@@ -3,6 +3,7 @@
#include "../Utils/DecoderTypeUtils.h"
#include "../Logger/SimpleLogger.h"
#include "../Logger/LogManager.h"
#include "../Config/VideoPlayerConfig.h"
#include <iostream>
#include <Windows.h>
@@ -20,6 +21,11 @@ FrameProcessor::~FrameProcessor()
}
}
void FrameProcessor::SetPlayerInstanceId(int playerId)
{
m_playerInstanceId = playerId;
}
void FrameProcessor::SetRenderer(D3D12VideoRenderer* renderer)
{
m_renderer = renderer;
@@ -37,13 +43,13 @@ void FrameProcessor::SetDecoderType(VavCoreDecoderType type)
// Log to UI (LogManager)
std::wstring decoderTypeName(Utils::GetDecoderTypeName(type),
Utils::GetDecoderTypeName(type) + strlen(Utils::GetDecoderTypeName(type)));
std::wstring logMsg = L"Decoder type set to: " + decoderTypeName +
std::wstring logMsg = L"[Player#" + std::to_wstring(m_playerInstanceId) + L"] Decoder type set to: " + decoderTypeName +
L" (type=" + std::to_wstring(static_cast<int>(type)) + L")";
LogManager::GetInstance().LogInfo(logMsg, L"FrameProcessor");
// Also log to console for debugging
LOGF_INFO("[FrameProcessor] Decoder type set to: %s (type=%d)",
Utils::GetDecoderTypeName(type), static_cast<int>(type));
LOGF_INFO("[Player#%d] [FrameProcessor] Decoder type set to: %s (type=%d)",
m_playerInstanceId, Utils::GetDecoderTypeName(type), static_cast<int>(type));
}
void FrameProcessor::PrepareVideoTexture(uint32_t width, uint32_t height)
@@ -59,7 +65,7 @@ bool FrameProcessor::ProcessFrame(VavCorePlayer* player,
auto processStart = std::chrono::high_resolution_clock::now();
if (!player || !m_renderer || !m_dispatcherQueue) {
LOGF_ERROR("[FrameProcessor] Invalid state: missing player/renderer/dispatcherQueue");
LOGF_ERROR("[Player#%d] [FrameProcessor] Invalid state: missing player/renderer/dispatcherQueue", m_playerInstanceId);
return false;
}
@@ -67,8 +73,8 @@ bool FrameProcessor::ProcessFrame(VavCorePlayer* player,
bool expected = false;
if (!m_frameProcessing.compare_exchange_strong(expected, true)) {
m_framesDropped++;
LOGF_ERROR("[FrameProcessor] FRAME DROPPED (#%llu) - previous frame still processing",
m_framesDropped.load());
LOGF_ERROR("[Player#%d] [FrameProcessor] FRAME DROPPED (#%llu) - previous frame still processing",
m_playerInstanceId, m_framesDropped.load());
return false;
}
@@ -79,19 +85,20 @@ bool FrameProcessor::ProcessFrame(VavCorePlayer* player,
if (m_decoderType == VAVCORE_DECODER_DAV1D) {
// DAV1D: CPU decoding only
LOGF_DEBUG("[FrameProcessor] Using DAV1D CPU decode path");
LOGF_DEBUG("[Player#%d] [FrameProcessor] Using DAV1D CPU decode path", m_playerInstanceId);
result = vavcore_decode_next_frame(player, &vavFrame);
if (result == VAVCORE_SUCCESS) {
vavFrame.surface_type = VAVCORE_SURFACE_CPU;
LOGF_DEBUG("[FrameProcessor] DAV1D decode success, surface_type=CPU");
LOGF_DEBUG("[Player#%d] [FrameProcessor] DAV1D decode success, surface_type=CPU", m_playerInstanceId);
}
} else {
// NVDEC/Hardware: D3D12 surface decoding with CUDA DPB buffering
// Phase 1: Initial 16-frame buffering (NULL surface)
// First 16 packets are submitted without D3D12 surface to fill CUDA DPB
if (m_framesDecoded < 16) {
LOGF_DEBUG("[FrameProcessor] Initial buffering phase: frame %llu/16", m_framesDecoded.load());
// Phase 1: Initial NVDEC DPB buffering (NULL surface)
// First N packets are submitted without D3D12 surface to fill CUDA DPB for B-frame reordering
if (m_framesDecoded < VAVCORE_NVDEC_INITIAL_BUFFERING) {
LOGF_DEBUG("[Player#%d] [FrameProcessor] Initial buffering phase: frame %llu/%d",
m_playerInstanceId, m_framesDecoded.load(), VAVCORE_NVDEC_INITIAL_BUFFERING);
result = vavcore_decode_to_surface(
player,
@@ -103,12 +110,12 @@ bool FrameProcessor::ProcessFrame(VavCorePlayer* player,
// Expected: VAVCORE_PACKET_ACCEPTED for first 16 frames
// No rendering during buffering phase
}
// Phase 2: Triple buffer filling (frames 16-18)
// Phase 2: Triple buffer filling (frames INITIAL_BUFFERING to INITIAL_BUFFERING+TRIPLE_BUFFER_SIZE-1)
// Fill textures 0, 1, 2 before starting normal operation
else if (m_framesDecoded < 19) {
else if (m_framesDecoded < VAVCORE_NVDEC_INITIAL_BUFFERING + VAV2PLAYER_TRIPLE_BUFFER_SIZE) {
auto backend = m_renderer->GetRGBASurfaceBackend();
if (!backend) {
LOGF_ERROR("[FrameProcessor] Failed to get RGBASurfaceBackend");
LOGF_ERROR("[Player#%d] [FrameProcessor] Failed to get RGBASurfaceBackend", m_playerInstanceId);
m_frameProcessing.store(false);
if (onComplete) onComplete(false);
return false;
@@ -116,8 +123,8 @@ bool FrameProcessor::ProcessFrame(VavCorePlayer* player,
ID3D12Resource* decodeTexture = backend->GetNextDecodeTexture();
int decodeIndex = backend->GetDecodeTextureIndex();
LOGF_INFO("[FrameProcessor] Triple buffer filling: frame %llu -> texture[%d]",
m_framesDecoded.load(), decodeIndex);
LOGF_INFO("[Player#%d] [FrameProcessor] Triple buffer filling: frame %llu -> texture[%d]",
m_playerInstanceId, m_framesDecoded.load(), decodeIndex);
result = vavcore_decode_to_surface(
player,
@@ -129,15 +136,15 @@ bool FrameProcessor::ProcessFrame(VavCorePlayer* player,
// After successful decode, advance decode index only (render index stays at 0)
if (result == VAVCORE_SUCCESS) {
backend->AdvanceDecodeOnly();
LOGF_INFO("[FrameProcessor] Triple buffer filled: texture[%d] ready", decodeIndex);
LOGF_INFO("[Player#%d] [FrameProcessor] Triple buffer filled: texture[%d] ready", m_playerInstanceId, decodeIndex);
}
}
// Phase 3: Normal operation (frame 19+)
// Phase 3: Normal operation (frame INITIAL_BUFFERING+TRIPLE_BUFFER_SIZE onwards)
// Render from current texture, decode into next texture
else {
auto backend = m_renderer->GetRGBASurfaceBackend();
if (!backend) {
LOGF_ERROR("[FrameProcessor] Failed to get RGBASurfaceBackend");
LOGF_ERROR("[Player#%d] [FrameProcessor] Failed to get RGBASurfaceBackend", m_playerInstanceId);
m_frameProcessing.store(false);
if (onComplete) onComplete(false);
return false;
@@ -146,8 +153,8 @@ bool FrameProcessor::ProcessFrame(VavCorePlayer* player,
ID3D12Resource* decodeTexture = backend->GetNextDecodeTexture();
int decodeIndex = backend->GetDecodeTextureIndex();
int renderIndex = backend->GetRenderTextureIndex();
LOGF_DEBUG("[FrameProcessor] Normal operation: render[%d], decode[%d]",
renderIndex, decodeIndex);
LOGF_DEBUG("[Player#%d] [FrameProcessor] Normal operation: render[%d], decode[%d]",
m_playerInstanceId, renderIndex, decodeIndex);
result = vavcore_decode_to_surface(
player,
@@ -159,8 +166,8 @@ bool FrameProcessor::ProcessFrame(VavCorePlayer* player,
// After successful decode, advance frame indices
if (result == VAVCORE_SUCCESS) {
backend->AdvanceFrame();
LOGF_DEBUG("[FrameProcessor] Frame advanced: render[%d]->render[%d]",
renderIndex, backend->GetRenderTextureIndex());
LOGF_DEBUG("[Player#%d] [FrameProcessor] Frame advanced: render[%d]->render[%d]",
m_playerInstanceId, renderIndex, backend->GetRenderTextureIndex());
}
}
}
@@ -170,7 +177,7 @@ bool FrameProcessor::ProcessFrame(VavCorePlayer* player,
if (result != VAVCORE_SUCCESS) {
if (result == VAVCORE_END_OF_STREAM) {
LOGF_INFO("[FrameProcessor] End of stream");
LOGF_INFO("[Player#%d] [FrameProcessor] End of stream", m_playerInstanceId);
m_frameProcessing.store(false);
if (onComplete) onComplete(true);
return false;
@@ -180,7 +187,7 @@ bool FrameProcessor::ProcessFrame(VavCorePlayer* player,
// VavCore CUDA DPB buffering: Packet was accepted and buffered internally
// This happens during initial 16-frame buffering or when DPB needs more frames
// No frame is ready yet - VavCore will return it in a future call
LOGF_DEBUG("[FrameProcessor] PACKET ACCEPTED - Frame buffered in VavCore CUDA DPB (16-frame buffering)");
LOGF_DEBUG("[Player#%d] [FrameProcessor] PACKET ACCEPTED - Frame buffered in VavCore CUDA DPB (16-frame buffering)", m_playerInstanceId);
// CRITICAL: Increment m_framesDecoded for buffered packets
// This counter determines when we switch from NULL surface (buffering) to valid surface (rendering)
@@ -197,14 +204,14 @@ bool FrameProcessor::ProcessFrame(VavCorePlayer* player,
// All other errors (not SUCCESS, not END_OF_STREAM, not PACKET_ACCEPTED)
m_decodeErrors++;
LOGF_ERROR("[FrameProcessor] Decode ERROR: result=%d", result);
LOGF_ERROR("[Player#%d] [FrameProcessor] Decode ERROR: result=%d", m_playerInstanceId, result);
m_frameProcessing.store(false);
if (onComplete) onComplete(false);
return false;
}
m_framesDecoded++;
LOGF_INFO("[FrameProcessor] DECODE: %.1f ms", decodeTime);
LOGF_INFO("[Player#%d] [FrameProcessor] DECODE: %.1f ms", m_playerInstanceId, decodeTime);
// Enqueue render on UI thread
@@ -221,7 +228,7 @@ bool FrameProcessor::ProcessFrame(VavCorePlayer* player,
if (!renderSuccess) {
m_renderErrors++;
LOGF_ERROR("[FrameProcessor] Render error: HRESULT = 0x%08X", hr);
LOGF_ERROR("[Player#%d] [FrameProcessor] Render error: HRESULT = 0x%08X", m_playerInstanceId, hr);
}
// Present to screen
@@ -232,14 +239,14 @@ bool FrameProcessor::ProcessFrame(VavCorePlayer* player,
double presentTime = std::chrono::duration<double, std::milli>(presentEnd - presentStart).count();
if (FAILED(hr)) {
LOGF_ERROR("[FrameProcessor] Present error: HRESULT = 0x%08X", hr);
LOGF_ERROR("[Player#%d] [FrameProcessor] Present error: HRESULT = 0x%08X", m_playerInstanceId, hr);
renderSuccess = false;
} else {
// Single consolidated timing log
auto totalEnd = std::chrono::high_resolution_clock::now();
double totalTime = std::chrono::duration<double, std::milli>(totalEnd - processStart).count();
LOGF_INFO("[FrameProcessor] RENDER: %.1f ms | PRESENT: %.1f ms | QUEUE_DELAY: %.1f ms | TOTAL: %.1f ms",
renderTime, presentTime, queueDelay, totalTime);
LOGF_INFO("[Player#%d] [FrameProcessor] RENDER: %.1f ms | PRESENT: %.1f ms | QUEUE_DELAY: %.1f ms | TOTAL: %.1f ms",
m_playerInstanceId, renderTime, presentTime, queueDelay, totalTime);
}
}
@@ -251,7 +258,7 @@ bool FrameProcessor::ProcessFrame(VavCorePlayer* player,
});
if (!enqueued) {
LOGF_ERROR("[FrameProcessor] TryEnqueue FAILED");
LOGF_ERROR("[Player#%d] [FrameProcessor] TryEnqueue FAILED", m_playerInstanceId);
m_frameProcessing.store(false);
if (onComplete) onComplete(false);
return false;

View File

@@ -20,6 +20,9 @@ public:
FrameProcessor();
~FrameProcessor();
// Set player instance ID for logging
void SetPlayerInstanceId(int playerId);
// Set renderer for frame output
void SetRenderer(D3D12VideoRenderer* renderer);
@@ -52,6 +55,9 @@ private:
D3D12VideoRenderer* m_renderer = nullptr; // Non-owning pointer
winrt::Microsoft::UI::Dispatching::DispatcherQueue m_dispatcherQueue{ nullptr };
// Player identification for logging
int m_playerInstanceId = -1;
// Decoder configuration
VavCoreDecoderType m_decoderType = VAVCORE_DECODER_AUTO;

View File

@@ -1,6 +1,7 @@
#pragma once
#include "IVideoBackend.h"
#include "../Config/VideoPlayerConfig.h"
#include <d3dcompiler.h>
namespace Vav2Player {
@@ -83,7 +84,7 @@ private:
// - m_renderTextureIndex: Currently rendering to screen (safe to read)
// - m_decodeTextureIndex: Next target for decoding (safe to write)
// - Third texture: Idle, previously decoded (ready to become render texture)
static const int BUFFER_COUNT = 3;
static const int BUFFER_COUNT = VAV2PLAYER_TRIPLE_BUFFER_SIZE;
ComPtr<ID3D12Resource> m_rgbaTextures[BUFFER_COUNT];
int m_renderTextureIndex = 0; // Texture currently being rendered
int m_decodeTextureIndex = 0; // Texture for next decode operation

View File

@@ -52,6 +52,11 @@ typedef enum {
VAVCORE_DECODER_MEDIACODEC = 6 // Android MediaCodec decoder
} VavCoreDecoderType;
// NVDEC decoder configuration constants
// These control NVDEC's internal DPB (Decoded Picture Buffer) and reordering behavior
#define VAVCORE_NVDEC_DPB_SIZE 16 // NVDEC internal ring buffer size (16 frame slots)
#define VAVCORE_NVDEC_INITIAL_BUFFERING 16 // Initial buffering frames before first render (reduced for faster startup)
// Surface types for cross-platform direct decoding
typedef enum {
VAVCORE_SURFACE_CPU = 0, // Traditional CPU memory

View File

@@ -281,14 +281,18 @@ void NVDECAV1Decoder::Cleanup() {
CUcontext currentCtx = nullptr;
CUresult ctxResult = cuCtxGetCurrent(&currentCtx);
if (ctxResult == CUDA_SUCCESS && currentCtx != nullptr) {
if (ctxResult == CUDA_SUCCESS && currentCtx != nullptr && currentCtx == m_cuContext) {
// CUDA takes ownership of the shared handle when importing the semaphore
// It will be closed automatically when destroying the semaphore
cudaDestroyExternalSemaphore(m_cudaSemaphore);
cudaError_t cudaStatus = cudaDestroyExternalSemaphore(m_cudaSemaphore);
if (cudaStatus != cudaSuccess) {
LOGF_WARNING("[NVDECAV1Decoder::Cleanup] cudaDestroyExternalSemaphore failed: %d", cudaStatus);
}
m_cudaSemaphore = nullptr;
} else {
// CUDA context not available, just null out the pointer
LOGF_WARNING("[NVDECAV1Decoder::Cleanup] CUDA context not current, skipping semaphore cleanup");
LOGF_WARNING("[NVDECAV1Decoder::Cleanup] CUDA context not current (current=%p, expected=%p), skipping semaphore cleanup",
currentCtx, m_cuContext);
m_cudaSemaphore = nullptr;
}
}

View File

@@ -166,7 +166,8 @@ private:
// RingBuffer for asynchronous decoding
// Note: NVDEC may request more surfaces than ulNumOutputSurfaces (e.g., 9 for some videos)
static constexpr size_t RING_BUFFER_SIZE = 16;
// Use VavCore.h defined constant for consistency across codebase
static constexpr size_t RING_BUFFER_SIZE = VAVCORE_NVDEC_DPB_SIZE;
// FrameSlot: Represents a decoded frame in VavCore's DPB
// Renamed from DecodeSlot for semantic clarity (not NVDEC's internal decode surface slot)