Contains fixed patch as per Michael Niedermayer's comment
about broken line endings in the original patch.

The block decoder does not always consume every byte of the video
section -- some Interplay C93 streams (notably Cyberia 1994 cutscenes
like finmus.c93, oceanmus.c93, port.c93, etc.) pad the video region
with bytes the block decoder has no opcode for, leaving the bytestream
cursor short of where the palette actually starts. The 768-byte
palette is then read from the unread tail of the video region,
corrupting the decoder's palette with arbitrary bytes.

The corrupt palette cascades through every subsequent P-frame via the
oldpic->data[1] memcpy branch until the next palette-update frame
lands, producing scrambled-colour scene-change glitches that persist
for tens of seconds (~12 s / 150 frames on the first finmus.c93
transition).

The demuxer (libavformat/c93.c) always appends the palette as the
last 768 bytes of the packet, regardless of how many video bytes the
block decoder will consume, so seeking to buf_size - 768 before the
palette loop fixes the misalignment. The seek is a no-op for streams
where the block loop already lands at the correct position.

Signed-off-by: Vidar Waagbø <[email protected]>
---
 libavcodec/c93.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/libavcodec/c93.c b/libavcodec/c93.c
index 288b1f0..f110d42 100644
--- a/libavcodec/c93.c
+++ b/libavcodec/c93.c
@@ -243,6 +243,12 @@ static int decode_frame(AVCodecContext *avctx,
 
     if (b & C93_HAS_PALETTE) {
         uint32_t *palette = (uint32_t *) newpic->data[1];
+        /* The block-encoded video section can be padded with bytes the
+         * block decoder doesn't consume, so the decoder's stream position
+         * after the block loop isn't necessarily where the palette begins.
+         * The demuxer always appends the palette as the LAST 768 bytes of
+         * the packet, so seek to the tail before reading it. */
+        bytestream2_seek(&gb, buf_size - 768, SEEK_SET);
         for (i = 0; i < 256; i++) {
             palette[i] = 0xFFU << 24 | bytestream2_get_be24(&gb);
         }
-- 
2.43.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to