@@ -19,38 +19,69 @@ class MyApp extends StatefulWidget {
19
19
class _MyAppState extends State <MyApp > {
20
20
MediaStream _localStream;
21
21
RTCPeerConnection _peerConnection;
22
- final _localVideoView = new RTCVideoViewController ();
23
- final _remoteVideoView = new RTCVideoViewController ();
24
- final _width = 200.0 ;
25
- final _height = 200.0 ;
22
+ var _width = 240.0 ;
23
+ var _height = 180.0 ;
24
+ var _rotation = 0 ;
25
+ final _localVideoRenderer = new RTCVideoRenderer ();
26
+ final _remoteVideoRenderer = new RTCVideoRenderer ();
26
27
27
28
@override
28
29
initState () {
29
30
super .initState ();
30
31
initPlatformState ();
32
+ _localVideoRenderer.onVideoRotationChange = _onVideoRotationChange;
31
33
}
32
34
33
- _onAddStream ( MediaStream stream )
35
+ _onVideoRotationChange ( int textureId, int rotation )
34
36
{
35
- _remoteVideoView.srcObject = stream;
37
+ setState ((){
38
+ _rotation = rotation;
39
+ });
36
40
}
37
41
38
- _onRemoveStream (MediaStream stream){
39
- _remoteVideoView.srcObject = null ;
42
+ _onVideoSizeChange (int textureId, double width, double height){
43
+
44
+ }
45
+
46
+ _onSignalingState (RTCSignalingState state) {
47
+ print (state);
48
+ }
49
+
50
+ _onIceGatheringState (RTCIceGatheringState state) {
51
+ print (state);
52
+ }
53
+
54
+ _onIceConnectionState (RTCIceConnectionState state) {
55
+ print (state);
56
+ }
57
+
58
+ _onAddStream (MediaStream stream) {
59
+ print ('addStream: ' + stream.id);
60
+ _remoteVideoRenderer.srcObject = stream;
40
61
}
41
62
42
- _onCandidate (RTCIceCandidate candidate){
63
+ _onRemoveStream (MediaStream stream) {
64
+ _remoteVideoRenderer.srcObject = null ;
65
+ }
66
+
67
+ _onCandidate (RTCIceCandidate candidate) {
68
+ print ('onCandidate: ' + candidate.candidate);
43
69
_peerConnection.addCandidate (candidate);
44
70
}
45
71
72
+ _onRenegotiationNeeded () {
73
+ print ('RenegotiationNeeded' );
74
+ }
75
+
46
76
// Platform messages are asynchronous, so we initialize in an async method.
47
77
initPlatformState () async {
48
78
final Map <String , dynamic > mediaConstraints = {
49
79
"audio" : true ,
50
80
"video" : {
51
81
"mandatory" : {
52
- "minWidth" : '640' , // Provide your own width, height and frame rate here
53
- "minHeight" : '360' ,
82
+ "minWidth" :
83
+ '640' , // Provide your own width, height and frame rate here
84
+ "minHeight" : '480' ,
54
85
"minFrameRate" : '30' ,
55
86
},
56
87
"facingMode" : "user" ,
@@ -62,52 +93,59 @@ class _MyAppState extends State<MyApp> {
62
93
"audio": true,
63
94
"video": true,
64
95
};*/
65
- Map <String , dynamic > configuration = {
96
+ Map <String , dynamic > configuration = {
66
97
"iceServers" : [
67
- { "url" : "stun:stun.l.google.com:19302" },
68
- ]
69
- };
98
+ { "url" : "stun:stun.l.google.com:19302" },
99
+ ]
100
+ };
70
101
71
- final Map <String , dynamic > OFFER_SDP_CONSTRAINTS = {
102
+ final Map <String , dynamic > OFFER_SDP_CONSTRAINTS = {
72
103
"mandatory" : {
73
104
"OfferToReceiveAudio" : true ,
74
105
"OfferToReceiveVideo" : true ,
75
106
},
76
107
"optional" : [],
77
108
};
78
109
79
- final Map <String , dynamic > LOOPBACK_CONSTRAINTS = {
110
+ final Map <String , dynamic > LOOPBACK_CONSTRAINTS = {
80
111
"mandatory" : {},
81
112
"optional" : [
82
- {"DtlsSrtpKeyAgreement" : false },
113
+ {"DtlsSrtpKeyAgreement" : false },
83
114
],
84
115
};
85
116
86
117
// Platform messages may fail, so we use a try/catch PlatformException.
87
118
try {
88
119
_localStream = await getUserMedia (mediaConstraints);
89
- await _localVideoView.initialize (_width, _height);
90
- await _remoteVideoView.initialize (_width, _height);
120
+ await _localVideoRenderer.initialize (_width, _height);
121
+ await _remoteVideoRenderer.initialize (_width, _height);
122
+ _localVideoRenderer.srcObject = _localStream;
123
+
124
+ _peerConnection =
125
+ await createPeerConnection (configuration, LOOPBACK_CONSTRAINTS );
91
126
92
- _peerConnection = await createPeerConnection (configuration, LOOPBACK_CONSTRAINTS );
127
+ _peerConnection.onSignalingState = _onSignalingState;
128
+ _peerConnection.onIceGatheringState = _onIceGatheringState;
129
+ _peerConnection.onIceConnectionState = _onIceConnectionState;
93
130
_peerConnection.onAddStream = _onAddStream;
94
131
_peerConnection.onRemoveStream = _onRemoveStream;
95
132
_peerConnection.onIceCandidate = _onCandidate;
133
+ _peerConnection.onRenegotiationNeeded = _onRenegotiationNeeded;
134
+
96
135
_peerConnection.addStream (_localStream);
97
- RTCSessionDescrption description = await _peerConnection.createOffer (OFFER_SDP_CONSTRAINTS );
136
+ RTCSessionDescrption description =
137
+ await _peerConnection.createOffer (OFFER_SDP_CONSTRAINTS );
138
+ print (description.sdp);
98
139
_peerConnection.setLocalDescription (description);
99
140
//change for loopback.
100
141
description.type = 'answer' ;
101
142
_peerConnection.setRemoteDescription (description);
102
- } catch (e) {
103
- //'Failed to get platform version.';
143
+ } catch (e) {
144
+ //'Failed to get platform version.';
104
145
}
105
- if (! mounted)
106
- return ;
146
+ if (! mounted) return ;
107
147
108
- setState (() {
109
- _localVideoView.srcObject = _localStream;
110
- });
148
+ setState (() {});
111
149
}
112
150
113
151
@override
@@ -117,28 +155,38 @@ class _MyAppState extends State<MyApp> {
117
155
appBar: new AppBar (
118
156
title: new Text ('Flutter-WebRTC example' ),
119
157
),
120
- body: new Center ( child: new Column (
121
- crossAxisAlignment: CrossAxisAlignment .start,
122
- children: [
123
- new Text ('WebRTC loopback demo.' ),
124
- new Container (
125
- width: _width,
126
- height: _height,
127
- child: _localVideoView.isInitialized
128
- ? new Texture (textureId: _localVideoView.renderId)
129
- : null ,
130
- ),
131
- new Text ('Local video' ),
132
- new Container (
133
- width: _width,
134
- height: _height,
135
- child: _remoteVideoView.isInitialized
136
- ? new Texture (textureId: _remoteVideoView.renderId)
137
- : null ,
138
- ),
139
- new Text ('Remote video' ),
140
- ])
141
- ),
158
+ body: new Center (
159
+ child: new Column (
160
+ crossAxisAlignment: CrossAxisAlignment .start,
161
+ children: [
162
+ new Text ('Loopback demo.' ),
163
+ new Transform (
164
+ child: new Container (
165
+ width: _width,
166
+ height: _height,
167
+ child: _remoteVideoRenderer.isInitialized
168
+ ? new Texture (textureId: _remoteVideoRenderer.renderId)
169
+ : null ,
170
+ ),
171
+ alignment: FractionalOffset .center, // set transform origin
172
+ transform: new Matrix4 .identity ()
173
+ ..
F987
rotateZ (_rotation * 3.1415927 / 180 ),
174
+ ),
175
+ new Text ('Local video' ),
176
+ new Transform (
177
+ child: new Container (
178
+ width: _width,
179
+ height: _height,
180
+ child: _remoteVideoRenderer.isInitialized
181
+ ? new Texture (textureId: _remoteVideoRenderer.renderId)
182
+ : null ,
183
+ ),
184
+ alignment: FractionalOffset .center, // set transform origin
185
+ transform: new Matrix4 .identity ()
186
+ ..rotateZ (90 * 3.1415927 / 180 ),
187
+ ),
188
+ new Text ('Remote video' ),
189
+ ])),
142
190
),
143
191
);
144
192
}
0 commit comments