@@ -229,23 +229,24 @@ class Utils {
229229 static List <VideoParameters > _computeDefaultScreenShareSimulcastParams ({
230230 required VideoParameters original,
231231 }) {
232- final layers = [rtc.RTCRtpEncoding (scaleResolutionDownBy: 2 , maxFramerate: 3 )];
233- return layers.map ((e) {
234- final scale = e.scaleResolutionDownBy ?? 1 ;
235- final fps = e.maxFramerate ?? 3 ;
232+ final originalEncoding = original.encoding! ;
233+ const scale = 2.0 ;
236234
237- return VideoParameters (
235+ return [
236+ VideoParameters (
238237 dimensions:
239238 VideoDimensions ((original.dimensions.width / scale).floor (), (original.dimensions.height / scale).floor ()),
240239 encoding: VideoEncoding (
241240 maxBitrate: math.max (
242241 150 * 1000 ,
243- (original.encoding ! . maxBitrate / ( math.pow (scale, 2 ) * (original.encoding ! .maxFramerate / fps) )).floor (),
242+ (originalEncoding. maxBitrate / math.pow (scale, 2 )).floor (),
244243 ),
245- maxFramerate: fps,
244+ maxFramerate: originalEncoding.maxFramerate,
245+ bitratePriority: originalEncoding.bitratePriority,
246+ networkPriority: originalEncoding.networkPriority,
246247 ),
247- );
248- }). toList () ;
248+ ),
249+ ] ;
249250 }
250251
251252 static List <VideoParameters > _computeDefaultSimulcastParams ({
@@ -311,18 +312,83 @@ class Utils {
311312 if (i >= videoRids.length) {
312313 return ;
313314 }
314- final size = dimensions.min ();
315+ final size = dimensions.max ();
315316 final rid = videoRids[i];
316317 if (e.encoding != null ) {
317318 result.add (e.encoding! .toRTCRtpEncoding (
318319 rid: rid,
319- scaleResolutionDownBy: math.max (1 , size / e.dimensions.min ()),
320+ scaleResolutionDownBy: math.max (1 , size / e.dimensions.max ()),
320321 ));
321322 }
322323 });
323324 return result;
324325 }
325326
327+ @internal
328+ static List <VideoParameters > computeSimulcastPresets ({
329+ required VideoDimensions dimensions,
330+ required VideoParameters original,
331+ required List <VideoParameters > requestedPresets,
332+ required bool isScreenShare,
333+ }) {
334+ final params = (requestedPresets.isNotEmpty
335+ ? requestedPresets
336+ : _computeDefaultSimulcastParams (isScreenShare: isScreenShare, original: original))
337+ .sorted ();
338+
339+ if (params.isEmpty) {
340+ return [original];
341+ }
342+ final lowPreset = params.first;
343+ final midPreset = params.length > 1 ? params[1 ] : null ;
344+
345+ final size = dimensions.max ();
346+ if (size >= 960 && midPreset != null ) {
347+ return [
348+ _clampSimulcastPreset (lowPreset, to: original, inDimensions: dimensions),
349+ _clampSimulcastPreset (midPreset, to: original, inDimensions: dimensions),
350+ original,
351+ ];
352+ }
353+ if (size >= 480 ) {
354+ return [
355+ _clampSimulcastPreset (lowPreset, to: original, inDimensions: dimensions),
356+ original,
357+ ];
358+ }
359+ return [original];
360+ }
361+
362+ static VideoParameters _clampSimulcastPreset (
363+ VideoParameters preset, {
364+ required VideoParameters to,
365+ required VideoDimensions inDimensions,
366+ }) {
367+ final presetEncoding = preset.encoding;
368+ final topEncoding = to.encoding;
369+ if (presetEncoding == null || topEncoding == null ) {
370+ return preset;
371+ }
372+
373+ final rawScaleDownBy = inDimensions.max () / preset.dimensions.max ();
374+ final clampedFramerate = math.min (presetEncoding.maxFramerate, topEncoding.maxFramerate);
375+ final clampedBitrate =
376+ rawScaleDownBy <= 1.0 ? math.min (presetEncoding.maxBitrate, topEncoding.maxBitrate) : presetEncoding.maxBitrate;
377+
378+ if (clampedFramerate == presetEncoding.maxFramerate && clampedBitrate == presetEncoding.maxBitrate) {
379+ return preset;
380+ }
381+
382+ return VideoParameters (
383+ description: preset.description,
384+ dimensions: preset.dimensions,
385+ encoding: presetEncoding.copyWith (
386+ maxFramerate: clampedFramerate,
387+ maxBitrate: clampedBitrate,
388+ ),
389+ );
390+ }
391+
326392 @internal
327393 static FutureOr <String > getNetworkType () async {
328394 if (! kIsWeb && lkPlatformIsTest ()) {
@@ -450,25 +516,12 @@ class Utils {
450516 // compute simulcast encodings
451517 final userParams = isScreenShare ? options.screenShareSimulcastLayers : options.videoSimulcastLayers;
452518
453- final params = (userParams.isNotEmpty
454- ? userParams
455- : _computeDefaultSimulcastParams (isScreenShare: isScreenShare, original: original))
456- .sorted ();
457-
458- final VideoParameters lowPreset = params.first;
459- VideoParameters ? midPreset;
460- if (params.length > 1 ) {
461- midPreset = params[1 ];
462- }
463-
464- final size = dimensions.max ();
465- List <VideoParameters > computedParams = [original];
466-
467- if (size >= 960 && midPreset != null ) {
468- computedParams = [lowPreset, midPreset, original];
469- } else if (size >= 480 ) {
470- computedParams = [lowPreset, original];
471- }
519+ final computedParams = computeSimulcastPresets (
520+ dimensions: dimensions,
521+ original: original,
522+ requestedPresets: userParams,
523+ isScreenShare: isScreenShare,
524+ );
472525
473526 return encodingsFromPresets (
474527 dimensions,
0 commit comments