werift 0.18.3 → 0.18.4

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 (97) hide show
  1. package/lib/dtls/src/flight/server/flight2.js +1 -1
  2. package/lib/dtls/src/flight/server/flight2.js.map +1 -1
  3. package/lib/rtp/src/container/ebml/ebml.d.ts +5 -6
  4. package/lib/rtp/src/container/ebml/ebml.js +14 -13
  5. package/lib/rtp/src/container/ebml/ebml.js.map +1 -1
  6. package/lib/rtp/src/container/ebml/typedArrayUtils.d.ts +3 -4
  7. package/lib/rtp/src/container/ebml/typedArrayUtils.js +9 -10
  8. package/lib/rtp/src/container/ebml/typedArrayUtils.js.map +1 -1
  9. package/lib/rtp/src/container/index.d.ts +2 -0
  10. package/lib/rtp/src/{processor/source → container}/index.js +2 -3
  11. package/lib/rtp/src/container/index.js.map +1 -0
  12. package/lib/rtp/src/helper.d.ts +4 -0
  13. package/lib/rtp/src/helper.js +14 -1
  14. package/lib/rtp/src/helper.js.map +1 -1
  15. package/lib/rtp/src/index.d.ts +2 -0
  16. package/lib/rtp/src/index.js +2 -0
  17. package/lib/rtp/src/index.js.map +1 -1
  18. package/lib/rtp/src/processor/depacketizer.d.ts +1 -1
  19. package/lib/rtp/src/processor/depacketizer.js +16 -9
  20. package/lib/rtp/src/processor/depacketizer.js.map +1 -1
  21. package/lib/rtp/src/processor/depacketizerCallback.d.ts +14 -6
  22. package/lib/rtp/src/processor/depacketizerCallback.js +2 -35
  23. package/lib/rtp/src/processor/depacketizerCallback.js.map +1 -1
  24. package/lib/rtp/src/processor/dtx.d.ts +1 -0
  25. package/lib/rtp/src/processor/dtx.js +10 -1
  26. package/lib/rtp/src/processor/dtx.js.map +1 -1
  27. package/lib/rtp/src/processor/dtxCallback.d.ts +14 -5
  28. package/lib/rtp/src/processor/dtxCallback.js +2 -35
  29. package/lib/rtp/src/processor/dtxCallback.js.map +1 -1
  30. package/lib/rtp/src/processor/index.d.ts +3 -1
  31. package/lib/rtp/src/processor/index.js +3 -1
  32. package/lib/rtp/src/processor/index.js.map +1 -1
  33. package/lib/rtp/src/processor/interface.d.ts +17 -0
  34. package/lib/rtp/src/processor/interface.js +57 -0
  35. package/lib/rtp/src/processor/interface.js.map +1 -1
  36. package/lib/rtp/src/processor/jitterBuffer.d.ts +1 -2
  37. package/lib/rtp/src/processor/jitterBuffer.js +3 -1
  38. package/lib/rtp/src/processor/jitterBuffer.js.map +1 -1
  39. package/lib/rtp/src/processor/jitterBufferCallback.d.ts +14 -5
  40. package/lib/rtp/src/processor/jitterBufferCallback.js +2 -35
  41. package/lib/rtp/src/processor/jitterBufferCallback.js.map +1 -1
  42. package/lib/rtp/src/processor/jitterBufferTransformer.d.ts +1 -1
  43. package/lib/rtp/src/processor/lipsync.d.ts +19 -8
  44. package/lib/rtp/src/processor/lipsync.js +131 -83
  45. package/lib/rtp/src/processor/lipsync.js.map +1 -1
  46. package/lib/rtp/src/processor/lipsyncCallback.d.ts +8 -5
  47. package/lib/rtp/src/processor/lipsyncCallback.js +39 -4
  48. package/lib/rtp/src/processor/lipsyncCallback.js.map +1 -1
  49. package/lib/rtp/src/processor/mute.d.ts +17 -4
  50. package/lib/rtp/src/processor/mute.js +121 -40
  51. package/lib/rtp/src/processor/mute.js.map +1 -1
  52. package/lib/rtp/src/processor/muteCallback.d.ts +5 -2
  53. package/lib/rtp/src/processor/muteCallback.js +23 -7
  54. package/lib/rtp/src/processor/muteCallback.js.map +1 -1
  55. package/lib/rtp/src/processor/nack.d.ts +6 -6
  56. package/lib/rtp/src/processor/nack.js +23 -17
  57. package/lib/rtp/src/processor/nack.js.map +1 -1
  58. package/lib/rtp/src/processor/nackHandlerCallback.d.ts +14 -7
  59. package/lib/rtp/src/processor/nackHandlerCallback.js +2 -29
  60. package/lib/rtp/src/processor/nackHandlerCallback.js.map +1 -1
  61. package/lib/rtp/src/processor/ntpTime.d.ts +7 -7
  62. package/lib/rtp/src/processor/ntpTime.js +27 -29
  63. package/lib/rtp/src/processor/ntpTime.js.map +1 -1
  64. package/lib/rtp/src/processor/ntpTimeCallback.d.ts +13 -4
  65. package/lib/rtp/src/processor/ntpTimeCallback.js +2 -29
  66. package/lib/rtp/src/processor/ntpTimeCallback.js.map +1 -1
  67. package/lib/rtp/src/processor/rtcpCallback.d.ts +18 -0
  68. package/lib/rtp/src/processor/{source/rtcpCallback.js → rtcpCallback.js} +25 -3
  69. package/lib/rtp/src/processor/rtcpCallback.js.map +1 -0
  70. package/lib/rtp/src/processor/rtpCallback.d.ts +28 -0
  71. package/lib/rtp/src/processor/rtpCallback.js +125 -0
  72. package/lib/rtp/src/processor/rtpCallback.js.map +1 -0
  73. package/lib/rtp/src/processor/{source/rtpStream.d.ts → rtpStream.d.ts} +1 -1
  74. package/lib/rtp/src/processor/{source/rtpStream.js → rtpStream.js} +1 -1
  75. package/lib/rtp/src/processor/rtpStream.js.map +1 -0
  76. package/lib/rtp/src/processor/rtpTimeCallback.d.ts +13 -5
  77. package/lib/rtp/src/processor/rtpTimeCallback.js +2 -29
  78. package/lib/rtp/src/processor/rtpTimeCallback.js.map +1 -1
  79. package/lib/rtp/src/processor/webm.d.ts +8 -4
  80. package/lib/rtp/src/processor/webm.js +41 -8
  81. package/lib/rtp/src/processor/webm.js.map +1 -1
  82. package/lib/rtp/src/processor/webmCallback.d.ts +6 -5
  83. package/lib/rtp/src/processor/webmCallback.js +21 -7
  84. package/lib/rtp/src/processor/webmCallback.js.map +1 -1
  85. package/lib/webrtc/src/nonstandard/userMedia.d.ts +32 -23
  86. package/lib/webrtc/src/nonstandard/userMedia.js +49 -131
  87. package/lib/webrtc/src/nonstandard/userMedia.js.map +1 -1
  88. package/package.json +1 -1
  89. package/src/nonstandard/userMedia.ts +69 -75
  90. package/lib/rtp/src/processor/source/index.d.ts +0 -3
  91. package/lib/rtp/src/processor/source/index.js.map +0 -1
  92. package/lib/rtp/src/processor/source/rtcpCallback.d.ts +0 -13
  93. package/lib/rtp/src/processor/source/rtcpCallback.js.map +0 -1
  94. package/lib/rtp/src/processor/source/rtpCallback.d.ts +0 -19
  95. package/lib/rtp/src/processor/source/rtpCallback.js +0 -62
  96. package/lib/rtp/src/processor/source/rtpCallback.js.map +0 -1
  97. package/lib/rtp/src/processor/source/rtpStream.js.map +0 -1
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MuteHandlerBase = void 0;
4
4
  const crypto_1 = require("crypto");
