get_y_image() wraps the decoder Y plane zero-copy but recorded
FFALIGN(width,32) as the Image stride instead of the frame's real
linesize[0]. For widths that are not a multiple of 32 the decoder packs
the plane tighter than FFALIGN, so:
- Image::Rotate/Flip re-derived the source stride via
av_image_fill_arrays(...,32) and read past the end of the borrowed
plane (and skewed Y-channel motion analysis, which reads the same
buffer).
- Image::Flip sized its destination from this->size, which is tight for a
borrowed plane and smaller than the 32-aligned layout the planes are
written at, overrunning the destination.
Record the frame's real linesize in get_y_image(); use the Image's own
linesize for the source plane-0 stride in Rotate/Flip; size Flip's
destination from av_image_get_buffer_size(...,32). All are no-ops for
self-consistent ZM-allocated (32-aligned) images.
tests/zm_image_linesize.cpp: Rotate 90/180/270 and Flip H/V over a tight,
non-32-aligned GRAY8 source verifying correct output.
refs #4788
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>