8000 Add Unified-Plan for Flutter Web, close #380. · next-coder/flutter-webrtc@b581804 · GitHub
[go: up one dir, main page]

Skip to content
8000

Commit b581804

Browse files
committed
Add Unified-Plan for Flutter Web, close flutter-webrtc#380.
* [WIP] Add Unified-Plan for Flutter Web. * more. * update. * update. * update. * Add video frame mirror support for web. * Fix compile error for Android. * Fix MediaRecorder and captureFrame for web. * update. * update. * Bump dart-webrtc to v0.2.0. * Add RTCTrackEvent support for web. * Fix getStats and remove old API. * Support simulcast for web.
1 parent 8cf0cd2 commit b581804

34 files changed

+714
-428
lines changed

android/src/main/java/com/cloudwebrtc/webrtc/MethodCallHandlerImpl.java

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -556,19 +556,6 @@ public void onMethodCall(MethodCall call, @NonNull Result notSafeResult) {
556556
}
557557
break;
558558
}
559-
case "createSender": {
560-
String peerConnectionId = call.argument("peerConnectionId");
561-
String kind = call.argument("kind");
562-
String streamId = call.argument("streamId");
563-
createSender(peerConnectionId, kind, streamId, result);
564-
break;
565-
}
566-
case "closeSender": {
567-
String peerConnectionId = call.argument("peerConnectionId");
568-
String senderId = call.argument("senderId");
569-
stopSender(peerConnectionId, senderId, result);
570-
break;
571-
}
572559
case "addTrack": {
573560
String peerConnectionId = call.argument("peerConnectionId");
574561
String trackId = call.argument("trackId");
@@ -1493,24 +1480,6 @@ public void setActivity(Activity activity) {
14931480
this.activity = activity;
14941481
}
14951482

1496-
public void createSender(String peerConnectionId, String kind, String streamId, Result result) {
1497-
PeerConnectionObserver pco = mPeerConnectionObservers.get(peerConnectionId);
1498-
if (pco == null || pco.getPeerConnection() == null) {
1499-
resultError("createSender", "peerConnection is null", result);
1500-
} else {
1501-
pco.createSender(kind, streamId, result);
1502-
}
1503-
}
1504-
1505-
public void stopSender(String peerConnectionId, String senderId, Result result) {
1506-
PeerConnectionObserver pco = mPeerConnectionObservers.get(peerConnectionId);
1507-
if (pco == null || pco.getPeerConnection() == null) {
1508-
resultError("stopSender", "peerConnection is null", result);
1509-
} else {
1510-
pco.closeSender(senderId, result);
1511-
}
1512-
}
1513-
15141483
public void addTrack(String peerConnectionId, String trackId, List<String> streamIds, Result result){
15151484
PeerConnectionObserver pco = mPeerConnectionObservers.get(peerConnectionId);
15161485
MediaStreamTrack track = localTracks.get(trackId);

android/src/main/java/com/cloudwebrtc/webrtc/PeerConnectionObserver.java

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -660,7 +660,7 @@ private RtpTransceiver.RtpTransceiverInit mapToRtpTransceiverInit(Map<String, Ob
660660
RtpTransceiver.RtpTransceiverInit init = null;
661661

662662
if(streamIds == null) {
663-
streamIds = new List<String>();
663+
streamIds = new ArrayList<String>();
664664
}
665665

666666
if(direction == null) {
@@ -867,19 +867,6 @@ Map<String, Object> candidateToMap(IceCandidate candidate) {
867867
return candidateParams.toMap();
868868
}
869869

870-
public void createSender(String kind, String streamId, Result result){
871-
RtpSender sender = peerConnection.createSender(kind, streamId);
872-
result.success(rtpSenderToMap(sender));
873-
}
874-
875-
public void closeSender(String senderId, Result result) {
876-
RtpSender sender = getRtpSenderById(senderId);
877-
sender.dispose();
878-
Map<String, Object> params = new HashMap<>();
879-
params.put("result", true);
880-
result.success(params);
881-
}
882-
883870
public void addTrack(MediaStreamTrack track, List<String> streamIds, Result result){
884871
RtpSender sender = peerConnection.addTrack(track, streamIds);
885872
result.success(rtpSenderToMap(sender));

common/darwin/Classes/FlutterWebRTCPlugin.m

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -599,47 +599,6 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult) result
599599
message:[NSString stringWithFormat:@"Error: peerConnection not found!"]
600600
details:nil]);
601601
}
602-
} else if ([@"createSender" isEqualToString:call.method]){
603-
NSDictionary* argsMap = call.arguments;
604-
NSString* peerConnectionId = argsMap[@"peerConnectionId"];
605-
NSString* kind = argsMap[@"kind"];
606-
NSString* streamId = argsMap[@"streamId"];
607-
RTCPeerConnection *peerConnection = self.peerConnections[peerConnectionId];
608-
if(peerConnection == nil) {
609-
result([FlutterError errorWithCode:[NSString stringWithFormat:@"%@Failed",call.method]
610-
message:[NSString stringWithFormat:@"Error: peerConnection not found!"]
611-
details:nil]);
612-
return;
613-
}
614-
RTCRtpSender* sender = [peerConnection senderWithKind:kind streamId:streamId];
615-
result([self rtpSenderToMap:sender]);
616-
} else if ([@"closeSender" isEqualToString:call.method]){
617-
NSDictionary* argsMap = call.arguments;
618-
NSString* peerConnectionId = argsMap[@"peerConnectionId"];
619-
NSString* senderId = argsMap[@"senderId"];
620-
RTCPeerConnection *peerConnection = self.peerConnections[peerConnectionId];
621-
if(peerConnection == nil) {
622-
result([FlutterError errorWithCode:[NSString stringWithFormat:@"%@Failed",call.method]
623-
message:[NSString stringWithFormat:@"Error: peerConnection not found!"]
624-
details:nil]);
625-
return;
626-
}
627-
RTCRtpSender *sender = [self getRtpSenderById:peerConnection Id:senderId];
628-
if(sender == nil) {
629-
result([FlutterError errorWithCode:[NSString stringWithFormat:@"%@Failed",call.method]
630-
message:[NSString stringWithFormat:@"Error: sender not found!"]
631-
details:nil]);
632-
return;
633-
}
634-
635-
if(![peerConnection removeTrack:sender]) {
636-
result([FlutterError errorWithCode:[NSString stringWithFormat:@"%@Failed",call.method]
637-
message:[NSString stringWithFormat:@"Error: can't close sender!"]
638-
details:nil]);
639-
return;
640-
}
641-
642-
result(nil);
643602
} else if ([@"addTrack" isEqualToString:call.method]){
644603
NSDictionary* argsMap = call.arguments;
645604
NSString* peerConnectionId = argsMap[@"peerConnectionId"];

example/lib/main.dart

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import 'dart:core';
2-
import 'dart:io';
32

43
import 'package:flutter/foundation.dart'
54
show debugDefaultTargetPlatformOverride;
@@ -17,33 +16,33 @@ import 'src/route_item.dart';
1716
void main() {
1817
if (WebRTC.platformIsDesktop) {
1918
debugDefaultTargetPlatformOverride = TargetPlatform.fuchsia;
20-
} else if(Platform.isAndroid) {
19+
} else if (WebRTC.platformIsAndroid) {
2120
WidgetsFlutterBinding.ensureInitialized();
2221
startForegroundService();
2322
}
2423
runApp(MyApp());
2524
}
2625

27-
startForegroundService() async {
26+
Future<bool> startForegroundService() async {
2827
await FlutterForegroundPlugin.setServiceMethodInterval(seconds: 5);
2928
await FlutterForegroundPlugin.setServiceMethod(globalForegroundService);
3029
await FlutterForegroundPlugin.startForegroundService(
3130
holdWakeLock: false,
3231
onStarted: () {
33-
print("Foreground on Started");
32+
print('Foreground on Started');
3433
},
3534
onStopped: () {
36-
print("Foreground on Stopped");
35+
print('Foreground on Stopped');
3736
},
38-
title: "Tcamera",
39-
content: "Tcamera sharing your screen.",
40-
iconName: "ic_stat_mobile_screen_share",
37+
title: 'Tcamera',
38+
content: 'Tcamera sharing your screen.',
39+
iconName: 'ic_stat_mobile_screen_share',
4140
);
4241
return true;
4342
}
4443

4544
void globalForegroundService() {
46-
debugPrint("current datetime is ${DateTime.now()}");
45+
debugPrint('current datetime is ${DateTime.now()}');
4746
}
4847

4948
class MyApp extends StatefulWidget {

example/lib/src/get_display_media_sample.dart

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class _GetDisplayMediaSampleState extends State<GetDisplayMediaSample> {
3131
void deactivate() {
3232
super.deactivate();
3333
if (_inCalling) {
34-
_hangUp();
34+
_stop();
3535
}
3636
if (_timer != null) _timer.cancel();
3737
_localRenderer.dispose();
@@ -72,13 +72,20 @@ class _GetDisplayMediaSampleState extends State<GetDisplayMediaSample> {
7272
_timer = Timer.periodic(Duration(milliseconds: 100), handleTimer);
7373
}
7474

75-
void _hangUp() async {
75+
Future<void> _stop() async {
7676
try {
77-
await _localStream.dispose();
77+
if (_localStream != null) {
78+
await _localStream.dispose();
79+
_localStream = null;
80+
}
7881
_localRenderer.srcObject = null;
7982
} catch (e) {
8083
print(e.toString());
8184
}
85+
}
86+
87+
Future<void> _hangUp() async {
88+
await _stop();
8289
setState(() {
8390
_inCalling = false;
8491
});

example/lib/src/get_user_media_sample_web.dart

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class _GetUserMediaSampleState extends State<GetUserMediaSample> {
3838
void deactivate() {
3939
super.deactivate();
4040
if (_inCalling) {
41-
_hangUp();
41+
_stop();
4242
}
4343
_localRenderer.dispose();
4444
}
@@ -75,13 +75,20 @@ class _GetUserMediaSampleState extends State<GetUserMediaSample> {
7575
});
7676
}
7777

78-
void _hangUp() async {
78+
Future<void> _stop() async {
7979
try {
80-
await _localStream.dispose();
80+
if (_localStream != null) {
81+
await _localStream.dispose();
82+
_localStream = null;
83+
}
8184
_localRenderer.srcObject = null;
8285
} catch (e) {
8386
print(e.toString());
8487
}
88+
}
89+
90+
void _hangUp() async {
91+
await _stop();
8592
setState(() {
8693
_inCalling = false;
8794
});

example/lib/src/loopback_sample.dart

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class _MyAppState extends State<LoopBackSample> {
1717
final _localRenderer = RTCVideoRenderer();
1818
final _remoteRenderer = RTCVideoRenderer();
1919
bool _inCalling = false;
20-
//Timer _timer;
20+
Timer _timer;
2121

2222
@override
2323
void initState() {
@@ -84,6 +84,10 @@ class _MyAppState extends State<LoopBackSample> {
8484
}
8585

8686
void _onCandidate(RTCIceCandidate candidate) {
87+
if (candidate == null) {
88+
print('onCandidate: complete!');
89+
return;
90+
}
8791
print('onCandidate: ' + candidate.candidate);
8892
_peerConnection.addCandidate(candidate);
8993
}
@@ -161,14 +165,6 @@ class _MyAppState extends State<LoopBackSample> {
161165

162166
/* old API
163167
await _peerConnection.addStream(_localStream);
164-
// or
165-
var rtpSender =
166-
await _peerConnection.createSender('audio', _localStream.id);
167-
await rtpSender.setTrack(_localStream.getAudioTracks()[0]);
168-
rtpSender = await _peerConnection.createSender('video', _localStream.id);
169-
await rtpSender.setTrack(_localStream.getVideoTracks()[0]);
170-
*/
171-
/*
172168
// Unified-Plan
173169
_localStream.getTracks().forEach((track) {
174170
_peerConnection.addTrack(track, [_localStream]);
@@ -247,7 +243,7 @@ class _MyAppState extends State<LoopBackSample> {
247243
}
248244
if (!mounted) return;
249245

250-
//_timer = Timer.periodic(Duration(seconds: 1), handleStatsReport);
246+
_timer = Timer.periodic(Duration(seconds: 1), handleStatsReport);
251247

252248
setState(() {
253249
_inCalling = true;
@@ -267,7 +263,7 @@ class _MyAppState extends State<LoopBackSample> {
267263
setState(() {
268264
_inCalling = false;
269265
});
270-
//_timer.cancel();
266+
_timer.cancel();
271267
}
272268

273269
void _sendDtmf() async {

lib/src/interface/mediadevices.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
import 'media_stream.dart';
22

3+
class MediaStreamConstraints {
4+
MediaStreamConstraints({this.audio, this.video});
5+
dynamic audio;
6+
dynamic video;
7+
}
8+
39
abstract class MediaDevices {
410
Future<MediaStream> getUserMedia(Map<String, dynamic> mediaConstraints);
511
Future<MediaStream> getDisplayMedia(Map<String, dynamic> mediaConstraints);
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
abstract class RTCOfferOptions {
2+
RTCOfferOptions({
3+
bool iceRestart,
4+
bool offerToReceiveAudio,
5+
bool offerToReceiveVideo,
6+
bool voiceActivityDetection,
7+
});
8+
bool get iceRestart;
9+
bool get offerToReceiveAudio;
10+
bool get offerToReceiveVideo;
11+
bool get voiceActivityDetection;
12+
}
13+
14+
abstract class RTCAnswerOptions {
15+
RTCAnswerOptions({bool voiceActivityDetection});
16+
bool get voiceActivityDetection; 741A
17+
}
18+
19+
abstract class RTCConfiguration {
20+
RTCConfiguration({
21+
List<RTCIceServer> iceServers,
22+
String rtcpMuxPolicy,
23+
String iceTransportPolicy,
24+
String bundlePolicy,
25+
String peerIdentity,
26+
int iceCandidatePoolSize,
27+
});
28+
List<RTCIceServer> get iceServers;
29+
30+
///Optional: 'negotiate' or 'require'
31+
String get rtcpMuxPolicy;
32+
33+
///Optional: 'relay' or 'all'
34+
String get iceTransportPolicy;
35+
36+
/// A DOMString which specifies the target peer identity for the
37+
/// RTCPeerConnection. If this value is set (it defaults to null),
38+
/// the RTCPeerConnection will not connect to a remote peer unless
39+
/// it can successfully authenticate with the given name.
40+
String get peerIdentity;
41+
42+
int get iceCandidatePoolSize;
43+
44+
///Optional: 'balanced' | 'max-compat' | 'max-bundle'
45+
String get bundlePolicy;
46+
}
47+
48+
abstract class RTCIceServer {
49+
RTCIceServer({String urls, String username, String credential});
50+
// String or List<String>
51+
dynamic get urls;
52+
String get username;
53+
String get credential;
54+
}

lib/src/interface/rtc_peerconnection.dart

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -99,15 +99,10 @@ abstract class RTCPeerConnection {
9999

100100
List<RTCRtpTransceiver> get transceivers;
101101

102-
Future<RTCRtpSender> createSender(String kind, String streamId);
103-
104-
Future<RTCRtpSender> addTrack(MediaStreamTrack track,
105-
[List<MediaStream> streams]);
102+
Future<RTCRtpSender> addTrack(MediaStreamTrack track, [MediaStream stream]);
106103

107104
Future<bool> removeTrack(RTCRtpSender sender);
108105

109-
Future<bool> closeSender(RTCRtpSender sender);
110-
111106
/// 'audio|video', { 'direction': 'recvonly|sendonly|sendrecv' }
112107
Future<RTCRtpTransceiver> addTransceiver(
113108
{MediaStreamTrack track,

lib/src/interface/rtc_rtp_receiver.dart

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import 'dart:async';
2-
31
import 'enums.dart';
42
import 'media_stream_track.dart';
53
import 'rtc_rtp_parameters.dart';
@@ -21,6 +19,4 @@ abstract class RTCRtpReceiver {
2119
MediaStreamTrack get track;
2220

2321
String get receiverId;
24-
25-
Future<void> dispose();
2622
}

lib/src/interface/rtc_stats_report.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
class StatsReport {
22
StatsReport(this.id, this.type, this.timestamp, this.values);
3+
factory StatsReport.fromMap(Map<String, dynamic> map) =>
4+
StatsReport(map['id'], map['type'], map['timestamp'], map);
35
final String id;
46
final String type;
57
final double timestamp;

lib/src/media_recorder.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,6 @@ class MediaRecorder extends _interface.MediaRecorder {
2222
Function(dynamic blob, bool isLastOne) onDataChunk,
2323
String mimeType,
2424
}) =>
25-
_delegate.startWeb(stream, onDataChunk: onDataChunk, mimeType: mimeType);
25+
_delegate.startWeb(stream,
26+
onDataChunk: onDataChunk, mimeType: mimeType ?? 'video/webm');
2627
}

0 commit comments

Comments
 (0)
0