@epicgames-ps/lib-pixelstreamingfrontend-ue5.5 0.4.8 → 1.0.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.
Files changed (116) hide show
  1. package/dist/cjs/Config/Config.js +4 -0
  2. package/dist/cjs/Config/Config.js.map +1 -1
  3. package/dist/cjs/Config/SettingBase.js +1 -3
  4. package/dist/cjs/Config/SettingBase.js.map +1 -1
  5. package/dist/cjs/Config/SettingFlag.js +1 -3
  6. package/dist/cjs/Config/SettingFlag.js.map +1 -1
  7. package/dist/cjs/Config/SettingNumber.js +1 -3
  8. package/dist/cjs/Config/SettingNumber.js.map +1 -1
  9. package/dist/cjs/Config/SettingOption.js +2 -6
  10. package/dist/cjs/Config/SettingOption.js.map +1 -1
  11. package/dist/cjs/Config/SettingText.js +1 -3
  12. package/dist/cjs/Config/SettingText.js.map +1 -1
  13. package/dist/cjs/Inputs/GamepadController.js +0 -2
  14. package/dist/cjs/Inputs/GamepadController.js.map +1 -1
  15. package/dist/cjs/PeerConnectionController/AggregatedStats.js +103 -45
  16. package/dist/cjs/PeerConnectionController/AggregatedStats.js.map +1 -1
  17. package/dist/cjs/PeerConnectionController/InboundRTPStats.js.map +1 -1
  18. package/dist/cjs/PeerConnectionController/LatencyCalculator.js +290 -0
  19. package/dist/cjs/PeerConnectionController/LatencyCalculator.js.map +1 -0
  20. package/dist/cjs/PeerConnectionController/OutBoundRTPStats.js +11 -7
  21. package/dist/cjs/PeerConnectionController/OutBoundRTPStats.js.map +1 -1
  22. package/dist/cjs/PeerConnectionController/PeerConnectionController.js +53 -19
  23. package/dist/cjs/PeerConnectionController/PeerConnectionController.js.map +1 -1
  24. package/dist/cjs/PixelStreaming/PixelStreaming.js +21 -3
  25. package/dist/cjs/PixelStreaming/PixelStreaming.js.map +1 -1
  26. package/dist/cjs/Util/EventEmitter.js +31 -1
  27. package/dist/cjs/Util/EventEmitter.js.map +1 -1
  28. package/dist/cjs/WebRtcPlayer/WebRtcPlayerController.js +20 -4
  29. package/dist/cjs/WebRtcPlayer/WebRtcPlayerController.js.map +1 -1
  30. package/dist/cjs/__test__/mockMediaStream.js +100 -0
  31. package/dist/cjs/__test__/mockMediaStream.js.map +1 -0
  32. package/dist/cjs/__test__/mockRTCPeerConnection.js +252 -0
  33. package/dist/cjs/__test__/mockRTCPeerConnection.js.map +1 -0
  34. package/dist/cjs/__test__/mockRTCRtpReceiver.js +26 -0
  35. package/dist/cjs/__test__/mockRTCRtpReceiver.js.map +1 -0
  36. package/dist/cjs/__test__/mockWebSocket.js +109 -0
  37. package/dist/cjs/__test__/mockWebSocket.js.map +1 -0
  38. package/dist/cjs/pixelstreamingfrontend.js +4 -2
  39. package/dist/cjs/pixelstreamingfrontend.js.map +1 -1
  40. package/dist/esm/Config/Config.js +4 -0
  41. package/dist/esm/Config/Config.js.map +1 -1
  42. package/dist/esm/Config/SettingBase.js +1 -3
  43. package/dist/esm/Config/SettingBase.js.map +1 -1
  44. package/dist/esm/Config/SettingFlag.js +1 -3
  45. package/dist/esm/Config/SettingFlag.js.map +1 -1
  46. package/dist/esm/Config/SettingNumber.js +1 -3
  47. package/dist/esm/Config/SettingNumber.js.map +1 -1
  48. package/dist/esm/Config/SettingOption.js +2 -6
  49. package/dist/esm/Config/SettingOption.js.map +1 -1
  50. package/dist/esm/Config/SettingText.js +1 -3
  51. package/dist/esm/Config/SettingText.js.map +1 -1
  52. package/dist/esm/Inputs/GamepadController.js +0 -2
  53. package/dist/esm/Inputs/GamepadController.js.map +1 -1
  54. package/dist/esm/PeerConnectionController/AggregatedStats.js +104 -46
  55. package/dist/esm/PeerConnectionController/AggregatedStats.js.map +1 -1
  56. package/dist/esm/PeerConnectionController/InboundRTPStats.js.map +1 -1
  57. package/dist/esm/PeerConnectionController/LatencyCalculator.js +284 -0
  58. package/dist/esm/PeerConnectionController/LatencyCalculator.js.map +1 -0
  59. package/dist/esm/PeerConnectionController/OutBoundRTPStats.js +8 -4
  60. package/dist/esm/PeerConnectionController/OutBoundRTPStats.js.map +1 -1
  61. package/dist/esm/PeerConnectionController/PeerConnectionController.js +52 -18
  62. package/dist/esm/PeerConnectionController/PeerConnectionController.js.map +1 -1
  63. package/dist/esm/PixelStreaming/PixelStreaming.js +22 -4
  64. package/dist/esm/PixelStreaming/PixelStreaming.js.map +1 -1
  65. package/dist/esm/Util/EventEmitter.js +27 -0
  66. package/dist/esm/Util/EventEmitter.js.map +1 -1
  67. package/dist/esm/WebRtcPlayer/WebRtcPlayerController.js +20 -4
  68. package/dist/esm/WebRtcPlayer/WebRtcPlayerController.js.map +1 -1
  69. package/dist/esm/__test__/mockMediaStream.js +92 -0
  70. package/dist/esm/__test__/mockMediaStream.js.map +1 -0
  71. package/dist/esm/__test__/mockRTCPeerConnection.js +242 -0
  72. package/dist/esm/__test__/mockRTCPeerConnection.js.map +1 -0
  73. package/dist/esm/__test__/mockRTCRtpReceiver.js +21 -0
  74. package/dist/esm/__test__/mockRTCRtpReceiver.js.map +1 -0
  75. package/dist/esm/__test__/mockWebSocket.js +103 -0
  76. package/dist/esm/__test__/mockWebSocket.js.map +1 -0
  77. package/dist/esm/pixelstreamingfrontend.js +2 -1
  78. package/dist/esm/pixelstreamingfrontend.js.map +1 -1
  79. package/dist/types/Config/Config.d.ts +1 -0
  80. package/dist/types/PeerConnectionController/AggregatedStats.d.ts +18 -7
  81. package/dist/types/PeerConnectionController/InboundRTPStats.d.ts +88 -85
  82. package/dist/types/PeerConnectionController/LatencyCalculator.d.ts +87 -0
  83. package/dist/types/PeerConnectionController/OutBoundRTPStats.d.ts +46 -12
  84. package/dist/types/PeerConnectionController/PeerConnectionController.d.ts +17 -3
  85. package/dist/types/PixelStreaming/PixelStreaming.d.ts +16 -3
  86. package/dist/types/Util/EventEmitter.d.ts +34 -1
  87. package/dist/types/VideoPlayer/VideoPlayer.d.ts +1 -1
  88. package/dist/types/__test__/mockMediaStream.d.ts +49 -0
  89. package/dist/types/__test__/mockRTCPeerConnection.d.ts +134 -0
  90. package/dist/types/__test__/mockRTCRtpReceiver.d.ts +3 -0
  91. package/dist/types/__test__/mockWebSocket.d.ts +33 -0
  92. package/dist/types/pixelstreamingfrontend.d.ts +2 -1
  93. package/eslint.config.mjs +52 -0
  94. package/package.json +13 -14
  95. package/src/Config/Config.ts +14 -0
  96. package/src/Config/SettingBase.ts +1 -1
  97. package/src/Config/SettingFlag.ts +1 -1
  98. package/src/Config/SettingNumber.ts +1 -1
  99. package/src/Config/SettingOption.ts +2 -2
  100. package/src/Config/SettingText.ts +1 -1
  101. package/src/Inputs/GamepadController.ts +2 -2
  102. package/src/PeerConnectionController/AggregatedStats.ts +111 -52
  103. package/src/PeerConnectionController/InboundRTPStats.ts +88 -85
  104. package/src/PeerConnectionController/LatencyCalculator.ts +392 -0
  105. package/src/PeerConnectionController/OutBoundRTPStats.ts +46 -12
  106. package/src/PeerConnectionController/PeerConnectionController.ts +72 -19
  107. package/src/PixelStreaming/PixelStreaming.ts +29 -4
  108. package/src/Util/EventEmitter.ts +48 -0
  109. package/src/VideoPlayer/VideoPlayer.ts +1 -1
  110. package/src/WebRtcPlayer/WebRtcPlayerController.ts +23 -5
  111. package/src/__test__/mockRTCPeerConnection.ts +1 -1
  112. package/src/pixelstreamingfrontend.ts +2 -1
  113. package/tsconfig.base.json +2 -2
  114. package/.eslintignore +0 -12
  115. package/.eslintrc.js +0 -20
  116. package/.prettierrc.json +0 -7
