[multiple] Improve video playback in image_picker example (#2819)

This change adds small bugfixes to the following packages:

* video_player_web:
  * Prevent parsing Blob URLs so Safari can play from a PickedFile.
  * Allow users to 'mute' videos by setting their volume to 0.0 (this enables auto-play in most modern browsers)
* video_player:
  * Fix an issue where aspect ratio calculations failed when some of the video sizes were zero (happened in web for incorrect videos)
* image_picker (example app):
  * Start videos in web muted so they can auto-play
  * Dispose video controllers when they're really not needed. This fixes a fatal crash in Safari (not so fatal in other browsers).
diff --git a/packages/image_picker/image_picker/CHANGELOG.md b/packages/image_picker/image_picker/CHANGELOG.md
index 6b85f26..0cba0c8 100644
--- a/packages/image_picker/image_picker/CHANGELOG.md
+++ b/packages/image_picker/image_picker/CHANGELOG.md
@@ -1,3 +1,9 @@
+## 0.6.7+3
+
+* Fixes to the example app:
+  * Make videos in web start muted. This allows auto-play across browsers.
+  * Prevent the app from disposing of video controllers too early.
+
 ## 0.6.7+2
 
 * iOS: Fixes unpresentable album/image picker if window's root view controller is already presenting other view controller.
diff --git a/packages/image_picker/image_picker/example/lib/main.dart b/packages/image_picker/image_picker/example/lib/main.dart
index dff2906..ece8c45 100755
--- a/packages/image_picker/image_picker/example/lib/main.dart
+++ b/packages/image_picker/image_picker/example/lib/main.dart
@@ -42,6 +42,7 @@
   dynamic _pickImageError;
   bool isVideo = false;
   VideoPlayerController _controller;
+  VideoPlayerController _toBeDisposed;
   String _retrieveDataError;
 
   final ImagePicker _picker = ImagePicker();
@@ -54,10 +55,16 @@
       await _disposeVideoController();
       if (kIsWeb) {
         _controller = VideoPlayerController.network(file.path);
+        // In web, most browsers won't honor a programmatic call to .play
+        // if the video has a sound track (and is not muted).
+        // Mute the video so it auto-plays in web!
+        // This is not needed if the call to .play is the result of user
+        // interaction (clicking on a "play" button, for example).
+        await _controller.setVolume(0.0);
       } else {
         _controller = VideoPlayerController.file(File(file.path));
+        await _controller.setVolume(1.0);
       }
-      await _controller.setVolume(1.0);
       await _controller.initialize();
       await _controller.setLooping(true);
       await _controller.play();
@@ -114,10 +121,11 @@
   }
 
   Future<void> _disposeVideoController() async {
-    if (_controller != null) {
-      await _controller.dispose();
-      _controller = null;
+    if (_toBeDisposed != null) {
+      await _toBeDisposed.dispose();
     }
+    _toBeDisposed = _controller;
+    _controller = null;
   }
 
   Widget _previewVideo() {
diff --git a/packages/image_picker/image_picker/pubspec.yaml b/packages/image_picker/image_picker/pubspec.yaml
index 4f52b19..eedecd4 100755
--- a/packages/image_picker/image_picker/pubspec.yaml
+++ b/packages/image_picker/image_picker/pubspec.yaml
@@ -2,7 +2,7 @@
 description: Flutter plugin for selecting images from the Android and iOS image
   library, and taking new pictures with the camera.
 homepage: https://github.com/flutter/plugins/tree/master/packages/image_picker/image_picker
-version: 0.6.7+2
+version: 0.6.7+3
 
 flutter:
   plugin:
diff --git a/packages/video_player/video_player/CHANGELOG.md b/packages/video_player/video_player/CHANGELOG.md
index 9928fe3..e3f49e7 100644
--- a/packages/video_player/video_player/CHANGELOG.md
+++ b/packages/video_player/video_player/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.10.11+2
+
+* Fix aspectRatio calculation when size.width or size.height are zero.
+
 ## 0.10.11+1
 
 * Post-v2 Android embedding cleanups.
diff --git a/packages/video_player/video_player/lib/video_player.dart b/packages/video_player/video_player/lib/video_player.dart
index f2f9289..a2290b2 100644
--- a/packages/video_player/video_player/lib/video_player.dart
+++ b/packages/video_player/video_player/lib/video_player.dart
@@ -97,7 +97,7 @@
   /// Returns [size.width] / [size.height] when size is non-null, or `1.0.` when
   /// size is null or the aspect ratio would be less than or equal to 0.0.
   double get aspectRatio {
-    if (size == null) {
+    if (size == null || size.width == 0 || size.height == 0) {
       return 1.0;
     }
     final double aspectRatio = size.width / size.height;
diff --git a/packages/video_player/video_player/pubspec.yaml b/packages/video_player/video_player/pubspec.yaml
index f967cd0..03f71bf 100644
--- a/packages/video_player/video_player/pubspec.yaml
+++ b/packages/video_player/video_player/pubspec.yaml
@@ -4,7 +4,7 @@
 # 0.10.y+z is compatible with 1.0.0, if you land a breaking change bump
 # the version to 2.0.0.
 # See more details: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0
-version: 0.10.11+1
+version: 0.10.11+2
 homepage: https://github.com/flutter/plugins/tree/master/packages/video_player/video_player
 
 flutter:
diff --git a/packages/video_player/video_player/test/video_player_test.dart b/packages/video_player/video_player/test/video_player_test.dart
index ac8459d..ae236de 100644
--- a/packages/video_player/video_player/test/video_player_test.dart
+++ b/packages/video_player/video_player/test/video_player_test.dart
@@ -517,6 +517,48 @@
 
       expect(exactCopy.toString(), original.toString());
     });
+
+    group('aspectRatio', () {
+      test('640x480 -> 4:3', () {
+        final value = VideoPlayerValue(
+          size: Size(640, 480),
+          duration: Duration(seconds: 1),
+        );
+        expect(value.aspectRatio, 4 / 3);
+      });
+
+      test('null size -> 1.0', () {
+        final value = VideoPlayerValue(
+          size: null,
+          duration: Duration(seconds: 1),
+        );
+        expect(value.aspectRatio, 1.0);
+      });
+
+      test('height = 0 -> 1.0', () {
+        final value = VideoPlayerValue(
+          size: Size(640, 0),
+          duration: Duration(seconds: 1),
+        );
+        expect(value.aspectRatio, 1.0);
+      });
+
+      test('width = 0 -> 1.0', () {
+        final value = VideoPlayerValue(
+          size: Size(0, 480),
+          duration: Duration(seconds: 1),
+        );
+        expect(value.aspectRatio, 1.0);
+      });
+
+      test('negative aspect ratio -> 1.0', () {
+        final value = VideoPlayerValue(
+          size: Size(640, -480),
+          duration: Duration(seconds: 1),
+        );
+        expect(value.aspectRatio, 1.0);
+      });
+    });
   });
 
   test('VideoProgressColors', () {
diff --git a/packages/video_player/video_player_web/CHANGELOG.md b/packages/video_player/video_player_web/CHANGELOG.md
index cd977c3..9c500e9 100644
--- a/packages/video_player/video_player_web/CHANGELOG.md
+++ b/packages/video_player/video_player_web/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 0.1.3+2
+
+* Allow users to set the 'muted' attribute on video elements by setting their volume to 0.
+* Do not parse URIs on 'network' videos to not break blobs (Safari).
+
 ## 0.1.3+1
 
 * Remove Android folder from `video_player_web`.
diff --git a/packages/video_player/video_player_web/lib/video_player_web.dart b/packages/video_player/video_player_web/lib/video_player_web.dart
index 039c3ce..3a849f4 100644
--- a/packages/video_player/video_player_web/lib/video_player_web.dart
+++ b/packages/video_player/video_player_web/lib/video_player_web.dart
@@ -66,10 +66,12 @@
     final int textureId = _textureCounter;
     _textureCounter++;
 
-    Uri uri;
+    String uri;
     switch (dataSource.sourceType) {
       case DataSourceType.network:
-        uri = Uri.parse(dataSource.uri);
+        // Do NOT modify the incoming uri, it can be a Blob, and Safari doesn't
+        // like blobs that have changed.
+        uri = dataSource.uri;
         break;
       case DataSourceType.asset:
         String assetUrl = dataSource.asset;
@@ -79,7 +81,7 @@
         // 'webOnlyAssetManager' is only in the web version of dart:ui
         // ignore: undefined_prefixed_name
         assetUrl = ui.webOnlyAssetManager.getAssetUrl(assetUrl);
-        uri = Uri.parse(assetUrl);
+        uri = assetUrl;
         break;
       case DataSourceType.file:
         return Future.error(UnimplementedError(
@@ -145,18 +147,21 @@
   final StreamController<VideoEvent> eventController =
       StreamController<VideoEvent>();
 
-  final Uri uri;
+  final String uri;
   final int textureId;
   VideoElement videoElement;
   bool isInitialized = false;
 
   void initialize() {
     videoElement = VideoElement()
-      ..src = uri.toString()
+      ..src = uri
       ..autoplay = false
       ..controls = false
       ..style.border = 'none';
 
+    // Allows Safari iOS to play the video inline
+    videoElement.setAttribute('playsinline', 'true');
+
     // TODO(hterkelsen): Use initialization parameters once they are available
     // ignore: undefined_prefixed_name
     ui.platformViewRegistry.registerViewFactory(
@@ -218,6 +223,12 @@
   }
 
   void setVolume(double value) {
+    // TODO: Do we need to expose a "muted" API? https://github.com/flutter/flutter/issues/60721
+    if (value > 0.0) {
+      videoElement.muted = false;
+    } else {
+      videoElement.muted = true;
+    }
     videoElement.volume = value;
   }
 
diff --git a/packages/video_player/video_player_web/pubspec.yaml b/packages/video_player/video_player_web/pubspec.yaml
index 523d5a7..891430d 100644
--- a/packages/video_player/video_player_web/pubspec.yaml
+++ b/packages/video_player/video_player_web/pubspec.yaml
@@ -4,7 +4,7 @@
 # 0.1.y+z is compatible with 1.0.0, if you land a breaking change bump
 # the version to 2.0.0.
 # See more details: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0
-version: 0.1.3+1
+version: 0.1.3+2
 
 flutter:
   plugin: