solid-software/flutter_vlc_player

flutter player issue Error during detachFromGLContext

Opened this issue · 1 comments

this issue keeps appearing in my firebase crashlyst console i am playing m3u8 file from network using flutter_vlc_player:
org.videolan.libvlc.AWindow$SurfaceTextureThread.detachFromGLContext

Fatal Exception: java.lang.RuntimeException
Error during detachFromGLContext (see logcat for details)
android.graphics.SurfaceTexture.detachFromGLContext (SurfaceTexture.java:274)
org.videolan.libvlc.AWindow$SurfaceTextureThread.detachFromGLContext (Unknown Source:40)
org.videolan.libvlc.AWindow$SurfaceTextureThread.access$1600
org.videolan.libvlc.AWindow.SurfaceTexture_detachFromGLContext (Unknown Source:2)

class LivestreamPlayer extends StatefulWidget {
final String downstreamUrl;
final String thumbnail;
final String postId;
final String pageType;
final int width;
final int height;

const LivestreamPlayer({
Key? key,
required this.downstreamUrl,
required this.thumbnail,
required this.postId,
required this.pageType,
required this.width,
required this.height,
}) : super(key: key);

@OverRide
LivestreamPlayerState createState() => LivestreamPlayerState();
}

class LivestreamPlayerState extends State {
static const _aspectRatio = 16 / 9;

late VlcPlayerController controller;

double sliderValue = 0.0;
double volumeValue = 50;
String position = '';
String duration = '';
int numberOfCaptions = 0;
int numberOfAudioTracks = 0;
bool validPosition = false;
String pauseState = "auto";

@OverRide
void initState() {
super.initState();
_initializeController();
}

_initializeController() async {
controller = VlcPlayerController.network(
widget.downstreamUrl,
hwAcc: HwAcc.auto,
autoPlay: false,
autoInitialize: true,
options: VlcPlayerOptions(
sout: VlcStreamOutputOptions(
[VlcStreamOutputOptions.soutMuxCaching(2000)]),
advanced: VlcAdvancedOptions([
VlcAdvancedOptions.networkCaching(2000),
VlcVideoOptions.dropLateFrames(true),
VlcAdvancedOptions.liveCaching(2000),
VlcAdvancedOptions.fileCaching(1000),
VlcAdvancedOptions.clockSynchronization(0),
VlcAdvancedOptions.clockJitter(0),
]),
extras: [
':network-caching=1000',
':clock-jitter=0',
':clock-synchro=0',
'--h264-fps=10'
],
),
);

controller.addListener(_listener);

}

void _listener() {
if (mounted) {
if (controller.value.isInitialized) {
final oPosition = controller.value.position;
final oDuration = controller.value.duration;
if (oDuration.inHours == 0) {
final strPosition = oPosition.toString().split('.').first;
final strDuration = oDuration.toString().split('.').first;
setState(() {
position =
"${strPosition.split(':')[1]}:${strPosition.split(':')[2]}";
duration =
"${strDuration.split(':')[1]}:${strDuration.split(':')[2]}";
});
} else {
setState(() {
position = oPosition.toString().split('.').first;
duration = oDuration.toString().split('.').first;
});
}
setState(() {
validPosition = oDuration.compareTo(oPosition) >= 0;
sliderValue = validPosition ? oPosition.inSeconds.toDouble() : 0;
});
setState(() {
numberOfCaptions = controller.value.spuTracksCount;
numberOfAudioTracks = controller.value.audioTracksCount;
});
}
}
}

@OverRide
void dispose() async {
if (controller.value.isInitialized) {
controller.removeListener(_listener);
controller.removeListener(_initListener);

  // Pause and stop the player before disposing
  await controller.stop();
  await controller.stopRendererScanning();
  await controller.dispose();
}
super.dispose();

}

@OverRide
void deactivate() async {
await controller.stop();
await controller.stopRendererScanning();
await controller.dispose();
super.deactivate();
}

void _setSoundVolume(double value) {
setState(() {
volumeValue = value;
});
controller.setVolume(volumeValue.toInt());
}

void _onSliderPositionChanged(double progress) {
setState(() {
sliderValue = progress.floor().toDouble();
});
controller.setTime(sliderValue.toInt() * Duration.millisecondsPerSecond);
}

void _resetPosition() {
setState(() {
sliderValue = 0.0;
});
controller.setTime(0);
}

@OverRide
Widget build(BuildContext context) {
return VisibilityDetector(
key: ObjectKey(widget.postId),
onVisibilityChanged: (visibilityInfo) async {
if (mounted) {
if (controller.value.isInitialized) {
if (visibilityInfo.visibleFraction > 0.1) {
if (!controller.value.isPlaying) {
if (mounted) {
await controller.play();
await controller.setVolume(100);
setState(() {
pauseState = "auto";
});
}
}
} else {
if (mounted) {
await controller.setVolume(0);
if (widget.pageType != 'scapes') {
await controller.pause();
_resetPosition();
} else {
await controller.stop();
}
}
}
}
}
},
child: SizedBox(
width: MediaQuery.of(context).size.width,
height: widget.pageType == 'scapes'
? MediaQuery.of(context).size.height - 60
: (1024 / 576) * MediaQuery.of(context).size.width,
child: Stack(
children: [
// Video player
SizedBox(
width: MediaQuery.of(context).size.width,
height: widget.pageType == 'scapes'
? MediaQuery.of(context).size.height - 60
: (1024 / 576) * MediaQuery.of(context).size.width,
child: VlcPlayer(
controller: controller,
aspectRatio: _aspectRatio,
placeholder: const Center(
child: CircularProgressIndicator(
strokeWidth: 1.0,
valueColor: AlwaysStoppedAnimation(
ThemeColors.accentColor,
),
),
),
),
),
ControlsOverlay(
controller: controller,
thumbnail: widget.thumbnail,
width: MediaQuery.of(context).size.width.toInt(),
height: widget.height,
pagetype: widget.pageType,
pauseState: pauseState,
),
Positioned(
bottom: 0,
left: 0,
right: 0,
child: SizedBox(
height: 10,
child: SliderTheme(
data: SliderThemeData(
trackHeight: 3,
thumbShape: SliderComponentShape.noThumb,
trackShape: SliderCustomTrackShape(),
),
child: Slider(
activeColor: ThemeColors.accentColor,
inactiveColor: Colors.black45,
value: sliderValue,
max: !validPosition
? 1.0
: controller!.value.duration.inSeconds.toDouble(),
onChanged:
validPosition ? _onSliderPositionChanged : null,
semanticFormatterCallback: (double newValue) {
return '${newValue.round()}';
},
),
),
),
),
Positioned(
bottom: 35,
right: 10,
child: GestureDetector(
onTap: () {
_setSoundVolume(volumeValue == 0 ? 100 : 0);
},
child: Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.5),
borderRadius: BorderRadius.circular(50),
),
child: Icon(
volumeValue == 0 ? Icons.volume_off : Icons.volume_up,
color: Colors.white,
),
),
),
),
],
),
));
}
}

class SliderCustomTrackShape extends RoundedRectSliderTrackShape {
@OverRide
Rect getPreferredRect({
required RenderBox parentBox,
Offset offset = Offset.zero,
required SliderThemeData sliderTheme,
bool isEnabled = false,
bool isDiscrete = false,
}) {
final double? trackHeight = sliderTheme.trackHeight;
final double trackLeft = offset.dx;
final double trackTop =
offset.dy + (parentBox.size.height - trackHeight!) / 2;
final double trackWidth = parentBox.size.width;
return Rect.fromLTWH(trackLeft, trackTop, trackWidth, trackHeight);
}
}

i am also getting this exact error when running the player on android 12