@@ -0,0 +1,134 @@
1
+ export interface MockRTCPeerConnectionSpyFunctions {
2
+ constructorSpy: null | ((config: RTCConfiguration) => void);
3
+ closeSpy: null | (() => void);
4
+ setRemoteDescriptionSpy: null | ((description: RTCSessionDescriptionInit) => void);
5
+ setLocalDescriptionSpy: null | ((description: RTCLocalSessionDescriptionInit) => void);
6
+ createAnswerSpy: null | (() => void);
7
+ addTransceiverSpy: null | ((trackOrKind: string | MediaStreamTrack, init?: RTCRtpTransceiverInit | undefined) => void);
8
+ addIceCandidateSpy: null | ((candidate: RTCIceCandidateInit) => void);
9
+ sendDataSpy: null | ((data: ArrayBuffer) => void);
10
+ }
11
+ export interface MockRTCPeerConnectionTriggerFunctions {
12
+ triggerIceConnectionStateChange: null | ((state: RTCIceConnectionState) => void);
13
+ triggerOnTrack: null | ((data: RTCTrackEventInit) => void);
14
+ triggerOnIceCandidate: null | ((data: RTCPeerConnectionIceEventInit) => void);
15
+ triggerOnDataChannel: null | ((data: RTCDataChannelEventInit) => void);
16
+ }
17
+ export declare class MockRTCPeerConnectionImpl implements RTCPeerConnection {
18
+ canTrickleIceCandidates: boolean | null;
19
+ connectionState: RTCPeerConnectionState;
20
+ currentLocalDescription: RTCSessionDescription | null;
21
+ currentRemoteDescription: RTCSessionDescription | null;
22
+ iceConnectionState: RTCIceConnectionState;
23
+ iceGatheringState: RTCIceGatheringState;
24
+ localDescription: RTCSessionDescription | null;
25
+ pendingLocalDescription: RTCSessionDescription | null;
26
+ pendingRemoteDescription: RTCSessionDescription | null;
27
+ remoteDescription: RTCSessionDescription | null;
28
+ sctp: RTCSctpTransport | null;
29
+ signalingState: RTCSignalingState;
30
+ _dataChannels: RTCDataChannel[];
31
+ constructor(config: RTCConfiguration);
32
+ onconnectionstatechange: ((this: RTCPeerConnection, ev: Event) => any) | null;
33
+ ondatachannel: ((this: RTCPeerConnection, ev: RTCDataChannelEvent) => any) | null;
34
+ onicecandidate: ((this: RTCPeerConnection, ev: RTCPeerConnectionIceEvent) => any) | null;
35
+ onicecandidateerror: ((this: RTCPeerConnection, ev: Event) => any) | null;
36
+ oniceconnectionstatechange: ((this: RTCPeerConnection, ev: Event) => any) | null;
37
+ onicegatheringstatechange: ((this: RTCPeerConnection, ev: Event) => any) | null;
38
+ onnegotiationneeded: ((this: RTCPeerConnection, ev: Event) => any) | null;
39
+ onsignalingstatechange: ((this: RTCPeerConnection, ev: Event) => any) | null;
40
+ ontrack: ((this: RTCPeerConnection, ev: RTCTrackEvent) => any) | null;
41
+ addIceCandidate(candidate?: RTCIceCandidateInit | undefined): Promise<void>;
42
+ addIceCandidate(candidate: RTCIceCandidateInit, successCallback: VoidFunction, failureCallback: RTCPeerConnectionErrorCallback): Promise<void>;
43
+ addTrack(track: MediaStreamTrack, ...streams: MediaStream[]): RTCRtpSender;
44
+ addTransceiver(trackOrKind: string | MediaStreamTrack, init?: RTCRtpTransceiverInit | undefined): RTCRtpTransceiver;
45
+ createAnswer(options?: RTCAnswerOptions | undefined): Promise<RTCSessionDescriptionInit>;
46
+ createAnswer(successCallback: RTCSessionDescriptionCallback, failureCallback: RTCPeerConnectionErrorCallback): Promise<void>;
47
+ createDataChannel(label: string, dataChannelDict?: RTCDataChannelInit | undefined): RTCDataChannel;
48
+ createOffer(options?: RTCOfferOptions | undefined): Promise<RTCSessionDescriptionInit>;
49
+ createOffer(successCallback: RTCSessionDescriptionCallback, failureCallback: RTCPeerConnectionErrorCallback, options?: RTCOfferOptions | undefined): Promise<void>;
50
+ getConfiguration(): RTCConfiguration;
51
+ getReceivers(): RTCRtpReceiver[];
52
+ getSenders(): RTCRtpSender[];
53
+ getStats(selector?: MediaStreamTrack | null | undefined): Promise<RTCStatsReport>;
54
+ getTransceivers(): RTCRtpTransceiver[];
55
+ removeTrack(sender: RTCRtpSender): void;
56
+ restartIce(): void;
57
+ setConfiguration(configuration?: RTCConfiguration | undefined): void;
58
+ setLocalDescription(description?: RTCLocalSessionDescriptionInit | undefined): Promise<void>;
59
+ setLocalDescription(description: RTCLocalSessionDescriptionInit, successCallback: VoidFunction, failureCallback: RTCPeerConnectionErrorCallback): Promise<void>;
60
+ setRemoteDescription(description: RTCSessionDescriptionInit): Promise<void>;
61
+ setRemoteDescription(description: RTCSessionDescriptionInit, successCallback: VoidFunction, failureCallback: RTCPeerConnectionErrorCallback): Promise<void>;
62
+ addEventListener<K extends keyof RTCPeerConnectionEventMap>(type: K, listener: (this: RTCPeerConnection, ev: RTCPeerConnectionEventMap[K]) => any, options?: boolean | AddEventListenerOptions | undefined): void;
63
+ addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions | undefined): void;
64
+ removeEventListener<K extends keyof RTCPeerConnectionEventMap>(type: K, listener: (this: RTCPeerConnection, ev: RTCPeerConnectionEventMap[K]) => any, options?: boolean | EventListenerOptions | undefined): void;
65
+ removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions | undefined): void;
66
+ dispatchEvent(event: Event): boolean;
67
+ static generateCertificate(keygenAlgorithm: AlgorithmIdentifier): Promise<RTCCertificate>;
68
+ close(): void;
69
+ triggerIceConnectionStateChange(state: RTCIceConnectionState): void;
70
+ triggerOnTrack(data: RTCTrackEventInit): void;
71
+ triggerOnIceCandidate(data: RTCPeerConnectionIceEventInit): void;
72
+ triggerOnDataChannel(data: RTCDataChannelEventInit): void;
73
+ }
74
+ export declare class MockRTCIceCandidateImpl implements RTCIceCandidate {
75
+ address: string | null;
76
+ candidate: string;
77
+ component: RTCIceComponent | null;
78
+ foundation: string | null;
79
+ port: number | null;
80
+ priority: number | null;
81
+ protocol: RTCIceProtocol | null;
82
+ relatedAddress: string | null;
83
+ relatedPort: number | null;
84
+ sdpMLineIndex: number | null;
85
+ sdpMid: string | null;
86
+ tcpType: RTCIceTcpCandidateType | null;
87
+ type: RTCIceCandidateType | null;
88
+ usernameFragment: string | null;
89
+ constructor(options?: RTCIceCandidateInit);
90
+ toJSON(): RTCIceCandidateInit;
91
+ }
92
+ export declare class MockRTCDataChannelImpl implements RTCDataChannel {
93
+ binaryType: BinaryType;
94
+ bufferedAmount: number;
95
+ bufferedAmountLowThreshold: number;
96
+ id: number | null;
97
+ label: string;
98
+ maxPacketLifeTime: number | null;
99
+ maxRetransmits: number | null;
100
+ negotiated: boolean;
101
+ ordered: boolean;
102
+ protocol: string;
103
+ readyState: RTCDataChannelState;
104
+ constructor();
105
+ onbufferedamountlow: ((this: RTCDataChannel, ev: Event) => any) | null;
106
+ onclose: ((this: RTCDataChannel, ev: Event) => any) | null;
107
+ onclosing: ((this: RTCDataChannel, ev: Event) => any) | null;
108
+ onerror: ((this: RTCDataChannel, ev: Event) => any) | null;
109
+ onmessage: ((this: RTCDataChannel, ev: MessageEvent<any>) => any) | null;
110
+ onopen: ((this: RTCDataChannel, ev: Event) => any) | null;
111
+ close(): void;
112
+ send(data: string): void;
113
+ send(data: Blob): void;
114
+ send(data: ArrayBuffer): void;
115
+ send(data: ArrayBufferView): void;
116
+ addEventListener<K extends keyof RTCDataChannelEventMap>(type: K, listener: (this: RTCDataChannel, ev: RTCDataChannelEventMap[K]) => any, options?: boolean | AddEventListenerOptions | undefined): void;
117
+ addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions | undefined): void;
118
+ removeEventListener<K extends keyof RTCDataChannelEventMap>(type: K, listener: (this: RTCDataChannel, ev: RTCDataChannelEventMap[K]) => any, options?: boolean | EventListenerOptions | undefined): void;
119
+ removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions | undefined): void;
120
+ dispatchEvent(event: Event): boolean;
121
+ }
122
+ export declare class MockRTCDataChannelEventImpl extends Event implements RTCDataChannelEvent {
123
+ channel: RTCDataChannel;
124
+ constructor(name: string, data: RTCDataChannelEventInit);
125
+ }
126
+ export declare class MockRTCTrackEventImpl extends Event implements RTCTrackEvent {
127
+ receiver: RTCRtpReceiver;
128
+ streams: readonly MediaStream[];
129
+ track: MediaStreamTrack;
130
+ transceiver: RTCRtpTransceiver;
131
+ constructor(name: string, data: RTCTrackEventInit);
132
+ }
133
+ export declare const mockRTCPeerConnection: () => [MockRTCPeerConnectionSpyFunctions, MockRTCPeerConnectionTriggerFunctions];
134
+ export declare const unmockRTCPeerConnection: () => void;
@@ -0,0 +1,3 @@
1
+ export declare const mockRTCRtpReceiverImpl: typeof global.RTCRtpReceiver;
2
+ export declare const mockRTCRtpReceiver: () => void;
3
+ export declare const unmockRTCRtpReceiver: () => void;
@@ -0,0 +1,33 @@
1
+ import { BaseMessage } from '@epicgames-ps/lib-pixelstreamingcommon-ue5.5';
2
+ export interface MockWebSocketSpyFunctions {
3
+ constructorSpy: null | ((url: string) => void);
4
+ openSpy: null | ((event: Event) => void);
5
+ errorSpy: null | ((event: Event) => void);
6
+ closeSpy: null | ((event: CloseEvent) => void);
7
+ messageSpy: null | ((event: MessageEvent) => void);
8
+ messageBinarySpy: null | ((event: MessageEvent) => void);
9
+ sendSpy: null | ((data: string | Blob | ArrayBufferView | ArrayBufferLike) => void);
10
+ }
11
+ export interface MockWebSocketTriggerFunctions {
12
+ triggerOnOpen: null | (() => void);
13
+ triggerOnError: null | (() => void);
14
+ triggerOnClose: null | ((closeReason?: CloseEventInit) => void);
15
+ triggerOnMessage: null | ((message?: BaseMessage) => void);
16
+ triggerOnMessageBinary: null | ((message?: Blob) => void);
17
+ triggerRemoteClose: null | ((code?: number, reason?: string) => void);
18
+ }
19
+ export declare class MockWebSocketImpl extends WebSocket {
20
+ _readyState: number;
21
+ constructor(url: string | URL, protocols?: string | string[]);
22
+ get readyState(): number;
23
+ close(code?: number | undefined, reason?: string | undefined): void;
24
+ send(data: string | Blob | ArrayBufferView | ArrayBufferLike): void;
25
+ triggerOnOpen(): void;
26
+ triggerOnError(): void;
27
+ triggerOnClose(closeReason?: CloseEventInit): void;
28
+ triggerRemoteClose(code?: number, reason?: string): void;
29
+ triggerOnMessage(message: BaseMessage): void;
30
+ triggerOnMessageBinary(message?: Blob): void;
31
+ }
32
+ export declare const mockWebSocket: () => [MockWebSocketSpyFunctions, MockWebSocketTriggerFunctions];
33
+ export declare const unmockWebSocket: () => void;
@@ -17,7 +17,8 @@ export { CandidatePairStats } from './PeerConnectionController/CandidatePairStat
17
17
  export { CandidateStat } from './PeerConnectionController/CandidateStat';
