-
Notifications
You must be signed in to change notification settings - Fork 1k
Expand file tree
/
Copy pathsession.h
More file actions
295 lines (223 loc) · 7.84 KB
/
session.h
File metadata and controls
295 lines (223 loc) · 7.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
#pragma once
#include <QSemaphore>
#include <QQuickWindow>
#include <Limelight.h>
#include <opus_multistream.h>
#include "settings/streamingpreferences.h"
#include "input/input.h"
#include "video/decoder.h"
#include "audio/renderers/renderer.h"
#include "video/overlaymanager.h"
class SupportedVideoFormatList : public QList<int>
{
public:
operator int() const
{
int value = 0;
for (const int v : *this) {
value |= v;
}
return value;
}
void
removeByMask(int mask)
{
int i = 0;
while (i < this->length()) {
if (this->value(i) & mask) {
this->removeAt(i);
}
else {
i++;
}
}
}
void
deprioritizeByMask(int mask)
{
QList<int> deprioritizedList;
int i = 0;
while (i < this->length()) {
if (this->value(i) & mask) {
deprioritizedList.append(this->takeAt(i));
}
else {
i++;
}
}
this->append(std::move(deprioritizedList));
}
int maskByServerCodecModes(int serverCodecModes)
{
int mask = 0;
const QMap<int, int> mapping = {
{SCM_H264, VIDEO_FORMAT_H264},
{SCM_H264_HIGH8_444, VIDEO_FORMAT_H264_HIGH8_444},
{SCM_HEVC, VIDEO_FORMAT_H265},
{SCM_HEVC_MAIN10, VIDEO_FORMAT_H265_MAIN10},
{SCM_HEVC_REXT8_444, VIDEO_FORMAT_H265_REXT8_444},
{SCM_HEVC_REXT10_444, VIDEO_FORMAT_H265_REXT10_444},
{SCM_AV1_MAIN8, VIDEO_FORMAT_AV1_MAIN8},
{SCM_AV1_MAIN10, VIDEO_FORMAT_AV1_MAIN10},
{SCM_AV1_HIGH8_444, VIDEO_FORMAT_AV1_HIGH8_444},
{SCM_AV1_HIGH10_444, VIDEO_FORMAT_AV1_HIGH10_444},
};
for (QMap<int, int>::const_iterator it = mapping.cbegin(); it != mapping.cend(); ++it) {
if (serverCodecModes & it.key()) {
mask |= it.value();
serverCodecModes &= ~it.key();
}
}
// Make sure nobody forgets to update this for new SCM values
SDL_assert(serverCodecModes == 0);
int val = *this;
return val & mask;
}
};
class Session : public QObject
{
Q_OBJECT
friend class SdlInputHandler;
friend class DeferredSessionCleanupTask;
friend class AsyncConnectionStartThread;
public:
explicit Session(NvComputer* computer, NvApp& app, StreamingPreferences *preferences = nullptr);
virtual ~Session();
Q_INVOKABLE bool initialize(QQuickWindow* qtWindow);
Q_INVOKABLE void start();
Q_INVOKABLE void interrupt();
Q_PROPERTY(QStringList launchWarnings MEMBER m_LaunchWarnings NOTIFY launchWarningsChanged);
static
void getDecoderInfo(SDL_Window* window,
bool& isHardwareAccelerated, bool& isFullScreenOnly,
bool& isHdrSupported, QSize& maxResolution);
static Session* get()
{
return s_ActiveSession;
}
Overlay::OverlayManager& getOverlayManager()
{
return m_OverlayManager;
}
void flushWindowEvents();
void setShouldExit(bool quitHostApp = false);
signals:
void stageStarting(QString stage);
void stageFailed(QString stage, int errorCode, QString failingPorts);
void connectionStarted();
void displayLaunchError(QString text);
void quitStarting();
void sessionFinished(int portTestResult);
// Emitted after sessionFinished() when the session is ready to be destroyed
void readyForDeletion();
void launchWarningsChanged();
private:
void exec();
bool startConnectionAsync();
bool validateLaunch(SDL_Window* testWindow);
void emitLaunchWarning(QString text);
bool populateDecoderProperties(SDL_Window* window);
IAudioRenderer* createAudioRenderer(const POPUS_MULTISTREAM_CONFIGURATION opusConfig);
bool initializeAudioRenderer();
bool testAudio(int audioConfiguration);
int getAudioRendererCapabilities(int audioConfiguration);
void getWindowDimensions(int& x, int& y,
int& width, int& height);
void toggleFullscreen();
void notifyMouseEmulationMode(bool enabled);
void updateOptimalWindowDisplayMode();
enum class DecoderAvailability {
None,
Software,
Hardware
};
static
DecoderAvailability getDecoderAvailability(SDL_Window* window,
StreamingPreferences::VideoDecoderSelection vds,
int videoFormat, int width, int height, int frameRate);
static
bool chooseDecoder(StreamingPreferences::VideoDecoderSelection vds,
SDL_Window* window, int videoFormat, int width, int height,
int frameRate, bool enableVsync, bool enableFramePacing,
bool testOnly,
IVideoDecoder*& chosenDecoder);
static
void clStageStarting(int stage);
static
void clStageFailed(int stage, int errorCode);
static
void clConnectionTerminated(int errorCode);
static
void clLogMessage(const char* format, ...);
static
void clRumble(unsigned short controllerNumber, unsigned short lowFreqMotor, unsigned short highFreqMotor);
static
void clConnectionStatusUpdate(int connectionStatus);
static
void clSetHdrMode(bool enabled);
static
void clRumbleTriggers(uint16_t controllerNumber, uint16_t leftTrigger, uint16_t rightTrigger);
static
void clSetMotionEventState(uint16_t controllerNumber, uint8_t motionType, uint16_t reportRateHz);
static
void clSetControllerLED(uint16_t controllerNumber, uint8_t r, uint8_t g, uint8_t b);
static
void clSetAdaptiveTriggers(uint16_t controllerNumber, uint8_t eventFlags, uint8_t typeLeft, uint8_t typeRight, uint8_t *left, uint8_t *right);
static
int arInit(int audioConfiguration,
const POPUS_MULTISTREAM_CONFIGURATION opusConfig,
void* arContext, int arFlags);
static
void arCleanup();
static
void arDecodeAndPlaySample(char* sampleData, int sampleLength);
static
int drSetup(int videoFormat, int width, int height, int frameRate, void*, int);
static
void drCleanup();
static
int drSubmitDecodeUnit(PDECODE_UNIT du);
StreamingPreferences* m_Preferences;
bool m_IsFullScreen;
SupportedVideoFormatList m_SupportedVideoFormats; // Sorted in order of descending priority
STREAM_CONFIGURATION m_StreamConfig;
DECODER_RENDERER_CALLBACKS m_VideoCallbacks;
AUDIO_RENDERER_CALLBACKS m_AudioCallbacks;
NvComputer* m_Computer;
NvApp m_App;
SDL_Window* m_Window;
IVideoDecoder* m_VideoDecoder;
SDL_mutex* m_DecoderLock;
bool m_AudioDisabled;
bool m_AudioMuted;
Uint32 m_FullScreenFlag;
QQuickWindow* m_QtWindow;
bool m_UnexpectedTermination;
SdlInputHandler* m_InputHandler;
int m_MouseEmulationRefCount;
int m_FlushingWindowEventsRef;
QStringList m_LaunchWarnings;
bool m_ShouldExit;
bool m_AsyncConnectionSuccess;
int m_PortTestResults;
int m_ActiveVideoFormat;
int m_ActiveVideoWidth;
int m_ActiveVideoHeight;
int m_ActiveVideoFrameRate;
OpusMSDecoder* m_OpusDecoder;
IAudioRenderer* m_AudioRenderer;
OPUS_MULTISTREAM_CONFIGURATION m_ActiveAudioConfig;
OPUS_MULTISTREAM_CONFIGURATION m_OriginalAudioConfig;
int m_AudioSampleCount;
Uint32 m_DropAudioEndTime;
Overlay::OverlayManager m_OverlayManager;
// Inactivity timeout tracking
Uint32 m_LastInputTime;
Uint32 m_InactivityTimeoutMs;
bool m_InactivityTimeoutEnabled;
static CONNECTION_LISTENER_CALLBACKS k_ConnCallbacks;
static Session* s_ActiveSession;
static QSemaphore s_ActiveSessionSemaphore;
void checkInactivityTimeout();
void resetInactivityTimer();
};