Skip to content
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

Closed
nkleenest opened this issue Feb 12, 2018 · 25 comments
Closed

iOS video_player sample doesn't show video in the emulator #14647

nkleenest opened this issue Feb 12, 2018 · 25 comments
Labels
a: video Video playback customer: crowd Affects or could affect many people, though not necessarily a specific customer. e: device-specific Only manifests on certain devices engine flutter/engine repository. See also e: labels. found in release: 1.22 Found to occur in 1.22 has reproducible steps The issue has been confirmed reproducible and is ready to work on p: video_player The Video Player plugin package flutter/packages repository. See also p: labels. platform-ios iOS applications specifically

Comments

@nkleenest
Copy link

nkleenest commented Feb 12, 2018

Steps to Reproduce

I'm trying to use flutter with a FlutterTexture in the iOS emulator and I'm repeatedly hitting:

[VERBOSE-1:ios_external_texture_gl.mm(37)] Failed to create GLES texture cache: -6661

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

Launching lib/main.dart on iPhone X in debug mode...
Running Xcode build...
Syncing files to device iPhone X...
[VERBOSE-1:ios_external_texture_gl.mm(37)] Failed to create GLES texture cache: -6661
[VERBOSE-1:ios_external_texture_gl.mm(37)] Failed to create GLES texture cache: -6661
[VERBOSE-1:ios_external_texture_gl.mm(37)] Failed to create GLES texture cache: -6661
...

Flutter Doctor

[✓] Flutter (on Mac OS X 10.13.2 17C205, locale en-US, channel dev)
    • Flutter version 0.0.25-pre.5 at [redacted]
    • Framework revision 4ae1b5f415 (5 days ago), 2018-02-07 15:18:04 -0800
    • Engine revision 9bc2efdf47
    • Tools Dart version 2.0.0-dev.19.0
    • Engine Dart version 2.0.0-edge.ea91bc9888184d5a2fc309c36656fdd325ef503c

[✓] Android toolchain - develop for Android devices (Android SDK 26.0.2)
    • Android SDK at [redacted]
    • Android NDK location not configured (optional; useful for native profiling support)
    • Platform android-26, build-tools 26.0.2
    • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-915-b08)

[✓] iOS toolchain - develop for iOS devices (Xcode 9.2)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 9.2, Build version 9C40b
    • ios-deploy 1.9.2
    • CocoaPods version 1.4.0

[✓] Android Studio (version 3.0)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-915-b08)

[✓] IntelliJ IDEA Community Edition (version 2017.3.4)
    • Flutter plugin version 21.2.3
    • Dart plugin version 173.4548.30

[✓] Connected devices
    • iPhone X • 0094171F-87B1-4C62-8DC5-8AE28FC5800A • ios • iOS 11.2 (simulator)

• No issues found!
@chinmaygarde
Copy link
Member

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.

@chinmaygarde chinmaygarde added platform-ios iOS applications specifically engine flutter/engine repository. See also e: labels. labels Feb 12, 2018
@mravn-google
Copy link
Contributor

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.

@chinmaygarde
Copy link
Member

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).

@bhlvoong
Copy link

At the very least, the README should warn users that iOS simulator is not supported.

@fuzzybinary
Copy link
Contributor

Also for us poor package developers, please put a comment in TextureRegistry to the same effect ;)

@nadenf
Copy link

nadenf commented Jun 9, 2018

This cost me quite a few hours. Please, please update the documentation.

@chinmaygarde
Copy link
Member

chinmaygarde commented Jun 11, 2018

I added a note to the README.

@zoechi
Copy link
Contributor

zoechi commented Jul 19, 2018

#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.

@esbenr
Copy link

esbenr commented Aug 8, 2018

Hi, this is becomming a deal breaker to our dev cycle/pace.
Are there anyone looking into this?
I'm not familiar enough with flutter to do it my self, yet.

So, os there an ETA?

Thanks.

@zoechi
Copy link
Contributor

zoechi commented Dec 4, 2018

