Player ID logging
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -281,14 +281,18 @@ void NVDECAV1Decoder::Cleanup() {
|
||||
CUcontext currentCtx = nullptr;
|
||||
CUresult ctxResult = cuCtxGetCurrent(¤tCtx);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user