werift 0.15.11 → 0.16.0

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 (79) hide show
  1. package/lib/common/src/index.d.ts +2 -0
  2. package/lib/common/src/index.js +2 -0
  3. package/lib/common/src/index.js.map +1 -1
  4. package/lib/common/src/log.d.ts +11 -0
  5. package/lib/common/src/log.js +17 -0
  6. package/lib/common/src/log.js.map +1 -0
  7. package/lib/common/src/type.d.ts +3 -0
  8. package/lib/common/src/type.js +3 -0
  9. package/lib/common/src/type.js.map +1 -0
  10. package/lib/dtls/src/context/cipher.js.map +1 -1
  11. package/lib/dtls/src/flight/server/flight2.js +10 -0
  12. package/lib/dtls/src/flight/server/flight2.js.map +1 -1
  13. package/lib/ice/src/ice.d.ts +1 -0
  14. package/lib/ice/src/ice.js +4 -0
  15. package/lib/ice/src/ice.js.map +1 -1
  16. package/lib/rtp/src/codec/index.d.ts +18 -0
  17. package/lib/rtp/src/codec/index.js +81 -0
  18. package/lib/rtp/src/codec/index.js.map +1 -0
  19. package/lib/rtp/src/codec/vp8.d.ts +5 -3
  20. package/lib/rtp/src/codec/vp8.js +19 -5
  21. package/lib/rtp/src/codec/vp8.js.map +1 -1
  22. package/lib/rtp/src/container/webm.d.ts +6 -1
  23. package/lib/rtp/src/container/webm.js +9 -2
  24. package/lib/rtp/src/container/webm.js.map +1 -1
  25. package/lib/rtp/src/index.d.ts +2 -6
  26. package/lib/rtp/src/index.js +2 -6
  27. package/lib/rtp/src/index.js.map +1 -1
  28. package/lib/rtp/src/processor/base.d.ts +3 -1
  29. package/lib/rtp/src/processor/base.js +19 -6
  30. package/lib/rtp/src/processor/base.js.map +1 -1
  31. package/lib/rtp/src/processor/jitterBuffer.js +1 -1
  32. package/lib/rtp/src/processor/jitterBuffer.js.map +1 -1
  33. package/lib/rtp/src/processor/lipsync.js +22 -2
  34. package/lib/rtp/src/processor/lipsync.js.map +1 -1
  35. package/lib/rtp/src/processor/webm.d.ts +11 -7
  36. package/lib/rtp/src/processor/webm.js +16 -41
  37. package/lib/rtp/src/processor/webm.js.map +1 -1
  38. package/lib/rtp/src/processor_v2/depacketizer.d.ts +17 -0
  39. package/lib/rtp/src/processor_v2/depacketizer.js +84 -0
  40. package/lib/rtp/src/processor_v2/depacketizer.js.map +1 -0
  41. package/lib/rtp/src/processor_v2/index.d.ts +4 -0
  42. package/lib/rtp/src/processor_v2/index.js +21 -0
  43. package/lib/rtp/src/processor_v2/index.js.map +1 -0
  44. package/lib/rtp/src/processor_v2/jitterBuffer.d.ts +33 -0
  45. package/lib/rtp/src/processor_v2/jitterBuffer.js +154 -0
  46. package/lib/rtp/src/processor_v2/jitterBuffer.js.map +1 -0
  47. package/lib/rtp/src/processor_v2/source/base.d.ts +8 -0
  48. package/lib/rtp/src/processor_v2/source/base.js +16 -0
  49. package/lib/rtp/src/processor_v2/source/base.js.map +1 -0
  50. package/lib/rtp/src/processor_v2/source/index.d.ts +2 -0
  51. package/lib/rtp/src/processor_v2/source/index.js +6 -0
  52. package/lib/rtp/src/processor_v2/source/index.js.map +1 -0
  53. package/lib/rtp/src/processor_v2/source/rtp.d.ts +14 -0
  54. package/lib/rtp/src/processor_v2/source/rtp.js +24 -0
  55. package/lib/rtp/src/processor_v2/source/rtp.js.map +1 -0
  56. package/lib/rtp/src/processor_v2/webmLive.d.ts +51 -0
  57. package/lib/rtp/src/processor_v2/webmLive.js +154 -0
  58. package/lib/rtp/src/processor_v2/webmLive.js.map +1 -0
  59. package/lib/webrtc/src/media/rtpTransceiver.d.ts +1 -1
  60. package/lib/webrtc/src/media/rtpTransceiver.js +3 -2
  61. package/lib/webrtc/src/media/rtpTransceiver.js.map +1 -1
  62. package/lib/webrtc/src/nonstandard/recorder/index.d.ts +5 -1
  63. package/lib/webrtc/src/nonstandard/recorder/index.js +2 -2
  64. package/lib/webrtc/src/nonstandard/recorder/index.js.map +1 -1
  65. package/lib/webrtc/src/nonstandard/recorder/writer/index.d.ts +1 -1
  66. package/lib/webrtc/src/nonstandard/recorder/writer/index.js +1 -1
  67. package/lib/webrtc/src/nonstandard/recorder/writer/index.js.map +1 -1
  68. package/lib/webrtc/src/nonstandard/recorder/writer/webm.d.ts +3 -3
  69. package/lib/webrtc/src/nonstandard/recorder/writer/webm.js +61 -41
  70. package/lib/webrtc/src/nonstandard/recorder/writer/webm.js.map +1 -1
  71. package/lib/webrtc/src/peerConnection.d.ts +9 -1
  72. package/lib/webrtc/src/peerConnection.js +9 -1
  73. package/lib/webrtc/src/peerConnection.js.map +1 -1
  74. package/package.json +2 -2
  75. package/src/media/rtpTransceiver.ts +4 -2
  76. package/src/nonstandard/recorder/index.ts +6 -2
  77. package/src/nonstandard/recorder/writer/index.ts +1 -1
  78. package/src/nonstandard/recorder/writer/webm.ts +105 -57
  79. package/src/peerConnection.ts +26 -2
@@ -2,13 +2,11 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.WebmOutput = void 0;
4
4
  const src_1 = require("../../../common/src");
5
- const __1 = require("..");
5
+ const codec_1 = require("../codec");
6
6
  const webm_1 = require("../container/webm");
