werift 0.12.8 → 0.13.2

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 (162) hide show
  1. package/lib/common/src/binary.d.ts +9 -0
  2. package/lib/common/src/binary.js +37 -1
  3. package/lib/common/src/binary.js.map +1 -1
  4. package/lib/dtls/src/context/srtp.d.ts +6 -2
  5. package/lib/dtls/src/context/srtp.js +9 -3
  6. package/lib/dtls/src/context/srtp.js.map +1 -1
  7. package/lib/dtls/src/flight/client/flight5.js.map +1 -1
  8. package/lib/dtls/src/flight/server/flight2.js.map +1 -1
  9. package/lib/dtls/src/socket.d.ts +3 -3
  10. package/lib/dtls/src/socket.js +6 -8
  11. package/lib/dtls/src/socket.js.map +1 -1
  12. package/lib/ice/src/utils.d.ts +1 -0
  13. package/lib/ice/src/utils.js +5 -1
  14. package/lib/ice/src/utils.js.map +1 -1
  15. package/lib/rtp/src/codec/base.d.ts +8 -0
  16. package/lib/rtp/src/codec/base.js +16 -0
  17. package/lib/rtp/src/codec/base.js.map +1 -0
  18. package/lib/rtp/src/codec/h264.d.ts +23 -2
  19. package/lib/rtp/src/codec/h264.js +66 -3
  20. package/lib/rtp/src/codec/h264.js.map +1 -1
  21. package/lib/rtp/src/codec/opus.d.ts +9 -0
  22. package/lib/rtp/src/codec/opus.js +18 -0
  23. package/lib/rtp/src/codec/opus.js.map +1 -0
  24. package/lib/rtp/src/codec/vp8.d.ts +18 -11
  25. package/lib/rtp/src/codec/vp8.js +51 -29
  26. package/lib/rtp/src/codec/vp8.js.map +1 -1
  27. package/lib/rtp/src/codec/vp9.d.ts +38 -10
  28. package/lib/rtp/src/codec/vp9.js +115 -26
  29. package/lib/rtp/src/codec/vp9.js.map +1 -1
  30. package/lib/rtp/src/index.d.ts +2 -0
  31. package/lib/rtp/src/index.js +2 -0
  32. package/lib/rtp/src/index.js.map +1 -1
  33. package/lib/rtp/src/rtcp/psfb/index.d.ts +2 -2
  34. package/lib/rtp/src/rtcp/psfb/index.js.map +1 -1
  35. package/lib/rtp/src/rtcp/rr.d.ts +2 -2
  36. package/lib/rtp/src/rtcp/rr.js.map +1 -1
  37. package/lib/rtp/src/rtcp/rtpfb/index.d.ts +2 -2
  38. package/lib/rtp/src/rtcp/rtpfb/index.js.map +1 -1
  39. package/lib/rtp/src/rtcp/sdes.d.ts +2 -2
  40. package/lib/rtp/src/rtcp/sdes.js.map +1 -1
  41. package/lib/rtp/src/rtcp/sr.d.ts +2 -2
  42. package/lib/rtp/src/rtcp/sr.js +36 -0
  43. package/lib/rtp/src/rtcp/sr.js.map +1 -1
  44. package/lib/rtp/src/rtp/rtp.d.ts +2 -0
  45. package/lib/rtp/src/rtp/rtp.js +2 -0
  46. package/lib/rtp/src/rtp/rtp.js.map +1 -1
  47. package/lib/rtp/src/srtp/cipher/ctr.d.ts +17 -0
  48. package/lib/rtp/src/srtp/cipher/ctr.js +103 -0
  49. package/lib/rtp/src/srtp/cipher/ctr.js.map +1 -0
  50. package/lib/rtp/src/srtp/cipher/gcm.d.ts +15 -0
  51. package/lib/rtp/src/srtp/cipher/gcm.js +106 -0
  52. package/lib/rtp/src/srtp/cipher/gcm.js.map +1 -0
  53. package/lib/rtp/src/srtp/cipher/index.d.ts +14 -0
  54. package/lib/rtp/src/srtp/cipher/index.js +25 -0
  55. package/lib/rtp/src/srtp/cipher/index.js.map +1 -0
  56. package/lib/rtp/src/srtp/const.d.ts +5 -0
  57. package/lib/rtp/src/srtp/const.js +23 -0
  58. package/lib/rtp/src/srtp/const.js.map +1 -0
  59. package/lib/rtp/src/srtp/context/context.d.ts +13 -11
  60. package/lib/rtp/src/srtp/context/context.js +23 -23
  61. package/lib/rtp/src/srtp/context/context.js.map +1 -1
  62. package/lib/rtp/src/srtp/context/srtcp.d.ts +3 -2
  63. package/lib/rtp/src/srtp/context/srtcp.js +10 -34
  64. package/lib/rtp/src/srtp/context/srtcp.js.map +1 -1
  65. package/lib/rtp/src/srtp/context/srtp.d.ts +4 -3
  66. package/lib/rtp/src/srtp/context/srtp.js +9 -28
  67. package/lib/rtp/src/srtp/context/srtp.js.map +1 -1
  68. package/lib/rtp/src/srtp/srtp.js +2 -2
  69. package/lib/rtp/src/srtp/srtp.js.map +1 -1
  70. package/lib/webrtc/src/const.d.ts +4 -3
  71. package/lib/webrtc/src/const.js +5 -4
  72. package/lib/webrtc/src/const.js.map +1 -1
  73. package/lib/webrtc/src/helper.d.ts +2 -2
  74. package/lib/webrtc/src/helper.js +2 -2
  75. package/lib/webrtc/src/helper.js.map +1 -1
  76. package/lib/webrtc/src/index.d.ts +6 -2
  77. package/lib/webrtc/src/index.js +6 -2
  78. package/lib/webrtc/src/index.js.map +1 -1
  79. package/lib/webrtc/src/{extension → media/extension}/rtcpFeedback.d.ts +1 -1
  80. package/lib/webrtc/src/{extension → media/extension}/rtcpFeedback.js +0 -0
  81. package/lib/webrtc/src/media/extension/rtcpFeedback.js.map +1 -0
  82. package/lib/webrtc/src/{extension → media/extension}/rtpExtension.d.ts +1 -1
  83. package/lib/webrtc/src/{extension → media/extension}/rtpExtension.js +1 -1
  84. package/lib/webrtc/src/media/extension/rtpExtension.js.map +1 -0
  85. package/lib/webrtc/src/media/{nack.d.ts → receiver/nack.d.ts} +2 -2
  86. package/lib/webrtc/src/media/{nack.js → receiver/nack.js} +2 -2
  87. package/lib/webrtc/src/media/receiver/nack.js.map +1 -0
  88. package/lib/webrtc/src/media/{statistics.d.ts → receiver/statistics.d.ts} +1 -1
  89. package/lib/webrtc/src/media/{statistics.js → receiver/statistics.js} +1 -1
  90. package/lib/webrtc/src/media/receiver/statistics.js.map +1 -0
  91. package/lib/webrtc/src/media/router.js +1 -1
  92. package/lib/webrtc/src/media/router.js.map +1 -1
  93. package/lib/webrtc/src/media/rtpReceiver.d.ts +4 -2
  94. package/lib/webrtc/src/media/rtpReceiver.js +13 -6
  95. package/lib/webrtc/src/media/rtpReceiver.js.map +1 -1
  96. package/lib/webrtc/src/media/rtpSender.d.ts +4 -4
  97. package/lib/webrtc/src/media/rtpSender.js +12 -6
  98. package/lib/webrtc/src/media/rtpSender.js.map +1 -1
  99. package/lib/webrtc/src/media/{senderBWE → sender}/cumulativeResult.d.ts +0 -0
  100. package/lib/webrtc/src/media/{senderBWE → sender}/cumulativeResult.js +0 -0
  101. package/lib/webrtc/src/media/sender/cumulativeResult.js.map +1 -0
  102. package/lib/webrtc/src/media/{senderBWE → sender}/senderBWE.d.ts +0 -0
  103. package/lib/webrtc/src/media/{senderBWE → sender}/senderBWE.js +0 -0
  104. package/lib/webrtc/src/media/sender/senderBWE.js.map +1 -0
  105. package/lib/webrtc/src/media/track.d.ts +3 -0
  106. package/lib/webrtc/src/media/track.js +2 -0
  107. package/lib/webrtc/src/media/track.js.map +1 -1
  108. package/lib/webrtc/src/nonstandard/jitterBuffer.d.ts +12 -0
  109. package/lib/webrtc/src/nonstandard/jitterBuffer.js +48 -0
  110. package/lib/webrtc/src/nonstandard/jitterBuffer.js.map +1 -0
  111. package/lib/webrtc/src/nonstandard/lipsync.d.ts +20 -0
  112. package/lib/webrtc/src/nonstandard/lipsync.js +39 -0
  113. package/lib/webrtc/src/nonstandard/lipsync.js.map +1 -0
  114. package/lib/webrtc/src/nonstandard/recorder.d.ts +18 -0
  115. package/lib/webrtc/src/nonstandard/recorder.js +25 -0
  116. package/lib/webrtc/src/nonstandard/recorder.js.map +1 -0
  117. package/lib/webrtc/src/nonstandard/sampleBuilder.d.ts +18 -0
  118. package/lib/webrtc/src/nonstandard/sampleBuilder.js +60 -0
  119. package/lib/webrtc/src/nonstandard/sampleBuilder.js.map +1 -0
  120. package/lib/webrtc/src/nonstandard/userMedia.d.ts +15 -0
  121. package/lib/webrtc/src/nonstandard/userMedia.js +67 -0
  122. package/lib/webrtc/src/nonstandard/userMedia.js.map +1 -0
  123. package/lib/webrtc/src/nonstandard/webm.d.ts +24 -0
  124. package/lib/webrtc/src/nonstandard/webm.js +308 -0
  125. package/lib/webrtc/src/nonstandard/webm.js.map +1 -0
  126. package/lib/webrtc/src/peerConnection.js +1 -0
  127. package/lib/webrtc/src/peerConnection.js.map +1 -1
  128. package/lib/webrtc/src/transport/dtls.d.ts +2 -1
  129. package/lib/webrtc/src/transport/dtls.js +7 -3
  130. package/lib/webrtc/src/transport/dtls.js.map +1 -1
  131. package/lib/webrtc/src/utils.d.ts +3 -0
  132. package/lib/webrtc/src/utils.js +13 -9
  133. package/lib/webrtc/src/utils.js.map +1 -1
  134. package/package.json +5 -4
  135. package/src/const.ts +8 -3
  136. package/src/helper.ts +4 -4
  137. package/src/index.ts +6 -2
  138. package/src/{extension → media/extension}/rtcpFeedback.ts +1 -1
  139. package/src/{extension → media/extension}/rtpExtension.ts +1 -1
  140. package/src/media/{nack.ts → receiver/nack.ts} +3 -3
  141. package/src/media/{statistics.ts → receiver/statistics.ts} +2 -2
  142. package/src/media/router.ts +1 -1
  143. package/src/media/rtpReceiver.ts +11 -7
  144. package/src/media/rtpSender.ts +19 -9
  145. package/src/media/{senderBWE → sender}/cumulativeResult.ts +0 -0
  146. package/src/media/{senderBWE → sender}/senderBWE.ts +0 -0
  147. package/src/media/track.ts +6 -0
  148. package/src/nonstandard/jitterBuffer.ts +47 -0
  149. package/src/nonstandard/lipsync.ts +55 -0
  150. package/src/nonstandard/recorder.ts +26 -0
  151. package/src/nonstandard/sampleBuilder.ts +71 -0
  152. package/src/nonstandard/userMedia.ts +74 -0
  153. package/src/nonstandard/webm.ts +421 -0
  154. package/src/peerConnection.ts +3 -1
  155. package/src/transport/dtls.ts +12 -4
  156. package/src/utils.ts +20 -12
  157. package/lib/webrtc/src/extension/rtcpFeedback.js.map +0 -1
  158. package/lib/webrtc/src/extension/rtpExtension.js.map +0 -1
  159. package/lib/webrtc/src/media/nack.js.map +0 -1
  160. package/lib/webrtc/src/media/senderBWE/cumulativeResult.js.map +0 -1
  161. package/lib/webrtc/src/media/senderBWE/senderBWE.js.map +0 -1
  162. package/lib/webrtc/src/media/statistics.js.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "werift",
