Skip to content
This repository has been archived by the owner on Oct 19, 2024. It is now read-only.

Commit

Permalink
Temporary fix for an upstream bug
Browse files Browse the repository at this point in the history
  • Loading branch information
porkbrain committed Jul 5, 2024
1 parent bfc4f9e commit fbd0319
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 23 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ exclude = ["examples", "assets"]

[dependencies]
image = "0.25"
image-webp = "*" # we want the one that image uses
thiserror = "1.0"
tokio = { version = "1.35", features = ["rt", "sync", "rt-multi-thread"] }
uuid = "1.7"
Expand Down
73 changes: 50 additions & 23 deletions src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use bevy::{
render_resource::{Extent3d, TextureDimension, TextureFormat},
},
};
use image::{codecs::webp::WebPDecoder, AnimationDecoder};
use image::{codecs::webp::WebPDecoder, AnimationDecoder, ImageError};
use tokio::sync::mpsc::{Receiver, Sender};
pub use tokio::{runtime, sync::mpsc::error::TryRecvError};
use uuid::Uuid;
Expand Down Expand Up @@ -200,31 +200,58 @@ impl WebpVideo {
// TODO: Enable an alternative with lower memory usage and
// faster startup times where we decode each frame every time
// it is played.
match decoder.into_frames().collect_frames() {
Ok(frames) => loop {
for frame in &frames {
let (width, height) = frame.buffer().dimensions();
let image = Image::new(
Extent3d {
width,
height,
..default()
},
TextureDimension::D2,
frame.clone().into_buffer().into_raw(),
TextureFormat::Rgba8Unorm,
RenderAssetUsages::RENDER_WORLD,
);

// animation no longer required
if animation_frames.send(image).await.is_err() {
break;
// we need to collect because we send the frames over an async channel
let frames: Vec<_> = decoder
.into_frames()
.take_while(|frame_res| match frame_res {
Ok(_) => true,
Err(ImageError::Decoding(err)) => {
use std::error::Error;
if let Some(image_webp::DecodingError::NoMoreFrames) =
err.source().and_then(|err| {
err.downcast_ref::<image_webp::DecodingError>()
})
{
// iterator ended
// TODO: https://github.com/image-rs/image/issues/2263
} else {
error!(
"Cannot decode webp frame from video {label}: {:?}",
err.source()
);
}

false
}
},
Err(e) => {
error!("Cannot collect webp frames from video {label}: {e}")
Err(e) => {
error!(
"Cannot collect webp frames from video {label}: {e}"
);
false
}
})
.filter_map(Result::ok)
.collect();

for frame in frames {
let (width, height) = frame.buffer().dimensions();
let image = Image::new(
Extent3d {
width,
height,
..default()
},
TextureDimension::D2,
frame.clone().into_buffer().into_raw(),
TextureFormat::Rgba8Unorm,
RenderAssetUsages::RENDER_WORLD,
);

// animation no longer required
if animation_frames.send(image).await.is_err() {
break;
}
};
}
}
}

0 comments on commit fbd0319

Please sign in to comment.