dynamic
initConnection(- Map data
)
Implementation
initConnection(Map<dynamic, dynamic> data) async {
_logger.i('Broadcast option values: $options');
List futures;
MillicastDirectorResponse publisherData;
if (options?['mediaStream'] == null) {
_logger.e('Error while broadcasting. MediaStream required');
throw Exception('MediaStream required');
}
if (isActive() && data['migrate'] == false) {
throw Exception('Broadcast curretly active');
}
try {
publisherData = await tokenGenerator();
} catch (error) {
_logger.e('Error generating token.');
rethrow;
}
if (publisherData.urls.isEmpty && publisherData.jwt.isEmpty) {
_logger.e('Error while broadcasting. Publisher data required');
throw Exception('Publisher data is required');
}
bool recordingAvailable = Jwt.parseJwt(publisherData.jwt)[
utf8.decode(base64.decode('bWlsbGljYXN0'))]['record'];
if (options?['record'] != null && !recordingAvailable) {
_logger.e(
'Error while broadcasting. Record option detected but recording is not available');
throw Exception('Record option detected but recording is not available');
}
var signalingInstance = Signaling({
'streamName': streamName,
'url': '${publisherData.urls[0]}?token=${publisherData.jwt}'
});
var webRTCPeerInstance = data['migrate'] ? PeerConnection() : webRTCPeer;
await webRTCPeerInstance.createRTCPeer(options?['peerConfig']);
// Stop emiting events from the previous instances
if (stopReemitingWebRTCPeerInstanceEvents != null) {
stopReemitingWebRTCPeerInstanceEvents!();
}
if (stopReemitingSignalingInstanceEvents != null) {
stopReemitingSignalingInstanceEvents!();
}
stopReemitingWebRTCPeerInstanceEvents = reemit(
webRTCPeerInstance, this, [webRTCEvents['connectionStateChange']]);
stopReemitingSignalingInstanceEvents =
reemit(signalingInstance, this, [SignalingEvents.broadcastEvent]);
Future<String?> getLocalSDPFuture =
webRTCPeerInstance.getRTCLocalSDP(options: options!);
Future signalingConnectFuture = signalingInstance.connect();
Iterable<Future<dynamic>> iterFuture = [
getLocalSDPFuture,
signalingConnectFuture
];
futures = await Future.wait(iterFuture);
String? localSdp = futures[0];
var publishFuture = signalingInstance.publish(localSdp, options: options);
var setLocalDescriptionFuture = webRTCPeerInstance.peer!
.setLocalDescription(webRTCPeerInstance.sessionDescription!);
iterFuture = [publishFuture, setLocalDescriptionFuture];
futures = await Future.wait(iterFuture);
String remoteSdp = futures[0];
await setLocalDescriptionFuture;
if (!options?['disableVideo'] && (options?['bandwidth'] > 0)) {
remoteSdp = webRTCPeerInstance.updateBandwidthRestriction(
remoteSdp, options?['bandwidth']);
}
await webRTCPeerInstance.setRTCRemoteSDP(remoteSdp);
_logger.i('Broadcasting to streamName: $streamName');
Signaling? oldSignlaling = signaling;
PeerConnection? oldWebRTCPeer = webRTCPeer;
signaling = signalingInstance;
webRTCPeer = webRTCPeerInstance;
setReconnect();
if (data['migrate']) {
webRTCPeer.on(webRTCEvents['connectionStateChange'], webRTCPeer,
(ev, context) async {
if (ev.eventData ==
RTCIceConnectionState.RTCIceConnectionStateConnected) {
Timer(const Duration(milliseconds: 1000), () {
oldSignlaling?.close();
oldWebRTCPeer?.closeRTCPeer();
oldSignlaling = null;
oldWebRTCPeer = null;
_logger.i('Current connection migrated');
});
} else if ([
RTCIceConnectionState.RTCIceConnectionStateClosed,
RTCIceConnectionState.RTCIceConnectionStateFailed,
RTCIceConnectionState.RTCIceConnectionStateDisconnected
].contains(ev.eventData)) {
oldSignlaling?.close();
oldWebRTCPeer?.closeRTCPeer();
oldSignlaling = null;
oldWebRTCPeer = null;
}
});
}
}