test program

This commit is contained in:
pigeatgarlic 2023-10-28 11:41:11 +07:00
parent 1262ee2706
commit 02a012d154
5 changed files with 232 additions and 144 deletions

View File

@ -29,15 +29,18 @@ list(APPEND PLATFORM_TARGET_FILES ${NVENC_SOURCES})
include_directories(${CMAKE_CURRENT_BINARY_DIR})
set(TEST_TARGET_FILES
src/dll.h
src/main.cpp)
set(SUNSHINE_TARGET_FILES
src/cbs.cpp
src/utility.h
src/uuid.h
src/config.h
src/config.cpp
src/main.cpp
src/main.h
src/dll.h
src/dll.cpp
src/video.cpp
src/video.h
src/video_colorspace.cpp

View File

@ -2,7 +2,7 @@
# this file will also load platform specific macros
add_library(sunshine SHARED ${SUNSHINE_TARGET_FILES})
# add_executable(sunshine ${SUNSHINE_TARGET_FILES})
add_executable(test ${TEST_TARGET_FILES})
# platform specific target definitions
if(WIN32)
@ -28,8 +28,15 @@ set_target_properties(sunshine PROPERTIES CXX_STANDARD 17
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR})
target_link_libraries(test ${SUNSHINE_EXTERNAL_LIBRARIES} ${EXTRA_LIBS})
target_compile_definitions(test PUBLIC ${SUNSHINE_DEFINITIONS})
set_target_properties(test PROPERTIES CXX_STANDARD 17
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR})
foreach(flag IN LISTS SUNSHINE_COMPILE_OPTIONS)
list(APPEND SUNSHINE_COMPILE_OPTIONS_CUDA "$<$<COMPILE_LANGUAGE:CUDA>:--compiler-options=${flag}>")
endforeach()
target_compile_options(sunshine PRIVATE $<$<COMPILE_LANGUAGE:CXX>:${SUNSHINE_COMPILE_OPTIONS}>;$<$<COMPILE_LANGUAGE:CUDA>:${SUNSHINE_COMPILE_OPTIONS_CUDA};-std=c++17>) # cmake-lint: disable=C0301
target_compile_options(sunshine PRIVATE $<$<COMPILE_LANGUAGE:CXX>:${SUNSHINE_COMPILE_OPTIONS}>;$<$<COMPILE_LANGUAGE:CUDA>:${SUNSHINE_COMPILE_OPTIONS_CUDA};-std=c++17>) # cmake-lint: disable=C0301
target_compile_options(test PRIVATE $<$<COMPILE_LANGUAGE:CXX>:${SUNSHINE_COMPILE_OPTIONS}>;$<$<COMPILE_LANGUAGE:CUDA>:${SUNSHINE_COMPILE_OPTIONS_CUDA};-std=c++17>) # cmake-lint: disable=C0301

153
src/dll.cpp Normal file
View File