3
- "version": "0.12.8",
3
+ "version": "0.13.2",
4
4
  "description": "WebRTC Implementation for TypeScript (Node.js)",
5
5
  "keywords": [
6
6
  "WebRTC",
@@ -36,6 +36,7 @@
36
36
  "@fidm/x509": "^1.2.1",
37
37
  "@peculiar/webcrypto": "^1.1.6",
38
38
  "@peculiar/x509": "^1.2.2",
39
+ "@shinyoshiaki/ebml-builder": "^0.0.1",
39
40
  "aes-js": "^3.1.2",
40
41
  "big-integer": "^1.6.48",
41
42
  "binary-data": "^0.6.0",
@@ -58,12 +59,12 @@
58
59
  "@types/aes-js": "^3.1.1",
59
60
  "@types/big-integer": "^0.0.31",
60
61
  "@types/buffer-crc32": "^0.2.0",
61
- "@types/debug": "^4.1.6",
62
+ "@types/debug": "^4.1.7",
62
63
  "@types/elliptic": "^6.4.12",
63
64
  "@types/ip": "^1.1.0",
64
- "@types/lodash": "^4.14.170",
65
+ "@types/lodash": "^4.14.172",
65
66
  "@types/uuid": "^8.3.0",
66
- "typedoc": "^0.21.4"
67
+ "typedoc": "^0.21.5"
67
68
  },
