wang-bin / fvp

Flutter video player plugin for all desktop+mobile platforms. download prebuilt examples from github actions. https://pub.dev/packages/fvp
BSD 3-Clause "New" or "Revised" License
126 stars 20 forks source link

[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Bad state: Future already completed #21

Closed tgc04042 closed 10 months ago

tgc04042 commented 10 months ago

Hello, First of all, thank you for your service. I used fvp 0.3.0 for video player in linux(ubuntu 20.04) desktop platform.

when I played a video, The app works fine, but sometimes I get errors and the app dies

glXGetCurrentDisplay:0xbfbc10, display from param: 0xbfbc10
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Bad state: Future already completed
[xcb] Unknown sequence number while processing reply
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
flutter_application_1: ../../src/xcb_io.c:641: _XReply: Assertion `!xcb_xlib_threads_sequence_lost' failed.
Lost connection to device.

Why does this error occur? I used video_player sample code

import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
import 'package:fvp/fvp.dart' as fvp;

void main() {
  fvp.registerWith(options: {
    'platforms': ['linux']
  });
  return runApp(
    const VideoApp(),
  );
}

/// Stateful widget to fetch and then display video content.
class VideoApp extends StatefulWidget {
  const VideoApp({super.key});

  @override
  _VideoAppState createState() => _VideoAppState();
}

class _VideoAppState extends State<VideoApp> {
  late VideoPlayerController _controller;

  @override
  void initState() {
    super.initState();
    _controller = VideoPlayerController.networkUrl(Uri.parse(
        'assets/test.mp4'))
      ..initialize().then((_) {
        // Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
        setState(() {});
      });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Video Demo',
      home: Scaffold(
        body: Center(
          child: _controller.value.isInitialized
              ? AspectRatio(
                  aspectRatio: _controller.value.aspectRatio,
                  child: VideoPlayer(_controller),
                )
              : Container(),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            setState(() {
              _controller.value.isPlaying
                  ? _controller.pause()
                  : _controller.play();
            });
          },
          child: Icon(
            _controller.value.isPlaying ? Icons.pause : Icons.play_arrow,
          ),
        ),
      ),
    );
  }

  @override
  void dispose() {
    super.dispose();
    _controller.dispose();
  }
}
wang-bin commented 10 months ago

I guess flutter must call XInitThreads() before any x11 call because it's x11 Display is also used by vaapi decoder in decoder thread. But I don't see it in flutter engine source code.

What about adding this at the bottom of fvp_plugin.cc? I'm not sure if it works because it will be called too early.

__attribute__((constructor, used)) static void init_xlib() {
    XInitThreads();
}

or you can try to add XInitThreads(); in the first line of int main(int argc, char** argv) in main.cc

You can also print the return value of XInitThreads

wang-bin commented 10 months ago

最新发布的版本加了这部分代码,你试下有没有效果

tgc04042 commented 10 months ago

I'm sorry for the late relpy..

That error no longer appear! Thank you for solving this problem!!