@@ -40,11 +40,12 @@ class SimulcastTrackInfo {
40
40
41
41
List <rtc.RTCRtpEncoding >? encodings;
42
42
43
- SimulcastTrackInfo (
44
- {required this .codec,
45
- this .encodings,
46
- required this .mediaStreamTrack,
47
- this .sender});
43
+ SimulcastTrackInfo ({
44
+ required this .codec,
45
+ this .encodings,
46
+ required this .mediaStreamTrack,
47
+ this .sender,
48
+ });
48
49
}
49
50
50
51
/// A video track from the local device. Use static methods in this class to create
@@ -62,6 +63,7 @@ class LocalVideoTrack extends LocalTrack with VideoTrack {
62
63
final Map <String , num > _bitrateFoLayers = {};
63
64
64
65
Map <String , SimulcastTrackInfo > simulcastCodecs = {};
66
+ Map <(String , int ), rtc.RTCRtpEncoding > encodingBackups = {};
65
67
66
68
List <lk_rtc.SubscribedCodec > subscribedCodecs = [];
67
69
@@ -100,11 +102,13 @@ class LocalVideoTrack extends LocalTrack with VideoTrack {
100
102
}
101
103
});
102
104
_currentBitrate = totalBitrate;
103
- events.emit (VideoSenderStatsEvent (
104
- stats: statsMap,
105
- currentBitrate: currentBitrate,
106
- bitrateForLayers: _bitrateFoLayers,
107
- ));
105
+ events.emit (
106
+ VideoSenderStatsEvent (
107
+ stats: statsMap,
108
+ currentBitrate: currentBitrate,
109
+ bitrateForLayers: _bitrateFoLayers,
110
+ ),
111
+ );
108
112
}
109
113
110
114
prevStats = statsMap;
@@ -131,14 +135,22 @@ class LocalVideoTrack extends LocalTrack with VideoTrack {
131
135
vs.bytesSent = getNumValFromReport (v.values, 'bytesSent' );
132
136
vs.framesSent = getNumValFromReport (v.values, 'framesSent' );
133
137
vs.rid = getStringValFromReport (v.values, 'rid' );
134
- vs.encoderImplementation =
135
- getStringValFromReport (v.values, 'encoderImplementation' );
136
- vs.retransmittedPacketsSent =
137
- getNumValFromReport (v.values, 'retransmittedPacketsSent' );
138
- vs.qualityLimitationReason =
139
- getStringValFromReport (v.values, 'qualityLimitationReason' );
140
- vs.qualityLimitationResolutionChanges =
141
- getNumValFromReport (v.values, 'qualityLimitationResolutionChanges' );
138
+ vs.encoderImplementation = getStringValFromReport (
139
+ v.values,
140
+ 'encoderImplementation' ,
141
+ );
142
+ vs.retransmittedPacketsSent = getNumValFromReport (
143
+ v.values,
144
+ 'retransmittedPacketsSent' ,
145
+ );
146
+ vs.qualityLimitationReason = getStringValFromReport (
147
+ v.values,
148
+ 'qualityLimitationReason' ,
149
+ );
150
+ vs.qualityLimitationResolutionChanges = getNumValFromReport (
151
+ v.values,
152
+ 'qualityLimitationResolutionChanges' ,
153
+ );
142
154
143
155
// locate the appropriate remote-inbound-rtp item
144
156
final remoteId = getStringValFromReport (v.values, 'remoteId' );
@@ -162,14 +174,12 @@ class LocalVideoTrack extends LocalTrack with VideoTrack {
162
174
}
163
175
164
176
// Private constructor
165
- LocalVideoTrack ._(TrackSource source, rtc.MediaStream stream,
166
- rtc.MediaStreamTrack track, this .currentOptions)
167
- : super (
168
- TrackType .VIDEO ,
169
- source,
170
- stream,
171
- track,
172
- );
177
+ LocalVideoTrack ._(
178
+ TrackSource source,
179
+ rtc.MediaStream stream,
180
+ rtc.MediaStreamTrack track,
181
+ this .currentOptions,
182
+ ) : super (TrackType .VIDEO , source, stream, track);
173
183
174
184
/// Creates a LocalVideoTrack from camera input.
175
185
static Future <LocalVideoTrack > createCameraTrack ([
@@ -201,7 +211,8 @@ class LocalVideoTrack extends LocalTrack with VideoTrack {
201
211
]) async {
202
212
if (lkPlatformIsWebMobile ()) {
203
213
throw TrackCreateException (
204
- 'Screen sharing is not supported on mobile devices' );
214
+ 'Screen sharing is not supported on mobile devices' ,
215
+ );
205
216
}
206
217
options ?? = const ScreenShareCaptureOptions ();
207
218
@@ -224,7 +235,8 @@ class LocalVideoTrack extends LocalTrack with VideoTrack {
224
235
]) async {
225
236
if (lkPlatformIsWebMobile ()) {
226
237
throw TrackCreateException (
227
- 'Screen sharing is not supported on mobile devices' );
238
+ 'Screen sharing is not supported on mobile devices' ,
239
+ );
228
240
}
229
241
if (options == null ) {
230
242
options = const ScreenShareCaptureOptions (captureScreenAudio: true );
@@ -239,12 +251,18 @@ class LocalVideoTrack extends LocalTrack with VideoTrack {
239
251
stream,
240
252
stream.getVideoTracks ().first,
241
253
options,
242
- )
254
+ ),
243
255
];
244
256
245
257
if (stream.getAudioTracks ().isNotEmpty) {
246
- tracks.add (LocalAudioTrack (TrackSource .screenShareAudio, stream,
247
- stream.getAudioTracks ().first, const AudioCaptureOptions ()));
258
+ tracks.add (
259
+ LocalAudioTrack (
260
+ TrackSource .screenShareAudio,
261
+ stream,
262
+ stream.getAudioTracks ().first,
263
+ const AudioCaptureOptions (),
264
+ ),
265
+ );
248
266
}
249
267
return tracks;
250
268
}
@@ -262,10 +280,11 @@ extension LocalVideoTrackExt on LocalVideoTrack {
262
280
return ;
263
281
}
264
282
final newOptions = CameraCaptureOptions (
265
- cameraPosition: position,
266
- deviceId: null ,
267
- maxFrameRate: options.maxFrameRate,
268
- params: options.params);
283
+ cameraPosition: position,
284
+ deviceId: null ,
285
+ maxFrameRate: options.maxFrameRate,
286
+ params: options.params,
287
+ );
269
288
await restartTrack (newOptions);
270
289
await replaceTrackForMultiCodecSimulcast (mediaStreamTrack);
271
290
currentOptions = newOptions;
@@ -284,23 +303,24 @@ extension LocalVideoTrackExt on LocalVideoTrack {
284
303
return ;
285
304
}
286
305
287
- await restartTrack (
288
- options.copyWith (deviceId: deviceId),
289
- );
306
+ await restartTrack (options.copyWith (deviceId: deviceId));
290
307
291
308
await replaceTrackForMultiCodecSimulcast (mediaStreamTrack);
292
309
}
293
310
294
311
Future <void > replaceTrackForMultiCodecSimulcast (
295
- rtc.MediaStreamTrack newTrack) async {
312
+ rtc.MediaStreamTrack newTrack,
313
+ ) async {
296
314
simulcastCodecs.forEach ((key, simulcastTrack) async {
297
315
await simulcastTrack.sender? .replaceTrack (newTrack);
298
316
simulcastTrack.mediaStreamTrack = mediaStreamTrack;
299
317
});
300
318
}
301
319
302
320
Future <List <String >> setPublishingCodecs (
303
- List <lk_rtc.SubscribedCodec > codecs, LocalTrack track) async {
321
+ List <lk_rtc.SubscribedCodec > codecs,
322
+ LocalTrack track,
323
+ ) async {
304
324
logger.fine ('setPublishingCodecs $codecs ' );
305
325
306
326
// only enable simulcast codec for preference codec setted
@@ -341,7 +361,9 @@ extension LocalVideoTrackExt on LocalVideoTrack {
341
361
}
342
362
343
363
Future <void > updatePublishingLayers (
344
- LocalTrack ? track, List <lk_rtc.SubscribedQuality > layers) async {
364
+ LocalTrack ? track,
365
+ List <lk_rtc.SubscribedQuality > layers,
366
+ ) async {
345
367
logger.fine ('Update publishing layers: $layers ' );
346
368
347
369
if (track? .sender == null ) {
@@ -378,9 +400,10 @@ extension LocalVideoTrackExt on LocalVideoTrack {
378
400
}
379
401
380
402
Future <void > setPublishingLayersForSender (
381
- rtc.RTCRtpSender sender,
382
- List <rtc.RTCRtpEncoding > encodings,
383
- List <lk_rtc.SubscribedQuality > layers) async {
403
+ rtc.RTCRtpSender sender,
404
+ List <rtc.RTCRtpEncoding > encodings,
405
+ List <lk_rtc.SubscribedQuality > layers,
406
+ ) async {
384
407
logger.fine ('Update publishing layers: $layers ' );
385
408
386
409
final params = sender.parameters;
@@ -436,8 +459,9 @@ extension LocalVideoTrackExt on LocalVideoTrack {
436
459
rid = 'q' ;
437
460
}
438
461
var quality = _videoQualityForRid (rid);
439
- var subscribedQuality =
440
- layers.firstWhereOrNull ((q) => q.quality == quality);
462
+ var subscribedQuality = layers.firstWhereOrNull (
463
+ (q) => q.quality == quality,
464
+ );
441
465
if (subscribedQuality == null ) {
442
466
continue ;
443
467
}
@@ -452,11 +476,18 @@ extension LocalVideoTrackExt on LocalVideoTrack {
452
476
// have a workaround of lowering its bitrate and resolution to the min.
453
477
if (kIsWeb && lkBrowser () == BrowserType .firefox) {
454
478
if (subscribedQuality.enabled) {
479
+ final encodingBackup =
480
+ encodingBackups[(sender.senderId, idx)] ?? encoding;
455
481
encoding.scaleResolutionDownBy =
456
- encodings[idx] .scaleResolutionDownBy;
457
- encoding.maxBitrate = encodings[idx] .maxBitrate;
458
- encoding.maxFramerate = encodings[idx].maxBitrate ;
482
+ encodingBackup .scaleResolutionDownBy;
483
+ encoding.maxBitrate = encodingBackup .maxBitrate;
484
+ encoding.maxFramerate = encodingBackup.maxFramerate ;
459
485
} else {
486
+ encodingBackups[(sender.senderId, idx)] = rtc.RTCRtpEncoding (
487
+ scaleResolutionDownBy: encoding.scaleResolutionDownBy,
488
+ maxBitrate: encoding.maxBitrate,
489
+ maxFramerate: encoding.maxFramerate,
490
+ );
460
491
encoding.scaleResolutionDownBy = 4 ;
461
492
encoding.maxBitrate = 10 ;
462
493
encoding.maxFramerate = 2 ;
@@ -481,7 +512,9 @@ extension LocalVideoTrackExt on LocalVideoTrack {
481
512
}
482
513
483
514
SimulcastTrackInfo addSimulcastTrack (
484
- String codec, List <rtc.RTCRtpEncoding > encodings) {
515
+ String codec,
516
+ List <rtc.RTCRtpEncoding > encodings,
517
+ ) {
485
518
if (simulcastCodecs[codec] != null ) {
486
519
throw Exception ('$codec already added' );
487
520
}
0 commit comments