mirror of
https://github.com/thinkonmay/sunshine-sdk.git
synced 2026-08-06 20:54:52 +00:00
test program
This commit is contained in:
parent
1262ee2706
commit
02a012d154
@ -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
|
||||
|
||||
@ -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
153
src/dll.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
25
src/dll.h
25
src/dll.h
@ -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);
|
||||
}
|
||||
182
src/main.cpp
182
src/main.cpp
@ -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;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user