18
18
  export { DataChannelStats } from './PeerConnectionController/DataChannelStats';
19
19
  export { InboundAudioStats, InboundVideoStats } from './PeerConnectionController/InboundRTPStats';
20
- export { OutBoundVideoStats } from './PeerConnectionController/OutBoundRTPStats';
20
+ export { OutboundRTPStats, RemoteOutboundRTPStats } from './PeerConnectionController/OutBoundRTPStats';
21
+ export * from './PeerConnectionController/LatencyCalculator';
21
22
  export * from './DataChannel/DataChannelLatencyTestResults';
22
23
  export * from './Util/EventEmitter';
23
24
  export * from '@epicgames-ps/lib-pixelstreamingcommon-ue5.5';
@@ -0,0 +1,52 @@
1
+ // Copyright Epic Games, Inc. All Rights Reserved.
2
+ import eslint from '@eslint/js';
3
+ import tseslint from 'typescript-eslint';
4
+
5
+ export default tseslint.config(
6
+ {
7
+ ignores: ["src/__test__/**/*.ts", "**/*.test.ts"],
8
+ },
9
+ eslint.configs.recommended,
10
+ tseslint.configs.recommendedTypeCheckedOnly,
11
+ {
12
+ languageOptions: {
13
+ parser: tseslint.parser,
14
+ parserOptions: {
15
+ project: 'tsconfig.base.json',
16
+ },
17
+ },
18
+ files: ["src/**/*.ts"],
19
+ rules: {
20
+ // TODO: when updating eslint a lot of issues suddently popped up
21
+ // these ignores should be turned off slowly and new issues should
22
+ // be addressed
23
+ "@typescript-eslint/no-explicit-any": "off",
24
+ "@typescript-eslint/no-unsafe-member-access": "off",
25
+ "@typescript-eslint/no-unsafe-call": "off",
26
+ "@typescript-eslint/no-unsafe-assignment": "off",
27
+ "@typescript-eslint/no-unsafe-argument": "off",
28
+ "@typescript-eslint/no-unsafe-return": "off",
29
+ "@typescript-eslint/no-floating-promises": "off",
30
+ "@typescript-eslint/restrict-plus-operands": "off",
31
+ "@typescript-eslint/unbound-method": "off",
32
+ "@typescript-eslint/no-duplicate-type-constituents": "off",
33
+ "@typescript-eslint/no-redundant-type-constituents": "off",
34
+ "@typescript-eslint/restrict-template-expressions": "off",
35
+ "@typescript-eslint/no-unnecessary-type-assertion": "off",
36
+ "@typescript-eslint/no-array-delete": "off",
37
+ "@typescript-eslint/no-unsafe-enum-comparison": "off",
38
+ "@typescript-eslint/require-await": "off",
39
+ "@typescript-eslint/no-base-to-string": "off",
40
+ "no-unused-vars": "off",
41
+ "@typescript-eslint/no-unused-vars": [
42
+ "error",
43
+ {
44
+ "argsIgnorePattern": "^_",
45
+ "varsIgnorePattern": "^_",
46
+ "caughtErrorsIgnorePattern": "^_"
47
+ }
48
+ ]
49
+ }
50
+ }
51
+ );
52
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@epicgames-ps/lib-pixelstreamingfrontend-ue5.5",
3
- "version": "0.4.8",
3
+ "version": "1.0.1",
4
4
  "description": "Frontend library for Unreal Engine 5.5 Pixel Streaming",
