SDL  2.0
SDL_yuv_sw.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2020 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 #if SDL_HAVE_YUV
26 
27 
28 #include "SDL_yuv_sw_c.h"
29 
30 
33 {
34  SDL_SW_YUVTexture *swdata;
35 
36  switch (format) {
44  break;
45  default:
46  SDL_SetError("Unsupported YUV format");
47  return NULL;
48  }
49 
50  swdata = (SDL_SW_YUVTexture *) SDL_calloc(1, sizeof(*swdata));
51  if (!swdata) {
53  return NULL;
54  }
55 
56  swdata->format = format;
58  swdata->w = w;
59  swdata->h = h;
60  {
61  const int sz_plane = w * h;
62  const int sz_plane_chroma = ((w + 1) / 2) * ((h + 1) / 2);
63  const int sz_plane_packed = ((w + 1) / 2) * h;
64  int dst_size = 0;
65  switch(format)
66  {
67  case SDL_PIXELFORMAT_YV12: /**< Planar mode: Y + V + U (3 planes) */
68  case SDL_PIXELFORMAT_IYUV: /**< Planar mode: Y + U + V (3 planes) */
69  dst_size = sz_plane + sz_plane_chroma + sz_plane_chroma;
70  break;
71 
72  case SDL_PIXELFORMAT_YUY2: /**< Packed mode: Y0+U0+Y1+V0 (1 plane) */
73  case SDL_PIXELFORMAT_UYVY: /**< Packed mode: U0+Y0+V0+Y1 (1 plane) */
74  case SDL_PIXELFORMAT_YVYU: /**< Packed mode: Y0+V0+Y1+U0 (1 plane) */
75  dst_size = 4 * sz_plane_packed;
76  break;
77 
78  case SDL_PIXELFORMAT_NV12: /**< Planar mode: Y + U/V interleaved (2 planes) */
79  case SDL_PIXELFORMAT_NV21: /**< Planar mode: Y + V/U interleaved (2 planes) */
80  dst_size = sz_plane + sz_plane_chroma + sz_plane_chroma;
81  break;
82 
83  default:
84  SDL_assert(0 && "We should never get here (caught above)");
85  break;
86  }
87  swdata->pixels = (Uint8 *) SDL_malloc(dst_size);
88  if (!swdata->pixels) {
91  return NULL;
92  }
93  }
94 
95  /* Find the pitch and offset values for the texture */
96  switch (format) {
99  swdata->pitches[0] = w;
100  swdata->pitches[1] = (swdata->pitches[0] + 1) / 2;
101  swdata->pitches[2] = (swdata->pitches[0] + 1) / 2;
102  swdata->planes[0] = swdata->pixels;
103  swdata->planes[1] = swdata->planes[0] + swdata->pitches[0] * h;
104  swdata->planes[2] = swdata->planes[1] + swdata->pitches[1] * ((h + 1) / 2);
105  break;
109  swdata->pitches[0] = ((w + 1) / 2) * 4;
110  swdata->planes[0] = swdata->pixels;
111  break;
112 
115  swdata->pitches[0] = w;
116  swdata->pitches[1] = 2 * ((swdata->pitches[0] + 1) / 2);
117  swdata->planes[0] = swdata->pixels;
118  swdata->planes[1] = swdata->planes[0] + swdata->pitches[0] * h;
119  break;
120 
121  default:
122  SDL_assert(0 && "We should never get here (caught above)");
123  break;
124  }
125 
126  /* We're all done.. */
127  return (swdata);
128 }
129 
130 int
132  int *pitch)
133 {
134  *pixels = swdata->planes[0];
135  *pitch = swdata->pitches[0];
136  return 0;
137 }
138 
139 int
141  const void *pixels, int pitch)
142 {
143  switch (swdata->format) {
146  if (rect->x == 0 && rect->y == 0 &&
147  rect->w == swdata->w && rect->h == swdata->h) {
148  SDL_memcpy(swdata->pixels, pixels,
149  (swdata->h * swdata->w) + 2* ((swdata->h + 1) /2) * ((swdata->w + 1) / 2));
150  } else {
151  Uint8 *src, *dst;
152  int row;
153  size_t length;
154 
155  /* Copy the Y plane */
156  src = (Uint8 *) pixels;
157  dst = swdata->pixels + rect->y * swdata->w + rect->x;
158  length = rect->w;
159  for (row = 0; row < rect->h; ++row) {
161  src += pitch;
162  dst += swdata->w;
163  }
164 
165  /* Copy the next plane */
166  src = (Uint8 *) pixels + rect->h * pitch;
167  dst = swdata->pixels + swdata->h * swdata->w;
168  dst += rect->y/2 * ((swdata->w + 1) / 2) + rect->x/2;
169  length = (rect->w + 1) / 2;
170  for (row = 0; row < (rect->h + 1)/2; ++row) {
172  src += (pitch + 1)/2;
173  dst += (swdata->w + 1)/2;
174  }
175 
176  /* Copy the next plane */
177  src = (Uint8 *) pixels + rect->h * pitch + ((rect->h + 1) / 2) * ((pitch + 1) / 2);
178  dst = swdata->pixels + swdata->h * swdata->w +
179  ((swdata->h + 1)/2) * ((swdata->w+1) / 2);
180  dst += rect->y/2 * ((swdata->w + 1)/2) + rect->x/2;
181  length = (rect->w + 1) / 2;
182  for (row = 0; row < (rect->h + 1)/2; ++row) {
184  src += (pitch + 1)/2;
185  dst += (swdata->w + 1)/2;
186  }
187  }
188  break;
192  {
193  Uint8 *src, *dst;
194  int row;
195  size_t length;
196 
197  src = (Uint8 *) pixels;
198  dst =
199  swdata->planes[0] + rect->y * swdata->pitches[0] +
200  rect->x * 2;
201  length = 4 * ((rect->w + 1) / 2);
202  for (row = 0; row < rect->h; ++row) {
204  src += pitch;
205  dst += swdata->pitches[0];
206  }
207  }
208  break;
211  {
212  if (rect->x == 0 && rect->y == 0 && rect->w == swdata->w && rect->h == swdata->h) {
213  SDL_memcpy(swdata->pixels, pixels,
214  (swdata->h * swdata->w) + 2* ((swdata->h + 1) /2) * ((swdata->w + 1) / 2));
215  } else {
216 
217  Uint8 *src, *dst;
218  int row;
219  size_t length;
220 
221  /* Copy the Y plane */
222  src = (Uint8 *) pixels;
223  dst = swdata->pixels + rect->y * swdata->w + rect->x;
224  length = rect->w;
225  for (row = 0; row < rect->h; ++row) {
227  src += pitch;
228  dst += swdata->w;
229  }
230 
231  /* Copy the next plane */
232  src = (Uint8 *) pixels + rect->h * pitch;
233  dst = swdata->pixels + swdata->h * swdata->w;
234  dst += 2 * ((rect->y + 1)/2) * ((swdata->w + 1) / 2) + 2 * (rect->x/2);
235  length = 2 * ((rect->w + 1) / 2);
236  for (row = 0; row < (rect->h + 1)/2; ++row) {
238  src += 2 * ((pitch + 1)/2);
239  dst += 2 * ((swdata->w + 1)/2);
240  }
241  }
242  }
243  }
244  return 0;
245 }
246 
247 int
249  const Uint8 *Yplane, int Ypitch,
250  const Uint8 *Uplane, int Upitch,
251  const Uint8 *Vplane, int Vpitch)
252 {
253  const Uint8 *src;
254  Uint8 *dst;
255  int row;
256  size_t length;
257 
258  /* Copy the Y plane */
259  src = Yplane;
260  dst = swdata->pixels + rect->y * swdata->w + rect->x;
261  length = rect->w;
262  for (row = 0; row < rect->h; ++row) {
264  src += Ypitch;
265  dst += swdata->w;
266  }
267 
268  /* Copy the U plane */
269  src = Uplane;
270  if (swdata->format == SDL_PIXELFORMAT_IYUV) {
271  dst = swdata->pixels + swdata->h * swdata->w;
272  } else {
273  dst = swdata->pixels + swdata->h * swdata->w +
274  ((swdata->h + 1) / 2) * ((swdata->w + 1) / 2);
275  }
276  dst += rect->y/2 * ((swdata->w + 1)/2) + rect->x/2;
277  length = (rect->w + 1) / 2;
278  for (row = 0; row < (rect->h + 1)/2; ++row) {
280  src += Upitch;
281  dst += (swdata->w + 1)/2;
282  }
283 
284  /* Copy the V plane */
285  src = Vplane;
286  if (swdata->format == SDL_PIXELFORMAT_YV12) {
287  dst = swdata->pixels + swdata->h * swdata->w;
288  } else {
289  dst = swdata->pixels + swdata->h * swdata->w +
290  ((swdata->h + 1) / 2) * ((swdata->w + 1) / 2);
291  }
292  dst += rect->y/2 * ((swdata->w + 1)/2) + rect->x/2;
293  length = (rect->w + 1) / 2;
294  for (row = 0; row < (rect->h + 1)/2; ++row) {
296  src += Vpitch;
297  dst += (swdata->w + 1)/2;
298  }
299  return 0;
300 }
301 
302 int
304  void **pixels, int *pitch)
305 {
306  switch (swdata->format) {
311  if (rect
312  && (rect->x != 0 || rect->y != 0 || rect->w != swdata->w
313  || rect->h != swdata->h)) {
314  return SDL_SetError
315  ("YV12, IYUV, NV12, NV21 textures only support full surface locks");
316  }
317  break;
318  }
319 
320  if (rect) {
321  *pixels = swdata->planes[0] + rect->y * swdata->pitches[0] + rect->x * 2;
322  } else {
323  *pixels = swdata->planes[0];
324  }
325  *pitch = swdata->pitches[0];
326  return 0;
327 }
328 
329 void
331 {
332 }
333 
334 int
336  Uint32 target_format, int w, int h, void *pixels,
337  int pitch)
338 {
339  int stretch;
340 
341  /* Make sure we're set up to display in the desired format */
342  if (target_format != swdata->target_format && swdata->display) {
343  SDL_FreeSurface(swdata->display);
344  swdata->display = NULL;
345  }
346 
347  stretch = 0;
348  if (srcrect->x || srcrect->y || srcrect->w < swdata->w || srcrect->h < swdata->h) {
349  /* The source rectangle has been clipped.
350  Using a scratch surface is easier than adding clipped
351  source support to all the blitters, plus that would
352  slow them down in the general unclipped case.
353  */
354  stretch = 1;
355  } else if ((srcrect->w != w) || (srcrect->h != h)) {
356  stretch = 1;
357  }
358  if (stretch) {
359  int bpp;
360  Uint32 Rmask, Gmask, Bmask, Amask;
361 
362  if (swdata->display) {
363  swdata->display->w = w;
364  swdata->display->h = h;
365  swdata->display->pixels = pixels;
366  swdata->display->pitch = pitch;
367  } else {
368  /* This must have succeeded in SDL_SW_SetupYUVDisplay() earlier */
369  SDL_PixelFormatEnumToMasks(target_format, &bpp, &Rmask, &Gmask,
370  &Bmask, &Amask);
371  swdata->display =
372  SDL_CreateRGBSurfaceFrom(pixels, w, h, bpp, pitch, Rmask,
373  Gmask, Bmask, Amask);
374  if (!swdata->display) {
375  return (-1);
376  }
377  }
378  if (!swdata->stretch) {
379  /* This must have succeeded in SDL_SW_SetupYUVDisplay() earlier */
380  SDL_PixelFormatEnumToMasks(target_format, &bpp, &Rmask, &Gmask,
381  &Bmask, &Amask);
382  swdata->stretch =
383  SDL_CreateRGBSurface(0, swdata->w, swdata->h, bpp, Rmask,
384  Gmask, Bmask, Amask);
385  if (!swdata->stretch) {
386  return (-1);
387  }
388  }
389  pixels = swdata->stretch->pixels;
390  pitch = swdata->stretch->pitch;
391  }
392  if (SDL_ConvertPixels(swdata->w, swdata->h, swdata->format,
393  swdata->planes[0], swdata->pitches[0],
394  target_format, pixels, pitch) < 0) {
395  return -1;
396  }
397  if (stretch) {
398  SDL_Rect rect = *srcrect;
399  SDL_SoftStretch(swdata->stretch, &rect, swdata->display, NULL);
400  }
401  return 0;
402 }
403 
404 void
406 {
407  if (swdata) {
408  SDL_free(swdata->pixels);
409  SDL_FreeSurface(swdata->stretch);
410  SDL_FreeSurface(swdata->display);
411  SDL_free(swdata);
412  }
413 }
414 
415 #endif /* SDL_HAVE_YUV */
416 
417 /* vi: set ts=4 sw=4 expandtab: */
#define SDL_assert(condition)
Definition: SDL_assert.h:171
#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:88
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:294
@ SDL_PIXELFORMAT_UYVY
Definition: SDL_pixels.h:292
@ SDL_PIXELFORMAT_YV12
Definition: SDL_pixels.h:286
@ SDL_PIXELFORMAT_YUY2
Definition: SDL_pixels.h:290
@ SDL_PIXELFORMAT_NV12
Definition: SDL_pixels.h:296
@ SDL_PIXELFORMAT_NV21
Definition: SDL_pixels.h:298
@ SDL_PIXELFORMAT_IYUV
Definition: SDL_pixels.h:288
@ SDL_PIXELFORMAT_UNKNOWN
Definition: SDL_pixels.h:173
uint8_t Uint8
Definition: SDL_stdinc.h:185
uint32_t Uint32
Definition: SDL_stdinc.h:209
void SDL_SW_DestroyYUVTexture(SDL_SW_YUVTexture *swdata)
Definition: SDL_yuv_sw.c:405
SDL_SW_YUVTexture * SDL_SW_CreateYUVTexture(Uint32 format, int w, int h)
Definition: SDL_yuv_sw.c:32
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:335
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:248
int SDL_SW_UpdateYUVTexture(SDL_SW_YUVTexture *swdata, const SDL_Rect *rect, const void *pixels, int pitch)
Definition: SDL_yuv_sw.c:140
int SDL_SW_LockYUVTexture(SDL_SW_YUVTexture *swdata, const SDL_Rect *rect, void **pixels, int *pitch)
Definition: SDL_yuv_sw.c:303
int SDL_SW_QueryYUVTexturePixels(SDL_SW_YUVTexture *swdata, void **pixels, int *pitch)
Definition: SDL_yuv_sw.c:131
void SDL_SW_UnlockYUVTexture(SDL_SW_YUVTexture *swdata)
Definition: SDL_yuv_sw.c:330
#define NULL
Definition: begin_code.h:163
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp
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