mediasoup 3.16.0 → 3.16.2

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mediasoup",
3
- "version": "3.16.0",
3
+ "version": "3.16.2",
4
4
  "description": "Cutting Edge WebRTC Video Conferencing",
5
5
  "contributors": [
6
6
  "Iñaki Baz Castillo <ibc@aliax.net> (https://inakibaz.me)",
@@ -100,24 +100,24 @@
100
100
  "tar": "^7.4.3"
101
101
  },
102
102
  "devDependencies": {
103
- "@eslint/js": "^9.27.0",
103
+ "@eslint/js": "^9.29.0",
104
104
  "@octokit/rest": "^22.0.0",
105
105
  "@types/debug": "^4.1.12",
106
- "@types/jest": "^29.5.14",
107
- "@types/node": "^22.15.21",
108
- "eslint": "^9.27.0",
106
+ "@types/jest": "^30.0.0",
107
+ "@types/node": "^24.0.4",
108
+ "eslint": "^9.29.0",
109
109
  "eslint-config-prettier": "^10.1.5",
110
- "eslint-plugin-jest": "^28.11.0",
111
- "eslint-plugin-prettier": "^5.4.0",
110
+ "eslint-plugin-jest": "^29.0.1",
111
+ "eslint-plugin-prettier": "^5.5.1",
112
112
  "globals": "^16.2.0",
113
- "jest": "^29.7.0",
114
- "marked": "^15.0.12",
113
+ "jest": "^30.0.3",
114
+ "marked": "^16.0.0",
115
115
  "open-cli": "^8.0.0",
116
116
  "pick-port": "^2.1.0",
117
- "prettier": "^3.5.3",
117
+ "prettier": "^3.6.2",
118
118
  "sctp": "^1.0.0",
119
- "ts-jest": "^29.3.4",
119
+ "ts-jest": "^29.4.0",
120
120
  "typescript": "^5.8.3",
121
- "typescript-eslint": "^8.32.1"
121
+ "typescript-eslint": "^8.35.0"
122
122
  }
123
123
  }
@@ -460,6 +460,7 @@ public:
460
460
  } \
461
461
  while (false)
462
462
 
463
+ #ifdef MS_EXECUTABLE
463
464
  #define MS_ABORT(desc, ...) \
464
465
  do \
465
466
  { \
@@ -468,6 +469,18 @@ public:
468
469
  std::abort(); \
469
470
  } \
470
471
  while (false)