5
5
  "main": "dist/cjs/pixelstreamingfrontend.js",
6
6
  "module": "dist/esm/pixelstreamingfrontend.js",
@@ -12,29 +12,28 @@
12
12
  "build:esm": "tsc --project tsconfig.esm.json",
13
13
  "build": "npm run build:cjs && npm run build:esm",
14
14
  "rebuild": "npm run clean && npm run build",
15
- "watch": "nodemon -V -d 3 --watch src --watch ../../Common/dist -e 'ts,js,mjs,cjs,json' --exec 'npm run build:cjs'",
16
- "lint": "eslint src --ext .js,.jsx,.ts,.tsx",
15
+ "watch": "nodemon -V -d 3 --watch src --watch ../../Common/dist -e \"ts,js,mjs,cjs,json\" --exec \"npm run build:cjs\"",
16
+ "lint": "eslint src",
17
17
  "test": "jest --detectOpenHandles --coverage=true",
18
18
  "spellcheck": "cspell \"{README.md,.github/*.md,src/**/*.ts}\""
19
19
  },
20
20
  "devDependencies": {
21
+ "@eslint/js": "^9.20.0",
21
22
  "@types/jest": "^29.5.14",
22
- "@typescript-eslint/eslint-plugin": "^6.21.0",
23
- "cspell": "^4.1.0",
24
- "eslint": "^8.11.0",
25
- "eslint-config-prettier": "^9.1.0",
26
- "eslint-plugin-prettier": "^5.2.1",
23
+ "@types/webxr": "^0.5.21",
24
+ "cspell": "^8.17.3",
25
+ "eslint": "^9.20.0",
27
26
  "jest": "^29.7.0",
28
27
  "jest-environment-jsdom": "^29.7.0",
29
- "prettier": "3.3.3",
28
+ "nodemon": "^3.1.9",
29
+ "rimraf": "^6.0.1",
30
30
  "ts-jest": "^29.2.5",
31
- "typedoc": "^0.27.4",
32
- "typescript": "^5.0.0"
31
+ "typescript": "^5.7.3",
32
+ "typescript-eslint": "^8.24.0"
33
33
  },
