@@ -7,33 +7,34 @@ import '../enums.dart';
7
7
import './ui_fake.dart' if (dart.library.html) 'dart:ui' as ui;
8
8
import 'media_stream.dart' ;
9
9
10
- typedef VideoRotationChangeCallback = void Function (
11
- int textureId, int rotation);
12
10
typedef VideoSizeChangeCallback = void Function (
13
11
int textureId, double width, double height);
12
+ typedef StateChangeCallback = void Function ();
13
+ typedef FirstFrameRenderedCallback = void Function ();
14
14
15
15
class RTCVideoRenderer {
16
16
RTCVideoRenderer ();
17
- double _width = 0.0 , _height = 0.0 ;
17
+ var _width = 0.0 , _height = 0.0 ;
18
+ var _isFirstFrameRendered = false ;
18
19
MediaStream _srcObject;
19
20
VideoSizeChangeCallback onVideoSizeChanged;
20
- VideoRotationChangeCallback onVideoRotationChanged;
21
- dynamic onFirstFrameRendered;
22
- var isFirstFrameRendered = false ;
23
- dynamic onStateChanged;
24
- HtmlElementView htmlElementView;
21
+ StateChangeCallback onStateChanged;
22
+ FirstFrameRenderedCallback onFirstFrameRendered;
23
+
24
+ HtmlElementView _htmlElementView;
25
25
html.VideoElement _htmlVideoElement;
26
26
27
- static final _videoViews = < html.VideoElement > [];
27
+ final _videoViews = < html.VideoElement > [];
28
28
29
29
bool get isMuted => _htmlVideoElement? .muted ?? true ;
30
30
set isMuted (bool i) => _htmlVideoElement? .muted = i;
31
31
32
- static void fixVideoElements () => _videoViews. forEach ((v) => v. play ()) ;
32
+ HtmlElementView get htmlElementView => _htmlElementView ;
33
33
34
- void initialize () async {
35
- print ('You don\' t have to call RTCVideoRenderer.initialize on Flutter Web' );
36
- }
34
+ void fixVideoElements () => _videoViews.forEach ((v) => v.play ());
35
+
36
+ /// You don\'t have to call RTCVideoRenderer.initialize if you use only Flutter web
37
+ void initialize () async {}
37
38
38
39
int get rotation => 0 ;
39
40
@@ -49,14 +50,12 @@ class RTCVideoRenderer {
49
50
MediaStream get srcObject => _srcObject;
50
51
51
52
set srcObject (MediaStream stream) {
52
- _srcObject = stream;
53
-
54
- if (_srcObject == null ) {
55
- findHtmlView ()? .srcObject = null ;
53
+ if (stream == null ) {
56
54
return ;
57
55
}
58
56
59
- if (htmlElementView != null ) {
57
+ _srcObject = stream;
58
+ if (_htmlElementView != null ) {
60
59
findHtmlView ()? .srcObject = stream? .jsStream;
61
60
}
62
61
@@ -70,55 +69,42 @@ class RTCVideoRenderer {
70
69
_videoViews.add (x);
71
70
return x;
72
71
});
73
- htmlElementView = HtmlElementView (viewType: stream.id);
74
- if (onStateChanged != null ) {
75
- onStateChanged ();
76
- }
72
+
73
+ _htmlElementView = HtmlElementView (viewType: stream.id);
74
+ onStateChanged? .call ();
77
75
}
78
76
79
77
void findAndApply (Size size) {
80
78
final htmlView = findHtmlView ();
81
- if (_srcObject != null && htmlView != null ) {
82
- if (htmlView.width == size.width.toInt () &&
83
- htmlView.height == size.height.toInt ()) return ;
84
- htmlView.srcObject = _srcObject.jsStream;
85
- htmlView.width = size.width.toInt ();
86
- htmlView.height = size.height.toInt ();
87
- htmlView.onLoadedMetadata.listen ((_) {
88
- if (htmlView.videoWidth != 0 &&
89
- htmlView.videoHeight != 0 &a
E377
mp;&
90
- (_width != htmlView.videoWidth ||
91
- _height != htmlView.videoHeight)) {
92
- _width = htmlView.videoWidth.toDouble ();
93
- _height = htmlView.videoHeight.toDouble ();
94
- if (onVideoSizeChanged != null ) {
95
- onVideoSizeChanged (0 , _width, _height);
96
- }
97
- }
98
- if (! isFirstFrameRendered && onFirstFrameRendered != null ) {
99
- onFirstFrameRendered ();
100
- isFirstFrameRendered = true ;
101
- }
102
- });
103
- htmlView.onResize.listen ((_) {
104
- if (htmlView.videoWidth != 0 &&
105
- htmlView.videoHeight != 0 &&
106
- (_width != htmlView.videoWidth ||
107
- _height != htmlView.videoHeight)) {
108
- _width = htmlView.videoWidth.toDouble ();
109
- _height = htmlView.videoHeight.toDouble ();
110
- if (onVideoSizeChanged != null ) {
111
- onVideoSizeChanged (0 , _width, _height);
112
- }
113
- }
114
- });
115
- if (htmlView.videoWidth != 0 &&
116
- htmlView.videoHeight != 0 &&
117
- (_width != htmlView.videoWidth || _height != htmlView.videoHeight)) {
118
- _width = htmlView.videoWidth.toDouble ();
119
- _height = htmlView.videoHeight.toDouble ();
120
- if (onVideoSizeChanged != null ) onVideoSizeChanged (0 , _width, _height);
79
+ if (_srcObject == null || htmlView == null ) return ;
80
+ if (htmlView.width == size.width.toInt () &&
81
+ htmlView.height == size.height.toInt ()) return ;
82
+
83
+ htmlView.srcObject = _srcObject.jsStream;
84
+ htmlView.width = size.width.toInt ();
85
+ htmlView.height = size.height.toInt ();
86
+
87
+ htmlView.onLoadedMetadata.listen ((_) {
88
+ _checkVideoSizeChanged (htmlView);
89
+
90
+ if (! _isFirstFrameRendered) {
91
+ onFirstFrameRendered? .call ();
92
+ _isFirstFrameRendered = true ;
121
93
}
94
+ });
95
+
96
+ htmlView.onResize.listen ((_) => _checkVideoSizeChanged (htmlView));
97
+
98
+ _checkVideoSizeChanged (htmlView);
99
+ }
100
+
101
+ void _checkVideoSizeChanged (html.VideoElement htmlView) {
102
+ if (htmlView.videoWidth != 0 &&
103
+ htmlView.videoHeight != 0 &&
104
+ (_width != htmlView.videoWidth || _height != htmlView.videoHeight)) {
105
+ _width = htmlView.videoWidth.toDouble ();
106
+ _height = htmlView.videoHeight.toDouble ();
107
+ onVideoSizeChanged? .call (0 , _width, _height);
122
108
}
123
109
}
124
110
@@ -133,7 +119,15 @@ class RTCVideoRenderer {
133
119
return lastChild;
134
120
}
135
121
136
- Future <Null > dispose () async {
122
+ ///By calling the dispose you are safely disposing the MediaStream
123
+ Future <void > dispose () async {
124
+ await _srcObject? .dispose ();
125
+
126
+ _srcObject = null ;
127
+ findHtmlView ()? .srcObject = null ;
128
+ _videoViews.forEach ((element) {
129
+ element.srcObject = null ;
130
+ });
137
131
// TODO(cloudwebrtc): ???
138
132
// https://stackoverflow.com/questions/3258587/how-to-properly-unload-destroy-a-video-element/28060352
139
133
}
0 commit comments