472
+ #else
473
+ #define MS_ABORT(desc, ...) \
474
+ do \
475
+ { \
476
+ std::fprintf(stderr, "(ABORT) " _MS_LOG_STR_DESC desc _MS_LOG_SEPARATOR_CHAR_STD, _MS_LOG_ARG, ##__VA_ARGS__); \
477
+ std::fflush(stderr); \
478
+ char abortMessage[Logger::BufferSize]; \
479
+ std::snprintf(abortMessage, Logger::BufferSize, "(ABORT) " _MS_LOG_STR_DESC desc _MS_LOG_SEPARATOR_CHAR_STD, _MS_LOG_ARG, ##__VA_ARGS__); \
480
+ throw std::runtime_error(abortMessage); \
481
+ } \
482
+ while (false)
483
+ #endif
471
484
 
472
485
  #define MS_ASSERT(condition, desc, ...) \
473
486
  if (!(condition)) \
@@ -4,6 +4,7 @@
4
4
  #include "RTC/Consumer.hpp"
5
5
  #include "RTC/SeqManager.hpp"
6
6
  #include "RTC/Shared.hpp"
7
+ #include <map>
7
8
 
8
9
  namespace RTC
9
10
  {
@@ -59,6 +60,11 @@ namespace RTC
59
60
  void UserOnResumed() override;
60
61
  void CreateRtpStreams();
61
62
  void RequestKeyFrame();
63
+ void StorePacketInTargetLayerRetransmissionBuffer(
64
+ std::map<uint16_t, std::shared_ptr<RTC::RtpPacket>, RTC::SeqManager<uint16_t>::SeqLowerThan>&
65
+ targetLayerRetransmissionBuffer,
66
+ RTC::RtpPacket* packet,
67
+ std::shared_ptr<RTC::RtpPacket>& sharedPacket);
62
68
 
63
69
  /* Pure virtual methods inherited from RtpStreamSend::Listener. */
64
70
  public:
@@ -75,6 +81,12 @@ namespace RTC
75
81
  absl::flat_hash_map<RTC::RtpStreamSend*, bool> mapRtpStreamSyncRequired;
76
82
  absl::flat_hash_map<RTC::RtpStreamSend*, std::unique_ptr<RTC::SeqManager<uint16_t>>>
77
83
  mapRtpStreamRtpSeqManager;
84
+ // Buffers to store packets that arrive earlier than the first packet of the
85
+ // video key frame.
86
+ absl::flat_hash_map<
87
+ RTC::RtpStreamSend*,
88
+ std::map<uint16_t, std::shared_ptr<RTC::RtpPacket>, RTC::SeqManager<uint16_t>::SeqLowerThan>>
89
+ mapRtpStreamTargetLayerRetransmissionBuffer;
78
90
  };
79
91
  } // namespace RTC
80
92
 
@@ -11,7 +11,7 @@ namespace RTC
11
11
  class RtpPacket
12
12
  {
13
13
  public:
14
- enum class DropReason : uint8_t
14
+ enum class DiscardReason : uint8_t
15
15
  {
16
16
  NONE = 0,
17
17
  PRODUCER_NOT_FOUND,
@@ -23,18 +23,18 @@ namespace RTC
23
23
  NOT_A_KEYFRAME,
24
24
  EMPTY_PAYLOAD,
25
25
  SPATIAL_LAYER_MISMATCH,
26
- TOO_HIGH_TIMESTAMP_EXTRA_NEEDED,
27
26
  PACKET_PREVIOUS_TO_SPATIAL_LAYER_SWITCH,
28
27
  DROPPED_BY_CODEC,
29
- SEND_RTP_STREAM_DISCARDED,
28
+ TOO_HIGH_TIMESTAMP_EXTRA_NEEDED,
29
+ SEND_RTP_STREAM_DISCARDED
30
30
  };
31
31
 
32
- static absl::flat_hash_map<DropReason, std::string> dropReason2String;
32
+ static absl::flat_hash_map<DiscardReason, std::string> discardReason2String;
33
33
 
34
34
  RtpPacket() = default;
35
35
  ~RtpPacket() = default;
36
36
  void Sent();
37
- void Dropped(DropReason dropReason);
37
+ void Discarded(DiscardReason discardReason);
38
38
 
39
39
  private:
40
40
  void Log() const;
@@ -51,8 +51,8 @@ namespace RTC
51
51
  uint32_t sendRtpTimestamp{};
52
52
  uint16_t recvSeqNumber{};
53
53
  uint16_t sendSeqNumber{};
54
- bool dropped{};
55
- DropReason dropReason{ DropReason::NONE };
54
+ bool discarded{};
55
+ DiscardReason discardReason{ DiscardReason::NONE };
56
56
  };
57
57
  }; // namespace RtcLogger
58
58
  } // namespace RTC
@@ -5,6 +5,7 @@
5
5
  #include "RTC/Consumer.hpp"
6
6
  #include "RTC/SeqManager.hpp"
7
7
  #include "RTC/Shared.hpp"
8
+ #include <map>
8
9
 
9
10
  namespace RTC
