From 02e85a153f6d56c36d671842faac42b5b83a6ba9 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 1 Jan 2025 15:50:50 -0800 Subject: [PATCH] Use the expected plane size when capturing Android camera frames On the Samsung Galaxy A52 the camera plane size is (pitch * (h - 1) + w) instead of (pitch * h). This led to us copying off the end of the plane when uploading the texture, so we pad out to our expected size. --- src/camera/android/SDL_camera_android.c | 35 ++++++++++++++++--------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/src/camera/android/SDL_camera_android.c b/src/camera/android/SDL_camera_android.c index 03af812a76..54b539a126 100644 --- a/src/camera/android/SDL_camera_android.c +++ b/src/camera/android/SDL_camera_android.c @@ -327,31 +327,40 @@ static SDL_CameraFrameResult ANDROIDCAMERA_AcquireFrame(SDL_Camera *device, SDL_ num_planes--; // treat the interleaved planes as one. } - // !!! FIXME: we have an open issue in SDL3 to allow SDL_Surface to support non-contiguous planar data, but we don't have it yet. size_t buflen = 0; + pAImage_getPlaneRowStride(image, 0, &frame->pitch); for (int i = 0; (i < num_planes) && (i < 3); i++) { - uint8_t *data = NULL; - int32_t datalen = 0; - pAImage_getPlaneData(image, i, &data, &datalen); - buflen += (int) datalen; + int32_t expected; + if (i == 0) { + expected = frame->pitch * frame->h; + } else { + expected = frame->pitch * (frame->h + 1) / 2; + } + buflen += expected; } frame->pixels = SDL_aligned_alloc(SDL_GetSIMDAlignment(), buflen); if (frame->pixels == NULL) { result = SDL_CAMERA_FRAME_ERROR; } else { - int32_t row_stride = 0; Uint8 *dst = frame->pixels; - pAImage_getPlaneRowStride(image, 0, &row_stride); - frame->pitch = (int) row_stride; // this is what SDL3 currently expects, probably incorrectly. for (int i = 0; (i < num_planes) && (i < 3); i++) { uint8_t *data = NULL; int32_t datalen = 0; + int32_t expected; + if (i == 0) { + expected = frame->pitch * frame->h; + } else { + expected = frame->pitch * (frame->h + 1) / 2; + } pAImage_getPlaneData(image, i, &data, &datalen); - const void *src = data; - SDL_memcpy(dst, src, datalen); - dst += datalen; + + int32_t row_stride = 0; + pAImage_getPlaneRowStride(image, i, &row_stride); + SDL_assert(row_stride == frame->pitch); + SDL_memcpy(dst, data, SDL_min(expected, datalen)); + dst += expected; } } @@ -631,8 +640,8 @@ static void GatherCameraSpecs(const char *devid, CameraFormatAddData *add_data, const int32_t *i32ptr = cfgentry.data.i32; for (int i = 0; i < cfgentry.count; i++, i32ptr += 4) { const int32_t fmt = i32ptr[0]; - const int w = (int) i32ptr[1]; - const int h = (int) i32ptr[2]; + const int w = i32ptr[1]; + const int h = i32ptr[2]; const int32_t type = i32ptr[3]; SDL_PixelFormat sdlfmt = SDL_PIXELFORMAT_UNKNOWN; SDL_Colorspace colorspace = SDL_COLORSPACE_UNKNOWN;