@epicgames-ps/lib-pixelstreamingfrontend-ue5.5 0.1.3 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +1 -1
- package/.prettierrc.json +1 -0
- package/dist/lib-pixelstreamingfrontend.esm.js +1 -1
- package/dist/lib-pixelstreamingfrontend.js +1 -1
- package/package.json +6 -5
- package/src/AFK/AFKController.ts +10 -32
- package/src/Config/Config.ts +179 -201
- package/src/Config/SettingBase.ts +61 -2
- package/src/Config/SettingFlag.ts +10 -48
- package/src/Config/SettingNumber.ts +10 -28
- package/src/Config/SettingOption.ts +13 -46
- package/src/Config/SettingText.ts +9 -37
- package/src/DataChannel/DataChannelController.ts +6 -26
- package/src/DataChannel/DataChannelLatencyTestController.ts +38 -33
- package/src/DataChannel/DataChannelLatencyTestResults.ts +8 -10
- package/src/DataChannel/DataChannelSender.ts +5 -15
- package/src/DataChannel/LatencyTestResults.ts +5 -15
- package/src/FreezeFrame/FreezeFrame.ts +7 -19
- package/src/FreezeFrame/FreezeFrameController.ts +3 -14
- package/src/Inputs/GamepadController.ts +123 -221
- package/src/Inputs/GamepadTypes.ts +23 -0
- package/src/Inputs/IInputController.ts +17 -0
- package/src/Inputs/InputClassesFactory.ts +38 -45
- package/src/Inputs/KeyCodes.ts +114 -0
- package/src/Inputs/KeyboardController.ts +49 -232
- package/src/Inputs/MouseController.ts +71 -297
- package/src/Inputs/MouseControllerHovering.ts +118 -0
- package/src/Inputs/MouseControllerLocked.ts +194 -0
- package/src/Inputs/TouchController.ts +49 -105
- package/src/Inputs/TouchControllerFake.ts +132 -0
- package/src/Inputs/XRGamepadController.ts +35 -44
- package/src/PeerConnectionController/AggregatedStats.ts +26 -54
- package/src/PeerConnectionController/CandidatePairStats.ts +1 -1
- package/src/PeerConnectionController/CandidateStat.ts +1 -1
- package/src/PeerConnectionController/PeerConnectionController.ts +217 -164
- package/src/PixelStreaming/PixelStreaming.ts +174 -226
- package/src/UI/OnScreenKeyboard.ts +14 -9
- package/src/UeInstanceMessage/ResponseController.ts +6 -15
- package/src/UeInstanceMessage/SendMessageController.ts +16 -18
- package/src/UeInstanceMessage/StreamMessageController.ts +3 -12
- package/src/UeInstanceMessage/ToStreamerMessagesController.ts +3 -9
- package/src/Util/EventEmitter.ts +17 -22
- package/src/Util/FileUtil.ts +11 -34
- package/src/Util/IURLSearchParams.ts +25 -0
- package/src/Util/InputCoordTranslator.ts +73 -0
- package/src/Util/RTCUtils.ts +23 -15
- package/src/VideoPlayer/StreamController.ts +6 -23
- package/src/VideoPlayer/VideoPlayer.ts +9 -30
- package/src/WebRtcPlayer/WebRtcPlayerController.ts +328 -690
- package/src/WebXR/WebXRController.ts +82 -94
- package/src/pixelstreamingfrontend.ts +6 -10
- package/types/AFK/AFKController.d.ts +0 -1
- package/types/Config/Config.d.ts +6 -5
- package/types/Config/SettingBase.d.ts +13 -0
- package/types/Config/SettingFlag.d.ts +1 -10
- package/types/Config/SettingNumber.d.ts +1 -5
- package/types/Config/SettingOption.d.ts +1 -10
- package/types/Config/SettingText.d.ts +1 -9
- package/types/DataChannel/DataChannelLatencyTestController.d.ts +1 -1
- package/types/Inputs/GamepadController.d.ts +22 -46
- package/types/Inputs/GamepadTypes.d.ts +7 -0
- package/types/Inputs/IInputController.d.ts +16 -0
- package/types/Inputs/InputClassesFactory.d.ts +7 -8
- package/types/Inputs/KeyCodes.d.ts +5 -0
- package/types/Inputs/KeyboardController.d.ts +17 -45
- package/types/Inputs/MouseController.d.ts +33 -68
- package/types/Inputs/MouseControllerHovering.d.ts +26 -0
- package/types/Inputs/MouseControllerLocked.d.ts +31 -0
- package/types/Inputs/TouchController.d.ts +19 -44
- package/types/Inputs/TouchControllerFake.d.ts +29 -0
- package/types/Inputs/XRGamepadController.d.ts +0 -7
- package/types/PeerConnectionController/PeerConnectionController.d.ts +10 -1
- package/types/PixelStreaming/PixelStreaming.d.ts +14 -2
- package/types/UI/OnScreenKeyboard.d.ts +2 -2
- package/types/Util/EventEmitter.d.ts +1 -1
- package/types/Util/IURLSearchParams.d.ts +9 -0
- package/types/Util/InputCoordTranslator.d.ts +29 -0
- package/types/VideoPlayer/StreamController.d.ts +0 -2
- package/types/WebRtcPlayer/WebRtcPlayerController.d.ts +19 -17
- package/types/pixelstreamingfrontend.d.ts +1 -1
- package/src/Inputs/FakeTouchController.ts +0 -199
- package/src/Inputs/HoveringMouseEvents.ts +0 -192
- package/src/Inputs/IMouseEvents.ts +0 -64
- package/src/Inputs/ITouchController.ts +0 -29
- package/src/Inputs/LockedMouseEvents.ts +0 -287
- package/src/Util/CoordinateConverter.ts +0 -290
- package/src/Util/EventListenerTracker.ts +0 -29
- package/types/Inputs/FakeTouchController.d.ts +0 -61
- package/types/Inputs/HoveringMouseEvents.d.ts +0 -56
- package/types/Inputs/IMouseEvents.d.ts +0 -53
- package/types/Inputs/ITouchController.d.ts +0 -24
- package/types/Inputs/LockedMouseEvents.d.ts +0 -80
- package/types/Util/CoordinateConverter.d.ts +0 -100
- package/types/Util/EventListenerTracker.d.ts +0 -14
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { UntranslatedCoordUnsigned } from '../Util/InputCoordTranslator';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Class for handling on screen keyboard usage
|
|
@@ -35,7 +35,7 @@ export class OnScreenKeyboard {
|
|
|
35
35
|
* @returns unquantizeAndDenormalizeUnsigned object
|
|
36
36
|
*/
|
|
37
37
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
38
|
-
unquantizeAndDenormalizeUnsigned(x: number, y: number):
|
|
38
|
+
unquantizeAndDenormalizeUnsigned(x: number, y: number): UntranslatedCoordUnsigned {
|
|
39
39
|
return null;
|
|
40
40
|
}
|
|
41
41
|
|
|
@@ -48,6 +48,14 @@ export class OnScreenKeyboard {
|
|
|
48
48
|
this.hiddenInput = document.createElement('input');
|
|
49
49
|
this.hiddenInput.id = 'hiddenInput';
|
|
50
50
|
this.hiddenInput.maxLength = 0;
|
|
51
|
+
|
|
52
|
+
// Set inline style so that users not using the UI library
|
|
53
|
+
// will still have this element display correctly
|
|
54
|
+
this.hiddenInput.style.position = 'absolute';
|
|
55
|
+
this.hiddenInput.style.left = '-10%';
|
|
56
|
+
this.hiddenInput.style.width = '0px';
|
|
57
|
+
this.hiddenInput.style.opacity = '0';
|
|
58
|
+
|
|
51
59
|
videoElementParent.appendChild(this.hiddenInput);
|
|
52
60
|
}
|
|
53
61
|
|
|
@@ -58,7 +66,7 @@ export class OnScreenKeyboard {
|
|
|
58
66
|
videoElementParent.appendChild(this.editTextButton);
|
|
59
67
|
|
|
60
68
|
// Hide the 'edit text' button.
|
|
61
|
-
this.editTextButton.
|
|
69
|
+
this.editTextButton.style.display = 'none';
|
|
62
70
|
|
|
63
71
|
this.editTextButton.addEventListener('touchend', (event: Event) => {
|
|
64
72
|
// Show the on-screen keyboard.
|
|
@@ -75,17 +83,14 @@ export class OnScreenKeyboard {
|
|
|
75
83
|
showOnScreenKeyboard(command: any) {
|
|
76
84
|
if (command.showOnScreenKeyboard) {
|
|
77
85
|
// Show the 'edit text' button.
|
|
78
|
-
this.editTextButton.
|
|
86
|
+
this.editTextButton.style.display = 'default';
|
|
79
87
|
// Place the 'edit text' button near the UE input widget.
|
|
80
|
-
const pos = this.unquantizeAndDenormalizeUnsigned(
|
|
81
|
-
command.x,
|
|
82
|
-
command.y
|
|
83
|
-
);
|
|
88
|
+
const pos = this.unquantizeAndDenormalizeUnsigned(command.x, command.y);
|
|
84
89
|
this.editTextButton.style.top = pos.y.toString() + 'px';
|
|
85
90
|
this.editTextButton.style.left = (pos.x - 40).toString() + 'px';
|
|
86
91
|
} else {
|
|
87
92
|
// Hide the 'edit text' button.
|
|
88
|
-
this.editTextButton.
|
|
93
|
+
this.editTextButton.style.display = 'none';
|
|
89
94
|
// Hide the on-screen keyboard.
|
|
90
95
|
this.hiddenInput.blur();
|
|
91
96
|
}
|
|
@@ -10,10 +10,7 @@ export class ResponseController {
|
|
|
10
10
|
* @param name - The name of the response
|
|
11
11
|
* @param listener - The method to be activated when the response is selected
|
|
12
12
|
*/
|
|
13
|
-
addResponseEventListener(
|
|
14
|
-
name: string,
|
|
15
|
-
listener: (response: string) => void
|
|
16
|
-
) {
|
|
13
|
+
addResponseEventListener(name: string, listener: (response: string) => void) {
|
|
17
14
|
this.responseEventListeners.set(name, listener);
|
|
18
15
|
}
|
|
19
16
|
|
|
@@ -30,18 +27,12 @@ export class ResponseController {
|
|
|
30
27
|
* @param message - Data received from the data channel with the command in question
|
|
31
28
|
*/
|
|
32
29
|
onResponse(message: ArrayBuffer) {
|
|
33
|
-
Logger.
|
|
34
|
-
Logger.GetStackTrace(),
|
|
35
|
-
'DataChannelReceiveMessageType.Response',
|
|
36
|
-
6
|
|
37
|
-
);
|
|
30
|
+
Logger.Info('DataChannelReceiveMessageType.Response');
|
|
38
31
|
const responses = new TextDecoder('utf-16').decode(message.slice(1));
|
|
39
32
|
|
|
40
|
-
Logger.
|
|
41
|
-
this.responseEventListeners.forEach(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
);
|
|
33
|
+
Logger.Info(responses);
|
|
34
|
+
this.responseEventListeners.forEach((listener: (response: string) => void) => {
|
|
35
|
+
listener(responses);
|
|
36
|
+
});
|
|
46
37
|
}
|
|
47
38
|
}
|
|
@@ -31,32 +31,31 @@ export class SendMessageController {
|
|
|
31
31
|
messageData = [];
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
const toStreamerMessages =
|
|
35
|
-
this.toStreamerMessagesMapProvider.toStreamerMessages;
|
|
34
|
+
const toStreamerMessages = this.toStreamerMessagesMapProvider.toStreamerMessages;
|
|
36
35
|
const messageFormat = toStreamerMessages.get(messageType);
|
|
37
36
|
if (messageFormat === undefined) {
|
|
38
37
|
Logger.Error(
|
|
39
|
-
Logger.GetStackTrace(),
|
|
40
38
|
`Attempted to send a message to the streamer with message type: ${messageType}, but the frontend hasn't been configured to send such a message. Check you've added the message type in your cpp`
|
|
41
39
|
);
|
|
42
40
|
return;
|
|
43
41
|
}
|
|
44
42
|
|
|
45
|
-
if(messageFormat.structure && messageData && messageFormat.structure.length !== messageData.length) {
|
|
43
|
+
if (messageFormat.structure && messageData && messageFormat.structure.length !== messageData.length) {
|
|
46
44
|
Logger.Error(
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
45
|
+
`Provided message data doesn't match expected layout. Expected [ ${messageFormat.structure
|
|
46
|
+
.map((element: string) => {
|
|
47
|
+
switch (element) {
|
|
48
|
+
case 'uint8':
|
|
49
|
+
case 'uint16':
|
|
50
|
+
case 'int16':
|
|
51
|
+
case 'float':
|
|
52
|
+
case 'double':
|
|
53
|
+
return 'number';
|
|
54
|
+
case 'string':
|
|
55
|
+
return 'string';
|
|
56
|
+
}
|
|
57
|
+
})
|
|
58
|
+
.toString()} ] but received [ ${messageData.map((element: number | string) => typeof element).toString()} ]`
|
|
60
59
|
);
|
|
61
60
|
return;
|
|
62
61
|
}
|
|
@@ -141,7 +140,6 @@ export class SendMessageController {
|
|
|
141
140
|
|
|
142
141
|
if (!this.dataChannelSender.canSend()) {
|
|
143
142
|
Logger.Info(
|
|
144
|
-
Logger.GetStackTrace(),
|
|
145
143
|
`Data channel cannot send yet, skipping sending message: ${messageType} - ${new Uint8Array(
|
|
146
144
|
data.buffer
|
|
147
145
|
)}`
|
|
@@ -8,14 +8,8 @@ export class ToStreamerMessage {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
export class StreamMessageController {
|
|
11
|
-
toStreamerHandlers: Map<
|
|
12
|
-
|
|
13
|
-
(messageData?: Array<number | string> | undefined) => void
|
|
14
|
-
>;
|
|
15
|
-
fromStreamerHandlers: Map<
|
|
16
|
-
string,
|
|
17
|
-
(messageType: string, messageData?: ArrayBuffer | undefined) => void
|
|
18
|
-
>;
|
|
11
|
+
toStreamerHandlers: Map<string, (messageData?: Array<number | string> | undefined) => void>;
|
|
12
|
+
fromStreamerHandlers: Map<string, (messageType: string, messageData?: ArrayBuffer | undefined) => void>;
|
|
19
13
|
// Type Format
|
|
20
14
|
toStreamerMessages: Map<string, ToStreamerMessage>;
|
|
21
15
|
// ID Type
|
|
@@ -216,10 +210,7 @@ export class StreamMessageController {
|
|
|
216
210
|
this.fromStreamerHandlers.set(messageType, messageHandler);
|
|
217
211
|
break;
|
|
218
212
|
default:
|
|
219
|
-
Logger.
|
|
220
|
-
Logger.GetStackTrace(),
|
|
221
|
-
`Unknown message direction ${messageDirection}`
|
|
222
|
-
);
|
|
213
|
+
Logger.Info(`Unknown message direction ${messageDirection}`);
|
|
223
214
|
}
|
|
224
215
|
}
|
|
225
216
|
}
|
|
@@ -16,9 +16,7 @@ export class ToStreamerMessagesController {
|
|
|
16
16
|
* Send Request to Take Quality Control to the UE Instance
|
|
17
17
|
*/
|
|
18
18
|
SendRequestQualityControl() {
|
|
19
|
-
this.sendMessageController.sendMessageToStreamer(
|
|
20
|
-
'RequestQualityControl'
|
|
21
|
-
);
|
|
19
|
+
this.sendMessageController.sendMessageToStreamer('RequestQualityControl');
|
|
22
20
|
}
|
|
23
21
|
|
|
24
22
|
/**
|
|
@@ -32,9 +30,7 @@ export class ToStreamerMessagesController {
|
|
|
32
30
|
* Send Average Bitrate Request to the UE Instance
|
|
33
31
|
*/
|
|
34
32
|
SendAverageBitrateRequest() {
|
|
35
|
-
this.sendMessageController.sendMessageToStreamer(
|
|
36
|
-
'AverageBitrateRequest'
|
|
37
|
-
);
|
|
33
|
+
this.sendMessageController.sendMessageToStreamer('AverageBitrateRequest');
|
|
38
34
|
}
|
|
39
35
|
|
|
40
36
|
/**
|
|
@@ -55,8 +51,6 @@ export class ToStreamerMessagesController {
|
|
|
55
51
|
* Send a Request Initial Settings to the UE Instance
|
|
56
52
|
*/
|
|
57
53
|
SendRequestInitialSettings() {
|
|
58
|
-
this.sendMessageController.sendMessageToStreamer(
|
|
59
|
-
'RequestInitialSettings'
|
|
60
|
-
);
|
|
54
|
+
this.sendMessageController.sendMessageToStreamer('RequestInitialSettings');
|
|
61
55
|
}
|
|
62
56
|
}
|
package/src/Util/EventEmitter.ts
CHANGED
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
FlagsIds,
|
|
3
|
-
NumericParametersIds,
|
|
4
|
-
OptionParametersIds,
|
|
5
|
-
TextParametersIds
|
|
6
|
-
} from '../Config/Config';
|
|
1
|
+
import { FlagsIds, NumericParametersIds, OptionParametersIds, TextParametersIds } from '../Config/Config';
|
|
7
2
|
import { LatencyTestResults } from '../DataChannel/LatencyTestResults';
|
|
8
3
|
import { AggregatedStats } from '../PeerConnectionController/AggregatedStats';
|
|
9
4
|
import { InitialSettings } from '../pixelstreamingfrontend';
|
|
@@ -15,7 +10,7 @@ import { SettingOption } from '../Config/SettingOption';
|
|
|
15
10
|
import {
|
|
16
11
|
DataChannelLatencyTestResponse,
|
|
17
12
|
DataChannelLatencyTestResult
|
|
18
|
-
} from
|
|
13
|
+
} from '../DataChannel/DataChannelLatencyTestResults';
|
|
19
14
|
|
|
20
15
|
/**
|
|
21
16
|
* An event that is emitted when AFK disconnect is about to happen.
|
|
@@ -42,7 +37,7 @@ export class AfkWarningUpdateEvent extends Event {
|
|
|
42
37
|
readonly type: 'afkWarningUpdate';
|
|
43
38
|
readonly data: {
|
|
44
39
|
/** How many seconds until the session is disconnected */
|
|
45
|
-
countDown: number
|
|
40
|
+
countDown: number;
|
|
46
41
|
};
|
|
47
42
|
constructor(data: AfkWarningUpdateEvent['data']) {
|
|
48
43
|
super('afkWarningUpdate');
|
|
@@ -77,7 +72,7 @@ export class VideoEncoderAvgQPEvent extends Event {
|
|
|
77
72
|
readonly type: 'videoEncoderAvgQP';
|
|
78
73
|
readonly data: {
|
|
79
74
|
/** Average video quality value */
|
|
80
|
-
avgQP: number
|
|
75
|
+
avgQP: number;
|
|
81
76
|
};
|
|
82
77
|
constructor(data: VideoEncoderAvgQPEvent['data']) {
|
|
83
78
|
super('videoEncoderAvgQP');
|
|
@@ -86,7 +81,7 @@ export class VideoEncoderAvgQPEvent extends Event {
|
|
|
86
81
|
}
|
|
87
82
|
|
|
88
83
|
/**
|
|
89
|
-
* An event that is emitted after a WebRtc connection has been negotiated.
|
|
84
|
+
* An event that is emitted after a WebRtc connection has been negotiated.
|
|
90
85
|
*/
|
|
91
86
|
export class WebRtcSdpEvent extends Event {
|
|
92
87
|
readonly type: 'webRtcSdp';
|
|
@@ -161,7 +156,7 @@ export class DataChannelOpenEvent extends Event {
|
|
|
161
156
|
/** Data channel label. One of 'datachannel', 'send-datachannel', 'recv-datachannel' */
|
|
162
157
|
label: string;
|
|
163
158
|
/** RTCDataChannel onOpen event */
|
|
164
|
-
event: Event
|
|
159
|
+
event: Event;
|
|
165
160
|
};
|
|
166
161
|
constructor(data: DataChannelOpenEvent['data']) {
|
|
167
162
|
super('dataChannelOpen');
|
|
@@ -178,7 +173,7 @@ export class DataChannelCloseEvent extends Event {
|
|
|
178
173
|
/** Data channel label. One of 'datachannel', 'send-datachannel', 'recv-datachannel' */
|
|
179
174
|
label: string;
|
|
180
175
|
/** RTCDataChannel onClose event */
|
|
181
|
-
event: Event
|
|
176
|
+
event: Event;
|
|
182
177
|
};
|
|
183
178
|
constructor(data: DataChannelCloseEvent['data']) {
|
|
184
179
|
super('dataChannelClose');
|
|
@@ -195,7 +190,7 @@ export class DataChannelErrorEvent extends Event {
|
|
|
195
190
|
/** Data channel label. One of 'datachannel', 'send-datachannel', 'recv-datachannel' */
|
|
196
191
|
label: string;
|
|
197
192
|
/** RTCDataChannel onError event */
|
|
198
|
-
event: Event
|
|
193
|
+
event: Event;
|
|
199
194
|
};
|
|
200
195
|
constructor(data: DataChannelErrorEvent['data']) {
|
|
201
196
|
super('dataChannelError');
|
|
@@ -260,7 +255,7 @@ export class PlayStreamErrorEvent extends Event {
|
|
|
260
255
|
readonly type: 'playStreamError';
|
|
261
256
|
readonly data: {
|
|
262
257
|
/** Error message */
|
|
263
|
-
message: string
|
|
258
|
+
message: string;
|
|
264
259
|
};
|
|
265
260
|
constructor(data: PlayStreamErrorEvent['data']) {
|
|
266
261
|
super('playStreamError');
|
|
@@ -286,7 +281,7 @@ export class PlayStreamRejectedEvent extends Event {
|
|
|
286
281
|
readonly type: 'playStreamRejected';
|
|
287
282
|
readonly data: {
|
|
288
283
|
/** Rejection reason */
|
|
289
|
-
reason: unknown
|
|
284
|
+
reason: unknown;
|
|
290
285
|
};
|
|
291
286
|
constructor(data: PlayStreamRejectedEvent['data']) {
|
|
292
287
|
super('playStreamRejected');
|
|
@@ -330,7 +325,7 @@ export class StatsReceivedEvent extends Event {
|
|
|
330
325
|
readonly type: 'statsReceived';
|
|
331
326
|
readonly data: {
|
|
332
327
|
/** Statistics object */
|
|
333
|
-
aggregatedStats: AggregatedStats
|
|
328
|
+
aggregatedStats: AggregatedStats;
|
|
334
329
|
};
|
|
335
330
|
constructor(data: StatsReceivedEvent['data']) {
|
|
336
331
|
super('statsReceived');
|
|
@@ -379,7 +374,7 @@ export class LatencyTestResultEvent extends Event {
|
|
|
379
374
|
readonly type: 'latencyTestResult';
|
|
380
375
|
readonly data: {
|
|
381
376
|
/** Latency test result object */
|
|
382
|
-
latencyTimings: LatencyTestResults
|
|
377
|
+
latencyTimings: LatencyTestResults;
|
|
383
378
|
};
|
|
384
379
|
constructor(data: LatencyTestResultEvent['data']) {
|
|
385
380
|
super('latencyTestResult');
|
|
@@ -395,7 +390,7 @@ export class DataChannelLatencyTestResponseEvent extends Event {
|
|
|
395
390
|
readonly type: 'dataChannelLatencyTestResponse';
|
|
396
391
|
readonly data: {
|
|
397
392
|
/** Latency test result object */
|
|
398
|
-
response: DataChannelLatencyTestResponse
|
|
393
|
+
response: DataChannelLatencyTestResponse;
|
|
399
394
|
};
|
|
400
395
|
constructor(data: DataChannelLatencyTestResponseEvent['data']) {
|
|
401
396
|
super('dataChannelLatencyTestResponse');
|
|
@@ -410,7 +405,7 @@ export class DataChannelLatencyTestResultEvent extends Event {
|
|
|
410
405
|
readonly type: 'dataChannelLatencyTestResult';
|
|
411
406
|
readonly data: {
|
|
412
407
|
/** Latency test result object */
|
|
413
|
-
result: DataChannelLatencyTestResult
|
|
408
|
+
result: DataChannelLatencyTestResult;
|
|
414
409
|
};
|
|
415
410
|
constructor(data: DataChannelLatencyTestResultEvent['data']) {
|
|
416
411
|
super('dataChannelLatencyTestResult');
|
|
@@ -425,7 +420,7 @@ export class InitialSettingsEvent extends Event {
|
|
|
425
420
|
readonly type: 'initialSettings';
|
|
426
421
|
readonly data: {
|
|
427
422
|
/** Initial settings from UE */
|
|
428
|
-
settings: InitialSettings
|
|
423
|
+
settings: InitialSettings;
|
|
429
424
|
};
|
|
430
425
|
constructor(data: InitialSettingsEvent['data']) {
|
|
431
426
|
super('initialSettings');
|
|
@@ -515,7 +510,7 @@ export type XrFrameData = {
|
|
|
515
510
|
*/
|
|
516
511
|
export class XrFrameEvent extends Event {
|
|
517
512
|
readonly type: 'xrFrame';
|
|
518
|
-
readonly data: XrFrameData
|
|
513
|
+
readonly data: XrFrameData;
|
|
519
514
|
constructor(data: XrFrameEvent['data']) {
|
|
520
515
|
super('xrFrame');
|
|
521
516
|
this.data = data;
|
|
@@ -529,7 +524,7 @@ export class PlayerCountEvent extends Event {
|
|
|
529
524
|
readonly type: 'playerCount';
|
|
530
525
|
readonly data: {
|
|
531
526
|
/** count object */
|
|
532
|
-
count: number
|
|
527
|
+
count: number;
|
|
533
528
|
};
|
|
534
529
|
constructor(data: PlayerCountEvent['data']) {
|
|
535
530
|
super('playerCount');
|
package/src/Util/FileUtil.ts
CHANGED
|
@@ -20,17 +20,11 @@ export class FileUtil {
|
|
|
20
20
|
file.size = 0;
|
|
21
21
|
file.data = [];
|
|
22
22
|
file.timestampStart = new Date().getTime();
|
|
23
|
-
Logger.
|
|
24
|
-
Logger.GetStackTrace(),
|
|
25
|
-
'Received first chunk of file',
|
|
26
|
-
6
|
|
27
|
-
);
|
|
23
|
+
Logger.Info('Received first chunk of file');
|
|
28
24
|
}
|
|
29
25
|
|
|
30
|
-
const extensionAsString = new TextDecoder('utf-16').decode(
|
|
31
|
-
|
|
32
|
-
);
|
|
33
|
-
Logger.Log(Logger.GetStackTrace(), extensionAsString, 6);
|
|
26
|
+
const extensionAsString = new TextDecoder('utf-16').decode(view.slice(1));
|
|
27
|
+
Logger.Info(extensionAsString);
|
|
34
28
|
file.extension = extensionAsString;
|
|
35
29
|
}
|
|
36
30
|
|
|
@@ -48,15 +42,11 @@ export class FileUtil {
|
|
|
48
42
|
file.size = 0;
|
|
49
43
|
file.data = [];
|
|
50
44
|
file.timestampStart = new Date().getTime();
|
|
51
|
-
Logger.
|
|
52
|
-
Logger.GetStackTrace(),
|
|
53
|
-
'Received first chunk of file',
|
|
54
|
-
6
|
|
55
|
-
);
|
|
45
|
+
Logger.Info('Received first chunk of file');
|
|
56
46
|
}
|
|
57
47
|
|
|
58
48
|
const mimeAsString = new TextDecoder('utf-16').decode(view.slice(1));
|
|
59
|
-
Logger.
|
|
49
|
+
Logger.Info(mimeAsString);
|
|
60
50
|
file.mimetype = mimeAsString;
|
|
61
51
|
}
|
|
62
52
|
|
|
@@ -81,26 +71,16 @@ export class FileUtil {
|
|
|
81
71
|
file.data.push(fileBytes);
|
|
82
72
|
|
|
83
73
|
// Uncomment for debug
|
|
84
|
-
Logger.
|
|
85
|
-
Logger.GetStackTrace(),
|
|
86
|
-
`Received file chunk: ${file.data.length}/${file.size}`,
|
|
87
|
-
6
|
|
88
|
-
);
|
|
74
|
+
Logger.Info(`Received file chunk: ${file.data.length}/${file.size}`);
|
|
89
75
|
|
|
90
76
|
if (file.data.length === file.size) {
|
|
91
77
|
file.receiving = false;
|
|
92
78
|
file.valid = true;
|
|
93
|
-
Logger.
|
|
79
|
+
Logger.Info('Received complete file');
|
|
94
80
|
const transferDuration = new Date().getTime() - file.timestampStart;
|
|
95
|
-
const transferBitrate = Math.round(
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
Logger.Log(
|
|
99
|
-
Logger.GetStackTrace(),
|
|
100
|
-
`Average transfer bitrate: ${transferBitrate}kb/s over ${
|
|
101
|
-
transferDuration / 1000
|
|
102
|
-
} seconds`,
|
|
103
|
-
6
|
|
81
|
+
const transferBitrate = Math.round((file.size * 16 * 1024) / transferDuration);
|
|
82
|
+
Logger.Info(
|
|
83
|
+
`Average transfer bitrate: ${transferBitrate}kb/s over ${transferDuration / 1000} seconds`
|
|
104
84
|
);
|
|
105
85
|
|
|
106
86
|
// File reconstruction
|
|
@@ -118,10 +98,7 @@ export class FileUtil {
|
|
|
118
98
|
a.remove();
|
|
119
99
|
} else if (file.data.length > file.size) {
|
|
120
100
|
file.receiving = false;
|
|
121
|
-
Logger.Error(
|
|
122
|
-
Logger.GetStackTrace(),
|
|
123
|
-
`Received bigger file than advertised: ${file.data.length}/${file.size}`
|
|
124
|
-
);
|
|
101
|
+
Logger.Error(`Received bigger file than advertised: ${file.data.length}/${file.size}`);
|
|
125
102
|
}
|
|
126
103
|
}
|
|
127
104
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A case insensitive, partial implementation of URLSearchParams
|
|
3
|
+
*/
|
|
4
|
+
export class IURLSearchParams {
|
|
5
|
+
_urlParams: Record<string, string>;
|
|
6
|
+
|
|
7
|
+
constructor(search: string) {
|
|
8
|
+
this._urlParams = {};
|
|
9
|
+
const urlParams = new URLSearchParams(search);
|
|
10
|
+
for (const [name, value] of urlParams) {
|
|
11
|
+
this._urlParams[name.toLowerCase()] = value;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
public has(name: string): boolean {
|
|
16
|
+
return name.toLowerCase() in this._urlParams;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
public get(name: string): string | null {
|
|
20
|
+
if (this.has(name)) {
|
|
21
|
+
return this._urlParams[name.toLowerCase()];
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
2
|
+
|
|
3
|
+
export interface RectSize {
|
|
4
|
+
width: number;
|
|
5
|
+
height: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface TranslatedCoordUnsigned {
|
|
9
|
+
inRange: boolean;
|
|
10
|
+
x: number;
|
|
11
|
+
y: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface TranslatedCoordSigned {
|
|
15
|
+
x: number;
|
|
16
|
+
y: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface UntranslatedCoordUnsigned {
|
|
20
|
+
x: number;
|
|
21
|
+
y: number;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Converts coordinates from element relative coordinates to values normalized within the value range of a short (and back again)
|
|
26
|
+
*/
|
|
27
|
+
export class InputCoordTranslator {
|
|
28
|
+
playerSize: RectSize;
|
|
29
|
+
ratio: number;
|
|
30
|
+
playerIsLarger: boolean;
|
|
31
|
+
|
|
32
|
+
// we dont use a constructor here because the object is created and passed around to various locations
|
|
33
|
+
// possibly before this method is called.
|
|
34
|
+
reconfigure(playerSize: RectSize, videoSize: RectSize) {
|
|
35
|
+
const playerAspectRatio = playerSize.height / playerSize.width;
|
|
36
|
+
const videoAspectRatio = videoSize.height / videoSize.width;
|
|
37
|
+
this.playerIsLarger = playerAspectRatio > videoAspectRatio;
|
|
38
|
+
this.playerSize = playerSize;
|
|
39
|
+
this.ratio = this.playerIsLarger
|
|
40
|
+
? playerAspectRatio / videoAspectRatio
|
|
41
|
+
: videoAspectRatio / playerAspectRatio;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
translateUnsigned(x: number, y: number): TranslatedCoordUnsigned {
|
|
45
|
+
const normalizedX = this.playerIsLarger
|
|
46
|
+
? x / this.playerSize.width
|
|
47
|
+
: this.ratio * (x / this.playerSize.width - 0.5) + 0.5;
|
|
48
|
+
const normalizedY = this.playerIsLarger
|
|
49
|
+
? this.ratio * (y / this.playerSize.height - 0.5) + 0.5
|
|
50
|
+
: y / this.playerSize.height;
|
|
51
|
+
if (normalizedX < 0.0 || normalizedX > 1.0 || normalizedY < 0.0 || normalizedY > 1.0) {
|
|
52
|
+
return { inRange: false, x: 65535, y: 65535 };
|
|
53
|
+
} else {
|
|
54
|
+
return { inRange: true, x: normalizedX * 65536, y: normalizedY * 65536 };
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
translateSigned(x: number, y: number): TranslatedCoordSigned {
|
|
59
|
+
const normalizedX = this.playerIsLarger
|
|
60
|
+
? x / (0.5 * this.playerSize.width)
|
|
61
|
+
: (this.ratio * x) / (0.5 * this.playerSize.width);
|
|
62
|
+
const normalizedY = this.playerIsLarger
|
|
63
|
+
? (this.ratio * y) / (0.5 * this.playerSize.height)
|
|
64
|
+
: y / (0.5 * this.playerSize.height);
|
|
65
|
+
return { x: normalizedX * 32767, y: normalizedY * 32767 };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
untranslateUnsigned(x: number, y: number): UntranslatedCoordUnsigned {
|
|
69
|
+
const normalizedX = this.playerIsLarger ? x / 65536 : (x / 65536 - 0.5) / this.ratio + 0.5;
|
|
70
|
+
const normalizedY = this.playerIsLarger ? (y / 65536 - 0.5) / this.ratio + 0.5 : y / 65536;
|
|
71
|
+
return { x: normalizedX * this.playerSize.width, y: normalizedY * this.playerSize.height };
|
|
72
|
+
}
|
|
73
|
+
}
|
package/src/Util/RTCUtils.ts
CHANGED
|
@@ -1,41 +1,49 @@
|
|
|
1
1
|
export class RTCUtils {
|
|
2
|
-
static isVideoTransceiver(transceiver
|
|
2
|
+
static isVideoTransceiver(transceiver: RTCRtpTransceiver | undefined): boolean {
|
|
3
3
|
return this.canTransceiverReceiveVideo(transceiver) || this.canTransceiverSendVideo(transceiver);
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
-
static canTransceiverReceiveVideo(transceiver
|
|
7
|
-
return
|
|
6
|
+
static canTransceiverReceiveVideo(transceiver: RTCRtpTransceiver | undefined): boolean {
|
|
7
|
+
return (
|
|
8
|
+
!!transceiver &&
|
|
8
9
|
(transceiver.direction === 'sendrecv' || transceiver.direction === 'recvonly') &&
|
|
9
10
|
transceiver.receiver &&
|
|
10
11
|
transceiver.receiver.track &&
|
|
11
|
-
transceiver.receiver.track.kind === 'video'
|
|
12
|
+
transceiver.receiver.track.kind === 'video'
|
|
13
|
+
);
|
|
12
14
|
}
|
|
13
15
|
|
|
14
|
-
static canTransceiverSendVideo(transceiver
|
|
15
|
-
return
|
|
16
|
+
static canTransceiverSendVideo(transceiver: RTCRtpTransceiver | undefined): boolean {
|
|
17
|
+
return (
|
|
18
|
+
!!transceiver &&
|
|
16
19
|
(transceiver.direction === 'sendrecv' || transceiver.direction === 'sendonly') &&
|
|
17
20
|
transceiver.sender &&
|
|
18
21
|
transceiver.sender.track &&
|
|
19
|
-
transceiver.sender.track.kind === 'video'
|
|
22
|
+
transceiver.sender.track.kind === 'video'
|
|
23
|
+
);
|
|
20
24
|
}
|
|
21
25
|
|
|
22
|
-
static isAudioTransceiver(transceiver
|
|
26
|
+
static isAudioTransceiver(transceiver: RTCRtpTransceiver | undefined): boolean {
|
|
23
27
|
return this.canTransceiverReceiveAudio(transceiver) || this.canTransceiverSendAudio(transceiver);
|
|
24
28
|
}
|
|
25
29
|
|
|
26
|
-
static canTransceiverReceiveAudio(transceiver
|
|
27
|
-
return
|
|
30
|
+
static canTransceiverReceiveAudio(transceiver: RTCRtpTransceiver | undefined): boolean {
|
|
31
|
+
return (
|
|
32
|
+
!!transceiver &&
|
|
28
33
|
(transceiver.direction === 'sendrecv' || transceiver.direction === 'recvonly') &&
|
|
29
34
|
transceiver.receiver &&
|
|
30
35
|
transceiver.receiver.track &&
|
|
31
|
-
transceiver.receiver.track.kind === 'audio'
|
|
36
|
+
transceiver.receiver.track.kind === 'audio'
|
|
37
|
+
);
|
|
32
38
|
}
|
|
33
39
|
|
|
34
|
-
static canTransceiverSendAudio(transceiver
|
|
35
|
-
return
|
|
40
|
+
static canTransceiverSendAudio(transceiver: RTCRtpTransceiver | undefined): boolean {
|
|
41
|
+
return (
|
|
42
|
+
!!transceiver &&
|
|
36
43
|
(transceiver.direction === 'sendrecv' || transceiver.direction === 'sendonly') &&
|
|
37
44
|
transceiver.sender &&
|
|
38
45
|
transceiver.sender.track &&
|
|
39
|
-
transceiver.sender.track.kind === 'audio'
|
|
46
|
+
transceiver.sender.track.kind === 'audio'
|
|
47
|
+
);
|
|
40
48
|
}
|
|
41
|
-
}
|
|
49
|
+
}
|