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 @@

- Version 3.1.6 + Version 3.1.7 Flutter Platforms Wiki 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"