From db021ee2ea0355f0c1733e51e3ee7c54e6ca2a3e Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 29 Apr 2021 14:57:23 +0200 Subject: Fix macOS arm crash in scaling images with ffmpeg Ref T78710 --- source/blender/imbuf/intern/anim_movie.c | 120 ++++++++++++++++--------------- 1 file changed, 62 insertions(+), 58 deletions(-) (limited to 'source/blender/imbuf') diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c index 6c63c1a1b5b..9e8224f58b2 100644 --- a/source/blender/imbuf/intern/anim_movie.c +++ b/source/blender/imbuf/intern/anim_movie.c @@ -815,66 +815,70 @@ static void ffmpeg_postprocess(struct anim *anim) anim->y); } - if (ENDIAN_ORDER == B_ENDIAN) { - int *dstStride = anim->pFrameRGB->linesize; - uint8_t **dst = anim->pFrameRGB->data; - const int dstStride2[4] = {dstStride[0], 0, 0, 0}; - uint8_t *dst2[4] = {dst[0], 0, 0, 0}; - int x, y, h, w; - unsigned char *bottom; - unsigned char *top; - - sws_scale(anim->img_convert_ctx, - (const uint8_t *const *)input->data, - input->linesize, - 0, - anim->y, - dst2, - dstStride2); - - bottom = (unsigned char *)ibuf->rect; - top = bottom + ibuf->x * (ibuf->y - 1) * 4; - - h = (ibuf->y + 1) / 2; - w = ibuf->x; - - for (y = 0; y < h; y++) { - unsigned char tmp[4]; - unsigned int *tmp_l = (unsigned int *)tmp; - - for (x = 0; x < w; x++) { - tmp[0] = bottom[0]; - tmp[1] = bottom[1]; - tmp[2] = bottom[2]; - tmp[3] = bottom[3]; - - bottom[0] = top[0]; - bottom[1] = top[1]; - bottom[2] = top[2]; - bottom[3] = top[3]; - - *(unsigned int *)top = *tmp_l; - - bottom += 4; - top += 4; - } - top -= 8 * w; +# if defined(__x86_64__) || defined(_M_X64) + /* Scale and flip image over Y axis in one go, using negative strides. + * This doesn't work with arm/powerpc though and may be misusing the API. + * Limit it x86_64 where it appears to work. + * http://trac.ffmpeg.org/ticket/9060 */ + int *dstStride = anim->pFrameRGB->linesize; + uint8_t **dst = anim->pFrameRGB->data; + const int dstStride2[4] = {-dstStride[0], 0, 0, 0}; + uint8_t *dst2[4] = {dst[0] + (anim->y - 1) * dstStride[0], 0, 0, 0}; + + sws_scale(anim->img_convert_ctx, + (const uint8_t *const *)input->data, + input->linesize, + 0, + anim->y, + dst2, + dstStride2); +# else + /* Scale with swscale then flip image over Y axis. */ + int *dstStride = anim->pFrameRGB->linesize; + uint8_t **dst = anim->pFrameRGB->data; + const int dstStride2[4] = {dstStride[0], 0, 0, 0}; + uint8_t *dst2[4] = {dst[0], 0, 0, 0}; + int x, y, h, w; + unsigned char *bottom; + unsigned char *top; + + sws_scale(anim->img_convert_ctx, + (const uint8_t *const *)input->data, + input->linesize, + 0, + anim->y, + dst2, + dstStride2); + + bottom = (unsigned char *)ibuf->rect; + top = bottom + ibuf->x * (ibuf->y - 1) * 4; + + h = (ibuf->y + 1) / 2; + w = ibuf->x; + + for (y = 0; y < h; y++) { + unsigned char tmp[4]; + unsigned int *tmp_l = (unsigned int *)tmp; + + for (x = 0; x < w; x++) { + tmp[0] = bottom[0]; + tmp[1] = bottom[1]; + tmp[2] = bottom[2]; + tmp[3] = bottom[3]; + + bottom[0] = top[0]; + bottom[1] = top[1]; + bottom[2] = top[2]; + bottom[3] = top[3]; + + *(unsigned int *)top = *tmp_l; + + bottom += 4; + top += 4; } + top -= 8 * w; } - else { - int *dstStride = anim->pFrameRGB->linesize; - uint8_t **dst = anim->pFrameRGB->data; - const int dstStride2[4] = {-dstStride[0], 0, 0, 0}; - uint8_t *dst2[4] = {dst[0] + (anim->y - 1) * dstStride[0], 0, 0, 0}; - - sws_scale(anim->img_convert_ctx, - (const uint8_t *const *)input->data, - input->linesize, - 0, - anim->y, - dst2, - dstStride2); - } +# endif if (need_aligned_ffmpeg_buffer(anim)) { uint8_t *src = anim->pFrameRGB->data[0]; -- cgit v1.2.3