223 lines
7.9 KiB
C++
223 lines
7.9 KiB
C++
|
|
#include <windows.h>
|
||
|
|
#include <stdio.h>
|
||
|
|
#include <string>
|
||
|
|
#include <vector>
|
||
|
|
#include <chrono>
|
||
|
|
#include <VavCore/VavCore.h>
|
||
|
|
#include "D3D12Manager.h"
|
||
|
|
|
||
|
|
using namespace std::chrono;
|
||
|
|
|
||
|
|
struct FrameTask {
|
||
|
|
int frame_index;
|
||
|
|
ID3D12Resource* texture;
|
||
|
|
VavCoreVideoFrame frame;
|
||
|
|
VavCoreResult result;
|
||
|
|
uint8_t* cpu_buffer;
|
||
|
|
};
|
||
|
|
|
||
|
|
int main(int argc, char* argv[])
|
||
|
|
{
|
||
|
|
printf("[LargeResolutionTest] Starting test...\n");
|
||
|
|
|
||
|
|
// Parse command line arguments
|
||
|
|
if (argc < 2) {
|
||
|
|
printf("[ERROR] Usage: LargeResolutionTest.exe <video_file_path>\n");
|
||
|
|
printf("[INFO] Test videos:\n");
|
||
|
|
printf(" - D:/Project/video-av1/sample/test_2160p_av1.webm\n");
|
||
|
|
printf(" - D:/Project/video-av1/sample/test_1080p_stripe.webm\n");
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
const char* video_path = argv[1];
|
||
|
|
printf("[LargeResolutionTest] Video: %s\n", video_path);
|
||
|
|
|
||
|
|
// Step 1: Initialize VavCore
|
||
|
|
printf("\n[Step 1] Initializing VavCore...\n");
|
||
|
|
VavCoreResult result = vavcore_initialize();
|
||
|
|
if (result != VAVCORE_SUCCESS) {
|
||
|
|
printf("[ERROR] Failed to initialize VavCore: error code %d\n", result);
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
printf("[OK] VavCore initialized successfully\n");
|
||
|
|
|
||
|
|
// Step 2: Create D3D12 device (headless)
|
||
|
|
printf("\n[Step 2] Creating D3D12 device...\n");
|
||
|
|
D3D12Manager d3d12;
|
||
|
|
if (!d3d12.Initialize()) {
|
||
|
|
printf("[ERROR] Failed to create D3D12 device\n");
|
||
|
|
vavcore_cleanup();
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
printf("[OK] D3D12 device created\n");
|
||
|
|
|
||
|
|
// Step 3: Create VavCore player
|
||
|
|
printf("\n[Step 3] Creating VavCore player...\n");
|
||
|
|
VavCorePlayer* player = vavcore_create_player();
|
||
|
|
if (!player) {
|
||
|
|
printf("[ERROR] Failed to create VavCore player\n");
|
||
|
|
d3d12.Cleanup();
|
||
|
|
vavcore_cleanup();
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
printf("[OK] VavCore player created\n");
|
||
|
|
|
||
|
|
// Step 4: Set decoder type to NVDEC explicitly
|
||
|
|
printf("\n[Step 4] Setting decoder type to NVDEC...\n");
|
||
|
|
result = vavcore_set_decoder_type(player, VAVCORE_DECODER_NVDEC);
|
||
|
|
if (result != VAVCORE_SUCCESS) {
|
||
|
|
printf("[ERROR] Failed to set decoder type: error code %d\n", result);
|
||
|
|
vavcore_destroy_player(player);
|
||
|
|
d3d12.Cleanup();
|
||
|
|
vavcore_cleanup();
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
printf("[OK] Decoder type set to NVDEC\n");
|
||
|
|
|
||
|
|
// Step 5: Set D3D12 device for zero-copy
|
||
|
|
printf("\n[Step 5] Setting D3D12 device for VavCore...\n");
|
||
|
|
result = vavcore_set_d3d_device(player, d3d12.GetDevice(), VAVCORE_SURFACE_D3D12_RESOURCE);
|
||
|
|
if (result != VAVCORE_SUCCESS) {
|
||
|
|
printf("[ERROR] Failed to set D3D12 device: error code %d\n", result);
|
||
|
|
vavcore_destroy_player(player);
|
||
|
|
d3d12.Cleanup();
|
||
|
|
vavcore_cleanup();
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
printf("[OK] D3D12 device set for VavCore\n");
|
||
|
|
|
||
|
|
// Step 6: Open video file
|
||
|
|
printf("\n[Step 6] Opening video file...\n");
|
||
|
|
result = vavcore_open_file(player, video_path);
|
||
|
|
if (result != VAVCORE_SUCCESS) {
|
||
|
|
printf("[ERROR] Failed to open video file: error code %d\n", result);
|
||
|
|
vavcore_destroy_player(player);
|
||
|
|
d3d12.Cleanup();
|
||
|
|
vavcore_cleanup();
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get video metadata
|
||
|
|
VavCoreVideoMetadata metadata = {};
|
||
|
|
result = vavcore_get_metadata(player, &metadata);
|
||
|
|
if (result != VAVCORE_SUCCESS) {
|
||
|
|
printf("[ERROR] Failed to get video metadata: error code %d\n", result);
|
||
|
|
vavcore_close_file(player);
|
||
|
|
vavcore_destroy_player(player);
|
||
|
|
d3d12.Cleanup();
|
||
|
|
vavcore_cleanup();
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
printf("[OK] Video opened: %dx%d, %.2f fps, %llu frames\n",
|
||
|
|
metadata.width, metadata.height, metadata.frame_rate, (unsigned long long)metadata.total_frames);
|
||
|
|
printf("[LargeResolutionTest] Decoder: NVDEC (explicit)\n");
|
||
|
|
printf("[LargeResolutionTest] Surface: D3D12\n");
|
||
|
|
|
||
|
|
// Step 7: Continuous frame decoding (limited to ~10 seconds)
|
||
|
|
const int MAX_FRAMES = 300; // ~10 seconds at 30fps
|
||
|
|
printf("\n[Step 7] Decoding video (limited to %d frames for testing)...\n\n", MAX_FRAMES);
|
||
|
|
printf("[INFO] NVDEC pipeline priming: Calling decode continuously\n");
|
||
|
|
printf("[INFO] First 2 frames will be skipped for priming\n");
|
||
|
|
printf("[INFO] Total frames in video: %llu\n\n", (unsigned long long)metadata.total_frames);
|
||
|
|
|
||
|
|
int decode_errors = 0;
|
||
|
|
int successful_decodes = 0;
|
||
|
|
int frame_index = 0;
|
||
|
|
|
||
|
|
// Performance measurement
|
||
|
|
auto start_time = high_resolution_clock::now();
|
||
|
|
auto last_report_time = start_time;
|
||
|
|
int frames_since_last_report = 0;
|
||
|
|
|
||
|
|
// Continuous decode loop - decode limited frames
|
||
|
|
while (!vavcore_is_end_of_file(player) && frame_index < MAX_FRAMES) {
|
||
|
|
// Create NV12 texture
|
||
|
|
ID3D12Resource* texture = d3d12.CreateNV12Texture(metadata.width, metadata.height);
|
||
|
|
if (!texture) {
|
||
|
|
printf("[ERROR] Failed to create texture for frame %d\n", frame_index);
|
||
|
|
decode_errors++;
|
||
|
|
frame_index++;
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Decode frame to D3D12 surface
|
||
|
|
VavCoreVideoFrame frame;
|
||
|
|
VavCoreResult result = vavcore_decode_to_surface(
|
||
|
|
player,
|
||
|
|
VAVCORE_SURFACE_D3D12_RESOURCE,
|
||
|
|
texture,
|
||
|
|
&frame
|
||
|
|
);
|
||
|
|
|
||
|
|
if (result != VAVCORE_SUCCESS) {
|
||
|
|
printf("Frame %3d: Decode failed (error code %d)\n", frame_index, result);
|
||
|
|
texture->Release();
|
||
|
|
decode_errors++;
|
||
|
|
frame_index++;
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Skip first 2 frames (priming)
|
||
|
|
if (frame_index < 2) {
|
||
|
|
printf("Frame %3d: PRIMING (decoded but skipped)\n", frame_index);
|
||
|
|
} else {
|
||
|
|
successful_decodes++;
|
||
|
|
frames_since_last_report++;
|
||
|
|
|
||
|
|
// Print performance report every 30 frames
|
||
|
|
if (frame_index % 30 == 0) {
|
||
|
|
auto current_time = high_resolution_clock::now();
|
||
|
|
auto elapsed_ms = duration_cast<milliseconds>(current_time - last_report_time).count();
|
||
|
|
double fps = (frames_since_last_report * 1000.0) / elapsed_ms;
|
||
|
|
|
||
|
|
printf("Frame %3d: Decoded successfully (progress: %d/%llu, FPS: %.1f)\n",
|
||
|
|
frame_index, frame_index, (unsigned long long)metadata.total_frames, fps);
|
||
|
|
|
||
|
|
last_report_time = current_time;
|
||
|
|
frames_since_last_report = 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Cleanup texture immediately to prevent memory buildup
|
||
|
|
texture->Release();
|
||
|
|
frame_index++;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Calculate overall performance
|
||
|
|
auto end_time = high_resolution_clock::now();
|
||
|
|
auto total_ms = duration_cast<milliseconds>(end_time - start_time).count();
|
||
|
|
double overall_fps = (successful_decodes * 1000.0) / total_ms;
|
||
|
|
double decode_time_per_frame = (double)total_ms / successful_decodes;
|
||
|
|
|
||
|
|
// Step 8: Print results
|
||
|
|
printf("\n[LargeResolutionTest] Results:\n");
|
||
|
|
printf(" Resolution: %dx%d\n", metadata.width, metadata.height);
|
||
|
|
printf(" Total frames in video: %llu\n", (unsigned long long)metadata.total_frames);
|
||
|
|
printf(" Total frames decoded: %d\n", frame_index);
|
||
|
|
printf(" Priming frames: 2\n");
|
||
|
|
printf(" Successful decodes (after priming): %d\n", successful_decodes);
|
||
|
|
printf(" Decode errors: %d\n", decode_errors);
|
||
|
|
printf("\n[LargeResolutionTest] Performance:\n");
|
||
|
|
printf(" Total time: %.2f seconds\n", total_ms / 1000.0);
|
||
|
|
printf(" Average FPS: %.1f fps\n", overall_fps);
|
||
|
|
printf(" Average decode time per frame: %.2f ms\n", decode_time_per_frame);
|
||
|
|
printf(" Target FPS (30fps): %s\n", overall_fps >= 30.0 ? "PASS" : "FAIL");
|
||
|
|
|
||
|
|
bool test_passed = (decode_errors == 0 && successful_decodes == (frame_index - 2) && overall_fps >= 30.0);
|
||
|
|
|
||
|
|
if (test_passed) {
|
||
|
|
printf("\n[LargeResolutionTest] Test SUCCESS - All frames decoded successfully\n");
|
||
|
|
} else {
|
||
|
|
printf("\n[LargeResolutionTest] Test FAILED - Some frames failed to decode\n");
|
||
|
|
}
|
||
|
|
|
||
|
|
// Cleanup
|
||
|
|
vavcore_close_file(player);
|
||
|
|
vavcore_destroy_player(player);
|
||
|
|
d3d12.Cleanup();
|
||
|
|
vavcore_cleanup();
|
||
|
|
|
||
|
|
return test_passed ? 0 : 1;
|
||
|
|
}
|