diff --git a/CHANGELOG.md b/CHANGELOG.md index bd6b245cc..4a44dee6c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ All notable changes to this project will be documented in this file. - Accessibility: apply bold font system setting +### Fixed + +- reading metadata for some MP4 files + ## [v1.7.4] - 2022-11-11 ### Added diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MetadataFetchHandler.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MetadataFetchHandler.kt index 70cc77434..d780a009e 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MetadataFetchHandler.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MetadataFetchHandler.kt @@ -124,6 +124,7 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler { val metadataMap = HashMap>() var foundExif = false var foundXmp = false + var foundMp4Uuid = false fun processXmp(xmpMeta: XMPMeta, dirMap: MutableMap, allowMultiple: Boolean = false) { if (foundXmp && !allowMultiple) return @@ -209,11 +210,13 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler { Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input -> val metadata = Helper.safeRead(input) foundExif = metadata.directories.any { it is ExifDirectoryBase && it.tagCount > 0 } + foundMp4Uuid = metadata.directories.any { it is Mp4UuidBoxDirectory && it.tagCount > 0 } val dirByName = metadata.directories.filter { (it.tagCount > 0 || it.errorCount > 0) && it !is FileTypeDirectory && it !is AviDirectory + && !(it is XmpDirectory && it.tagCount == 1 && it.containsTag(XmpDirectory.TAG_XMP_VALUE_COUNT)) }.groupBy { dir -> dir.name } for (dirEntry in dirByName) { @@ -388,11 +391,13 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler { } XMP.checkHeic(context, mimeType, uri, foundXmp, ::fallbackProcessXmp) - if (isLargeMp4(mimeType, sizeBytes)) { - XMP.checkMp4(context, mimeType, uri) { dirs -> - for (dir in dirs.filterIsInstance()) { - fallbackProcessXmp(dir.xmpMeta) - } + // `metadata-extractor` may fail to get UUID boxes for some MP4 files, + // so we always check with `mp4parser`, even for smaller files + XMP.checkMp4(context, mimeType, uri) { dirs -> + for (dir in dirs.filterIsInstance()) { + fallbackProcessXmp(dir.xmpMeta) + } + if (!foundMp4Uuid) { for (dir in dirs.filterIsInstance()) { processMp4Uuid(dir) } @@ -491,6 +496,7 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler { var flags = (metadataMap[KEY_FLAGS] ?: 0) as Int var foundExif = false var foundXmp = false + var foundMp4Uuid = false fun processXmp(xmpMeta: XMPMeta, allowMultiple: Boolean = false) { if (foundXmp && !allowMultiple) return @@ -543,6 +549,7 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler { Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input -> val metadata = Helper.safeRead(input) foundExif = metadata.directories.any { it is ExifDirectoryBase && it.tagCount > 0 } + foundMp4Uuid = metadata.directories.any { it is Mp4UuidBoxDirectory && it.tagCount > 0 } // File type for (dir in metadata.getDirectoriesOfType(FileTypeDirectory::class.java)) { @@ -695,11 +702,13 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler { } XMP.checkHeic(context, mimeType, uri, foundXmp, ::processXmp) - if (isLargeMp4(mimeType, sizeBytes)) { - XMP.checkMp4(context, mimeType, uri) { dirs -> - for (dir in dirs.filterIsInstance()) { - processXmp(dir.xmpMeta) - } + // `metadata-extractor` may fail to get UUID boxes for some MP4 files, + // so we always check with `mp4parser`, even for smaller files + XMP.checkMp4(context, mimeType, uri) { dirs -> + for (dir in dirs.filterIsInstance()) { + processXmp(dir.xmpMeta) + } + if (!foundMp4Uuid) { for (dir in dirs.filterIsInstance()) { processMp4Uuid(dir) } @@ -941,11 +950,11 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler { } XMP.checkHeic(context, mimeType, uri, foundXmp, ::processXmp) - if (isLargeMp4(mimeType, sizeBytes)) { - XMP.checkMp4(context, mimeType, uri) { dirs -> - for (dir in dirs.filterIsInstance()) { - processXmp(dir.xmpMeta) - } + // `metadata-extractor` may fail to get UUID boxes for some MP4 files, + // so we always check with `mp4parser`, even for smaller files + XMP.checkMp4(context, mimeType, uri) { dirs -> + for (dir in dirs.filterIsInstance()) { + processXmp(dir.xmpMeta) } } @@ -1026,11 +1035,11 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler { } XMP.checkHeic(context, mimeType, uri, foundXmp, ::processXmp) - if (isLargeMp4(mimeType, sizeBytes)) { - XMP.checkMp4(context, mimeType, uri) { dirs -> - for (dir in dirs.filterIsInstance()) { - processXmp(dir.xmpMeta) - } + // `metadata-extractor` may fail to get UUID boxes for some MP4 files, + // so we always check with `mp4parser`, even for smaller files + XMP.checkMp4(context, mimeType, uri) { dirs -> + for (dir in dirs.filterIsInstance()) { + processXmp(dir.xmpMeta) } } diff --git a/pubspec.lock b/pubspec.lock index bb827f20f..89102e1ca 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -8,6 +8,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "47.0.0" + _flutterfire_internals: + dependency: transitive + description: + name: _flutterfire_internals + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.8" analyzer: dependency: transitive description: @@ -60,7 +67,7 @@ packages: aves_report_platform: dependency: "direct main" description: - path: "plugins/aves_report_console" + path: "plugins/aves_report_crashlytics" relative: true source: path version: "0.0.1" @@ -74,7 +81,7 @@ packages: aves_services_platform: dependency: "direct main" description: - path: "plugins/aves_services_none" + path: "plugins/aves_services_google" relative: true source: path version: "0.0.1" @@ -120,6 +127,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.1.1" + cloud_firestore_platform_interface: + dependency: transitive + description: + name: cloud_firestore_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "5.8.5" + cloud_firestore_web: + dependency: transitive + description: + name: cloud_firestore_web + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.5" collection: dependency: "direct main" description: @@ -264,6 +285,41 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "6.1.2" + firebase_core: + dependency: transitive + description: + name: firebase_core + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.0" + firebase_core_platform_interface: + dependency: transitive + description: + name: firebase_core_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "4.5.2" + firebase_core_web: + dependency: transitive + description: + name: firebase_core_web + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" + firebase_crashlytics: + dependency: transitive + description: + name: firebase_crashlytics + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.5" + firebase_crashlytics_platform_interface: + dependency: transitive + description: + name: firebase_crashlytics_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "3.3.6" flex_color_picker: dependency: "direct main" description: @@ -342,6 +398,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.6.13" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.7" flutter_staggered_animations: dependency: "direct main" description: @@ -385,6 +448,41 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + google_api_availability: + dependency: transitive + description: + name: google_api_availability + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" + google_maps_flutter: + dependency: transitive + description: + name: google_maps_flutter + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.1" + google_maps_flutter_android: + dependency: transitive + description: + name: google_maps_flutter_android + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.3" + google_maps_flutter_ios: + dependency: transitive + description: + name: google_maps_flutter_ios + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.12" + google_maps_flutter_platform_interface: + dependency: transitive + description: + name: google_maps_flutter_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.4" highlight: dependency: transitive description: @@ -947,6 +1045,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + stream_transform: + dependency: transitive + description: + name: stream_transform + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" streams_channel: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 7bf42b4a4..a7a721bb2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -30,11 +30,11 @@ dependencies: aves_report: path: plugins/aves_report aves_report_platform: - path: plugins/aves_report_console + path: plugins/aves_report_crashlytics aves_services: path: plugins/aves_services aves_services_platform: - path: plugins/aves_services_none + path: plugins/aves_services_google charts_flutter: collection: connectivity_plus: