diff --git a/lib/src/widgets/video_track_renderer.dart b/lib/src/widgets/video_track_renderer.dart index 0ba3024b..53b36564 100644 --- a/lib/src/widgets/video_track_renderer.dart +++ b/lib/src/widgets/video_track_renderer.dart @@ -69,6 +69,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; @@ -107,6 +108,7 @@ class _VideoTrackRendererState extends State { void disposeRenderer() { try { + _renderer?.onResize = null; _renderer?.srcObject = null; _renderer?.dispose(); _renderer = null; @@ -153,6 +155,13 @@ class _VideoTrackRendererState extends State { // force recompute of mirror mode setState(() {}); }); + _renderer?.onResize = () { + if (mounted) { + setState(() { + _aspectRatio = _renderer?.videoValue.aspectRatio; + }); + } + }; } @override @@ -254,8 +263,46 @@ 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 == rtc.RTCVideoViewObjectFit.RTCVideoViewObjectFitCover) { + return child; + } + + return 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); + }, + ); + } bool _shouldMirror() { // off for screen share