diff --git a/lib/src/widgets/video_track_renderer.dart b/lib/src/widgets/video_track_renderer.dart index 61e35360..eb7ccc27 100644 --- a/lib/src/widgets/video_track_renderer.dart +++ b/lib/src/widgets/video_track_renderer.dart @@ -65,6 +65,9 @@ class VideoTrackRenderer extends StatefulWidget { final rtc.RTCVideoRenderer? cachedRenderer; final bool autoDisposeRenderer; + /// wrap the video view in a Center widget (if [fit] is [VideoViewFit.contain]) + final bool autoCenter; + const VideoTrackRenderer( this.track, { this.fit = VideoViewFit.contain, @@ -72,6 +75,7 @@ class VideoTrackRenderer extends StatefulWidget { this.renderMode = VideoRenderMode.texture, this.autoDisposeRenderer = true, this.cachedRenderer, + this.autoCenter = true, Key? key, }) : super(key: key); @@ -83,6 +87,7 @@ class _VideoTrackRendererState extends State { rtc.VideoRenderer? _renderer; // for flutter web only. bool _rendererReadyForWeb = false; + double? _aspectRatio; EventsListener? _listener; // Used to compute visibility information late GlobalKey _internalKey; @@ -121,6 +126,7 @@ class _VideoTrackRendererState extends State { void disposeRenderer() { try { + _renderer?.onResize = null; _renderer?.srcObject = null; _renderer?.dispose(); _renderer = null; @@ -167,6 +173,14 @@ class _VideoTrackRendererState extends State { // force recompute of mirror mode setState(() {}); }); + _renderer?.onResize = () { + if (mounted) { + setState(() { + _aspectRatio = + (_renderer as rtc.RTCVideoRenderer?)?.videoValue.aspectRatio; + }); + } + }; } @override @@ -268,8 +282,52 @@ class _VideoTrackRendererState extends State { // FutureBuilder will cause flickering for flutter web. so using // different rendering methods for web and native. @override - Widget build(BuildContext context) => - kIsWeb ? _videoViewForWeb() : _videoViewForNative(); + Widget build(BuildContext context) { + final child = kIsWeb ? _videoViewForWeb() : _videoViewForNative(); + + if (widget.fit == VideoViewFit.cover) { + return child; + } + + final videoView = LayoutBuilder( + builder: (BuildContext context, BoxConstraints constraints) { + if (!constraints.hasBoundedWidth && !constraints.hasBoundedHeight) { + return child; + } + if (_aspectRatio == null) { + return child; + } + + bool fixHeight; + if (!constraints.hasBoundedWidth) { + fixHeight = true; + } else if (!constraints.hasBoundedHeight) { + fixHeight = false; + } else { + // both width and height are bound, figure out which to fix based on aspect ratios + final constraintsAspectRatio = + constraints.maxWidth / constraints.maxHeight; + fixHeight = constraintsAspectRatio > _aspectRatio!; + } + final double width; + final double height; + if (fixHeight) { + height = constraints.maxHeight; + width = height * _aspectRatio!; + } else { + width = constraints.maxWidth; + height = width / _aspectRatio!; + } + return SizedBox(width: width, height: height, child: child); + }, + ); + + if (widget.autoCenter) { + return Center(child: videoView); + } else { + return videoView; + } + } bool _shouldMirror() { // off for screen share