mirror of
https://github.com/thinkonmay/sunshine-sdk.git
synced 2026-08-08 10:37:14 +00:00
build parent process
This commit is contained in:
parent
0f434e969d
commit
3f6c88419f
@ -3,17 +3,19 @@
|
||||
|
||||
add_executable(sunshine ${SUNSHINE_TARGET_FILES})
|
||||
|
||||
# Homebrew build fails the vite build if we set these environment variables
|
||||
# this block must be before the platform specific code
|
||||
if(${SUNSHINE_BUILD_HOMEBREW})
|
||||
set(NPM_SOURCE_ASSETS_DIR "")
|
||||
set(NPM_ASSETS_DIR "")
|
||||
set(NPM_BUILD_HOMEBREW "true")
|
||||
else()
|
||||
set(NPM_SOURCE_ASSETS_DIR ${SUNSHINE_SOURCE_ASSETS_DIR})
|
||||
set(NPM_ASSETS_DIR ${CMAKE_BINARY_DIR})
|
||||
set(NPM_BUILD_HOMEBREW "")
|
||||
endif()
|
||||
|
||||
|
||||
add_executable(parent
|
||||
"${CMAKE_SOURCE_DIR}/src/parent.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/interprocess.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/interprocess.cpp")
|
||||
set_target_properties(parent PROPERTIES CXX_STANDARD 17)
|
||||
target_link_libraries(parent
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
${Boost_LIBRARIES})
|
||||
target_compile_options(parent PRIVATE ${SUNSHINE_COMPILE_OPTIONS})
|
||||
|
||||
|
||||
|
||||
# platform specific target definitions
|
||||
if(WIN32)
|
||||
|
||||
189
src/interprocess.cpp
Normal file
189
src/interprocess.cpp
Normal file
@ -0,0 +1,189 @@
|
||||
/**
|
||||
* @file globals.cpp
|
||||
* @brief Implementation for globally accessible variables and functions.
|
||||
*/
|
||||
#include "interprocess.h"
|
||||
|
||||
#include <thread>
|
||||
#include <boost/interprocess/sync/scoped_lock.hpp>
|
||||
|
||||
using namespace boost::interprocess;
|
||||
using namespace std::literals;
|
||||
|
||||
|
||||
|
||||
|
||||
void
|
||||
init_shared_memory(SharedMemory* memory){
|
||||
for (int i = 0; i < QUEUE_SIZE; i++) {
|
||||
memory->audio_order[i] = -1;
|
||||
memory->video_order[i] = -1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < EventType::EVENT_TYPE_MAX; i++)
|
||||
memory->events[i].read = 1;
|
||||
}
|
||||
|
||||
|
||||
int queue_size(int* queue) {
|
||||
int i = 0;
|
||||
while (*queue != -1 && i != QUEUE_SIZE){ // wait while queue is full
|
||||
queue++;
|
||||
i++;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
push_audio_packet(SharedMemory* memory, void* data, int size){
|
||||
// wait while queue is full
|
||||
while (queue_size(memory->audio_order) == QUEUE_SIZE)
|
||||
std::this_thread::sleep_for(1ms);
|
||||
|
||||
scoped_lock<interprocess_mutex> lock(memory->lock);
|
||||
|
||||
int available = -1;
|
||||
// find available packet slot
|
||||
for (int k = 0; k < QUEUE_SIZE; k++) {
|
||||
int fnd = 0;
|
||||
|
||||
int j = 0;
|
||||
while ( memory->audio_order[j] != -1 && j != QUEUE_SIZE) {
|
||||
if (memory->audio_order[j] == k) {
|
||||
fnd = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
j++;
|
||||
}
|
||||
|
||||
if (fnd)
|
||||
continue;
|
||||
|
||||
available = k;
|
||||
}
|
||||
|
||||
|
||||
memory->audio_order[queue_size(memory->audio_order)] = available;
|
||||
Packet* block = &memory->audio[available];
|
||||
memcpy(block->data,data,size);
|
||||
block->size = size;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
push_video_packet(SharedMemory* memory,
|
||||
void* data,
|
||||
int size,
|
||||
VideoMetadata metadata){
|
||||
// wait while queue is full
|
||||
while (queue_size(memory->audio_order) == QUEUE_SIZE)
|
||||
std::this_thread::sleep_for(1ms);
|
||||
|
||||
scoped_lock<interprocess_mutex> lock(memory->lock);
|
||||
|
||||
int available = -1;
|
||||
for (int k = 0; k < QUEUE_SIZE; k++) {
|
||||
int fnd = 0;
|
||||
|
||||
int j = 0;
|
||||
while ( memory->video_order[j] != -1 && j != QUEUE_SIZE) {
|
||||
if (memory->video_order[j] == k) {
|
||||
fnd = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
j++;
|
||||
}
|
||||
|
||||
if (fnd)
|
||||
continue;
|
||||
|
||||
available = k;
|
||||
}
|
||||
|
||||
|
||||
memory->video_order[queue_size(memory->video_order)] = available;
|
||||
Packet* block = &memory->video[available];
|
||||
memcpy(block->data,data,size);
|
||||
block->size = size;
|
||||
block->metadata = metadata;
|
||||
}
|
||||
|
||||
int
|
||||
peek_video_packet(SharedMemory* memory){
|
||||
return memory->video_order[0] != -1;
|
||||
}
|
||||
|
||||
int
|
||||
peek_audio_packet(SharedMemory* memory){
|
||||
return memory->audio_order[0] != -1;
|
||||
}
|
||||
|
||||
void
|
||||
pop_audio_packet(SharedMemory* memory, void* data, int* size){
|
||||
while (!peek_audio_packet(memory))
|
||||
std::this_thread::sleep_for(1ms);
|
||||
|
||||
scoped_lock<interprocess_mutex> lock(memory->lock);
|
||||
|
||||
int pop = memory->audio_order[0];
|
||||
Packet *block = &memory->audio[pop];
|
||||
memcpy(data,block->data,block->size);
|
||||
*size = block->size;
|
||||
|
||||
// reorder
|
||||
for (int i = 0; i < QUEUE_SIZE - 1; i++)
|
||||
memory->audio_order[i] = memory->audio_order[i+1];
|
||||
|
||||
memory->audio_order[QUEUE_SIZE - 1] = -1;
|
||||
|
||||
}
|
||||
|
||||
VideoMetadata
|
||||
pop_video_packet(SharedMemory* memory, void* data, int* size){
|
||||
while (!peek_video_packet(memory))
|
||||
std::this_thread::sleep_for(1ms);
|
||||
|
||||
scoped_lock<interprocess_mutex> lock(memory->lock);
|
||||
|
||||
int pop = memory->video_order[0];
|
||||
Packet *block = &memory->video[pop];
|
||||
memcpy(data,block->data,block->size);
|
||||
*size = block->size;
|
||||
auto copy = block->metadata;
|
||||
|
||||
// reorder
|
||||
for (int i = 0; i < QUEUE_SIZE - 1; i++)
|
||||
memory->video_order[i] = memory->video_order[i+1];
|
||||
|
||||
memory->video_order[QUEUE_SIZE - 1] = -1;
|
||||
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
void
|
||||
raise_event(SharedMemory* memory, EventType type, Event event){
|
||||
event.read = false;
|
||||
memcpy(&memory->events[type],&event,sizeof(Event));
|
||||
}
|
||||
|
||||
int
|
||||
peek_event(SharedMemory* memory, EventType type){
|
||||
return !memory->events[type].read;
|
||||
}
|
||||
|
||||
Event
|
||||
pop_event(SharedMemory* memory, EventType type){
|
||||
memory->events[type].read = true;
|
||||
return memory->events[type];
|
||||
}
|
||||
|
||||
void
|
||||
wait_event(SharedMemory* memory, EventType type){
|
||||
while(memory->events[type].read)
|
||||
std::this_thread::sleep_for(1ms);
|
||||
}
|
||||
98
src/interprocess.h
Normal file
98
src/interprocess.h
Normal file
@ -0,0 +1,98 @@
|
||||
/**
|
||||
* @file globals.h
|
||||
* @brief Header for globally accessible variables and functions.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "thread_pool.h"
|
||||
#include "thread_safe.h"
|
||||
|
||||
#include <boost/interprocess/sync/interprocess_mutex.hpp>
|
||||
|
||||
|
||||
using namespace boost::interprocess;
|
||||
|
||||
#define QUEUE_SIZE 16
|
||||
#define PACKET_SIZE 32 * 1024
|
||||
|
||||
typedef struct {
|
||||
int is_idr;
|
||||
|
||||
|
||||
}VideoMetadata;
|
||||
|
||||
typedef struct {
|
||||
int size;
|
||||
VideoMetadata metadata;
|
||||
char data[PACKET_SIZE];
|
||||
} Packet;
|
||||
|
||||
typedef enum _EventType {
|
||||
POINTER_VISIBLE,
|
||||
CHANGE_BITRATE,
|
||||
CHANGE_FRAMERATE,
|
||||
CHANGE_DISPLAY,
|
||||
IDR_FRAME,
|
||||
|
||||
STOP,
|
||||
HDR_CALLBACK,
|
||||
EVENT_TYPE_MAX
|
||||
} EventType;
|
||||
|
||||
typedef enum _DataType {
|
||||
HDR_INFO,
|
||||
} DataType;
|
||||
|
||||
typedef struct {
|
||||
int value_number;
|
||||
char value_raw[PACKET_SIZE];
|
||||
int data_size;
|
||||
|
||||
DataType type;
|
||||
|
||||
int read;
|
||||
} Event;
|
||||
|
||||
typedef struct {
|
||||
interprocess_mutex lock;
|
||||
Packet audio[QUEUE_SIZE];
|
||||
Packet video[QUEUE_SIZE];
|
||||
int audio_order[QUEUE_SIZE];
|
||||
int video_order[QUEUE_SIZE];
|
||||
|
||||
|
||||
Event events[EVENT_TYPE_MAX];
|
||||
}SharedMemory;
|
||||
|
||||
void
|
||||
init_shared_memory(SharedMemory* memory);
|
||||
|
||||
void
|
||||
push_audio_packet(SharedMemory* memory, void* data, int size);
|
||||
|
||||
void
|
||||
push_video_packet(SharedMemory* memory, void* data, int size, VideoMetadata metadata);
|
||||
|
||||
int
|
||||
peek_video_packet(SharedMemory* memory);
|
||||
|
||||
int
|
||||
peek_audio_packet(SharedMemory* memory);
|
||||
|
||||
void
|
||||
pop_audio_packet(SharedMemory* memory, void* data, int* size);
|
||||
|
||||
VideoMetadata
|
||||
pop_video_packet(SharedMemory* memory, void* data, int* size);
|
||||
|
||||
void
|
||||
raise_event(SharedMemory* memory, EventType type, Event event);
|
||||
|
||||
int
|
||||
peek_event(SharedMemory* memory, EventType type);
|
||||
|
||||
Event
|
||||
pop_event(SharedMemory* memory, EventType type);
|
||||
|
||||
void
|
||||
wait_event(SharedMemory* memory, EventType type);
|
||||
18
src/main.cpp
18
src/main.cpp
@ -7,9 +7,11 @@
|
||||
#include <csignal>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <boost/interprocess/managed_shared_memory.hpp>
|
||||
|
||||
// local includes
|
||||
#include "globals.h"
|
||||
#include "interprocess.h"
|
||||
#include "logging.h"
|
||||
#include "main.h"
|
||||
#include "version.h"
|
||||
@ -23,6 +25,7 @@
|
||||
#endif
|
||||
|
||||
using namespace std::literals;
|
||||
using namespace boost::interprocess;
|
||||
|
||||
std::map<int, std::function<void()>> signal_handlers;
|
||||
void
|
||||
@ -142,6 +145,21 @@ main(int argc, char *argv[]) {
|
||||
BOOST_LOG(error) << "Video failed to find working encoder"sv;
|
||||
}
|
||||
|
||||
|
||||
//Open managed segment
|
||||
managed_shared_memory segment(open_only, "MySharedMemory");
|
||||
|
||||
//An handle from the base address can identify any byte of the shared
|
||||
//memory segment even if it is mapped in different base addresses
|
||||
managed_shared_memory::handle_t handle = 0;
|
||||
|
||||
//Obtain handle value
|
||||
std::stringstream s; s << argv[1]; s >> handle;
|
||||
|
||||
//Get buffer local address from handle
|
||||
SharedMemory* memory = (SharedMemory*)segment.get_address_from_handle(handle);
|
||||
|
||||
|
||||
auto video_capture = std::thread{[&](){
|
||||
video::capture(mail::man,video::config_t{
|
||||
1920, 1080, 60, 6000, 1, 0, 1, 0, 0
|
||||
|
||||
70
src/parent.cpp
Normal file
70
src/parent.cpp
Normal file
@ -0,0 +1,70 @@
|
||||
|
||||
#include <boost/interprocess/managed_shared_memory.hpp>
|
||||
#include <cstdlib> //std::system
|
||||
#include <thread>
|
||||
#include <sstream>
|
||||
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
#include "interprocess.h"
|
||||
|
||||
|
||||
using namespace boost::interprocess;
|
||||
using namespace std::literals;
|
||||
int main (int argc, char *argv[]) {
|
||||
|
||||
//Remove shared memory on construction and destruction
|
||||
struct shm_remove {
|
||||
shm_remove() { shared_memory_object::remove("MySharedMemory"); }
|
||||
~shm_remove(){ shared_memory_object::remove("MySharedMemory"); }
|
||||
} remover;
|
||||
|
||||
//Create a managed shared memory segment
|
||||
managed_shared_memory segment(create_only, "MySharedMemory", 2 * sizeof(SharedMemory));
|
||||
|
||||
//Allocate a portion of the segment (raw memory)
|
||||
std::size_t free_memory = segment.get_free_memory();
|
||||
SharedMemory* memory = (SharedMemory*)segment.allocate(sizeof(SharedMemory));
|
||||
|
||||
//Check invariant
|
||||
if(free_memory <= segment.get_free_memory())
|
||||
return 1;
|
||||
|
||||
auto running = true;
|
||||
auto thread = std::thread{[&](){
|
||||
while (running) {
|
||||
// std::this_thread::sleep_for(1ms);
|
||||
// if (!video_buffer->read) {
|
||||
// std::cout << "Audio buffer received : " << video_buffer->size << "\n";
|
||||
// video_buffer->read = true;
|
||||
// }
|
||||
// if (!audio_buffer->read) {
|
||||
// std::cout << "Video buffer received : " << audio_buffer->size << "\n";
|
||||
// audio_buffer->read = true;
|
||||
// }
|
||||
}
|
||||
}};
|
||||
|
||||
//An handle from the base address can identify any byte of the shared
|
||||
//memory segment even if it is mapped in different base addresses
|
||||
managed_shared_memory::handle_t handle = segment.get_handle_from_address((void*)memory);
|
||||
|
||||
#ifdef _WIN32
|
||||
auto binary = "sunshine.exe";
|
||||
#else
|
||||
auto binary = "./sunshine";
|
||||
#endif
|
||||
|
||||
std::stringstream s; s << binary << " " << handle; s << std::ends;
|
||||
|
||||
//Launch child process
|
||||
if(0 != std::system(s.str().c_str()))
|
||||
return 1;
|
||||
if(free_memory != segment.get_free_memory())
|
||||
return 1;
|
||||
|
||||
running = false;
|
||||
thread.join();
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user