We're not offloading scaling and YUV conversion from the CPU yet, so the gains aren't as high as one of the fully accelerated backends like Windows NVENC or Linux VAAPI. Still, offloading the H.264/HEVC encoding itself is an improvement over doing everything on the CPU.
260 lines
5.6 KiB
C++
260 lines
5.6 KiB
C++
//
|
|
// Created by loki on 6/21/19.
|
|
//
|
|
|
|
#ifndef SUNSHINE_COMMON_H
|
|
#define SUNSHINE_COMMON_H
|
|
|
|
#include <bitset>
|
|
#include <filesystem>
|
|
#include <mutex>
|
|
#include <string>
|
|
|
|
#include "sunshine/utility.h"
|
|
|
|
struct sockaddr;
|
|
struct AVFrame;
|
|
|
|
namespace platf {
|
|
constexpr auto MAX_GAMEPADS = 32;
|
|
|
|
constexpr std::uint16_t DPAD_UP = 0x0001;
|
|
constexpr std::uint16_t DPAD_DOWN = 0x0002;
|
|
constexpr std::uint16_t DPAD_LEFT = 0x0004;
|
|
constexpr std::uint16_t DPAD_RIGHT = 0x0008;
|
|
constexpr std::uint16_t START = 0x0010;
|
|
constexpr std::uint16_t BACK = 0x0020;
|
|
constexpr std::uint16_t LEFT_STICK = 0x0040;
|
|
constexpr std::uint16_t RIGHT_STICK = 0x0080;
|
|
constexpr std::uint16_t LEFT_BUTTON = 0x0100;
|
|
constexpr std::uint16_t RIGHT_BUTTON = 0x0200;
|
|
constexpr std::uint16_t HOME = 0x0400;
|
|
constexpr std::uint16_t A = 0x1000;
|
|
constexpr std::uint16_t B = 0x2000;
|
|
constexpr std::uint16_t X = 0x4000;
|
|
constexpr std::uint16_t Y = 0x8000;
|
|
|
|
namespace speaker {
|
|
enum speaker_e {
|
|
FRONT_LEFT,
|
|
FRONT_RIGHT,
|
|
FRONT_CENTER,
|
|
LOW_FREQUENCY,
|
|
BACK_LEFT,
|
|
BACK_RIGHT,
|
|
SIDE_LEFT,
|
|
SIDE_RIGHT,
|
|
MAX_SPEAKERS,
|
|
};
|
|
|
|
constexpr std::uint8_t map_stereo[] {
|
|
FRONT_LEFT, FRONT_RIGHT
|
|
};
|
|
constexpr std::uint8_t map_surround51[] {
|
|
FRONT_LEFT,
|
|
FRONT_RIGHT,
|
|
FRONT_CENTER,
|
|
LOW_FREQUENCY,
|
|
BACK_LEFT,
|
|
BACK_RIGHT,
|
|
};
|
|
constexpr std::uint8_t map_surround71[] {
|
|
FRONT_LEFT,
|
|
FRONT_RIGHT,
|
|
FRONT_CENTER,
|
|
LOW_FREQUENCY,
|
|
LOW_FREQUENCY,
|
|
BACK_LEFT,
|
|
BACK_RIGHT,
|
|
SIDE_LEFT,
|
|
SIDE_RIGHT,
|
|
};
|
|
} // namespace speaker
|
|
|
|
enum class mem_type_e {
|
|
system,
|
|
vaapi,
|
|
dxgi,
|
|
cuda,
|
|
unknown
|
|
};
|
|
|
|
enum class pix_fmt_e {
|
|
yuv420p,
|
|
yuv420p10,
|
|
nv12,
|
|
p010,
|
|
unknown
|
|
};
|
|
|
|
inline std::string_view from_pix_fmt(pix_fmt_e pix_fmt) {
|
|
using namespace std::literals;
|
|
#define _CONVERT(x) \
|
|
case pix_fmt_e::x: \
|
|
return #x##sv
|
|
switch(pix_fmt) {
|
|
_CONVERT(yuv420p);
|
|
_CONVERT(yuv420p10);
|
|
_CONVERT(nv12);
|
|
_CONVERT(p010);
|
|
_CONVERT(unknown);
|
|
}
|
|
#undef _CONVERT
|
|
|
|
return "unknown"sv;
|
|
}
|
|
|
|
// Dimensions for touchscreen input
|
|
struct touch_port_t {
|
|
int offset_x, offset_y;
|
|
int width, height;
|
|
};
|
|
|
|
struct gamepad_state_t {
|
|
std::uint16_t buttonFlags;
|
|
std::uint8_t lt;
|
|
std::uint8_t rt;
|
|
std::int16_t lsX;
|
|
std::int16_t lsY;
|
|
std::int16_t rsX;
|
|
std::int16_t rsY;
|
|
};
|
|
|
|
class deinit_t {
|
|
public:
|
|
virtual ~deinit_t() = default;
|
|
};
|
|
|
|
struct img_t {
|
|
public:
|
|
std::uint8_t *data {};
|
|
std::int32_t width {};
|
|
std::int32_t height {};
|
|
std::int32_t pixel_pitch {};
|
|
std::int32_t row_pitch {};
|
|
|
|
img_t() = default;
|
|
img_t(const img_t &) = delete;
|
|
img_t(img_t &&) = delete;
|
|
|
|
virtual ~img_t() = default;
|
|
};
|
|
|
|
struct sink_t {
|
|
// Play on host PC
|
|
std::string host;
|
|
|
|
// On Windows, it is not possible to create a virtual sink
|
|
// Therefore, it is optional
|
|
struct null_t {
|
|
std::string stereo;
|
|
std::string surround51;
|
|
std::string surround71;
|
|
};
|
|
std::optional<null_t> null;
|
|
};
|
|
|
|
struct hwdevice_t {
|
|
void *data {};
|
|
AVFrame *frame {};
|
|
|
|
virtual int convert(platf::img_t &img) {
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* implementations must take ownership of 'frame'
|
|
*/
|
|
virtual int set_frame(AVFrame *frame) {
|
|
std::abort(); // ^ This function must never be called
|
|
return -1;
|
|
};
|
|
|
|
virtual void set_colorspace(std::uint32_t colorspace, std::uint32_t color_range) {};
|
|
|
|
virtual ~hwdevice_t() = default;
|
|
};
|
|
|
|
enum class capture_e : int {
|
|
ok,
|
|
reinit,
|
|
timeout,
|
|
error
|
|
};
|
|
|
|
class display_t {
|
|
public:
|
|
display_t() noexcept : offset_x { 0 }, offset_y { 0 } {}
|
|
virtual capture_e snapshot(img_t *img, std::chrono::milliseconds timeout, bool cursor) = 0;
|
|
virtual std::shared_ptr<img_t> alloc_img() = 0;
|
|
|
|
virtual int dummy_img(img_t *img) = 0;
|
|
|
|
virtual std::shared_ptr<hwdevice_t> make_hwdevice(pix_fmt_e pix_fmt) {
|
|
return std::make_shared<hwdevice_t>();
|
|
}
|
|
|
|
virtual ~display_t() = default;
|
|
|
|
// Offsets for when streaming a specific monitor. By default, they are 0.
|
|
int offset_x, offset_y;
|
|
int env_width, env_height;
|
|
|
|
int width, height;
|
|
};
|
|
|
|
class mic_t {
|
|
public:
|
|
virtual capture_e sample(std::vector<std::int16_t> &frame_buffer) = 0;
|
|
|
|
virtual ~mic_t() = default;
|
|
};
|
|
|
|
class audio_control_t {
|
|
public:
|
|
virtual int set_sink(const std::string &sink) = 0;
|
|
|
|
virtual std::unique_ptr<mic_t> microphone(const std::uint8_t *mapping, int channels, std::uint32_t sample_rate, std::uint32_t frame_size) = 0;
|
|
|
|
virtual std::optional<sink_t> sink_info() = 0;
|
|
|
|
virtual ~audio_control_t() = default;
|
|
};
|
|
|
|
void freeInput(void *);
|
|
|
|
using input_t = util::safe_ptr<void, freeInput>;
|
|
|
|
std::filesystem::path appdata();
|
|
|
|
std::string get_mac_address(const std::string_view &address);
|
|
|
|
std::string from_sockaddr(const sockaddr *const);
|
|
std::pair<std::uint16_t, std::string> from_sockaddr_ex(const sockaddr *const);
|
|
|
|
std::unique_ptr<audio_control_t> audio_control();
|
|
std::shared_ptr<display_t> display(mem_type_e hwdevice_type);
|
|
|
|
input_t input();
|
|
void move_mouse(input_t &input, int deltaX, int deltaY);
|
|
void abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y);
|
|
void button_mouse(input_t &input, int button, bool release);
|
|
void scroll(input_t &input, int distance);
|
|
void keyboard(input_t &input, uint16_t modcode, bool release);
|
|
void gamepad(input_t &input, int nr, const gamepad_state_t &gamepad_state);
|
|
|
|
int alloc_gamepad(input_t &input, int nr);
|
|
void free_gamepad(input_t &input, int nr);
|
|
|
|
#define SERVICE_NAME "Sunshine"
|
|
#define SERVICE_TYPE "_nvstream._tcp"
|
|
|
|
namespace publish {
|
|
[[nodiscard]] std::unique_ptr<deinit_t> start();
|
|
}
|
|
|
|
[[nodiscard]] std::unique_ptr<deinit_t> init();
|
|
} // namespace platf
|
|
|
|
#endif //SUNSHINE_COMMON_H
|