Merge branch 'voip/improve-ice-connect-speed' into 'main'
Improve ice connection speed. See merge request famedly/company/frontend/famedlysdk!1136
This commit is contained in:
commit
ddb7cf8e30
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:core';
|
import 'dart:core';
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:webrtc_interface/webrtc_interface.dart';
|
import 'package:webrtc_interface/webrtc_interface.dart';
|
||||||
|
|
||||||
|
|
@ -327,6 +328,7 @@ class CallSession {
|
||||||
CallSession? successor;
|
CallSession? successor;
|
||||||
bool waitForLocalAVStream = false;
|
bool waitForLocalAVStream = false;
|
||||||
int toDeviceSeq = 0;
|
int toDeviceSeq = 0;
|
||||||
|
int candidateSendTries = 0;
|
||||||
|
|
||||||
final CachedStreamController<CallSession> onCallStreamsChanged =
|
final CachedStreamController<CallSession> onCallStreamsChanged =
|
||||||
CachedStreamController();
|
CachedStreamController();
|
||||||
|
|
@ -1084,23 +1086,36 @@ class CallSession {
|
||||||
pc!.onRenegotiationNeeded = onNegotiationNeeded;
|
pc!.onRenegotiationNeeded = onNegotiationNeeded;
|
||||||
|
|
||||||
pc!.onIceCandidate = (RTCIceCandidate candidate) async {
|
pc!.onIceCandidate = (RTCIceCandidate candidate) async {
|
||||||
|
if (callHasEnded) return;
|
||||||
//Logs().v('[VOIP] onIceCandidate => ${candidate.toMap().toString()}');
|
//Logs().v('[VOIP] onIceCandidate => ${candidate.toMap().toString()}');
|
||||||
localCandidates.add(candidate);
|
localCandidates.add(candidate);
|
||||||
|
|
||||||
|
if (state == CallState.kRinging || !inviteOrAnswerSent) return;
|
||||||
|
|
||||||
|
// MSC2746 recommends these values (can be quite long when calling because the
|
||||||
|
// callee will need a while to answer the call)
|
||||||
|
final delay = direction == CallDirection.kIncoming ? 500 : 2000;
|
||||||
|
if (candidateSendTries == 0) {
|
||||||
|
Timer(Duration(milliseconds: delay), () {
|
||||||
|
_sendCandidateQueue();
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pc!.onIceGatheringState = (RTCIceGatheringState state) async {
|
pc!.onIceGatheringState = (RTCIceGatheringState state) async {
|
||||||
Logs().v('[VOIP] IceGatheringState => ${state.toString()}');
|
Logs().v('[VOIP] IceGatheringState => ${state.toString()}');
|
||||||
if (state == RTCIceGatheringState.RTCIceGatheringStateGathering) {
|
if (state == RTCIceGatheringState.RTCIceGatheringStateGathering) {
|
||||||
Timer(Duration(seconds: 3), () async {
|
Timer(Duration(seconds: 3), () async {
|
||||||
if (!iceGatheringFinished) {
|
if (!iceGatheringFinished) {
|
||||||
iceGatheringFinished = true;
|
iceGatheringFinished = true;
|
||||||
await _candidateReady();
|
await _sendCandidateQueue();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (state == RTCIceGatheringState.RTCIceGatheringStateComplete) {
|
if (state == RTCIceGatheringState.RTCIceGatheringStateComplete) {
|
||||||
if (!iceGatheringFinished) {
|
if (!iceGatheringFinished) {
|
||||||
iceGatheringFinished = true;
|
iceGatheringFinished = true;
|
||||||
await _candidateReady();
|
await _sendCandidateQueue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -1277,22 +1292,43 @@ class CallSession {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _candidateReady() async {
|
Future<void> _sendCandidateQueue() async {
|
||||||
|
if (callHasEnded) return;
|
||||||
/*
|
/*
|
||||||
Currently, trickle-ice is not supported, so it will take a
|
Currently, trickle-ice is not supported, so it will take a
|
||||||
long time to wait to collect all the canidates, set the
|
long time to wait to collect all the canidates, set the
|
||||||
timeout for collection canidates to speed up the connection.
|
timeout for collection canidates to speed up the connection.
|
||||||
*/
|
*/
|
||||||
|
final candidatesQueue = localCandidates;
|
||||||
try {
|
try {
|
||||||
final candidates = <Map<String, dynamic>>[];
|
if (candidatesQueue.isNotEmpty) {
|
||||||
localCandidates.forEach((element) {
|
final candidates = <Map<String, dynamic>>[];
|
||||||
candidates.add(element.toMap());
|
candidatesQueue.forEach((element) {
|
||||||
});
|
candidates.add(element.toMap());
|
||||||
final res =
|
});
|
||||||
await sendCallCandidates(opts.room, callId, localPartyId, candidates);
|
localCandidates = [];
|
||||||
Logs().v('[VOIP] sendCallCandidates res => $res');
|
final res = await sendCallCandidates(
|
||||||
|
opts.room, callId, localPartyId, candidates);
|
||||||
|
Logs().v('[VOIP] sendCallCandidates res => $res');
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Logs().v('[VOIP] sendCallCandidates e => ${e.toString()}');
|
Logs().v('[VOIP] sendCallCandidates e => ${e.toString()}');
|
||||||
|
candidateSendTries++;
|
||||||
|
localCandidates = candidatesQueue;
|
||||||
|
|
||||||
|
if (candidateSendTries > 5) {
|
||||||
|
Logs().d(
|
||||||
|
'Failed to send candidates on attempt $candidateSendTries Giving up on this call.');
|
||||||
|
lastError =
|
||||||
|
CallError(CallErrorCode.SignallingFailed, 'Signalling failed', e);
|
||||||
|
await hangup(CallErrorCode.SignallingFailed, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final delay = 500 * pow(2, candidateSendTries);
|
||||||
|
Timer(Duration(milliseconds: delay as int), () {
|
||||||
|
_sendCandidateQueue();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue