diff --git a/fluxer_media_proxy/src/component_tests.rs b/fluxer_media_proxy/src/component_tests.rs
index 69fc95e58..f485a4cb0 100644
--- a/fluxer_media_proxy/src/component_tests.rs
+++ b/fluxer_media_proxy/src/component_tests.rs
@@ -171,11 +171,13 @@ fn gif_animation_status(input: &[u8]) -> NativeStatus {
})
}
-fn probe_animated_status(input: &[u8]) -> (NativeStatus, c_int, c_int, c_int) {
+fn probe_animated_status(input: &[u8]) -> (NativeStatus, c_int, c_int, c_int, c_int) {
ensure_vips_init().expect("libvips initialises");
let mut width = c_int::MAX;
let mut height = c_int::MAX;
let mut pages = c_int::MAX;
+ let mut bands = c_int::MAX;
+ let mut format = c_int::MAX;
let status = NativeStatus::from_code(unsafe {
native::fluxer_vips_probe_animated(
input.as_ptr().cast(),
@@ -183,10 +185,12 @@ fn probe_animated_status(input: &[u8]) -> (NativeStatus, c_int, c_int, c_int) {
&mut width,
&mut height,
&mut pages,
+ &mut bands,
+ &mut format,
)
});
unsafe { native::fluxer_vips_error_clear() };
- (status, width, height, pages)
+ (status, width, height, pages, bands)
}
fn apng_decode_status(input: &[u8]) -> (NativeStatus, *mut native::VipsImage, u32) {
@@ -286,16 +290,18 @@ fn every_remaining_native_validator_zeroes_its_out_params_on_failure() {
"input {bytes:?}"
);
- let (status, width, height, pages) = probe_animated_status(&bytes);
+ let (status, width, height, pages, bands) = probe_animated_status(&bytes);
assert_eq!(decodable, status == NativeStatus::Ok, "input {bytes:?}");
if decodable {
assert_eq!(1, width, "input {bytes:?}");
assert_eq!(1, height, "input {bytes:?}");
assert_eq!(1, pages, "input {bytes:?}");
+ assert!(bands > 0, "input {bytes:?}");
} else {
assert_eq!(0, width, "input {bytes:?}");
assert_eq!(0, height, "input {bytes:?}");
assert_eq!(0, pages, "input {bytes:?}");
+ assert_eq!(0, bands, "input {bytes:?}");
}
let (status, out, num_plays) = apng_decode_status(&bytes);
diff --git a/fluxer_media_proxy/src/constants.rs b/fluxer_media_proxy/src/constants.rs
index e509831c2..5b475e08f 100644
--- a/fluxer_media_proxy/src/constants.rs
+++ b/fluxer_media_proxy/src/constants.rs
@@ -15,6 +15,7 @@ pub const DEFAULT_IMAGE_SIZE: u32 = 128;
pub const MAX_ANIMATED_FRAMES_DEFAULT: u32 = 20_000;
pub const MAX_ANIMATED_TOTAL_PIXELS_DEFAULT: usize = 4 * MAX_MEDIA_IMAGE_PIXELS_DEFAULT;
pub const MAX_JXL_DECODE_PIXELS: usize = 4096 * 4096;
+pub const MAX_JXL_SIMPLE_DECODE_PIXELS: usize = 8192 * 6144;
pub const MAX_STATIC_OUTPUT_PIXELS: usize = 6144 * 4096;
pub const MAX_ANIMATED_OUTPUT_PIXELS: usize = 16 << 20;
pub const SVG_RASTER_MAX_DIMENSION: u32 = 4096;
diff --git a/fluxer_media_proxy/src/media_limits.rs b/fluxer_media_proxy/src/media_limits.rs
index fdebce38e..d6e189d3a 100644
--- a/fluxer_media_proxy/src/media_limits.rs
+++ b/fluxer_media_proxy/src/media_limits.rs
@@ -12,6 +12,7 @@ pub struct MediaLimits {
animated_frames: u32,
animated_total_pixels: usize,
max_media_proxy_bytes: usize,
+ native_memory_budget_bytes: usize,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
@@ -59,9 +60,17 @@ impl MediaLimits {
animated_frames,
animated_total_pixels,
max_media_proxy_bytes,
+ native_memory_budget_bytes: usize::MAX,
})
}
+ pub(crate) fn with_native_memory_budget(self, native_memory_budget_bytes: usize) -> Self {
+ Self {
+ native_memory_budget_bytes,
+ ..self
+ }
+ }
+
pub fn default_from_config() -> Self {
Self::new(MediaLimitConfiguration {
image_dimension: MAX_MEDIA_IMAGE_DIMENSION_DEFAULT,
@@ -92,4 +101,8 @@ impl MediaLimits {
pub fn max_media_proxy_bytes(&self) -> usize {
self.max_media_proxy_bytes
}
+
+ pub fn native_memory_budget_bytes(&self) -> usize {
+ self.native_memory_budget_bytes
+ }
}
diff --git a/fluxer_media_proxy/src/media_process/image_probe.rs b/fluxer_media_proxy/src/media_process/image_probe.rs
index 790ced846..6fa6a237d 100644
--- a/fluxer_media_proxy/src/media_process/image_probe.rs
+++ b/fluxer_media_proxy/src/media_process/image_probe.rs
@@ -15,9 +15,24 @@ pub(crate) fn probe_animated(
media_limits: &MediaLimits,
input: &[u8],
) -> Result