diff --git a/mobile/lib/db/ml/clip_db.dart b/mobile/lib/db/ml/clip_db.dart index c5509081a4..3ac64477ec 100644 --- a/mobile/lib/db/ml/clip_db.dart +++ b/mobile/lib/db/ml/clip_db.dart @@ -1,6 +1,7 @@ import "dart:io"; import "dart:typed_data"; +import "package:logging/logging.dart"; import "package:photos/core/event_bus.dart"; import "package:photos/db/ml/db.dart"; import "package:photos/db/ml/db_fields.dart"; @@ -19,6 +20,7 @@ extension ClipDB on MLDataDB { } Future> getAllClipVectors() async { + Logger("ClipDB").info("reading all embeddings from DB"); final db = await MLDataDB.instance.asyncDB; final results = await db.getAll('SELECT * FROM $clipTable'); return _convertToVectors(results); diff --git a/mobile/lib/db/ml/db.dart b/mobile/lib/db/ml/db.dart index 0d4b0c2772..89c4860506 100644 --- a/mobile/lib/db/ml/db.dart +++ b/mobile/lib/db/ml/db.dart @@ -30,6 +30,8 @@ class MLDataDB { static const _databaseName = "ente.ml.db"; + static Logger get logger => _logger; + // static const _databaseVersion = 1; MLDataDB._privateConstructor(); diff --git a/mobile/lib/models/file/file.dart b/mobile/lib/models/file/file.dart index 74affd9844..a11d2071a9 100644 --- a/mobile/lib/models/file/file.dart +++ b/mobile/lib/models/file/file.dart @@ -2,7 +2,6 @@ import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:logging/logging.dart'; -import "package:motion_photos/src/xmp_extractor.dart"; import 'package:path/path.dart'; import 'package:photo_manager/photo_manager.dart'; import 'package:photos/core/configuration.dart'; @@ -185,8 +184,7 @@ class EnteFile { if (mediaUploadData.isPanorama != true) { try { - final xmpData = XMPExtractor() - .extract(mediaUploadData.sourceFile!.readAsBytesSync()); + final xmpData = await getXmp(mediaUploadData.sourceFile!); mediaUploadData.isPanorama = checkPanoramaFromXMP(xmpData); } catch (_) {} diff --git a/mobile/lib/services/machine_learning/semantic_search/semantic_search_service.dart b/mobile/lib/services/machine_learning/semantic_search/semantic_search_service.dart index 8885829743..e6eb268f52 100644 --- a/mobile/lib/services/machine_learning/semantic_search/semantic_search_service.dart +++ b/mobile/lib/services/machine_learning/semantic_search/semantic_search_service.dart @@ -108,8 +108,12 @@ class SemanticSearchService { } Future> getClipVectors() async { - _logger.info("Pulling cached clip embeddings"); + if (_cachedImageEmbeddingVectors != null) { + return _cachedImageEmbeddingVectors!; + } _cachedImageEmbeddingVectors ??= MLDataDB.instance.getAllClipVectors(); + _logger.info("read all embeddings from DB"); + return _cachedImageEmbeddingVectors!; } diff --git a/mobile/lib/utils/exif_util.dart b/mobile/lib/utils/exif_util.dart index 5459cd543f..3ab9b6e443 100644 --- a/mobile/lib/utils/exif_util.dart +++ b/mobile/lib/utils/exif_util.dart @@ -10,6 +10,7 @@ import "package:ffmpeg_kit_flutter_min/media_information_session.dart"; import "package:flutter/foundation.dart"; import 'package:intl/intl.dart'; import 'package:logging/logging.dart'; +import "package:motion_photos/src/xmp_extractor.dart"; import "package:photos/models/ffmpeg/ffprobe_props.dart"; import 'package:photos/models/file/file.dart'; import "package:photos/models/location/location.dart"; @@ -56,6 +57,19 @@ Future?> getExifFromSourceFile(File originFile) async { } } +Future> getXmp(File file) async { + return Computer.shared().compute( + _getXMPComputer, + param: {"file": file}, + taskName: "getXMPAsync", + ); +} + +Map _getXMPComputer(Map args) { + final File originalFile = args["file"] as File; + return XMPExtractor().extract(originalFile.readAsBytesSync()); +} + Future getVideoPropsAsync(File originalFile) async { try { final stopwatch = Stopwatch()..start(); diff --git a/mobile/lib/utils/file_uploader_util.dart b/mobile/lib/utils/file_uploader_util.dart index d06234bcf6..0500b6947f 100644 --- a/mobile/lib/utils/file_uploader_util.dart +++ b/mobile/lib/utils/file_uploader_util.dart @@ -160,8 +160,11 @@ Future _getMediaUploadDataFromAssetFile(EnteFile file) async { int? motionPhotoStartingIndex; if (Platform.isAndroid && asset.type == AssetType.image) { try { - motionPhotoStartingIndex = - (await MotionPhotos(sourceFile.path).getMotionVideoIndex())?.start; + motionPhotoStartingIndex = await Computer.shared().compute( + motionVideoIndex, + param: {'path': sourceFile.path}, + taskName: 'motionPhotoIndex', + ); } catch (e) { _logger.severe('error while detecthing motion photo start index', e); } @@ -177,6 +180,11 @@ Future _getMediaUploadDataFromAssetFile(EnteFile file) async { ); } +Future motionVideoIndex(Map args) async { + final String path = args['path']; + return (await MotionPhotos(path).getMotionVideoIndex())?.start; +} + Future _computeZip(Map args) async { final String zipPath = args['zipPath']; final String imagePath = args['imagePath']; diff --git a/mobile/lib/utils/panorama_util.dart b/mobile/lib/utils/panorama_util.dart index 909801a546..cb6ba57006 100644 --- a/mobile/lib/utils/panorama_util.dart +++ b/mobile/lib/utils/panorama_util.dart @@ -18,8 +18,7 @@ Future checkIfPanorama(EnteFile enteFile) async { } try { final result = XMPExtractor().extract(file.readAsBytesSync()); - if (result["GPano:ProjectionType"] == "cylindrical" || - result["GPano:ProjectionType"] == "equirectangular") { + if (checkPanoramaFromXMP(result)) { return true; } } catch (_) {} @@ -30,7 +29,7 @@ Future checkIfPanorama(EnteFile enteFile) async { return element?.printable == "6"; } -bool? checkPanoramaFromXMP(Map xmpData) { +bool checkPanoramaFromXMP(Map xmpData) { if (xmpData["GPano:ProjectionType"] == "cylindrical" || xmpData["GPano:ProjectionType"] == "equirectangular") { return true;