Rollback to commit windows stable hash 146a861
This commit is contained in:
@@ -1,10 +1,7 @@
|
||||
// VavCore_Windows_Full.cpp - Complete Windows implementation of VavCore C API
|
||||
// All platform-specific code consolidated in this file
|
||||
|
||||
#include "pch.h"
|
||||
#include "VavCore/VavCore.h"
|
||||
#include "Common/VideoTypes.h"
|
||||
#include "Common/AdaptiveTypes.h"
|
||||
#include "Common/VideoTypes.h" // Internal VavCore types
|
||||
#include "Common/AdaptiveTypes.h" // Adaptive types
|
||||
#include "Decoder/IVideoDecoder.h"
|
||||
#include "Decoder/VideoDecoderFactory.h"
|
||||
#include "FileIO/WebMFileReader.h"
|
||||
@@ -15,6 +12,7 @@
|
||||
#include <mutex>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
// Use VavCore namespace internally
|
||||
using namespace VavCore;
|
||||
|
||||
@@ -22,10 +20,15 @@ using namespace VavCore;
|
||||
extern "C" bool PerformSafeDllInitialization();
|
||||
extern "C" bool IsDllReadyForInitialization();
|
||||
|
||||
// Forward declarations for decoder registration functions
|
||||
extern "C" void RegisterAV1Decoders();
|
||||
|
||||
// Global state
|
||||
static bool g_initialized = false;
|
||||
static bool g_jni_loaded = false;
|
||||
static std::mutex g_mutex;
|
||||
|
||||
|
||||
// Error message mapping
|
||||
static const char* get_error_message(VavCoreResult result) {
|
||||
switch (result) {
|
||||
@@ -45,7 +48,7 @@ class VavCorePlayerImpl;
|
||||
|
||||
// C-compatible player structure (pimpl pattern)
|
||||
struct VavCorePlayer {
|
||||
VavCorePlayerImpl* impl;
|
||||
VavCorePlayerImpl* impl; // Opaque pointer to C++ implementation
|
||||
};
|
||||
|
||||
// C++ implementation class (hidden from C API)
|
||||
@@ -65,9 +68,15 @@ public:
|
||||
void* pendingD3DDevice;
|
||||
VavCoreSurfaceType pendingD3DSurfaceType;
|
||||
|
||||
// Store Vulkan device before decoder creation
|
||||
void* vulkan_device;
|
||||
void* vulkan_instance;
|
||||
void* vulkan_physical_device;
|
||||
bool has_vulkan_device;
|
||||
|
||||
// Debug options
|
||||
VavCoreDebugOptions debugOptions;
|
||||
std::string debugOutputPath;
|
||||
std::string debugOutputPath; // Owned copy of debug_output_path
|
||||
|
||||
VavCorePlayerImpl()
|
||||
: qualityMode(VAVCORE_QUALITY_CONSERVATIVE)
|
||||
@@ -78,10 +87,15 @@ public:
|
||||
, decoderName("unknown")
|
||||
, pendingD3DDevice(nullptr)
|
||||
, pendingD3DSurfaceType(VAVCORE_SURFACE_CPU)
|
||||
, vulkan_device(nullptr)
|
||||
, vulkan_instance(nullptr)
|
||||
, vulkan_physical_device(nullptr)
|
||||
, has_vulkan_device(false)
|
||||
, debugOutputPath("./debug_output")
|
||||
{
|
||||
fileReader = std::make_unique<WebMFileReader>();
|
||||
|
||||
// Initialize debug options with defaults
|
||||
debugOptions.enable_first_frame_debug = false;
|
||||
debugOptions.first_frame_debug_count = 3;
|
||||
debugOptions.enable_rgba_debug = false;
|
||||
@@ -136,20 +150,25 @@ static void copy_frame_data(const VideoFrame& src, VavCoreVideoFrame* dst) {
|
||||
|
||||
dst->width = src.width;
|
||||
dst->height = src.height;
|
||||
dst->timestamp_us = static_cast<uint64_t>(src.timestamp_seconds * 1000000.0);
|
||||
dst->timestamp_us = static_cast<uint64_t>(src.timestamp_seconds * 1000000.0); // Convert seconds to microseconds
|
||||
dst->frame_number = src.frame_index;
|
||||
|
||||
// Set default surface type to CPU
|
||||
dst->surface_type = VAVCORE_SURFACE_CPU;
|
||||
|
||||
// Use actual plane sizes from source frame
|
||||
size_t y_size = src.y_size;
|
||||
size_t u_size = src.u_size;
|
||||
size_t v_size = src.v_size;
|
||||
|
||||
// Allocate memory for frame data
|
||||
dst->y_plane = static_cast<uint8_t*>(malloc(y_size));
|
||||
dst->u_plane = static_cast<uint8_t*>(malloc(u_size));
|
||||
dst->v_plane = static_cast<uint8_t*>(malloc(v_size));
|
||||
|
||||
if (dst->y_plane && dst->u_plane && dst->v_plane &&
|
||||
src.y_plane && src.u_plane && src.v_plane) {
|
||||
// Copy frame data from individual planes
|
||||
memcpy(dst->y_plane, src.y_plane.get(), y_size);
|
||||
memcpy(dst->u_plane, src.u_plane.get(), u_size);
|
||||
memcpy(dst->v_plane, src.v_plane.get(), v_size);
|
||||
@@ -159,6 +178,7 @@ static void copy_frame_data(const VideoFrame& src, VavCoreVideoFrame* dst) {
|
||||
dst->u_stride = src.u_stride;
|
||||
dst->v_stride = src.v_stride;
|
||||
|
||||
// Initialize CPU surface data for backward compatibility
|
||||
dst->surface_data.cpu.planes[0] = dst->y_plane;
|
||||
dst->surface_data.cpu.planes[1] = dst->u_plane;
|
||||
dst->surface_data.cpu.planes[2] = dst->v_plane;
|
||||
@@ -167,10 +187,7 @@ static void copy_frame_data(const VideoFrame& src, VavCoreVideoFrame* dst) {
|
||||
dst->surface_data.cpu.strides[2] = dst->v_stride;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// C API Implementation - Windows Platform
|
||||
// ============================================================================
|
||||
|
||||
// API Implementation
|
||||
extern "C" {
|
||||
|
||||
VAVCORE_API VavCoreResult vavcore_initialize(void) {
|
||||
@@ -180,22 +197,19 @@ VAVCORE_API VavCoreResult vavcore_initialize(void) {
|
||||
return VAVCORE_SUCCESS;
|
||||
}
|
||||
|
||||
// Windows-specific: Check if DLL is ready for safe initialization
|
||||
// Check if DLL is ready for safe initialization
|
||||
if (!IsDllReadyForInitialization()) {
|
||||
LOGF_ERROR("[VavCore Windows] DLL not ready for initialization");
|
||||
return VAVCORE_ERROR_INIT_FAILED;
|
||||
}
|
||||
|
||||
// Windows-specific: Perform safe DLL-level initialization
|
||||
// Perform safe DLL-level initialization
|
||||
if (!PerformSafeDllInitialization()) {
|
||||
LOGF_ERROR("[VavCore Windows] DLL initialization failed");
|
||||
return VAVCORE_ERROR_INIT_FAILED;
|
||||
}
|
||||
|
||||
// Initialize decoder factory (Windows uses static initialization for decoder registration)
|
||||
// Initialize decoder factory
|
||||
VideoDecoderFactory::InitializeFactory();
|
||||
g_initialized = true;
|
||||
LOGF_INFO("[VavCore Windows] Initialization complete");
|
||||
return VAVCORE_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -203,8 +217,8 @@ VAVCORE_API void vavcore_cleanup(void) {
|
||||
std::lock_guard<std::mutex> lock(g_mutex);
|
||||
|
||||
if (g_initialized) {
|
||||
// Cleanup subsystems
|
||||
g_initialized = false;
|
||||
LOGF_INFO("[VavCore Windows] Cleanup complete");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,6 +242,7 @@ VAVCORE_API VavCorePlayer* vavcore_create_player(void) {
|
||||
VavCorePlayer* player = new VavCorePlayer();
|
||||
player->impl = new VavCorePlayerImpl();
|
||||
|
||||
// Verify fileReader was created successfully
|
||||
if (!player->impl->fileReader) {
|
||||
delete player->impl;
|
||||
delete player;
|
||||
@@ -254,13 +269,16 @@ VAVCORE_API VavCoreResult vavcore_open_file(VavCorePlayer* player, const char* f
|
||||
return VAVCORE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
// Verify fileReader exists before proceeding
|
||||
if (!player->impl->fileReader) {
|
||||
return VAVCORE_ERROR_INIT_FAILED;
|
||||
}
|
||||
|
||||
try {
|
||||
// Debug log
|
||||
LOGF_DEBUG("[VavCore] Opening file: %s", filepath);
|
||||
|
||||
// Open file with WebM reader
|
||||
if (!player->impl->fileReader->OpenFile(filepath)) {
|
||||
LOGF_DEBUG("[VavCore] OpenFile() returned false");
|
||||
return VAVCORE_ERROR_FILE_NOT_FOUND;
|
||||
@@ -268,7 +286,9 @@ VAVCORE_API VavCoreResult vavcore_open_file(VavCorePlayer* player, const char* f
|
||||
|
||||
LOGF_DEBUG("[VavCore] OpenFile() succeeded");
|
||||
|
||||
// Get video tracks and select the first AV1 track
|
||||
auto tracks = player->impl->fileReader->GetVideoTracks();
|
||||
|
||||
LOGF_DEBUG("[VavCore] Found %zu video tracks", tracks.size());
|
||||
|
||||
bool foundAV1 = false;
|
||||
@@ -280,6 +300,7 @@ VAVCORE_API VavCoreResult vavcore_open_file(VavCorePlayer* player, const char* f
|
||||
LOGF_DEBUG("[VavCore] AV1 track found! Selecting track...");
|
||||
if (player->impl->fileReader->SelectVideoTrack(track.track_number)) {
|
||||
LOGF_DEBUG("[VavCore] Track selected successfully");
|
||||
// Get full metadata from WebMFileReader (includes codec_private_data)
|
||||
player->impl->metadata = player->impl->fileReader->GetVideoMetadata();
|
||||
foundAV1 = true;
|
||||
break;
|
||||
@@ -293,10 +314,11 @@ VAVCORE_API VavCoreResult vavcore_open_file(VavCorePlayer* player, const char* f
|
||||
return VAVCORE_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
// Create appropriate decoder
|
||||
LOGF_DEBUG("[VavCore] Creating decoder...");
|
||||
auto decoderType = to_decoder_type(player->impl->decoderType);
|
||||
|
||||
LOGF_DEBUG("[VavCore] Decoder type requested: %d (0=AUTO, 1=NVDEC, 2=VPL, 3=AMF, 4=DAV1D, 5=MF)",
|
||||
LOGF_DEBUG("[VavCore] Decoder type requested: %d (0=AUTO, 1=NVDEC, 2=VPL, 3=AMF, 4=DAV1D, 5=MF, 6=MEDIACODEC)",
|
||||
static_cast<int>(decoderType));
|
||||
|
||||
player->impl->decoder = VavCore::VideoDecoderFactory::CreateDecoder(VavCore::VideoCodecType::AV1, decoderType);
|
||||
@@ -309,7 +331,7 @@ VAVCORE_API VavCoreResult vavcore_open_file(VavCorePlayer* player, const char* f
|
||||
|
||||
LOGF_DEBUG("[VavCore] Decoder created successfully.");
|
||||
|
||||
// Windows-specific: Apply pending D3D device if it was set before decoder creation
|
||||
// Apply pending D3D device if it was set before decoder creation
|
||||
if (player->impl->pendingD3DDevice) {
|
||||
LOGF_DEBUG("[VavCore] Applying pending D3D device before decoder initialization...");
|
||||
LOGF_DEBUG("[VavCore] Pending D3D device: %p, Type: %d",
|
||||
@@ -317,12 +339,14 @@ VAVCORE_API VavCoreResult vavcore_open_file(VavCorePlayer* player, const char* f
|
||||
|
||||
player->impl->decoder->SetD3DDevice(player->impl->pendingD3DDevice, player->impl->pendingD3DSurfaceType);
|
||||
|
||||
// Clear pending device after applying
|
||||
player->impl->pendingD3DDevice = nullptr;
|
||||
player->impl->pendingD3DSurfaceType = VAVCORE_SURFACE_CPU;
|
||||
}
|
||||
|
||||
LOGF_DEBUG("[VavCore] Initializing decoder...");
|
||||
|
||||
// Initialize decoder
|
||||
if (!player->impl->decoder->Initialize(player->impl->metadata)) {
|
||||
LOGF_ERROR("[VavCore] Decoder initialization failed (unsupported format or hardware unavailable)");
|
||||
player->impl->decoder.reset();
|
||||
@@ -332,11 +356,23 @@ VAVCORE_API VavCoreResult vavcore_open_file(VavCorePlayer* player, const char* f
|
||||
|
||||
LOGF_DEBUG("[VavCore] Decoder initialized successfully!");
|
||||
|
||||
|
||||
// Apply debug options to newly created decoder
|
||||
player->impl->decoder->SetDebugOptions(&player->impl->debugOptions);
|
||||
LOGF_DEBUG("[VavCore] Debug options applied to decoder");
|
||||
|
||||
// Store the actual decoder name for later retrieval
|
||||
player->impl->decoderName = player->impl->decoder->GetCodecName();
|
||||
|
||||
// Set adaptive quality mode if supported
|
||||
// TODO: Implement adaptive quality support in VavCore v1.1
|
||||
// Currently disabled as adaptive decoders don't implement IAdaptiveVideoDecoder interface yet
|
||||
// auto adaptiveDecoder = dynamic_cast<VavCore::IAdaptiveVideoDecoder*>(player->impl->decoder.get());
|
||||
// if (adaptiveDecoder) {
|
||||
// adaptiveDecoder->SetQualityMode(to_adaptive_quality_mode(player->impl->qualityMode));
|
||||
// }
|
||||
|
||||
// Final verification - both fileReader and decoder should be ready
|
||||
if (!player->impl->fileReader || !player->impl->decoder) {
|
||||
if (player->impl->fileReader) {
|
||||
player->impl->fileReader->CloseFile();
|
||||
@@ -378,16 +414,19 @@ VAVCORE_API VavCoreResult vavcore_decode_next_frame(VavCorePlayer* player, VavCo
|
||||
}
|
||||
|
||||
try {
|
||||
// Read next packet
|
||||
VideoPacket packet;
|
||||
if (!player->impl->fileReader->ReadNextPacket(packet)) {
|
||||
return VAVCORE_END_OF_STREAM;
|
||||
return VAVCORE_END_OF_STREAM; // End of file
|
||||
}
|
||||
|
||||
// Decode frame
|
||||
VideoFrame videoFrame;
|
||||
if (!player->impl->decoder->DecodeFrame(packet, videoFrame)) {
|
||||
return VAVCORE_ERROR_DECODE_FAILED;
|
||||
}
|
||||
|
||||
// Copy frame data to C structure
|
||||
copy_frame_data(videoFrame, frame);
|
||||
|
||||
player->impl->currentFrame++;
|
||||
@@ -432,6 +471,7 @@ VAVCORE_API VavCoreResult vavcore_seek_to_frame(VavCorePlayer* player, uint64_t
|
||||
}
|
||||
}
|
||||
|
||||
// Test function to verify linking
|
||||
VAVCORE_API VavCoreResult vavcore_test_function(void) {
|
||||
return VAVCORE_SUCCESS;
|
||||
}
|
||||
@@ -446,6 +486,7 @@ VAVCORE_API VavCoreResult vavcore_reset(VavCorePlayer* player) {
|
||||
}
|
||||
|
||||
try {
|
||||
// Reset decoder if available
|
||||
if (player->impl->decoder) {
|
||||
if (!player->impl->decoder->Reset()) {
|
||||
// Continue anyway - not fatal
|
||||
@@ -454,6 +495,7 @@ VAVCORE_API VavCoreResult vavcore_reset(VavCorePlayer* player) {
|
||||
return VAVCORE_ERROR_INIT_FAILED;
|
||||
}
|
||||
|
||||
// Reset file reader if available
|
||||
if (player->impl->fileReader) {
|
||||
if (!player->impl->fileReader->Reset()) {
|
||||
// Continue anyway - not fatal
|
||||
@@ -462,6 +504,7 @@ VAVCORE_API VavCoreResult vavcore_reset(VavCorePlayer* player) {
|
||||
return VAVCORE_ERROR_INIT_FAILED;
|
||||
}
|
||||
|
||||
// Reset state variables
|
||||
player->impl->currentFrame = 0;
|
||||
player->impl->currentTimeSeconds = 0.0;
|
||||
|
||||
@@ -484,7 +527,7 @@ VAVCORE_API VavCoreResult vavcore_get_metadata(VavCorePlayer* player, VavCoreVid
|
||||
metadata->frame_rate = player->impl->metadata.frame_rate;
|
||||
metadata->duration_seconds = player->impl->metadata.duration_seconds;
|
||||
metadata->total_frames = player->impl->metadata.total_frames;
|
||||
metadata->codec_name = "AV1";
|
||||
metadata->codec_name = "AV1"; // Static for now
|
||||
|
||||
return VAVCORE_SUCCESS;
|
||||
}
|
||||
@@ -499,7 +542,7 @@ VAVCORE_API double vavcore_get_current_time(VavCorePlayer* player) {
|
||||
|
||||
VAVCORE_API int vavcore_is_end_of_file(VavCorePlayer* player) {
|
||||
if (!player || !player->impl || !player->impl->isOpen || !player->impl->fileReader) {
|
||||
return 1;
|
||||
return 1; // Consider as EOF if invalid
|
||||
}
|
||||
return player->impl->fileReader->IsEndOfFile() ? 1 : 0;
|
||||
}
|
||||
@@ -520,6 +563,10 @@ VAVCORE_API VavCoreResult vavcore_set_quality_mode(VavCorePlayer* player, VavCor
|
||||
|
||||
if (player->impl->isOpen && player->impl->decoder) {
|
||||
// TODO: Implement adaptive quality support in VavCore v1.1
|
||||
// auto adaptiveDecoder = dynamic_cast<VavCore::IAdaptiveVideoDecoder*>(player->impl->decoder.get());
|
||||
// if (adaptiveDecoder) {
|
||||
// adaptiveDecoder->SetQualityMode(to_adaptive_quality_mode(mode));
|
||||
// }
|
||||
}
|
||||
|
||||
return VAVCORE_SUCCESS;
|
||||
@@ -535,8 +582,19 @@ VAVCORE_API VavCoreResult vavcore_get_performance_metrics(VavCorePlayer* player,
|
||||
}
|
||||
|
||||
// TODO: Implement adaptive performance metrics in VavCore v1.1
|
||||
memset(metrics, 0, sizeof(VavCorePerformanceMetrics));
|
||||
metrics->current_quality_level = 4;
|
||||
// auto adaptiveDecoder = dynamic_cast<VavCore::IAdaptiveVideoDecoder*>(player->decoder.get());
|
||||
// if (adaptiveDecoder) {
|
||||
// auto perfMetrics = adaptiveDecoder->GetPerformanceMetrics();
|
||||
// metrics->average_decode_time_ms = perfMetrics.average_decode_time_ms;
|
||||
// metrics->current_fps = perfMetrics.current_fps;
|
||||
// metrics->frames_decoded = perfMetrics.frames_decoded;
|
||||
// metrics->frames_dropped = perfMetrics.frames_dropped;
|
||||
// metrics->current_quality_level = static_cast<int>(adaptiveDecoder->GetCurrentQualityLevel());
|
||||
// } else {
|
||||
// Default metrics for non-adaptive decoders
|
||||
memset(metrics, 0, sizeof(VavCorePerformanceMetrics));
|
||||
metrics->current_quality_level = 4; // ULTRA quality
|
||||
// }
|
||||
|
||||
return VAVCORE_SUCCESS;
|
||||
}
|
||||
@@ -556,6 +614,12 @@ VAVCORE_API VavCoreResult vavcore_enable_adaptive_quality(VavCorePlayer* player,
|
||||
}
|
||||
|
||||
// TODO: Implement adaptive mode control in VavCore v1.1
|
||||
// auto adaptiveDecoder = dynamic_cast<VavCore::IAdaptiveVideoDecoder*>(player->decoder.get());
|
||||
// if (adaptiveDecoder) {
|
||||
// adaptiveDecoder->EnableAdaptiveMode(enable != 0);
|
||||
// return VAVCORE_SUCCESS;
|
||||
// }
|
||||
|
||||
return VAVCORE_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
@@ -565,6 +629,12 @@ VAVCORE_API VavCoreResult vavcore_set_target_framerate(VavCorePlayer* player, do
|
||||
}
|
||||
|
||||
// TODO: Implement adaptive framerate control in VavCore v1.1
|
||||
// auto adaptiveDecoder = dynamic_cast<VavCore::IAdaptiveVideoDecoder*>(player->decoder.get());
|
||||
// if (adaptiveDecoder) {
|
||||
// adaptiveDecoder->SetTargetFrameRate(fps);
|
||||
// return VAVCORE_SUCCESS;
|
||||
// }
|
||||
|
||||
return VAVCORE_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
@@ -580,10 +650,10 @@ VAVCORE_API void vavcore_free_frame(VavCoreVideoFrame* frame) {
|
||||
frame->v_plane = nullptr;
|
||||
}
|
||||
|
||||
// Windows-specific D3D Surface decoding API functions
|
||||
// D3D Surface decoding API functions
|
||||
VAVCORE_API int vavcore_supports_surface_type(VavCorePlayer* player, VavCoreSurfaceType type) {
|
||||
if (!player || !player->impl || !player->impl->decoder) {
|
||||
return 0;
|
||||
return 0; // false
|
||||
}
|
||||
|
||||
return player->impl->decoder->SupportsSurfaceType(type) ? 1 : 0;
|
||||
@@ -594,9 +664,11 @@ VAVCORE_API VavCoreResult vavcore_set_d3d_device(VavCorePlayer* player, void* d3
|
||||
return VAVCORE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
// Always store for pending use (in case decoder is recreated)
|
||||
player->impl->pendingD3DDevice = d3d_device;
|
||||
player->impl->pendingD3DSurfaceType = type;
|
||||
|
||||
// If decoder exists, also apply immediately
|
||||
if (player->impl->decoder) {
|
||||
bool success = player->impl->decoder->SetD3DDevice(d3d_device, type);
|
||||
if (success) {
|
||||
@@ -604,6 +676,7 @@ VAVCORE_API VavCoreResult vavcore_set_d3d_device(VavCorePlayer* player, void* d3
|
||||
return VAVCORE_SUCCESS;
|
||||
} else {
|
||||
LOGF_ERROR("[vavcore_set_d3d_device] WARNING: Failed to apply D3D device to existing decoder (will retry on next decode)");
|
||||
// Still return success - device is stored for later use
|
||||
return VAVCORE_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
@@ -631,72 +704,72 @@ VAVCORE_API VavCoreResult vavcore_decode_to_surface(VavCorePlayer* player,
|
||||
return VAVCORE_ERROR_INIT_FAILED;
|
||||
}
|
||||
|
||||
// Check if decoder supports the requested surface type
|
||||
if (!player->impl->decoder->SupportsSurfaceType(target_type)) {
|
||||
return VAVCORE_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
try {
|
||||
const uint8_t* packet_data = nullptr;
|
||||
size_t packet_size = 0;
|
||||
// Read next packet from file
|
||||
VideoPacket packet;
|
||||
|
||||
if (target_surface == nullptr) {
|
||||
LOGF_DEBUG("[vavcore_decode_to_surface] Drain mode - flushing buffered frames");
|
||||
} else {
|
||||
if (!player->impl->fileReader->ReadNextPacket(packet)) {
|
||||
if (player->impl->fileReader->IsEndOfFile()) {
|
||||
LOGF_DEBUG("[vavcore_decode_to_surface] End of file reached");
|
||||
return VAVCORE_END_OF_STREAM;
|
||||
}
|
||||
return VAVCORE_ERROR_DECODE_FAILED;
|
||||
if (!player->impl->fileReader->ReadNextPacket(packet)) {
|
||||
if (player->impl->fileReader->IsEndOfFile()) {
|
||||
return VAVCORE_END_OF_STREAM;
|
||||
}
|
||||
packet_data = packet.data.get();
|
||||
packet_size = packet.size;
|
||||
return VAVCORE_ERROR_DECODE_FAILED;
|
||||
}
|
||||
|
||||
// Decode to surface
|
||||
VideoFrame videoFrame;
|
||||
bool success = player->impl->decoder->DecodeToSurface(
|
||||
packet_data, packet_size,
|
||||
packet.data.get(), packet.size,
|
||||
target_type, target_surface,
|
||||
videoFrame
|
||||
);
|
||||
|
||||
if (!success) {
|
||||
if (videoFrame.width == 0 && videoFrame.height == 0) {
|
||||
LOGF_DEBUG("[vavcore_decode_to_surface] Packet accepted, no output yet (priming)");
|
||||
return VAVCORE_PACKET_ACCEPTED;
|
||||
} else {
|
||||
LOGF_ERROR("[vavcore_decode_to_surface] Decode failed");
|
||||
return VAVCORE_ERROR_DECODE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
if (videoFrame.width == 0 || videoFrame.height == 0 || !videoFrame.is_valid) {
|
||||
LOGF_WARNING("[vavcore_decode_to_surface] Decoder returned success but frame invalid");
|
||||
// Packet accepted but no frame yet (buffering or reordering)
|
||||
// NVDEC returns false for display-only packets where no new frame is decoded
|
||||
// or when initial buffering is still in progress
|
||||
return VAVCORE_PACKET_ACCEPTED;
|
||||
}
|
||||
|
||||
// Convert to VavCoreVideoFrame with surface data
|
||||
frame->width = videoFrame.width;
|
||||
frame->height = videoFrame.height;
|
||||
frame->timestamp_us = static_cast<uint64_t>(videoFrame.timestamp_seconds * 1000000.0);
|
||||
frame->frame_number = videoFrame.frame_index;
|
||||
frame->surface_type = target_type;
|
||||
|
||||
// Set surface-specific data
|
||||
switch (target_type) {
|
||||
case VAVCORE_SURFACE_D3D11_TEXTURE:
|
||||
frame->surface_data.d3d11.d3d11_texture = target_surface;
|
||||
break;
|
||||
case VAVCORE_SURFACE_D3D12_RESOURCE:
|
||||
frame->surface_data.d3d12.d3d12_resource = target_surface;
|
||||
// CRITICAL FIX: Copy CUDA fence value for D3D12-CUDA synchronization
|
||||
// This fence value is set by NVDECAV1Decoder after CUDA kernel completion
|
||||
frame->surface_data.d3d12.fence_value = videoFrame.sync_fence_value;
|
||||
break;
|
||||
case VAVCORE_SURFACE_CUDA_DEVICE:
|
||||
// CUDA device pointer will be set by decoder implementation
|
||||
break;
|
||||
case VAVCORE_SURFACE_AMF_SURFACE:
|
||||
frame->surface_data.amf.amf_surface = target_surface;
|
||||
break;
|
||||
case VAVCORE_SURFACE_VULKAN_IMAGE:
|
||||
// Android MediaCodec → ImageReader → VkImage pipeline
|
||||
frame->surface_data.vulkan.vk_image = videoFrame.surface_data.vulkan.vk_image;
|
||||
frame->surface_data.vulkan.vk_device = videoFrame.surface_data.vulkan.vk_device;
|
||||
frame->surface_data.vulkan.vk_device_memory = videoFrame.surface_data.vulkan.vk_device_memory;
|
||||
frame->surface_data.vulkan.memory_offset = videoFrame.surface_data.vulkan.memory_offset;
|
||||
LOGF_DEBUG("[vavcore_decode_to_surface] Copied Vulkan surface data: VkImage=%p, VkMemory=%p",
|
||||
frame->surface_data.vulkan.vk_image, frame->surface_data.vulkan.vk_device_memory);
|
||||
break;
|
||||
case VAVCORE_SURFACE_CPU:
|
||||
default:
|
||||
// Fallback to CPU decoding
|
||||
copy_frame_data(videoFrame, frame);
|
||||
break;
|
||||
}
|
||||
@@ -728,16 +801,19 @@ VAVCORE_API VavCoreResult vavcore_set_debug_options(VavCorePlayer* player, const
|
||||
return VAVCORE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
// Copy debug options
|
||||
player->impl->debugOptions.enable_first_frame_debug = options->enable_first_frame_debug;
|
||||
player->impl->debugOptions.first_frame_debug_count = options->first_frame_debug_count;
|
||||
player->impl->debugOptions.enable_rgba_debug = options->enable_rgba_debug;
|
||||
player->impl->debugOptions.rgba_debug_count = options->rgba_debug_count;
|
||||
|
||||
// Copy debug output path if provided
|
||||
if (options->debug_output_path) {
|
||||
player->impl->debugOutputPath = options->debug_output_path;
|
||||
player->impl->debugOptions.debug_output_path = player->impl->debugOutputPath.c_str();
|
||||
}
|
||||
|
||||
// Pass debug options to decoder if it exists
|
||||
if (player->impl->decoder) {
|
||||
player->impl->decoder->SetDebugOptions(&player->impl->debugOptions);
|
||||
}
|
||||
@@ -754,6 +830,7 @@ VAVCORE_API VavCoreResult vavcore_get_debug_options(VavCorePlayer* player, VavCo
|
||||
return VAVCORE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
// Copy current debug options to output
|
||||
*options = player->impl->debugOptions;
|
||||
|
||||
return VAVCORE_SUCCESS;
|
||||
@@ -767,40 +844,67 @@ VAVCORE_API int vavcore_get_pending_decode_count(VavCorePlayer* player) {
|
||||
return player->impl->decoder->GetPendingDecodeCount();
|
||||
}
|
||||
|
||||
// Stub implementations for unsupported GPU APIs on Windows
|
||||
VAVCORE_API VavCoreResult vavcore_set_vulkan_device(VavCorePlayer* player, void* vk_device, void* vk_instance, void* vk_physical_device) {
|
||||
LOGF_WARNING("[vavcore_set_vulkan_device] Vulkan device registration not supported on Windows");
|
||||
return VAVCORE_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
// Android GPU Surface API stubs (Phase 1-3 implementation)
|
||||
// TODO: Implement Vulkan device registration for MediaCodec → Vulkan pipeline
|
||||
|
||||
VAVCORE_API VavCoreResult vavcore_set_vulkan_device(VavCorePlayer* player, void* vk_device, void* vk_instance, void* vk_physical_device) {
|
||||
if (!player || !player->impl) {
|
||||
return VAVCORE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (!vk_device || !vk_instance || !vk_physical_device) {
|
||||
LOGF_ERROR("[vavcore_set_vulkan_device] Invalid Vulkan handles");
|
||||
return VAVCORE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
LOGF_INFO("[vavcore_set_vulkan_device] Registering Vulkan device with VavCore");
|
||||
LOGF_DEBUG("[vavcore_set_vulkan_device] VkDevice: %p, VkInstance: %p, VkPhysicalDevice: %p",
|
||||
vk_device, vk_instance, vk_physical_device);
|
||||
|
||||
VAVCORE_API VavCoreResult vavcore_set_current_frame_fence(VavCorePlayer* player, void* vk_fence) {
|
||||
LOGF_WARNING("[vavcore_set_current_frame_fence] VkFence setting not supported on Windows");
|
||||
return VAVCORE_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
VAVCORE_API VavCoreResult vavcore_set_android_java_vm(void* java_vm) {
|
||||
LOGF_WARNING("[vavcore_set_android_java_vm] JavaVM registration not supported on Windows");
|
||||
return VAVCORE_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
VAVCORE_API VavCoreResult vavcore_set_android_surface(VavCorePlayer* player, void* native_window) {
|
||||
LOGF_WARNING("[vavcore_set_android_surface] Android surface registration not supported on Windows");
|
||||
return VAVCORE_ERROR_NOT_SUPPORTED;
|
||||
if (!player || !player->impl) {
|
||||
return VAVCORE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
// TODO: Implement Android surface registration
|
||||
LOGF_DEBUG("[vavcore_set_android_surface] Android surface registration requested (NOT YET IMPLEMENTED)");
|
||||
return VAVCORE_SUCCESS;
|
||||
}
|
||||
|
||||
VAVCORE_API VavCoreResult vavcore_set_opengl_es_context(VavCorePlayer* player, void* egl_context) {
|
||||
if (!player || !player->impl) {
|
||||
return VAVCORE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
// TODO: Implement OpenGL ES context registration
|
||||
LOGF_DEBUG("[vavcore_set_opengl_es_context] OpenGL ES context registration requested (NOT YET IMPLEMENTED)");
|
||||
return VAVCORE_SUCCESS;
|
||||
}
|
||||
|
||||
VAVCORE_API VavCoreResult vavcore_set_opengl_context(VavCorePlayer* player, void* gl_context) {
|
||||
if (!player || !player->impl) {
|
||||
return VAVCORE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
// TODO: Implement OpenGL context registration
|
||||
LOGF_DEBUG("[vavcore_set_opengl_context] OpenGL context registration requested (NOT YET IMPLEMENTED)");
|
||||
return VAVCORE_SUCCESS;
|
||||
}
|
||||
|
||||
VAVCORE_API VavCoreResult vavcore_set_metal_device(VavCorePlayer* player, void* metal_device) {
|
||||
LOGF_WARNING("[vavcore_set_metal_device] Metal device registration not supported on Windows");
|
||||
return VAVCORE_ERROR_NOT_SUPPORTED;
|
||||
if (!player || !player->impl) {
|
||||
return VAVCORE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
// TODO: Implement Metal device registration
|
||||
LOGF_DEBUG("[vavcore_set_metal_device] Metal device registration requested (NOT YET IMPLEMENTED)");
|
||||
return VAVCORE_SUCCESS;
|
||||
}
|
||||
|
||||
VAVCORE_API VavCoreResult vavcore_convert_yuv_to_rgb(
|
||||
@@ -812,8 +916,10 @@ VAVCORE_API VavCoreResult vavcore_convert_yuv_to_rgb(
|
||||
return VAVCORE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
// TODO: Implement YUV to RGB conversion
|
||||
LOGF_DEBUG("[vavcore_convert_yuv_to_rgb] YUV→RGB conversion requested (NOT YET IMPLEMENTED)");
|
||||
return VAVCORE_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user