SDL 2.0
SDL_yuv_sw.c
Go to the documentation of this file.
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "../SDL_internal.h"
22
23/* This is the software implementation of the YUV texture support */
24
25#include "SDL_assert.h"
26
27#include "SDL_yuv_sw_c.h"
28
29
32{
33 SDL_SW_YUVTexture *swdata;
34
35 switch (format) {
43 break;
44 default:
45 SDL_SetError("Unsupported YUV format");
46 return NULL;
47 }
48
49 swdata = (SDL_SW_YUVTexture *) SDL_calloc(1, sizeof(*swdata));
50 if (!swdata) {
52 return NULL;
53 }
54
55 swdata->format = format;
57 swdata->w = w;
58 swdata->h = h;
59 {
60 const int sz_plane = w * h;
61 const int sz_plane_chroma = ((w + 1) / 2) * ((h + 1) / 2);
62 const int sz_plane_packed = ((w + 1) / 2) * h;
63 int dst_size = 0;
64 switch(format)
65 {
66 case SDL_PIXELFORMAT_YV12: /**< Planar mode: Y + V + U (3 planes) */
67 case SDL_PIXELFORMAT_IYUV: /**< Planar mode: Y + U + V (3 planes) */
68 dst_size = sz_plane + sz_plane_chroma + sz_plane_chroma;
69 break;
70
71 case SDL_PIXELFORMAT_YUY2: /**< Packed mode: Y0+U0+Y1+V0 (1 plane) */
72 case SDL_PIXELFORMAT_UYVY: /**< Packed mode: U0+Y0+V0+Y1 (1 plane) */
73 case SDL_PIXELFORMAT_YVYU: /**< Packed mode: Y0+V0+Y1+U0 (1 plane) */
74 dst_size = 4 * sz_plane_packed;
75 break;
76
77 case SDL_PIXELFORMAT_NV12: /**< Planar mode: Y + U/V interleaved (2 planes) */
78 case SDL_PIXELFORMAT_NV21: /**< Planar mode: Y + V/U interleaved (2 planes) */
79 dst_size = sz_plane + sz_plane_chroma + sz_plane_chroma;
80 break;
81
82 default:
83 SDL_assert(0 && "We should never get here (caught above)");
84 break;
85 }
86 swdata->pixels = (Uint8 *) SDL_malloc(dst_size);
87 if (!swdata->pixels) {
90 return NULL;
91 }
92 }
93
94 /* Find the pitch and offset values for the texture */
95 switch (format) {
98 swdata->pitches[0] = w;
99 swdata->pitches[1] = (swdata->pitches[0] + 1) / 2;
100 swdata->pitches[2] = (swdata->pitches[0] + 1) / 2;
101 swdata->planes[0] = swdata->pixels;
102 swdata->planes[1] = swdata->planes[0] + swdata->pitches[0] * h;
103 swdata->planes[2] = swdata->planes[1] + swdata->pitches[1] * ((h + 1) / 2);
104 break;
108 swdata->pitches[0] = ((w + 1) / 2) * 4;
109 swdata->planes[0] = swdata->pixels;
110 break;
111
114 swdata->pitches[0] = w;
115 swdata->pitches[1] = 2 * ((swdata->pitches[0] + 1) / 2);
116 swdata->planes[0] = swdata->pixels;
117 swdata->planes[1] = swdata->planes[0] + swdata->pitches[0] * h;
118 break;
119
120 default:
121 SDL_assert(0 && "We should never get here (caught above)");
122 break;
123 }
124
125 /* We're all done.. */
126 return (swdata);
127}
128
129int
131 int *pitch)
132{
133 *pixels = swdata->planes[0];
134 *pitch = swdata->pitches[0];
135 return 0;
136}
137
138int
140 const void *pixels, int pitch)
141{
142 switch (swdata->format) {
145 if (rect->x == 0 && rect->y == 0 &&
146 rect->w == swdata->w && rect->h == swdata->h) {
147 SDL_memcpy(swdata->pixels, pixels,
148 (swdata->h * swdata->w) + 2* ((swdata->h + 1) /2) * ((swdata->w + 1) / 2));
149 } else {
150 Uint8 *src, *dst;
151 int row;
152 size_t length;
153
154 /* Copy the Y plane */
155 src = (Uint8 *) pixels;
156 dst = swdata->pixels + rect->y * swdata->w + rect->x;
157 length = rect->w;
158 for (row = 0; row < rect->h; ++row) {
160 src += pitch;
161 dst += swdata->w;
162 }
163
164 /* Copy the next plane */
165 src = (Uint8 *) pixels + rect->h * pitch;
166 dst = swdata->pixels + swdata->h * swdata->w;
167 dst += rect->y/2 * ((swdata->w + 1) / 2) + rect->x/2;
168 length = (rect->w + 1) / 2;
169 for (row = 0; row < (rect->h + 1)/2; ++row) {
171 src += (pitch + 1)/2;
172 dst += (swdata->w + 1)/2;
173 }
174
175 /* Copy the next plane */
176 src = (Uint8 *) pixels + rect->h * pitch + ((rect->h + 1) / 2) * ((pitch + 1) / 2);
177 dst = swdata->pixels + swdata->h * swdata->w +
178 ((swdata->h + 1)/2) * ((swdata->w+1) / 2);
179 dst += rect->y/2 * ((swdata->w + 1)/2) + rect->x/2;
180 length = (rect->w + 1) / 2;
181 for (row = 0; row < (rect->h + 1)/2; ++row) {
183 src += (pitch + 1)/2;
184 dst += (swdata->w + 1)/2;
185 }
186 }
187 break;
191 {
192 Uint8 *src, *dst;
193 int row;
194 size_t length;
195
196 src = (Uint8 *) pixels;
197 dst =
198 swdata->planes[0] + rect->y * swdata->pitches[0] +
199 rect->x * 2;
200 length = 4 * ((rect->w + 1) / 2);
201 for (row = 0; row < rect->h; ++row) {
203 src += pitch;
204 dst += swdata->pitches[0];
205 }
206 }
207 break;
210 {
211 if (rect->x == 0 && rect->y == 0 && rect->w == swdata->w && rect->h == swdata->h) {
212 SDL_memcpy(swdata->pixels, pixels,
213 (swdata->h * swdata->w) + 2* ((swdata->h + 1) /2) * ((swdata->w + 1) / 2));
214 } else {
215
216 Uint8 *src, *dst;
217 int row;
218 size_t length;
219
220 /* Copy the Y plane */
221 src = (Uint8 *) pixels;
222 dst = swdata->pixels + rect->y * swdata->w + rect->x;
223 length = rect->w;
224 for (row = 0; row < rect->h; ++row) {
226 src += pitch;
227 dst += swdata->w;
228 }
229
230 /* Copy the next plane */
231 src = (Uint8 *) pixels + rect->h * pitch;
232 dst = swdata->pixels + swdata->h * swdata->w;
233 dst += 2 * ((rect->y + 1)/2) * ((swdata->w + 1) / 2) + 2 * (rect->x/2);
234 length = 2 * ((rect->w + 1) / 2);
235 for (row = 0; row < (rect->h + 1)/2; ++row) {
237 src += 2 * ((pitch + 1)/2);
238 dst += 2 * ((swdata->w + 1)/2);
239 }
240 }
241 }
242 }
243 return 0;
244}
245
246int
248 const Uint8 *Yplane, int Ypitch,
249 const Uint8 *Uplane, int Upitch,
250 const Uint8 *Vplane, int Vpitch)
251{
252 const Uint8 *src;
253 Uint8 *dst;
254 int row;
255 size_t length;
256
257 /* Copy the Y plane */
258 src = Yplane;
259 dst = swdata->pixels + rect->y * swdata->w + rect->x;
260 length = rect->w;
261 for (row = 0; row < rect->h; ++row) {
263 src += Ypitch;
264 dst += swdata->w;
265 }
266
267 /* Copy the U plane */
268 src = Uplane;
269 if (swdata->format == SDL_PIXELFORMAT_IYUV) {
270 dst = swdata->pixels + swdata->h * swdata->w;
271 } else {
272 dst = swdata->pixels + swdata->h * swdata->w +
273 ((swdata->h + 1) / 2) * ((swdata->w + 1) / 2);
274 }
275 dst += rect->y/2 * ((swdata->w + 1)/2) + rect->x/2;
276 length = (rect->w + 1) / 2;
277 for (row = 0; row < (rect->h + 1)/2; ++row) {
279 src += Upitch;
280 dst += (swdata->w + 1)/2;
281 }
282
283 /* Copy the V plane */
284 src = Vplane;
285 if (swdata->format == SDL_PIXELFORMAT_YV12) {
286 dst = swdata->pixels + swdata->h * swdata->w;
287 } else {
288 dst = swdata->pixels + swdata->h * swdata->w +
289 ((swdata->h + 1) / 2) * ((swdata->w + 1) / 2);
290 }
291 dst += rect->y/2 * ((swdata->w + 1)/2) + rect->x/2;
292 length = (rect->w + 1) / 2;
293 for (row = 0; row < (rect->h + 1)/2; ++row) {
295 src += Vpitch;
296 dst += (swdata->w + 1)/2;
297 }
298 return 0;
299}
300
301int
303 void **pixels, int *pitch)
304{
305 switch (swdata->format) {
310 if (rect
311 && (rect->x != 0 || rect->y != 0 || rect->w != swdata->w
312 || rect->h != swdata->h)) {
313 return SDL_SetError
314 ("YV12, IYUV, NV12, NV21 textures only support full surface locks");
315 }
316 break;
317 }
318
319 if (rect) {
320 *pixels = swdata->planes[0] + rect->y * swdata->pitches[0] + rect->x * 2;
321 } else {
322 *pixels = swdata->planes[0];
323 }
324 *pitch = swdata->pitches[0];
325 return 0;
326}
327
328void
330{
331}
332
333int
335 Uint32 target_format, int w, int h, void *pixels,
336 int pitch)
337{
338 int stretch;
339
340 /* Make sure we're set up to display in the desired format */
341 if (target_format != swdata->target_format && swdata->display) {
342 SDL_FreeSurface(swdata->display);
343 swdata->display = NULL;
344 }
345
346 stretch = 0;
347 if (srcrect->x || srcrect->y || srcrect->w < swdata->w || srcrect->h < swdata->h) {
348 /* The source rectangle has been clipped.
349 Using a scratch surface is easier than adding clipped
350 source support to all the blitters, plus that would
351 slow them down in the general unclipped case.
352 */
353 stretch = 1;
354 } else if ((srcrect->w != w) || (srcrect->h != h)) {
355 stretch = 1;
356 }
357 if (stretch) {
358 int bpp;
359 Uint32 Rmask, Gmask, Bmask, Amask;
360
361 if (swdata->display) {
362 swdata->display->w = w;
363 swdata->display->h = h;
364 swdata->display->pixels = pixels;
365 swdata->display->pitch = pitch;
366 } else {
367 /* This must have succeeded in SDL_SW_SetupYUVDisplay() earlier */
368 SDL_PixelFormatEnumToMasks(target_format, &bpp, &Rmask, &Gmask,
369 &Bmask, &Amask);
370 swdata->display =
371 SDL_CreateRGBSurfaceFrom(pixels, w, h, bpp, pitch, Rmask,
372 Gmask, Bmask, Amask);
373 if (!swdata->display) {
374 return (-1);
375 }
376 }
377 if (!swdata->stretch) {
378 /* This must have succeeded in SDL_SW_SetupYUVDisplay() earlier */
379 SDL_PixelFormatEnumToMasks(target_format, &bpp, &Rmask, &Gmask,
380 &Bmask, &Amask);
381 swdata->stretch =
382 SDL_CreateRGBSurface(0, swdata->w, swdata->h, bpp, Rmask,
383 Gmask, Bmask, Amask);
384 if (!swdata->stretch) {
385 return (-1);
386 }
387 }
388 pixels = swdata->stretch->pixels;
389 pitch = swdata->stretch->pitch;
390 }
391 if (SDL_ConvertPixels(swdata->w, swdata->h, swdata->format,
392 swdata->planes[0], swdata->pitches[0],
393 target_format, pixels, pitch) < 0) {
394 return -1;
395 }
396 if (stretch) {
397 SDL_Rect rect = *srcrect;
398 SDL_SoftStretch(swdata->stretch, &rect, swdata->display, NULL);
399 }
400 return 0;
401}
402
403void
405{
406 if (swdata) {
407 SDL_free(swdata->pixels);
408 SDL_FreeSurface(swdata->stretch);
409 SDL_FreeSurface(swdata->display);
410 SDL_free(swdata);
411 }
412}
413
414/* vi: set ts=4 sw=4 expandtab: */
#define SDL_assert(condition)
Definition: SDL_assert.h:169
#define SDL_SetError
#define SDL_SoftStretch
#define SDL_malloc
#define SDL_PixelFormatEnumToMasks
#define SDL_free
#define SDL_CreateRGBSurfaceFrom
#define SDL_CreateRGBSurface
#define SDL_memcpy
#define SDL_FreeSurface
#define SDL_calloc
#define SDL_ConvertPixels
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
Definition: SDL_opengl.h:1572
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
GLenum src
GLenum GLenum dst
GLenum GLenum void * row
GLuint GLsizei GLsizei * length
GLfloat GLfloat GLfloat GLfloat h
GLubyte GLubyte GLubyte GLubyte w
@ SDL_PIXELFORMAT_YVYU
Definition: SDL_pixels.h:285
@ SDL_PIXELFORMAT_UYVY
Definition: SDL_pixels.h:283
@ SDL_PIXELFORMAT_YV12
Definition: SDL_pixels.h:277
@ SDL_PIXELFORMAT_YUY2
Definition: SDL_pixels.h:281
@ SDL_PIXELFORMAT_NV12
Definition: SDL_pixels.h:287
@ SDL_PIXELFORMAT_NV21
Definition: SDL_pixels.h:289
@ SDL_PIXELFORMAT_IYUV
Definition: SDL_pixels.h:279
@ SDL_PIXELFORMAT_UNKNOWN
Definition: SDL_pixels.h:173
uint32_t Uint32
Definition: SDL_stdinc.h:203
uint8_t Uint8
Definition: SDL_stdinc.h:179
void SDL_SW_DestroyYUVTexture(SDL_SW_YUVTexture *swdata)
Definition: SDL_yuv_sw.c:404
int SDL_SW_CopyYUVToRGB(SDL_SW_YUVTexture *swdata, const SDL_Rect *srcrect, Uint32 target_format, int w, int h, void *pixels, int pitch)
Definition: SDL_yuv_sw.c:334
int SDL_SW_UpdateYUVTexturePlanar(SDL_SW_YUVTexture *swdata, const SDL_Rect *rect, const Uint8 *Yplane, int Ypitch, const Uint8 *Uplane, int Upitch, const Uint8 *Vplane, int Vpitch)
Definition: SDL_yuv_sw.c:247
int SDL_SW_UpdateYUVTexture(SDL_SW_YUVTexture *swdata, const SDL_Rect *rect, const void *pixels, int pitch)
Definition: SDL_yuv_sw.c:139
int SDL_SW_LockYUVTexture(SDL_SW_YUVTexture *swdata, const SDL_Rect *rect, void **pixels, int *pitch)
Definition: SDL_yuv_sw.c:302
SDL_SW_YUVTexture * SDL_SW_CreateYUVTexture(Uint32 format, int w, int h)
Definition: SDL_yuv_sw.c:31
int SDL_SW_QueryYUVTexturePixels(SDL_SW_YUVTexture *swdata, void **pixels, int *pitch)
Definition: SDL_yuv_sw.c:130
void SDL_SW_UnlockYUVTexture(SDL_SW_YUVTexture *swdata)
Definition: SDL_yuv_sw.c:329
#define NULL
Definition: begin_code.h:167
A rectangle, with the origin at the upper left (integer).
Definition: SDL_rect.h:78
int h
Definition: SDL_rect.h:80
int w
Definition: SDL_rect.h:80
int y
Definition: SDL_rect.h:79
int x
Definition: SDL_rect.h:79
SDL_Surface * stretch
Definition: SDL_yuv_sw_c.h:43
SDL_Surface * display
Definition: SDL_yuv_sw_c.h:44
Uint16 pitches[3]
Definition: SDL_yuv_sw_c.h:39
Uint8 * planes[3]
Definition: SDL_yuv_sw_c.h:40
void * pixels
Definition: SDL_surface.h:76
SDL_Rect rect
Definition: testrelative.c:27