7
7
  class WebmOutput {
8
- constructor(
9
- /**fs/promises */
10
- fs, path, tracks, streams) {
11
- this.fs = fs;
8
+ constructor(writer, path, tracks, streams) {
9
+ this.writer = writer;
12
10
  this.path = path;
13
11
  this.tracks = tracks;
14
12
  this.queue = new src_1.PromiseQueue();
@@ -34,26 +32,29 @@ class WebmOutput {
34
32
  this.builder.ebmlHeader,
35
33
  this.builder.createSegment(),
36
34
  ]);
37
- await this.fs.writeFile(this.path, staticPart);
35
+ await this.writer.writeFile(this.path, staticPart);
38
36
  this.position += staticPart.length;
39
37
  const video = this.tracks.find((t) => t.kind === "video");
40
38
  if (video) {
41
39
  this.cuePoints.push(new CuePoint(this.builder, video.trackNumber, 0.0, this.position));
42
40
  }
43
41
  const cluster = this.builder.createCluster(0.0);
44
- await this.fs.appendFile(this.path, cluster);
42
+ await this.writer.appendFile(this.path, cluster);
45
43
  this.position += cluster.length;
46
44
  }
47
- async stop() {
45
+ async stop(insertDuration = true) {
48
46
  this.stopped = true;
49
47
  if (this.disposer) {
50
48
  this.disposer();
51
49
  }
50
+ if (!insertDuration) {
51
+ return;
52
+ }
52
53
  const originStaticPartOffset = Buffer.concat([
53
54
  this.builder.ebmlHeader,
54
55
  this.builder.createSegment(),
55
56
  ]).length;
56
- const clusters = (await this.fs.readFile(this.path)).slice(originStaticPartOffset);
57
+ const clusters = (await this.writer.readFile(this.path)).slice(originStaticPartOffset);
57
58
  const latestTimestamp = Object.values(this.timestamps).sort((a, b) => a.relativeTimestamp - b.relativeTimestamp)[0].relativeTimestamp;
58
59
  const duration = this.relativeTimestamp + latestTimestamp;
59
60
  const staticPart = Buffer.concat([
@@ -75,9 +76,9 @@ class WebmOutput {
75
76
  });
76
77
  cues = this.builder.createCues(this.cuePoints.map((c) => c.build()));
77
78
  }
78
- await this.fs.writeFile(this.path, staticPart);
79
- await this.fs.appendFile(this.path, cues);
80
- await this.fs.appendFile(this.path, clusters);
79
+ await this.writer.writeFile(this.path, staticPart);
80
+ await this.writer.appendFile(this.path, cues);
81
+ await this.writer.appendFile(this.path, clusters);
81
82
  }
82
83
  pushRtpPackets(packets) {
83
84
  if (this.stopped)
@@ -90,7 +91,7 @@ class WebmOutput {
90
91
  return;
91
92
  }
92
93
  const timestampManager = this.timestamps[track.payloadType];
93
- const { data, isKeyframe } = this.dePacketizeRtpPackets(track.codec, packets);
94
+ const { data, isKeyframe } = (0, codec_1.dePacketizeRtpPackets)(track.codec, packets);
94
95
  const tailTimestamp = packets.slice(-1)[0].header.timestamp;
95
96
  timestampManager.update(tailTimestamp);
96
97
  if ((track.kind === "video" &&
@@ -99,45 +100,19 @@ class WebmOutput {
99
100
  timestampManager.relativeTimestamp > MaxSinged16Int) {
100
101
  this.relativeTimestamp += timestampManager.relativeTimestamp;
101
102
  const cluster = this.builder.createCluster(this.relativeTimestamp);
102
- await this.fs.appendFile(this.path, cluster);
103
+ await this.writer.appendFile(this.path, cluster);
103
104
  this.cuePoints.push(new CuePoint(this.builder, track.trackNumber, this.relativeTimestamp, this.position));
104
105
  this.position += cluster.length;
105
106
  Object.values(this.timestamps).forEach((t) => t.reset());
106
107
  }
107
108
  const block = this.builder.createSimpleBlock(data, isKeyframe, track.trackNumber, timestampManager.relativeTimestamp);
108
- await this.fs.appendFile(this.path, block);
109
+ await this.writer.appendFile(this.path, block);
109
110
  this.position += block.length;
110
111
  const [cuePoint] = this.cuePoints.slice(-1);
111
112
  if (cuePoint) {
112
113
  cuePoint.blockNumber++;
113
114
  }
114
115
  }
115
- dePacketizeRtpPackets(codec, packets) {
116
- const basicCodecParser = (DePacketizer) => {
117
- const frames = packets.map((p) => DePacketizer.deSerialize(p.payload));
118
- const isKeyframe = !!frames.find((f) => f.isKeyframe);
119
- const data = Buffer.concat(frames.map((f) => f.payload));
120
- return { isKeyframe, data };
121
- };
122
- switch (codec) {
123
- case "AV1": {
124
- const chunks = packets.map((p) => __1.AV1RtpPayload.deSerialize(p.payload));
125
- const data = __1.AV1RtpPayload.getFrame(chunks);
126
- const isKeyframe = !!chunks.find((f) => f.isKeyframe);
127
- return { isKeyframe, data };
128
- }
129
- case "MPEG4/ISO/AVC":
130
- return basicCodecParser(__1.H264RtpPayload);
131
- case "VP8":
132
- return basicCodecParser(__1.Vp8RtpPayload);
133
- case "VP9":
134
- return basicCodecParser(__1.Vp9RtpPayload);
135
- case "OPUS":
136
- return basicCodecParser(__1.OpusRtpPayload);
137
- default:
138
- throw new Error();
139
- }
140
- }
141
116
  }
142
117
  exports.WebmOutput = WebmOutput;
143
118
  class TimestampManager {
@@ -1 +1 @@
1
- {"version":3,"file":"webm.js","sourceRoot":"","sources":["../../../../../rtp/src/processor/webm.ts"],"names":[],"mappings":"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","sourcesContent":["import Event from \"rx.mini\";\n\nimport { int, PromiseQueue } from \"../../../common/src\";\nimport {\n AV1RtpPayload,\n DePacketizerBase,\n H264RtpPayload,\n OpusRtpPayload,\n RtpPacket,\n Vp8RtpPayload,\n Vp9RtpPayload,\n} from \"..\";\nimport { SupportedCodec, WEBMBuilder } from \"../container/webm\";\nimport { Output } from \"./base\";\n\nexport class WebmOutput implements Output {\n private builder: WEBMBuilder;\n private queue = new PromiseQueue();\n private relativeTimestamp = 0;\n private timestamps: { [pt: number]: TimestampManager } = {};\n private disposer?: () => void;\n private cuePoints: CuePoint[] = [];\n private position = 0;\n stopped = false;\n\n constructor(\n /**fs/promises */\n private fs: any,\n public path: string,\n public tracks: {\n width?: number;\n height?: number;\n kind: \"audio\" | \"video\";\n codec: SupportedCodec;\n clockRate: number;\n payloadType: number;\n trackNumber: number;\n }[],\n streams?: {\n rtpStream?: Event<[RtpPacket]>;\n }\n ) {\n this.builder = new WEBMBuilder(tracks);\n\n tracks.forEach((t) => {\n this.timestamps[t.payloadType] = new TimestampManager(t.clockRate);\n });\n\n this.queue.push(() => this.init());\n\n if (streams?.rtpStream) {\n const { unSubscribe } = streams.rtpStream.subscribe((packet) => {\n this.pushRtpPackets([packet]);\n });\n this.disposer = unSubscribe;\n }\n }\n\n private async init() {\n const staticPart = Buffer.concat([\n this.builder.ebmlHeader,\n this.builder.createSegment(),\n ]);\n await this.fs.writeFile(this.path, staticPart);\n this.position += staticPart.length;\n\n const video = this.tracks.find((t) => t.kind === \"video\");\n if (video) {\n this.cuePoints.push(\n new CuePoint(this.builder, video.trackNumber, 0.0, this.position)\n );\n }\n\n const cluster = this.builder.createCluster(0.0);\n await this.fs.appendFile(this.path, cluster);\n this.position += cluster.length;\n }\n\n async stop() {\n this.stopped = true;\n if (this.disposer) {\n this.disposer();\n }\n\n const originStaticPartOffset = Buffer.concat([\n this.builder.ebmlHeader,\n this.builder.createSegment(),\n ]).length;\n const clusters = (await this.fs.readFile(this.path)).slice(\n originStaticPartOffset\n );\n\n const latestTimestamp = Object.values(this.timestamps).sort(\n (a, b) => a.relativeTimestamp - b.relativeTimestamp\n )[0].relativeTimestamp;\n const duration = this.relativeTimestamp + latestTimestamp;\n const staticPart = Buffer.concat([\n this.builder.ebmlHeader,\n this.builder.createSegment(duration),\n ]);\n // durationを挿入したことによるギャップの解消\n const staticPartGap = staticPart.length - originStaticPartOffset;\n this.cuePoints.forEach((c) => {\n c.position += staticPartGap;\n });\n\n let cuesSize = 0;\n let cues = this.builder.createCues(this.cuePoints.map((c) => c.build()));\n // cuesの最終的なサイズを再帰的に求める\n while (cuesSize !== cues.length) {\n cuesSize = cues.length;\n this.cuePoints.forEach((cue) => {\n cue.cuesLength += cuesSize;\n });\n cues = this.builder.createCues(this.cuePoints.map((c) => c.build()));\n }\n\n await this.fs.writeFile(this.path, staticPart);\n await this.fs.appendFile(this.path, cues);\n await this.fs.appendFile(this.path, clusters);\n }\n\n pushRtpPackets(packets: RtpPacket[]) {\n if (this.stopped) return;\n this.queue.push(() => this.onRtpPackets(packets));\n }\n\n private async onRtpPackets(packets: RtpPacket[]) {\n const track = this.tracks.find(\n (t) => t.payloadType === packets[0].header.payloadType\n );\n if (!track) {\n return;\n }\n\n const timestampManager = this.timestamps[track.payloadType];\n\n const { data, isKeyframe } = this.dePacketizeRtpPackets(\n track.codec,\n packets\n );\n\n const tailTimestamp = packets.slice(-1)[0].header.timestamp;\n timestampManager.update(tailTimestamp);\n\n if (\n (track.kind === \"video\" &&\n timestampManager.relativeTimestamp > 0 &&\n isKeyframe) ||\n timestampManager.relativeTimestamp > MaxSinged16Int\n ) {\n this.relativeTimestamp += timestampManager.relativeTimestamp;\n\n const cluster = this.builder.createCluster(this.relativeTimestamp);\n await this.fs.appendFile(this.path, cluster);\n this.cuePoints.push(\n new CuePoint(\n this.builder,\n track.trackNumber,\n this.relativeTimestamp,\n this.position\n )\n );\n this.position += cluster.length;\n Object.values(this.timestamps).forEach((t) => t.reset());\n }\n\n const block = this.builder.createSimpleBlock(\n data,\n isKeyframe,\n track.trackNumber,\n timestampManager.relativeTimestamp\n );\n await this.fs.appendFile(this.path, block);\n this.position += block.length;\n const [cuePoint] = this.cuePoints.slice(-1);\n if (cuePoint) {\n cuePoint.blockNumber++;\n }\n }\n\n private dePacketizeRtpPackets(codec: string, packets: RtpPacket[]) {\n const basicCodecParser = (\n DePacketizer: typeof DePacketizerBase\n ): { data: Buffer; isKeyframe: boolean } => {\n const frames = packets.map((p) => DePacketizer.deSerialize(p.payload));\n const isKeyframe = !!frames.find((f) => f.isKeyframe);\n const data = Buffer.concat(frames.map((f) => f.payload));\n return { isKeyframe, data };\n };\n\n switch (codec) {\n case \"AV1\": {\n const chunks = packets.map((p) => AV1RtpPayload.deSerialize(p.payload));\n const data = AV1RtpPayload.getFrame(chunks);\n const isKeyframe = !!chunks.find((f) => f.isKeyframe);\n return { isKeyframe, data };\n }\n case \"MPEG4/ISO/AVC\":\n return basicCodecParser(H264RtpPayload);\n case \"VP8\":\n return basicCodecParser(Vp8RtpPayload);\n case \"VP9\":\n return basicCodecParser(Vp9RtpPayload);\n case \"OPUS\":\n return basicCodecParser(OpusRtpPayload);\n default:\n throw new Error();\n }\n }\n}\n\nclass TimestampManager {\n private baseTimestamp?: number;\n relativeTimestamp = 0;\n\n constructor(public clockRate: number) {}\n\n reset() {\n this.baseTimestamp = undefined;\n this.relativeTimestamp = 0;\n }\n\n update(tailTimestamp: number) {\n if (this.baseTimestamp == undefined) {\n this.baseTimestamp = tailTimestamp;\n }\n const rotate =\n Math.abs(tailTimestamp - this.baseTimestamp) > (Max32Uint / 4) * 3;\n\n const elapsed = rotate\n ? tailTimestamp + Max32Uint - this.baseTimestamp\n : tailTimestamp - this.baseTimestamp;\n\n this.relativeTimestamp = int((elapsed / this.clockRate) * 1000);\n }\n}\n\nclass CuePoint {\n /**\n * cuesの後のclusterのあるべき位置\n * cuesはclusterの前に挿入される\n */\n cuesLength = 0;\n blockNumber = 0;\n\n constructor(\n private readonly builder: WEBMBuilder,\n private readonly trackNumber: number,\n private readonly relativeTimestamp: number,\n public position: number\n ) {}\n\n build() {\n return this.builder.createCuePoint(\n this.relativeTimestamp,\n this.trackNumber,\n this.position - 48 + this.cuesLength,\n this.blockNumber\n );\n }\n}\n\n/**4294967295 */\nconst Max32Uint = Number(0x01n << 32n) - 1;\n/**32767 */\nconst MaxSinged16Int = (0x01 << 16) / 2 - 1;\n"]}
1
+ {"version":3,"file":"webm.js","sourceRoot":"","sources":["../../../../../rtp/src/processor/webm.ts"],"names":[],"mappings":"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","sourcesContent":["import { BinaryLike } from \"crypto\";\nimport Event from \"rx.mini\";\n\nimport { int, PromiseQueue } from \"../../../common/src\";\nimport { RtpPacket } from \"..\";\nimport { dePacketizeRtpPackets } from \"../codec\";\nimport { SupportedCodec, WEBMBuilder } from \"../container/webm\";\nimport { Output } from \"./base\";\n\nexport interface FileIO {\n writeFile: (path: string, bin: BinaryLike) => Promise<void>;\n appendFile: (path: string, bin: BinaryLike) => Promise<void>;\n readFile: (path: string) => Promise<Buffer>;\n}\n\nexport class WebmOutput implements Output {\n private builder: WEBMBuilder;\n private queue = new PromiseQueue();\n private relativeTimestamp = 0;\n private timestamps: { [pt: number]: TimestampManager } = {};\n private disposer?: () => void;\n private cuePoints: CuePoint[] = [];\n private position = 0;\n stopped = false;\n\n constructor(\n private writer: FileIO,\n public path: string,\n public tracks: {\n width?: number;\n height?: number;\n kind: \"audio\" | \"video\";\n codec: SupportedCodec;\n clockRate: number;\n payloadType: number;\n trackNumber: number;\n }[],\n streams?: {\n rtpStream?: Event<[RtpPacket]>;\n }\n ) {\n this.builder = new WEBMBuilder(tracks);\n\n tracks.forEach((t) => {\n this.timestamps[t.payloadType] = new TimestampManager(t.clockRate);\n });\n\n this.queue.push(() => this.init());\n\n if (streams?.rtpStream) {\n const { unSubscribe } = streams.rtpStream.subscribe((packet) => {\n this.pushRtpPackets([packet]);\n });\n this.disposer = unSubscribe;\n }\n }\n\n private async init() {\n const staticPart = Buffer.concat([\n this.builder.ebmlHeader,\n this.builder.createSegment(),\n ]);\n await this.writer.writeFile(this.path, staticPart);\n this.position += staticPart.length;\n\n const video = this.tracks.find((t) => t.kind === \"video\");\n if (video) {\n this.cuePoints.push(\n new CuePoint(this.builder, video.trackNumber, 0.0, this.position)\n );\n }\n\n const cluster = this.builder.createCluster(0.0);\n await this.writer.appendFile(this.path, cluster);\n this.position += cluster.length;\n }\n\n async stop(insertDuration = true) {\n this.stopped = true;\n if (this.disposer) {\n this.disposer();\n }\n\n if (!insertDuration) {\n return;\n }\n\n const originStaticPartOffset = Buffer.concat([\n this.builder.ebmlHeader,\n this.builder.createSegment(),\n ]).length;\n const clusters = (await this.writer.readFile(this.path)).slice(\n originStaticPartOffset\n );\n\n const latestTimestamp = Object.values(this.timestamps).sort(\n (a, b) => a.relativeTimestamp - b.relativeTimestamp\n )[0].relativeTimestamp;\n const duration = this.relativeTimestamp + latestTimestamp;\n const staticPart = Buffer.concat([\n this.builder.ebmlHeader,\n this.builder.createSegment(duration),\n ]);\n // durationを挿入したことによるギャップの解消\n const staticPartGap = staticPart.length - originStaticPartOffset;\n this.cuePoints.forEach((c) => {\n c.position += staticPartGap;\n });\n\n let cuesSize = 0;\n let cues = this.builder.createCues(this.cuePoints.map((c) => c.build()));\n // cuesの最終的なサイズを再帰的に求める\n while (cuesSize !== cues.length) {\n cuesSize = cues.length;\n this.cuePoints.forEach((cue) => {\n cue.cuesLength += cuesSize;\n });\n cues = this.builder.createCues(this.cuePoints.map((c) => c.build()));\n }\n\n await this.writer.writeFile(this.path, staticPart);\n await this.writer.appendFile(this.path, cues);\n await this.writer.appendFile(this.path, clusters);\n }\n\n pushRtpPackets(packets: RtpPacket[]) {\n if (this.stopped) return;\n this.queue.push(() => this.onRtpPackets(packets));\n }\n\n private async onRtpPackets(packets: RtpPacket[]) {\n const track = this.tracks.find(\n (t) => t.payloadType === packets[0].header.payloadType\n );\n if (!track) {\n return;\n }\n\n const timestampManager = this.timestamps[track.payloadType];\n\n const { data, isKeyframe } = dePacketizeRtpPackets(track.codec, packets);\n\n const tailTimestamp = packets.slice(-1)[0].header.timestamp;\n timestampManager.update(tailTimestamp);\n\n if (\n (track.kind === \"video\" &&\n timestampManager.relativeTimestamp > 0 &&\n isKeyframe) ||\n timestampManager.relativeTimestamp > MaxSinged16Int\n ) {\n this.relativeTimestamp += timestampManager.relativeTimestamp;\n\n const cluster = this.builder.createCluster(this.relativeTimestamp);\n await this.writer.appendFile(this.path, cluster);\n this.cuePoints.push(\n new CuePoint(\n this.builder,\n track.trackNumber,\n this.relativeTimestamp,\n this.position\n )\n );\n this.position += cluster.length;\n Object.values(this.timestamps).forEach((t) => t.reset());\n }\n\n const block = this.builder.createSimpleBlock(\n data,\n isKeyframe,\n track.trackNumber,\n timestampManager.relativeTimestamp\n );\n await this.writer.appendFile(this.path, block);\n this.position += block.length;\n const [cuePoint] = this.cuePoints.slice(-1);\n if (cuePoint) {\n cuePoint.blockNumber++;\n }\n }\n}\n\nclass TimestampManager {\n private baseTimestamp?: number;\n relativeTimestamp = 0;\n\n constructor(public clockRate: number) {}\n\n reset() {\n this.baseTimestamp = undefined;\n this.relativeTimestamp = 0;\n }\n\n update(tailTimestamp: number) {\n if (this.baseTimestamp == undefined) {\n this.baseTimestamp = tailTimestamp;\n }\n const rotate =\n Math.abs(tailTimestamp - this.baseTimestamp) > (Max32Uint / 4) * 3;\n\n const elapsed = rotate\n ? tailTimestamp + Max32Uint - this.baseTimestamp\n : tailTimestamp - this.baseTimestamp;\n\n this.relativeTimestamp = int((elapsed / this.clockRate) * 1000);\n }\n}\n\nclass CuePoint {\n /**\n * cuesの後のclusterのあるべき位置\n * cuesはclusterの前に挿入される\n */\n cuesLength = 0;\n blockNumber = 0;\n\n constructor(\n private readonly builder: WEBMBuilder,\n private readonly trackNumber: number,\n private readonly relativeTimestamp: number,\n public position: number\n ) {}\n\n build() {\n return this.builder.createCuePoint(\n this.relativeTimestamp,\n this.trackNumber,\n this.position - 48 + this.cuesLength,\n this.blockNumber\n );\n }\n}\n\n/**4294967295 */\nconst Max32Uint = Number(0x01n << 32n) - 1;\n/**32767 */\nconst MaxSinged16Int = (0x01 << 16) / 2 - 1;\n"]}
@@ -0,0 +1,17 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ import { TransformStream } from "stream/web";
4
+ import { RtpHeader } from "..";
5
+ import { RtpOutput } from "./source/rtp";
6
+ export declare type DepacketizerInput = RtpOutput;
7
+ export interface DepacketizerOutput {
8
+ frame?: {
9
+ data: Buffer;
10
+ isKeyframe: boolean;
11
+ timestamp: number;
12
+ };
13
+ eol?: boolean;
14
+ }
15
+ export declare const depacketizeTransformer: (isFinalPacketInSequence: (header: RtpHeader) => boolean, codec: string, options?: {
16
+ waitForKeyframe?: boolean | undefined;
17
+ } | undefined) => TransformStream<RtpOutput, DepacketizerOutput>;
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.depacketizeTransformer = void 0;
7
+ const debug_1 = __importDefault(require("debug"));
8
+ const web_1 = require("stream/web");
9
+ const __1 = require("..");
10
+ const codec_1 = require("../codec");
11
+ const helper_1 = require("../helper");
12
+ const srcPath = `werift-rtp : packages/rtp/src/processor_v2/depacketizer.ts`;
13
+ const log = (0, debug_1.default)(srcPath);
14
+ const depacketizeTransformer = (...args) => new DepacketizeTransformer(...args).transform;
15
+ exports.depacketizeTransformer = depacketizeTransformer;
16
+ class DepacketizeTransformer {
17
+ constructor(isFinalPacketInSequence, codec, options = {}) {
18
+ this.isFinalPacketInSequence = isFinalPacketInSequence;
19
+ this.buffering = [];
20
+ this.packetLostHappened = false;
21
+ this.transform = new web_1.TransformStream({
22
+ transform: (input, output) => {
23
+ if (!input.rtp) {
24
+ if (input.eol) {
25
+ output.enqueue({ eol: true });
26
+ }
27
+ return;
28
+ }
29
+ const packets = this.onRtp(input.rtp);
30
+ if (packets) {
31
+ try {
32
+ const { data, isKeyframe } = (0, codec_1.dePacketizeRtpPackets)(codec, packets);
33
+ if (this.packetLostHappened) {
34
+ if (isKeyframe) {
35
+ this.packetLostHappened = false;
36
+ }
37
+ else if (options.waitForKeyframe) {
38
+ return;
39
+ }
40
+ }
41
+ output.enqueue({
42
+ frame: {
43
+ data,
44
+ isKeyframe,
45
+ timestamp: packets[0].header.timestamp,
46
+ },
47
+ });
48
+ }
49
+ catch (error) { }
50
+ }
51
+ },
52
+ });
53
+ }
54
+ onRtp(rtp) {
55
+ const { sequenceNumber } = rtp.header;
56
+ if (this.lastSeqNum != undefined) {
57
+ const expect = (0, __1.uint16Add)(this.lastSeqNum, 1);
58
+ if (sequenceNumber < expect) {
59
+ return;
60
+ }
61
+ if (sequenceNumber > expect) {
62
+ log("packet lost happened", { expect, sequenceNumber });
63
+ this.packetLostHappened = true;
64
+ this.buffering = [];
65
+ }
66
+ }
67
+ this.buffering.push(rtp);
68
+ this.lastSeqNum = sequenceNumber;
69
+ let finalPacket;
70
+ for (const [i, p] of (0, helper_1.enumerate)(this.buffering)) {
71
+ if (this.isFinalPacketInSequence(p.header)) {
72
+ finalPacket = i;
73
+ break;
74
+ }
75
+ }
76
+ if (finalPacket == undefined) {
77
+ return;
78
+ }
79
+ const packets = this.buffering;
80
+ this.buffering = [];
81
+ return packets;
82
+ }
83
+ }
84
+ //# sourceMappingURL=depacketizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"depacketizer.js","sourceRoot":"","sources":["../../../../../rtp/src/processor_v2/depacketizer.ts"],"names":[],"mappings":"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","sourcesContent":["import debug from \"debug\";\nimport { TransformStream } from \"stream/web\";\n\nimport { uint16Add } from \"..\";\nimport { RtpHeader, RtpPacket } from \"..\";\nimport { dePacketizeRtpPackets } from \"../codec\";\nimport { enumerate } from \"../helper\";\nimport { RtpOutput } from \"./source/rtp\";\n\nconst srcPath = `werift-rtp : packages/rtp/src/processor_v2/depacketizer.ts`;\nconst log = debug(srcPath);\n\nexport type DepacketizerInput = RtpOutput;\n\nexport interface DepacketizerOutput {\n frame?: { data: Buffer; isKeyframe: boolean; timestamp: number };\n eol?: boolean;\n}\n\nexport const depacketizeTransformer = (\n ...args: ConstructorParameters<typeof DepacketizeTransformer>\n) => new DepacketizeTransformer(...args).transform;\n\nclass DepacketizeTransformer {\n private buffering: RtpPacket[] = [];\n\n transform: TransformStream<DepacketizerInput, DepacketizerOutput>;\n packetLostHappened = false;\n\n constructor(\n private isFinalPacketInSequence: (header: RtpHeader) => boolean,\n codec: string,\n options: { waitForKeyframe?: boolean } = {}\n ) {\n this.transform = new TransformStream({\n transform: (input, output) => {\n if (!input.rtp) {\n if (input.eol) {\n output.enqueue({ eol: true });\n }\n return;\n }\n\n const packets = this.onRtp(input.rtp);\n if (packets) {\n try {\n const { data, isKeyframe } = dePacketizeRtpPackets(codec, packets);\n\n if (this.packetLostHappened) {\n if (isKeyframe) {\n this.packetLostHappened = false;\n } else if (options.waitForKeyframe) {\n return;\n }\n }\n\n output.enqueue({\n frame: {\n data,\n isKeyframe,\n timestamp: packets[0].header.timestamp,\n },\n });\n } catch (error) {}\n }\n },\n });\n }\n\n lastSeqNum?: number;\n private onRtp(rtp: RtpPacket) {\n const { sequenceNumber } = rtp.header;\n if (this.lastSeqNum != undefined) {\n const expect = uint16Add(this.lastSeqNum, 1);\n if (sequenceNumber < expect) {\n return;\n }\n if (sequenceNumber > expect) {\n log(\"packet lost happened\", { expect, sequenceNumber });\n this.packetLostHappened = true;\n this.buffering = [];\n }\n }\n\n this.buffering.push(rtp);\n this.lastSeqNum = sequenceNumber;\n\n let finalPacket: number | undefined;\n for (const [i, p] of enumerate(this.buffering)) {\n if (this.isFinalPacketInSequence(p.header)) {\n finalPacket = i;\n break;\n }\n }\n if (finalPacket == undefined) {\n return;\n }\n\n const packets = this.buffering;\n this.buffering = [];\n\n return packets;\n }\n}\n"]}
@@ -0,0 +1,4 @@
1
+ export * from "./depacketizer";
2
+ export * from "./jitterBuffer";
3
+ export * from "./source";
4
+ export * from "./webmLive";
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./depacketizer"), exports);
18
+ __exportStar(require("./jitterBuffer"), exports);
19
+ __exportStar(require("./source"), exports);
20
+ __exportStar(require("./webmLive"), exports);
21
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../rtp/src/processor_v2/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,iDAA+B;AAC/B,iDAA+B;AAC/B,2CAAyB;AACzB,6CAA2B","sourcesContent":["export * from \"./depacketizer\";\nexport * from \"./jitterBuffer\";\nexport * from \"./source\";\nexport * from \"./webmLive\";\n"]}
@@ -0,0 +1,33 @@
1
+ /// <reference types="node" />
2
+ import { TransformStream } from "stream/web";
3
+ import { RtpPacket } from "..";
4
+ import { RtpOutput } from "./source/rtp";
5
+ export declare type JitterBufferInput = RtpOutput;
6
+ export interface JitterBufferOutput extends RtpOutput {
7
+ isPacketLost?: {
8
+ from: number;
9
+ to: number;
10
+ };
11
+ }
12
+ export declare const jitterBufferTransformer: (clockRate: number, options?: Partial<JitterBufferOptions> | undefined) => TransformStream<RtpOutput, JitterBufferOutput>;
13
+ export declare class JitterBufferTransformer {
14
+ clockRate: number;
15
+ transform: TransformStream<JitterBufferInput, JitterBufferOutput>;
16
+ options: JitterBufferOptions;
17
+ presentSeqNum?: number;
18
+ rtpBuffer: {
19
+ [sequenceNumber: number]: RtpPacket;
20
+ };
21
+ private get expectNextSeqNum();
22
+ constructor(clockRate: number, options?: Partial<JitterBufferOptions>);
23
+ private processRtp;
24
+ private pushRtpBuffer;
25
+ private resolveBuffer;
26
+ private sortAndClearBuffer;
27
+ private disposeTimeoutPackets;
28
+ }
29
+ export interface JitterBufferOptions {
30
+ /**milliseconds */
31
+ latency: number;
32
+ bufferSize: number;
33
+ }
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.JitterBufferTransformer = exports.jitterBufferTransformer = void 0;
7
+ const debug_1 = __importDefault(require("debug"));
8
+ const web_1 = require("stream/web");
9
+ const __1 = require("..");
10
+ const srcPath = `werift-rtp : packages/rtp/src/processor_v2/jitterBuffer.ts`;
11
+ const log = (0, debug_1.default)(srcPath);
12
+ const jitterBufferTransformer = (...args) => new JitterBufferTransformer(...args).transform;
13
+ exports.jitterBufferTransformer = jitterBufferTransformer;
14
+ class JitterBufferTransformer {
15
+ constructor(clockRate, options = {}) {
16
+ this.clockRate = clockRate;
17
+ this.rtpBuffer = {};
18
+ this.options = {
19
+ latency: options.latency ?? 200,
20
+ bufferSize: options.bufferSize ?? 10000,
21
+ };
22
+ this.transform = new web_1.TransformStream({
23
+ transform: (input, output) => {
24
+ if (!input.rtp) {
25
+ if (input.eol) {
26
+ const packets = this.sortAndClearBuffer(this.rtpBuffer);
27
+ packets.forEach((rtp) => output.enqueue({ rtp }));
28
+ output.enqueue({ eol: true });
29
+ }
30
+ return;
31
+ }
32
+ const { packets, timeoutSeqNum } = this.processRtp(input.rtp);
33
+ if (timeoutSeqNum != undefined) {
34
+ const isPacketLost = {
35
+ from: this.expectNextSeqNum,
36
+ to: timeoutSeqNum,
37
+ };
38
+ this.presentSeqNum = input.rtp.header.sequenceNumber;
39
+ output.enqueue({ isPacketLost });
40
+ if (packets) {
41
+ [...packets, input.rtp].forEach((rtp) => output.enqueue({ rtp }));
42
+ }
43
+ }
44
+ else {
45
+ if (packets) {
46
+ packets.forEach((rtp) => output.enqueue({ rtp }));
47
+ }
48
+ }
49
+ },
50
+ });
51
+ }
52
+ get expectNextSeqNum() {
53
+ return (0, __1.uint16Add)(this.presentSeqNum, 1);
54
+ }
55
+ processRtp(rtp) {
56
+ const { sequenceNumber, timestamp } = rtp.header;
57
+ if (this.presentSeqNum == undefined) {
58
+ this.presentSeqNum = sequenceNumber;
59
+ return { packets: [rtp] };
60
+ }
61
+ if (sequenceNumber <= this.presentSeqNum) {
62
+ return { nothing: undefined };
63
+ }
64
+ if (sequenceNumber === this.expectNextSeqNum) {
65
+ this.presentSeqNum = sequenceNumber;
66
+ const rtpBuffer = this.resolveBuffer((0, __1.uint16Add)(sequenceNumber, 1));
67
+ this.presentSeqNum =
68
+ rtpBuffer.at(-1)?.header.sequenceNumber ?? this.presentSeqNum;
69
+ return { packets: [rtp, ...rtpBuffer] };
70
+ }
71
+ this.pushRtpBuffer(rtp);
72
+ const { latestTimeoutSeqNum, sorted } = this.disposeTimeoutPackets(timestamp);
73
+ if (latestTimeoutSeqNum) {
74
+ return { timeoutSeqNum: latestTimeoutSeqNum, packets: sorted };
75
+ }
76
+ else {
77
+ return { nothing: undefined };
78
+ }
79
+ }
80
+ pushRtpBuffer(rtp) {
81
+ if (Object.values(this.rtpBuffer).length > this.options.bufferSize) {
82
+ return;
83
+ }
84
+ this.rtpBuffer[rtp.header.sequenceNumber] = rtp;
85
+ }
86
+ resolveBuffer(seqNumFrom) {
87
+ const resolve = [];
88
+ for (let index = seqNumFrom;; index = (0, __1.uint16Add)(index, 1)) {
89
+ const rtp = this.rtpBuffer[index];
90
+ if (rtp) {
91
+ resolve.push(rtp);
92
+ delete this.rtpBuffer[index];
93
+ }
94
+ else {
95
+ break;
96
+ }
97
+ }
98
+ return resolve;
99
+ }
100
+ sortAndClearBuffer(rtpBuffer) {
101
+ const buffer = [];
102
+ for (let index = this.presentSeqNum ?? 0;; index = (0, __1.uint16Add)(index, 1)) {
103
+ const rtp = rtpBuffer[index];
104
+ if (rtp) {
105
+ buffer.push(rtp);
106
+ delete rtpBuffer[index];
107
+ }
108
+ if (Object.values(rtpBuffer).length === 0) {
109
+ break;
110
+ }
111
+ }
112
+ return buffer;
113
+ }
114
+ disposeTimeoutPackets(baseTimestamp) {
115
+ let latestTimeoutSeqNum;
116
+ const packets = Object.values(this.rtpBuffer)
117
+ .map((rtp) => {
118
+ const { timestamp, sequenceNumber } = rtp.header;
119
+ if ((0, __1.uint32Gt)(timestamp, baseTimestamp)) {
120
+ log("gap", { timestamp, baseTimestamp });
121
+ return;
122
+ }
123
+ const elapsedSec = (0, __1.uint32Add)(baseTimestamp, -timestamp) / this.clockRate;
124
+ if (elapsedSec * 1000 > this.options.latency) {
125
+ log("timeout packet", {
126
+ sequenceNumber,
127
+ elapsedSec,
128
+ baseTimestamp,
129
+ timestamp,
130
+ });
131
+ if (latestTimeoutSeqNum == undefined) {
132
+ latestTimeoutSeqNum = sequenceNumber;
133
+ }
134
+ // 現在のSeqNumとの差が最も大きいSeqNumを探す
135
+ if ((0, __1.uint16Add)(sequenceNumber, -this.presentSeqNum) >
136
+ (0, __1.uint16Add)(latestTimeoutSeqNum, -this.presentSeqNum)) {
137
+ latestTimeoutSeqNum = sequenceNumber;
138
+ }
139
+ const packet = this.rtpBuffer[sequenceNumber];
140
+ delete this.rtpBuffer[sequenceNumber];
141
+ return packet;
142
+ }
143
+ })
144
+ .flatMap((p) => p)
145
+ .filter((p) => p);
146
+ const sorted = this.sortAndClearBuffer(packets.reduce((acc, cur) => {
147
+ acc[cur.header.sequenceNumber] = cur;
148
+ return acc;
149
+ }, {}));
150
+ return { latestTimeoutSeqNum, sorted };
151
+ }
152
+ }
153
+ exports.JitterBufferTransformer = JitterBufferTransformer;
154
+ //# sourceMappingURL=jitterBuffer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jitterBuffer.js","sourceRoot":"","sources":["../../../../../rtp/src/processor_v2/jitterBuffer.ts"],"names":[],"mappings":"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","sourcesContent":["import debug from \"debug\";\nimport { TransformStream } from \"stream/web\";\n\nimport {\n RequireAtLeastOne,\n RtpPacket,\n uint16Add,\n uint32Add,\n uint32Gt,\n} from \"..\";\nimport { RtpOutput } from \"./source/rtp\";\n\nconst srcPath = `werift-rtp : packages/rtp/src/processor_v2/jitterBuffer.ts`;\nconst log = debug(srcPath);\n\nexport type JitterBufferInput = RtpOutput;\n\nexport interface JitterBufferOutput extends RtpOutput {\n isPacketLost?: { from: number; to: number };\n}\n\nexport const jitterBufferTransformer = (\n ...args: ConstructorParameters<typeof JitterBufferTransformer>\n) => new JitterBufferTransformer(...args).transform;\n\nexport class JitterBufferTransformer {\n transform: TransformStream<JitterBufferInput, JitterBufferOutput>;\n options: JitterBufferOptions;\n presentSeqNum?: number;\n rtpBuffer: { [sequenceNumber: number]: RtpPacket } = {};\n\n private get expectNextSeqNum() {\n return uint16Add(this.presentSeqNum!, 1);\n }\n\n constructor(\n public clockRate: number,\n options: Partial<JitterBufferOptions> = {}\n ) {\n this.options = {\n latency: options.latency ?? 200,\n bufferSize: options.bufferSize ?? 10000,\n };\n\n this.transform = new TransformStream({\n transform: (input, output) => {\n if (!input.rtp) {\n if (input.eol) {\n const packets = this.sortAndClearBuffer(this.rtpBuffer);\n packets.forEach((rtp) => output.enqueue({ rtp }));\n output.enqueue({ eol: true });\n }\n return;\n }\n\n const { packets, timeoutSeqNum } = this.processRtp(input.rtp);\n\n if (timeoutSeqNum != undefined) {\n const isPacketLost = {\n from: this.expectNextSeqNum,\n to: timeoutSeqNum,\n };\n this.presentSeqNum = input.rtp.header.sequenceNumber;\n output.enqueue({ isPacketLost });\n if (packets) {\n [...packets, input.rtp].forEach((rtp) => output.enqueue({ rtp }));\n }\n } else {\n if (packets) {\n packets.forEach((rtp) => output.enqueue({ rtp }));\n }\n }\n },\n });\n }\n\n private processRtp(rtp: RtpPacket): RequireAtLeastOne<{\n packets: RtpPacket[];\n timeoutSeqNum: number;\n nothing: undefined;\n }> {\n const { sequenceNumber, timestamp } = rtp.header;\n\n if (this.presentSeqNum == undefined) {\n this.presentSeqNum = sequenceNumber;\n return { packets: [rtp] };\n }\n\n if (sequenceNumber <= this.presentSeqNum) {\n return { nothing: undefined };\n }\n\n if (sequenceNumber === this.expectNextSeqNum) {\n this.presentSeqNum = sequenceNumber;\n\n const rtpBuffer = this.resolveBuffer(uint16Add(sequenceNumber, 1));\n this.presentSeqNum =\n rtpBuffer.at(-1)?.header.sequenceNumber ?? this.presentSeqNum;\n\n return { packets: [rtp, ...rtpBuffer] };\n }\n\n this.pushRtpBuffer(rtp);\n\n const { latestTimeoutSeqNum, sorted } =\n this.disposeTimeoutPackets(timestamp);\n\n if (latestTimeoutSeqNum) {\n return { timeoutSeqNum: latestTimeoutSeqNum, packets: sorted };\n } else {\n return { nothing: undefined };\n }\n }\n\n private pushRtpBuffer(rtp: RtpPacket) {\n if (Object.values(this.rtpBuffer).length > this.options.bufferSize) {\n return;\n }\n\n this.rtpBuffer[rtp.header.sequenceNumber] = rtp;\n }\n\n private resolveBuffer(seqNumFrom: number) {\n const resolve: RtpPacket[] = [];\n\n for (let index = seqNumFrom; ; index = uint16Add(index, 1)) {\n const rtp = this.rtpBuffer[index];\n if (rtp) {\n resolve.push(rtp);\n delete this.rtpBuffer[index];\n } else {\n break;\n }\n }\n return resolve;\n }\n\n private sortAndClearBuffer(rtpBuffer: {\n [sequenceNumber: number]: RtpPacket;\n }) {\n const buffer: RtpPacket[] = [];\n for (let index = this.presentSeqNum ?? 0; ; index = uint16Add(index, 1)) {\n const rtp = rtpBuffer[index];\n if (rtp) {\n buffer.push(rtp);\n delete rtpBuffer[index];\n }\n if (Object.values(rtpBuffer).length === 0) {\n break;\n }\n }\n return buffer;\n }\n\n private disposeTimeoutPackets(baseTimestamp: number) {\n let latestTimeoutSeqNum: number | undefined;\n\n const packets = Object.values(this.rtpBuffer)\n .map((rtp) => {\n const { timestamp, sequenceNumber } = rtp.header;\n\n if (uint32Gt(timestamp, baseTimestamp)) {\n log(\"gap\", { timestamp, baseTimestamp });\n return;\n }\n\n const elapsedSec =\n uint32Add(baseTimestamp, -timestamp) / this.clockRate;\n\n if (elapsedSec * 1000 > this.options.latency) {\n log(\"timeout packet\", {\n sequenceNumber,\n elapsedSec,\n baseTimestamp,\n timestamp,\n });\n\n if (latestTimeoutSeqNum == undefined) {\n latestTimeoutSeqNum = sequenceNumber;\n }\n // 現在のSeqNumとの差が最も大きいSeqNumを探す\n if (\n uint16Add(sequenceNumber, -this.presentSeqNum!) >\n uint16Add(latestTimeoutSeqNum, -this.presentSeqNum!)\n ) {\n latestTimeoutSeqNum = sequenceNumber;\n }\n\n const packet = this.rtpBuffer[sequenceNumber];\n delete this.rtpBuffer[sequenceNumber];\n return packet;\n }\n })\n .flatMap((p): RtpPacket => p as RtpPacket)\n .filter((p) => p);\n\n const sorted = this.sortAndClearBuffer(\n packets.reduce((acc, cur) => {\n acc[cur.header.sequenceNumber] = cur;\n return acc;\n }, {})\n );\n\n return { latestTimeoutSeqNum, sorted };\n }\n}\n\nexport interface JitterBufferOptions {\n /**milliseconds */\n latency: number;\n bufferSize: number;\n}\n"]}
@@ -0,0 +1,8 @@
1
+ /// <reference types="node" />
2
+ import { ReadableStream, ReadableStreamController } from "stream/web";
3
+ export declare class SourceStream<T> {
4
+ readable: ReadableStream<T>;
5
+ write: (chunk: T) => void;
6
+ protected controller: ReadableStreamController<T>;
7
+ constructor();
8
+ }
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SourceStream = void 0;
4
+ const web_1 = require("stream/web");
5
+ class SourceStream {
6
+ constructor() {
7
+ this.readable = new web_1.ReadableStream({
8
+ start: (controller) => {
9
+ this.controller = controller;
10
+ this.write = (chunk) => controller.enqueue(chunk);
11
+ },
12
+ });
13
+ }
14
+ }
15
+ exports.SourceStream = SourceStream;
16
+ //# sourceMappingURL=base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../../../../../rtp/src/processor_v2/source/base.ts"],"names":[],"mappings":";;;AAAA,oCAAsE;AAEtE,MAAa,YAAY;IAKvB;QACE,IAAI,CAAC,QAAQ,GAAG,IAAI,oBAAc,CAAC;YACjC,KAAK,EAAE,CAAC,UAAU,EAAE,EAAE;gBACpB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;gBAC7B,IAAI,CAAC,KAAK,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YACpD,CAAC;SACF,CAAC,CAAC;IACL,CAAC;CACF;AAbD,oCAaC","sourcesContent":["import { ReadableStream, ReadableStreamController } from \"stream/web\";\n\nexport class SourceStream<T> {\n readable: ReadableStream<T>;\n write!: (chunk: T) => void;\n protected controller!: ReadableStreamController<T>;\n\n constructor() {\n this.readable = new ReadableStream({\n start: (controller) => {\n this.controller = controller;\n this.write = (chunk) => controller.enqueue(chunk);\n },\n });\n }\n}\n"]}
@@ -0,0 +1,2 @@
1
+ import { RtpSourceStream } from "./rtp";
2
+ export { RtpSourceStream };
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RtpSourceStream = void 0;
4
+ const rtp_1 = require("./rtp");
5
+ Object.defineProperty(exports, "RtpSourceStream", { enumerable: true, get: function () { return rtp_1.RtpSourceStream; } });
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../rtp/src/processor_v2/source/index.ts"],"names":[],"mappings":";;;AAAA,+BAAwC;AAE/B,gGAFA,qBAAe,OAEA","sourcesContent":["import { RtpSourceStream } from \"./rtp\";\n\nexport { RtpSourceStream };\n"]}
@@ -0,0 +1,14 @@
1
+ import Event from "rx.mini";
2
+ import { RtpPacket } from "../../rtp/rtp";
3
+ import { SourceStream } from "./base";
4
+ export interface RtpOutput {
5
+ rtp?: RtpPacket;
6
+ eol?: boolean;
7
+ }
8
+ export declare class RtpSourceStream extends SourceStream<RtpOutput> {
9
+ private readonly disposer;
10
+ constructor(ev: Event<[RtpPacket]>, options?: {
11
+ payloadType?: number;
12
+ });
13
+ stop(): Promise<void>;
14
+ }
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RtpSourceStream = void 0;
4
+ const rx_mini_1 = require("rx.mini");
5
+ const base_1 = require("./base");
6
+ class RtpSourceStream extends base_1.SourceStream {
7
+ constructor(ev, options = {}) {
8
+ super();
9
+ this.disposer = new rx_mini_1.EventDisposer();
10
+ ev.subscribe((rtp) => {
11
+ if (options.payloadType != undefined &&
12
+ options.payloadType !== rtp.header.payloadType) {
13
+ return;
14
+ }
15
+ this.write({ rtp });
16
+ }).disposer(this.disposer);
17
+ }
18
+ async stop() {
19
+ this.controller.enqueue({ eol: true });
20
+ this.disposer.dispose();
21
+ }
22
+ }
23
+ exports.RtpSourceStream = RtpSourceStream;
24
+ //# sourceMappingURL=rtp.js.map