@@ -26,6 +26,11 @@ enum CallState {
2626 CallStateBye ,
2727}
2828
29+ enum VideoSource {
30+ Camera ,
31+ Screen ,
32+ }
33+
2934class Session {
3035 Session ({required this .sid, required this .pid});
3136 String pid;
@@ -49,6 +54,8 @@ class Signaling {
4954 Map <String , Session > _sessions = {};
5055 MediaStream ? _localStream;
5156 List <MediaStream > _remoteStreams = < MediaStream > [];
57+ List <RTCRtpSender > _senders = < RTCRtpSender > [];
58+ VideoSource _videoSource = VideoSource .Camera ;
5259
5360 Function (SignalingState state)? onSignalingStateChange;
5461 Function (Session session, CallState state)? onCallStateChange;
@@ -60,8 +67,7 @@ class Signaling {
6067 onDataChannelMessage;
6168 Function (Session session, RTCDataChannel dc)? onDataChannel;
6269
63- String get sdpSemantics =>
64- WebRTC .platformIsWindows ? 'plan-b' : 'unified-plan' ;
70+ String get sdpSemantics => 'unified-plan' ;
6571
6672 Map <String , dynamic > _iceServers = {
6773 'iceServers' : [
@@ -99,7 +105,29 @@ class Signaling {
99105
100106 void switchCamera () {
101107 if (_localStream != null ) {
102- Helper .switchCamera (_localStream! .getVideoTracks ()[0 ]);
108+ if (_videoSource != VideoSource .Camera ) {
109+ _senders.forEach ((sender) {
110+ if (sender.track! .kind == 'video' ) {
111+ sender.replaceTrack (_localStream! .getVideoTracks ()[0 ]);
112+ }
113+ });
114+ _videoSource = VideoSource .Camera ;
115+ onLocalStream? .call (_localStream! );
116+ } else {
117+ Helper .switchCamera (_localStream! .getVideoTracks ()[0 ]);
118+ }
119+ }
120+ }
121+
122+ void switchToScreenSharing (MediaStream stream) {
123+ if (_localStream != null && _videoSource != VideoSource .Screen ) {
124+ _senders.forEach ((sender) {
125+ if (sender.track! .kind == 'video' ) {
126+ sender.replaceTrack (stream.getVideoTracks ()[0 ]);
127+ }
128+ });
129+ onLocalStream? .call (stream);
130+ _videoSource = VideoSource .Screen ;
103131 }
104132 }
105133
@@ -193,7 +221,6 @@ class Signaling {
193221 newSession.remoteCandidates.clear ();
194222 }
195223 onCallStateChange? .call (newSession, CallState .CallStateNew );
196-
197224 onCallStateChange? .call (newSession, CallState .CallStateRinging );
198225 }
199226 break ;
@@ -381,8 +408,8 @@ class Signaling {
381408 onAddRemoteStream? .call (newSession, event.streams[0 ]);
382409 }
383410 };
384- _localStream! .getTracks ().forEach ((track) {
385- pc.addTrack (track, _localStream! );
411+ _localStream! .getTracks ().forEach ((track) async {
412+ _senders. add ( await pc.addTrack (track, _localStream! ) );
386413 });
387414 break ;
388415 }
@@ -492,7 +519,7 @@ class Signaling {
492519 try {
493520 RTCSessionDescription s =
494521 await session.pc! .createOffer (media == 'data' ? _dcConstraints : {});
495- await session.pc! .setLocalDescription (s );
522+ await session.pc! .setLocalDescription (_fixSdp (s) );
496523 _send ('offer' , {
497524 'to' : session.pid,
498525 'from' : _selfId,
@@ -505,11 +532,18 @@ class Signaling {
505532 }
506533 }
507534
535+ RTCSessionDescription _fixSdp (RTCSessionDescription s) {
536+ var sdp = s.sdp;
537+ s.sdp =
538+ sdp! .replaceAll ('profile-level-id=640c1f' , 'profile-level-id=42e032' );
539+ return s;
540+ }
541+
508542 Future <void > _createAnswer (Session session, String media) async {
509543 try {
510544 RTCSessionDescription s =
511545 await session.pc! .createAnswer (media == 'data' ? _dcConstraints : {});
512- await session.pc! .setLocalDescription (s );
546+ await session.pc! .setLocalDescription (_fixSdp (s) );
513547 _send ('answer' , {
514548 'to' : session.pid,
515549 'from' : _selfId,
@@ -565,5 +599,7 @@ class Signaling {
565599
566600 await session.pc? .close ();
567601 await session.dc? .close ();
602+ _senders.clear ();
603+ _videoSource = VideoSource .Camera ;
568604 }
569605}
0 commit comments