@ -0,0 +1,153 @@
/**
* @file src/main.cpp
* @brief Main entry point for Sunshine.
*/
// standard includes
#include <csignal>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <thread>
// local includes
#include "config.h"
#include "main.h"
#include "dll.h"
#include "platform/common.h"
#include "video.h"
struct _VideoPipeline
{
std::chrono::steady_clock::time_point start;
video::config_t monitor;
safe::mail_t mail;
};
extern VideoPipeline *__cdecl StartQueue(int video_width,
int video_height,
int video_bitrate,
int video_framerate,
int video_codec)
{
static bool init = false;
if (!init)
{
// If any of the following fail, we log an error and continue event though sunshine will not function correctly.
// This allows access to the UI to fix configuration problems or view the logs.
if (platf::init())
{
// BOOST_LOG(error) << "Platform failed to initialize"sv;
return NULL;
}
else if (video::probe_encoders())
{
// BOOST_LOG(error) << "Video failed to find working encoder"sv;
return NULL;
}
init = true;
}
static VideoPipeline pipeline = {};
auto mail = std::make_shared<safe::mail_raw_t>();
pipeline.mail = mail;
pipeline.monitor = {1920, 1080, 60, 6000, 1, 0, 1, 0, 0};
pipeline.start = std::chrono::steady_clock::now();
switch (video_codec)
{
case 2: // h265
pipeline.monitor.videoFormat = 1;
config::video.hevc_mode = 1;
config::video.av1_mode = 0;
break;
case 3: // av1
pipeline.monitor.videoFormat = 2;
config::video.hevc_mode = 0;
config::video.av1_mode = 1;
break;
default:
pipeline.monitor.videoFormat = 0;
config::video.hevc_mode = 0;
config::video.av1_mode = 0;
break;
}
auto thread = std::thread{[&](){ video::capture(pipeline.mail, pipeline.monitor, NULL); }};
thread.detach();
return &pipeline;
}
long long
duration_to_latency(std::chrono::steady_clock::duration duration) {
const auto duration_ns = std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count();
return std::clamp<decltype(duration_ns)>((duration_ns + 50) / 100, 0, std::numeric_limits<int>::max());
};
int __cdecl
PopFromQueue(VideoPipeline *pipeline,
void *data,
int *duration)
{
auto packet = pipeline->mail->queue<video::packet_t>(mail::video_packets)->pop();
// if (packet->frame_timestamp) {
// *duration = duration_to_latency(*packet->frame_timestamp - pipeline->start);
// pipeline->start = *packet->frame_timestamp;
// }
memcpy(data, packet->data(), packet->data_size());
int size = packet->data_size();
packet.release();
return size;
}
void __cdecl
RaiseEvent(VideoPipeline *pipeline,
EventType event,
int value)
{
switch (event)
{
case IDR_FRAME: // IDR FRAME
pipeline->mail->event<bool>(mail::idr)->raise(true);
break;
case STOP: // IDR FRAME
pipeline->mail->event<bool>(mail::shutdown)->raise(true);
break;
default:
break;
}
}
void __cdecl
WaitEvent(VideoPipeline* pipeline,
EventType event,
int* value)
{
switch (event)
{
case STOP: // IDR FRAME
pipeline->mail->event<bool>(mail::shutdown)->pop();
break;
default:
break;
}
}
int __cdecl
PeekEvent(VideoPipeline* pipeline,
EventType event,
int* value)
{
switch (event)
{
case STOP: // IDR FRAME
return pipeline->mail->event<bool>(mail::shutdown)->peek();
default:
return 0;
}
}

View File

@ -34,4 +34,29 @@ __declspec(dllexport) void __cdecl WaitEvent(VideoPipeline* pipeline,
int* value);
__declspec(dllexport) int __cdecl PeekEvent(VideoPipeline* pipeline,
EventType event,
int* value);
typedef VideoPipeline* (*STARTQUEUE) ( int video_width,
int video_height,
int video_bitrate,
int video_framerate,
int video_codec);
typedef int (*POPFROMQUEUE) (VideoPipeline* pipeline,
void* data,
int* duration);
typedef void (*RAISEEVENT) (VideoPipeline* pipeline,
EventType event,
int value);
typedef void (*WAITEVENT) (VideoPipeline* pipeline,
EventType event,
int* value);
typedef int (*PEEKEVENT) (VideoPipeline* pipeline,
EventType event,
int* value);
}

View File

