[video_player] Fixed HLS Streams on iOS (#3360)

Refactor `FLTCMTimeToMillis` to support indefinite streams.

Co-authored-by: Mike Diarmid <mike.diarmid@gmail.com>
diff --git a/packages/video_player/video_player/CHANGELOG.md b/packages/video_player/video_player/CHANGELOG.md
index f35a198..135057b 100644
--- a/packages/video_player/video_player/CHANGELOG.md
+++ b/packages/video_player/video_player/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 2.1.8
+
+* Refactor `FLTCMTimeToMillis` to support indefinite streams. Fixes [#48670](https://github.com/flutter/flutter/issues/48670).
+
 ## 2.1.7
 
 * Update exoplayer to 2.14.1, removing dependency on Bintray.
diff --git a/packages/video_player/video_player/example/integration_test/video_player_test.dart b/packages/video_player/video_player/example/integration_test/video_player_test.dart
index 87575df..aef3beb 100644
--- a/packages/video_player/video_player/example/integration_test/video_player_test.dart
+++ b/packages/video_player/video_player/example/integration_test/video_player_test.dart
@@ -78,6 +78,23 @@
     );
 
     testWidgets(
+      'live stream duration != 0',
+      (WidgetTester tester) async {
+        VideoPlayerController networkController = VideoPlayerController.network(
+          'https://cph-p2p-msl.akamaized.net/hls/live/2000341/test/master.m3u8',
+        );
+        await networkController.initialize();
+
+        expect(networkController.value.isInitialized, true);
+        // Live streams should have either a positive duration or C.TIME_UNSET if the duration is unknown
+        // See https://exoplayer.dev/doc/reference/com/google/android/exoplayer2/Player.html#getDuration--
+        expect(networkController.value.duration,
+            (Duration duration) => duration != Duration.zero);
+      },
+      skip: (kIsWeb),
+    );
+
+    testWidgets(
       'can be played',
       (WidgetTester tester) async {
         await _controller.initialize();
diff --git a/packages/video_player/video_player/ios/Classes/FLTVideoPlayerPlugin.m b/packages/video_player/video_player/ios/Classes/FLTVideoPlayerPlugin.m
index b359c1b..f0f672d 100644
--- a/packages/video_player/video_player/ios/Classes/FLTVideoPlayerPlugin.m
+++ b/packages/video_player/video_player/ios/Classes/FLTVideoPlayerPlugin.m
@@ -11,11 +11,6 @@
 #error Code Requires ARC.
 #endif
 
-int64_t FLTCMTimeToMillis(CMTime time) {
-  if (time.timescale == 0) return 0;
-  return time.value * 1000 / time.timescale;
-}
-
 @interface FLTFrameUpdater : NSObject
 @property(nonatomic) int64_t textureId;
 @property(nonatomic, weak, readonly) NSObject<FlutterTextureRegistry>* registry;
@@ -107,6 +102,16 @@
   }
 }
 
+const int64_t TIME_UNSET = -9223372036854775807;
+
+static inline int64_t FLTCMTimeToMillis(CMTime time) {
+  // When CMTIME_IS_INDEFINITE return a value that matches TIME_UNSET from ExoPlayer2 on Android.
+  // Fixes https://github.com/flutter/flutter/issues/48670
+  if (CMTIME_IS_INDEFINITE(time)) return TIME_UNSET;
+  if (time.timescale == 0) return 0;
+  return time.value * 1000 / time.timescale;
+}
+
 static inline CGFloat radiansToDegrees(CGFloat radians) {
   // Input range [-pi, pi] or [-180, 180]
   CGFloat degrees = GLKMathRadiansToDegrees((float)radians);
diff --git a/packages/video_player/video_player/pubspec.yaml b/packages/video_player/video_player/pubspec.yaml
index 15b2cc9..cf03129 100644
--- a/packages/video_player/video_player/pubspec.yaml
+++ b/packages/video_player/video_player/pubspec.yaml
@@ -3,7 +3,7 @@
   widgets on Android, iOS, and web.
 repository: https://github.com/flutter/plugins/tree/master/packages/video_player/video_player
 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+video_player%22
-version: 2.1.7
+version: 2.1.8
 
 environment:
   sdk: ">=2.12.0 <3.0.0"