flutterexoplayerandroid-mediacodecflutter-video-playerflutter-exception

Flutter: Flutter Video Player cannot play a video file TWICE [Video controller cannot be used after disposed]~


I'm using Official Flutter Video Player Package for my flutter app, but the displayer is totally black and I also got this error while displaying it on the screen:

E/flutter (10774): [ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: A VideoPlayerController was used after being disposed.
E/flutter (10774): Once you have called dispose() on a VideoPlayerController, it can no longer be used.

Or Sometimes this:

V/LGCodecAdapter(  515): LG Codec Adapter start
I/ACodec  (  515): Now uninitialized
I/ACodec  (  515): onAllocateComponent
I/OMXClient(  515): MuxOMX ctor
I/ACodec  (  515): [OMX.qcom.video.decoder.avc] Now Loaded
I/ACodec  (  515): Now uninitialized
W/MediaCodecRenderer(  515): Failed to initialize decoder: OMX.qcom.video.decoder.avc
W/MediaCodecRenderer(  515):   android.media.MediaCodec$CodecException: Error 0xfffffff4
W/MediaCodecRenderer(  515):       at android.media.MediaCodec.native_configure(Native Method)
W/MediaCodecRenderer(  515):       at android.media.MediaCodec.configure(MediaCodec.java:1895)
W/MediaCodecRenderer(  515):       at com.google.android.exoplayer2.mediacodec.SynchronousMediaCodecAdapter.configure(SynchronousMediaCodecAdapter.java:61)
W/MediaCodecRenderer(  515):       at com.google.android.exoplayer2.video.MediaCodecVideoRenderer.configureCodec(MediaCodecVideoRenderer.java:620)
W/MediaCodecRenderer(  515):       at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.initCodec(MediaCodecRenderer.java:1110)
W/MediaCodecRenderer(  515):       at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.maybeInitCodecWithFallback(MediaCodecRenderer.java:1011)
W/MediaCodecRenderer(  515):       at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.maybeInitCodecOrBypass(MediaCodecRenderer.java:578)
W/MediaCodecRenderer(  515):       at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.onInputFormatChanged(MediaCodecRenderer.java:1420)
W/MediaCodecRenderer(  515):       at com.google.android.exoplayer2.video.MediaCodecVideoRenderer.onInputFormatChanged(MediaCodecVideoRenderer.java:694)
W/MediaCodecRenderer(  515):       at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.readToFlagsOnlyBuffer(MediaCodecRenderer.java:965)
W/MediaCodecRenderer(  515):       at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.render(MediaCodecRenderer.java:811)
W/MediaCodecRenderer(  515):       at com.google.android.exoplayer2.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:947)
W/MediaCodecRenderer(  515):       at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:477)
W/MediaCodecRenderer(  515):       at android.os.Handler.dispatchMessage(Handler.java:98)
W/MediaCodecRenderer(  515):       at android.os.Looper.loop(Looper.java:154)
W/MediaCodecRenderer(  515):       at android.os.HandlerThread.run(HandlerThread.java:61)
E/ExoPlayerImplInternal(  515): Playback error
E/ExoPlayerImplInternal(  515):   com.google.android.exoplayer2.ExoPlaybackException: MediaCodecVideoRenderer error, index=0, format=Format(1, null, null, video/avc, avc1.428028, -1, null, [1920, 1080, 28.391167], [-1, -1]), format_supported=YES
E/ExoPlayerImplInternal(  515):       at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:554)
E/ExoPlayerImplInternal(  515):       at android.os.Handler.dispatchMessage(Handler.java:98)
E/ExoPlayerImplInternal(  515):       at android.os.Looper.loop(Looper.java:154)
E/ExoPlayerImplInternal(  515):       at android.os.HandlerThread.run(HandlerThread.java:61)
E/ExoPlayerImplInternal(  515):   Caused by: com.google.android.exoplayer2.mediacodec.MediaCodecRenderer$DecoderInitializationException: Decoder init failed: OMX.qcom.video.decoder.avc, Format(1, null, null, video/avc, avc1.428028, -1, null, [1920, 1080, 28.391167], [-1, -1])

Here is the code for the player:

late final VideoPlayerController _videoCtrl;
late final Future<void> _videoCtrlInitializationFuture;

  @override
  void initState() {
    super.initState();

    _initVideoCtrl();
  }

  void _initVideoCtrl() {
    _videoCtrl = VideoPlayerController.file(widget.videoFile);
    _videoCtrlInitializationFuture = _videoCtrl.initialize();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: _videoCtrlInitializationFuture,
      builder: (BuildContext context, AsyncSnapshot videoCtrlInitSnap) {
        if (videoCtrlInitSnap.connectionState == ConnectionState.done) {
          return AspectRatio(
            aspectRatio: _videoCtrl.value.aspectRatio,
            child: VideoPlayer(_videoCtrl),
          );
        } else {
          return SizedBox.shrink();
        }
      },
    );
  }

  @override
  void dispose() {
    _videoCtrl.dispose();

    super.dispose();
  }

I try to use setState(() {}) and pass a new UniqueKey() to my VideoPlayer widget to create a new video, but the error appears, shows that the controller cannot be used after dispose, although is completely two different widgets.


Solution

  • The bug is caused by the targetSdkVersion in build.gradle file (app level), so I need to add an extra permission

    <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>

    in my manifest.xml file, also set the ios version in podfile to 10 (or above), and done!