Merge branch 'mobile_face' of https://github.com/ente-io/auth into mobile_face

This commit is contained in:
Neeraj Gupta 2024-04-30 14:48:28 +05:30
commit b1cbf8526b
3 changed files with 34 additions and 16 deletions

View file

@ -261,21 +261,21 @@ class _PersonClustersState extends State<PersonReviewClusterSuggestion> {
], ],
); );
// Precompute face thumbnails for next suggestions, in case there are // Precompute face thumbnails for next suggestions, in case there are
const precompute = 6; const precomputeSuggestions = 6;
const maxComputations = 10; const maxPrecomputations = 10;
int compCount = 0; int compCount = 0;
if (allSuggestions.length > currentSuggestionIndex + 1) { if (allSuggestions.length > currentSuggestionIndex + 1) {
for (final suggestion in allSuggestions.sublist( for (final suggestion in allSuggestions.sublist(
currentSuggestionIndex + 1, currentSuggestionIndex + 1,
min(allSuggestions.length, currentSuggestionIndex + precompute), min(allSuggestions.length, currentSuggestionIndex + precomputeSuggestions),
)) { )) {
final files = suggestion.filesInCluster; final files = suggestion.filesInCluster;
final clusterID = suggestion.clusterIDToMerge; final clusterID = suggestion.clusterIDToMerge;
for (final file in files.sublist(0, min(files.length, 8))) { for (final file in files.sublist(0, min(files.length, 8))) {
unawaited(PersonFaceWidget.precomputeFaceCrops(file, clusterID)); unawaited(PersonFaceWidget.precomputeNextFaceCrops(file, clusterID));
compCount++; compCount++;
if (compCount >= maxComputations) { if (compCount >= maxPrecomputations) {
break; break;
} }
} }
@ -300,6 +300,7 @@ class _PersonClustersState extends State<PersonReviewClusterSuggestion> {
child: PersonFaceWidget( child: PersonFaceWidget(
files[start + index], files[start + index],
clusterID: cluserId, clusterID: cluserId,
useFullFile: false,
), ),
), ),
), ),

View file

@ -19,6 +19,7 @@ class PersonFaceWidget extends StatelessWidget {
final EnteFile file; final EnteFile file;
final String? personId; final String? personId;
final int? clusterID; final int? clusterID;
final bool useFullFile;
// PersonFaceWidget constructor checks that both personId and clusterID are not null // PersonFaceWidget constructor checks that both personId and clusterID are not null
// and that the file is not null // and that the file is not null
@ -26,6 +27,7 @@ class PersonFaceWidget extends StatelessWidget {
this.file, { this.file, {
this.personId, this.personId,
this.clusterID, this.clusterID,
this.useFullFile = true,
Key? key, Key? key,
}) : assert( }) : assert(
personId != null || clusterID != null, personId != null || clusterID != null,
@ -33,7 +35,7 @@ class PersonFaceWidget extends StatelessWidget {
), ),
super(key: key); super(key: key);
static Future<void> precomputeFaceCrops(file, clusterID) async { static Future<void> precomputeNextFaceCrops(file, clusterID) async {
try { try {
final Face? face = await FaceMLDataDB.instance.getCoverFaceForPerson( final Face? face = await FaceMLDataDB.instance.getCoverFaceForPerson(
recentFileID: file.uploadedFileID!, recentFileID: file.uploadedFileID!,
@ -176,6 +178,13 @@ class PersonFaceWidget extends StatelessWidget {
faceCropCache.put(face.faceID, data); faceCropCache.put(face.faceID, data);
return data; return data;
} }
if (!useFullFile) {
final Uint8List? cachedFaceThumbnail =
faceCropThumbnailCache.get(face.faceID);
if (cachedFaceThumbnail != null) {
return cachedFaceThumbnail;
}
}
EnteFile? fileForFaceCrop = file; EnteFile? fileForFaceCrop = file;
if (face.fileID != file.uploadedFileID!) { if (face.fileID != file.uploadedFileID!) {
fileForFaceCrop = fileForFaceCrop =
@ -191,12 +200,17 @@ class PersonFaceWidget extends StatelessWidget {
{ {
face.faceID: face.detection.box, face.faceID: face.detection.box,
}, },
useFullFile: useFullFile,
), ),
); );
final Uint8List? computedCrop = result?[face.faceID]; final Uint8List? computedCrop = result?[face.faceID];
if (computedCrop != null) { if (computedCrop != null) {
if (useFullFile) {
faceCropCache.put(face.faceID, computedCrop); faceCropCache.put(face.faceID, computedCrop);
faceCropCacheFile.writeAsBytes(computedCrop).ignore(); faceCropCacheFile.writeAsBytes(computedCrop).ignore();
} else {
faceCropThumbnailCache.put(face.faceID, computedCrop);
}
} }
return computedCrop; return computedCrop;
} catch (e, s) { } catch (e, s) {

View file

@ -1,4 +1,4 @@
import "dart:io"; import "dart:io" show File;
import "package:flutter/foundation.dart"; import "package:flutter/foundation.dart";
import "package:photos/core/cache/lru_map.dart"; import "package:photos/core/cache/lru_map.dart";
@ -12,13 +12,16 @@ import "package:photos/utils/thumbnail_util.dart";
import "package:pool/pool.dart"; import "package:pool/pool.dart";
final LRUMap<String, Uint8List?> faceCropCache = LRUMap(1000); final LRUMap<String, Uint8List?> faceCropCache = LRUMap(1000);
final LRUMap<String, Uint8List?> faceCropThumbnailCache = LRUMap(1000);
final pool = Pool(10, timeout: const Duration(seconds: 15)); final pool = Pool(10, timeout: const Duration(seconds: 15));
Future<Map<String, Uint8List>?> getFaceCrops( Future<Map<String, Uint8List>?> getFaceCrops(
EnteFile file, EnteFile file,
Map<String, FaceBox> faceBoxeMap, Map<String, FaceBox> faceBoxeMap, {
bool useFullFile = true,
}
) async { ) async {
late String? imagePath; late String? imagePath;
if (file.fileType != FileType.video) { if (useFullFile && file.fileType != FileType.video) {
final File? ioFile = await getFile(file); final File? ioFile = await getFile(file);
if (ioFile == null) { if (ioFile == null) {
return null; return null;