@ -4,165 +4,65 @@
*/
// standard includes
#include <csignal>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <thread>
#include <Windows.h>
// local includes
#include "config.h"
#include "main.h"
#include "dll.h"
#include "platform/common.h"
#include "video.h"
struct _VideoPipeline
{
std::chrono::steady_clock::time_point start;
video::config_t monitor;
safe::mail_t mail;
};
extern VideoPipeline *__cdecl StartQueue(int video_width,
int video_height,
int video_bitrate,
int video_framerate,
int video_codec)
{
static bool init = false;
if (!init)
{
// If any of the following fail, we log an error and continue event though sunshine will not function correctly.
// This allows access to the UI to fix configuration problems or view the logs.
if (platf::init())
{
// BOOST_LOG(error) << "Platform failed to initialize"sv;
return NULL;
}
else if (video::probe_encoders())
{
// BOOST_LOG(error) << "Video failed to find working encoder"sv;
return NULL;
}
init = true;
}
static VideoPipeline pipeline = {};
auto mail = std::make_shared<safe::mail_raw_t>();
pipeline.mail = mail;
pipeline.monitor = {1920, 1080, 60, 6000, 1, 0, 1, 0, 0};
pipeline.start = std::chrono::steady_clock::now();
static HMODULE hModule;
static STARTQUEUE callstart;
static POPFROMQUEUE callpop;
static WAITEVENT callwait;
static RAISEEVENT callraise;
static PEEKEVENT callpeek;
switch (video_codec)
{
case 2: // h265
pipeline.monitor.videoFormat = 1;
config::video.hevc_mode = 1;
config::video.av1_mode = 0;
break;
case 3: // av1
pipeline.monitor.videoFormat = 2;
config::video.hevc_mode = 0;
config::video.av1_mode = 1;
break;
default:
pipeline.monitor.videoFormat = 0;
config::video.hevc_mode = 0;
config::video.av1_mode = 0;
break;
}
int
initlibrary() {
hModule = LoadLibraryA(".\\libsunshine.dll");
callstart = (STARTQUEUE) GetProcAddress( hModule,"StartQueue");
callpop = (POPFROMQUEUE) GetProcAddress( hModule,"PopFromQueue");
callraise = (RAISEEVENT) GetProcAddress( hModule,"RaiseEvent");
callwait = (WAITEVENT) GetProcAddress( hModule,"WaitEvent");
callpeek = (PEEKEVENT) GetProcAddress( hModule,"PeekEvent");
auto thread = std::thread{[&](){ video::capture(pipeline.mail, pipeline.monitor, NULL); }};
thread.detach();
if(callpop ==0 || callstart == 0 || callraise == 0 || callwait == 0)
return 1;
return &pipeline;
return 0;
}
int __cdecl
PopFromQueue(VideoPipeline *pipeline,
void *data,
int *duration)
{
auto packets = pipeline->mail->queue<video::packet_t>(mail::video_packets);
auto packet = packets->pop();
if (packet->frame_timestamp)
{
auto duration_to_latency = [](const std::chrono::steady_clock::duration &duration)
{
const auto duration_ns = std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count();
return std::clamp<decltype(duration_ns)>((duration_ns + 50) / 100, 0, std::numeric_limits<int>::max());
};
*duration = duration_to_latency(*packet->frame_timestamp - pipeline->start);
pipeline->start = *packet->frame_timestamp;
}
memcpy(data, packet->data(), packet->data_size());
return packet->data_size();
}
void __cdecl
RaiseEvent(VideoPipeline *pipeline,
EventType event,
int value)
{
switch (event)
{
case IDR_FRAME: // IDR FRAME
pipeline->mail->event<bool>(mail::idr)->raise(true);
break;
case STOP: // IDR FRAME
pipeline->mail->event<bool>(mail::shutdown)->raise(true);
break;
default:
break;
}
}
void __cdecl
WaitEvent(VideoPipeline* pipeline,
EventType event,
int* value)
{
switch (event)
{
case STOP: // IDR FRAME
pipeline->mail->event<bool>(mail::shutdown)->pop();
break;
default:
break;
}
}
int main(int argc, char *argv[])
{
initlibrary();
// second encode session
for (int i =0; i < 30; i++)
{
VideoPipeline *pipeline = callstart(1920, 1080, 6000, 60, 1);
auto video = std::thread{[&]() {
// Video traffic is sent on this thread
int duration = 0;
void *data = malloc(100 * 1000 * 1000);
VideoPipeline *pipeline = StartQueue(1920, 1080, 6000, 60, 1);
auto video = std::thread{[&]() {
// Video traffic is sent on this thread
platf::adjust_thread_priority(platf::thread_priority_e::high);
int duration = 0;
void *data = malloc(100 * 1000 * 1000);
int count = 0;
while (true) {
int size = callpop(pipeline, data, &duration);
if (callpeek(pipeline,STOP,NULL) || count == 1000) {
break;
}
int count = 0;
while (true) {
int size = PopFromQueue(pipeline, data, &duration);
if (pipeline->mail->event<bool>(mail::shutdown)->peek() || count == 10) {
break;
printf("received packet with size %d\n", size);
count++;
}
printf("received packet with size %d\n", size);
count++;
}
callraise(pipeline,STOP,0);
free(data);
}};
RaiseEvent(pipeline,STOP,0);
}};
int val;
WaitEvent(pipeline,STOP,&val);
callwait(pipeline,STOP,NULL);
video.join();
}
return 0;
}