@chinmaygarde are there plans to do something or is this just not technically feasible?

@mrgoonie
Copy link

Just be curious, any plan to make the video work on iOS Simulator guys?

@thosakwe
Copy link

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.

@lattice0
Copy link

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

@marcosradix
Copy link

I have erro every time I tring to run in my device
flutter: The following NoSuchMethodError was thrown while handling a gesture:
flutter: The getter '_duration' was called on null.
flutter: Receiver: null
flutter: Tried calling: _duration
flutter:
flutter: When the exception was thrown, this was the stack:
flutter: #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
flutter: #1 Duration.>= (dart:core/duration.dart:175:63)
flutter: #2 _CupertinoControlsState._playPause (package:chewie/src/cupertino_controls.dart:498:45)
flutter: #3 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:182:24)
flutter: #4 TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:486:11)
flutter: #5 BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:264:5)
flutter: #6 BaseTapGestureRecognizer.acceptGesture (package:flutter/src/gestures/tap.dart:236:7)
flutter: #7 GestureArenaManager.sweep (package:flutter/src/gestures/arena.dart:156:27)
flutter: #8 GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:222:20)
flutter: #9 GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:198:22)
flutter: #10 GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:156:7)
flutter: #11 GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:102:7)
flutter: #12 GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:86:7)
flutter: #16 _invoke1 (dart:ui/hooks.dart:273:10)
flutter: #17 _dispatchPointerDataPacket (dart:ui/hooks.dart:182:5)
flutter: (elided 3 frames from package dart:async)
flutter:
flutter: Handler: "onTap"
flutter: Recognizer:
flutter: TapGestureRecognizer#33f47
flutter: ═════════════════════════

@jmagman jmagman added this to Awaiting triage in Mobile - iOS engine review Feb 25, 2020
@VladyslavBondarenko VladyslavBondarenko added customer: crowd Affects or could affect many people, though not necessarily a specific customer. plugin labels Mar 13, 2020
@gaaclarke
Copy link
Member

#43028 would allow this

@gaaclarke gaaclarke moved this from Awaiting triage to Engineer reviewed in Mobile - iOS engine review Apr 7, 2020
@chinmaygarde
Copy link
Member

#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.

@chinmaygarde
Copy link
Member

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.

@lattice0
Copy link

@chinmaygarde this is worse as I use macOS on a VM in Ubuntu. I guess Metal wont work...
:c

@chinmaygarde
Copy link
Member

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.

@ventr1x

This comment has been minimized.

@TahaTesser
Copy link
Member

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!

@TahaTesser TahaTesser added found in release: 1.22 Found to occur in 1.22 has reproducible steps The issue has been confirmed reproducible and is ready to work on p: first party labels Oct 1, 2020
@dnfield
Copy link
Contributor

dnfield commented Oct 9, 2020

Fixed by #67705

@dnfield dnfield closed this as completed Oct 9, 2020
@real1900
Copy link

maybe edit the docs that say it doesn't work in the simulator

@yaizudamashii
Copy link

yaizudamashii commented Jan 11, 2021

@real1900 I think that should wait until the skia surface update goes into the stable channel. I wanted to make screen captures of video but I had to switch to build with master channel for Flutter

@github-actions
Copy link

github-actions bot commented Aug 7, 2021

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 flutter doctor -v and a minimal reproduction of the issue.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 7, 2021
@flutter-triage-bot flutter-triage-bot bot added the package flutter/packages repository. See also p: labels. label Jul 5, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
a: video Video playback customer: crowd Affects or could affect many people, though not necessarily a specific customer. e: device-specific Only manifests on certain devices engine flutter/engine repository. See also e: labels. found in release: 1.22 Found to occur in 1.22 has reproducible steps The issue has been confirmed reproducible and is ready to work on p: video_player The Video Player plugin package flutter/packages repository. See also p: labels. platform-ios iOS applications specifically
Projects
Mobile - iOS engine review
  
Engineer reviewed
Development

No branches or pull requests