mediasoup 3.20.4 → 3.20.6
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/package.json +4 -4
- package/worker/include/RTC/Consumer.hpp +80 -45
- package/worker/include/RTC/PipeProducerStreamManager.hpp +78 -0
- package/worker/include/RTC/ProducerStreamManager.hpp +181 -0
- package/worker/include/RTC/SCTP/association/Association.hpp +24 -0
- package/worker/include/RTC/SCTP/association/StateCookie.hpp +104 -11
- package/worker/include/RTC/SCTP/packet/parameters/StateCookieParameter.hpp +4 -1
- package/worker/include/RTC/SCTP/public/SctpOptions.hpp +13 -0
- package/worker/include/RTC/SeqManager.hpp +2 -2
- package/worker/include/RTC/SimpleProducerStreamManager.hpp +72 -0
- package/worker/include/RTC/SimulcastProducerStreamManager.hpp +93 -0
- package/worker/include/RTC/SvcProducerStreamManager.hpp +72 -0
- package/worker/include/RTC/Transport.hpp +7 -1
- package/worker/meson.build +9 -5
- package/worker/src/RTC/Consumer.cpp +1404 -30
- package/worker/src/RTC/DirectTransport.cpp +4 -1
- package/worker/src/RTC/PipeProducerStreamManager.cpp +266 -0
- package/worker/src/RTC/PipeTransport.cpp +4 -1
- package/worker/src/RTC/PlainTransport.cpp +4 -1
- package/worker/src/RTC/SCTP/association/Association.cpp +142 -3
- package/worker/src/RTC/SCTP/association/StateCookie.cpp +96 -31
- package/worker/src/RTC/SCTP/association/StreamResetHandler.cpp +4 -0
- package/worker/src/RTC/SCTP/packet/Packet.cpp +1 -1
- package/worker/src/RTC/SCTP/packet/parameters/StateCookieParameter.cpp +12 -3
- package/worker/src/RTC/SCTP/public/SctpOptions.cpp +4 -0
- package/worker/src/RTC/SCTP/rx/DataTracker.cpp +4 -1
- package/worker/src/RTC/SeqManager.cpp +42 -29
- package/worker/src/RTC/SimpleProducerStreamManager.cpp +343 -0
- package/worker/src/RTC/SimulcastProducerStreamManager.cpp +1068 -0
- package/worker/src/RTC/SvcProducerStreamManager.cpp +664 -0
- package/worker/src/RTC/Transport.cpp +7 -44
- package/worker/src/RTC/WebRtcTransport.cpp +8 -2
- package/worker/test/include/RTC/SCTP/sctpCommon.hpp +1 -1
- package/worker/test/src/RTC/SCTP/association/TestAssociation.cpp +115 -0
- package/worker/test/src/RTC/SCTP/association/TestStateCookie.cpp +123 -0
- package/worker/test/src/RTC/SCTP/packet/TestPacket.cpp +4 -4
- package/worker/test/src/RTC/{TestSimpleConsumer.cpp → TestConsumer.cpp} +6 -7
- package/worker/test/src/RTC/TestPipeProducerStreamManager.cpp +471 -0
- package/worker/test/src/RTC/TestSimpleProducerStreamManager.cpp +531 -0
- package/worker/test/src/RTC/TestSimulcastProducerStreamManager.cpp +1040 -0
- package/worker/test/src/RTC/TestSvcProducerStreamManager.cpp +1278 -0
- package/worker/include/RTC/PipeConsumer.hpp +0 -95
- package/worker/include/RTC/SimpleConsumer.hpp +0 -102
- package/worker/include/RTC/SimulcastConsumer.hpp +0 -141
- package/worker/include/RTC/SvcConsumer.hpp +0 -118
- package/worker/src/RTC/PipeConsumer.cpp +0 -874
- package/worker/src/RTC/SimpleConsumer.cpp +0 -882
- package/worker/src/RTC/SimulcastConsumer.cpp +0 -1887
- package/worker/src/RTC/SvcConsumer.cpp +0 -1384
|
@@ -0,0 +1,664 @@
|
|
|
1
|
+
#define MS_CLASS "RTC::SvcProducerStreamManager"
|
|
2
|
+
// #define MS_LOG_DEV_LEVEL 3
|
|
3
|
+
|
|
4
|
+
#include "RTC/SvcProducerStreamManager.hpp"
|
|
5
|
+
#include "Logger.hpp"
|
|
6
|
+
|
|
7
|
+
namespace RTC
|
|
8
|
+
{
|
|
9
|
+
/* Static. */
|
|
10
|
+
|
|
11
|
+
static constexpr uint64_t BweDowngradeConservativeMs{ 10000u };
|
|
12
|
+
static constexpr uint64_t BweDowngradeMinActiveMs{ 8000u };
|
|
13
|
+
|
|
14
|
+
/* Instance methods. */
|
|
15
|
+
|
|
16
|
+
SvcProducerStreamManager::SvcProducerStreamManager(
|
|
17
|
+
const std::vector<RTC::RtpEncodingParameters>& consumableRtpEncodings,
|
|
18
|
+
const RTC::ConsumerTypes::VideoLayers& preferredLayers,
|
|
19
|
+
std::unique_ptr<RTC::RTP::Codecs::EncodingContext> encodingContext,
|
|
20
|
+
RTC::Media::Kind kind,
|
|
21
|
+
bool keyFrameSupported,
|
|
22
|
+
Listener* listener,
|
|
23
|
+
SharedInterface* shared)
|
|
24
|
+
: ProducerStreamManager(
|
|
25
|
+
consumableRtpEncodings,
|
|
26
|
+
preferredLayers,
|
|
27
|
+
std::move(encodingContext),
|
|
28
|
+
kind,
|
|
29
|
+
keyFrameSupported,
|
|
30
|
+
listener,
|
|
31
|
+
shared)
|
|
32
|
+
{
|
|
33
|
+
MS_TRACE();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
RTC::RTP::RtpStreamRecv* SvcProducerStreamManager::GetProducerCurrentRtpStream() const
|
|
37
|
+
{
|
|
38
|
+
MS_TRACE();
|
|
39
|
+
|
|
40
|
+
// SVC has a single producer stream. Return it if we have a current layer.
|
|
41
|
+
if (this->encodingContext->GetCurrentSpatialLayer() == -1)
|
|
42
|
+
{
|
|
43
|
+
return nullptr;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return this->producerRtpStream;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
RTC::RTP::RtpStreamRecv* SvcProducerStreamManager::GetProducerTargetRtpStream() const
|
|
50
|
+
{
|
|
51
|
+
MS_TRACE();
|
|
52
|
+
|
|
53
|
+
// SVC has a single producer stream. Return it if we have a target layer.
|
|
54
|
+
if (this->encodingContext->GetTargetSpatialLayer() == -1)
|
|
55
|
+
{
|
|
56
|
+
return nullptr;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return this->producerRtpStream;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
bool SvcProducerStreamManager::IsActive() const
|
|
63
|
+
{
|
|
64
|
+
MS_TRACE();
|
|
65
|
+
|
|
66
|
+
// clang-format off
|
|
67
|
+
return (
|
|
68
|
+
this->listener->IsActive() &&
|
|
69
|
+
this->producerRtpStream &&
|
|
70
|
+
// If there is no RTP inactivity check do not consider the stream
|
|
71
|
+
// inactive despite it has score 0.
|
|
72
|
+
(this->producerRtpStream->GetScore() > 0u || !this->producerRtpStream->HasRtpInactivityCheckEnabled())
|
|
73
|
+
);
|
|
74
|
+
// clang-format on
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
void SvcProducerStreamManager::ProducerRtpStream(
|
|
78
|
+
RTC::RTP::RtpStreamRecv* rtpStream, uint32_t /*mappedSsrc*/)
|
|
79
|
+
{
|
|
80
|
+
MS_TRACE();
|
|
81
|
+
|
|
82
|
+
this->producerRtpStream = rtpStream;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
void SvcProducerStreamManager::ProducerNewRtpStream(
|
|
86
|
+
RTC::RTP::RtpStreamRecv* rtpStream, uint32_t /*mappedSsrc*/)
|
|
87
|
+
{
|
|
88
|
+
MS_TRACE();
|
|
89
|
+
|
|
90
|
+
this->producerRtpStream = rtpStream;
|
|
91
|
+
|
|
92
|
+
// Emit the score event.
|
|
93
|
+
this->listener->OnProducerStreamManagerScore();
|
|
94
|
+
|
|
95
|
+
if (IsActive())
|
|
96
|
+
{
|
|
97
|
+
MayChangeLayers(/*force*/ false);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
void SvcProducerStreamManager::ProducerRtpStreamScore(
|
|
102
|
+
RTC::RTP::RtpStreamRecv* /*rtpStream*/, uint8_t score, uint8_t previousScore)
|
|
103
|
+
{
|
|
104
|
+
MS_TRACE();
|
|
105
|
+
|
|
106
|
+
if (this->listener->IsActive())
|
|
107
|
+
{
|
|
108
|
+
// Just check target layers if the stream has died or reborned or if
|
|
109
|
+
// bitrate is not externally managed.
|
|
110
|
+
if (!this->externallyManagedBitrate || (score == 0u || previousScore == 0u))
|
|
111
|
+
{
|
|
112
|
+
MayChangeLayers(/*force*/ false);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
void SvcProducerStreamManager::ProducerRtcpSenderReport(
|
|
118
|
+
RTC::RTP::RtpStreamRecv* /*rtpStream*/, bool /*first*/)
|
|
119
|
+
{
|
|
120
|
+
MS_TRACE();
|
|
121
|
+
|
|
122
|
+
// Do nothing.
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
uint32_t SvcProducerStreamManager::IncreaseLayer(
|
|
126
|
+
uint32_t bitrate, bool considerLoss, float lossPercentage, uint64_t nowMs)
|
|
127
|
+
{
|
|
128
|
+
MS_TRACE();
|
|
129
|
+
|
|
130
|
+
if (!this->producerRtpStream || this->producerRtpStream->GetScore() == 0u)
|
|
131
|
+
{
|
|
132
|
+
return 0u;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// If already in the preferred layers, do nothing.
|
|
136
|
+
if (this->provisionalTargetLayers == this->preferredLayers)
|
|
137
|
+
{
|
|
138
|
+
return 0u;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
uint32_t virtualBitrate;
|
|
142
|
+
|
|
143
|
+
if (considerLoss)
|
|
144
|
+
{
|
|
145
|
+
// Calculate virtual available bitrate based on given bitrate and our
|
|
146
|
+
// packet lost.
|
|
147
|
+
if (lossPercentage < 2)
|
|
148
|
+
{
|
|
149
|
+
virtualBitrate = 1.08 * bitrate;
|
|
150
|
+
}
|
|
151
|
+
else if (lossPercentage > 10)
|
|
152
|
+
{
|
|
153
|
+
virtualBitrate = (1 - 0.5 * (lossPercentage / 100)) * bitrate;
|
|
154
|
+
}
|
|
155
|
+
else
|
|
156
|
+
{
|
|
157
|
+
virtualBitrate = bitrate;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
else
|
|
161
|
+
{
|
|
162
|
+
virtualBitrate = bitrate;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
uint32_t requiredBitrate{ 0u };
|
|
166
|
+
int16_t spatialLayer{ 0 };
|
|
167
|
+
int16_t temporalLayer{ 0 };
|
|
168
|
+
|
|
169
|
+
for (; std::cmp_less(spatialLayer, this->producerRtpStream->GetSpatialLayers()); ++spatialLayer)
|
|
170
|
+
{
|
|
171
|
+
// If this is higher than current spatial layer and we moved to current
|
|
172
|
+
// spatial layer due to BWE limitations, check how much it has elapsed
|
|
173
|
+
// since then.
|
|
174
|
+
if (nowMs - this->lastBweDowngradeAtMs < BweDowngradeConservativeMs)
|
|
175
|
+
{
|
|
176
|
+
if (this->provisionalTargetLayers.spatial > -1 && spatialLayer > this->encodingContext->GetCurrentSpatialLayer())
|
|
177
|
+
{
|
|
178
|
+
MS_DEBUG_DEV(
|
|
179
|
+
"avoid upgrading to spatial layer %" PRIi16 " due to recent BWE downgrade", spatialLayer);
|
|
180
|
+
|
|
181
|
+
goto done;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Ignore spatial layers lower than the one we already have.
|
|
186
|
+
if (spatialLayer < this->provisionalTargetLayers.spatial)
|
|
187
|
+
{
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
temporalLayer = 0;
|
|
192
|
+
|
|
193
|
+
// Check bitrate of every temporal layer.
|
|
194
|
+
for (; std::cmp_less(temporalLayer, this->producerRtpStream->GetTemporalLayers());
|
|
195
|
+
++temporalLayer)
|
|
196
|
+
{
|
|
197
|
+
// Ignore temporal layers lower than the one we already have (taking
|
|
198
|
+
// into account the spatial layer too).
|
|
199
|
+
if (
|
|
200
|
+
spatialLayer == this->provisionalTargetLayers.spatial &&
|
|
201
|
+
temporalLayer <= this->provisionalTargetLayers.temporal)
|
|
202
|
+
{
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
requiredBitrate =
|
|
207
|
+
this->producerRtpStream->GetLayerBitrate(nowMs, spatialLayer, temporalLayer);
|
|
208
|
+
|
|
209
|
+
// When using K-SVC we must subtract the bitrate of the current used
|
|
210
|
+
// layer if the new layer is the temporal layer 0 of a higher spatial
|
|
211
|
+
// layer.
|
|
212
|
+
if (
|
|
213
|
+
this->encodingContext->IsKSvc() && requiredBitrate && temporalLayer == 0 &&
|
|
214
|
+
this->provisionalTargetLayers.spatial > -1 &&
|
|
215
|
+
spatialLayer > this->provisionalTargetLayers.spatial)
|
|
216
|
+
{
|
|
217
|
+
auto provisionalRequiredBitrate = this->producerRtpStream->GetSpatialLayerBitrate(
|
|
218
|
+
nowMs, this->provisionalTargetLayers.spatial);
|
|
219
|
+
|
|
220
|
+
if (requiredBitrate > provisionalRequiredBitrate)
|
|
221
|
+
{
|
|
222
|
+
requiredBitrate -= provisionalRequiredBitrate;
|
|
223
|
+
}
|
|
224
|
+
else
|
|
225
|
+
{
|
|
226
|
+
requiredBitrate = 1u; // Don't set 0 since it would be ignored.
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
MS_DEBUG_DEV(
|
|
231
|
+
"testing layers %" PRIi16 ":%" PRIi16 " [virtual bitrate:%" PRIu32
|
|
232
|
+
", required bitrate:%" PRIu32 "]",
|
|
233
|
+
spatialLayer,
|
|
234
|
+
temporalLayer,
|
|
235
|
+
virtualBitrate,
|
|
236
|
+
requiredBitrate);
|
|
237
|
+
|
|
238
|
+
// If active layer, end iterations here. Otherwise move to next spatial
|
|
239
|
+
// layer.
|
|
240
|
+
if (requiredBitrate)
|
|
241
|
+
{
|
|
242
|
+
goto done;
|
|
243
|
+
}
|
|
244
|
+
else
|
|
245
|
+
{
|
|
246
|
+
break;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// If this is the preferred or higher spatial layer, take it and exit.
|
|
251
|
+
if (spatialLayer >= this->preferredLayers.spatial)
|
|
252
|
+
{
|
|
253
|
+
break;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
done:
|
|
258
|
+
|
|
259
|
+
// No higher active layers found.
|
|
260
|
+
if (!requiredBitrate)
|
|
261
|
+
{
|
|
262
|
+
return 0u;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// No luck.
|
|
266
|
+
if (requiredBitrate > virtualBitrate)
|
|
267
|
+
{
|
|
268
|
+
return 0u;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// Set provisional layers.
|
|
272
|
+
this->provisionalTargetLayers.spatial = spatialLayer;
|
|
273
|
+
this->provisionalTargetLayers.temporal = temporalLayer;
|
|
274
|
+
|
|
275
|
+
MS_DEBUG_DEV(
|
|
276
|
+
"upgrading to layers %" PRIi16 ":%" PRIi16 " [virtual bitrate:%" PRIu32
|
|
277
|
+
", required bitrate:%" PRIu32 "]",
|
|
278
|
+
this->provisionalTargetLayers.spatial,
|
|
279
|
+
this->provisionalTargetLayers.temporal,
|
|
280
|
+
virtualBitrate,
|
|
281
|
+
requiredBitrate);
|
|
282
|
+
|
|
283
|
+
if (requiredBitrate <= bitrate)
|
|
284
|
+
{
|
|
285
|
+
return requiredBitrate;
|
|
286
|
+
}
|
|
287
|
+
else if (requiredBitrate <= virtualBitrate)
|
|
288
|
+
{
|
|
289
|
+
return bitrate;
|
|
290
|
+
}
|
|
291
|
+
else
|
|
292
|
+
{
|
|
293
|
+
return requiredBitrate; // NOTE: This cannot happen.
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
void SvcProducerStreamManager::ApplyLayers(uint64_t rtpStreamActiveMs)
|
|
298
|
+
{
|
|
299
|
+
MS_TRACE();
|
|
300
|
+
|
|
301
|
+
auto provisionalTargetLayers = this->provisionalTargetLayers;
|
|
302
|
+
|
|
303
|
+
// Reset provisional target layers.
|
|
304
|
+
this->provisionalTargetLayers.Reset();
|
|
305
|
+
|
|
306
|
+
if (provisionalTargetLayers != this->encodingContext->GetTargetLayers())
|
|
307
|
+
{
|
|
308
|
+
UpdateTargetLayers(provisionalTargetLayers.spatial, provisionalTargetLayers.temporal);
|
|
309
|
+
|
|
310
|
+
// If this looks like a spatial layer downgrade due to BWE limitations,
|
|
311
|
+
// set member.
|
|
312
|
+
if (
|
|
313
|
+
rtpStreamActiveMs > BweDowngradeMinActiveMs &&
|
|
314
|
+
this->encodingContext->GetTargetSpatialLayer() <
|
|
315
|
+
this->encodingContext->GetCurrentSpatialLayer() &&
|
|
316
|
+
this->encodingContext->GetCurrentSpatialLayer() <= this->preferredLayers.spatial)
|
|
317
|
+
{
|
|
318
|
+
MS_DEBUG_DEV(
|
|
319
|
+
"possible target spatial layer downgrade (from %" PRIi16 " to %" PRIi16
|
|
320
|
+
") due to BWE limitation",
|
|
321
|
+
this->encodingContext->GetCurrentSpatialLayer(),
|
|
322
|
+
this->encodingContext->GetTargetSpatialLayer());
|
|
323
|
+
|
|
324
|
+
this->lastBweDowngradeAtMs = this->shared->GetTimeMs();
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
uint32_t SvcProducerStreamManager::GetDesiredBitrate(uint64_t nowMs) const
|
|
330
|
+
{
|
|
331
|
+
MS_TRACE();
|
|
332
|
+
|
|
333
|
+
if (!this->producerRtpStream)
|
|
334
|
+
{
|
|
335
|
+
return 0u;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
uint32_t desiredBitrate{ 0u };
|
|
339
|
+
|
|
340
|
+
// When using K-SVC each spatial layer is independent of the others.
|
|
341
|
+
if (this->encodingContext->IsKSvc())
|
|
342
|
+
{
|
|
343
|
+
// Let's iterate all spatial layers of the Producer (from highest to lowest)
|
|
344
|
+
// and obtain their bitrate. Choose the highest one.
|
|
345
|
+
// NOTE: When the Producer enables a higher spatial layer, initially the
|
|
346
|
+
// bitrate of it could be less than the bitrate of a lower one. That's why
|
|
347
|
+
// we iterate all spatial layers here anyway.
|
|
348
|
+
for (auto spatialLayer{ this->producerRtpStream->GetSpatialLayers() - 1 }; spatialLayer >= 0;
|
|
349
|
+
--spatialLayer)
|
|
350
|
+
{
|
|
351
|
+
auto spatialLayerBitrate =
|
|
352
|
+
this->producerRtpStream->GetSpatialLayerBitrate(nowMs, spatialLayer);
|
|
353
|
+
|
|
354
|
+
desiredBitrate = std::max(spatialLayerBitrate, desiredBitrate);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
else
|
|
358
|
+
{
|
|
359
|
+
desiredBitrate = this->producerRtpStream->GetBitrate(nowMs);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
return desiredBitrate;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
ProducerStreamManager::RtpPacketProcessResult SvcProducerStreamManager::ProcessRtpPacket(
|
|
366
|
+
RTC::RTP::Packet* packet,
|
|
367
|
+
bool /*lastSentPacketHasMarker*/,
|
|
368
|
+
uint32_t /*clockRate*/,
|
|
369
|
+
uint32_t /*maxPacketTs*/)
|
|
370
|
+
{
|
|
371
|
+
MS_TRACE();
|
|
372
|
+
|
|
373
|
+
RtpPacketProcessResult result;
|
|
374
|
+
|
|
375
|
+
if (this->encodingContext->GetTargetSpatialLayer() == -1 || this->encodingContext->GetTargetTemporalLayer() == -1)
|
|
376
|
+
{
|
|
377
|
+
result.type = RtpPacketProcessResult::Type::DROP;
|
|
378
|
+
|
|
379
|
+
#ifdef MS_RTC_LOGGER_RTP
|
|
380
|
+
packet->logger.Discarded(RTC::RtcLogger::RtpPacket::DiscardReason::INVALID_TARGET_LAYER);
|
|
381
|
+
#endif
|
|
382
|
+
|
|
383
|
+
return result;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// If we need to sync and this is not a key frame, ignore the packet.
|
|
387
|
+
if (this->syncRequired && !packet->IsKeyFrame())
|
|
388
|
+
{
|
|
389
|
+
// NOTE: No need to drop the packet in the RTP sequence manager since here
|
|
390
|
+
// we are blocking all packets but the key frame that would trigger sync
|
|
391
|
+
// below.
|
|
392
|
+
|
|
393
|
+
// Store the packet for the scenario in which this packet is part of the
|
|
394
|
+
// key frame and it arrived before the first packet of the key frame.
|
|
395
|
+
result.type = RtpPacketProcessResult::Type::BUFFER;
|
|
396
|
+
|
|
397
|
+
#ifdef MS_RTC_LOGGER_RTP
|
|
398
|
+
packet->logger.Discarded(RTC::RtcLogger::RtpPacket::DiscardReason::NOT_A_KEYFRAME);
|
|
399
|
+
#endif
|
|
400
|
+
|
|
401
|
+
return result;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// Packets with only padding are not forwarded.
|
|
405
|
+
if (packet->GetPayloadLength() == 0)
|
|
406
|
+
{
|
|
407
|
+
result.type = RtpPacketProcessResult::Type::DROP;
|
|
408
|
+
|
|
409
|
+
#ifdef MS_RTC_LOGGER_RTP
|
|
410
|
+
packet->logger.Discarded(RTC::RtcLogger::RtpPacket::DiscardReason::EMPTY_PAYLOAD);
|
|
411
|
+
#endif
|
|
412
|
+
|
|
413
|
+
return result;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// Whether this is the first packet after re-sync.
|
|
417
|
+
const bool isSyncPacket = this->syncRequired;
|
|
418
|
+
|
|
419
|
+
// Whether packets stored in the target layer retransmission buffer must be
|
|
420
|
+
// sent once this packet is sent.
|
|
421
|
+
bool sendBufferedPackets{ false };
|
|
422
|
+
|
|
423
|
+
// Sync sequence number and timestamp if required.
|
|
424
|
+
if (isSyncPacket)
|
|
425
|
+
{
|
|
426
|
+
if (packet->IsKeyFrame())
|
|
427
|
+
{
|
|
428
|
+
MS_DEBUG_TAG(
|
|
429
|
+
rtp,
|
|
430
|
+
"sync key frame received [ssrc:%" PRIu32 ", seq:%" PRIu16 ", ts:%" PRIu32 "]",
|
|
431
|
+
packet->GetSsrc(),
|
|
432
|
+
packet->GetSequenceNumber(),
|
|
433
|
+
packet->GetTimestamp());
|
|
434
|
+
|
|
435
|
+
sendBufferedPackets = true;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
result.isSyncPacket = true;
|
|
439
|
+
result.syncSeqValue = packet->GetSequenceNumber() - 1;
|
|
440
|
+
result.shouldSyncEncodingContext = true;
|
|
441
|
+
|
|
442
|
+
// Sync the encoding context before ProcessPayload runs below.
|
|
443
|
+
this->encodingContext->SyncRequired();
|
|
444
|
+
|
|
445
|
+
this->syncRequired = false;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
auto previousLayers = this->encodingContext->GetCurrentLayers();
|
|
449
|
+
|
|
450
|
+
bool marker{ false };
|
|
451
|
+
|
|
452
|
+
if (!packet->ProcessPayload(this->encodingContext.get(), marker))
|
|
453
|
+
{
|
|
454
|
+
result.type = RtpPacketProcessResult::Type::DROP;
|
|
455
|
+
|
|
456
|
+
#ifdef MS_RTC_LOGGER_RTP
|
|
457
|
+
packet->logger.Discarded(RTC::RtcLogger::RtpPacket::DiscardReason::DROPPED_BY_CODEC);
|
|
458
|
+
#endif
|
|
459
|
+
|
|
460
|
+
return result;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
if (previousLayers != this->encodingContext->GetCurrentLayers())
|
|
464
|
+
{
|
|
465
|
+
result.temporalLayerChanged = true;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
// Set forward action.
|
|
469
|
+
result.type = RtpPacketProcessResult::Type::FORWARD;
|
|
470
|
+
result.tsOffset = 0u;
|
|
471
|
+
result.marker = marker;
|
|
472
|
+
result.sendBufferedPackets = sendBufferedPackets;
|
|
473
|
+
|
|
474
|
+
return result;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
void SvcProducerStreamManager::RequestKeyFrame()
|
|
478
|
+
{
|
|
479
|
+
MS_TRACE();
|
|
480
|
+
|
|
481
|
+
auto mappedSsrc = this->consumableRtpEncodings[0].ssrc;
|
|
482
|
+
|
|
483
|
+
this->listener->OnProducerStreamManagerKeyFrameRequested(mappedSsrc);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
void SvcProducerStreamManager::RequestKeyFrameForTargetSpatialLayer()
|
|
487
|
+
{
|
|
488
|
+
MS_TRACE();
|
|
489
|
+
|
|
490
|
+
RequestKeyFrame();
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
void SvcProducerStreamManager::RequestKeyFrameForCurrentSpatialLayer()
|
|
494
|
+
{
|
|
495
|
+
MS_TRACE();
|
|
496
|
+
|
|
497
|
+
RequestKeyFrame();
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
void SvcProducerStreamManager::UpdateTargetLayers(
|
|
501
|
+
int16_t newTargetSpatialLayer, int16_t newTargetTemporalLayer)
|
|
502
|
+
{
|
|
503
|
+
MS_TRACE();
|
|
504
|
+
|
|
505
|
+
if (newTargetSpatialLayer == -1)
|
|
506
|
+
{
|
|
507
|
+
// Unset current and target layers.
|
|
508
|
+
this->encodingContext->SetTargetSpatialLayer(-1);
|
|
509
|
+
this->encodingContext->SetCurrentSpatialLayer(-1);
|
|
510
|
+
this->encodingContext->SetTargetTemporalLayer(-1);
|
|
511
|
+
this->encodingContext->SetCurrentTemporalLayer(-1);
|
|
512
|
+
|
|
513
|
+
MS_DEBUG_TAG(svc, "target layers changed [spatial:-1, temporal:-1]");
|
|
514
|
+
|
|
515
|
+
this->listener->OnProducerStreamManagerLayersChanged();
|
|
516
|
+
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
this->encodingContext->SetTargetSpatialLayer(newTargetSpatialLayer);
|
|
521
|
+
this->encodingContext->SetTargetTemporalLayer(newTargetTemporalLayer);
|
|
522
|
+
|
|
523
|
+
MS_DEBUG_TAG(
|
|
524
|
+
svc,
|
|
525
|
+
"target layers changed [spatial:%" PRIi16 ", temporal:%" PRIi16 "]",
|
|
526
|
+
newTargetSpatialLayer,
|
|
527
|
+
newTargetTemporalLayer);
|
|
528
|
+
|
|
529
|
+
// Target spatial layer has changed.
|
|
530
|
+
if (newTargetSpatialLayer != this->encodingContext->GetCurrentSpatialLayer())
|
|
531
|
+
{
|
|
532
|
+
// In K-SVC always ask for a keyframe when changing target spatial layer.
|
|
533
|
+
if (this->encodingContext->IsKSvc())
|
|
534
|
+
{
|
|
535
|
+
MS_DEBUG_DEV("K-SVC: requesting keyframe to target spatial change");
|
|
536
|
+
|
|
537
|
+
RequestKeyFrame();
|
|
538
|
+
}
|
|
539
|
+
// In full SVC just ask for a keyframe when upgrading target spatial layer.
|
|
540
|
+
// NOTE: This is because nobody implements RTCP LRR yet.
|
|
541
|
+
else if (newTargetSpatialLayer > this->encodingContext->GetCurrentSpatialLayer())
|
|
542
|
+
{
|
|
543
|
+
MS_DEBUG_DEV("full SVC: requesting keyframe to target spatial upgrade");
|
|
544
|
+
|
|
545
|
+
RequestKeyFrame();
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
bool SvcProducerStreamManager::RecalculateTargetLayers(
|
|
551
|
+
RTC::ConsumerTypes::VideoLayers& newTargetLayers) const
|
|
552
|
+
{
|
|
553
|
+
MS_TRACE();
|
|
554
|
+
|
|
555
|
+
// Start with no layers.
|
|
556
|
+
newTargetLayers.Reset();
|
|
557
|
+
|
|
558
|
+
auto nowMs = this->shared->GetTimeMs();
|
|
559
|
+
int16_t spatialLayer{ 0 };
|
|
560
|
+
|
|
561
|
+
if (!this->producerRtpStream)
|
|
562
|
+
{
|
|
563
|
+
goto done;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
if (this->producerRtpStream->GetScore() == 0u)
|
|
567
|
+
{
|
|
568
|
+
goto done;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
for (; std::cmp_less(spatialLayer, this->producerRtpStream->GetSpatialLayers()); ++spatialLayer)
|
|
572
|
+
{
|
|
573
|
+
// If this is higher than current spatial layer and we moved to current
|
|
574
|
+
// spatial layer due to BWE limitations, check how much it has elapsed
|
|
575
|
+
// since then.
|
|
576
|
+
if (nowMs - this->lastBweDowngradeAtMs < BweDowngradeConservativeMs)
|
|
577
|
+
{
|
|
578
|
+
if (newTargetLayers.spatial > -1 && spatialLayer > this->encodingContext->GetCurrentSpatialLayer())
|
|
579
|
+
{
|
|
580
|
+
continue;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
if (!this->producerRtpStream->GetSpatialLayerBitrate(nowMs, spatialLayer))
|
|
585
|
+
{
|
|
586
|
+
continue;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
newTargetLayers.spatial = spatialLayer;
|
|
590
|
+
|
|
591
|
+
// If this is the preferred or higher spatial layer and has bitrate,
|
|
592
|
+
// take it and exit.
|
|
593
|
+
if (spatialLayer >= this->preferredLayers.spatial)
|
|
594
|
+
{
|
|
595
|
+
break;
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
if (newTargetLayers.spatial != -1)
|
|
600
|
+
{
|
|
601
|
+
if (newTargetLayers.spatial == this->preferredLayers.spatial)
|
|
602
|
+
{
|
|
603
|
+
newTargetLayers.temporal = this->preferredLayers.temporal;
|
|
604
|
+
}
|
|
605
|
+
else if (newTargetLayers.spatial < this->preferredLayers.spatial)
|
|
606
|
+
{
|
|
607
|
+
newTargetLayers.temporal =
|
|
608
|
+
static_cast<int16_t>(this->encodingContext->GetTemporalLayers() - 1);
|
|
609
|
+
}
|
|
610
|
+
else
|
|
611
|
+
{
|
|
612
|
+
newTargetLayers.temporal = 0;
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
done:
|
|
617
|
+
|
|
618
|
+
// Return true if any target layer changed.
|
|
619
|
+
return newTargetLayers != this->encodingContext->GetTargetLayers();
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
void SvcProducerStreamManager::OnTransportConnected()
|
|
623
|
+
{
|
|
624
|
+
MS_TRACE();
|
|
625
|
+
|
|
626
|
+
this->syncRequired = true;
|
|
627
|
+
|
|
628
|
+
if (IsActive())
|
|
629
|
+
{
|
|
630
|
+
MayChangeLayers(/*force*/ false);
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
void SvcProducerStreamManager::OnTransportDisconnected()
|
|
635
|
+
{
|
|
636
|
+
MS_TRACE();
|
|
637
|
+
|
|
638
|
+
this->lastBweDowngradeAtMs = 0u;
|
|
639
|
+
|
|
640
|
+
UpdateTargetLayers(-1, -1);
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
void SvcProducerStreamManager::OnPaused()
|
|
644
|
+
{
|
|
645
|
+
MS_TRACE();
|
|
646
|
+
|
|
647
|
+
this->lastBweDowngradeAtMs = 0u;
|
|
648
|
+
|
|
649
|
+
UpdateTargetLayers(-1, -1);
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
void SvcProducerStreamManager::OnResumed()
|
|
653
|
+
{
|
|
654
|
+
MS_TRACE();
|
|
655
|
+
|
|
656
|
+
this->syncRequired = true;
|
|
657
|
+
|
|
658
|
+
if (IsActive())
|
|
659
|
+
{
|
|
660
|
+
MayChangeLayers(/*force*/ false);
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
} // namespace RTC
|