10
11
  {
@@ -72,6 +73,8 @@ namespace RTC
72
73
  void UserOnResumed() override;
73
74
  void CreateRtpStream();
74
75
  void RequestKeyFrame();
76
+ void StorePacketInTargetLayerRetransmissionBuffer(
77
+ RTC::RtpPacket* packet, std::shared_ptr<RTC::RtpPacket>& sharedPacket);
75
78
  void EmitScore() const;
76
79
 
77
80
  /* Pure virtual methods inherited from RtpStreamSend::Listener. */
@@ -90,6 +93,10 @@ namespace RTC
90
93
  std::unique_ptr<RTC::SeqManager<uint16_t>> rtpSeqManager;
91
94
  bool managingBitrate{ false };
92
95
  std::unique_ptr<RTC::Codecs::EncodingContext> encodingContext;
96
+ // Buffer to store packets that arrive earlier than the first packet of the
97
+ // video key frame.
98
+ std::map<uint16_t, std::shared_ptr<RTC::RtpPacket>, RTC::SeqManager<uint16_t>::SeqLowerThan>
99
+ targetLayerRetransmissionBuffer;
93
100
  };
94
101
  } // namespace RTC
95
102
 
@@ -6,6 +6,7 @@
6
6
  #include "RTC/Consumer.hpp"
7
7
  #include "RTC/SeqManager.hpp"
8
8
  #include "RTC/Shared.hpp"
9
+ #include <map>
9
10
 
10
11
  namespace RTC
11
12
  {
@@ -95,6 +96,8 @@ namespace RTC
95
96
  void UpdateTargetLayers(int16_t newTargetSpatialLayer, int16_t newTargetTemporalLayer);
96
97
  bool CanSwitchToSpatialLayer(int16_t spatialLayer) const;
97
98
  void EmitScore() const;
99
+ void StorePacketInTargetLayerRetransmissionBuffer(
100
+ RTC::RtpPacket* packet, std::shared_ptr<RTC::RtpPacket>& sharedPacket);
98
101
  void EmitLayersChange() const;
99
102
  RTC::RtpStreamRecv* GetProducerCurrentRtpStream() const;
100
103
  RTC::RtpStreamRecv* GetProducerTargetRtpStream() const;
@@ -129,7 +132,12 @@ namespace RTC
129
132
  std::unique_ptr<RTC::Codecs::EncodingContext> encodingContext;
130
133
  uint32_t tsOffset{ 0u }; // RTP Timestamp offset.
131
134
  bool keyFrameForTsOffsetRequested{ false };
132
- uint64_t lastBweDowngradeAtMs{ 0u }; // Last time we moved to lower spatial layer due to BWE.
135
+ // Last time we moved to lower spatial layer due to BWE.
136
+ uint64_t lastBweDowngradeAtMs{ 0u };
137
+ // Buffer to store packets that arrive earlier than the first packet of the
138
+ // video key frame.
139
+ std::map<uint16_t, std::shared_ptr<RTC::RtpPacket>, RTC::SeqManager<uint16_t>::SeqLowerThan>
140
+ targetLayerRetransmissionBuffer;
133
141
  };
134
142
  } // namespace RTC
135
143
 
@@ -86,6 +86,8 @@ namespace RTC
86
86
  bool RecalculateTargetLayers(int16_t& newTargetSpatialLayer, int16_t& newTargetTemporalLayer) const;
87
87
  void UpdateTargetLayers(int16_t newTargetSpatialLayer, int16_t newTargetTemporalLayer);
88
88
  void EmitScore() const;
89
+ void StorePacketInTargetLayerRetransmissionBuffer(
90
+ RTC::RtpPacket* packet, std::shared_ptr<RTC::RtpPacket>& sharedPacket);
89
91
  void EmitLayersChange() const;
90
92
 
91
93
  /* Pure virtual methods inherited from RtpStreamSend::Listener. */
@@ -106,7 +108,12 @@ namespace RTC
106
108
  int16_t provisionalTargetSpatialLayer{ -1 };
107
109
  int16_t provisionalTargetTemporalLayer{ -1 };
108
110
  std::unique_ptr<RTC::Codecs::EncodingContext> encodingContext;
109
- uint64_t lastBweDowngradeAtMs{ 0u }; // Last time we moved to lower spatial layer due to BWE.
111
+ // Last time we moved to lower spatial layer due to BWE.
112
+ uint64_t lastBweDowngradeAtMs{ 0u };
113
+ // Buffer to store packets that arrive earlier than the first packet of the
114
+ // video key frame.
115
+ std::map<uint16_t, std::shared_ptr<RTC::RtpPacket>, RTC::SeqManager<uint16_t>::SeqLowerThan>
116
+ targetLayerRetransmissionBuffer;
110
117
  };
