1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2026-06-19 19:03:00 +02:00

avcodec/snowenc: fix chroma reference edge extension for odd width

When extending the edges of the reconstructed reference frame, the chroma
plane width and height were passed to draw_edges() as w >> chroma_h_shift
(floor) instead of AV_CEIL_RSHIFT(). For an odd width with subsampled chroma
(e.g. 4:2:0) the chroma plane is one column wider than the floor, and
draw_edges() replicates the edge columns, so it overwrote the last real
chroma column with the previous one. The decoder does not draw_edges() its
reference, so its copy kept the correct value: the encoder and decoder
references diverged and every following inter frame was reconstructed
differently by the two, breaking bit-exact (lossless) round-tripping and
drifting lossy inter coding, for any odd-width 4:2:0 snow stream.

Use AV_CEIL_RSHIFT(), matching the input_picture edge extension just above.

Found-by: Claude
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
This commit is contained in:
Michael Niedermayer
2026-06-17 01:18:26 +02:00
parent a62d996927
commit d67a6d27c2
+2 -2
View File
@@ -1838,10 +1838,10 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
EDGE_WIDTH , EDGE_WIDTH , EDGE_TOP | EDGE_BOTTOM);
if (s->current_picture->data[2]) {
enc->mpvencdsp.draw_edges(s->current_picture->data[1],
s->current_picture->linesize[1], w>>s->chroma_h_shift, h>>s->chroma_v_shift,
s->current_picture->linesize[1], AV_CEIL_RSHIFT(w, s->chroma_h_shift), AV_CEIL_RSHIFT(h, s->chroma_v_shift),
EDGE_WIDTH>>s->chroma_h_shift, EDGE_WIDTH>>s->chroma_v_shift, EDGE_TOP | EDGE_BOTTOM);
enc->mpvencdsp.draw_edges(s->current_picture->data[2],
s->current_picture->linesize[2], w>>s->chroma_h_shift, h>>s->chroma_v_shift,
s->current_picture->linesize[2], AV_CEIL_RSHIFT(w, s->chroma_h_shift), AV_CEIL_RSHIFT(h, s->chroma_v_shift),
EDGE_WIDTH>>s->chroma_h_shift, EDGE_WIDTH>>s->chroma_v_shift, EDGE_TOP | EDGE_BOTTOM);
}
}