5
+ const __1 = require("..");
5
6
  class MuteHandlerBase {
6
7
  constructor(output, props) {
7
8
  Object.defineProperty(this, "output", {
@@ -26,13 +27,13 @@ class MuteHandlerBase {
26
27
  enumerable: true,
27
28
  configurable: true,
28
29
  writable: true,
29
- value: []
30
+ value: void 0
30
31
  });
31
- Object.defineProperty(this, "started", {
32
+ Object.defineProperty(this, "index", {
32
33
  enumerable: true,
33
34
  configurable: true,
34
35
  writable: true,
35
- value: false
36
+ value: 0
36
37
  });
37
38
  Object.defineProperty(this, "ended", {
38
39
  enumerable: true,
@@ -40,7 +41,7 @@ class MuteHandlerBase {
40
41
  writable: true,
41
42
  value: false
42
43
  });
43
- Object.defineProperty(this, "intervalId", {
44
+ Object.defineProperty(this, "baseTime", {
44
45
  enumerable: true,
45
46
  configurable: true,
46
47
  writable: true,
@@ -52,60 +53,140 @@ class MuteHandlerBase {
52
53
  writable: true,
53
54
  value: void 0
54
55
  });
56
+ Object.defineProperty(this, "internalStats", {
57
+ enumerable: true,
58
+ configurable: true,
59
+ writable: true,
60
+ value: {}
61
+ });
62
+ /**ms */
63
+ Object.defineProperty(this, "lastCommittedTime", {
64
+ enumerable: true,
65
+ configurable: true,
66
+ writable: true,
67
+ value: 0
68
+ });
69
+ Object.defineProperty(this, "lastExecutionTime", {
70
+ enumerable: true,
71
+ configurable: true,
72
+ writable: true,
73
+ value: 0
74
+ });
75
+ /**ms */
76
+ Object.defineProperty(this, "interval", {
77
+ enumerable: true,
78
+ configurable: true,
79
+ writable: true,
80
+ value: this.props.interval
81
+ });
82
+ Object.defineProperty(this, "bufferDuration", {
83
+ enumerable: true,
84
+ configurable: true,
85
+ writable: true,
86
+ value: this.interval / 2
87
+ });
88
+ Object.defineProperty(this, "bufferLength", {
89
+ enumerable: true,
90
+ configurable: true,
91
+ writable: true,
92
+ value: this.props.bufferLength * 2
93
+ });
94
+ /**ms */
95
+ Object.defineProperty(this, "lastFrameReceivedAt", {
96
+ enumerable: true,
97
+ configurable: true,
98
+ writable: true,
99
+ value: 0
100
+ });
55
101
  Object.defineProperty(this, "processInput", {
56
102
  enumerable: true,
57
103
  configurable: true,
58
104
  writable: true,
59
105
  value: ({ frame, eol }) => {
60
- if (eol) {
106
+ if (!frame) {
61
107
  this.stop();
62
- return [{ eol: true }];
108
+ return [{ eol }];
109
+ }
110
+ if (this.ended) {
111
+ return [];
63
112
  }
64
- if (frame) {
65
- this.startIfNeed(frame.time);
66
- if (frame.time >= this.currentTimestamp) {
67
- this.buffer.push(frame);
113
+ if (this.baseTime == undefined) {
114
+ this.baseTime = frame.time;
115
+ this.currentTimestamp = this.baseTime;
116
+ this.lastExecutionTime = this.baseTime;
117
+ this.lastCommittedTime = this.baseTime;
118
+ this.lastFrameReceivedAt = Date.now();
119
+ }
120
+ // 過去のフレームを捨てる
121
+ if (frame.time < this.lastCommittedTime) {
122
+ return [];
123
+ }
124
+ // NTPの同期ずれが疑われるので捨てる
125
+ const now = Date.now();
126
+ const gap = 5000; // RTCP SR interval;
127
+ const lastCommittedElapsed = frame.time - this.lastCommittedTime;
128
+ const lastFrameReceivedElapsed = now - this.lastFrameReceivedAt;
129
+ if (gap < lastFrameReceivedElapsed && lastCommittedElapsed < gap) {
130
+ this.internalStats["invalidFrameTime"] = {
131
+ count: (this.internalStats["invalidFrameTime"]?.count ?? 0) + 1,
132
+ at: new Date().toISOString(),
133
+ lastCommittedElapsed,
134
+ lastFrameReceivedElapsed,
135
+ };
136
+ return [];
137
+ }
138
+ this.lastFrameReceivedAt = now;
139
+ const elapsed = frame.time - this.baseTime;
140
+ const index = (0, __1.int)(elapsed / this.bufferDuration) % this.bufferLength;
141
+ this.buffer[index].push(frame);
142
+ const lastExecution = frame.time - this.lastExecutionTime;
143
+ if (lastExecution >= this.interval) {
144
+ const times = (0, __1.int)(lastExecution / this.bufferDuration) - 1;
145
+ this.lastExecutionTime = this.currentTimestamp;
146
+ for (let i = 0; i < times; i++) {
147
+ this.executeTask();
148
+ this.lastExecutionTime += this.bufferDuration;
68
149
  }
69
150
  }
70
151
  return [];
71
152
  }
72
153
  });
154
+ this.buffer = [...new Array(this.bufferLength)].map(() => []);
73
155
  }
74
156
  toJSON() {
75
- return { id: this.id };
157
+ return { ...this.internalStats, id: this.id };
76
158
  }
77
- startIfNeed(baseTimestamp) {
78
- if (this.started) {
79
- return;
80
- }
81
- this.started = true;
82
- const { sort, interval, ptime, dummyPacket } = this.props;
83
- this.currentTimestamp = baseTimestamp;
84
- this.intervalId = setInterval(() => {
85
- if (this.ended) {
86
- return;
87
- }
88
- if (sort ?? true) {
89
- this.buffer = this.buffer.sort((a, b) => a.time - b.time);
159
+ executeTask() {
160
+ const { ptime, dummyPacket } = this.props;
161
+ const buffer = this.buffer[this.index].sort((a, b) => a.time - b.time);
162
+ const last = buffer.at(-1);
163
+ const expect = last
164
+ ? last.time +
165
+ // offset
166
+ ptime
167
+ : this.currentTimestamp;
168
+ if (expect < this.currentTimestamp + this.bufferDuration) {
169
+ for (let time = expect; time < this.currentTimestamp + this.bufferDuration; time += ptime) {
170
+ buffer.push({
171
+ time,
172
+ data: dummyPacket,
173
+ isKeyframe: true,
174
+ });
90
175
  }
91
- const last = this.buffer.at(-1);
92
- const expect = last ? last.time + ptime : this.currentTimestamp;
93
- if (expect < this.currentTimestamp + interval) {
94
- for (let time = expect; time < this.currentTimestamp + interval; time += ptime) {
95
- this.buffer.push({
96
- time,
97
- data: dummyPacket,
98
- isKeyframe: true,
99
- });
100
- }
101
- }
102
- this.buffer.forEach((frame) => this.output({ frame }));
103
- this.buffer = [];
104
- this.currentTimestamp += interval;
105
- }, interval);
176
+ }
177
+ this.currentTimestamp += this.bufferDuration;
178
+ this.internalStats["mute"] = new Date().toISOString();
179
+ this.buffer[this.index] = [];
180
+ buffer.forEach((frame) => {
181
+ this.output({ frame });
182
+ this.lastCommittedTime = frame.time;
183
+ });
184
+ this.index++;
185
+ if (this.index === this.bufferLength) {
186
+ this.index = 0;
187
+ }
106
188
  }
107
189
  stop() {
108
- clearInterval(this.intervalId);
109
190
  this.ended = true;
110
191
  this.buffer = [];
111
192
  this.output = undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"mute.js","sourceRoot":"","sources":["../../../../../rtp/src/processor/mute.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"crypto\";\n\nimport { CodecFrame, DepacketizerOutput } from \"./depacketizer\";\nimport { Processor } from \"./interface\";\n\nexport type MuteInput = DepacketizerOutput;\n\nexport type MuteOutput = MuteInput;\n\nexport class MuteHandlerBase implements Processor<MuteInput, MuteOutput> {\n readonly id = randomUUID();\n private buffer: CodecFrame[] = [];\n private started = false;\n private ended = false;\n private intervalId: any;\n private currentTimestamp!: number;\n\n constructor(\n private output: (o: MuteOutput) => void,\n private props: {\n ptime: number;\n dummyPacket: Buffer;\n interval: number;\n sort?: boolean;\n }\n ) {}\n\n toJSON(): Record<string, any> {\n return { id: this.id };\n }\n\n private startIfNeed(baseTimestamp: number) {\n if (this.started) {\n return;\n }\n this.started = true;\n\n const { sort, interval, ptime, dummyPacket } = this.props;\n this.currentTimestamp = baseTimestamp;\n this.intervalId = setInterval(() => {\n if (this.ended) {\n return;\n }\n\n if (sort ?? true) {\n this.buffer = this.buffer.sort((a, b) => a.time - b.time);\n }\n const last = this.buffer.at(-1);\n const expect = last ? last.time + ptime : this.currentTimestamp;\n if (expect < this.currentTimestamp + interval) {\n for (\n let time = expect;\n time < this.currentTimestamp + interval;\n time += ptime\n ) {\n this.buffer.push({\n time,\n data: dummyPacket,\n isKeyframe: true,\n });\n }\n }\n this.buffer.forEach((frame) => this.output({ frame }));\n this.buffer = [];\n\n this.currentTimestamp += interval;\n }, interval);\n }\n\n private stop() {\n clearInterval(this.intervalId);\n this.ended = true;\n this.buffer = [];\n this.output = undefined as any;\n }\n\n processInput = ({ frame, eol }: MuteInput): MuteOutput[] => {\n if (eol) {\n this.stop();\n return [{ eol: true }];\n }\n\n if (frame) {\n this.startIfNeed(frame.time);\n if (frame.time >= this.currentTimestamp) {\n this.buffer.push(frame);\n }\n }\n\n return [];\n };\n}\n"]}
1
+ {"version":3,"file":"mute.js","sourceRoot":"","sources":["../../../../../rtp/src/processor/mute.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"crypto\";\n\nimport { int } from \"..\";\nimport { CodecFrame, DepacketizerOutput } from \"./depacketizer\";\nimport { Processor } from \"./interface\";\n\nexport type MuteInput = DepacketizerOutput;\n\nexport type MuteOutput = MuteInput;\n\nexport class MuteHandlerBase implements Processor<MuteInput, MuteOutput> {\n readonly id = randomUUID();\n private buffer: CodecFrame[][];\n private index = 0;\n private ended = false;\n private baseTime?: number;\n private currentTimestamp!: number;\n private internalStats = {};\n /**ms */\n private lastCommittedTime = 0;\n private lastExecutionTime = 0;\n /**ms */\n private interval = this.props.interval;\n private bufferDuration: number = this.interval / 2;\n private bufferLength = this.props.bufferLength * 2;\n /**ms */\n private lastFrameReceivedAt = 0;\n\n constructor(\n private output: (o: MuteOutput) => void,\n private props: {\n ptime: number;\n dummyPacket: Buffer;\n /**ms\n * @description intervalごとに無音区間に空パケットを挿入する\n */\n interval: number;\n bufferLength: number;\n }\n ) {\n this.buffer = [...new Array(this.bufferLength)].map(() => []);\n }\n\n toJSON(): Record<string, any> {\n return { ...this.internalStats, id: this.id };\n }\n\n private executeTask() {\n const { ptime, dummyPacket } = this.props;\n\n const buffer = this.buffer[this.index].sort((a, b) => a.time - b.time);\n const last = buffer.at(-1);\n const expect = last\n ? last.time +\n // offset\n ptime\n : this.currentTimestamp;\n\n if (expect < this.currentTimestamp + this.bufferDuration) {\n for (\n let time = expect;\n time < this.currentTimestamp + this.bufferDuration;\n time += ptime\n ) {\n buffer.push({\n time,\n data: dummyPacket,\n isKeyframe: true,\n });\n }\n }\n this.currentTimestamp += this.bufferDuration;\n this.internalStats[\"mute\"] = new Date().toISOString();\n\n this.buffer[this.index] = [];\n buffer.forEach((frame) => {\n this.output({ frame });\n this.lastCommittedTime = frame.time;\n });\n\n this.index++;\n if (this.index === this.bufferLength) {\n this.index = 0;\n }\n }\n\n private stop() {\n this.ended = true;\n this.buffer = [];\n this.output = undefined as any;\n }\n\n processInput = ({ frame, eol }: MuteInput): MuteOutput[] => {\n if (!frame) {\n this.stop();\n return [{ eol }];\n }\n\n if (this.ended) {\n return [];\n }\n\n if (this.baseTime == undefined) {\n this.baseTime = frame.time;\n this.currentTimestamp = this.baseTime;\n this.lastExecutionTime = this.baseTime;\n this.lastCommittedTime = this.baseTime;\n this.lastFrameReceivedAt = Date.now();\n }\n\n // 過去のフレームを捨てる\n if (frame.time < this.lastCommittedTime) {\n return [];\n }\n\n // NTPの同期ずれが疑われるので捨てる\n const now = Date.now();\n const gap = 5000; // RTCP SR interval;\n const lastCommittedElapsed = frame.time - this.lastCommittedTime;\n const lastFrameReceivedElapsed = now - this.lastFrameReceivedAt;\n if (gap < lastFrameReceivedElapsed && lastCommittedElapsed < gap) {\n this.internalStats[\"invalidFrameTime\"] = {\n count: (this.internalStats[\"invalidFrameTime\"]?.count ?? 0) + 1,\n at: new Date().toISOString(),\n lastCommittedElapsed,\n lastFrameReceivedElapsed,\n };\n return [];\n }\n this.lastFrameReceivedAt = now;\n\n const elapsed = frame.time - this.baseTime;\n const index = int(elapsed / this.bufferDuration) % this.bufferLength;\n this.buffer[index].push(frame);\n\n const lastExecution = frame.time - this.lastExecutionTime;\n if (lastExecution >= this.interval) {\n const times = int(lastExecution / this.bufferDuration) - 1;\n this.lastExecutionTime = this.currentTimestamp;\n for (let i = 0; i < times; i++) {\n this.executeTask();\n this.lastExecutionTime += this.bufferDuration;\n }\n }\n\n return [];\n };\n}\n"]}
@@ -1,7 +1,10 @@
1
+ import { SimpleProcessorCallback } from "./interface";
1
2
  import { MuteHandlerBase, MuteInput, MuteOutput } from "./mute";
2
- export declare class MuteCallback extends MuteHandlerBase {
3
+ export declare class MuteCallback extends MuteHandlerBase implements SimpleProcessorCallback<MuteInput, MuteOutput> {
3
4
  private cb?;
5
+ destructor?: () => void;
4
6
  constructor(props: ConstructorParameters<typeof MuteHandlerBase>[1]);
5
- pipe: (cb: (input: MuteOutput) => void) => void;
7
+ pipe: (cb: (input: MuteOutput) => void, destructor?: () => void) => this;
6
8
  input: (input: MuteInput) => void;
9
+ destroy: () => void;
7
10
  }
@@ -15,12 +15,20 @@ class MuteCallback extends mute_1.MuteHandlerBase {
15
15
  writable: true,
16
16
  value: void 0
17
17
  });
18
+ Object.defineProperty(this, "destructor", {
19
+ enumerable: true,
20
+ configurable: true,
21
+ writable: true,
22
+ value: void 0
23
+ });
18
24
  Object.defineProperty(this, "pipe", {
19
25
  enumerable: true,
20
26
  configurable: true,
21
27
  writable: true,
22
- value: (cb) => {
28
+ value: (cb, destructor) => {
23
29
  this.cb = cb;
30
+ this.destructor = destructor;
31
+ return this;
24
32
  }
25
33
  });
26
34
  Object.defineProperty(this, "input", {
@@ -28,15 +36,23 @@ class MuteCallback extends mute_1.MuteHandlerBase {
28
36
  configurable: true,
29
37
  writable: true,
30
38
  value: (input) => {
31
- if (!this.cb) {
32
- return;
33
- }
34
39
  for (const output of this.processInput(input)) {
35
- this.cb(output);
40
+ if (this.cb) {
41
+ this.cb(output);
42
+ }
36
43
  }
37
- if (input.eol) {
38
- this.cb = undefined;
44
+ }
45
+ });
46
+ Object.defineProperty(this, "destroy", {
47
+ enumerable: true,
48
+ configurable: true,
49
+ writable: true,
50
+ value: () => {
51
+ if (this.destructor) {
52
+ this.destructor();
53
+ this.destructor = undefined;
39
54
  }
55
+ this.cb = undefined;
40
56
  }
41
57
  });
42
58
  }
@@ -1 +1 @@
1
- {"version":3,"file":"muteCallback.js","sourceRoot":"","sources":["../../../../../rtp/src/processor/muteCallback.ts"],"names":[],"mappings":";;;AAAA,iCAAgE;AAEhE,MAAa,YAAa,SAAQ,sBAAe;IAG/C,YAAY,KAAuD;QACjE,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;YACV,IAAI,IAAI,CAAC,EAAE,EAAE;gBACX,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;aACZ;QACH,CAAC,EAAE,KAAK,CAAC,CAAC;QAPZ;;;;;WAAyC;QAUzC;;;;mBAAO,CAAC,EAA+B,EAAE,EAAE;gBACzC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;YACf,CAAC;WAAC;QAEF;;;;mBAAQ,CAAC,KAAgB,EAAE,EAAE;gBAC3B,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE;oBACZ,OAAO;iBACR;gBACD,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE;oBAC7C,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;iBACjB;gBACD,IAAI,KAAK,CAAC,GAAG,EAAE;oBACb,IAAI,CAAC,EAAE,GAAG,SAAS,CAAC;iBACrB;YACH,CAAC;WAAC;IAhBF,CAAC;CAiBF;AA1BD,oCA0BC","sourcesContent":["import { MuteHandlerBase, MuteInput, MuteOutput } from \"./mute\";\n\nexport class MuteCallback extends MuteHandlerBase {\n private cb?: (input: MuteOutput) => void;\n\n constructor(props: ConstructorParameters<typeof MuteHandlerBase>[1]) {\n super((o) => {\n if (this.cb) {\n this.cb(o);\n }\n }, props);\n }\n\n pipe = (cb: (input: MuteOutput) => void) => {\n this.cb = cb;\n };\n\n input = (input: MuteInput) => {\n if (!this.cb) {\n return;\n }\n for (const output of this.processInput(input)) {\n this.cb(output);\n }\n if (input.eol) {\n this.cb = undefined;\n }\n };\n}\n"]}
1
+ {"version":3,"file":"muteCallback.js","sourceRoot":"","sources":["../../../../../rtp/src/processor/muteCallback.ts"],"names":[],"mappings":";;;AACA,iCAAgE;AAEhE,MAAa,YACX,SAAQ,sBAAe;IAMvB,YAAY,KAAuD;QACjE,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;YACV,IAAI,IAAI,CAAC,EAAE,EAAE;gBACX,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;aACZ;QACH,CAAC,EAAE,KAAK,CAAC,CAAC;QARZ;;;;;WAAyC;QACzC;;;;;WAAwB;QAUxB;;;;mBAAO,CAAC,EAA+B,EAAE,UAAuB,EAAE,EAAE;gBAClE,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;gBACb,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;gBAC7B,OAAO,IAAI,CAAC;YACd,CAAC;WAAC;QAEF;;;;mBAAQ,CAAC,KAAgB,EAAE,EAAE;gBAC3B,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE;oBAC7C,IAAI,IAAI,CAAC,EAAE,EAAE;wBACX,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;qBACjB;iBACF;YACH,CAAC;WAAC;QAEF;;;;mBAAU,GAAG,EAAE;gBACb,IAAI,IAAI,CAAC,UAAU,EAAE;oBACnB,IAAI,CAAC,UAAU,EAAE,CAAC;oBAClB,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;iBAC7B;gBACD,IAAI,CAAC,EAAE,GAAG,SAAS,CAAC;YACtB,CAAC;WAAC;IAtBF,CAAC;CAuBF;AApCD,oCAoCC","sourcesContent":["import { SimpleProcessorCallback } from \"./interface\";\nimport { MuteHandlerBase, MuteInput, MuteOutput } from \"./mute\";\n\nexport class MuteCallback\n extends MuteHandlerBase\n implements SimpleProcessorCallback<MuteInput, MuteOutput>\n{\n private cb?: (input: MuteOutput) => void;\n destructor?: () => void;\n\n constructor(props: ConstructorParameters<typeof MuteHandlerBase>[1]) {\n super((o) => {\n if (this.cb) {\n this.cb(o);\n }\n }, props);\n }\n\n pipe = (cb: (input: MuteOutput) => void, destructor?: () => void) => {\n this.cb = cb;\n this.destructor = destructor;\n return this;\n };\n\n input = (input: MuteInput) => {\n for (const output of this.processInput(input)) {\n if (this.cb) {\n this.cb(output);\n }\n }\n };\n\n destroy = () => {\n if (this.destructor) {\n this.destructor();\n this.destructor = undefined;\n }\n this.cb = undefined;\n };\n}\n"]}
@@ -1,8 +1,7 @@
1
1
  import Event from "rx.mini";
2
- import { RtcpTransportLayerFeedback } from "../rtcp/rtpfb";
3
- import { GenericNack } from "../rtcp/rtpfb/nack";
2
+ import { GenericNack, RtcpTransportLayerFeedback } from "..";
4
3
  import { Processor } from "./interface";
5
- import { RtpOutput } from "./source";
4
+ import { RtpOutput } from "./rtpCallback";
6
5
  export type NackHandlerInput = RtpOutput;
7
6
  export type NackHandlerOutput = RtpOutput;
8
7
  export declare class NackHandlerBase implements Processor<NackHandlerInput, NackHandlerOutput> {
@@ -10,11 +9,12 @@ export declare class NackHandlerBase implements Processor<NackHandlerInput, Nack
10
9
  private onNack;
11
10
  private newEstSeqNum;
12
11
  private _lost;
13
- private nackLoop;
12
+ private clearNackInterval?;
14
13
  private internalStats;
15
- readonly onPacketLost: Event<[GenericNack]>;
14
+ readonly onNackSent: Event<[GenericNack]>;
15
+ readonly onPacketLost: Event<[number]>;
16
16
  mediaSourceSsrc?: number;
17
- retryCount: number;
17
+ readonly retryCount = 10;
18
18
  stopped: boolean;
19
19
  constructor(senderSsrc: number, onNack: (rtcp: RtcpTransportLayerFeedback) => Promise<void>);
20
20
  toJSON(): Record<string, any>;
@@ -7,9 +7,7 @@ exports.NackHandlerBase = void 0;
7
7
  const debug_1 = __importDefault(require("debug"));
8
8
  const range_1 = __importDefault(require("lodash/range"));
9
9
  const rx_mini_1 = __importDefault(require("rx.mini"));
10
- const src_1 = require("../../../common/src");
11
- const rtpfb_1 = require("../rtcp/rtpfb");
12
- const nack_1 = require("../rtcp/rtpfb/nack");
10
+ const __1 = require("..");
13
11
  const log = (0, debug_1.default)("werift-rtp : packages/rtp/src/processor/nack.ts");
14
12
  const LOST_SIZE = 30 * 5;
15
13
  class NackHandlerBase {
@@ -38,7 +36,7 @@ class NackHandlerBase {
38
36
  writable: true,
39
37
  value: {}
40
38
  });
41
- Object.defineProperty(this, "nackLoop", {
39
+ Object.defineProperty(this, "clearNackInterval", {
42
40
  enumerable: true,
43
41
  configurable: true,
44
42
  writable: true,
@@ -50,6 +48,12 @@ class NackHandlerBase {
50
48
  writable: true,
51
49
  value: {}
52
50
  });
51
+ Object.defineProperty(this, "onNackSent", {
52
+ enumerable: true,
53
+ configurable: true,
54
+ writable: true,
55
+ value: new rx_mini_1.default()
56
+ });
53
57
  Object.defineProperty(this, "onPacketLost", {
54
58
  enumerable: true,
55
59
  configurable: true,
@@ -81,6 +85,7 @@ class NackHandlerBase {
81
85
  value: (input) => {
82
86
  if (input.rtp) {
83
87
  this.addPacket(input.rtp);
88
+ this.internalStats["nackHandler"] = new Date().toISOString();
84
89
  return [input];
85
90
  }
86
91
  this.stop();
@@ -94,28 +99,28 @@ class NackHandlerBase {
94
99
  value: () => new Promise((r, f) => {
95
100
  if (this.lostSeqNumbers.length > 0 && this.mediaSourceSsrc) {
96
101
  this.internalStats["count"] = (this.internalStats["count"] ?? 0) + 1;
97
- const nack = new nack_1.GenericNack({
102
+ const nack = new __1.GenericNack({
98
103
  senderSsrc: this.senderSsrc,
99
104
  mediaSourceSsrc: this.mediaSourceSsrc,
100
105
  lost: this.lostSeqNumbers,
101
106
  });
102
- const rtcp = new rtpfb_1.RtcpTransportLayerFeedback({
107
+ const rtcp = new __1.RtcpTransportLayerFeedback({
103
108
  feedback: nack,
104
109
  });
105
110
  this.onNack(rtcp).then(r).catch(f);
106
111
  this.updateRetryCount();
107
- this.onPacketLost.execute(nack);
112
+ this.onNackSent.execute(nack);
108
113
  }
109
114
  })
110
115
  });
111
116
  }
112
117
  toJSON() {
113
118
  return {
119
+ ...this.internalStats,
114
120
  newEstSeqNum: this.newEstSeqNum,
115
121
  lostLength: Object.values(this._lost).length,
116
122
  senderSsrc: this.senderSsrc,
117
123
  mediaSourceSsrc: this.mediaSourceSsrc,
118
- ...this.internalStats,
119
124
  };
120
125
  }
121
126
  get lostSeqNumbers() {
@@ -126,15 +131,15 @@ class NackHandlerBase {
126
131
  }
127
132
  setLost(seq, count) {
128
133
  this._lost[seq] = count;
129
- if (this.nackLoop || this.stopped) {
134
+ if (this.clearNackInterval || this.stopped) {
130
135
  return;
131
136
  }
132
- this.nackLoop = setInterval(async () => {
137
+ this.clearNackInterval = __1.timer.setInterval(async () => {
133
138
  try {
134
139
  await this.sendNack();
135
140
  if (!Object.keys(this._lost).length) {
136
- clearInterval(this.nackLoop);
137
- this.nackLoop = undefined;
141
+ this.clearNackInterval?.();
142
+ this.clearNackInterval = undefined;
138
143
  }
139
144
  }
140
145
  catch (error) {
@@ -157,12 +162,12 @@ class NackHandlerBase {
157
162
  this.removeLost(sequenceNumber);
158
163
  return;
159
164
  }
160
- if (sequenceNumber === (0, src_1.uint16Add)(this.newEstSeqNum, 1)) {
165
+ if (sequenceNumber === (0, __1.uint16Add)(this.newEstSeqNum, 1)) {
161
166
  this.newEstSeqNum = sequenceNumber;
162
167
  }
163
- else if (sequenceNumber > (0, src_1.uint16Add)(this.newEstSeqNum, 1)) {
168
+ else if (sequenceNumber > (0, __1.uint16Add)(this.newEstSeqNum, 1)) {
164
169
  // packet lost detected
165
- (0, range_1.default)((0, src_1.uint16Add)(this.newEstSeqNum, 1), sequenceNumber).forEach((seq) => {
170
+ (0, range_1.default)((0, __1.uint16Add)(this.newEstSeqNum, 1), sequenceNumber).forEach((seq) => {
166
171
  this.setLost(seq, 1);
167
172
  });
168
173
  // this.receiver.sendRtcpPLI(this.mediaSourceSsrc);
@@ -183,7 +188,8 @@ class NackHandlerBase {
183
188
  stop() {
184
189
  this.stopped = true;
185
190
  this._lost = {};
186
- clearInterval(this.nackLoop);
191
+ this.clearNackInterval?.();
192
+ this.onNackSent.allUnsubscribe();
187
193
  this.onPacketLost.allUnsubscribe();
188
194
  this.onNack = undefined;
189
195
  }
@@ -192,7 +198,7 @@ class NackHandlerBase {
192
198
  const count = this._lost[seq]++;
193
199
  if (count > this.retryCount) {
194
200
  this.removeLost(seq);
195
- return seq;
201
+ this.onPacketLost.execute(seq);
196
202
  }
197
203
  });
198
204
  }
@@ -1 +1 @@
1
- {"version":3,"file":"nack.js","sourceRoot":"","sources":["../../../../../rtp/src/processor/nack.ts"],"names":[],"mappings":"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","sourcesContent":["import debug from \"debug\";\nimport range from \"lodash/range\";\nimport Event from \"rx.mini\";\n\nimport { uint16Add } from \"../../../common/src\";\nimport { RtcpTransportLayerFeedback } from \"../rtcp/rtpfb\";\nimport { GenericNack } from \"../rtcp/rtpfb/nack\";\nimport { RtpPacket } from \"../rtp/rtp\";\nimport { Processor } from \"./interface\";\nimport { RtpOutput } from \"./source\";\n\nconst log = debug(\"werift-rtp : packages/rtp/src/processor/nack.ts\");\n\nconst LOST_SIZE = 30 * 5;\n\nexport type NackHandlerInput = RtpOutput;\n\nexport type NackHandlerOutput = RtpOutput;\n\nexport class NackHandlerBase\n implements Processor<NackHandlerInput, NackHandlerOutput>\n{\n private newEstSeqNum = 0;\n private _lost: { [seqNum: number]: number } = {};\n private nackLoop: any;\n private internalStats = {};\n\n readonly onPacketLost = new Event<[GenericNack]>();\n mediaSourceSsrc?: number;\n retryCount = 10;\n stopped = false;\n\n constructor(\n private senderSsrc: number,\n private onNack: (rtcp: RtcpTransportLayerFeedback) => Promise<void>\n ) {}\n\n toJSON(): Record<string, any> {\n return {\n newEstSeqNum: this.newEstSeqNum,\n lostLength: Object.values(this._lost).length,\n senderSsrc: this.senderSsrc,\n mediaSourceSsrc: this.mediaSourceSsrc,\n ...this.internalStats,\n };\n }\n\n private get lostSeqNumbers() {\n return Object.keys(this._lost).map(Number).sort();\n }\n\n private getLost(seq: number) {\n return this._lost[seq];\n }\n\n private setLost(seq: number, count: number) {\n this._lost[seq] = count;\n\n if (this.nackLoop || this.stopped) {\n return;\n }\n this.nackLoop = setInterval(async () => {\n try {\n await this.sendNack();\n if (!Object.keys(this._lost).length) {\n clearInterval(this.nackLoop);\n this.nackLoop = undefined;\n }\n } catch (error) {\n log(\"failed to send nack\", error);\n }\n }, 5);\n }\n\n private removeLost(sequenceNumber: number) {\n delete this._lost[sequenceNumber];\n }\n\n processInput = (input: RtpOutput) => {\n if (input.rtp) {\n this.addPacket(input.rtp);\n return [input];\n }\n\n this.stop();\n return [input];\n };\n\n private addPacket(packet: RtpPacket) {\n const { sequenceNumber, ssrc } = packet.header;\n this.mediaSourceSsrc = ssrc;\n\n if (this.newEstSeqNum === 0) {\n this.newEstSeqNum = sequenceNumber;\n return;\n }\n\n if (this.getLost(sequenceNumber)) {\n // log(\"packetLoss resolved\", { sequenceNumber });\n this.removeLost(sequenceNumber);\n return;\n }\n\n if (sequenceNumber === uint16Add(this.newEstSeqNum, 1)) {\n this.newEstSeqNum = sequenceNumber;\n } else if (sequenceNumber > uint16Add(this.newEstSeqNum, 1)) {\n // packet lost detected\n range(uint16Add(this.newEstSeqNum, 1), sequenceNumber).forEach((seq) => {\n this.setLost(seq, 1);\n });\n // this.receiver.sendRtcpPLI(this.mediaSourceSsrc);\n\n this.newEstSeqNum = sequenceNumber;\n this.pruneLost();\n }\n }\n\n private pruneLost() {\n if (this.lostSeqNumbers.length > LOST_SIZE) {\n this._lost = Object.entries(this._lost)\n .slice(-LOST_SIZE)\n .reduce((acc, [key, v]) => {\n acc[key] = v;\n return acc;\n }, {} as { [seqNum: number]: number });\n }\n }\n\n private stop() {\n this.stopped = true;\n this._lost = {};\n clearInterval(this.nackLoop);\n this.onPacketLost.allUnsubscribe();\n this.onNack = undefined as any;\n }\n\n private updateRetryCount() {\n this.lostSeqNumbers.forEach((seq) => {\n const count = this._lost[seq]++;\n if (count > this.retryCount) {\n this.removeLost(seq);\n return seq;\n }\n });\n }\n\n private sendNack = () =>\n new Promise((r, f) => {\n if (this.lostSeqNumbers.length > 0 && this.mediaSourceSsrc) {\n this.internalStats[\"count\"] = (this.internalStats[\"count\"] ?? 0) + 1;\n\n const nack = new GenericNack({\n senderSsrc: this.senderSsrc,\n mediaSourceSsrc: this.mediaSourceSsrc,\n lost: this.lostSeqNumbers,\n });\n\n const rtcp = new RtcpTransportLayerFeedback({\n feedback: nack,\n });\n this.onNack(rtcp).then(r).catch(f);\n\n this.updateRetryCount();\n this.onPacketLost.execute(nack);\n }\n });\n}\n"]}
1
+ {"version":3,"file":"nack.js","sourceRoot":"","sources":["../../../../../rtp/src/processor/nack.ts"],"names":[],"mappings":"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","sourcesContent":["import debug from \"debug\";\nimport range from \"lodash/range\";\nimport Event from \"rx.mini\";\n\nimport {\n GenericNack,\n RtcpTransportLayerFeedback,\n RtpPacket,\n timer,\n uint16Add,\n} from \"..\";\nimport { Processor } from \"./interface\";\nimport { RtpOutput } from \"./rtpCallback\";\n\nconst log = debug(\"werift-rtp : packages/rtp/src/processor/nack.ts\");\n\nconst LOST_SIZE = 30 * 5;\n\nexport type NackHandlerInput = RtpOutput;\n\nexport type NackHandlerOutput = RtpOutput;\n\nexport class NackHandlerBase\n implements Processor<NackHandlerInput, NackHandlerOutput>\n{\n private newEstSeqNum = 0;\n private _lost: { [seqNum: number]: number } = {};\n private clearNackInterval?: () => void;\n private internalStats = {};\n\n readonly onNackSent = new Event<[GenericNack]>();\n readonly onPacketLost = new Event<[number]>();\n mediaSourceSsrc?: number;\n readonly retryCount = 10;\n stopped = false;\n\n constructor(\n private senderSsrc: number,\n private onNack: (rtcp: RtcpTransportLayerFeedback) => Promise<void>\n ) {}\n\n toJSON(): Record<string, any> {\n return {\n ...this.internalStats,\n newEstSeqNum: this.newEstSeqNum,\n lostLength: Object.values(this._lost).length,\n senderSsrc: this.senderSsrc,\n mediaSourceSsrc: this.mediaSourceSsrc,\n };\n }\n\n private get lostSeqNumbers() {\n return Object.keys(this._lost).map(Number).sort();\n }\n\n private getLost(seq: number) {\n return this._lost[seq];\n }\n\n private setLost(seq: number, count: number) {\n this._lost[seq] = count;\n\n if (this.clearNackInterval || this.stopped) {\n return;\n }\n this.clearNackInterval = timer.setInterval(async () => {\n try {\n await this.sendNack();\n if (!Object.keys(this._lost).length) {\n this.clearNackInterval?.();\n this.clearNackInterval = undefined;\n }\n } catch (error) {\n log(\"failed to send nack\", error);\n }\n }, 5);\n }\n\n private removeLost(sequenceNumber: number) {\n delete this._lost[sequenceNumber];\n }\n\n processInput = (input: RtpOutput) => {\n if (input.rtp) {\n this.addPacket(input.rtp);\n this.internalStats[\"nackHandler\"] = new Date().toISOString();\n return [input];\n }\n\n this.stop();\n return [input];\n };\n\n private addPacket(packet: RtpPacket) {\n const { sequenceNumber, ssrc } = packet.header;\n this.mediaSourceSsrc = ssrc;\n\n if (this.newEstSeqNum === 0) {\n this.newEstSeqNum = sequenceNumber;\n return;\n }\n\n if (this.getLost(sequenceNumber)) {\n // log(\"packetLoss resolved\", { sequenceNumber });\n this.removeLost(sequenceNumber);\n return;\n }\n\n if (sequenceNumber === uint16Add(this.newEstSeqNum, 1)) {\n this.newEstSeqNum = sequenceNumber;\n } else if (sequenceNumber > uint16Add(this.newEstSeqNum, 1)) {\n // packet lost detected\n range(uint16Add(this.newEstSeqNum, 1), sequenceNumber).forEach((seq) => {\n this.setLost(seq, 1);\n });\n // this.receiver.sendRtcpPLI(this.mediaSourceSsrc);\n\n this.newEstSeqNum = sequenceNumber;\n this.pruneLost();\n }\n }\n\n private pruneLost() {\n if (this.lostSeqNumbers.length > LOST_SIZE) {\n this._lost = Object.entries(this._lost)\n .slice(-LOST_SIZE)\n .reduce((acc, [key, v]) => {\n acc[key] = v;\n return acc;\n }, {} as { [seqNum: number]: number });\n }\n }\n\n private stop() {\n this.stopped = true;\n this._lost = {};\n this.clearNackInterval?.();\n this.onNackSent.allUnsubscribe();\n this.onPacketLost.allUnsubscribe();\n this.onNack = undefined as any;\n }\n\n private updateRetryCount() {\n this.lostSeqNumbers.forEach((seq) => {\n const count = this._lost[seq]++;\n if (count > this.retryCount) {\n this.removeLost(seq);\n this.onPacketLost.execute(seq);\n }\n });\n }\n\n private sendNack = () =>\n new Promise((r, f) => {\n if (this.lostSeqNumbers.length > 0 && this.mediaSourceSsrc) {\n this.internalStats[\"count\"] = (this.internalStats[\"count\"] ?? 0) + 1;\n\n const nack = new GenericNack({\n senderSsrc: this.senderSsrc,\n mediaSourceSsrc: this.mediaSourceSsrc,\n lost: this.lostSeqNumbers,\n });\n\n const rtcp = new RtcpTransportLayerFeedback({\n feedback: nack,\n });\n this.onNack(rtcp).then(r).catch(f);\n\n this.updateRetryCount();\n this.onNackSent.execute(nack);\n }\n });\n}\n"]}
@@ -1,8 +1,15 @@
1
- import { RtcpTransportLayerFeedback } from "../rtcp/rtpfb";
2
- import { NackHandlerBase, NackHandlerInput, NackHandlerOutput } from "./nack";
3
- export declare class NackHandlerCallback extends NackHandlerBase {
4
- private cb;
5
- constructor(senderSsrc: number, onNack: (rtcp: RtcpTransportLayerFeedback) => Promise<void>);
6
- pipe: (cb: (input: NackHandlerOutput) => void) => this;
7
- input: (input: NackHandlerInput) => void;
1
+ import { NackHandlerBase } from "./nack";
2
+ declare const NackHandlerCallback_base: {
3
+ new (...args: any[]): {
4
+ cb?: ((o: import("./rtpCallback").RtpOutput) => void) | undefined;
5
+ destructor?: (() => void) | undefined;
6
+ pipe: (cb: (o: import("./rtpCallback").RtpOutput) => void, destructor?: (() => void) | undefined) => any;
7
+ input: (input: import("./rtpCallback").RtpOutput) => void;
8
+ destroy: () => void;
9
+ processInput: (input: import("./rtpCallback").RtpOutput) => import("./rtpCallback").RtpOutput[];
10
+ toJSON(): Record<string, any>;
11
+ };
12
+ } & typeof NackHandlerBase;
13
+ export declare class NackHandlerCallback extends NackHandlerCallback_base {
8
14
  }
15
+ export {};
@@ -1,36 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.NackHandlerCallback = void 0;
4
+ const interface_1 = require("./interface");
4
5
  const nack_1 = require("./nack");
5
- class NackHandlerCallback extends nack_1.NackHandlerBase {
6
- constructor(senderSsrc, onNack) {
7
- super(senderSsrc, onNack);
8
- Object.defineProperty(this, "cb", {
9
- enumerable: true,
10
- configurable: true,
11
- writable: true,
12
- value: void 0
13
- });
14
- Object.defineProperty(this, "pipe", {
15
- enumerable: true,
16
- configurable: true,
17
- writable: true,
18
- value: (cb) => {
19
- this.cb = cb;
20
- return this;
21
- }
22
- });
23
- Object.defineProperty(this, "input", {
24
- enumerable: true,
25
- configurable: true,
26
- writable: true,
27
- value: (input) => {
28
- for (const output of this.processInput(input)) {
29
- this.cb(output);
30
- }
31
- }
32
- });
33
- }
6
+ class NackHandlerCallback extends (0, interface_1.SimpleProcessorCallbackBase)(nack_1.NackHandlerBase) {
34
7
  }
35
8
  exports.NackHandlerCallback = NackHandlerCallback;
36
9
  //# sourceMappingURL=nackHandlerCallback.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"nackHandlerCallback.js","sourceRoot":"","sources":["../../../../../rtp/src/processor/nackHandlerCallback.ts"],"names":[],"mappings":";;;AACA,iCAA8E;AAE9E,MAAa,mBAAoB,SAAQ,sBAAe;IAEtD,YACE,UAAkB,EAClB,MAA2D;QAE3D,KAAK,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAL5B;;;;;WAAgD;QAQhD;;;;mBAAO,CAAC,EAAsC,EAAE,EAAE;gBAChD,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;gBACb,OAAO,IAAI,CAAC;YACd,CAAC;WAAC;QAEF;;;;mBAAQ,CAAC,KAAuB,EAAE,EAAE;gBAClC,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE;oBAC7C,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;iBACjB;YACH,CAAC;WAAC;IAXF,CAAC;CAYF;AAnBD,kDAmBC","sourcesContent":["import { RtcpTransportLayerFeedback } from \"../rtcp/rtpfb\";\nimport { NackHandlerBase, NackHandlerInput, NackHandlerOutput } from \"./nack\";\n\nexport class NackHandlerCallback extends NackHandlerBase {\n private cb!: (input: NackHandlerOutput) => void;\n constructor(\n senderSsrc: number,\n onNack: (rtcp: RtcpTransportLayerFeedback) => Promise<void>\n ) {\n super(senderSsrc, onNack);\n }\n\n pipe = (cb: (input: NackHandlerOutput) => void) => {\n this.cb = cb;\n return this;\n };\n\n input = (input: NackHandlerInput) => {\n for (const output of this.processInput(input)) {\n this.cb(output);\n }\n };\n}\n"]}
1
+ {"version":3,"file":"nackHandlerCallback.js","sourceRoot":"","sources":["../../../../../rtp/src/processor/nackHandlerCallback.ts"],"names":[],"mappings":";;;AAAA,2CAA0D;AAC1D,iCAA8E;AAE9E,MAAa,mBAAoB,SAAQ,IAAA,uCAA2B,EAIlE,sBAAe,CAAC;CAAG;AAJrB,kDAIqB","sourcesContent":["import { SimpleProcessorCallbackBase } from \"./interface\";\nimport { NackHandlerBase, NackHandlerInput, NackHandlerOutput } from \"./nack\";\n\nexport class NackHandlerCallback extends SimpleProcessorCallbackBase<\n NackHandlerInput,\n NackHandlerOutput,\n typeof NackHandlerBase\n>(NackHandlerBase) {}\n"]}
@@ -12,15 +12,15 @@ export interface NtpTimeOutput {
12
12
  }
13
13
  export declare class NtpTimeBase implements Processor<NtpTimeInput, NtpTimeOutput> {
14
14
  clockRate: number;
15
- baseNtpTimestamp?: bigint;
16
- baseRtpTimestamp?: number;
17
- latestNtpTimestamp?: bigint;
18
- latestRtpTimestamp?: number;
15
+ readonly id: string;
16
+ private baseNtpTimestamp?;
17
+ private baseRtpTimestamp?;
18
+ private latestNtpTimestamp?;
19
+ private latestRtpTimestamp?;
19
20
  private currentElapsed;
20
- buffer: RtpPacket[];
21
+ private buffer;
21
22
  private internalStats;
22
- id: string;
23
- payloadType: number;
23
+ started: boolean;
24
24
  constructor(clockRate: number);
25
25
  toJSON(): Record<string, any>;
26
26
  private stop;