68
69
  "engines": {
69
70
  "node": ">=15"
package/src/const.ts CHANGED
@@ -1,3 +1,7 @@
1
+ import {
2
+ ProtectionProfileAeadAes128Gcm,
3
+ ProtectionProfileAes128CmHmacSha1_80,
4
+ } from "../../dtls/src/context/srtp";
1
5
  import { DtlsRole } from "./transport/dtls";
2
6
 
3
7
  // data channel export constants
@@ -47,9 +51,10 @@ export const FMTP_INT_PARAMETERS = [
47
51
 
48
52
  export const SSRC_INFO_ATTRS = ["cname", "msid", "mslabel", "label"];
49
53
 
50
- export enum SRTP_PROFILE {
51
- SRTP_AES128_CM_HMAC_SHA1_80 = 1,
52
- }
54
+ export const SRTP_PROFILE = {
55
+ SRTP_AES128_CM_HMAC_SHA1_80: ProtectionProfileAes128CmHmacSha1_80,
56
+ SRTP_AEAD_AES_128_GCM: ProtectionProfileAeadAes128Gcm,
57
+ } as const;
53
58
 
54
59
  export const SenderDirections = ["sendonly", "sendrecv"];
55
60
  export const NotSenderDirections = ["inactive", "recvonly"];
package/src/helper.ts CHANGED
@@ -10,21 +10,21 @@ export function divide(from: string, split: string): [string, string] {
10
10
  }
11
11
 
12
12
  export class PromiseQueue {
13
- queue: { promise: () => Promise<any>; call: () => void }[] = [];
13
+ queue: { promise: () => Promise<any>; done: () => void }[] = [];
14
14
  running = false;
15
15
 
16
16
  push = (promise: () => Promise<any>) =>
17
17
  new Promise<void>((r) => {
18
- this.queue.push({ promise, call: r });
18
+ this.queue.push({ promise, done: r });
19
19
  if (!this.running) this.run();
20
20
  });
21
21
 
22
- async run() {
22
+ private async run() {
23
23
  const task = this.queue.shift();
24
24
  if (task) {
25
25
  this.running = true;
26
26
  await task.promise();
27
- task.call();
27
+ task.done();
28
28
 
29
29
  this.run();
30
30
  } else {
package/src/index.ts CHANGED
@@ -1,12 +1,16 @@
1
1
  export * from "../../ice/src";
2
2
  export * from "../../rtp/src";
3
3
  export * from "./dataChannel";
4
- export * from "./extension/rtcpFeedback";
5
- export * from "./extension/rtpExtension";
6
4
  export * from "./helper";
5
+ export * from "./media/extension/rtcpFeedback";
6
+ export * from "./media/extension/rtpExtension";
7
7
  export * from "./media/parameters";
8
8
  export * from "./media/rtpTransceiver";
9
9
  export * from "./media/track";
10
+ export * from "./nonstandard/lipsync";
11
+ export * from "./nonstandard/recorder";
12
+ export * from "./nonstandard/sampleBuilder";
13
+ export * from "./nonstandard/userMedia";
10
14
  export * from "./peerConnection";
11
15
  export * from "./sdp";
12
16
  export * from "./transport/dtls";
@@ -1,4 +1,4 @@
1
- import { RTCPFB } from "../media/parameters";
1
+ import { RTCPFB } from "../parameters";
2
2
 
3
3
  export const useFIR = (): RTCPFB => ({ type: "ccm", parameter: "fir" });
4
4
 
@@ -1,4 +1,4 @@
1
- import { RTCRtpHeaderExtensionParameters } from "../media/parameters";
1
+ import { RTCRtpHeaderExtensionParameters } from "../parameters";
2
2
 
3
3
  export const RTP_EXTENSION_URI = {
4
4
  sdesMid: "urn:ietf:params:rtp-hdrext:sdes:mid",
@@ -1,13 +1,13 @@
1
1
  import { range } from "lodash";
2
2
  import Event from "rx.mini";
3
3
 
4
- import { uint16Add } from "../../../common/src";
4
+ import { uint16Add } from "../../../../common/src";
5
5
  import {
6
6
  GenericNack,
7
7
  RtcpTransportLayerFeedback,
8
8
  RtpPacket,
9
- } from "../../../rtp/src";
10
- import { RTCRtpReceiver } from "./rtpReceiver";
9
+ } from "../../../../rtp/src";
10
+ import { RTCRtpReceiver } from "../rtpReceiver";
11
11
 
12
12
  const LOST_SIZE = 30 * 5;
13
13
 
@@ -1,5 +1,5 @@
1
- import { int, uint16Gt } from "../../../common/src";
2
- import { RtpPacket } from "../../../rtp/src";
1
+ import { int, uint16Gt } from "../../../../common/src";
2
+ import { RtpPacket } from "../../../../rtp/src";
3
3
 
4
4
  // from aiortc
5
5
 
@@ -12,7 +12,7 @@ import {
12
12
  RtcpTransportLayerFeedback,
13
13
  RtpPacket,
14
14
  } from "../../../rtp/src";
15
- import { RTP_EXTENSION_URI } from "../extension/rtpExtension";
15
+ import { RTP_EXTENSION_URI } from "./extension/rtpExtension";
16
16
  import {
17
17
  RTCRtpReceiveParameters,
18
18
  RTCRtpSimulcastParameters,
@@ -1,5 +1,6 @@
1
1
  import { debug } from "debug";
2
2
  import { jspack } from "jspack";
3
+ import Event from "rx.mini";
3
4
  import { setTimeout } from "timers/promises";
4
5
  import { v4 as uuid } from "uuid";
5
6
 
@@ -14,14 +15,15 @@ import {
14
15
  RtpHeader,
15
16
  RtpPacket,
16
17
  } from "../../../rtp/src";
17
- import { RTP_EXTENSION_URI } from "../extension/rtpExtension";
18
18
  import { RTCDtlsTransport } from "../transport/dtls";
19
19
  import { Kind } from "../types/domain";
20
- import { Nack } from "./nack";
20
+ import { compactNtp } from "../utils";
21
+ import { RTP_EXTENSION_URI } from "./extension/rtpExtension";
21
22
  import { RTCRtpCodecParameters, RTCRtpReceiveParameters } from "./parameters";
23
+ import { Nack } from "./receiver/nack";
22
24
  import { ReceiverTWCC } from "./receiver/receiverTwcc";
25
+ import { StreamStatistics } from "./receiver/statistics";
23
26
  import { Extensions } from "./router";
24
- import { StreamStatistics } from "./statistics";
25
27
  import { MediaStreamTrack } from "./track";
26
28
 
27
29
  const log = debug("werift:packages/webrtc/src/media/rtpReceiver.ts");
@@ -37,9 +39,10 @@ export class RTCRtpReceiver {
37
39
  readonly trackBySSRC: { [ssrc: string]: MediaStreamTrack } = {};
38
40
  readonly trackByRID: { [rid: string]: MediaStreamTrack } = {};
39
41
  // last senderReport
40
- readonly lsr: { [ssrc: number]: BigInt } = {};
42
+ readonly lsr: { [ssrc: number]: number } = {};
41
43
  readonly lsrTime: { [ssrc: number]: number } = {};
42
44
  readonly onPacketLost = this.nack.onPacketLost;
45
+ readonly onRtcp = new Event<[RtcpPacket]>();
43
46
 
44
47
  sdesMid?: string;
45
48
  latestRid?: string;
@@ -128,7 +131,7 @@ export class RTCRtpReceiver {
128
131
 
129
132
  const reports = Object.entries(this.remoteStreams).map(
130
133
  ([ssrc, stream]) => {
131
- let lsr = 0n,
134
+ let lsr = 0,
132
135
  dlsr = 0;
133
136
  if (this.lsr[ssrc]) {
134
137
  lsr = this.lsr[ssrc];
@@ -144,7 +147,7 @@ export class RTCRtpReceiver {
144
147
  packetsLost: stream.packets_lost,
145
148
  highestSequence: stream.max_seq,
146
149
  jitter: stream.jitter,
147
- lsr: Number(lsr),
150
+ lsr,
148
151
  dlsr,
149
152
  });
150
153
  }
@@ -184,11 +187,12 @@ export class RTCRtpReceiver {
184
187
  case RtcpSrPacket.type:
185
188
  {
186
189
  const sr = packet as RtcpSrPacket;
187
- this.lsr[sr.ssrc] = (sr.senderInfo.ntpTimestamp >> 16n) & 0xffffffffn;
190
+ this.lsr[sr.ssrc] = compactNtp(sr.senderInfo.ntpTimestamp);
188
191
  this.lsrTime[sr.ssrc] = Date.now() / 1000;
189
192
  }
190
193
  break;
191
194
  }
195
+ this.onRtcp.execute(packet);
192
196
  }
193
197
 
194
198
  handleRtpBySsrc = (packet: RtpPacket, extensions: Extensions) => {
@@ -29,16 +29,16 @@ import {
29
29
  SourceDescriptionItem,
30
30
  TransportWideCC,
31
31
  } from "../../../rtp/src";
32
- import { RTP_EXTENSION_URI } from "../extension/rtpExtension";
33
32
  import { RTCDtlsTransport } from "../transport/dtls";
34
33
  import { Kind } from "../types/domain";
35
- import { milliTime, ntpTime } from "../utils";
34
+ import { compactNtp, milliTime, ntpTime } from "../utils";
35
+ import { RTP_EXTENSION_URI } from "./extension/rtpExtension";
36
36
  import {
37
37
  RTCRtpCodecParameters,
38
38
  RTCRtpHeaderExtensionParameters,
39
39
  RTCRtpSendParameters,
40
40
  } from "./parameters";
41
- import { SenderBandwidthEstimator, SentInfo } from "./senderBWE/senderBWE";
41
+ import { SenderBandwidthEstimator, SentInfo } from "./sender/senderBWE";
42
42
  import { MediaStreamTrack } from "./track";
43
43
 
44
44
  const log = debug("werift:packages/webrtc/src/media/rtpSender.ts");
@@ -54,7 +54,7 @@ export class RTCRtpSender {
54
54
  : this.trackOrKind.kind;
55
55
  readonly ssrc = jspack.Unpack("!L", randomBytes(4))[0];
56
56
  readonly rtxSsrc = jspack.Unpack("!L", randomBytes(4))[0];
57
- readonly streamId = uuid.v4();
57
+ streamId = uuid.v4();
58
58
  readonly trackId = uuid.v4();
59
59
  readonly onReady = new Event();
60
60
  readonly onRtcp = new Event<[RtcpPacket]>();
@@ -72,7 +72,7 @@ export class RTCRtpSender {
72
72
  private disposeTrack?: () => void;
73
73
 
74
74
  // # stats
75
- private lsr?: bigint;
75
+ private lsr?: number;
76
76
  private lsrTime: number = Date.now() / 1000;
77
77
  private ntpTimestamp = 0n;
78
78
  private rtpTimestamp = 0;
@@ -104,6 +104,9 @@ export class RTCRtpSender {
104
104
  }
105
105
  });
106
106
  if (trackOrKind instanceof MediaStreamTrack) {
107
+ if (trackOrKind.streamId) {
108
+ this.streamId = trackOrKind.streamId;
109
+ }
107
110
  this.registerTrack(trackOrKind);
108
111
  }
109
112
  }
@@ -149,6 +152,10 @@ export class RTCRtpSender {
149
152
  if (this.codec) {
150
153
  track.codec = this.codec;
151
154
  }
155
+
156
+ track.onSourceChanged.subscribe((header) => {
157
+ this.replaceRTP(header);
158
+ });
152
159
  }
153
160
 
154
161
  async replaceTrack(track: MediaStreamTrack | null) {
@@ -167,7 +174,7 @@ export class RTCRtpSender {
167
174
  }
168
175
 
169
176
  this.registerTrack(track);
170
- log("replaceTrack", track.ssrc, track.rid);
177
+ log("replaceTrack", "ssrc", track.ssrc, "rid", track.rid);
171
178
  }
172
179
 
173
180
  stop() {
@@ -199,7 +206,7 @@ export class RTCRtpSender {
199
206
  }),
200
207
  }),
201
208
  ];
202
- this.lsr = (this.ntpTimestamp >> 16n) & 0xffffffffn;
209
+ this.lsr = compactNtp(this.ntpTimestamp);
203
210
  this.lsrTime = Date.now() / 1000;
204
211
 
205
212
  if (this.cname) {
@@ -227,7 +234,10 @@ export class RTCRtpSender {
227
234
  } catch (error) {}
228
235
  }
229
236
 
230
- private replaceRTP({ sequenceNumber, timestamp }: RtpHeader) {
237
+ replaceRTP({
238
+ sequenceNumber,
239
+ timestamp,
240
+ }: Pick<RtpHeader, "sequenceNumber" | "timestamp">) {
231
241
  if (this.sequenceNumber != undefined) {
232
242
  this.seqOffset = uint16Add(this.sequenceNumber, -sequenceNumber);
233
243
  }
@@ -330,7 +340,7 @@ export class RTCRtpSender {
330
340
  packet.reports
331
341
  .filter((report) => report.ssrc === this.ssrc)
332
342
  .forEach((report) => {
333
- if (this.lsr === BigInt(report.lsr) && report.dlsr) {
343
+ if (this.lsr === report.lsr && report.dlsr) {
334
344
  const rtt =
335
345
  Date.now() / 1000 - this.lsrTime - report.dlsr / 65536;
336
346
  if (this.rtt === undefined) {
File without changes
@@ -8,6 +8,8 @@ import { RTCRtpCodecParameters } from "./parameters";
8
8
 
9
9
  export class MediaStreamTrack extends EventTarget {
10
10
  readonly uuid = v4();
11
+ /**MediaStream ID*/
12
+ streamId?: string;
11
13
  remote = false;
12
14
  label: string;
13
15
  kind!: Kind;
@@ -21,6 +23,9 @@ export class MediaStreamTrack extends EventTarget {
21
23
  enabled = true;
22
24
 
23
25
  readonly onReceiveRtp = new Event<[RtpPacket]>();
26
+ readonly onSourceChanged = new Event<
27
+ [Pick<RtpHeader, "sequenceNumber" | "timestamp">]
28
+ >();
24
29
 
25
30
  stopped = false;
26
31
  muted = true;
@@ -64,6 +69,7 @@ export class MediaStream {
64
69
  }
65
70
 
66
71
  addTrack(track: MediaStreamTrack) {
72
+ track.streamId = this.id;
67
73
  this.tracks.push(track);
68
74
  }
69
75
 
@@ -0,0 +1,47 @@
1
+ import { debug } from "debug";
2
+
3
+ import { uint16Add } from "../../../common/src";
4
+ import { RtpPacket } from "../../../rtp/src";
5
+
6
+ const log = debug("werift:packages/webrtc/src/nonstandard/jitterBuffer.ts");
7
+
8
+ export class JitterBuffer {
9
+ static MaxRetry = 100;
10
+ retry = 0;
11
+ head?: number;
12
+ buffer: { [sequenceNumber: number]: RtpPacket } = {};
13
+
14
+ constructor(public maxRetry = JitterBuffer.MaxRetry) {}
15
+
16
+ push(p: RtpPacket) {
17
+ this.buffer[p.header.sequenceNumber] = p;
18
+
19
+ if (this.head == undefined) {
20
+ this.head = p.header.sequenceNumber;
21
+ } else if (p.header.sequenceNumber != uint16Add(this.head, 1)) {
22
+ if (this.retry++ >= this.maxRetry) {
23
+ log("give up packet lost");
24
+ this.head = uint16Add(this.head, 2);
25
+ } else {
26
+ return [];
27
+ }
28
+ } else {
29
+ this.head = uint16Add(this.head, 1);
30
+ }
31
+
32
+ const packets: RtpPacket[] = [];
33
+ let tail = this.head;
34
+ for (; ; tail = uint16Add(tail, 1)) {
35
+ const p = this.buffer[tail];
36
+ if (p) {
37
+ packets.push(p);
38
+ delete this.buffer[tail];
39
+ } else {
40
+ break;
41
+ }
42
+ }
43
+ this.head = uint16Add(tail, -1);
44
+
45
+ return packets;
46
+ }
47
+ }
@@ -0,0 +1,55 @@
1
+ import { bufferReader, bufferWriter } from "../../../common/src";
2
+ import { RtcpSrPacket, RtpPacket } from "../../../rtp/src";
3
+
4
+ export class LipSync {
5
+ baseNtpTimestamp?: bigint;
6
+ baseRtpTimestamp?: number;
7
+
8
+ constructor(public clockRate: number) {}
9
+
10
+ srReceived(sr: RtcpSrPacket) {
11
+ const { ntpTimestamp, rtpTimestamp } = sr.senderInfo;
12
+ this.baseNtpTimestamp = ntpTimestamp;
13
+ this.baseRtpTimestamp = rtpTimestamp;
14
+ }
15
+
16
+ calcNtpTime(rtpTimestamp: number) {
17
+ if (!this.baseRtpTimestamp || !this.baseNtpTimestamp) {
18
+ return 0;
19
+ }
20
+
21
+ // base rtpTimestamp is rollover
22
+ if (rtpTimestamp - this.baseRtpTimestamp > Max32bit - this.clockRate * 60) {
23
+ this.baseRtpTimestamp += Max32bit;
24
+ }
25
+ // target rtpTimestamp is rollover
26
+ else if (
27
+ rtpTimestamp + (Max32bit - this.clockRate * 60) - this.baseRtpTimestamp <
28
+ 0
29
+ ) {
30
+ rtpTimestamp += Max32bit;
31
+ }
32
+
33
+ const elapsed = (rtpTimestamp - this.baseRtpTimestamp) / this.clockRate;
34
+
35
+ return ntpTime2Time(this.baseNtpTimestamp) + elapsed;
36
+ }
37
+ }
38
+
39
+ export const ntpTime2Time = (ntp: bigint) => {
40
+ const [ntpSec, ntpMsec] = bufferReader(bufferWriter([8], [ntp]), [4, 4]);
41
+
42
+ return Number(`${ntpSec}.${ntpMsec}`);
43
+ };
44
+
45
+ /**4294967295 */
46
+ export const Max32bit = Number((0x01n << 32n) - 1n);
47
+
48
+ export interface BufferResolve {
49
+ packets: {
50
+ packet: RtpPacket;
51
+ offset: number;
52
+ }[];
53
+ /**NTP seconds */
54
+ startAtNtpTime: number;
55
+ }
@@ -0,0 +1,26 @@
1
+ import { MediaStreamTrack } from "../media/track";
2
+ import { WebmFactory } from "./webm";
3
+
4
+ export class MediaRecorder {
5
+ webm?: WebmFactory;
6
+
7
+ constructor(
8
+ public tracks: MediaStreamTrack[],
9
+ public path: string,
10
+ public options: Partial<{ width: number; height: number }> = {}
11
+ ) {}
12
+
13
+ addTrack(track: MediaStreamTrack) {
14
+ this.tracks.push(track);
15
+ }
16
+
17
+ async start() {
18
+ this.webm = new WebmFactory(this.tracks, this.path, this.options);
19
+ await this.webm.start();
20
+ }
21
+
22
+ async stop() {
23
+ if (!this.webm) throw new Error();
24
+ await this.webm.stop();
25
+ }
26
+ }
@@ -0,0 +1,71 @@
1
+ import { debug } from "debug";
2
+
3
+ import { int } from "../../../common/src";
4
+ import { DePacketizerBase, RtpPacket } from "../../../rtp/src";
5
+ import { enumerate } from "../helper";
6
+ import { JitterBuffer } from "./jitterBuffer";
7
+
8
+ const log = debug("werift:packages/webrtc/src/nonstandard/sampleBuilder.ts");
9
+
10
+ export class SampleBuilder {
11
+ private readonly jitterBuffer = new JitterBuffer();
12
+ private buffer: RtpPacket[] = [];
13
+ private baseTimestamp?: number;
14
+ relativeTimestamp = 0;
15
+
16
+ constructor(
17
+ readonly DePacketizer: typeof DePacketizerBase,
18
+ public clockRate: number
19
+ ) {}
20
+
21
+ push(p: RtpPacket) {
22
+ const buf = this.jitterBuffer.push(p);
23
+ this.buffer = [...this.buffer, ...buf];
24
+ }
25
+
26
+ resetTimestamp() {
27
+ this.baseTimestamp = undefined;
28
+ this.relativeTimestamp = 0;
29
+ }
30
+
31
+ build() {
32
+ let tail: number | undefined;
33
+ for (const [i, p] of enumerate(this.buffer)) {
34
+ if (this.DePacketizer.isDetectedFinalPacketInSequence(p.header)) {
35
+ tail = i;
36
+ break;
37
+ }
38
+ }
39
+
40
+ if (tail == undefined) return;
41
+ if (this.baseTimestamp == undefined) {
42
+ this.baseTimestamp = this.buffer[tail].header.timestamp;
43
+ }
44
+
45
+ const tailTimestamp = this.buffer[tail].header.timestamp;
46
+ const rotate =
47
+ Math.abs(tailTimestamp - this.baseTimestamp) > (Max32Uint / 4) * 3;
48
+ if (rotate) log({ rotate }, tailTimestamp, this.baseTimestamp);
49
+
50
+ const elapsed = rotate
51
+ ? tailTimestamp + Max32Uint - this.baseTimestamp
52
+ : tailTimestamp - this.baseTimestamp;
53
+
54
+ const relativeTimestamp = int((elapsed / this.clockRate) * 1000);
55
+ this.relativeTimestamp = relativeTimestamp;
56
+
57
+ const frames = this.buffer.slice(0, tail + 1).map((p) => {
58
+ const frame = this.DePacketizer.deSerialize(p.payload);
59
+ return frame;
60
+ });
61
+ const isKeyframe = !!frames.find((f) => f.isKeyframe);
62
+ const data = Buffer.concat(frames.map((f) => f.payload));
63
+
64
+ this.buffer = this.buffer.slice(tail + 1);
65
+
66
+ return { data, relativeTimestamp, isKeyframe };
67
+ }
68
+ }
69
+
70
+ /**4294967295 */
71
+ const Max32Uint = Number(0x01n << 32n) - 1;
@@ -0,0 +1,74 @@
1
+ import { exec } from "child_process";
2
+ import { createSocket } from "dgram";
3
+ import { setImmediate } from "timers/promises";
4
+ import { v4 } from "uuid";
5
+
6
+ import { randomPort } from "../../../ice/src";
7
+ import { RtpPacket } from "../../../rtp/src";
8
+ import { MediaStreamTrack } from "../media/track";
9
+
10
+ export const getUserMp4 = async (path: string, loop?: boolean) => {
11
+ const audioPort = await randomPort();
12
+ const videoPort = await randomPort();
13
+
14
+ return new MediaMp4(audioPort, videoPort, path, loop);
15
+ };
16
+
17
+ class MediaMp4 {
18
+ private streamId = v4();
19
+ audio = new MediaStreamTrack({ kind: "audio", streamId: this.streamId });
20
+ video = new MediaStreamTrack({ kind: "video", streamId: this.streamId });
21
+
22
+ constructor(
23
+ private videoPort: number,
24
+ private audioPort: number,
25
+ private path: string,
26
+ private loop?: boolean
27
+ ) {
28
+ this.setupTrack(audioPort, this.audio);
29
+ this.setupTrack(videoPort, this.video);
30
+ }
31
+
32
+ private setupTrack = (port: number, track: MediaStreamTrack) => {
33
+ let payloadType = 0;
34
+
35
+ const socket = createSocket("udp4");
36
+ socket.bind(port);
37
+ socket.on("message", async (buf) => {
38
+ const rtp = RtpPacket.deSerialize(buf);
39
+ if (!payloadType) {
40
+ payloadType = rtp.header.payloadType;
41
+ }
42
+
43
+ // detect gStreamer restarted
44
+ if (payloadType !== rtp.header.payloadType) {
45
+ payloadType = rtp.header.payloadType;
46
+ track.onSourceChanged.execute(rtp.header);
47
+ }
48
+
49
+ track.writeRtp(buf);
50
+ });
51
+ };
52
+
53
+ async start() {
54
+ let payloadType = 96;
55
+ const run = async () => {
56
+ if (payloadType > 100) payloadType = 96;
57
+
58
+ const cmd = `gst-launch-1.0 filesrc location= ${this.path} ! \
59
+ qtdemux name=d ! \
60
+ queue ! h264parse ! rtph264pay config-interval=10 pt=${payloadType++} ! \
61
+ udpsink host=127.0.0.1 port=${this.videoPort} d. ! \
62
+ queue ! aacparse ! avdec_aac ! audioresample ! audioconvert ! opusenc ! rtpopuspay pt=${payloadType++} ! \
63
+ udpsink host=127.0.0.1 port=${this.audioPort}`;
64
+ const process = exec(cmd);
65
+
66
+ if (this.loop) {
67
+ await new Promise((r) => process.on("close", r));
68
+ run();
69
+ }
70
+ };
71
+ await setImmediate();
72
+ run();
73
+ }
74
+ }