From 0fc2710e62e7af054ee59eea91a5240ed7e83854 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Sun, 20 Aug 2023 20:04:04 +0200 Subject: [PATCH] #716 video: fail fast instead of corrupting file when editing fragmented mp4 --- .../deckers/thibault/aves/metadata/Mp4ParserHelper.kt | 10 +++++++--- lib/model/video/metadata.dart | 2 ++ lib/widgets/viewer/debug/metadata.dart | 2 +- plugins/aves_model/lib/src/video/keys.dart | 1 + plugins/aves_video_mpv/pubspec.lock | 8 ++++---- pubspec.lock | 8 ++++---- 6 files changed, 19 insertions(+), 12 deletions(-) diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/Mp4ParserHelper.kt b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/Mp4ParserHelper.kt index 8bb9e096c..75e74b7d7 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/Mp4ParserHelper.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/Mp4ParserHelper.kt @@ -52,6 +52,9 @@ object Mp4ParserHelper { } // creating `IsoFile` with a `File` or a `File.inputStream()` yields `No such device` IsoFile(channel, boxParser).use { isoFile -> + val fragmented = isoFile.boxes.any { box -> box is MovieFragmentBox || box is SegmentIndexBox } + if (fragmented) throw Exception("editing fragmented movies is not supported") + val lastContentBox = isoFile.boxes.reversed().firstOrNull { box -> when { box == isoFile.movieBox -> false @@ -60,7 +63,7 @@ object Mp4ParserHelper { else -> true } } - lastContentBox ?: throw Exception("failed to find last context box") + lastContentBox ?: throw Exception("failed to find last content box") val oldFileSize = isoFile.size var appendOffset = (isoFile.getBoxOffset { box -> box == lastContentBox })!! + lastContentBox.size @@ -97,7 +100,6 @@ object Mp4ParserHelper { if (trailing > 0) { addFreeBoxEdit(appendOffset, trailing) } - return edits } } @@ -277,7 +279,9 @@ object Mp4ParserHelper { // creating `IsoFile` with a `File` or a `File.inputStream()` yields `No such device` IsoFile(channel, metadataBoxParser()).use { isoFile -> val userDataBox = Path.getPath(isoFile.movieBox, UserDataBox.TYPE) - fields.putAll(extractBoxFields(userDataBox)) + if (userDataBox != null) { + fields.putAll(extractBoxFields(userDataBox)) + } } } } diff --git a/lib/model/video/metadata.dart b/lib/model/video/metadata.dart index d86b9dc77..56023b89b 100644 --- a/lib/model/video/metadata.dart +++ b/lib/model/video/metadata.dart @@ -356,6 +356,8 @@ class VideoMetadataFormatter { final sarDen = info[Keys.sarDen]; // skip common square pixels (1:1) if (sarNum != sarDen) save('SAR', '$sarNum:$sarDen'); + case Keys.segmentCount: + save('Segment Count', value); case Keys.sourceOshash: save('Source OSHash', value); case Keys.startMicros: diff --git a/lib/widgets/viewer/debug/metadata.dart b/lib/widgets/viewer/debug/metadata.dart index ccf4eb7d5..81963246e 100644 --- a/lib/widgets/viewer/debug/metadata.dart +++ b/lib/widgets/viewer/debug/metadata.dart @@ -149,7 +149,7 @@ class _MetadataTabState extends State { padding: const EdgeInsets.symmetric(horizontal: 8), child: SingleChildScrollView( scrollDirection: Axis.horizontal, - child: Text(data), + child: SelectableText(data), ), ) ], diff --git a/plugins/aves_model/lib/src/video/keys.dart b/plugins/aves_model/lib/src/video/keys.dart index 5f824d104..40a64c534 100644 --- a/plugins/aves_model/lib/src/video/keys.dart +++ b/plugins/aves_model/lib/src/video/keys.dart @@ -82,6 +82,7 @@ class Keys { static const streams = 'streams'; static const tbrDen = 'tbr_den'; static const tbrNum = 'tbr_num'; + static const segmentCount = 'segment_count'; static const streamType = 'type'; static const title = 'title'; static const timeBase = 'time_base'; diff --git a/plugins/aves_video_mpv/pubspec.lock b/plugins/aves_video_mpv/pubspec.lock index 3aed6d86f..a7006875d 100644 --- a/plugins/aves_video_mpv/pubspec.lock +++ b/plugins/aves_video_mpv/pubspec.lock @@ -172,10 +172,10 @@ packages: dependency: "direct main" description: name: media_kit - sha256: "0a89e7037002a62701ec319c375586849f9ef8e681820e1dd4a4ff7b843f7542" + sha256: d7a827080fb28f0ba4e8a7ab3f3e3f868fa817f0a94499640466ade84a1c31c9 url: "https://pub.dev" source: hosted - version: "1.1.4+1" + version: "1.1.5" media_kit_libs_android_video: dependency: "direct main" description: @@ -196,10 +196,10 @@ packages: dependency: "direct main" description: name: media_kit_video - sha256: e7fcbe426d42a78ad6696f8f557adb9cbdc012177829026d04992cc106a1c815 + sha256: d4143a96d97965d025bbb8b88db0ebf301e3c4cfa10c7e2ad7fd47c86a7febae url: "https://pub.dev" source: hosted - version: "1.1.5" + version: "1.1.6" meta: dependency: transitive description: diff --git a/pubspec.lock b/pubspec.lock index 3b0bdadc8..fb19c76ac 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -835,10 +835,10 @@ packages: dependency: transitive description: name: media_kit - sha256: "0a89e7037002a62701ec319c375586849f9ef8e681820e1dd4a4ff7b843f7542" + sha256: d7a827080fb28f0ba4e8a7ab3f3e3f868fa817f0a94499640466ade84a1c31c9 url: "https://pub.dev" source: hosted - version: "1.1.4+1" + version: "1.1.5" media_kit_libs_android_video: dependency: transitive description: @@ -859,10 +859,10 @@ packages: dependency: transitive description: name: media_kit_video - sha256: e7fcbe426d42a78ad6696f8f557adb9cbdc012177829026d04992cc106a1c815 + sha256: d4143a96d97965d025bbb8b88db0ebf301e3c4cfa10c7e2ad7fd47c86a7febae url: "https://pub.dev" source: hosted - version: "1.1.5" + version: "1.1.6" meta: dependency: transitive description: