From fe2bca9748afa754ebbca4c543c5b28bbce30cf4 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Wed, 9 Sep 2026 13:43:34 -0700
Subject: [PATCH] Fixed YUV size and pitch calculations
---
src/render/SDL_yuv_sw.c | 7 ++--
src/render/direct3d/SDL_render_d3d.c | 9 +++--
src/render/direct3d11/SDL_render_d3d11.c | 14 +++++---
src/render/direct3d12/SDL_render_d3d12.c | 16 ++++++---
src/render/gpu/SDL_render_gpu.c | 34 +++++++------------
src/render/metal/SDL_render_metal.m | 26 +++++++++-----
src/video/SDL_yuv.c | 43 +++++++++++-------------
test/testyuv.c | 5 +--
8 files changed, 85 insertions(+), 69 deletions(-)
diff --git a/src/render/SDL_yuv_sw.c b/src/render/SDL_yuv_sw.c
index 9bb35eedd038d..96ca1bec63b12 100644
--- a/src/render/SDL_yuv_sw.c
+++ b/src/render/SDL_yuv_sw.c
@@ -140,6 +140,7 @@ bool SDL_SW_UpdateYUVTexture(SDL_SW_YUVTexture *swdata, const SDL_Rect *rect,
int row;
size_t length;
const int bpp = SDL_BYTESPERPIXEL(swdata->format);
+ const int UVpitch = ((pitch / bpp + 1) / 2) * bpp;
// Copy the Y plane
src = (Uint8 *)pixels;
@@ -158,19 +159,19 @@ bool SDL_SW_UpdateYUVTexture(SDL_SW_YUVTexture *swdata, const SDL_Rect *rect,
length = ((rect->w + 1) / 2) * bpp;
for (row = 0; row < (rect->h + 1) / 2; ++row) {
SDL_memcpy(dst, src, length);
- src += (pitch + 1) / 2;
+ src += UVpitch;
dst += swdata->pitches[1];
}
// Copy the next plane
- src = (Uint8 *)pixels + rect->h * pitch + ((rect->h + 1) / 2) * ((pitch + 1) / 2);
+ src = (Uint8 *)pixels + rect->h * pitch + ((rect->h + 1) / 2) * UVpitch;
dst = swdata->pixels + swdata->h * swdata->w +
((swdata->h + 1) / 2) * ((swdata->w + 1) / 2);
dst += rect->y / 2 * ((swdata->w + 1) / 2) + rect->x / 2;
length = ((rect->w + 1) / 2) * bpp;
for (row = 0; row < (rect->h + 1) / 2; ++row) {
SDL_memcpy(dst, src, length);
- src += (pitch + 1) / 2;
+ src += UVpitch;
dst += swdata->pitches[2];
}
}
diff --git a/src/render/direct3d/SDL_render_d3d.c b/src/render/direct3d/SDL_render_d3d.c
index ed5e4130df0d7..929dbdafd6721 100644
--- a/src/render/direct3d/SDL_render_d3d.c
+++ b/src/render/direct3d/SDL_render_d3d.c
@@ -28,6 +28,7 @@
#include "../SDL_d3dmath.h"
#include "../../video/windows/SDL_windowsvideo.h"
#include "../../video/SDL_pixels_c.h"
+#include "../../video/SDL_yuv_c.h"
#define D3D_DEBUG_INFO
#include <d3d9.h>
@@ -807,8 +808,12 @@ static bool D3D_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture,
if (texturedata->yuv) {
// It's more efficient to upload directly...
if (!texturedata->pixels) {
- texturedata->pitch = texture->w;
- texturedata->pixels = (Uint8 *)SDL_malloc((texture->h * texturedata->pitch * 3) / 2);
+ size_t size, calculated_pitch;
+ if (!SDL_CalculateYUVSize(texture->format, texture->w, texture->h, &size, &calculated_pitch)) {
+ return false;
+ }
+ texturedata->pitch = (int)calculated_pitch;
+ texturedata->pixels = (Uint8 *)SDL_malloc(size);
if (!texturedata->pixels) {
return false;
}
diff --git a/src/render/direct3d11/SDL_render_d3d11.c b/src/render/direct3d11/SDL_render_d3d11.c
index 2b6b339286891..121c61d3c96e9 100644
--- a/src/render/direct3d11/SDL_render_d3d11.c
+++ b/src/render/direct3d11/SDL_render_d3d11.c
@@ -28,6 +28,7 @@
#include "../SDL_sysrender.h"
#include "../SDL_d3dmath.h"
#include "../../video/SDL_pixels_c.h"
+#include "../../video/SDL_yuv_c.h"
#include <d3d11_1.h>
#ifdef HAVE_DXGI1_5_H
@@ -1608,8 +1609,9 @@ static bool D3D11_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
return false;
}
} else {
- int Ypitch = srcPitch;
- int UVpitch = ((Ypitch + 1 * SDL_BYTESPERPIXEL(texture->format)) / 2);
+ const int bpp = SDL_BYTESPERPIXEL(texture->format);
+ const int Ypitch = srcPitch;
+ const int UVpitch = ((Ypitch / bpp + 1) / 2) * bpp;
const Uint8 *plane0 = (const Uint8 *)srcPixels;
const Uint8 *plane1 = plane0 + rect->h * Ypitch;
const Uint8 *plane2 = plane1 + ((rect->h + 1) / 2) * UVpitch;
@@ -1795,8 +1797,12 @@ static bool D3D11_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture,
if (textureData->yuv || textureData->nv12) {
// It's more efficient to upload directly...
if (!textureData->pixels) {
- textureData->pitch = texture->w;
- textureData->pixels = (Uint8 *)SDL_malloc((texture->h * textureData->pitch * 3) / 2);
+ size_t size, calculated_calculated_pitch;
+ if (!SDL_CalculateYUVSize(texture->format, texture->w, texture->h, &size, &calculated_calculated_pitch)) {
+ return false;
+ }
+ textureData->pitch = (int)calculated_calculated_pitch;
+ textureData->pixels = (Uint8 *)SDL_malloc(size);
if (!textureData->pixels) {
return false;
}
diff --git a/src/render/direct3d12/SDL_render_d3d12.c b/src/render/direct3d12/SDL_render_d3d12.c
index 9e529ce5beb1f..8051b183850f9 100644
--- a/src/render/direct3d12/SDL_render_d3d12.c
+++ b/src/render/direct3d12/SDL_render_d3d12.c
@@ -46,6 +46,7 @@ extern "C" {
// This must be included here as the function definitions in SDL_pixels.c/_c.h are C, not C++
#include "../../video/SDL_pixels_c.h"
+#include "../../video/SDL_yuv_c.h"
/* !!! FIXME: vertex buffer bandwidth could be lower; only use UV coords when
!!! FIXME: textures are needed. */
@@ -2079,16 +2080,17 @@ static bool D3D12_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
}
} else {
const int bpp = SDL_BYTESPERPIXEL(texture->format);
+ const int UVpitch = ((srcPitch / bpp + 1) / 2) * bpp;
// Skip to the correct offset into the next texture
srcPixels = (const void *)((const Uint8 *)srcPixels + rect->h * srcPitch);
- if (!D3D12_UpdateTextureInternal(rendererData, texture->format == SDL_PIXELFORMAT_YV12 ? textureData->mainTextureV : textureData->mainTextureU, 0, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, srcPixels, (srcPitch + 1 * bpp) / 2, texture->format == SDL_PIXELFORMAT_YV12 ? &textureData->mainResourceStateV : &textureData->mainResourceStateU)) {
+ if (!D3D12_UpdateTextureInternal(rendererData, texture->format == SDL_PIXELFORMAT_YV12 ? textureData->mainTextureV : textureData->mainTextureU, 0, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, srcPixels, UVpitch, texture->format == SDL_PIXELFORMAT_YV12 ? &textureData->mainResourceStateV : &textureData->mainResourceStateU)) {
return false;
}
// Skip to the correct offset into the next texture
- srcPixels = (const void *)((const Uint8 *)srcPixels + ((rect->h + 1) / 2) * ((srcPitch + 1 * bpp) / 2));
- if (!D3D12_UpdateTextureInternal(rendererData, texture->format == SDL_PIXELFORMAT_YV12 ? textureData->mainTextureU : textureData->mainTextureV, 0, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, srcPixels, (srcPitch + 1 * bpp) / 2, texture->format == SDL_PIXELFORMAT_YV12 ? &textureData->mainResourceStateU : &textureData->mainResourceStateV)) {
+ srcPixels = (const void *)((const Uint8 *)srcPixels + ((rect->h + 1) / 2) * UVpitch);
+ if (!D3D12_UpdateTextureInternal(rendererData, texture->format == SDL_PIXELFORMAT_YV12 ? textureData->mainTextureU : textureData->mainTextureV, 0, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, srcPixels, UVpitch, texture->format == SDL_PIXELFORMAT_YV12 ? &textureData->mainResourceStateU : &textureData->mainResourceStateV)) {
return false;
}
}
@@ -2201,8 +2203,12 @@ static bool D3D12_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture,
if (textureData->yuv || textureData->nv12) {
// It's more efficient to upload directly...
if (!textureData->pixels) {
- textureData->pitch = texture->w;
- textureData->pixels = (Uint8 *)SDL_malloc((texture->h * textureData->pitch * 3) / 2);
+ size_t size, calculated_pitch;
+ if (!SDL_CalculateYUVSize(texture->format, texture->w, texture->h, &size, &calculated_pitch)) {
+ return false;
+ }
+ textureData->pitch = (int)calculated_pitch;
+ textureData->pixels = (Uint8 *)SDL_malloc(size);
if (!textureData->pixels) {
return false;
}
diff --git a/src/render/gpu/SDL_render_gpu.c b/src/render/gpu/SDL_render_gpu.c
index d54243478cba8..c6e7ff38bc9b4 100644
--- a/src/render/gpu/SDL_render_gpu.c
+++ b/src/render/gpu/SDL_render_gpu.c
@@ -25,6 +25,7 @@
#include "../../events/SDL_windowevents_c.h"
#include "../../video/SDL_pixels_c.h"
#include "../../video/SDL_sysvideo.h"
+#include "../../video/SDL_yuv_c.h"
#include "../SDL_d3dmath.h"
#include "../SDL_sysrender.h"
#include "SDL_gpu_util.h"
@@ -321,25 +322,16 @@ static bool GPU_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_
data->format = format;
if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
- size_t size;
- data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
- size = (size_t)texture->h * data->pitch;
- if (texture->format == SDL_PIXELFORMAT_YV12 ||
- texture->format == SDL_PIXELFORMAT_IYUV ||
- texture->format == SDL_PIXELFORMAT_I0FL) {
- // Need to add size for the U and V planes
- size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
- }
- if (texture->format == SDL_PIXELFORMAT_I444 ||
- texture->format == SDL_PIXELFORMAT_I4FL) {
- // Need to add size for the U and V planes
- size += 2 * texture->h * data->pitch;
- }
- if (texture->format == SDL_PIXELFORMAT_NV12 ||
- texture->format == SDL_PIXELFORMAT_NV21 ||
- texture->format == SDL_PIXELFORMAT_P010) {
- // Need to add size for the U/V plane
- size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
+ size_t size, pitch;
+ if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
+ if (!SDL_CalculateYUVSize(texture->format, texture->w, texture->h, &size, &pitch)) {
+ SDL_free(data);
+ return false;
+ }
+ data->pitch = (int)pitch;
+ } else {
+ data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
+ size = (size_t)texture->h * data->pitch;
}
data->pixels = SDL_calloc(1, size);
if (!data->pixels) {
@@ -584,8 +576,8 @@ static bool GPU_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, cons
retval &= GPU_UpdateTextureInternal(renderdata, cpass, data->textureU, bpp, rect->x, rect->y, rect->w, rect->h, Uplane, pitch);
retval &= GPU_UpdateTextureInternal(renderdata, cpass, data->textureV, bpp, rect->x, rect->y, rect->w, rect->h, Vplane, pitch);
} else {
- int Ypitch = pitch;
- int UVpitch = ((Ypitch + 1 * SDL_BYTESPERPIXEL(texture->format)) / 2);
+ const int Ypitch = pitch;
+ const int UVpitch = ((Ypitch / bpp + 1) / 2) * bpp;
const Uint8 *Yplane = (const Uint8 *)pixels;
const Uint8 *Uplane = Yplane + rect->h * Ypitch;
const Uint8 *Vplane = Uplane + ((rect->h + 1) / 2) * UVpitch;
diff --git a/src/render/metal/SDL_render_metal.m b/src/render/metal/SDL_render_metal.m
index 39eae3a36dac3..2e9cc4a491258 100644
--- a/src/render/metal/SDL_render_metal.m
+++ b/src/render/metal/SDL_render_metal.m
@@ -24,6 +24,7 @@
#include "../SDL_sysrender.h"
#include "../../video/SDL_pixels_c.h"
+#include "../../video/SDL_yuv_c.h"
#import <CoreVideo/CoreVideo.h>
#import <Metal/Metal.h>
@@ -1003,13 +1004,14 @@ static bool METAL_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
// YV12 stores V before U, so the plane order is swapped for it.
id<MTLTexture> firstplane = texture->format == SDL_PIXELFORMAT_YV12 ? texturedata.mtltextureV : texturedata.mtltextureU;
id<MTLTexture> secondplane = texture->format == SDL_PIXELFORMAT_YV12 ? texturedata.mtltextureU : texturedata.mtltextureV;
+ const int bpp = SDL_BYTESPERPIXEL(texture->format);
int UVpitch;
SDL_Rect UVrect;
if (texture->format == SDL_PIXELFORMAT_I444 || texture->format == SDL_PIXELFORMAT_I4FL) {
UVpitch = pitch;
UVrect = *rect;
} else {
- UVpitch = (pitch + 1 * SDL_BYTESPERPIXEL(texture->format)) / 2;
+ UVpitch = ((pitch / bpp + 1) / 2) * bpp;
UVrect.x = rect->x / 2;
UVrect.y = rect->y / 2;
UVrect.w = (rect->w + 1) / 2;
@@ -1030,8 +1032,9 @@ static bool METAL_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
}
if (texturedata.nv12) {
+ const int bpp = SDL_BYTESPERPIXEL(texture->format);
+ const int UVpitch = ((pitch / bpp + 1) / 2) * 2 * bpp;
SDL_Rect UVrect = { rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2 };
- int UVpitch = 2 * ((pitch + 1) / 2);
// Skip to the correct offset into the next texture
pixels = (const void *)((const Uint8 *)pixels + rect->h * pitch);
@@ -1121,24 +1124,26 @@ static bool METAL_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture,
@autoreleasepool {
SDL3METAL_RenderData *data = (__bridge SDL3METAL_RenderData *)renderer->internal;
SDL3METAL_TextureData *texturedata = (__bridge SDL3METAL_TextureData *)texture->internal;
- int buffersize = 0;
id<MTLBuffer> lockedbuffer = nil;
+ size_t size, calculated_pitch;
if (rect->w <= 0 || rect->h <= 0) {
return SDL_SetError("Invalid rectangle dimensions for LockTexture.");
}
- *pitch = SDL_BYTESPERPIXEL(texture->format) * rect->w;
#ifdef SDL_HAVE_YUV
if (texturedata.yuv || texturedata.nv12) {
- buffersize = ((*pitch) * rect->h) + (2 * (*pitch + 1) / 2) * ((rect->h + 1) / 2);
+ if (!SDL_CalculateYUVSize(texture->format, rect->w, rect->h, &size, &calculated_pitch)) {
+ return false;
+ }
} else
#endif
{
- buffersize = (*pitch) * rect->h;
+ calculated_pitch = SDL_BYTESPERPIXEL(texture->format) * rect->w;
+ size = rect->h * calculated_pitch;
}
- lockedbuffer = [data.mtldevice newBufferWithLength:buffersize options:MTLResourceStorageModeShared];
+ lockedbuffer = [data.mtldevice newBufferWithLength:size options:MTLResourceStorageModeShared];
if (lockedbuffer == nil) {
return SDL_OutOfMemory();
}
@@ -1146,6 +1151,7 @@ static bool METAL_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture,
texturedata.lockedrect = *rect;
texturedata.lockedbuffer = lockedbuffer;
*pixels = [lockedbuffer contents];
+ *pitch = (int)calculated_pitch;
return true;
}
@@ -1192,7 +1198,8 @@ static void METAL_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
// YV12 stores V before U, so the plane order is swapped for it.
id<MTLTexture> firstplane = texture->format == SDL_PIXELFORMAT_YV12 ? texturedata.mtltextureV : texturedata.mtltextureU;
id<MTLTexture> secondplane = texture->format == SDL_PIXELFORMAT_YV12 ? texturedata.mtltextureU : texturedata.mtltextureV;
- int UVpitch = (pitch + 1) / 2;
+ const int bpp = SDL_BYTESPERPIXEL(texture->format);
+ const int UVpitch = ((pitch / bpp + 1) / 2) * bpp;
[blitcmd copyFromBuffer:texturedata.lockedbuffer
sourceOffset:rect.h * pitch
@@ -1216,7 +1223,8 @@ static void METAL_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
}
if (texturedata.nv12) {
- int UVpitch = 2 * ((pitch + 1) / 2);
+ const int bpp = SDL_BYTESPERPIXEL(texture->format);
+ const int UVpitch = ((pitch / bpp + 1) / 2) * 2 * bpp;
[blitcmd copyFromBuffer:texturedata.lockedbuffer
sourceOffset:rect.h * pitch
diff --git a/src/video/SDL_yuv.c b/src/video/SDL_yuv.c
index 0295e6a349f46..41e7be25122bd 100644
--- a/src/video/SDL_yuv.c
+++ b/src/video/SDL_yuv.c
@@ -166,8 +166,9 @@ bool SDL_CalculateYUVSize(SDL_PixelFormat format, int w, int h, size_t *size, si
case SDL_PIXELFORMAT_NV12: /**< Planar mode: Y + U/V interleaved (2 planes) */
case SDL_PIXELFORMAT_NV21: /**< Planar mode: Y + V/U interleaved (2 planes) */
+ case SDL_PIXELFORMAT_P010: /**< Planar mode: Y + U/V interleaved, 10 bit (2 planes) */
if (pitch) {
- *pitch = w;
+ *pitch = w * SDL_BYTESPERPIXEL(format);
}
if (size) {
@@ -237,7 +238,7 @@ static bool GetYUVPlanes(int width, int height, SDL_PixelFormat format, const vo
case SDL_PIXELFORMAT_IYUV:
case SDL_PIXELFORMAT_I0FL:
pitches[0] = yuv_pitch;
- pitches[1] = (pitches[0] + 1 * SDL_BYTESPERPIXEL(format)) / 2;
+ pitches[1] = ((pitches[0] / SDL_BYTESPERPIXEL(format) + 1) / 2) * SDL_BYTESPERPIXEL(format);
pitches[2] = pitches[1];
planes[0] = (const Uint8 *)yuv;
planes[1] = planes[0] + pitches[0] * height;
@@ -1353,46 +1354,42 @@ static bool SDL_ConvertPixels_YUV_to_YUV_Copy(int width, int height, SDL_PixelFo
}
if (IsPlanar2x2Format(format)) {
+ const int bpp = SDL_BYTESPERPIXEL(format);
+
// Y plane
+ const size_t length = width * bpp;
for (i = height; i--;) {
- SDL_memcpy(dst, src, width);
+ SDL_memcpy(dst, src, length);
src = (const Uint8 *)src + src_pitch;
dst = (Uint8 *)dst + dst_pitch;
}
- if (format == SDL_PIXELFORMAT_YV12 || format == SDL_PIXELFORMAT_IYUV) {
+ if (format == SDL_PIXELFORMAT_YV12 ||
+ format == SDL_PIXELFORMAT_IYUV ||
+ format == SDL_PIXELFORMAT_I0FL) {
// U and V planes are a quarter the size of the Y plane, rounded up
- width = (width + 1) / 2;
+ width = ((width + 1) / 2) * bpp;
height = (height + 1) / 2;
- src_pitch = (src_pitch + 1) / 2;
- dst_pitch = (dst_pitch + 1) / 2;
+ src_pitch = ((src_pitch / bpp + 1) / 2) * bpp;
+ dst_pitch = ((dst_pitch / bpp + 1) / 2) * bpp;
for (i = height * 2; i--;) {
SDL_memcpy(dst, src, width);
src = (const Uint8 *)src + src_pitch;
dst = (Uint8 *)dst + dst_pitch;
}
- } else if (format == SDL_PIXELFORMAT_NV12 || format == SDL_PIXELFORMAT_NV21) {
- // U/V plane is half the height of the Y plane, rounded up
+ } else if (format == SDL_PIXELFORMAT_NV12 ||
+ format == SDL_PIXELFORMAT_NV21 ||
+ format == SDL_PIXELFORMAT_P010) {
+ // U/V plane is half the height of the Y plane, rounded up, with packed CrCb
+ width = ((width + 1) / 2) * 2 * bpp;
height = (height + 1) / 2;
- width = ((width + 1) / 2) * 2;
- src_pitch = ((src_pitch + 1) / 2) * 2;
- dst_pitch = ((dst_pitch + 1) / 2) * 2;
+ src_pitch = ((src_pitch / bpp + 1) / 2) * 2 * bpp;
+ dst_pitch = ((dst_pitch / bpp + 1) / 2) * 2 * bpp;
for (i = height; i--;) {
SDL_memcpy(dst, src, width);
src = (const Uint8 *)src + src_pitch;
dst = (Uint8 *)dst + dst_pitch;
}
- } else if (format == SDL_PIXELFORMAT_P010) {
- // U/V plane is half the height of the Y plane, rounded up
- height = (height + 1) / 2;
- width = ((width + 1) / 2) * 2;
- src_pitch = ((src_pitch + 1) / 2) * 2;
- dst_pitch = ((dst_pitch + 1) / 2) * 2;
- for (i = height; i--;) {
- SDL_memcpy(dst, src, width * sizeof(Uint16));
- src = (const Uint8 *)src + src_pitch;
- dst = (Uint8 *)dst + dst_pitch;
- }
}
return true;
}
diff --git a/test/testyuv.c b/test/testyuv.c
index 767b616e40c52..1b1dc1070a0a6 100644
--- a/test/testyuv.c
+++ b/test/testyuv.c
@@ -416,15 +416,16 @@ static bool create_textures(SDL_Renderer *renderer, SDL_Surface *original, SDL_P
goto done;
}
if (planar && (yuv_format == SDL_PIXELFORMAT_YV12 || yuv_format == SDL_PIXELFORMAT_IYUV || yuv_format == SDL_PIXELFORMAT_I0FL)) {
+ const int bpp = SDL_BYTESPERPIXEL(yuv_format);
const int Yrows = original->h;
const int UVrows = ((original->h + 1) / 2);
const int src_Ypitch = pitch;
- const int src_UVpitch = ((pitch + 1 * SDL_BYTESPERPIXEL(yuv_format)) / 2);
+ const int src_UVpitch = ((pitch / bpp + 1) / 2) * bpp;
const Uint8 *src_plane0 = (const Uint8 *)raw_yuv;
const Uint8 *src_plane1 = src_plane0 + Yrows * src_Ypitch;
const Uint8 *src_plane2 = src_plane1 + UVrows * src_UVpitch;
const int Ypitch = pitch + 37;
- const int UVpitch = ((Ypitch + 1 * SDL_BYTESPERPIXEL(yuv_format)) / 2);
+ const int UVpitch = ((Ypitch / bpp + 1) / 2) * bpp;
Uint8 *plane0 = (Uint8 *)SDL_calloc(1, Yrows * Ypitch);
Uint8 *plane1 = (Uint8 *)SDL_calloc(1, UVrows * UVpitch);
Uint8 *plane2 = (Uint8 *)SDL_calloc(1, UVrows * UVpitch);