250 lines
8.7 KiB
C++
250 lines
8.7 KiB
C++
|
|
#include "pch.h"
|
||
|
|
|
||
|
|
// Basic Windows includes
|
||
|
|
#include <windows.h>
|
||
|
|
|
||
|
|
// AV1 Player core components (no WinUI3 dependencies)
|
||
|
|
#include "../src/Common/VideoTypes.h"
|
||
|
|
#include "../src/Decoder/VideoDecoderFactory.h"
|
||
|
|
#include "../src/FileIO/WebMFileReader.h"
|
||
|
|
#include "../src/Common/FramePool.h"
|
||
|
|
|
||
|
|
using namespace Vav2Player;
|
||
|
|
|
||
|
|
class HeadlessTestRunner
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
HeadlessTestRunner() {
|
||
|
|
std::cout << "=== Vav2Player Headless Test Runner ===" << std::endl;
|
||
|
|
std::cout << "Pure console application for testing AV1 components" << std::endl << std::endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool RunBasicTests(const std::string& videoFile) {
|
||
|
|
std::cout << "[TEST] Starting basic component tests..." << std::endl;
|
||
|
|
|
||
|
|
// Test 1: VideoDecoderFactory
|
||
|
|
if (!TestVideoDecoderFactory()) return false;
|
||
|
|
|
||
|
|
// Test 2: WebMFileReader
|
||
|
|
if (!TestWebMFileReader(videoFile)) return false;
|
||
|
|
|
||
|
|
// Test 3: AV1 Decoder
|
||
|
|
if (!TestAV1Decoder(videoFile)) return false;
|
||
|
|
|
||
|
|
// Test 4: Full Pipeline
|
||
|
|
if (!TestFullPipeline(videoFile)) return false;
|
||
|
|
|
||
|
|
std::cout << std::endl << "[SUCCESS] All basic tests passed!" << std::endl;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
private:
|
||
|
|
bool TestVideoDecoderFactory() {
|
||
|
|
std::cout << "[TEST 1] VideoDecoderFactory..." << std::endl;
|
||
|
|
|
||
|
|
try {
|
||
|
|
// Test AUTO decoder creation
|
||
|
|
auto decoder = VideoDecoderFactory::CreateDecoder(VideoDecoderFactory::DecoderType::AUTO);
|
||
|
|
if (!decoder) {
|
||
|
|
std::cout << "[FAIL] Could not create AUTO decoder" << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Test SOFTWARE decoder creation
|
||
|
|
auto softwareDecoder = VideoDecoderFactory::CreateDecoder(VideoDecoderFactory::DecoderType::SOFTWARE);
|
||
|
|
if (!softwareDecoder) {
|
||
|
|
std::cout << "[FAIL] Could not create SOFTWARE decoder" << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
std::cout << "[PASS] VideoDecoderFactory working correctly" << std::endl;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cout << "[FAIL] VideoDecoderFactory exception: " << e.what() << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
bool TestWebMFileReader(const std::string& videoFile) {
|
||
|
|
std::cout << "[TEST 2] WebMFileReader with file: " << videoFile << std::endl;
|
||
|
|
|
||
|
|
try {
|
||
|
|
WebMFileReader reader;
|
||
|
|
|
||
|
|
// Test file opening
|
||
|
|
if (!reader.OpenFile(videoFile)) {
|
||
|
|
std::cout << "[FAIL] Could not open WebM file" << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Test video track detection
|
||
|
|
auto tracks = reader.GetVideoTracks();
|
||
|
|
if (tracks.empty()) {
|
||
|
|
std::cout << "[FAIL] No video tracks found" << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
std::cout << "[INFO] Found " << tracks.size() << " video track(s)" << std::endl;
|
||
|
|
|
||
|
|
// Test track selection
|
||
|
|
if (!reader.SelectVideoTrack(0)) {
|
||
|
|
std::cout << "[FAIL] Could not select video track 0" << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Test metadata
|
||
|
|
auto metadata = reader.GetVideoMetadata();
|
||
|
|
std::cout << "[INFO] Video: " << metadata.width << "x" << metadata.height
|
||
|
|
<< " @ " << metadata.frameRate << " fps" << std::endl;
|
||
|
|
|
||
|
|
std::cout << "[PASS] WebMFileReader working correctly" << std::endl;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cout << "[FAIL] WebMFileReader exception: " << e.what() << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
bool TestAV1Decoder(const std::string& videoFile) {
|
||
|
|
std::cout << "[TEST 3] AV1 Decoder..." << std::endl;
|
||
|
|
|
||
|
|
try {
|
||
|
|
WebMFileReader reader;
|
||
|
|
if (!reader.OpenFile(videoFile) || !reader.SelectVideoTrack(0)) {
|
||
|
|
std::cout << "[FAIL] Could not prepare file for decoder test" << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
auto decoder = VideoDecoderFactory::CreateDecoder(VideoDecoderFactory::DecoderType::SOFTWARE);
|
||
|
|
if (!decoder) {
|
||
|
|
std::cout << "[FAIL] Could not create decoder" << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!decoder->Initialize()) {
|
||
|
|
std::cout << "[FAIL] Could not initialize decoder" << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Test decoding first few frames
|
||
|
|
int decodedFrames = 0;
|
||
|
|
int maxTestFrames = 5;
|
||
|
|
|
||
|
|
for (int i = 0; i < maxTestFrames; i++) {
|
||
|
|
VideoPacket packet;
|
||
|
|
if (!reader.ReadNextPacket(packet)) {
|
||
|
|
std::cout << "[INFO] End of file reached at frame " << i << std::endl;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
VideoFrame frame;
|
||
|
|
if (decoder->DecodeFrame(packet, frame)) {
|
||
|
|
decodedFrames++;
|
||
|
|
std::cout << "[INFO] Frame " << (i + 1) << ": "
|
||
|
|
<< frame.width << "x" << frame.height << std::endl;
|
||
|
|
} else {
|
||
|
|
std::cout << "[WARN] Failed to decode frame " << (i + 1) << std::endl;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (decodedFrames == 0) {
|
||
|
|
std::cout << "[FAIL] No frames were decoded" << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
std::cout << "[PASS] AV1 Decoder working correctly ("
|
||
|
|
<< decodedFrames << " frames decoded)" << std::endl;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cout << "[FAIL] AV1 Decoder exception: " << e.what() << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
bool TestFullPipeline(const std::string& videoFile) {
|
||
|
|
std::cout << "[TEST 4] Full Pipeline Performance..." << std::endl;
|
||
|
|
|
||
|
|
try {
|
||
|
|
auto startTime = std::chrono::high_resolution_clock::now();
|
||
|
|
|
||
|
|
WebMFileReader reader;
|
||
|
|
if (!reader.OpenFile(videoFile) || !reader.SelectVideoTrack(0)) {
|
||
|
|
std::cout << "[FAIL] Could not prepare file for pipeline test" << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
auto decoder = VideoDecoderFactory::CreateDecoder(VideoDecoderFactory::DecoderType::SOFTWARE);
|
||
|
|
if (!decoder || !decoder->Initialize()) {
|
||
|
|
std::cout << "[FAIL] Could not initialize decoder for pipeline test" << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Process 30 frames for performance measurement
|
||
|
|
int processedFrames = 0;
|
||
|
|
int maxFrames = 30;
|
||
|
|
|
||
|
|
for (int i = 0; i < maxFrames; i++) {
|
||
|
|
VideoPacket packet;
|
||
|
|
if (!reader.ReadNextPacket(packet)) break;
|
||
|
|
|
||
|
|
VideoFrame frame;
|
||
|
|
if (decoder->DecodeFrame(packet, frame)) {
|
||
|
|
processedFrames++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
auto endTime = std::chrono::high_resolution_clock::now();
|
||
|
|
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime);
|
||
|
|
|
||
|
|
if (processedFrames > 0) {
|
||
|
|
double fps = (double)processedFrames * 1000.0 / duration.count();
|
||
|
|
std::cout << "[INFO] Processed " << processedFrames << " frames in "
|
||
|
|
<< duration.count() << "ms" << std::endl;
|
||
|
|
std::cout << "[INFO] Performance: " << fps << " fps" << std::endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
std::cout << "[PASS] Full Pipeline working correctly" << std::endl;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cout << "[FAIL] Full Pipeline exception: " << e.what() << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
// Headless-only main function
|
||
|
|
int main(int argc, char* argv[])
|
||
|
|
{
|
||
|
|
// Setup console
|
||
|
|
SetConsoleCP(CP_UTF8);
|
||
|
|
SetConsoleOutputCP(CP_UTF8);
|
||
|
|
|
||
|
|
if (argc < 2) {
|
||
|
|
std::cout << "Usage: Vav2PlayerHeadless.exe <video_file.webm>" << std::endl;
|
||
|
|
std::cout << "Example: Vav2PlayerHeadless.exe test_video.webm" << std::endl;
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string videoFile = argv[1];
|
||
|
|
std::cout << "Testing with video file: " << videoFile << std::endl << std::endl;
|
||
|
|
|
||
|
|
HeadlessTestRunner runner;
|
||
|
|
bool success = runner.RunBasicTests(videoFile);
|
||
|
|
|
||
|
|
std::cout << std::endl << "=== Test Summary ===" << std::endl;
|
||
|
|
if (success) {
|
||
|
|
std::cout << "All tests PASSED ✓" << std::endl;
|
||
|
|
std::cout << "Press Enter to exit...";
|
||
|
|
std::cin.get();
|
||
|
|
return 0;
|
||
|
|
} else {
|
||
|
|
std::cout << "Some tests FAILED ✗" << std::endl;
|
||
|
|
std::cout << "Press Enter to exit...";
|
||
|
|
std::cin.get();
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
}
|