34
34
  "dependencies": {
35
- "@epicgames-ps/lib-pixelstreamingcommon-ue5.5": "^0.1.7",
36
- "@types/webxr": "^0.5.1",
37
- "sdp": "^3.1.0"
35
+ "@epicgames-ps/lib-pixelstreamingcommon-ue5.5": "^0.2.8",
36
+ "sdp": "^3.2.0"
38
37
  },
39
38
  "repository": {
40
39
  "type": "git",
@@ -33,6 +33,7 @@ export class Flags {
33
33
  static XRControllerInput = 'XRControllerInput' as const;
34
34
  static WaitForStreamer = 'WaitForStreamer' as const;
35
35
  static HideUI = 'HideUI' as const;
36
+ static EnableCaptureTimeExt = 'EnableCaptureTimeExt' as const;
36
37
  }
37
38
 
38
39
  export type FlagsKeys = Exclude<keyof typeof Flags, 'prototype'>;
@@ -564,6 +565,19 @@ export class Config {
564
565
  )
565
566
  );
566
567
 
568
+ this.flags.set(
569
+ Flags.EnableCaptureTimeExt,
570
+ new SettingFlag(
571
+ Flags.EnableCaptureTimeExt,
572
+ 'Enable abs-capture-time',
573
+ 'Enables the abs-capture-time RTP header extension',
574
+ settings && Object.prototype.hasOwnProperty.call(settings, Flags.EnableCaptureTimeExt)
575
+ ? settings[Flags.EnableCaptureTimeExt]
576
+ : true,
577
+ useUrlParams
578
+ )
579
+ );
580
+
567
581
  /**
568
582
  * Numeric parameters
569
583
  */
