mediasoup 3.24.2 → 3.26.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 (55) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/node/lib/Consumer.js +1 -1
  3. package/node/lib/Transport.d.ts.map +1 -1
  4. package/node/lib/Transport.js +7 -0
  5. package/node/lib/ortc.d.ts.map +1 -1
  6. package/node/lib/ortc.js +10 -0
  7. package/node/lib/test/test-PipeTransport.js +35 -30
  8. package/package.json +6 -6
  9. package/worker/include/DepLibUV.hpp +33 -4
  10. package/worker/include/RTC/Consumer.hpp +4 -1
  11. package/worker/include/RTC/Producer.hpp +34 -5
  12. package/worker/include/RTC/RTCP/Packet.hpp +7 -1
  13. package/worker/include/RTC/RTP/Packet.hpp +18 -0
  14. package/worker/include/RTC/RTP/RtpStream.hpp +76 -14
  15. package/worker/include/RTC/RTP/RtpStreamRecv.hpp +191 -7
  16. package/worker/include/RTC/RTP/RtpStreamSend.hpp +56 -10
  17. package/worker/include/RTC/RTP/RtxStream.hpp +34 -2
  18. package/worker/include/RTC/RemoteCaptureTimeEstimator.hpp +92 -0
  19. package/worker/include/RTC/RemoteClockOffsetEstimator.hpp +87 -0
  20. package/worker/include/RTC/Router.hpp +2 -5
  21. package/worker/include/RTC/SimulcastProducerStreamManager.hpp +3 -0
  22. package/worker/include/RTC/Transport.hpp +15 -7
  23. package/worker/include/Shared.hpp +5 -0
  24. package/worker/include/SharedInterface.hpp +6 -0
  25. package/worker/include/Utils.hpp +44 -3
  26. package/worker/meson.build +4 -0
  27. package/worker/mocks/include/MockShared.hpp +7 -0
  28. package/worker/src/DepLibUV.cpp +17 -0
  29. package/worker/src/RTC/Consumer.cpp +8 -5
  30. package/worker/src/RTC/Producer.cpp +85 -16
  31. package/worker/src/RTC/RTP/Packet.cpp +9 -1
  32. package/worker/src/RTC/RTP/RtpStream.cpp +14 -10
  33. package/worker/src/RTC/RTP/RtpStreamRecv.cpp +150 -23
  34. package/worker/src/RTC/RTP/RtpStreamSend.cpp +34 -19
  35. package/worker/src/RTC/RTP/RtxStream.cpp +12 -6
  36. package/worker/src/RTC/RemoteCaptureTimeEstimator.cpp +77 -0
  37. package/worker/src/RTC/RemoteClockOffsetEstimator.cpp +106 -0
  38. package/worker/src/RTC/Router.cpp +10 -8
  39. package/worker/src/RTC/RtpDictionaries/RtcpParameters.cpp +13 -3
  40. package/worker/src/RTC/SCTP/packet/chunks/SackChunk.cpp +6 -2
  41. package/worker/src/RTC/SimulcastProducerStreamManager.cpp +115 -56
  42. package/worker/src/RTC/SvcProducerStreamManager.cpp +22 -17
  43. package/worker/src/RTC/Transport.cpp +96 -4
  44. package/worker/test/src/RTC/RTP/TestPacket.cpp +6 -0
  45. package/worker/test/src/RTC/RTP/TestRtpStreamRecv.cpp +2 -2
  46. package/worker/test/src/RTC/RTP/TestRtpStreamSend.cpp +119 -0
  47. package/worker/test/src/RTC/TestConsumer.cpp +4 -3
  48. package/worker/test/src/RTC/TestPortManager.cpp +1 -1
  49. package/worker/test/src/RTC/TestRemoteCaptureTimeEstimator.cpp +164 -0
  50. package/worker/test/src/RTC/TestRemoteClockOffsetEstimator.cpp +241 -0
  51. package/worker/test/src/RTC/TestSimpleProducerStreamManager.cpp +2 -2
  52. package/worker/test/src/RTC/TestSimulcastProducerStreamManager.cpp +340 -15
  53. package/worker/test/src/RTC/TestSvcProducerStreamManager.cpp +2 -2
  54. package/worker/test/src/RTC/TestTransportTuple.cpp +1 -1
  55. package/worker/test/src/Utils/TestTime.cpp +49 -0
package/CHANGELOG.md CHANGED
@@ -2,6 +2,22 @@
2
2
 
3
3
  ### NEXT
4
4
 
