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