@@ -18,7 +18,7 @@ export class SettingBase {
18
18
  label: string,
19
19
  description: string,
20
20
  defaultSettingValue: unknown,
21
- // eslint-disable-next-line @typescript-eslint/no-empty-function
21
+
22
22
  defaultOnChangeListener: (changedValue: unknown, setting: SettingBase) => void = () => {
23
23
  /* Do nothing, to be overridden. */
24
24
  }
@@ -16,7 +16,7 @@ export class SettingFlag<CustomIds extends string = FlagsIds> extends SettingBas
16
16
  description: string,
17
17
  defaultFlagValue: boolean,
18
18
  useUrlParams: boolean,
19
- // eslint-disable-next-line @typescript-eslint/no-empty-function
19
+
20
20
  defaultOnChangeListener: (changedValue: unknown, setting: SettingBase) => void = () => {
21
21
  /* Do nothing, to be overridden. */
22
22
  }
@@ -21,7 +21,7 @@ export class SettingNumber<CustomIds extends string = NumericParametersIds> exte
21
21
  max: number | null,
22
22
  defaultNumber: number,
23
23
  useUrlParams: boolean,
24
- // eslint-disable-next-line @typescript-eslint/no-empty-function
24
+
25
25
  defaultOnChangeListener: (changedValue: unknown, setting: SettingBase) => void = () => {
26
26
  /* Do nothing, to be overridden. */
27
27
  }
@@ -22,12 +22,12 @@ export class SettingOption<CustomIds extends string = OptionParametersIds> exten
22
22
  defaultTextValue: string,
23
23
  options: Array<string>,
24
24
  useUrlParams: boolean,
25
- // eslint-disable-next-line @typescript-eslint/no-empty-function
25
+
26
26
  defaultUrlParamResolver: (urlParamValue: string) => string = function (value: string) {
27
27
  /* Return the string as-is by default */
28
28
  return value;
29
29
  },
30
- // eslint-disable-next-line @typescript-eslint/no-empty-function
30
+
31
31
  defaultOnChangeListener: (changedValue: unknown, setting: SettingBase) => void = () => {
32
32
  /* Do nothing, to be overridden. */
33
33
  }
@@ -17,7 +17,7 @@ export class SettingText<CustomIds extends string = TextParametersIds> extends S
17
17
  description: string,
18
18
  defaultTextValue: string,
19
19
  useUrlParams: boolean,
20
- // eslint-disable-next-line @typescript-eslint/no-empty-function
20
+
21
21
  defaultOnChangeListener: (changedValue: unknown, setting: SettingBase) => void = () => {
22
22
  /* Do nothing, to be overridden. */
23
23
  }
@@ -21,7 +21,7 @@ declare global {
21
21
  /**
22
22
  * Gamepad layout codes enum
23
23
  */
24
- /* eslint-disable @typescript-eslint/no-duplicate-enum-values */
24
+
25
25
  export enum GamepadLayout {
26
26
  RightClusterBottomButton = 0,
27
27
  RightClusterRightButton = 1,
@@ -46,7 +46,7 @@ export enum GamepadLayout {
46
46
  RightStickHorizontal = 2,
47
47
  RightStickVertical = 3
48
48
  }
49
- /* eslint-enable @typescript-eslint/no-duplicate-enum-values */
49
+
50
50
 
51
51
  /**
52
52
  * Handles gamepad events from the document to send to the streamer.
@@ -5,7 +5,7 @@ import { InboundTrackStats } from './InboundTrackStats';
5
5
  import { DataChannelStats } from './DataChannelStats';
6
6
  import { CandidateStat } from './CandidateStat';
7
7
  import { CandidatePairStats } from './CandidatePairStats';
8
- import { OutBoundRTPStats, OutBoundVideoStats } from './OutBoundRTPStats';
8
+ import { RemoteOutboundRTPStats, OutboundRTPStats } from './OutBoundRTPStats';
9
9
  import { SessionStats } from './SessionStats';
10
10
  import { StreamStats } from './StreamStats';
11
11
  import { CodecStats } from './CodecStats';
@@ -15,15 +15,17 @@ import { Logger } from '@epicgames-ps/lib-pixelstreamingcommon-ue5.5';
15
15
  * The Aggregated Stats that is generated from the RTC Stats Report
16
16
  */
17
17
 
18
- type RTCStatsTypePS = RTCStatsType | 'stream' | 'media-playout' | 'track';
19
18
  export class AggregatedStats {
20
19
  inboundVideoStats: InboundVideoStats;
21
20
  inboundAudioStats: InboundAudioStats;
22
21
  candidatePairs: Array<CandidatePairStats>;
23
- DataChannelStats: DataChannelStats;
22
+ datachannelStats: DataChannelStats;
24
23
  localCandidates: Array<CandidateStat>;
25
24
  remoteCandidates: Array<CandidateStat>;
26
- outBoundVideoStats: OutBoundVideoStats;
25
+ outboundVideoStats: OutboundRTPStats;
26
+ outboundAudioStats: OutboundRTPStats;
27
+ remoteOutboundVideoStats: RemoteOutboundRTPStats;
28
+ remoteOutboundAudioStats: RemoteOutboundRTPStats;
27
29
  sessionStats: SessionStats;
28
30
  streamStats: StreamStats;
29
31
  codecs: Map<string, CodecStats>;
@@ -32,8 +34,11 @@ export class AggregatedStats {
32
34
  constructor() {
33
35
  this.inboundVideoStats = new InboundVideoStats();
34
36
  this.inboundAudioStats = new InboundAudioStats();
35
- this.DataChannelStats = new DataChannelStats();
36
- this.outBoundVideoStats = new OutBoundVideoStats();
37
+ this.datachannelStats = new DataChannelStats();
38
+ this.outboundVideoStats = new OutboundRTPStats();
39
+ this.outboundAudioStats = new OutboundRTPStats();
40
+ this.remoteOutboundAudioStats = new RemoteOutboundRTPStats();
41
+ this.remoteOutboundVideoStats = new RemoteOutboundRTPStats();
37
42
  this.sessionStats = new SessionStats();
38
43
  this.streamStats = new StreamStats();
39
44
  this.codecs = new Map<string, CodecStats>();
@@ -49,7 +54,7 @@ export class AggregatedStats {
49
54
  this.candidatePairs = new Array<CandidatePairStats>();
50
55
 
51
56
  rtcStatsReport.forEach((stat) => {
52
- const type: RTCStatsTypePS = stat.type;
57
+ const type: string = stat.type;
53
58
 
54
59
  switch (type) {
55
60
  case 'candidate-pair':
@@ -64,7 +69,7 @@ export class AggregatedStats {
64
69
  this.handleDataChannel(stat);
65
70
  break;
66
71
  case 'inbound-rtp':
67
- this.handleInBoundRTP(stat);
72
+ this.handleInboundRTP(stat);
68
73
  break;
69
74
  case 'local-candidate':
70
75
  this.handleLocalCandidate(stat);
@@ -74,6 +79,7 @@ export class AggregatedStats {
74
79
  case 'media-playout':
75
80
  break;
76
81
  case 'outbound-rtp':
82
+ this.handleLocalOutbound(stat);
77
83
  break;
78
84
  case 'peer-connection':
79
85
  break;
@@ -83,7 +89,7 @@ export class AggregatedStats {
83
89
  case 'remote-inbound-rtp':
84
90
  break;
85
91
  case 'remote-outbound-rtp':
86
- this.handleRemoteOutBound(stat);
92
+ this.handleRemoteOutbound(stat);
87
93
  break;
88
94
  case 'track':
89
95
  this.handleTrack(stat);
@@ -125,16 +131,16 @@ export class AggregatedStats {
125
131
  * @param stat - the stats coming in from the data channel
126
132
  */
127
133
  handleDataChannel(stat: DataChannelStats) {
128
- this.DataChannelStats.bytesReceived = stat.bytesReceived;
129
- this.DataChannelStats.bytesSent = stat.bytesSent;
130
- this.DataChannelStats.dataChannelIdentifier = stat.dataChannelIdentifier;
131
- this.DataChannelStats.id = stat.id;
132
- this.DataChannelStats.label = stat.label;
133
- this.DataChannelStats.messagesReceived = stat.messagesReceived;
134
- this.DataChannelStats.messagesSent = stat.messagesSent;
135
- this.DataChannelStats.protocol = stat.protocol;
136
- this.DataChannelStats.state = stat.state;
137
- this.DataChannelStats.timestamp = stat.timestamp;
134
+ this.datachannelStats.bytesReceived = stat.bytesReceived;
135
+ this.datachannelStats.bytesSent = stat.bytesSent;
136
+ this.datachannelStats.dataChannelIdentifier = stat.dataChannelIdentifier;
137
+ this.datachannelStats.id = stat.id;
138
+ this.datachannelStats.label = stat.label;
139
+ this.datachannelStats.messagesReceived = stat.messagesReceived;
140
+ this.datachannelStats.messagesSent = stat.messagesSent;
141
+ this.datachannelStats.protocol = stat.protocol;
142
+ this.datachannelStats.state = stat.state;
143
+ this.datachannelStats.timestamp = stat.timestamp;
138
144
  }
139
145
 
140
146
  /**
@@ -159,23 +165,23 @@ export class AggregatedStats {
159
165
  * @param stat - ice candidate stats
160
166
  */
161
167
  handleRemoteCandidate(stat: CandidateStat) {
162
- const RemoteCandidate = new CandidateStat();
163
- RemoteCandidate.label = 'remote-candidate';
164
- RemoteCandidate.address = stat.address;
165
- RemoteCandidate.port = stat.port;
166
- RemoteCandidate.protocol = stat.protocol;
167
- RemoteCandidate.id = stat.id;
168
- RemoteCandidate.candidateType = stat.candidateType;
169
- RemoteCandidate.relayProtocol = stat.relayProtocol;
170
- RemoteCandidate.transportId = stat.transportId;
171
- this.remoteCandidates.push(RemoteCandidate);
168
+ const remoteCandidate = new CandidateStat();
169
+ remoteCandidate.label = 'remote-candidate';
170
+ remoteCandidate.address = stat.address;
171
+ remoteCandidate.port = stat.port;
172
+ remoteCandidate.protocol = stat.protocol;
173
+ remoteCandidate.id = stat.id;
174
+ remoteCandidate.candidateType = stat.candidateType;
175
+ remoteCandidate.relayProtocol = stat.relayProtocol;
176
+ remoteCandidate.transportId = stat.transportId;
177
+ this.remoteCandidates.push(remoteCandidate);
172
178
  }
173
179
 
174
180
  /**
175
181
  * Process the Inbound RTP Audio and Video Data
176
182
  * @param stat - inbound rtp stats
177
183
  */
178
- handleInBoundRTP(stat: InboundRTPStats) {
184
+ handleInboundRTP(stat: InboundRTPStats) {
179
185
  switch (stat.kind) {
180
186
  case 'video':
181
187
  // Calculate bitrate between stat updates
@@ -216,25 +222,63 @@ export class AggregatedStats {
216
222
  }
217
223
 
218
224
  /**
219
- * Process the outbound RTP Audio and Video Data
220
- * @param stat - remote outbound stats
225
+ * Process the "local" outbound RTP Audio and Video stats.
226
+ * @param stat - local outbound rtp stats
221
227
  */
222
- handleRemoteOutBound(stat: OutBoundRTPStats) {
223
- switch (stat.kind) {
224
- case 'video':
225
- this.outBoundVideoStats.bytesSent = stat.bytesSent;
226
- this.outBoundVideoStats.id = stat.id;
227
- this.outBoundVideoStats.localId = stat.localId;
228
- this.outBoundVideoStats.packetsSent = stat.packetsSent;
229
- this.outBoundVideoStats.remoteTimestamp = stat.remoteTimestamp;
230
- this.outBoundVideoStats.timestamp = stat.timestamp;
231
- break;
232
- case 'audio':
233
- break;
228
+ handleLocalOutbound(stat: OutboundRTPStats) {
229
+ const localOutboundStats: OutboundRTPStats =
230
+ stat.kind === 'audio' ? this.outboundAudioStats : this.outboundVideoStats;
231
+ localOutboundStats.active = stat.active;
232
+ localOutboundStats.codecId = stat.codecId;
233
+ localOutboundStats.bytesSent = stat.bytesSent;
234
+ localOutboundStats.frameHeight = stat.frameHeight;
235
+ localOutboundStats.frameWidth = stat.frameWidth;
236
+ localOutboundStats.framesEncoded = stat.framesEncoded;
237
+ localOutboundStats.framesPerSecond = stat.framesPerSecond;
238
+ localOutboundStats.headerBytesSent = stat.headerBytesSent;
239
+ localOutboundStats.id = stat.id;
240
+ localOutboundStats.keyFramesEncoded = stat.keyFramesEncoded;
241
+ localOutboundStats.kind = stat.kind;
242
+ localOutboundStats.mediaSourceId = stat.mediaSourceId;
243
+ localOutboundStats.mid = stat.mid;
244
+ localOutboundStats.nackCount = stat.nackCount;
245
+ localOutboundStats.packetsSent = stat.packetsSent;
246
+ localOutboundStats.qpSum = stat.qpSum;
247
+ localOutboundStats.qualityLimitationDurations = stat.qualityLimitationDurations;
248
+ localOutboundStats.qualityLimitationReason = stat.qualityLimitationReason;
249
+ localOutboundStats.remoteId = stat.remoteId;
250
+ localOutboundStats.retransmittedBytesSent = stat.retransmittedBytesSent;
251
+ localOutboundStats.rid = stat.rid;
252
+ localOutboundStats.scalabilityMode = stat.scalabilityMode;
253
+ localOutboundStats.ssrc = stat.ssrc;
254
+ localOutboundStats.targetBitrate = stat.targetBitrate;
255
+ localOutboundStats.timestamp = stat.timestamp;
256
+ localOutboundStats.totalEncodeTime = stat.totalEncodeTime;
257
+ localOutboundStats.totalEncodeBytesTarget = stat.totalEncodeBytesTarget;
258
+ localOutboundStats.totalPacketSendDelay = stat.totalPacketSendDelay;
259
+ localOutboundStats.transportId = stat.transportId;
260
+ }
234
261
 
235
- default:
236
- break;
237
- }
262
+ /**
263
+ * Process the "remote" outbound RTP Audio and Video stats.
264
+ * @param stat - remote outbound rtp stats
265
+ */
266
+ handleRemoteOutbound(stat: RemoteOutboundRTPStats) {
267
+ const remoteOutboundStats: RemoteOutboundRTPStats =
268
+ stat.kind === 'audio' ? this.remoteOutboundAudioStats : this.remoteOutboundVideoStats;
269
+ remoteOutboundStats.bytesSent = stat.bytesSent;
270
+ remoteOutboundStats.codecId = stat.codecId;
271
+ remoteOutboundStats.id = stat.id;
272
+ remoteOutboundStats.kind = stat.kind;
273
+ remoteOutboundStats.localId = stat.localId;
274
+ remoteOutboundStats.packetsSent = stat.packetsSent;
275
+ remoteOutboundStats.remoteTimestamp = stat.remoteTimestamp;
276
+ remoteOutboundStats.reportsSent = stat.reportsSent;
277
+ remoteOutboundStats.roundTripTimeMeasurements = stat.roundTripTimeMeasurements;
278
+ remoteOutboundStats.ssrc = stat.ssrc;
279
+ remoteOutboundStats.timestamp = stat.timestamp;
280
+ remoteOutboundStats.totalRoundTripTime = stat.totalRoundTripTime;
281
+ remoteOutboundStats.transportId = stat.transportId;
238
282
  }
239
283
 
240
284
  /**
@@ -288,16 +332,31 @@ export class AggregatedStats {
288
332
  * @returns The candidate pair that is currently receiving data
289
333
  */
290
334
  public getActiveCandidatePair(): CandidatePairStats | null {
335
+ if (this.candidatePairs === undefined) {
336
+ return null;
337
+ }
338
+
291
339
  // Check if the RTCTransport stat is not undefined
292
340
  if (this.transportStats) {
293
341
  // Return the candidate pair that matches the transport candidate pair id
294
- return this.candidatePairs.find(
295
- (candidatePair) => candidatePair.id === this.transportStats.selectedCandidatePairId,
296
- null
342
+ const selectedPair: CandidatePairStats | undefined = this.candidatePairs.find(
343
+ (candidatePair) => candidatePair.id === this.transportStats.selectedCandidatePairId
297
344
  );
345
+ if (selectedPair === undefined) {
346
+ return null;
347
+ } else {
348
+ return selectedPair;
349
+ }
298
350
  }
299
351
 
300
- // Fall back to the selected candidate pair
301
- return this.candidatePairs.find((candidatePair) => candidatePair.selected, null);
352
+ // Fall back to the `.selected` member of the candidate pair
353
+ const selectedPair: CandidatePairStats | undefined = this.candidatePairs.find(
354
+ (candidatePair) => candidatePair.selected
355
+ );
356
+ if (selectedPair === undefined) {
357
+ return null;
358
+ } else {
359
+ return selectedPair;
360
+ }
302
361
  }
303
362
  }