Skip to content

Commit 804eaf0

Browse files
authored
fix: tighten VideoTrackRenderer Widget (#695)
This allows external users to e.g. apply rounded edges. Without this patch, VideoTrackRenderer will expand to its available space with no way (known to me..) for parent widgets to know how large the video actually is. depends on flutter-webrtc/flutter-webrtc#1754 (and flutter-webrtc/webrtc-interface#30)
1 parent ac031cc commit 804eaf0

File tree

1 file changed

+60
-2
lines changed

1 file changed

+60
-2
lines changed

lib/src/widgets/video_track_renderer.dart

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,17 @@ class VideoTrackRenderer extends StatefulWidget {
6565
final rtc.RTCVideoRenderer? cachedRenderer;
6666
final bool autoDisposeRenderer;
6767

68+
/// wrap the video view in a Center widget (if [fit] is [VideoViewFit.contain])
69+
final bool autoCenter;
70+
6871
const VideoTrackRenderer(
6972
this.track, {
7073
this.fit = VideoViewFit.contain,
7174
this.mirrorMode = VideoViewMirrorMode.auto,
7275
this.renderMode = VideoRenderMode.texture,
7376
this.autoDisposeRenderer = true,
7477
this.cachedRenderer,
78+
this.autoCenter = true,
7579
Key? key,
7680
}) : super(key: key);
7781

@@ -83,6 +87,7 @@ class _VideoTrackRendererState extends State<VideoTrackRenderer> {
8387
rtc.VideoRenderer? _renderer;
8488
// for flutter web only.
8589
bool _rendererReadyForWeb = false;
90+
double? _aspectRatio;
8691
EventsListener<TrackEvent>? _listener;
8792
// Used to compute visibility information
8893
late GlobalKey _internalKey;
@@ -121,6 +126,7 @@ class _VideoTrackRendererState extends State<VideoTrackRenderer> {
121126

122127
void disposeRenderer() {
123128
try {
129+
_renderer?.onResize = null;
124130
_renderer?.srcObject = null;
125131
_renderer?.dispose();
126132
_renderer = null;
@@ -167,6 +173,14 @@ class _VideoTrackRendererState extends State<VideoTrackRenderer> {
167173
// force recompute of mirror mode
168174
setState(() {});
169175
});
176+
_renderer?.onResize = () {
177+
if (mounted) {
178+
setState(() {
179+
_aspectRatio =
180+
(_renderer as rtc.RTCVideoRenderer?)?.videoValue.aspectRatio;
181+
});
182+
}
183+
};
170184
}
171185

172186
@override
@@ -268,8 +282,52 @@ class _VideoTrackRendererState extends State<VideoTrackRenderer> {
268282
// FutureBuilder will cause flickering for flutter web. so using
269283
// different rendering methods for web and native.
270284
@override
271-
Widget build(BuildContext context) =>
272-
kIsWeb ? _videoViewForWeb() : _videoViewForNative();
285+
Widget build(BuildContext context) {
286+
final child = kIsWeb ? _videoViewForWeb() : _videoViewForNative();
287+
288+
if (widget.fit == VideoViewFit.cover) {
289+
return child;
290+
}
291+
292+
final videoView = LayoutBuilder(
293+
builder: (BuildContext context, BoxConstraints constraints) {
294+
if (!constraints.hasBoundedWidth && !constraints.hasBoundedHeight) {
295+
return child;
296+
}
297+
if (_aspectRatio == null) {
298+
return child;
299+
}
300+
301+
bool fixHeight;
302+
if (!constraints.hasBoundedWidth) {
303+
fixHeight = true;
304+
} else if (!constraints.hasBoundedHeight) {
305+
fixHeight = false;
306+
} else {
307+
// both width and height are bound, figure out which to fix based on aspect ratios
308+
final constraintsAspectRatio =
309+
constraints.maxWidth / constraints.maxHeight;
310+
fixHeight = constraintsAspectRatio > _aspectRatio!;
311+
}
312+
final double width;
313+
final double height;
314+
if (fixHeight) {
315+
height = constraints.maxHeight;
316+
width = height * _aspectRatio!;
317+
} else {
318+
width = constraints.maxWidth;
319+
height = width / _aspectRatio!;
320+
}
321+
return SizedBox(width: width, height: height, child: child);
322+
},
323+
);
324+
325+
if (widget.autoCenter) {
326+
return Center(child: videoView);
327+
} else {
328+
return videoView;
329+
}
330+
}
273331

274332
bool _shouldMirror() {
275333
// off for screen share

0 commit comments

Comments
 (0)