mediasoup 3.13.3 → 3.13.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.
- package/node/lib/ortc.js +1 -1
- package/node/lib/tests/test-Consumer.js +2 -2
- package/node/lib/tests/test-multiopus.js +1 -1
- package/node/lib/tests/test-node-sctp.js +6 -6
- package/node/lib/tests/test-ortc.js +4 -4
- package/package.json +7 -7
- package/worker/Makefile +3 -3
- package/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.cc +4 -0
- package/worker/scripts/clang-format.mjs +89 -0
- package/worker/src/RTC/RTCP/XrDelaySinceLastRr.cpp +1 -3
- package/worker/test/src/RTC/RTCP/TestXr.cpp +87 -0
package/node/lib/ortc.js
CHANGED
|
@@ -656,7 +656,7 @@ function getConsumableRtpParameters(kind, params, caps, rtpMapping) {
|
|
|
656
656
|
payloadType: matchedCapCodec.preferredPayloadType,
|
|
657
657
|
clockRate: matchedCapCodec.clockRate,
|
|
658
658
|
channels: matchedCapCodec.channels,
|
|
659
|
-
parameters: codec.parameters,
|
|
659
|
+
parameters: codec.parameters, // Keep the Producer codec parameters.
|
|
660
660
|
rtcpFeedback: matchedCapCodec.rtcpFeedback
|
|
661
661
|
};
|
|
662
662
|
consumableParams.codecs.push(consumableCodec);
|
|
@@ -185,13 +185,13 @@ const consumerDeviceCapabilities = {
|
|
|
185
185
|
},
|
|
186
186
|
{
|
|
187
187
|
kind: 'audio',
|
|
188
|
-
uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time',
|
|
188
|
+
uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len
|
|
189
189
|
preferredId: 4,
|
|
190
190
|
preferredEncrypt: false
|
|
191
191
|
},
|
|
192
192
|
{
|
|
193
193
|
kind: 'video',
|
|
194
|
-
uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time',
|
|
194
|
+
uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len
|
|
195
195
|
preferredId: 4,
|
|
196
196
|
preferredEncrypt: false
|
|
197
197
|
},
|
|
@@ -73,7 +73,7 @@ const consumerDeviceCapabilities = {
|
|
|
73
73
|
},
|
|
74
74
|
{
|
|
75
75
|
kind: 'audio',
|
|
76
|
-
uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time',
|
|
76
|
+
uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len
|
|
77
77
|
preferredId: 4,
|
|
78
78
|
preferredEncrypt: false
|
|
79
79
|
},
|
|
@@ -19,8 +19,8 @@ beforeAll(async () => {
|
|
|
19
19
|
worker = await mediasoup.createWorker();
|
|
20
20
|
router = await worker.createRouter();
|
|
21
21
|
transport = await router.createPlainTransport({
|
|
22
|
-
listenIp: '127.0.0.1',
|
|
23
|
-
comedia: true,
|
|
22
|
+
listenIp: '127.0.0.1', // https://github.com/nodejs/node/issues/14900
|
|
23
|
+
comedia: true, // So we don't need to call transport.connect().
|
|
24
24
|
enableSctp: true,
|
|
25
25
|
numSctpStreams: { OS: 256, MIS: 256 }
|
|
26
26
|
});
|
|
@@ -40,8 +40,8 @@ beforeAll(async () => {
|
|
|
40
40
|
return;
|
|
41
41
|
}
|
|
42
42
|
sctpSocket = sctp.connect({
|
|
43
|
-
localPort: 5000,
|
|
44
|
-
port: 5000,
|
|
43
|
+
localPort: 5000, // Required for SCTP over UDP in mediasoup.
|
|
44
|
+
port: 5000, // Required for SCTP over UDP in mediasoup.
|
|
45
45
|
OS: OS,
|
|
46
46
|
MIS: MIS,
|
|
47
47
|
udpTransport: udpSocket
|
|
@@ -53,8 +53,8 @@ beforeAll(async () => {
|
|
|
53
53
|
// Use UDP disconnected socket if Node < 12.
|
|
54
54
|
else {
|
|
55
55
|
sctpSocket = sctp.connect({
|
|
56
|
-
localPort: 5000,
|
|
57
|
-
port: 5000,
|
|
56
|
+
localPort: 5000, // Required for SCTP over UDP in mediasoup.
|
|
57
|
+
port: 5000, // Required for SCTP over UDP in mediasoup.
|
|
58
58
|
OS: OS,
|
|
59
59
|
MIS: MIS,
|
|
60
60
|
udpTransport: udpSocket,
|
|
@@ -17,7 +17,7 @@ test('generateRouterRtpCapabilities() succeeds', () => {
|
|
|
17
17
|
{
|
|
18
18
|
kind: 'video',
|
|
19
19
|
mimeType: 'video/VP8',
|
|
20
|
-
preferredPayloadType: 125,
|
|
20
|
+
preferredPayloadType: 125, // Let's force it.
|
|
21
21
|
clockRate: 90000
|
|
22
22
|
},
|
|
23
23
|
{
|
|
@@ -38,7 +38,7 @@ test('generateRouterRtpCapabilities() succeeds', () => {
|
|
|
38
38
|
expect(rtpCapabilities.codecs?.[0]).toEqual({
|
|
39
39
|
kind: 'audio',
|
|
40
40
|
mimeType: 'audio/opus',
|
|
41
|
-
preferredPayloadType: 100,
|
|
41
|
+
preferredPayloadType: 100, // 100 is the first available dynamic PT.
|
|
42
42
|
clockRate: 48000,
|
|
43
43
|
channels: 2,
|
|
44
44
|
parameters: {
|
|
@@ -69,7 +69,7 @@ test('generateRouterRtpCapabilities() succeeds', () => {
|
|
|
69
69
|
expect(rtpCapabilities.codecs?.[2]).toEqual({
|
|
70
70
|
kind: 'video',
|
|
71
71
|
mimeType: 'video/rtx',
|
|
72
|
-
preferredPayloadType: 101,
|
|
72
|
+
preferredPayloadType: 101, // 101 is the second available dynamic PT.
|
|
73
73
|
clockRate: 90000,
|
|
74
74
|
parameters: {
|
|
75
75
|
apt: 125
|
|
@@ -80,7 +80,7 @@ test('generateRouterRtpCapabilities() succeeds', () => {
|
|
|
80
80
|
expect(rtpCapabilities.codecs?.[3]).toEqual({
|
|
81
81
|
kind: 'video',
|
|
82
82
|
mimeType: 'video/H264',
|
|
83
|
-
preferredPayloadType: 102,
|
|
83
|
+
preferredPayloadType: 102, // 102 is the third available dynamic PT.
|
|
84
84
|
clockRate: 90000,
|
|
85
85
|
parameters: {
|
|
86
86
|
// Since packetization-mode param was not included in the H264 codec
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mediasoup",
|
|
3
|
-
"version": "3.13.
|
|
3
|
+
"version": "3.13.4",
|
|
4
4
|
"description": "Cutting Edge WebRTC Video Conferencing",
|
|
5
5
|
"contributors": [
|
|
6
6
|
"Iñaki Baz Castillo <ibc@aliax.net> (https://inakibaz.me)",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"worker/fuzzer/include",
|
|
27
27
|
"worker/fuzzer/src",
|
|
28
28
|
"worker/include",
|
|
29
|
-
"worker/scripts/*.
|
|
29
|
+
"worker/scripts/*.mjs",
|
|
30
30
|
"worker/scripts/*.json",
|
|
31
31
|
"worker/scripts/*.py",
|
|
32
32
|
"worker/scripts/*.sh",
|
|
@@ -105,10 +105,10 @@
|
|
|
105
105
|
"devDependencies": {
|
|
106
106
|
"@octokit/rest": "^20.0.2",
|
|
107
107
|
"@types/debug": "^4.1.12",
|
|
108
|
-
"@types/jest": "^29.5.
|
|
109
|
-
"@types/node": "^20.9.
|
|
110
|
-
"@typescript-eslint/eslint-plugin": "^6.
|
|
111
|
-
"@typescript-eslint/parser": "^6.
|
|
108
|
+
"@types/jest": "^29.5.9",
|
|
109
|
+
"@types/node": "^20.9.3",
|
|
110
|
+
"@typescript-eslint/eslint-plugin": "^6.12.0",
|
|
111
|
+
"@typescript-eslint/parser": "^6.12.0",
|
|
112
112
|
"eslint": "^8.54.0",
|
|
113
113
|
"eslint-plugin-jest": "^27.6.0",
|
|
114
114
|
"jest": "^29.7.0",
|
|
@@ -117,6 +117,6 @@
|
|
|
117
117
|
"pick-port": "^1.0.1",
|
|
118
118
|
"sctp": "^1.0.0",
|
|
119
119
|
"ts-jest": "^29.1.1",
|
|
120
|
-
"typescript": "^5.
|
|
120
|
+
"typescript": "^5.3.2"
|
|
121
121
|
}
|
|
122
122
|
}
|
package/worker/Makefile
CHANGED
|
@@ -213,7 +213,7 @@ libmediasoup-worker: setup flatc
|
|
|
213
213
|
flatc: setup
|
|
214
214
|
$(MESON) compile -C $(BUILD_DIR) flatbuffers-generator
|
|
215
215
|
|
|
216
|
-
xcode: setup
|
|
216
|
+
xcode: setup flatc
|
|
217
217
|
$(MESON) setup --buildtype debug --backend xcode $(MEDIASOUP_OUT_DIR)/xcode
|
|
218
218
|
|
|
219
219
|
lint:
|
|
@@ -234,7 +234,7 @@ else
|
|
|
234
234
|
$(BUILD_DIR)/mediasoup-worker-test --invisibles --use-colour=yes $(MEDIASOUP_TEST_TAGS)
|
|
235
235
|
endif
|
|
236
236
|
|
|
237
|
-
test-asan: setup
|
|
237
|
+
test-asan: setup flatc
|
|
238
238
|
$(MESON) compile -C $(BUILD_DIR) -j $(CORES) mediasoup-worker-test-asan
|
|
239
239
|
$(MESON) install -C $(BUILD_DIR) --no-rebuild --tags mediasoup-worker-test-asan
|
|
240
240
|
ASAN_OPTIONS=detect_leaks=1 $(BUILD_DIR)/mediasoup-worker-test-asan --invisibles --use-colour=yes $(MEDIASOUP_TEST_TAGS)
|
|
@@ -249,7 +249,7 @@ tidy:
|
|
|
249
249
|
-checks=$(MEDIASOUP_TIDY_CHECKS) \
|
|
250
250
|
-quiet
|
|
251
251
|
|
|
252
|
-
fuzzer: setup
|
|
252
|
+
fuzzer: setup flatc
|
|
253
253
|
$(MESON) compile -C $(BUILD_DIR) -j $(CORES) mediasoup-worker-fuzzer
|
|
254
254
|
$(MESON) install -C $(BUILD_DIR) --no-rebuild --tags mediasoup-worker-fuzzer
|
|
255
255
|
|
|
@@ -289,6 +289,8 @@ void RemoteBitrateEstimatorAbsSendTime::IncomingPacketInfo(
|
|
|
289
289
|
if (payload_size > kMinProbePacketSize &&
|
|
290
290
|
(!remote_rate_.ValidEstimate() ||
|
|
291
291
|
now_ms - first_packet_time_ms_ < kInitialProbingIntervalMs)) {
|
|
292
|
+
|
|
293
|
+
#if MS_LOG_DEV_LEVEL == 3
|
|
292
294
|
// TODO(holmer): Use a map instead to get correct order?
|
|
293
295
|
if (total_probes_received_ < kMaxProbePackets) {
|
|
294
296
|
int send_delta_ms = -1;
|
|
@@ -306,6 +308,8 @@ void RemoteBitrateEstimatorAbsSendTime::IncomingPacketInfo(
|
|
|
306
308
|
send_delta_ms,
|
|
307
309
|
recv_delta_ms);
|
|
308
310
|
}
|
|
311
|
+
#endif
|
|
312
|
+
|
|
309
313
|
probes_.push_back(Probe(send_time_ms, arrival_time_ms, payload_size));
|
|
310
314
|
++total_probes_received_;
|
|
311
315
|
// Make sure that a probe which updated the bitrate immediately has an
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
2
|
+
import { glob } from 'glob';
|
|
3
|
+
import clangFormat from 'clang-format';
|
|
4
|
+
|
|
5
|
+
const task = process.argv.slice(2).join(' ');
|
|
6
|
+
|
|
7
|
+
run();
|
|
8
|
+
|
|
9
|
+
async function run()
|
|
10
|
+
{
|
|
11
|
+
const clangFormatNativeBinary = clangFormat.getNativeBinary();
|
|
12
|
+
const workerFiles = await glob(
|
|
13
|
+
[
|
|
14
|
+
'../src/**/*.cpp',
|
|
15
|
+
'../include/**/*.hpp',
|
|
16
|
+
'../test/src/**/*.cpp',
|
|
17
|
+
'../test/include/helpers.hpp',
|
|
18
|
+
'../fuzzer/src/**/*.cpp',
|
|
19
|
+
'../fuzzer/include/**/*.hpp'
|
|
20
|
+
]
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
switch (task)
|
|
24
|
+
{
|
|
25
|
+
case 'lint':
|
|
26
|
+
{
|
|
27
|
+
executeCmd(
|
|
28
|
+
`${clangFormatNativeBinary} --Werror --dry-run ${workerFiles.join(' ')}`
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
case 'format':
|
|
35
|
+
{
|
|
36
|
+
executeCmd(
|
|
37
|
+
`${clangFormatNativeBinary} --Werror -i ${workerFiles.join(' ')}`
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
default:
|
|
44
|
+
{
|
|
45
|
+
logError('unknown task');
|
|
46
|
+
|
|
47
|
+
exitWithError();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function executeCmd(command)
|
|
53
|
+
{
|
|
54
|
+
try
|
|
55
|
+
{
|
|
56
|
+
execSync(command, { stdio: [ 'ignore', process.stdout, process.stderr ] });
|
|
57
|
+
}
|
|
58
|
+
catch (error)
|
|
59
|
+
{
|
|
60
|
+
logError('executeCmd() failed');
|
|
61
|
+
|
|
62
|
+
exitWithError();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// eslint-disable-next-line no-unused-vars
|
|
67
|
+
function logInfo(message)
|
|
68
|
+
{
|
|
69
|
+
// eslint-disable-next-line no-console
|
|
70
|
+
console.log(`clang-format.mjs \x1b[36m[INFO] [${task}]\x1b\[0m`, message);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// eslint-disable-next-line no-unused-vars
|
|
74
|
+
function logWarn(message)
|
|
75
|
+
{
|
|
76
|
+
// eslint-disable-next-line no-console
|
|
77
|
+
console.warn(`clang-format.mjs \x1b[33m[WARN] [${task}]\x1b\[0m`, message);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function logError(message)
|
|
81
|
+
{
|
|
82
|
+
// eslint-disable-next-line no-console
|
|
83
|
+
console.error(`clang-format.mjs \x1b[31m[ERROR] [${task}]\x1b\[0m`, message);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function exitWithError()
|
|
87
|
+
{
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
@@ -75,14 +75,12 @@ namespace RTC
|
|
|
75
75
|
{
|
|
76
76
|
report->AddSsrcInfo(ssrcInfo);
|
|
77
77
|
offset += ssrcInfo->GetSize();
|
|
78
|
+
reportLength -= ssrcInfo->GetSize();
|
|
78
79
|
}
|
|
79
80
|
else
|
|
80
81
|
{
|
|
81
82
|
return report.release();
|
|
82
83
|
}
|
|
83
|
-
|
|
84
|
-
offset += ssrcInfo->GetSize();
|
|
85
|
-
reportLength -= DelaySinceLastRr::SsrcInfo::BodySize;
|
|
86
84
|
}
|
|
87
85
|
|
|
88
86
|
return report.release();
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#include "common.hpp"
|
|
2
|
+
#include "RTC/RTCP/XR.hpp"
|
|
2
3
|
#include "RTC/RTCP/XrDelaySinceLastRr.hpp"
|
|
3
4
|
#include "RTC/RTCP/XrReceiverReferenceTime.hpp"
|
|
4
5
|
#include <catch2/catch.hpp>
|
|
@@ -6,6 +7,92 @@
|
|
|
6
7
|
|
|
7
8
|
using namespace RTC::RTCP;
|
|
8
9
|
|
|
10
|
+
SCENARIO("RTCP XR parsing", "[parser][rtcp][xr]")
|
|
11
|
+
{
|
|
12
|
+
// clang-format off
|
|
13
|
+
uint8_t buffer[] =
|
|
14
|
+
{
|
|
15
|
+
0xa0, 0xcf, 0x00, 0x08, // Padding, Type: 207 (XR), Length: 8
|
|
16
|
+
0x5d, 0x93, 0x15, 0x34, // Sender SSRC: 0x5d931534
|
|
17
|
+
// Extended Report DLRR
|
|
18
|
+
0x05, 0x00, 0x00, 0x06, // BT: 5 (DLRR), Block Length: 6
|
|
19
|
+
0x11, 0x12, 0x13, 0x14, // SSRC 1
|
|
20
|
+
0x00, 0x11, 0x00, 0x11, // LRR 1
|
|
21
|
+
0x11, 0x00, 0x11, 0x00, // DLRR 1
|
|
22
|
+
0x21, 0x22, 0x23, 0x24, // SSRC 2
|
|
23
|
+
0x00, 0x22, 0x00, 0x22, // LRR 2
|
|
24
|
+
0x22, 0x00, 0x22, 0x00, // DLRR 2
|
|
25
|
+
0x00, 0x00, 0x00, 0x04 // Padding (4 bytes)
|
|
26
|
+
};
|
|
27
|
+
// clang-format on
|
|
28
|
+
|
|
29
|
+
SECTION("parse XR packet")
|
|
30
|
+
{
|
|
31
|
+
auto* packet = ExtendedReportPacket::Parse(buffer, sizeof(buffer));
|
|
32
|
+
|
|
33
|
+
REQUIRE(packet);
|
|
34
|
+
// Despite total buffer size is 40 bytes, our GetSize() method doesn't not
|
|
35
|
+
// consider RTCP padding (4 bytes in this case).
|
|
36
|
+
REQUIRE(packet->GetSize() == 36);
|
|
37
|
+
REQUIRE(packet->GetCount() == 0);
|
|
38
|
+
REQUIRE(packet->GetSsrc() == 0x5d931534);
|
|
39
|
+
|
|
40
|
+
size_t blockIdx{ 0u };
|
|
41
|
+
|
|
42
|
+
for (auto it = packet->Begin(); it != packet->End(); ++it, ++blockIdx)
|
|
43
|
+
{
|
|
44
|
+
auto* block = *it;
|
|
45
|
+
|
|
46
|
+
switch (blockIdx)
|
|
47
|
+
{
|
|
48
|
+
case 0:
|
|
49
|
+
{
|
|
50
|
+
REQUIRE(block->GetSize() == 28);
|
|
51
|
+
|
|
52
|
+
size_t ssrcInfoIdx{ 0u };
|
|
53
|
+
auto* dlrrBlock = reinterpret_cast<DelaySinceLastRr*>(block);
|
|
54
|
+
|
|
55
|
+
for (auto it2 = dlrrBlock->Begin(); it2 != dlrrBlock->End(); ++it2, ++ssrcInfoIdx)
|
|
56
|
+
{
|
|
57
|
+
auto* ssrcInfo = *it2;
|
|
58
|
+
|
|
59
|
+
switch (ssrcInfoIdx)
|
|
60
|
+
{
|
|
61
|
+
case 0:
|
|
62
|
+
{
|
|
63
|
+
REQUIRE(ssrcInfo->GetSsrc() == 0x11121314);
|
|
64
|
+
REQUIRE(ssrcInfo->GetLastReceiverReport() == 0x00110011);
|
|
65
|
+
REQUIRE(ssrcInfo->GetDelaySinceLastReceiverReport() == 0x11001100);
|
|
66
|
+
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
case 1:
|
|
71
|
+
{
|
|
72
|
+
REQUIRE(ssrcInfo->GetSsrc() == 0x21222324);
|
|
73
|
+
REQUIRE(ssrcInfo->GetLastReceiverReport() == 0x00220022);
|
|
74
|
+
REQUIRE(ssrcInfo->GetDelaySinceLastReceiverReport() == 0x22002200);
|
|
75
|
+
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// There are 2 SSRC infos.
|
|
82
|
+
REQUIRE(ssrcInfoIdx == 2);
|
|
83
|
+
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// There are 1 block (the DLRR block).
|
|
90
|
+
REQUIRE(blockIdx == 1);
|
|
91
|
+
|
|
92
|
+
delete packet;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
9
96
|
SCENARIO("RTCP XrDelaySinceLastRt parsing", "[parser][rtcp][xr-dlrr]")
|
|
10
97
|
{
|
|
11
98
|
SECTION("create RRT")
|