111
118
  } // namespace RTC
112
119
 
@@ -259,8 +259,8 @@ libuv_proj = subproject(
259
259
  ],
260
260
  )
261
261
 
262
- libsrtp2_proj = subproject(
263
- 'libsrtp2',
262
+ libsrtp3_proj = subproject(
263
+ 'libsrtp3',
264
264
  default_options: [
265
265
  'warning_level=0',
266
266
  'crypto-library=openssl',
@@ -310,7 +310,7 @@ dependencies = [
310
310
  abseil_cpp_proj.get_variable('absl_container_dep'),
311
311
  openssl_proj.get_variable('openssl_dep'),
312
312
  libuv_proj.get_variable('libuv_dep'),
313
- libsrtp2_proj.get_variable('libsrtp2_dep'),
313
+ libsrtp3_proj.get_variable('libsrtp3_dep'),
314
314
  usrsctp_proj.get_variable('usrsctp_dep'),
315
315
  flatbuffers_proj.get_variable('flatbuffers_dep'),
316
316
  flatbuffers_generator_dep,
@@ -322,7 +322,7 @@ link_whole = [
322
322
  openssl_proj.get_variable('libcrypto_lib'),
323
323
  openssl_proj.get_variable('libssl_lib'),
324
324
  libuv_proj.get_variable('libuv'),
325
- libsrtp2_proj.get_variable('libsrtp2'),
325
+ libsrtp3_proj.get_variable('libsrtp3'),
326
326
  usrsctp_proj.get_variable('usrsctp'),
327
327
  flatbuffers_proj.get_variable('flatbuffers_lib'),
328
328
  libwebrtc,
@@ -1,5 +1,5 @@
1
1
  option('ms_log_trace', type : 'boolean', value : false, description : 'When set to true, logs the current method/function if current log level is "debug"')
2
2
  option('ms_log_file_line', type : 'boolean', value : false, description : 'When set to true, all the logging macros print more verbose information, including current file and line')
3
- option('ms_rtc_logger_rtp', type : 'boolean', value : false, description : 'When set to true, prints a line with information for each RTP packet')
3
+ option('ms_rtc_logger_rtp', type : 'boolean', value : false, description : 'When set to true, prints a line with information for each processed RTP packet')
4
4
  option('ms_disable_liburing', type : 'boolean', value : false, description : 'When set to true, disables liburing integration despite current host supports it')
5
5
  option('ms_sctp_stack', type : 'boolean', value : false, description : 'When set to true, uses mediasoup SCTP stack instead of usrsctp library')
@@ -121,9 +121,10 @@
121
121
  "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
122
122
  },
123
123
  "node_modules/brace-expansion": {
124
- "version": "2.0.1",
125
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
126
- "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
124
+ "version": "2.0.2",
125
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
126
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
127
+ "license": "MIT",
127
128
  "dependencies": {
128
129
  "balanced-match": "^1.0.0"
129
130
  }
@@ -144,9 +145,10 @@
144
145
  }
145
146
  },
146
147
  "node_modules/clang-format/node_modules/brace-expansion": {
147
- "version": "1.1.11",
148
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
149
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
148
+ "version": "1.1.12",
149
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
150
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
151
+ "license": "MIT",
150
152
  "dependencies": {
151
153
  "balanced-match": "^1.0.0",
152
154
  "concat-map": "0.0.1"
@@ -674,9 +676,9 @@
674
676
  "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
675
677
  },
676
678
  "brace-expansion": {
677
- "version": "2.0.1",
678
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
679
- "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
679
+ "version": "2.0.2",
680
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
681
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
680
682
  "requires": {
681
683
  "balanced-match": "^1.0.0"
682
684
  }
@@ -692,9 +694,9 @@
692
694
  },
693
695
  "dependencies": {
694
696
  "brace-expansion": {
695
- "version": "1.1.11",
696
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
697
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
697
+ "version": "1.1.12",
698
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
699
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
698
700
  "requires": {
699
701
  "balanced-match": "^1.0.0",
700
702
  "concat-map": "0.0.1"
@@ -6,9 +6,16 @@
6
6
  #include "MediaSoupErrors.hpp"
7
7
  #include "Utils.hpp"
8
8
  #include "RTC/Codecs/Tools.hpp"
9
+ #ifdef MS_RTC_LOGGER_RTP
10
+ #include "RTC/RtcLogger.hpp"
11
+ #endif
9
12
 
10
13
  namespace RTC
11
14
  {
15
+ /* Static. */
16
+
17
+ static constexpr size_t TargetLayerRetransmissionBufferSize{ 15u };
18
+
12
19
  /* Instance methods. */
13
20
 
14
21
  PipeConsumer::PipeConsumer(
@@ -52,9 +59,13 @@ namespace RTC
52
59
  {
53
60
  delete rtpStream;
54
61
  }
62
+
55
63
  this->rtpStreams.clear();
56
64
  this->mapMappedSsrcSsrc.clear();
57
65
  this->mapSsrcRtpStream.clear();
66
+ this->mapRtpStreamSyncRequired.clear();
67
+ this->mapRtpStreamRtpSeqManager.clear();
68
+ this->mapRtpStreamTargetLayerRetransmissionBuffer.clear();
58
69
  }
59
70
 
60
71
  flatbuffers::Offset<FBS::Consumer::DumpResponse> PipeConsumer::FillBuffer(
@@ -222,67 +233,95 @@ namespace RTC
222
233
  packet->logger.consumerId = this->id;
223
234
  #endif
224
235
 
236
+ auto ssrc = this->mapMappedSsrcSsrc.at(packet->GetSsrc());
237
+ auto* rtpStream = this->mapSsrcRtpStream.at(ssrc);
238
+ auto& syncRequired = this->mapRtpStreamSyncRequired.at(rtpStream);
239
+ auto& rtpSeqManager = this->mapRtpStreamRtpSeqManager.at(rtpStream);
240
+ auto& targetLayerRetransmissionBuffer =
241
+ this->mapRtpStreamTargetLayerRetransmissionBuffer.at(rtpStream);
242
+
225
243
  if (!IsActive())
226
244
  {
227
245
  #ifdef MS_RTC_LOGGER_RTP
228
- packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::CONSUMER_INACTIVE);
246
+ packet->logger.Discarded(RtcLogger::RtpPacket::DiscardReason::CONSUMER_INACTIVE);
229
247
  #endif
230
248
 
249
+ rtpSeqManager->Drop(packet->GetSequenceNumber());
250
+
231
251
  return;
232
252
  }
233
253
 
234
- auto payloadType = packet->GetPayloadType();
235
-
236
- // NOTE: This may happen if this Consumer supports just some codecs of those
237
- // in the corresponding Producer.
238
- if (!this->supportedCodecPayloadTypes[payloadType])
254
+ // If we need to sync, support key frames and this is not a key frame, ignore
255
+ // the packet.
256
+ if (syncRequired && this->keyFrameSupported && !packet->IsKeyFrame())
239
257
  {
240
- MS_DEBUG_DEV("payload type not supported [payloadType:%" PRIu8 "]", payloadType);
241
-
242
258
  #ifdef MS_RTC_LOGGER_RTP
243
- packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::UNSUPPORTED_PAYLOAD_TYPE);
259
+ packet->logger.Discarded(RtcLogger::RtpPacket::DiscardReason::NOT_A_KEYFRAME);
244
260
  #endif
245
261
 
262
+ // NOTE: No need to drop the packet in the RTP sequence manager since here
263
+ // we are blocking all packets but the key frame that would trigger sync
264
+ // below.
265
+
266
+ // Store the packet for the scenario in which this packet is part of the
267
+ // key frame and it arrived before the first packet of the key frame.
268
+ // TODO: Uncomment once this issue is fixed:
269
+ // https://github.com/versatica/mediasoup/issues/1554
270
+ // StorePacketInTargetLayerRetransmissionBuffer(
271
+ // targetLayerRetransmissionBuffer, packet, sharedPacket);
272
+
246
273
  return;
247
274
  }
248
275
 
249
- auto ssrc = this->mapMappedSsrcSsrc.at(packet->GetSsrc());
250
- auto* rtpStream = this->mapSsrcRtpStream.at(ssrc);
251
- auto& syncRequired = this->mapRtpStreamSyncRequired.at(rtpStream);
252
- auto& rtpSeqManager = this->mapRtpStreamRtpSeqManager.at(rtpStream);
276
+ auto payloadType = packet->GetPayloadType();
253
277
 
254
- // If we need to sync, support key frames and this is not a key frame, ignore
255
- // the packet.
256
- if (syncRequired && this->keyFrameSupported && !packet->IsKeyFrame())
278
+ // NOTE: This may happen if this Consumer supports just some codecs of those
279
+ // in the corresponding Producer.
280
+ if (!this->supportedCodecPayloadTypes[payloadType])
257
281
  {
282
+ MS_WARN_DEV("payload type not supported [payloadType:%" PRIu8 "]", payloadType);
283
+
258
284
  #ifdef MS_RTC_LOGGER_RTP
259
- packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::NOT_A_KEYFRAME);
285
+ packet->logger.Discarded(RtcLogger::RtpPacket::DiscardReason::UNSUPPORTED_PAYLOAD_TYPE);
260
286
  #endif
261
287
 
288
+ rtpSeqManager->Drop(packet->GetSequenceNumber());
289
+
262
290
  return;
263
291
  }
264
292
 
265
293
  // Packets with only padding are not forwarded.
266
294
  if (packet->GetPayloadLength() == 0)
267
295
  {
268
- rtpSeqManager->Drop(packet->GetSequenceNumber());
269
-
270
296
  #ifdef MS_RTC_LOGGER_RTP
271
- packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::EMPTY_PAYLOAD);
297
+ packet->logger.Discarded(RtcLogger::RtpPacket::DiscardReason::EMPTY_PAYLOAD);
272
298
  #endif
273
299
 
300
+ rtpSeqManager->Drop(packet->GetSequenceNumber());
301
+
274
302
  return;
275
303
  }
276
304
 
277
305
  // Whether this is the first packet after re-sync.
278
306
  const bool isSyncPacket = syncRequired;
279
307
 
308
+ // Whether packets stored in the target layer retransmission buffer must be
309
+ // sent once this packet is sent.
310
+ bool sendPacketsInTargetLayerRetransmissionBuffer{ false };
311
+
280
312
  // Sync sequence number and timestamp if required.
281
313
  if (isSyncPacket)
282
314
  {
283
315
  if (packet->IsKeyFrame())
284
316
  {
285
- MS_DEBUG_TAG(rtp, "sync key frame received");
317
+ MS_DEBUG_TAG(
318
+ rtp,
319
+ "sync key frame received [ssrc:%" PRIu32 ", seq:%" PRIu16 ", ts:%" PRIu32 "]",
320
+ packet->GetSsrc(),
321
+ packet->GetSequenceNumber(),
322
+ packet->GetTimestamp());
323
+
324
+ sendPacketsInTargetLayerRetransmissionBuffer = true;
286
325
  }
287
326
 
288
327
  rtpSeqManager->Sync(packet->GetSequenceNumber() - 1);
@@ -321,8 +360,9 @@ namespace RTC
321
360
  origSeq);
322
361
  }
323
362
 
324
- // Process the packet.
325
- if (rtpStream->ReceivePacket(packet, sharedPacket))
363
+ const bool sent = rtpStream->ReceivePacket(packet, sharedPacket);
364
+
365
+ if (sent)
326
366
  {
327
367
  // Send the packet.
328
368
  this->listener->OnConsumerSendRtpPacket(this, packet);
@@ -341,11 +381,46 @@ namespace RTC
341
381
  packet->GetTimestamp(),
342
382
  origSsrc,
343
383
  origSeq);
384
+
385
+ #ifdef MS_RTC_LOGGER_RTP
386
+ packet->logger.Discarded(RtcLogger::RtpPacket::DiscardReason::SEND_RTP_STREAM_DISCARDED);
387
+ #endif
344
388
  }
345
389
 
346
390
  // Restore packet fields.
347
391
  packet->SetSsrc(origSsrc);
348
392
  packet->SetSequenceNumber(origSeq);
393
+
394
+ // If sent packet was the first packet of a key frame, let's send buffered
395
+ // packets belonging to the same key frame that arrived earlier due to
396
+ // packet misorder.
397
+ if (sendPacketsInTargetLayerRetransmissionBuffer)
398
+ {
399
+ // NOTE: Only send buffered packets if the first packet containing the key
400
+ // frame was sent.
401
+ if (sent)
402
+ {
403
+ for (auto& kv : targetLayerRetransmissionBuffer)
404
+ {
405
+ auto& bufferedSharedPacket = kv.second;
406
+ auto* bufferedPacket = bufferedSharedPacket.get();
407
+
408
+ if (bufferedPacket->GetSequenceNumber() > origSeq)
409
+ {
410
+ MS_DEBUG_DEV(
411
+ "sending packet buffered in the target layer retransmission buffer [ssrc:%" PRIu32
412
+ ", seq:%" PRIu16 ", ts:%" PRIu32 "]",
413
+ bufferedPacket->GetSsrc(),
414
+ bufferedPacket->GetSequenceNumber(),
415
+ bufferedPacket->GetTimestamp());
416
+
417
+ SendRtpPacket(bufferedPacket, bufferedSharedPacket);
418
+ }
419
+ }
420
+ }
421
+
422
+ targetLayerRetransmissionBuffer.clear();
423
+ }
349
424
  }
350
425
 
351
426
  bool PipeConsumer::GetRtcp(RTC::RTCP::CompoundPacket* packet, uint64_t nowMs)
@@ -557,6 +632,13 @@ namespace RTC
557
632
  {
558
633
  rtpStream->Pause();
559
634
  }
635
+
636
+ for (auto& kv : this->mapRtpStreamTargetLayerRetransmissionBuffer)
637
+ {
638
+ auto& targetLayerRetransmissionBuffer = kv.second;
639
+
640
+ targetLayerRetransmissionBuffer.clear();
641
+ }
560
642
  }
561
643
 
562
644
  void PipeConsumer::UserOnPaused()
@@ -567,6 +649,13 @@ namespace RTC
567
649
  {
568
650
  rtpStream->Pause();
569
651
  }
652
+
653
+ for (auto& kv : this->mapRtpStreamTargetLayerRetransmissionBuffer)
654
+ {
655
+ auto& targetLayerRetransmissionBuffer = kv.second;
656
+
657
+ targetLayerRetransmissionBuffer.clear();
658
+ }
570
659
  }
