From eb05a39313093bf37b7fb435dffa48f0ad122112 Mon Sep 17 00:00:00 2001 From: FlareFlo Date: Sat, 4 Nov 2023 01:08:33 +0100 Subject: [PATCH] Handle non-fatal error dav1d::Error::Again (#2043) --- src/codecs/avif/decoder.rs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/codecs/avif/decoder.rs b/src/codecs/avif/decoder.rs index 7729492907..fd774179a4 100644 --- a/src/codecs/avif/decoder.rs +++ b/src/codecs/avif/decoder.rs @@ -40,14 +40,14 @@ impl AvifDecoder { primary_decoder .send_data(coded.to_vec(), None, None, None) .map_err(error_map)?; - let picture = primary_decoder.get_picture().map_err(error_map)?; + let picture = read_until_ready(&mut primary_decoder)?; let alpha_item = ctx.alpha_item_coded_data().unwrap_or_default(); let alpha_picture = if !alpha_item.is_empty() { let mut alpha_decoder = dav1d::Decoder::new().map_err(error_map)?; alpha_decoder .send_data(alpha_item.to_vec(), None, None, None) .map_err(error_map)?; - Some(alpha_decoder.get_picture().map_err(error_map)?) + Some(read_until_ready(&mut alpha_decoder)?) } else { None }; @@ -68,6 +68,7 @@ impl AvifDecoder { /// Wrapper struct around a `Cursor>` pub struct AvifReader(Cursor>, PhantomData); + impl Read for AvifReader { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.0.read(buf) @@ -172,3 +173,19 @@ impl<'a, R: 'a + Read> ImageDecoder<'a> for AvifDecoder { Ok(()) } } + +/// `get_picture` and `send_pending_data` yield `Again` as a non-fatal error requesting more data is sent to the decoder +/// This ensures that in the case of `Again` all pending data is submitted +/// This should be called after `send_data` (which does not yield `Again` when called the first time) +fn read_until_ready(decoder: &mut dav1d::Decoder) -> ImageResult { + loop { + match decoder.get_picture() { + Err(dav1d::Error::Again) => match decoder.send_pending_data() { + Ok(_) => {} + Err(dav1d::Error::Again) => {} + Err(e) => return Err(error_map(e)), + }, + r => return r.map_err(error_map), + } + } +}