From 1395cfd4141bfa5b7a00b74caa2251e75db7915f Mon Sep 17 00:00:00 2001
From: RarDog
Date: Fri, 4 Sep 2026 23:17:15 +0300
Subject: [PATCH] fix: remove unsafe libmpv setProperty FFI calls causing
SIGSEGV crash (v3.1.7)
---
README.md | 2 +-
lib/app/app_version.dart | 4 +-
lib/app/changelog.dart | 9 +++++
.../widgets/post_media_viewer.dart | 39 ++++++++++---------
pubspec.yaml | 2 +-
5 files changed, 33 insertions(+), 23 deletions(-)
diff --git a/README.md b/README.md
index fb6383a..1ae3770 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@
-
+
diff --git a/lib/app/app_version.dart b/lib/app/app_version.dart
index 7d9c00d..f847632 100644
--- a/lib/app/app_version.dart
+++ b/lib/app/app_version.dart
@@ -1,3 +1,3 @@
-const appDisplayVersion = '3.1.6';
-const appBuildNumber = 67;
+const appDisplayVersion = '3.1.7';
+const appBuildNumber = 68;
const appReleaseChannel = 'Stable';
diff --git a/lib/app/changelog.dart b/lib/app/changelog.dart
index 80e3994..9f3be11 100644
--- a/lib/app/changelog.dart
+++ b/lib/app/changelog.dart
@@ -1,4 +1,13 @@
const lunarisChangelog = [
+ LunarisChange(
+ version: '3.1.7',
+ title: 'Устранение критического сбоя при открытии видеопоста (SIGSEGV в libmpv)',
+ bullets: [
+ 'Устранение нативного вылета: полностью удалены небезопасные прямые FFI-вызовы setProperty к mpv, приводившие к немедленному падению приложения на Android при инициализации видео.',
+ 'Безопасная конфигурация декодирования: перевод настроек аппаратного ускорения и фоллбэка кодеков на официальный типобезопасный VideoControllerConfiguration (media_kit_video).',
+ 'Надежный фоллбэк при редких ошибках кодека: при несовместимости аппаратного декодера плеер бесшовно переключается на программный FFmpeg-декодер без риска краша.',
+ ],
+ ),
LunarisChange(
version: '3.1.6',
title: 'Надежный полноэкранный плеер, сохранение провайдеров в поиске, громкость и устранение ошибки кодека',
diff --git a/lib/features/post/presentation/widgets/post_media_viewer.dart b/lib/features/post/presentation/widgets/post_media_viewer.dart
index 419b993..a9bf3f5 100644
--- a/lib/features/post/presentation/widgets/post_media_viewer.dart
+++ b/lib/features/post/presentation/widgets/post_media_viewer.dart
@@ -75,6 +75,7 @@ class _PostMediaViewerState extends State
late double _currentVolume;
String? _videoError;
bool _retriedFormatError = false;
+ bool _softwareDecodingFallback = false;
Timer? _hideTimer;
StreamSubscription? _errorSubscription;
StreamSubscription? _positionSubscription;
@@ -105,6 +106,7 @@ class _PostMediaViewerState extends State
_videoIndex = 0;
_videoError = null;
_retriedFormatError = false;
+ _softwareDecodingFallback = false;
_imageUrls = _buildImageUrls(widget.post);
_videoUrls = _buildVideoUrls(widget.post);
if (_isVideo(widget.post) && _videoUrls.isNotEmpty) {
@@ -359,13 +361,13 @@ class _PostMediaViewerState extends State
void _initializeVideo() {
MediaKit.ensureInitialized();
_player = Player();
- _controller = VideoController(_player!);
- try {
- final native = _player!.platform as dynamic;
- native?.setProperty('hwdec', 'auto-safe', waitForInitialization: false);
- native?.setProperty('vd-lavc-software-fallback', 'yes', waitForInitialization: false);
- native?.setProperty('vd-lavc-check-hw-profile', 'yes', waitForInitialization: false);
- } catch (_) {}
+ _controller = VideoController(
+ _player!,
+ configuration: VideoControllerConfiguration(
+ enableHardwareAcceleration: !_softwareDecodingFallback,
+ hwdec: _softwareDecodingFallback ? 'no' : 'auto-safe',
+ ),
+ );
_applyVolume();
_player!.setPlaylistMode(
_loopVideo ? PlaylistMode.single : PlaylistMode.none,
@@ -437,14 +439,12 @@ class _PostMediaViewerState extends State
lower.contains('stream format not recognized') ||
lower.contains('failed to recognize file format'))) {
_retriedFormatError = true;
- try {
- final native = _player?.platform as dynamic;
- await native?.setProperty('hwdec', 'no', waitForInitialization: false);
- } catch (_) {}
- await Future.delayed(const Duration(milliseconds: 300));
- if (mounted && _player != null) {
+ _softwareDecodingFallback = true;
+ _disposeVideo();
+ await Future.delayed(const Duration(milliseconds: 250));
+ if (mounted) {
_videoIndex = 0;
- await _openVideo(play: play);
+ _initializeVideo();
return;
}
}
@@ -456,11 +456,12 @@ class _PostMediaViewerState extends State
Future _retryVideo() async {
_videoIndex = 0;
_retriedFormatError = false;
- try {
- final native = _player?.platform as dynamic;
- await native?.setProperty('hwdec', 'no', waitForInitialization: false);
- } catch (_) {}
- await _openVideo(play: true);
+ _softwareDecodingFallback = true;
+ _disposeVideo();
+ await Future.delayed(const Duration(milliseconds: 150));
+ if (mounted) {
+ _initializeVideo();
+ }
}
void _disposeVideo() {
diff --git a/pubspec.yaml b/pubspec.yaml
index 0a56959..ecb8c24 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,7 +1,7 @@
name: gel_rule_app
description: Local backend/core layer for a Flutter booru browser app.
publish_to: "none"
-version: 3.1.6+67
+version: 3.1.7+68
environment:
sdk: ">=3.3.0 <4.0.0"