[mob][photos] Handle/fix issues with media dimensions (#2580)

## Description

- Stopped updating image width and height in public metadata since the
these could be incorrect (width and height inverted to be precise).
- Parse `rotation` metadata from video metadata when parsing video
properties with `ffprobe` to get the correct video width and height
considering `rotation`.
This commit is contained in:
Ashil
2024-08-01 14:46:02 +05:30
committed by GitHub
3 changed files with 51 additions and 36 deletions

View File

@@ -28,7 +28,7 @@ class FFProbeKeys {
static const date = 'date';
static const disposition = 'disposition';
static const duration = 'duration';
static const quickTimeLocation ="com.apple.quicktime.location.ISO6709";
static const quickTimeLocation = "com.apple.quicktime.location.ISO6709";
static const durationMicros = 'duration_us';
static const encoder = 'encoder';
static const extraDataSize = 'extradata_size';
@@ -70,6 +70,8 @@ class FFProbeKeys {
static const vendorId = 'vendor_id';
static const width = 'width';
static const xiaomiSlowMoment = 'com.xiaomi.slow_moment';
static const sideDataList = 'side_data_list';
static const rotation = 'rotation';
}
class MediaStreamTypes {

View File

@@ -18,20 +18,56 @@ class FFProbeProps {
String? bitrate;
String? majorBrand;
String? fps;
String? codecWidth;
String? codecHeight;
String? _codecWidth;
String? _codecHeight;
int? _rotation;
// dot separated bitrate, fps, codecWidth, codecHeight. Ignore null value
String get videoInfo {
final List<String> info = [];
if (bitrate != null) info.add('$bitrate');
if (fps != null) info.add('ƒ/$fps');
if (codecWidth != null && codecHeight != null) {
info.add('$codecWidth x $codecHeight');
if (_codecWidth != null && _codecHeight != null) {
info.add('$_codecWidth x $_codecHeight');
}
return info.join(' * ');
}
int? get width {
if (_codecWidth == null || _codecHeight == null) return null;
final intCodecWidth = int.tryParse(_codecWidth!);
if (_rotation == null) {
return intCodecWidth;
} else {
if ((_rotation! ~/ 90).isEven) {
return intCodecWidth;
} else {
return int.tryParse(_codecHeight!);
}
}
}
int? get height {
if (_codecWidth == null || _codecHeight == null) return null;
final intCodecHeight = int.tryParse(_codecHeight!);
if (_rotation == null) {
return intCodecHeight;
} else {
if ((_rotation! ~/ 90).isEven) {
return intCodecHeight;
} else {
return int.tryParse(_codecWidth!);
}
}
}
double? get aspectRatio {
if (width == null || height == null || height == 0 || width == 0) {
return null;
}
return width! / height!;
}
// toString() method
@override
String toString() {
@@ -132,11 +168,13 @@ class FFProbeProps {
result.fps = _formatFPS(stream[key]);
parsedData[key] = result.fps;
} else if (key == FFProbeKeys.codedWidth) {
result.codecWidth = stream[key].toString();
parsedData[key] = result.codecWidth;
result._codecWidth = stream[key].toString();
parsedData[key] = result._codecWidth;
} else if (key == FFProbeKeys.codedHeight) {
result.codecHeight = stream[key].toString();
parsedData[key] = result.codecHeight;
result._codecHeight = stream[key].toString();
parsedData[key] = result._codecHeight;
} else if (key == FFProbeKeys.sideDataList) {
result._rotation = stream[key][0][FFProbeKeys.rotation];
}
}
}

View File

@@ -14,8 +14,6 @@ import 'package:photos/events/files_updated_event.dart';
import 'package:photos/events/local_photos_updated_event.dart';
import "package:photos/models/file/extensions/file_props.dart";
import 'package:photos/models/file/file.dart';
import "package:photos/models/metadata/file_magic.dart";
import "package:photos/services/file_magic_service.dart";
import "package:photos/ui/actions/file/file_actions.dart";
import 'package:photos/ui/common/loading_widget.dart';
import 'package:photos/utils/file_util.dart';
@@ -31,12 +29,12 @@ class ZoomableImage extends StatefulWidget {
const ZoomableImage(
this.photo, {
Key? key,
super.key,
this.shouldDisableScroll,
required this.tagPrefix,
this.backgroundDecoration,
this.shouldCover = false,
}) : super(key: key);
});
@override
State<ZoomableImage> createState() => _ZoomableImageState();
@@ -359,29 +357,6 @@ class _ZoomableImageState extends State<ZoomableImage> {
if (finalImageInfo == null && canUpdateMetadata && !_photo.hasDimensions) {
finalImageInfo = await getImageInfo(finalImageProvider);
}
if (finalImageInfo != null && canUpdateMetadata) {
_updateAspectRatioIfNeeded(_photo, finalImageInfo).ignore();
}
}
// Fallback logic to finish back fill and update aspect
// ratio if needed.
Future<void> _updateAspectRatioIfNeeded(
EnteFile enteFile,
ImageInfo imageInfo,
) async {
final int h = imageInfo.image.height, w = imageInfo.image.width;
if (h != enteFile.height || w != enteFile.width) {
final logMessage =
'Updating aspect ratio for from ${enteFile.height}x${enteFile.width} to ${h}x$w';
_logger.info(logMessage);
await FileMagicService.instance.updatePublicMagicMetadata([
enteFile,
], {
heightKey: h,
widthKey: w,
});
}
}
bool _isGIF() => _photo.displayName.toLowerCase().endsWith(".gif");