forked from Nexus/nexus
use another avif library that works on aarch64-linux
This commit is contained in:
parent
72c5e7d819
commit
8180338d99
12 changed files with 93 additions and 196 deletions
|
|
@ -1,8 +1,10 @@
|
|||
import "dart:async";
|
||||
import "dart:io";
|
||||
import "dart:isolate";
|
||||
import "dart:ui" as ui;
|
||||
|
||||
import "package:avif_native/avif_native.dart";
|
||||
import "package:flutter/widgets.dart";
|
||||
import "package:flutter_avif/flutter_avif.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:nexus/controllers/client.dart";
|
||||
import "package:nexus/models/requests/download_media.dart";
|
||||
|
|
@ -24,13 +26,9 @@ class MxcImage(final WidgetRef ref, final DownloadMediaRequest request)
|
|||
final bytes = await File(file.path).readAsBytes();
|
||||
|
||||
// Flutter can't decode AVIF on Linux/Windows (or older Android/iOS), so we do it ourselves
|
||||
final avifType = isAvifFile(bytes.sublist(0, 16.clamp(0, bytes.length)));
|
||||
if (avifType != .unknown) {
|
||||
final codec = avifType == .avif
|
||||
? SingleFrameAvifCodec(bytes: bytes)
|
||||
: MultiFrameAvifCodec(key: hashCode, avifBytes: bytes);
|
||||
await codec.ready();
|
||||
return AvifCodecAdapter(codec);
|
||||
if (String.fromCharCodes(bytes.skip(4).take(8))
|
||||
case "ftypavif" || "ftypavis") {
|
||||
return AvifCodec(await Isolate.run(() => decodeAvif(bytes)));
|
||||
}
|
||||
|
||||
return decode(await .fromUint8List(bytes));
|
||||
|
|
@ -44,21 +42,33 @@ class MxcImage(final WidgetRef ref, final DownloadMediaRequest request)
|
|||
int get hashCode => request.hashCode;
|
||||
}
|
||||
|
||||
class AvifCodecAdapter(final AvifCodec codec) implements ui.Codec {
|
||||
@override
|
||||
int get frameCount => codec.frameCount;
|
||||
class AvifCodec(final AvifImageData data) implements ui.Codec {
|
||||
var _frameIndex = 0;
|
||||
|
||||
@override
|
||||
int get repetitionCount => frameCount > 1 ? -1 : 0;
|
||||
int get frameCount => data.frames.length;
|
||||
|
||||
// libavif uses -2 for unknown, which we treat as infinite like browsers do
|
||||
@override
|
||||
int get repetitionCount =>
|
||||
data.repetitionCount < 0 ? -1 : data.repetitionCount;
|
||||
|
||||
@override
|
||||
Future<ui.FrameInfo> getNextFrame() async {
|
||||
final frame = await codec.getNextFrame();
|
||||
return AvifFrameInfo(frame.duration, frame.image);
|
||||
Future<ui.FrameInfo> getNextFrame() {
|
||||
final frame = data.frames[_frameIndex++ % frameCount];
|
||||
final completer = Completer<ui.FrameInfo>();
|
||||
ui.decodeImageFromPixels(
|
||||
frame.rgba,
|
||||
frame.width,
|
||||
frame.height,
|
||||
.rgba8888,
|
||||
(image) => completer.complete(AvifFrameInfo(frame.duration, image)),
|
||||
);
|
||||
return completer.future;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() => codec.dispose();
|
||||
void dispose() {}
|
||||
}
|
||||
|
||||
class AvifFrameInfo(
|
||||
|
|
|
|||
Loading…
Reference in a new issue