-
Notifications
You must be signed in to change notification settings - Fork 27.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
iOS video_player sample doesn't show video in the emulator #14647
Comments
The iOS emulator uses the software renderer which does not support external texture sources. You will have to use a device to test video support. @mravn-google: If the simulators support the necessary Core Video frameworks, we can use emulated OpenGL on the simulator to enable users to test video and external texture sources on the simulator. |
The culprit on Simulator appears to be our use of the texture cache. We have not had time to look into alternatives yet, but https://stackoverflow.com/questions/12813442/cvopenglestexturecache-vs-gltexsubimage2d-on-ios may provide a starting point. |
So it is not as straightforward as just flipping the renderer backend on the simulators back to OpenGL then. Maybe we should log a clearer message that states that external texture sources are not available and suggests the user test on a device then (till we figure out a workaround). |
At the very least, the README should warn users that iOS simulator is not supported. |
Also for us poor package developers, please put a comment in TextureRegistry to the same effect ;) |
This cost me quite a few hours. Please, please update the documentation. |
I added a note to the README. |
#13331 is the equivalent issue for Android. I guess it makes sense to keep them both open because they are probably caused by different underlying issues. |
Hi, this is becomming a deal breaker to our dev cycle/pace. So, os there an ETA? Thanks. |
@chinmaygarde are there plans to do something or is this just not technically feasible? |
Just be curious, any plan to make the video work on iOS Simulator guys? |
What kind of work would be necessary to get this work? I'm willing to send in a PR (this is something that would be very beneficial IMO), but from reading this conversation, I'm not 100% sure how to alleviate the underlying problem. |
It'd be very good to have this feature as I don't have neither a macbook or iPhone. I'd like to develop in a hackintosh |
I have erro every time I tring to run in my device |
#43028 would allow this |
Not really. Last time I checked, CoreMedia would not vend pixel buffers on the simulator. That issue is necessary but not sufficient for video playback on the simulators. I haven't tested with Metal however. |
Initial observations suggest that this issue will be fixed by using Metal rendering on iOS simulators. Unlike OpenGL, Metal uses host passthrough on simulators so the CoreVideo with OpenGL restriction should not exist when using that backend. |
@chinmaygarde this is worse as I use macOS on a VM in Ubuntu. I guess Metal wont work... |
I expect there will be a fallback to software rendering (the current status quo) as even Metal on iOS simulators will only be available from Catalina onwards. So I wouldn't expect any regressions to your workflow. However, folks on macOS Catalina and above should see performance improvements and plugins that use external texture composition to work in simulators. |
This comment has been minimized.
This comment has been minimized.
code sample// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// ignore_for_file: public_member_api_docs
/// An example of using the plugin, controlling lifecycle and playback of the
/// video.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
void main() {
runApp(
MaterialApp(
home: _App(),
),
);
}
class _App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return DefaultTabController(
length: 3,
child: Scaffold(
key: const ValueKey<String>('home_page'),
appBar: AppBar(
title: const Text('Video player example'),
actions: <Widget>[
IconButton(
key: const ValueKey<String>('push_tab'),
icon: const Icon(Icons.navigation),
onPressed: () {
Navigator.push<_PlayerVideoAndPopPage>(
context,
MaterialPageRoute<_PlayerVideoAndPopPage>(
builder: (BuildContext context) => _PlayerVideoAndPopPage(),
),
);
},
)
],
bottom: const TabBar(
isScrollable: true,
tabs: <Widget>[
Tab(
icon: Icon(Icons.cloud),
text: "Remote",
),
Tab(icon: Icon(Icons.insert_drive_file), text: "Asset"),
Tab(icon: Icon(Icons.list), text: "List example"),
],
),
),
body: TabBarView(
children: <Widget>[
_BumbleBeeRemoteVideo(),
_ButterFlyAssetVideo(),
_ButterFlyAssetVideoInList(),
],
),
),
);
}
}
class _ButterFlyAssetVideoInList extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListView(
children: <Widget>[
_ExampleCard(title: "Item a"),
_ExampleCard(title: "Item b"),
_ExampleCard(title: "Item c"),
_ExampleCard(title: "Item d"),
_ExampleCard(title: "Item e"),
_ExampleCard(title: "Item f"),
_ExampleCard(title: "Item g"),
Card(
child: Column(children: <Widget>[
Column(
children: <Widget>[
const ListTile(
leading: Icon(Icons.cake),
title: Text("Video video"),
),
Stack(
alignment: FractionalOffset.bottomRight
const FractionalOffset(-0.1, -0.1),
children: <Widget>[
_ButterFlyAssetVideo(),
Image.asset('assets/flutter-mark-square-64.png'),
]),
],
),
])),
_ExampleCard(title: "Item h"),
_ExampleCard(title: "Item i"),
_ExampleCard(title: "Item j"),
_ExampleCard(title: "Item k"),
_ExampleCard(title: "Item l"),
],
);
}
}
/// A filler card to show the video in a list of scrolling contents.
class _ExampleCard extends StatelessWidget {
const _ExampleCard({Key key, this.title}) : super(key: key);
final String title;
@override
Widget build(BuildContext context) {
return Card(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ListTile(
leading: const Icon(Icons.airline_seat_flat_angled),
title: Text(title),
),
ButtonBar(
children: <Widget>[
FlatButton(
child: const Text('BUY TICKETS'),
onPressed: () {
/* ... */
},
),
FlatButton(
child: const Text('SELL TICKETS'),
onPressed: () {
/* ... */
},
),
],
),
],
),
);
}
}
class _ButterFlyAssetVideo extends StatefulWidget {
@override
_ButterFlyAssetVideoState createState() => _ButterFlyAssetVideoState();
}
class _ButterFlyAssetVideoState extends State<_ButterFlyAssetVideo> {
VideoPlayerController _controller;
@override
void initState() {
super.initState();
_controller = VideoPlayerController.asset('assets/Butterfly-209.mp4');
_controller.addListener(() {
setState(() {});
});
_controller.setLooping(true);
_controller.initialize().then((_) => setState(() {}));
_controller.play();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
padding: const EdgeInsets.only(top: 20.0),
),
const Text('With assets mp4'),
Container(
padding: const EdgeInsets.all(20),
child: AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: Stack(
alignment: Alignment.bottomCenter,
children: <Widget>[
VideoPlayer(_controller),
_PlayPauseOverlay(controller: _controller),
VideoProgressIndicator(_controller, allowScrubbing: true),
],
),
),
),
],
),
);
}
}
class _BumbleBeeRemoteVideo extends StatefulWidget {
@override
_BumbleBeeRemoteVideoState createState() => _BumbleBeeRemoteVideoState();
}
class _BumbleBeeRemoteVideoState extends State<_BumbleBeeRemoteVideo> {
VideoPlayerController _controller;
Future<ClosedCaptionFile> _loadCaptions() async {
final String fileContents = await DefaultAssetBundle.of(context)
.loadString('assets/bumble_bee_captions.srt');
return SubRipCaptionFile(fileContents);
}
@override
void initState() {
super.initState();
_controller = VideoPlayerController.network(
'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4',
closedCaptionFile: _loadCaptions(),
);
_controller.addListener(() {
setState(() {});
});
_controller.setLooping(true);
_controller.initialize();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Column(
children: <Widget>[
Container(padding: const EdgeInsets.only(top: 20.0)),
const Text('With remote mp4'),
Container(
padding: const EdgeInsets.all(20),
child: AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: Stack(
alignment: Alignment.bottomCenter,
children: <Widget>[
VideoPlayer(_controller),
ClosedCaption(text: _controller.value.caption.text),
_PlayPauseOverlay(controller: _controller),
VideoProgressIndicator(_controller, allowScrubbing: true),
],
),
),
),
],
),
);
}
}
class _PlayPauseOverlay extends StatelessWidget {
const _PlayPauseOverlay({Key key, this.controller}) : super(key: key);
final VideoPlayerController controller;
@override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
AnimatedSwitcher(
duration: Duration(milliseconds: 50),
reverseDuration: Duration(milliseconds: 200),
child: controller.value.isPlaying
? SizedBox.shrink()
: Container(
color: Colors.black26,
child: Center(
child: Icon(
Icons.play_arrow,
color: Colors.white,
size: 100.0,
),
),
),
),
GestureDetector(
onTap: () {
controller.value.isPlaying ? controller.pause() : controller.play();
},
),
],
);
}
}
class _PlayerVideoAndPopPage extends StatefulWidget {
@override
_PlayerVideoAndPopPageState createState() => _PlayerVideoAndPopPageState();
}
class _PlayerVideoAndPopPageState extends State<_PlayerVideoAndPopPage> {
VideoPlayerController _videoPlayerController;
bool startedPlaying = false;
@override
void initState() {
super.initState();
_videoPlayerController =
VideoPlayerController.asset('assets/Butterfly-209.mp4');
_videoPlayerController.addListener(() {
if (startedPlaying && !_videoPlayerController.value.isPlaying) {
Navigator.pop(context);
}
});
}
@override
void dispose() {
_videoPlayerController.dispose();
super.dispose();
}
Future<bool> started() async {
await _videoPlayerController.initialize();
await _videoPlayerController.play();
startedPlaying = true;
return true;
}
@override
Widget build(BuildContext context) {
return Material(
elevation: 0,
child: Center(
child: FutureBuilder<bool>(
future: started(),
builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
if (snapshot.data == true) {
return AspectRatio(
aspectRatio: _videoPlayerController.value.aspectRatio,
child: VideoPlayer(_videoPlayerController),
);
} else {
return const Text('waiting for video to load');
}
},
),
),
);
}
}
flutter doctor -v[✓] Flutter (Channel master, 1.22.0-10.0.pre.451, on Mac OS X 10.15.7 19H2
x86_64, locale en-GB)
• Flutter version 1.22.0-10.0.pre.451 at
/Users/tahatesser/Code/flutter_master
• Framework revision 79400b2462 (46 minutes ago), 2020-10-01 09:06:46 -0400
• Engine revision 612acf349e
• Dart version 2.11.0 (build 2.11.0-180.0.dev)
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
• Android SDK at /Users/tahatesser/Code/sdk
• Platform android-30, build-tools 30.0.2
• ANDROID_HOME = /Users/tahatesser/Code/sdk
• Java binary at: /Applications/Android
Studio.app/Contents/jre/jdk/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build
1.8.0_242-release-1644-b3-6222593)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 12.0.1)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Xcode 12.0.1, Build version 12A7300
• CocoaPods version 1.9.3
[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio (version 4.0)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin version 50.0.1
• Dart plugin version 193.7547
• Java version OpenJDK Runtime Environment (build
1.8.0_242-release-1644-b3-6222593)
[✓] VS Code (version 1.49.2)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.15.0
[✓] Connected device (4 available)
• RMX2001 (mobile) • EUYTFEUSQSRGDA6D • android-arm64 • Android 10 (API 29)
• macOS (desktop) • macos • darwin-x64 • Mac OS X 10.15.7
19H2 x86_64
• Web Server (web) • web-server • web-javascript • Flutter Tools
• Chrome (web) • chrome • web-javascript • Google Chrome
85.0.4183.121
• No issues found! |
Fixed by #67705 |
maybe edit the docs that say it doesn't work in the simulator |
@real1900 I think that should wait until the skia surface update goes into the |
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of |
Steps to Reproduce
I'm trying to use flutter with a FlutterTexture in the iOS emulator and I'm repeatedly hitting:
I downloaded this sample:
https://github.com/flutter/plugins/tree/master/packages/video_player
and hit the play button. This also repeatedly shows this error and doesn't render video.
Logs
Flutter Doctor
The text was updated successfully, but these errors were encountered: