mediasoup 3.20.9 → 3.20.10
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/README.md +9 -3
- package/npm-scripts.mjs +50 -10
- package/package.json +5 -5
- package/worker/include/RTC/ICE/StunPacket.hpp +21 -2
- package/worker/include/RTC/NackGenerator.hpp +2 -2
- package/worker/include/RTC/RTP/RtpStreamRecv.hpp +2 -2
- package/worker/src/RTC/ICE/IceServer.cpp +2 -1
- package/worker/src/RTC/ICE/StunPacket.cpp +8 -0
- package/worker/src/RTC/NackGenerator.cpp +1 -1
- package/worker/src/RTC/Producer.cpp +1 -1
- package/worker/src/RTC/SeqManager.cpp +1 -3
- package/worker/test/src/RTC/ICE/TestStunPacket.cpp +6 -2
- package/worker/test/src/RTC/RTP/TestRtpStreamRecv.cpp +1 -1
- package/worker/test/src/RTC/TestNackGenerator.cpp +1 -1
package/README.md
CHANGED
|
@@ -13,8 +13,10 @@
|
|
|
13
13
|
[![][github-actions-shield-mediasoup-rust]][github-actions-mediasoup-rust]
|
|
14
14
|
[![][github-actions-shield-mediasoup-worker-fuzzer]][github-actions-mediasoup-worker-fuzzer]
|
|
15
15
|
[![][github-actions-shield-mediasoup-npm-publish]][github-actions-mediasoup-npm-publish]
|
|
16
|
+
[![][github-actions-shield-mediasoup-crate-publish]][github-actions-mediasoup-crate-publish]
|
|
16
17
|
[![][github-actions-shield-mediasoup-worker-prebuild]][github-actions-mediasoup-worker-prebuild]
|
|
17
|
-
[![][github-actions-shield-mediasoup-website-
|
|
18
|
+
[![][github-actions-shield-mediasoup-website-update]][github-actions-mediasoup-website-update]
|
|
19
|
+
[![][github-actions-shield-mediasoup-demo-update]][github-actions-mediasoup-demo-update]
|
|
18
20
|
[![][github-actions-mediasoup-codeql-shield-mediasoup]][github-actions-mediasoup-codeql-mediasoup]
|
|
19
21
|
|
|
20
22
|
## Website and Documentation
|
|
@@ -108,8 +110,12 @@ You can support mediasoup by [sponsoring][sponsor] it. Thanks!
|
|
|
108
110
|
[github-actions-mediasoup-worker-prebuild]: https://github.com/versatica/mediasoup/actions/workflows/mediasoup-worker-prebuild.yaml?query=event%3Aworkflow_run
|
|
109
111
|
[github-actions-shield-mediasoup-npm-publish]: https://github.com/versatica/mediasoup/actions/workflows/mediasoup-npm-publish.yaml/badge.svg?event=push
|
|
110
112
|
[github-actions-mediasoup-npm-publish]: https://github.com/versatica/mediasoup/actions/workflows/mediasoup-npm-publish.yaml?query=event%3Apush
|
|
111
|
-
[github-actions-shield-mediasoup-
|
|
112
|
-
[github-actions-mediasoup-
|
|
113
|
+
[github-actions-shield-mediasoup-crate-publish]: https://github.com/versatica/mediasoup/actions/workflows/mediasoup-crate-publish.yaml/badge.svg?event=push
|
|
114
|
+
[github-actions-mediasoup-crate-publish]: https://github.com/versatica/mediasoup/actions/workflows/mediasoup-crate-publish.yaml?query=event%3Apush
|
|
115
|
+
[github-actions-shield-mediasoup-website-update]: https://github.com/versatica/mediasoup/actions/workflows/mediasoup-website-update.yaml/badge.svg?event=workflow_run
|
|
116
|
+
[github-actions-mediasoup-website-update]: https://github.com/versatica/mediasoup/actions/workflows/mediasoup-website-update.yaml?query=event%3Aworkflow_run
|
|
117
|
+
[github-actions-shield-mediasoup-demo-update]: https://github.com/versatica/mediasoup/actions/workflows/mediasoup-demo-update.yaml/badge.svg?event=workflow_run
|
|
118
|
+
[github-actions-mediasoup-demo-update]: https://github.com/versatica/mediasoup/actions/workflows/mediasoup-demo-update.yaml?query=event%3Aworkflow_run
|
|
113
119
|
[github-actions-mediasoup-codeql-shield-mediasoup]: https://github.com/versatica/mediasoup/actions/workflows/mediasoup-codeql.yaml/badge.svg?branch=v3
|
|
114
120
|
[github-actions-mediasoup-codeql-mediasoup]: https://github.com/versatica/mediasoup/actions/workflows/mediasoup-codeql.yaml?query=branch%3Av3
|
|
115
121
|
[sponsor]: https://mediasoup.org/sponsor
|
package/npm-scripts.mjs
CHANGED
|
@@ -138,6 +138,12 @@ async function run() {
|
|
|
138
138
|
break;
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
+
case 'prepublishOnly': {
|
|
142
|
+
prepublishOnly();
|
|
143
|
+
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
|
|
141
147
|
case 'typescript:build': {
|
|
142
148
|
buildTypescript({ force: true, args: taskArgs });
|
|
143
149
|
|
|
@@ -524,6 +530,26 @@ function installNodeDeps() {
|
|
|
524
530
|
executeCmd('npm audit --prefix worker/scripts');
|
|
525
531
|
}
|
|
526
532
|
|
|
533
|
+
/**
|
|
534
|
+
* `prepublishOnly` is run by NPM only on `npm publish` (not on `npm pack`,
|
|
535
|
+
* `npm install` or `npm ci`). We use it to forbid publishing mediasoup from a
|
|
536
|
+
* local machine. The package must only be published by the
|
|
537
|
+
* `mediasoup-npm-publish.yaml` workflow, which runs inside GitHub Actions (where
|
|
538
|
+
* GITHUB_ACTIONS environment variable is set to 'true') and uses OIDC trusted
|
|
539
|
+
* publishing.
|
|
540
|
+
*/
|
|
541
|
+
function prepublishOnly() {
|
|
542
|
+
logInfo('prepublishOnly()');
|
|
543
|
+
|
|
544
|
+
if (process.env.GITHUB_ACTIONS !== 'true') {
|
|
545
|
+
logError(
|
|
546
|
+
"prepublishOnly() | refusing to 'npm publish' outside of GitHub Actions: mediasoup is published only by the mediasoup-npm-publish.yaml workflow (triggered by pushing a release tag via 'npm run release')"
|
|
547
|
+
);
|
|
548
|
+
|
|
549
|
+
exitWithError();
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
|
|
527
553
|
function publishDryRun() {
|
|
528
554
|
logInfo('publishDryRun()');
|
|
529
555
|
|
|
@@ -551,7 +577,7 @@ async function checkRelease() {
|
|
|
551
577
|
try {
|
|
552
578
|
versionChanges = await getVersionChanges();
|
|
553
579
|
} catch (error) {
|
|
554
|
-
logError(error.message);
|
|
580
|
+
logError(`checkRelease() | ${error.message}`);
|
|
555
581
|
|
|
556
582
|
exitWithError();
|
|
557
583
|
}
|
|
@@ -609,10 +635,19 @@ async function release({ args = '' } = {}) {
|
|
|
609
635
|
await updateChangelog(version);
|
|
610
636
|
|
|
611
637
|
// Commit the bump, tag it, and push both. The pushed tag triggers
|
|
612
|
-
// mediasoup-npm-publish.yaml
|
|
613
|
-
// publishes to NPM; on its success mediasoup-worker-prebuild.yaml builds
|
|
614
|
-
// uploads the prebuilt binaries.
|
|
615
|
-
|
|
638
|
+
// `mediasoup-npm-publish.yaml`, which checks, creates the GitHub release and
|
|
639
|
+
// publishes to NPM; on its success `mediasoup-worker-prebuild.yaml` builds
|
|
640
|
+
// and uploads the prebuilt binaries.
|
|
641
|
+
//
|
|
642
|
+
// The commit message carries a "[no-ci]" marker so the regular branch CI
|
|
643
|
+
// workflows (node, worker, rust, fuzzer, codeql) skip this commit: it only
|
|
644
|
+
// bumps version/CHANGELOG (no code change) and its parent already passed CI,
|
|
645
|
+
// and the release is driven by the tag-triggered workflows instead.
|
|
646
|
+
//
|
|
647
|
+
// NOTE: "[no-ci]" (with a hyphen) is a custom marker, NOT GitHub's native
|
|
648
|
+
// "[skip ci]"/"[no ci]" (which would also skip mediasoup-npm-publish, since
|
|
649
|
+
// the tag push shares this same commit).
|
|
650
|
+
executeCmd(`git commit -am 'release ${version} [no-ci]'`);
|
|
616
651
|
executeCmd(`git tag -a ${version} -m '${version}'`);
|
|
617
652
|
executeCmd(`git push origin ${MAIN_BRANCH}`);
|
|
618
653
|
executeCmd(`git push origin '${version}'`);
|
|
@@ -664,8 +699,10 @@ async function prebuildWorker() {
|
|
|
664
699
|
}
|
|
665
700
|
}
|
|
666
701
|
|
|
667
|
-
|
|
668
|
-
|
|
702
|
+
/**
|
|
703
|
+
* Returns a Promise resolving to true if a mediasoup-worker prebuilt binary was
|
|
704
|
+
* downloaded and uncompressed, false otherwise.
|
|
705
|
+
*/
|
|
669
706
|
async function downloadPrebuiltWorker() {
|
|
670
707
|
const releaseBase =
|
|
671
708
|
process.env.MEDIASOUP_WORKER_PREBUILT_DOWNLOAD_BASE_URL ||
|
|
@@ -873,11 +910,14 @@ async function updateChangelog(version) {
|
|
|
873
910
|
fs.writeFileSync('./CHANGELOG.md', updatedChangelog);
|
|
874
911
|
}
|
|
875
912
|
|
|
876
|
-
function executeCmd(command) {
|
|
877
|
-
logInfo(`executeCmd(): ${command}`);
|
|
913
|
+
function executeCmd(command, { cwd } = {}) {
|
|
914
|
+
logInfo(`executeCmd(): ${command}${cwd ? ` [cwd:${cwd}]` : ''}`);
|
|
878
915
|
|
|
879
916
|
try {
|
|
880
|
-
execSync(command, {
|
|
917
|
+
execSync(command, {
|
|
918
|
+
cwd,
|
|
919
|
+
stdio: ['ignore', process.stdout, process.stderr],
|
|
920
|
+
});
|
|
881
921
|
} catch (error) {
|
|
882
922
|
logError(`executeCmd() failed, exiting: ${error}`);
|
|
883
923
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mediasoup",
|
|
3
|
-
"version": "3.20.
|
|
3
|
+
"version": "3.20.10",
|
|
4
4
|
"description": "Cutting Edge WebRTC Video Conferencing",
|
|
5
5
|
"contributors": [
|
|
6
6
|
"Iñaki Baz Castillo <ibc@aliax.net> (https://inakibaz.me)",
|
|
@@ -75,6 +75,7 @@
|
|
|
75
75
|
"scripts": {
|
|
76
76
|
"prepare": "node npm-scripts.mjs prepare",
|
|
77
77
|
"postinstall": "node npm-scripts.mjs postinstall",
|
|
78
|
+
"prepublishOnly": "node npm-scripts.mjs prepublishOnly",
|
|
78
79
|
"typescript:build": "node npm-scripts.mjs typescript:build",
|
|
79
80
|
"typescript:watch": "node npm-scripts.mjs typescript:watch",
|
|
80
81
|
"worker:build": "node npm-scripts.mjs worker:build",
|
|
@@ -112,7 +113,6 @@
|
|
|
112
113
|
},
|
|
113
114
|
"devDependencies": {
|
|
114
115
|
"@eslint/js": "^10.0.1",
|
|
115
|
-
"@octokit/rest": "^22.0.1",
|
|
116
116
|
"@types/debug": "^4.1.13",
|
|
117
117
|
"@types/ini": "^4.1.1",
|
|
118
118
|
"@types/jest": "^30.0.0",
|
|
@@ -121,17 +121,17 @@
|
|
|
121
121
|
"eslint-config-prettier": "^10.1.8",
|
|
122
122
|
"eslint-plugin-jest": "^29.15.2",
|
|
123
123
|
"eslint-plugin-prettier": "^5.5.6",
|
|
124
|
-
"globals": "^17.
|
|
124
|
+
"globals": "^17.7.0",
|
|
125
125
|
"ini": "^7.0.0",
|
|
126
126
|
"jest": "^30.4.2",
|
|
127
|
-
"knip": "^6.
|
|
127
|
+
"knip": "^6.18.0",
|
|
128
128
|
"marked": "^18.0.5",
|
|
129
129
|
"open-cli": "^9.0.0",
|
|
130
130
|
"pick-port": "^2.2.1",
|
|
131
131
|
"prettier": "^3.8.4",
|
|
132
132
|
"ts-jest": "^29.4.11",
|
|
133
133
|
"typescript": "^6.0.3",
|
|
134
|
-
"typescript-eslint": "^8.
|
|
134
|
+
"typescript-eslint": "^8.62.0",
|
|
135
135
|
"werift-sctp": "^0.0.11"
|
|
136
136
|
}
|
|
137
137
|
}
|
|
@@ -113,7 +113,21 @@ namespace RTC
|
|
|
113
113
|
FINGERPRINT = 0x8028,
|
|
114
114
|
ICE_CONTROLLED = 0x8029,
|
|
115
115
|
ICE_CONTROLLING = 0x802A,
|
|
116
|
-
|
|
116
|
+
/**
|
|
117
|
+
* In libwebrtc native code, STUN_ATTR_NOMINATION is defined as 0xC001.
|
|
118
|
+
* However that value is not defined in any RFC/draft, not even in the
|
|
119
|
+
* draft that defines the NOMINATION attribute.
|
|
120
|
+
*
|
|
121
|
+
* @see https://datatracker.ietf.org/doc/html/draft-thatcher-ice-renomination
|
|
122
|
+
* @see https://issues.webrtc.org/issues/496629058
|
|
123
|
+
*/
|
|
124
|
+
NOMINATION_OLD = 0xC001,
|
|
125
|
+
/**
|
|
126
|
+
* Value of the NOMINATION attribute in the new specification.
|
|
127
|
+
*
|
|
128
|
+
* @see https://juberti.github.io/draft-renomination/draft-thatcher-tsvwg-renomination.html
|
|
129
|
+
*/
|
|
130
|
+
NOMINATION = 0x0030
|
|
117
131
|
};
|
|
118
132
|
|
|
119
133
|
// Authentication result.
|
|
@@ -290,7 +304,12 @@ namespace RTC
|
|
|
290
304
|
|
|
291
305
|
uint32_t GetNomination() const
|
|
292
306
|
{
|
|
293
|
-
|
|
307
|
+
auto* attribute = GetAttribute(StunPacket::AttributeType::NOMINATION);
|
|
308
|
+
|
|
309
|
+
if (!attribute)
|
|
310
|
+
{
|
|
311
|
+
attribute = GetAttribute(StunPacket::AttributeType::NOMINATION_OLD);
|
|
312
|
+
}
|
|
294
313
|
|
|
295
314
|
if (!attribute)
|
|
296
315
|
{
|
|
@@ -48,7 +48,7 @@ namespace RTC
|
|
|
48
48
|
};
|
|
49
49
|
|
|
50
50
|
public:
|
|
51
|
-
explicit NackGenerator(Listener* listener, SharedInterface* shared,
|
|
51
|
+
explicit NackGenerator(Listener* listener, SharedInterface* shared, uint32_t sendNackDelayMs);
|
|
52
52
|
~NackGenerator() override;
|
|
53
53
|
|
|
54
54
|
bool ReceivePacket(const RTC::RTP::Packet* packet, bool isRecovered);
|
|
@@ -76,7 +76,7 @@ namespace RTC
|
|
|
76
76
|
// Passed by argument.
|
|
77
77
|
Listener* listener{ nullptr };
|
|
78
78
|
SharedInterface* shared{ nullptr };
|
|
79
|
-
|
|
79
|
+
uint32_t sendNackDelayMs{ 0u };
|
|
80
80
|
// Allocated by this.
|
|
81
81
|
TimerHandleInterface* timer{ nullptr };
|
|
82
82
|
// Others.
|
|
@@ -49,7 +49,7 @@ namespace RTC
|
|
|
49
49
|
RTP::RtpStreamRecv::Listener* listener,
|
|
50
50
|
SharedInterface* shared,
|
|
51
51
|
RTP::RtpStream::Params& params,
|
|
52
|
-
|
|
52
|
+
uint32_t sendNackDelayMs,
|
|
53
53
|
bool useRtpInactivityCheck);
|
|
54
54
|
~RtpStreamRecv() override;
|
|
55
55
|
|
|
@@ -105,7 +105,7 @@ namespace RTC
|
|
|
105
105
|
|
|
106
106
|
private:
|
|
107
107
|
// Passed by argument.
|
|
108
|
-
|
|
108
|
+
uint32_t sendNackDelayMs{ 0u };
|
|
109
109
|
bool useRtpInactivityCheck{ false };
|
|
110
110
|
// Others.
|
|
111
111
|
// Packets expected at last interval.
|
|
@@ -523,7 +523,8 @@ namespace RTC
|
|
|
523
523
|
HandleTuple(
|
|
524
524
|
tuple,
|
|
525
525
|
request->HasAttribute(StunPacket::AttributeType::USE_CANDIDATE),
|
|
526
|
-
request->HasAttribute(StunPacket::AttributeType::NOMINATION)
|
|
526
|
+
request->HasAttribute(StunPacket::AttributeType::NOMINATION) ||
|
|
527
|
+
request->HasAttribute(StunPacket::AttributeType::NOMINATION_OLD),
|
|
527
528
|
request->GetNomination());
|
|
528
529
|
|
|
529
530
|
// If state is 'connected' or 'completed' after handling the tuple, then
|
|
@@ -250,6 +250,11 @@ namespace RTC
|
|
|
250
250
|
MS_DUMP_CLEAN(indentation + 1, " nomination: %" PRIu32, GetNomination());
|
|
251
251
|
}
|
|
252
252
|
|
|
253
|
+
if (HasAttribute(StunPacket::AttributeType::NOMINATION_OLD))
|
|
254
|
+
{
|
|
255
|
+
MS_DUMP_CLEAN(indentation + 1, " nomination (old): %" PRIu32, GetNomination());
|
|
256
|
+
}
|
|
257
|
+
|
|
253
258
|
if (HasAttribute(StunPacket::AttributeType::SOFTWARE))
|
|
254
259
|
{
|
|
255
260
|
const auto software = GetSoftware();
|
|
@@ -404,6 +409,8 @@ namespace RTC
|
|
|
404
409
|
|
|
405
410
|
StoreNewAttribute(
|
|
406
411
|
StunPacket::AttributeType::NOMINATION, AttributeFactoryBuffer, sizeof(nomination));
|
|
412
|
+
StoreNewAttribute(
|
|
413
|
+
StunPacket::AttributeType::NOMINATION_OLD, AttributeFactoryBuffer, sizeof(nomination));
|
|
407
414
|
}
|
|
408
415
|
|
|
409
416
|
void StunPacket::AddSoftware(const std::string_view software)
|
|
@@ -1058,6 +1065,7 @@ namespace RTC
|
|
|
1058
1065
|
}
|
|
1059
1066
|
|
|
1060
1067
|
case StunPacket::AttributeType::NOMINATION:
|
|
1068
|
+
case StunPacket::AttributeType::NOMINATION_OLD:
|
|
1061
1069
|
{
|
|
1062
1070
|
if (attrLen != 4)
|
|
1063
1071
|
{
|
|
@@ -16,7 +16,7 @@ namespace RTC
|
|
|
16
16
|
|
|
17
17
|
/* Instance methods. */
|
|
18
18
|
|
|
19
|
-
NackGenerator::NackGenerator(Listener* listener, SharedInterface* shared,
|
|
19
|
+
NackGenerator::NackGenerator(Listener* listener, SharedInterface* shared, uint32_t sendNackDelayMs)
|
|
20
20
|
: listener(listener),
|
|
21
21
|
shared(shared),
|
|
22
22
|
sendNackDelayMs(sendNackDelayMs),
|
|
@@ -20,7 +20,7 @@ namespace RTC
|
|
|
20
20
|
|
|
21
21
|
static constexpr size_t ProducerSendBufferSize{ 65536 };
|
|
22
22
|
static thread_local uint8_t ProducerSendBuffer[ProducerSendBufferSize];
|
|
23
|
-
static constexpr
|
|
23
|
+
static constexpr uint32_t SendNackDelay{ 10u }; // In ms.
|
|
24
24
|
|
|
25
25
|
/* Instance methods. */
|
|
26
26
|
|
|
@@ -140,9 +140,7 @@ namespace RTC
|
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
// There are dropped inputs, calculate 'base' for this input.
|
|
143
|
-
auto droppedCount = std::distance(
|
|
144
|
-
this->dropped.begin(),
|
|
145
|
-
std::lower_bound(this->dropped.begin(), this->dropped.end(), input, SeqLowerThan()));
|
|
143
|
+
auto droppedCount = std::distance(this->dropped.begin(), it);
|
|
146
144
|
|
|
147
145
|
base = (this->base - droppedCount) & SeqManager::MaxValue;
|
|
148
146
|
}
|
|
@@ -508,7 +508,9 @@ SCENARIO("ICE StunPacket", "[serializable][ice][stunpacket]")
|
|
|
508
508
|
// Byte length: 8.
|
|
509
509
|
uint64_t iceControlling = 15697499370457501716u;
|
|
510
510
|
// Byte length of USE_CANDIDATE: 0.
|
|
511
|
-
//
|
|
511
|
+
// NOTE: `AddNomination()` adds the "NOMINATION" attribute with both the old
|
|
512
|
+
// and the new value, so it will insert 2 attributes instead of one.
|
|
513
|
+
// Byte length: 4 x 2.
|
|
512
514
|
uint32_t nomination = 12345678u;
|
|
513
515
|
// Byte length: 18 (2 byte of padding needed).
|
|
514
516
|
std::string software = "mediasoup x.y.z :)";
|
|
@@ -518,7 +520,7 @@ SCENARIO("ICE StunPacket", "[serializable][ice][stunpacket]")
|
|
|
518
520
|
|
|
519
521
|
// Total length of the attributes.
|
|
520
522
|
size_t attributesLen =
|
|
521
|
-
(4 + 27 + 1) + (4 + 4) + (4 + 8) + (4) + (4 + 4) + (4 + 18 + 2) + (4 + 4 + 23 + 1);
|
|
523
|
+
(4 + 27 + 1) + (4 + 4) + (4 + 8) + (4) + ((4 + 4) * 2) + (4 + 18 + 2) + (4 + 4 + 23 + 1);
|
|
522
524
|
|
|
523
525
|
request->AddUsername(username);
|
|
524
526
|
request->AddPriority(priority);
|
|
@@ -533,6 +535,8 @@ SCENARIO("ICE StunPacket", "[serializable][ice][stunpacket]")
|
|
|
533
535
|
REQUIRE_THROWS_AS(request->AddPriority(priority), MediaSoupError);
|
|
534
536
|
REQUIRE_THROWS_AS(request->AddIceControlling(iceControlling), MediaSoupError);
|
|
535
537
|
REQUIRE_THROWS_AS(request->AddUseCandidate(), MediaSoupError);
|
|
538
|
+
// NOTE: `AddNomination()` adds the "NOMINATION" attribute with both the old
|
|
539
|
+
// and the new value, so it will insert 2 attributes instead of one.
|
|
536
540
|
REQUIRE_THROWS_AS(request->AddNomination(nomination), MediaSoupError);
|
|
537
541
|
REQUIRE_THROWS_AS(request->AddSoftware(software), MediaSoupError);
|
|
538
542
|
REQUIRE_THROWS_AS(request->AddErrorCode(errorCode, errorReasonPhrase), MediaSoupError);
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
// 17: 16 bit mask + the initial sequence number.
|
|
10
10
|
static constexpr size_t MaxRequestedPackets{ 17 };
|
|
11
|
-
static constexpr
|
|
11
|
+
static constexpr uint32_t SendNackDelay{ 0u }; // In ms.
|
|
12
12
|
static const bool UseRtpInactivityCheck{ false };
|
|
13
13
|
|
|
14
14
|
SCENARIO("RtpStreamRecv", "[rtp][rtpstream][rtpstreamrecv]")
|