5
+ ### 3.26.0
6
+
7
+ - **Breaking change:** Simulcast and SVC: Limit temporal layer to the preferred one ([PR #1892](https://github.com/versatica/mediasoup/pull/1892)).
8
+
9
+ ### 3.25.0
10
+
11
+ - Worker: Fix undefined behavior in `RtpStreamRecv::UpdateScore()` when no packets were received ([PR #1886](https://github.com/versatica/mediasoup/pull/1886)).
12
+ - SCTP: Fix `SackChunk::GetValidatedGapAckBlocks()` returning a bogus gap-ack-block ([PR #1891](https://github.com/versatica/mediasoup/pull/1891)).
13
+ - Do not make generated RTCP Sender Reports depend on RTP packet arrival time ([issue #1881](https://github.com/versatica/mediasoup/issues/1881)):
14
+ - `RemoteClockOffsetEstimator` class ([PR #1882](https://github.com/versatica/mediasoup/pull/1882)).
15
+ - Prepare `RtpStream` classes for capture time based RTCP Sender Reports ([PR #1883](https://github.com/versatica/mediasoup/pull/1883), [PR #1888](https://github.com/versatica/mediasoup/pull/1888)).
16
+ - `RemoteCaptureTimeEstimator` class ([PR #1884](https://github.com/versatica/mediasoup/pull/1884)).
17
+ - Estimate the capture instant of each received RTP packet ([PR #1885](https://github.com/versatica/mediasoup/pull/1885)).
18
+ - Generate RTCP Sender Reports based on the capture instant of the media rather than on the packet arrival time ([PR #1887](https://github.com/versatica/mediasoup/pull/1887)).
19
+ - `SimulcastProducerStreamManager`: Apply new capture time logic and fix 'abs-capture-time' rewriting ([PR #1889](https://github.com/versatica/mediasoup/pull/1889)).
20
+
5
21
  ### 3.24.2
6
22
 
7
23
  - Worker: Verify `DataConsumer` subchannels before cloning the message ([PR #1880](https://github.com/versatica/mediasoup/pull/1880)).
@@ -211,7 +211,7 @@ class ConsumerImpl extends enhancedEvents_1.EnhancedEventEmitter {
211
211
  if (typeof spatialLayer !== 'number') {
212
212
  throw new TypeError('spatialLayer must be a number');
213
213
  }
214
- if (temporalLayer && typeof temporalLayer !== 'number') {
214
+ if (temporalLayer != null && typeof temporalLayer !== 'number') {
215
215
  throw new TypeError('if given, temporalLayer must be a number');
216
216
  }
217
217
  const builder = this.#channel.bufferBuilder;
@@ -1 +1 @@
1
- {"version":3,"file":"Transport.d.ts","sourceRoot":"","sources":["../src/Transport.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Transport.d.ts","sourceRoot":"","sources":["../src/Transport.ts"],"names":[],"mappings":"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"}
@@ -310,6 +310,13 @@ class TransportImpl extends enhancedEvents_1.EnhancedEventEmitter {
310
310
  clonedRtpParameters.rtcp = clonedRtpParameters.rtcp ?? {};
311
311
  clonedRtpParameters.rtcp.cname = this.#cnameForProducers;
312
312
  }
313
+ // In a PipeTransport, give a random CNAME to a Producer that comes without one.
314
+ // Its own one, since a CNAME shared with the other Producers without CNAME would
315
+ // tell the worker that they all come from a same sender and share its clock.
316
+ else if (!clonedRtpParameters.rtcp?.cname) {
317
+ clonedRtpParameters.rtcp = clonedRtpParameters.rtcp ?? {};
318
+ clonedRtpParameters.rtcp.cname = utils.generateUUIDv4().substr(0, 8);
319
+ }
313
320
  const routerRtpCapabilities = this.#getRouterRtpCapabilities();
314
321
  // This may throw.
315
322
  const rtpMapping = ortc.getProducerRtpParametersMapping(clonedRtpParameters, routerRtpCapabilities);
@@ -1 +1 @@
1
- {"version":3,"file":"ortc.d.ts","sourceRoot":"","sources":["../src/ortc.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,WAAW,MAAM,aAAa,CAAC;AAGhD,OAAO,KAAK,EACX,eAAe,EACf,qBAAqB,EAGrB,wBAAwB,EAExB,aAAa,EAMb,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAKlE,MAAM,MAAM,yBAAyB,GAAG;IACvC,MAAM,EAAE;QACP,WAAW,EAAE,MAAM,CAAC;QACpB,iBAAiB,EAAE,MAAM,CAAC;KAC1B,EAAE,CAAC;IACJ,SAAS,EAAE;QACV,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,UAAU,EAAE,MAAM,CAAC;KACnB,EAAE,CAAC;CACJ,CAAC;AAoBF;;;;GAIG;AACH,wBAAgB,mCAAmC,CAClD,IAAI,EAAE,eAAe,GAAG,qBAAqB,GAC3C,IAAI,CA0BN;AAED;;;;GAIG;AACH,wBAAgB,iCAAiC,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAsD7E;AAED;;;;GAIG;AACH,wBAAgB,wCAAwC,CACvD,MAAM,EAAE,oBAAoB,GAC1B,IAAI,CAoDN;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAC5C,WAAW,GAAE,wBAAwB,EAAO,GAC1C,eAAe,CA+HjB;AAED;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAC9C,MAAM,EAAE,aAAa,EACrB,IAAI,EAAE,eAAe,GACnB,yBAAyB,CAyF3B;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CACzC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,aAAa,EACrB,IAAI,EAAE,eAAe,EACrB,UAAU,EAAE,yBAAyB,GACnC,aAAa,CAkGf;AAED;;GAEG;AACH,wBAAgB,UAAU,CACzB,gBAAgB,EAAE,aAAa,EAC/B,IAAI,EAAE,eAAe,GACnB,OAAO,CAwBT;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,EACxC,uBAAuB,EACvB,qBAAqB,EACrB,IAAI,EACJ,SAAS,GACT,EAAE;IACF,uBAAuB,EAAE,aAAa,CAAC;IACvC,qBAAqB,EAAE,eAAe,CAAC;IACvC,IAAI,EAAE,OAAO,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;CACnB,GAAG,aAAa,CAiLhB;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,EAC5C,uBAAuB,EACvB,SAAS,GACT,EAAE;IACF,uBAAuB,EAAE,aAAa,CAAC;IACvC,SAAS,EAAE,OAAO,CAAC;CACnB,GAAG,aAAa,CA4EhB;AAED,wBAAgB,mBAAmB,CAClC,OAAO,EAAE,WAAW,CAAC,OAAO,EAC5B,UAAU,EAAE,yBAAyB,GACnC,MAAM,CAyCR"}
1
+ {"version":3,"file":"ortc.d.ts","sourceRoot":"","sources":["../src/ortc.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,WAAW,MAAM,aAAa,CAAC;AAGhD,OAAO,KAAK,EACX,eAAe,EACf,qBAAqB,EAGrB,wBAAwB,EAExB,aAAa,EAMb,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAKlE,MAAM,MAAM,yBAAyB,GAAG;IACvC,MAAM,EAAE;QACP,WAAW,EAAE,MAAM,CAAC;QACpB,iBAAiB,EAAE,MAAM,CAAC;KAC1B,EAAE,CAAC;IACJ,SAAS,EAAE;QACV,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,UAAU,EAAE,MAAM,CAAC;KACnB,EAAE,CAAC;CACJ,CAAC;AAoBF;;;;GAIG;AACH,wBAAgB,mCAAmC,CAClD,IAAI,EAAE,eAAe,GAAG,qBAAqB,GAC3C,IAAI,CA0BN;AAED;;;;GAIG;AACH,wBAAgB,iCAAiC,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAsD7E;AAED;;;;GAIG;AACH,wBAAgB,wCAAwC,CACvD,MAAM,EAAE,oBAAoB,GAC1B,IAAI,CAoDN;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAC5C,WAAW,GAAE,wBAAwB,EAAO,GAC1C,eAAe,CA+HjB;AAED;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAC9C,MAAM,EAAE,aAAa,EACrB,IAAI,EAAE,eAAe,GACnB,yBAAyB,CAyF3B;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CACzC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,aAAa,EACrB,IAAI,EAAE,eAAe,EACrB,UAAU,EAAE,yBAAyB,GACnC,aAAa,CA+Gf;AAED;;GAEG;AACH,wBAAgB,UAAU,CACzB,gBAAgB,EAAE,aAAa,EAC/B,IAAI,EAAE,eAAe,GACnB,OAAO,CAwBT;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,EACxC,uBAAuB,EACvB,qBAAqB,EACrB,IAAI,EACJ,SAAS,GACT,EAAE;IACF,uBAAuB,EAAE,aAAa,CAAC;IACvC,qBAAqB,EAAE,eAAe,CAAC;IACvC,IAAI,EAAE,OAAO,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;CACnB,GAAG,aAAa,CAiLhB;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,EAC5C,uBAAuB,EACvB,SAAS,GACT,EAAE;IACF,uBAAuB,EAAE,aAAa,CAAC;IACvC,SAAS,EAAE,OAAO,CAAC;CACnB,GAAG,aAAa,CA4EhB;AAED,wBAAgB,mBAAmB,CAClC,OAAO,EAAE,WAAW,CAAC,OAAO,EAC5B,UAAU,EAAE,yBAAyB,GACnC,MAAM,CAyCR"}
package/node/lib/ortc.js CHANGED
@@ -386,6 +386,16 @@ function getConsumableRtpParameters(kind, params, caps, rtpMapping) {
386
386
  (capExt.direction !== 'sendrecv' && capExt.direction !== 'sendonly')) {
387
387
  continue;
388
388
  }
389
+ // 'abs-capture-time' RTP extension is just proxied from the packets of this
390
+ // Producer, so don't announce it to Consumers unless this Producer negotiated
391
+ // it. Otherwise a Producer created out of a pipe Consumer would announce it
392
+ // and the worker would wait forever for an extension that is never going to
393
+ // arrive.
394
+ if (capExt.uri ===
395
+ 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time' &&
396
+ !params.headerExtensions.some(ext => ext.uri === capExt.uri)) {
397
+ continue;
398
+ }
389
399
  const consumableExt = {
390
400
  uri: capExt.uri,
391
401
  id: capExt.preferredId,
@@ -260,12 +260,6 @@ test('router.pipeToRouter() succeeds with audio', async () => {
260
260
  parameters: {},
261
261
  uri: 'https://aomediacodec.github.io/av1-rtp-spec/#dependency-descriptor-rtp-header-extension',
262
262
  },
263
- {
264
- uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time',
265
- id: 10,
266
- encrypt: false,
267
- parameters: {},
268
- },
269
263
  {
270
264
  uri: 'http://www.webrtc.org/experiments/rtp-hdrext/playout-delay',
271
265
  id: 11,
@@ -319,12 +313,6 @@ test('router.pipeToRouter() succeeds with audio', async () => {
319
313
  parameters: {},
320
314
  uri: 'https://aomediacodec.github.io/av1-rtp-spec/#dependency-descriptor-rtp-header-extension',
321
315
  },
322
- {
323
- uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time',
324
- id: 10,
325
- encrypt: false,
326
- parameters: {},
327
- },
328
316
  {
329
317
  uri: 'http://www.webrtc.org/experiments/rtp-hdrext/playout-delay',
330
318
  id: 11,
@@ -388,12 +376,6 @@ test('router.pipeToRouter() succeeds with video', async () => {
388
376
  encrypt: false,
389
377
  parameters: {},
390
378
  },
391
- {
392
- uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time',
393
- id: 10,
394
- encrypt: false,
395
- parameters: {},
396
- },
397
379
  {
398
380
  uri: 'http://www.webrtc.org/experiments/rtp-hdrext/playout-delay',
399
381
  id: 11,
@@ -452,12 +434,6 @@ test('router.pipeToRouter() succeeds with video', async () => {
452
434
  encrypt: false,
453
435
  parameters: {},
454
436
  },
455
- {
456
- uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time',
457
- id: 10,
458
- encrypt: false,
459
- parameters: {},
460
- },
461
437
  {
462
438
  uri: 'http://www.webrtc.org/experiments/rtp-hdrext/playout-delay',
463
439
  id: 11,
@@ -473,6 +449,41 @@ test('router.pipeToRouter() succeeds with video', async () => {
473
449
  ]);
474
450
  expect(pipeProducer.paused).toBe(true);
475
451
  }, 2000);
452
+ test('router.pipeToRouter() gives abs-capture-time to the pipe Consumer if the Producer has it', async () => {
453
+ const videoProducer2 = await ctx.webRtcTransport1.produce({
454
+ kind: 'video',
455
+ rtpParameters: {
456
+ mid: 'VIDEO2',
457
+ codecs: [
458
+ {
459
+ mimeType: 'video/VP8',
460
+ payloadType: 112,
461
+ clockRate: 90000,
462
+ },
463
+ ],
464
+ headerExtensions: [
465
+ {
466
+ uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time',
467
+ id: 12,
468
+ },
469
+ ],
470
+ encodings: [{ ssrc: 44444444 }],
471
+ rtcp: {
472
+ cname: 'FOOBAR',
473
+ },
474
+ },
475
+ });
476
+ const { pipeConsumer } = (await ctx.router1.pipeToRouter({
477
+ producerId: videoProducer2.id,
478
+ router: ctx.router2,
479
+ }));
480
+ expect(pipeConsumer.rtpParameters.headerExtensions).toContainEqual({
481
+ uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time',
482
+ id: 10,
483
+ encrypt: false,
484
+ parameters: {},
485
+ });
486
+ }, 2000);
476
487
  test('router.pipeToRouter() with unknown router, producerId or dataProducerId fails', async () => {
477
488
  const router3 = await ctx.worker1.createRouter({
478
489
  mediaCodecs: ctx.mediaCodecs,
@@ -571,12 +582,6 @@ test('router.createPipeTransport() with enableRtx succeeds', async () => {
571
582
  encrypt: false,
572
583
  parameters: {},
573
584
  },
574
- {
575
- uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time',
576
- id: 10,
577
- encrypt: false,
578
- parameters: {},
579
- },
580
585
  {
581
586
  uri: 'http://www.webrtc.org/experiments/rtp-hdrext/playout-delay',
582
587
  id: 11,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mediasoup",
3
- "version": "3.24.2",
3
+ "version": "3.26.0",
4
4
  "description": "Cutting Edge WebRTC Video Conferencing",
5
5
  "contributors": [
6
6
  "Iñaki Baz Castillo <ibc@aliax.net> (https://inakibaz.me)",
@@ -124,19 +124,19 @@
124
124
  "@types/node": "^26.2.0",
125
125
  "eslint": "^10.8.1",
126
126
  "eslint-config-prettier": "^10.1.8",
127
- "eslint-plugin-jest": "^29.16.0",
127
+ "eslint-plugin-jest": "^29.16.1",
128
128
  "eslint-plugin-prettier": "^5.5.6",
129
- "globals": "^17.9.0",
129
+ "globals": "^17.11.0",
130
130
  "ini": "^7.0.0",
131
131
  "jest": "^30.4.2",
132
- "knip": "^6.32.0",
133
- "marked": "^18.0.9",
132
+ "knip": "^6.32.2",
133
+ "marked": "^18.0.10",
134
134
  "open-cli": "^9.0.0",
135
135
  "pick-port": "^2.2.1",
136
136
  "prettier": "^3.9.6",
137
137
  "ts-jest": "^29.4.12",
138
138
  "typescript": "^6.0.3",
139
- "typescript-eslint": "^8.66.0",
139
+ "typescript-eslint": "^8.67.0",
140
140
  "werift-sctp": "^0.0.11"
141
141
  }
142
142
  }
@@ -8,33 +8,59 @@ class DepLibUV
8
8
  {
9
9
  public:
10
10
  static void ClassInit();
11
+
11
12
  static void ClassDestroy();
13
+
12
14
  static void PrintVersion();
15
+
13
16
  static void RunLoop();
17
+
14
18
  static uv_loop_t* GetLoop()
15
19
  {
16
20
  return DepLibUV::loop;
17
21
  }
22
+
18
23
  static uint64_t GetTimeMs()
19
24
  {
20
25
  return static_cast<uint64_t>(uv_hrtime() / 1000000u);
21
26
  }
27
+
28
+ /**
29
+ * Offset between our own monotonic clock and the NTP epoch (ms).
30
+ *
31
+ * @remarks
32
+ * - It is taken just once, in ClassInit(), so that the NTP timestamps we generate
33
+ * never step when the system clock is adjusted. They just drift away from the real
34
+ * wall clock as much as our monotonic clock does.
35
+ */
36
+ static uint64_t GetNtpOffsetMs()
37
+ {
38
+ return DepLibUV::ntpOffsetMs;
39
+ }
40
+
22
41
  static uint64_t GetTimeUs()
23
42
  {
24
43
  return static_cast<uint64_t>(uv_hrtime() / 1000u);
25
44
  }
45
+
26
46
  static uint64_t GetTimeNs()
27
47
  {
28
48
  return uv_hrtime();
29
49
  }
30
- // Used within libwebrtc dependency which uses int64_t values for time
31
- // representation.
50
+
51
+ /**
52
+ * Used within libwebrtc dependency which uses int64_t values for time
53
+ * representation.
54
+ */
32
55
  static int64_t GetTimeMsInt64()
33
56
  {
34
57
  return static_cast<int64_t>(DepLibUV::GetTimeMs());
35
58
  }
36
- // Used within libwebrtc dependency which uses int64_t values for time
37
- // representation.
59
+
60
+ /**
61
+ * Used within libwebrtc dependency which uses int64_t values for time
62
+ * representation.
63
+ */
38
64
  static int64_t GetTimeUsInt64()
39
65
  {
40
66
  return static_cast<int64_t>(DepLibUV::GetTimeUs());
@@ -42,6 +68,9 @@ public:
42
68
 
43
69
  private:
44
70
  static thread_local uv_loop_t* loop;
71
+ // Distance from our own monotonic clock to the NTP epoch (ms), taken at
72
+ // ClassInit().
73
+ static thread_local uint64_t ntpOffsetMs;
45
74
  };
46
75
 
47
76
  #endif
@@ -146,7 +146,10 @@ namespace RTC
146
146
  uint32_t GetDesiredBitrate() const;
147
147
  void SendRtpPacket(RTC::RTP::Packet* packet, RTC::RTP::SharedPacket& sharedPacket);
148
148
  bool GetRtcp(RTC::RTCP::CompoundPacket* packet, uint64_t nowMs);
149
- void NeedWorstRemoteFractionLost(uint32_t mappedSsrc, uint8_t& worstRemoteFractionLost);
149
+ /**
150
+ * Worst remote fraction lost among the RTP streams of this Consumer.
151
+ */
152
+ uint8_t GetWorstRemoteFractionLost(uint32_t mappedSsrc) const;
150
153
  void ReceiveNack(RTC::RTCP::FeedbackRtpNackPacket* nackPacket);
151
154
  void ReceiveKeyFrameRequest(RTC::RTCP::FeedbackPs::MessageType messageType, uint32_t ssrc);
152
155
  void ReceiveRtcpReceiverReport(RTC::RTCP::ReceiverReport* report);
@@ -47,8 +47,27 @@ namespace RTC
47
47
  RTC::Producer* producer, RTC::RTP::RtpStreamRecv* rtpStream, bool first) = 0;
48
48
  virtual void OnProducerRtpPacketReceived(RTC::Producer* producer, RTC::RTP::Packet* packet) = 0;
49
49
  virtual void OnProducerSendRtcpPacket(RTC::Producer* producer, RTC::RTCP::Packet* packet) = 0;
50
- virtual void OnProducerNeedWorstRemoteFractionLost(
51
- RTC::Producer* producer, uint32_t mappedSsrc, uint8_t& worstRemoteFractionLost) = 0;
50
+ /**
51
+ * Obtains the worst remote fraction lost of all the Consumers consuming the
52
+ * given mapped SSRC of this Producer.
53
+ */
54
+ virtual uint8_t OnProducerNeedWorstRemoteFractionLost(
55
+ RTC::Producer* producer, uint32_t mappedSsrc) = 0;
56
+ /**
57
+ * Capture instant of the given RTP timestamp of the given RTP stream, expressed
58
+ * in our own monotonic clock.
59
+ *
60
+ * @returns No value while the capture instant cannot be told yet.
61
+ */
62
+ virtual std::optional<uint64_t> OnProducerNeedLocalCaptureMs(
63
+ RTC::Producer* producer, const RTC::RTP::RtpStreamRecv* rtpStream, uint32_t ts) = 0;
64
+ /**
65
+ * Offset between the wall clock of the sender of this Producer and our own
66
+ * monotonic one (ms).
67
+ *
68
+ * @returns No value while the offset cannot be told yet.
69
+ */
70
+ virtual std::optional<int64_t> OnProducerNeedRemoteClockOffsetMs(const RTC::Producer* producer) = 0;
52
71
  };
53
72
 
54
73
  private:
@@ -154,7 +173,18 @@ namespace RTC
154
173
  const RTC::RTP::Packet* packet, const RTC::RtpCodecParameters& mediaCodec, size_t encodingIdx);
155
174
  void NotifyNewRtpStream(RTC::RTP::RtpStreamRecv* rtpStream);
156
175
  bool MangleRtpPacket(RTC::RTP::Packet* packet, RTC::RTP::RtpStreamRecv* rtpStream) const;
157
- void PostProcessRtpPacket(RTC::RTP::Packet* packet);
176
+ /**
177
+ * @param maxPacketTsChanged - Whether this packet became the one holding the
178
+ * highest RTP timestamp of its RTP stream, which happens just for the first
179
+ * arriving packet of each frame.
180
+ *
181
+ * @remarks
182
+ * - Not "advanced": the stream also takes a packet as its new reference when its
183
+ * RTP timestamp is lower, be it the very first packet, a timestamp moving
184
+ * backwards after prolonged sender inactivity or a sequence number resync.
185
+ */
186
+ void PostProcessRtpPacket(
187
+ RTC::RTP::Packet* packet, RTC::RTP::RtpStreamRecv* rtpStream, bool maxPacketTsChanged);
158
188
  void EmitScore() const;
159
189
  void EmitTraceEventRtpAndKeyFrameTypes(const RTC::RTP::Packet* packet, bool isRtx = false) const;
160
190
  void EmitTraceEventPliType(uint32_t ssrc) const;
@@ -167,8 +197,7 @@ namespace RTC
167
197
  public:
168
198
  void OnRtpStreamScore(RTC::RTP::RtpStream* rtpStream, uint8_t score, uint8_t previousScore) override;
169
199
  void OnRtpStreamSendRtcpPacket(RTC::RTP::RtpStreamRecv* rtpStream, RTC::RTCP::Packet* packet) override;
170
- void OnRtpStreamNeedWorstRemoteFractionLost(
171
- RTC::RTP::RtpStreamRecv* rtpStream, uint8_t& worstRemoteFractionLost) override;
200
+ uint8_t OnRtpStreamNeedWorstRemoteFractionLost(RTC::RTP::RtpStreamRecv* rtpStream) override;
172
201
 
173
202
  /* Pure virtual methods inherited from RTC::KeyFrameRequestManager::Listener. */
174
203
  public:
@@ -14,7 +14,13 @@ namespace RTC
14
14
  extern uint8_t SerializationBuffer[SerializationBufferSize];
15
15
 
16
16
  // Maximum interval for regular RTCP mode.
17
- constexpr uint16_t MaxAudioIntervalMs{ 5000 };
17
+ //
18
+ // NOTE: Audio does not take the 5000 ms that other implementations take, because our
19
+ // correspondence between NTP and RTP timestamps is not the fixed line of a real
20
+ // capture system but an estimation that moves. Refreshing it for audio less often
21
+ // than for video would make receivers combine measurements taken at different
22
+ // instants, and that difference is lip sync error.
23
+ constexpr uint16_t MaxAudioIntervalMs{ 1000 };
18
24
  constexpr uint16_t MaxVideoIntervalMs{ 1000 };
19
25
 
20
26
  enum class Type : uint8_t
@@ -838,6 +838,22 @@ namespace RTC
838
838
  return this->payloadDescriptorHandler->GetTemporalLayer();
839
839
  }
840
840
 
841
+ /**
842
+ * Capture time (in ms) of the packet.
843
+ */
844
+ std::optional<uint64_t> GetCaptureMs() const
845
+ {
846
+ return this->captureMs;
847
+ }
848
+
849
+ /**
850
+ * Set the capture time (in ms) of the packet.
851
+ */
852
+ void SetCaptureMs(uint64_t captureMs)
853
+ {
854
+ this->captureMs = captureMs;
855
+ }
856
+
841
857
  private:
842
858
  /**
843
859
  * @remarks
@@ -960,6 +976,8 @@ namespace RTC
960
976
  RTP::HeaderExtensionIds headerExtensionIds{};
961
977
  // Codec related.
962
978
  std::shared_ptr<Codecs::PayloadDescriptorHandler> payloadDescriptorHandler;
979
+ // Capture time of the packet.
980
+ std::optional<uint64_t> captureMs;
963
981
  };
964
982
  } // namespace RTP
965
983
  } // namespace RTC
@@ -60,110 +60,162 @@ namespace RTC
60
60
  uint8_t temporalLayers{ 1u };
61
61
  };
62
62
 
63
+ public:
64
+ /**
65
+ * Correspondence between wall clock and RTP timeline carried by an RTCP Sender
66
+ * Report.
67
+ */
68
+ struct SenderReportMapping
69
+ {
70
+ /**
71
+ * NTP timestamp of the Sender Report (ms).
72
+ */
73
+ uint64_t ntpMs;
74
+ /**
75
+ * RTP timestamp the NTP timestamp above corresponds to.
76
+ */
77
+ uint32_t ts;
78
+ };
79
+
63
80
  public:
64
81
  RtpStream(
65
82
  RTP::RtpStream::Listener* listener,
66
83
  SharedInterface* shared,
67
84
  RTP::RtpStream::Params& params,
68
85
  uint8_t initialScore);
86
+
69
87
  virtual ~RtpStream();
70
88
 
89
+ public:
71
90
  flatbuffers::Offset<FBS::RtpStream::Dump> FillBuffer(flatbuffers::FlatBufferBuilder& builder) const;
91
+
72
92
  virtual flatbuffers::Offset<FBS::RtpStream::Stats> FillBufferStats(
73
93
  flatbuffers::FlatBufferBuilder& builder);
94
+
74
95
  uint32_t GetEncodingIdx() const
75
96
  {
76
97
  return this->params.encodingIdx;
77
98
  }
99
+
78
100
  uint32_t GetSsrc() const
79
101
  {
80
102
  return this->params.ssrc;
81
103
  }
104
+
82
105
  uint8_t GetPayloadType() const
83
106
  {
84
107
  return this->params.payloadType;
85
108
  }
109
+
86
110
  const RTC::RtpCodecMimeType& GetMimeType() const
87
111
  {
88
112
  return this->params.mimeType;
89
113
  }
114
+
90
115
  uint32_t GetClockRate() const
91
116
  {
92
117
  return this->params.clockRate;
93
118
  }
119
+
94
120
  const std::string& GetRid() const
95
121
  {
96
122
  return this->params.rid;
97
123
  }
124
+
98
125
  const std::string& GetCname() const
99
126
  {
100
127
  return this->params.cname;
101
128
  }
129
+
102
130
  bool HasRtx() const
103
131
  {
104
132
  return this->rtxStream != nullptr;
105
133
  }
134
+
106
135
  virtual void SetRtx(uint8_t payloadType, uint32_t ssrc);
136
+
107
137
  uint32_t GetRtxSsrc() const
108
138
  {
109
139
  return this->params.rtxSsrc;
110
140
  }
141
+
111
142
  uint8_t GetRtxPayloadType() const
112
143
  {
113
144
  return this->params.rtxPayloadType;
114
145
  }
146
+
115
147
  uint8_t GetSpatialLayers() const
116
148
  {
117
149
  return this->params.spatialLayers;
118
150
  }
151
+
119
152
  bool HasDtx() const
120
153
  {
121
154
  return this->params.useDtx;
122
155
  }
156
+
123
157
  uint8_t GetTemporalLayers() const
124
158
  {
125
159
  return this->params.temporalLayers;
126
160
  }
161
+
127
162
  virtual bool ReceiveStreamPacket(const RTP::Packet* packet);
128
- virtual void Pause() = 0;
129
- virtual void Resume() = 0;
130
- virtual uint32_t GetBitrate(uint64_t nowMs) = 0;
163
+
164
+ virtual void Pause() = 0;
165
+
166
+ virtual void Resume() = 0;
167
+
168
+ virtual uint32_t GetBitrate(uint64_t nowMs) = 0;
169
+
131
170
  virtual uint32_t GetBitrate(uint64_t nowMs, uint8_t spatialLayer, uint8_t temporalLayer) = 0;
132
- virtual uint32_t GetSpatialLayerBitrate(uint64_t nowMs, uint8_t spatialLayer) = 0;
171
+
172
+ virtual uint32_t GetSpatialLayerBitrate(uint64_t nowMs, uint8_t spatialLayer) = 0;
173
+
133
174
  virtual uint32_t GetLayerBitrate(uint64_t nowMs, uint8_t spatialLayer, uint8_t temporalLayer) = 0;
175
+
134
176
  void ResetScore(uint8_t score, bool notify);
177
+
135
178
  uint8_t GetFractionLost() const
136
179
  {
137
180
  return this->fractionLost;
138
181
  }
182
+
139
183
  float GetLossPercentage() const
140
184
  {
141
185
  return static_cast<float>(this->fractionLost) * 100 / 256;
142
186
  }
187
+
143
188
  float GetRtt() const
144
189
  {
145
190
  return this->rtt;
146
191
  }
192
+
147
193
  uint64_t GetMaxPacketMs() const
148
194
  {
149
195
  return this->maxPacketMs;
150
196
  }
197
+
151
198
  uint32_t GetMaxPacketTs() const
152
199
  {
153
200
  return this->maxPacketTs;
154
201
  }
155
- uint64_t GetSenderReportNtpMs() const
156
- {
157
- return this->lastSenderReportNtpMs;
158
- }
159
- uint32_t GetSenderReportTs() const
202
+
203
+ /**
204
+ * Correspondence between wall clock and RTP timeline given by the last Sender
205
+ * Report.
206
+ *
207
+ * @returns No value if there has been no Sender Report yet.
208
+ */
209
+ std::optional<RTP::RtpStream::SenderReportMapping> GetSenderReportMapping() const
160
210
  {
161
- return this->lastSenderReportTs;
211
+ return this->lastSenderReportMapping;
162
212
  }
213
+
163
214
  uint8_t GetScore() const
164
215
  {
165
216
  return this->score;
166
217
  }
218
+
167
219
  uint64_t GetActiveMs() const
168
220
  {
169
221
  return this->shared->GetTimeMs() - this->activeSinceMs;
@@ -171,9 +223,13 @@ namespace RTC
171
223
 
172
224
  protected:
173
225
  bool UpdateSeq(const RTP::Packet* packet);
226
+
174
227
  void UpdateScore(uint8_t score);
228
+
175
229
  void PacketRetransmitted(const RTP::Packet* packet);
230
+
176
231
  void PacketRepaired(const RTP::Packet* packet);
232
+
177
233
  uint32_t GetExpectedPackets() const
178
234
  {
179
235
  return (this->cycles + this->maxSeq) - this->baseSeq + 1;
@@ -205,6 +261,13 @@ namespace RTC
205
261
  uint32_t maxPacketTs{ 0u };
206
262
  // When the packet with highest timestammp was seen.
207
263
  uint64_t maxPacketMs{ 0u };
264
+ // When the media in the packet with highest timestamp was captured, in our own
265
+ // monotonic clock.
266
+ // NOTE: Only meaningful in a send stream, whose packets arrive already carrying
267
+ // their capture instant. In a receive stream it is the Producer that tells it,
268
+ // once this class has already seen the packet, so
269
+ // RtpStreamRecv::GetCaptureMapping() is what must be used there.
270
+ std::optional<uint64_t> maxPacketCaptureMs;
208
271
  int32_t packetsLost{ 0 };
209
272
  uint8_t fractionLost{ 0u };
210
273
  // Jitter in RTP timestamp units. As per spec it's kept as floating value
@@ -221,10 +284,9 @@ namespace RTC
221
284
  size_t repairedPriorScore{ 0u };
222
285
  // Packets retransmitted at last interval for score calculation.
223
286
  size_t retransmittedPriorScore{ 0u };
224
- // NTP timestamp in last Sender Report (in ms).
225
- uint64_t lastSenderReportNtpMs{ 0u };
226
- // RTP timestamp in last Sender Report.
227
- uint32_t lastSenderReportTs{ 0u };
287
+ // Correspondence between wall clock and RTP timeline given by the last Sender
288
+ // Report.
289
+ std::optional<RTP::RtpStream::SenderReportMapping> lastSenderReportMapping;
228
290
  float rtt{ 0.0f };
229
291
  // Instance of RtxStream.
230
292
  RTP::RtxStream* rtxStream{ nullptr };