setPublishingLayersForSender method
Implementation
Future<void> setPublishingLayersForSender(
rtc.RTCRtpSender sender,
List<rtc.RTCRtpEncoding> encodings,
List<lk_rtc.SubscribedQuality> layers, {
bool isSVC = false,
}) async {
logger.fine('Update publishing layers: $layers');
final params = sender.parameters;
var hasChanged = false;
// NOTE: closable spatial layer is disabled due to video blur / frozen issues
// with Chrome 113+ and LiveKit SFU PLI handling. See JS SDK LocalVideoTrack.ts:529-568.
// For SVC codecs, all layers are kept enabled and the SFU handles layer selection.
if (isSVC) {
final hasEnabledEncoding = layers.any((q) => q.enabled);
if (hasEnabledEncoding) {
for (var q in layers) {
q.enabled = true;
}
}
}
// simulcast dynacast encodings
var idx = 0;
for (var encoding in encodings) {
var rid = encoding.rid ?? '';
if (rid == '') {
rid = 'q';
}
final quality = _videoQualityForRid(rid);
final subscribedQuality = layers.firstWhereOrNull(
(q) => q.quality == quality,
);
if (subscribedQuality == null) {
continue;
}
if (encoding.active != subscribedQuality.enabled) {
hasChanged = true;
encoding.active = subscribedQuality.enabled;
logger.fine(
'setting layer ${subscribedQuality.quality} to ${encoding.active ? 'enabled' : 'disabled'}',
);
// FireFox does not support setting encoding.active to false, so we
// have a workaround of lowering its bitrate and resolution to the min.
if (kIsWeb && lkBrowser() == BrowserType.firefox) {
if (subscribedQuality.enabled) {
final encodingBackup = encodingBackups[(sender.senderId, idx)] ?? encoding;
encoding.scaleResolutionDownBy = encodingBackup.scaleResolutionDownBy;
encoding.maxBitrate = encodingBackup.maxBitrate;
encoding.maxFramerate = encodingBackup.maxFramerate;
} else {
encodingBackups[(sender.senderId, idx)] = rtc.RTCRtpEncoding(
scaleResolutionDownBy: encoding.scaleResolutionDownBy,
maxBitrate: encoding.maxBitrate,
maxFramerate: encoding.maxFramerate,
);
encoding.scaleResolutionDownBy = 4;
encoding.maxBitrate = 10;
encoding.maxFramerate = 2;
}
}
}
idx++;
}
if (hasChanged) {
params.encodings = encodings;
try {
final result = await sender.setParameters(params);
if (result == false) {
logger.warning('Failed to update sender parameters');
}
} catch (e) {
logger.warning('Failed to update sender parameters $e');
}
}
}