571
660
 
572
661
  void PipeConsumer::UserOnResumed()
@@ -690,6 +779,8 @@ namespace RTC
690
779
 
691
780
  this->mapRtpStreamRtpSeqManager[rtpStream].reset(
692
781
  new RTC::SeqManager<uint16_t>(initialOutputSeq));
782
+
783
+ this->mapRtpStreamTargetLayerRetransmissionBuffer[rtpStream];
693
784
  }
694
785
  }
695
786
 
@@ -710,7 +801,37 @@ namespace RTC
710
801
  }
711
802
  }
712
803
 
713
- inline void PipeConsumer::OnRtpStreamScore(
804
+ void PipeConsumer::StorePacketInTargetLayerRetransmissionBuffer(
805
+ std::map<uint16_t, std::shared_ptr<RTC::RtpPacket>, RTC::SeqManager<uint16_t>::SeqLowerThan>&
806
+ targetLayerRetransmissionBuffer,
807
+ RTC::RtpPacket* packet,
808
+ std::shared_ptr<RTC::RtpPacket>& sharedPacket)
809
+ {
810
+ MS_TRACE();
811
+
812
+ MS_DEBUG_DEV(
813
+ "storing packet in target layer retransmission buffer [ssrc:%" PRIu32 ", seq:%" PRIu16
814
+ ", ts:%" PRIu32 "]",
815
+ packet->GetSsrc(),
816
+ packet->GetSequenceNumber(),
817
+ packet->GetTimestamp());
818
+
819
+ // Store original packet into the buffer. Only clone once and only if
820
+ // necessary.
821
+ if (!sharedPacket)
822
+ {
823
+ sharedPacket.reset(packet->Clone());
824
+ }
825
+
826
+ targetLayerRetransmissionBuffer[packet->GetSequenceNumber()] = sharedPacket;
827
+
828
+ if (targetLayerRetransmissionBuffer.size() > TargetLayerRetransmissionBufferSize)
829
+ {
830
+ targetLayerRetransmissionBuffer.erase(targetLayerRetransmissionBuffer.begin());
831
+ }
832
+ }
833
+
834
+ void PipeConsumer::OnRtpStreamScore(
714
835
  RTC::RtpStream* /*rtpStream*/, uint8_t /*score*/, uint8_t /*previousScore*/)
715
836
  {
716
837
  MS_TRACE();
@@ -718,8 +839,7 @@ namespace RTC
718
839
  // Do nothing.
719
840
  }
720
841
 
721
- inline void PipeConsumer::OnRtpStreamRetransmitRtpPacket(
722
- RTC::RtpStreamSend* rtpStream, RTC::RtpPacket* packet)
842
+ void PipeConsumer::OnRtpStreamRetransmitRtpPacket(RTC::RtpStreamSend* rtpStream, RTC::RtpPacket* packet)
723
843
  {
724
844
  MS_TRACE();
725
845
 
@@ -10,6 +10,9 @@
10
10
  #include "RTC/Consts.hpp"
11
11
  #include "RTC/RTCP/Feedback.hpp"
12
12
  #include "RTC/RTCP/XrReceiverReferenceTime.hpp"
13
+ #ifdef MS_RTC_LOGGER_RTP
14
+ #include "RTC/RtcLogger.hpp"
15
+ #endif
13
16
  #include <absl/container/inlined_vector.h>
14
17
  #include <cstring> // std::memcpy()
15
18
 
@@ -592,7 +595,7 @@ namespace RTC
592
595
  MS_WARN_TAG(rtp, "no stream found for received packet [ssrc:%" PRIu32 "]", packet->GetSsrc());
593
596
 
594
597
  #ifdef MS_RTC_LOGGER_RTP
595
- packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::RECV_RTP_STREAM_NOT_FOUND);
598
+ packet->logger.Discarded(RtcLogger::RtpPacket::DiscardReason::RECV_RTP_STREAM_NOT_FOUND);
596
599
  #endif
597
600
 
598
601
  return ReceiveRtpPacketResult::DISCARDED;
@@ -619,7 +622,7 @@ namespace RTC
619
622
  }
620
623
 
621
624
  #ifdef MS_RTC_LOGGER_RTP
622
- packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::RECV_RTP_STREAM_DISCARDED);
625
+ packet->logger.Discarded(RtcLogger::RtpPacket::DiscardReason::RECV_RTP_STREAM_DISCARDED);
623
626
  #endif
624
627
 
625
628
  return result;
@@ -635,7 +638,7 @@ namespace RTC
635
638
  if (!rtpStream->ReceiveRtxPacket(packet))
636
639
  {
637
640
  #ifdef MS_RTC_LOGGER_RTP
638
- packet->logger.Dropped(RtcLogger::RtpPacket::DropReason::RECV_RTP_STREAM_NOT_FOUND);
641
+ packet->logger.Discarded(RtcLogger::RtpPacket::DiscardReason::RECV_RTP_STREAM_NOT_FOUND);
639
642
  #endif
640
643
 
641
644
  return result;