Sunshine latest
Self-hosted game stream host for Moonlight.
video.h
Go to the documentation of this file.
1
5#pragma once
6
7// local includes
8#include "input.h"
9#include "platform/common.h"
10#include "thread_safe.h"
11#include "video_colorspace.h"
12
13extern "C" {
14#include <libavcodec/avcodec.h>
15#include <libswscale/swscale.h>
16}
17
18struct AVPacket;
19
20namespace video {
21
22 /* Encoding configuration requested by remote client */
23 struct config_t {
24 int width; // Video width in pixels
25 int height; // Video height in pixels
26 int framerate; // Requested framerate, used in individual frame bitrate budget calculation
27 int bitrate; // Video bitrate in kilobits (1000 bits) for requested framerate
28 int slicesPerFrame; // Number of slices per frame
29 int numRefFrames; // Max number of reference frames
30
31 /* Requested color range and SDR encoding colorspace, HDR encoding colorspace is always BT.2020+ST2084
32 Color range (encoderCscMode & 0x1) : 0 - limited, 1 - full
33 SDR encoding colorspace (encoderCscMode >> 1) : 0 - BT.601, 1 - BT.709, 2 - BT.2020 */
34 int encoderCscMode;
35
36 int videoFormat; // 0 - H.264, 1 - HEVC, 2 - AV1
37
38 /* Encoding color depth (bit depth): 0 - 8-bit, 1 - 10-bit
39 HDR encoding activates when color depth is higher than 8-bit and the display which is being captured is operating in HDR mode */
40 int dynamicRange;
41
42 int chromaSamplingType; // 0 - 4:2:0, 1 - 4:4:4
43
44 int enableIntraRefresh; // 0 - disabled, 1 - enabled
45 };
46
47 platf::mem_type_e map_base_dev_type(AVHWDeviceType type);
48 platf::pix_fmt_e map_pix_fmt(AVPixelFormat fmt);
49
50 void free_ctx(AVCodecContext *ctx);
51 void free_frame(AVFrame *frame);
52 void free_buffer(AVBufferRef *ref);
53
58 using img_event_t = std::shared_ptr<safe::event_t<std::shared_ptr<platf::img_t>>>;
59
61 virtual ~encoder_platform_formats_t() = default;
62 platf::mem_type_e dev_type;
63 platf::pix_fmt_e pix_fmt_8bit, pix_fmt_10bit;
64 platf::pix_fmt_e pix_fmt_yuv444_8bit, pix_fmt_yuv444_10bit;
65 };
66
68 using init_buffer_function_t = std::function<util::Either<avcodec_buffer_t, int>(platf::avcodec_encode_device_t *)>;
69
71 const AVHWDeviceType &avcodec_base_dev_type,
72 const AVHWDeviceType &avcodec_derived_dev_type,
73 const AVPixelFormat &avcodec_dev_pix_fmt,
74 const AVPixelFormat &avcodec_pix_fmt_8bit,
75 const AVPixelFormat &avcodec_pix_fmt_10bit,
76 const AVPixelFormat &avcodec_pix_fmt_yuv444_8bit,
77 const AVPixelFormat &avcodec_pix_fmt_yuv444_10bit,
78 const init_buffer_function_t &init_avcodec_hardware_input_buffer_function
79 ):
80 avcodec_base_dev_type {avcodec_base_dev_type},
81 avcodec_derived_dev_type {avcodec_derived_dev_type},
82 avcodec_dev_pix_fmt {avcodec_dev_pix_fmt},
83 avcodec_pix_fmt_8bit {avcodec_pix_fmt_8bit},
84 avcodec_pix_fmt_10bit {avcodec_pix_fmt_10bit},
85 avcodec_pix_fmt_yuv444_8bit {avcodec_pix_fmt_yuv444_8bit},
86 avcodec_pix_fmt_yuv444_10bit {avcodec_pix_fmt_yuv444_10bit},
87 init_avcodec_hardware_input_buffer {init_avcodec_hardware_input_buffer_function} {
88 dev_type = map_base_dev_type(avcodec_base_dev_type);
89 pix_fmt_8bit = map_pix_fmt(avcodec_pix_fmt_8bit);
90 pix_fmt_10bit = map_pix_fmt(avcodec_pix_fmt_10bit);
91 pix_fmt_yuv444_8bit = map_pix_fmt(avcodec_pix_fmt_yuv444_8bit);
92 pix_fmt_yuv444_10bit = map_pix_fmt(avcodec_pix_fmt_yuv444_10bit);
93 }
94
95 AVHWDeviceType avcodec_base_dev_type, avcodec_derived_dev_type;
96 AVPixelFormat avcodec_dev_pix_fmt;
97 AVPixelFormat avcodec_pix_fmt_8bit, avcodec_pix_fmt_10bit;
98 AVPixelFormat avcodec_pix_fmt_yuv444_8bit, avcodec_pix_fmt_yuv444_10bit;
99
100 init_buffer_function_t init_avcodec_hardware_input_buffer;
101 };
102
105 const platf::mem_type_e &dev_type,
106 const platf::pix_fmt_e &pix_fmt_8bit,
107 const platf::pix_fmt_e &pix_fmt_10bit,
108 const platf::pix_fmt_e &pix_fmt_yuv444_8bit,
109 const platf::pix_fmt_e &pix_fmt_yuv444_10bit
110 ) {
111 encoder_platform_formats_t::dev_type = dev_type;
112 encoder_platform_formats_t::pix_fmt_8bit = pix_fmt_8bit;
113 encoder_platform_formats_t::pix_fmt_10bit = pix_fmt_10bit;
114 encoder_platform_formats_t::pix_fmt_yuv444_8bit = pix_fmt_yuv444_8bit;
115 encoder_platform_formats_t::pix_fmt_yuv444_10bit = pix_fmt_yuv444_10bit;
116 }
117 };
118
119 struct encoder_t {
120 std::string_view name;
121
130
131 static std::string_view from_flag(flag_e flag) {
132#define _CONVERT(x) \
133 case flag_e::x: \
134 return std::string_view(#x)
135 switch (flag) {
136 _CONVERT(PASSED);
137 _CONVERT(REF_FRAMES_RESTRICT);
138 _CONVERT(DYNAMIC_RANGE);
139 _CONVERT(YUV444);
140 _CONVERT(VUI_PARAMETERS);
141 _CONVERT(MAX_FLAGS);
142 }
143#undef _CONVERT
144
145 return {"unknown"};
146 }
147
148 struct option_t {
149 KITTY_DEFAULT_CONSTR_MOVE(option_t)
150 option_t(const option_t &) = default;
151
152 std::string name;
153 std::variant<int, int *, std::optional<int> *, std::function<int()>, std::string, std::string *> value;
154
155 option_t(std::string &&name, decltype(value) &&value):
156 name {std::move(name)},
157 value {std::move(value)} {
158 }
159 };
160
161 const std::unique_ptr<const encoder_platform_formats_t> platform_formats;
162
163 struct codec_t {
164 std::vector<option_t> common_options;
165 std::vector<option_t> sdr_options;
166 std::vector<option_t> hdr_options;
167 std::vector<option_t> sdr444_options;
168 std::vector<option_t> hdr444_options;
169 std::vector<option_t> fallback_options;
170
171 std::string name;
172 std::bitset<MAX_FLAGS> capabilities;
173
174 bool operator[](flag_e flag) const {
175 return capabilities[(std::size_t) flag];
176 }
177
178 std::bitset<MAX_FLAGS>::reference operator[](flag_e flag) {
179 return capabilities[(std::size_t) flag];
180 }
181 } av1, hevc, h264;
182
183 const codec_t &codec_from_config(const config_t &config) const {
184 switch (config.videoFormat) {
185 default:
186 BOOST_LOG(error) << "Unknown video format " << config.videoFormat << ", falling back to H.264";
187 // fallthrough
188 case 0:
189 return h264;
190 case 1:
191 return hevc;
192 case 2:
193 return av1;
194 }
195 }
196
197 uint32_t flags;
198 };
199
201 virtual ~encode_session_t() = default;
202
203 virtual int convert(platf::img_t &img) = 0;
204
205 virtual void request_idr_frame() = 0;
206
207 virtual void request_normal_frame() = 0;
208
209 virtual void invalidate_ref_frames(int64_t first_frame, int64_t last_frame) = 0;
210 };
211
212 // encoders
213 extern encoder_t software;
214
215#if !defined(__APPLE__)
216 extern encoder_t nvenc; // available for windows and linux
217#endif
218
219#ifdef _WIN32
220 extern encoder_t amdvce;
221 extern encoder_t quicksync;
222#endif
223
224#ifdef __linux__
225 extern encoder_t vaapi;
226#endif
227
228#ifdef __APPLE__
229 extern encoder_t videotoolbox;
230#endif
231
233 virtual ~packet_raw_t() = default;
234
235 virtual bool is_idr() = 0;
236
237 virtual int64_t frame_index() = 0;
238
239 virtual uint8_t *data() = 0;
240
241 virtual size_t data_size() = 0;
242
243 struct replace_t {
244 std::string_view old;
245 std::string_view _new;
246
247 KITTY_DEFAULT_CONSTR_MOVE(replace_t)
248
249 replace_t(std::string_view old, std::string_view _new) noexcept:
250 old {std::move(old)},
251 _new {std::move(_new)} {
252 }
253 };
254
255 std::vector<replace_t> *replacements = nullptr;
256 void *channel_data = nullptr;
257 bool after_ref_frame_invalidation = false;
258 std::optional<std::chrono::steady_clock::time_point> frame_timestamp;
259 };
260
263 av_packet = av_packet_alloc();
264 }
265
267 av_packet_free(&this->av_packet);
268 }
269
270 bool is_idr() override {
271 return av_packet->flags & AV_PKT_FLAG_KEY;
272 }
273
274 int64_t frame_index() override {
275 return av_packet->pts;
276 }
277
278 uint8_t *data() override {
279 return av_packet->data;
280 }
281
282 size_t data_size() override {
283 return av_packet->size;
284 }
285
286 AVPacket *av_packet;
287 };
288
290 packet_raw_generic(std::vector<uint8_t> &&frame_data, int64_t frame_index, bool idr):
291 frame_data {std::move(frame_data)},
292 index {frame_index},
293 idr {idr} {
294 }
295
296 bool is_idr() override {
297 return idr;
298 }
299
300 int64_t frame_index() override {
301 return index;
302 }
303
304 uint8_t *data() override {
305 return frame_data.data();
306 }
307
308 size_t data_size() override {
309 return frame_data.size();
310 }
311
312 std::vector<uint8_t> frame_data;
313 int64_t index;
314 bool idr;
315 };
316
317 using packet_t = std::unique_ptr<packet_raw_t>;
318
320 explicit hdr_info_raw_t(bool enabled):
321 enabled {enabled},
322 metadata {} {};
323 explicit hdr_info_raw_t(bool enabled, const SS_HDR_METADATA &metadata):
324 enabled {enabled},
325 metadata {metadata} {};
326
327 bool enabled;
328 SS_HDR_METADATA metadata;
329 };
330
331 using hdr_info_t = std::unique_ptr<hdr_info_raw_t>;
332
333 extern int active_hevc_mode;
334 extern int active_av1_mode;
335 extern bool last_encoder_probe_supported_ref_frames_invalidation;
336 extern std::array<bool, 3> last_encoder_probe_supported_yuv444_for_codec; // 0 - H.264, 1 - HEVC, 2 - AV1
337
338 void capture(
339 safe::mail_t mail,
340 config_t config,
341 void *channel_data
342 );
343
344 bool validate_encoder(encoder_t &encoder, bool expect_failure);
345
354 int probe_encoders();
355} // namespace video
Definition utility.h:530
Declarations for common platform specific utilities.
mem_type_e
Definition common.h:211
pix_fmt_e
Definition common.h:220
Declarations for gamepad, keyboard, and mouse input handling.
Handles process-wide communication.
Definition globals.h:34
Standalone NVENC encoder.
Definition nvenc_base.cpp:87
Definition common.h:390
Definition common.h:347
Definition video.h:23
Definition video.h:200
Definition video.h:163
Definition video.h:148
Definition video.h:119
flag_e
Definition video.h:122
@ DYNAMIC_RANGE
HDR support.
Definition video.h:125
@ VUI_PARAMETERS
AMD encoder with VAAPI doesn't add VUI parameters to SPS.
Definition video.h:127
@ PASSED
Indicates the encoder is supported.
Definition video.h:123
@ REF_FRAMES_RESTRICT
Set maximum reference frames.
Definition video.h:124
@ YUV444
YUV 4:4:4 support.
Definition video.h:126
@ MAX_FLAGS
Maximum number of flags.
Definition video.h:128
Definition video.h:319
Definition video.h:261
Definition video.h:289
Definition video.h:243
Definition video.h:232
Declarations for thread-safe data structures.
flag_e
Definition video.cpp:259
int probe_encoders()
Probe encoders and select the preferred encoder. This is called once at startup and each time a strea...
Definition video.cpp:2552
Declarations for colorspace functions.