mediasoup 3.25.0 → 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.
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
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
|
+
|
|
5
9
|
### 3.25.0
|
|
6
10
|
|
|
7
11
|
- Worker: Fix undefined behavior in `RtpStreamRecv::UpdateScore()` when no packets were received ([PR #1886](https://github.com/versatica/mediasoup/pull/1886)).
|
package/node/lib/Consumer.js
CHANGED
|
@@ -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;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mediasoup",
|
|
3
|
-
"version": "3.
|
|
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.
|
|
127
|
+
"eslint-plugin-jest": "^29.16.1",
|
|
128
128
|
"eslint-plugin-prettier": "^5.5.6",
|
|
129
|
-
"globals": "^17.
|
|
129
|
+
"globals": "^17.11.0",
|
|
130
130
|
"ini": "^7.0.0",
|
|
131
131
|
"jest": "^30.4.2",
|
|
132
|
-
"knip": "^6.32.
|
|
133
|
-
"marked": "^18.0.
|
|
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.
|
|
139
|
+
"typescript-eslint": "^8.67.0",
|
|
140
140
|
"werift-sctp": "^0.0.11"
|
|
141
141
|
}
|
|
142
142
|
}
|
|
@@ -238,6 +238,11 @@ namespace RTC
|
|
|
238
238
|
uint32_t requiredBitrate{ 0u };
|
|
239
239
|
int16_t spatialLayer{ 0 };
|
|
240
240
|
int16_t temporalLayer{ 0 };
|
|
241
|
+
// Whether a usable spatial layer has been found, in which case we must not
|
|
242
|
+
// go above the preferred spatial layer. Same criteria as in
|
|
243
|
+
// RecalculateTargetLayers(), so both take the same decision no matter the
|
|
244
|
+
// bitrate of the layer.
|
|
245
|
+
bool usableSpatialLayerFound{ this->provisionalTargetLayers.spatial != -1 };
|
|
241
246
|
|
|
242
247
|
for (size_t sIdx{ 0u }; sIdx < this->producerRtpStreams.size(); ++sIdx)
|
|
243
248
|
{
|
|
@@ -262,8 +267,12 @@ namespace RTC
|
|
|
262
267
|
{
|
|
263
268
|
continue;
|
|
264
269
|
}
|
|
265
|
-
// If this is higher than preferred spatial layer, abort
|
|
266
|
-
|
|
270
|
+
// If this is higher than preferred spatial layer, abort unless no lower
|
|
271
|
+
// spatial layer is usable or this is the provisional one (so we may still
|
|
272
|
+
// increase its temporal layer).
|
|
273
|
+
else if (
|
|
274
|
+
spatialLayer > this->preferredLayers.spatial && usableSpatialLayerFound &&
|
|
275
|
+
spatialLayer != this->provisionalTargetLayers.spatial)
|
|
267
276
|
{
|
|
268
277
|
MS_DEBUG_DEV(
|
|
269
278
|
"avoid upgrading to spatial layer %" PRIi16
|
|
@@ -313,10 +322,19 @@ namespace RTC
|
|
|
313
322
|
continue;
|
|
314
323
|
}
|
|
315
324
|
|
|
325
|
+
// This spatial layer is usable even if it has no bitrate at all.
|
|
326
|
+
usableSpatialLayerFound = true;
|
|
327
|
+
|
|
316
328
|
temporalLayer = 0;
|
|
317
329
|
|
|
330
|
+
// Don't consider temporal layers above the preferred one, nor above the
|
|
331
|
+
// ones this stream has.
|
|
332
|
+
const auto maxTemporalLayer = std::min(
|
|
333
|
+
static_cast<int16_t>(producerRtpStream->GetTemporalLayers() - 1),
|
|
334
|
+
this->preferredLayers.temporal);
|
|
335
|
+
|
|
318
336
|
// Check bitrate of every temporal layer.
|
|
319
|
-
for (;
|
|
337
|
+
for (; temporalLayer <= maxTemporalLayer; ++temporalLayer)
|
|
320
338
|
{
|
|
321
339
|
// Ignore temporal layers lower than the one we already have (taking
|
|
322
340
|
// into account the spatial layer too).
|
|
@@ -1004,6 +1022,13 @@ namespace RTC
|
|
|
1004
1022
|
continue;
|
|
1005
1023
|
}
|
|
1006
1024
|
|
|
1025
|
+
// Don't go above the preferred spatial layer if we already found a usable
|
|
1026
|
+
// lower one.
|
|
1027
|
+
if (spatialLayer > this->preferredLayers.spatial && newTargetLayers.spatial != -1)
|
|
1028
|
+
{
|
|
1029
|
+
break;
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1007
1032
|
newTargetLayers.spatial = spatialLayer;
|
|
1008
1033
|
|
|
1009
1034
|
// If this is the preferred or higher spatial layer take it and exit.
|
|
@@ -1015,19 +1040,11 @@ namespace RTC
|
|
|
1015
1040
|
|
|
1016
1041
|
if (newTargetLayers.spatial != -1)
|
|
1017
1042
|
{
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
{
|
|
1024
|
-
newTargetLayers.temporal =
|
|
1025
|
-
static_cast<int16_t>(this->encodingContext->GetTemporalLayers() - 1);
|
|
1026
|
-
}
|
|
1027
|
-
else
|
|
1028
|
-
{
|
|
1029
|
-
newTargetLayers.temporal = 0;
|
|
1030
|
-
}
|
|
1043
|
+
// Don't consider temporal layers above the preferred one, nor above the
|
|
1044
|
+
// ones this stream has.
|
|
1045
|
+
newTargetLayers.temporal = std::min(
|
|
1046
|
+
this->preferredLayers.temporal,
|
|
1047
|
+
static_cast<int16_t>(this->encodingContext->GetTemporalLayers() - 1));
|
|
1031
1048
|
}
|
|
1032
1049
|
|
|
1033
1050
|
// Return true if any target layer changed.
|
|
@@ -190,9 +190,14 @@ namespace RTC
|
|
|
190
190
|
|
|
191
191
|
temporalLayer = 0;
|
|
192
192
|
|
|
193
|
+
// Don't consider temporal layers above the preferred one, nor above the
|
|
194
|
+
// ones this stream has.
|
|
195
|
+
const auto maxTemporalLayer = std::min(
|
|
196
|
+
static_cast<int16_t>(this->producerRtpStream->GetTemporalLayers() - 1),
|
|
197
|
+
this->preferredLayers.temporal);
|
|
198
|
+
|
|
193
199
|
// Check bitrate of every temporal layer.
|
|
194
|
-
for (;
|
|
195
|
-
++temporalLayer)
|
|
200
|
+
for (; temporalLayer <= maxTemporalLayer; ++temporalLayer)
|
|
196
201
|
{
|
|
197
202
|
// Ignore temporal layers lower than the one we already have (taking
|
|
198
203
|
// into account the spatial layer too).
|
|
@@ -247,8 +252,9 @@ namespace RTC
|
|
|
247
252
|
}
|
|
248
253
|
}
|
|
249
254
|
|
|
250
|
-
// If this is the preferred or higher spatial layer, take it and exit
|
|
251
|
-
|
|
255
|
+
// If this is the preferred or higher spatial layer, take it and exit,
|
|
256
|
+
// unless we have not found any usable spatial layer yet.
|
|
257
|
+
if (spatialLayer >= this->preferredLayers.spatial && this->provisionalTargetLayers.spatial != -1)
|
|
252
258
|
{
|
|
253
259
|
break;
|
|
254
260
|
}
|
|
@@ -589,6 +595,13 @@ namespace RTC
|
|
|
589
595
|
continue;
|
|
590
596
|
}
|
|
591
597
|
|
|
598
|
+
// Don't go above the preferred spatial layer if we already found a usable
|
|
599
|
+
// lower one.
|
|
600
|
+
if (spatialLayer > this->preferredLayers.spatial && newTargetLayers.spatial != -1)
|
|
601
|
+
{
|
|
602
|
+
break;
|
|
603
|
+
}
|
|
604
|
+
|
|
592
605
|
newTargetLayers.spatial = spatialLayer;
|
|
593
606
|
|
|
594
607
|
// If this is the preferred or higher spatial layer and has bitrate,
|
|
@@ -601,19 +614,11 @@ namespace RTC
|
|
|
601
614
|
|
|
602
615
|
if (newTargetLayers.spatial != -1)
|
|
603
616
|
{
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
{
|
|
610
|
-
newTargetLayers.temporal =
|
|
611
|
-
static_cast<int16_t>(this->encodingContext->GetTemporalLayers() - 1);
|
|
612
|
-
}
|
|
613
|
-
else
|
|
614
|
-
{
|
|
615
|
-
newTargetLayers.temporal = 0;
|
|
616
|
-
}
|
|
617
|
+
// Don't consider temporal layers above the preferred one, nor above the
|
|
618
|
+
// ones this stream has.
|
|
619
|
+
newTargetLayers.temporal = std::min(
|
|
620
|
+
this->preferredLayers.temporal,
|
|
621
|
+
static_cast<int16_t>(this->encodingContext->GetTemporalLayers() - 1));
|
|
617
622
|
}
|
|
618
623
|
|
|
619
624
|
done:
|