Mercurial > sdl-ios-xcode
comparison src/video/x11/SDL_x11yuv.c @ 813:6a2c6717b386
Added support for remote XVideo (thanks Frederic!)
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Thu, 12 Feb 2004 16:05:30 +0000 |
parents | b8d311d90021 |
children | b7a5c1b64829 |
comparison
equal
deleted
inserted
replaced
812:d315a411d5b2 | 813:6a2c6717b386 |
---|---|
30 #ifdef XFREE86_XV | 30 #ifdef XFREE86_XV |
31 | 31 |
32 #include <stdlib.h> | 32 #include <stdlib.h> |
33 #include <string.h> | 33 #include <string.h> |
34 #include <X11/Xlib.h> | 34 #include <X11/Xlib.h> |
35 #ifndef NO_SHARED_MEMORY | |
35 #include <sys/ipc.h> | 36 #include <sys/ipc.h> |
36 #include <sys/shm.h> | 37 #include <sys/shm.h> |
37 #include <X11/extensions/XShm.h> | 38 #include <X11/extensions/XShm.h> |
39 #endif | |
38 #include <XFree86/extensions/Xvlib.h> | 40 #include <XFree86/extensions/Xvlib.h> |
39 | 41 |
40 #include "SDL_error.h" | 42 #include "SDL_error.h" |
41 #include "SDL_video.h" | 43 #include "SDL_video.h" |
42 #include "SDL_x11yuv_c.h" | 44 #include "SDL_x11yuv_c.h" |
61 X11_FreeYUVOverlay | 63 X11_FreeYUVOverlay |
62 }; | 64 }; |
63 | 65 |
64 struct private_yuvhwdata { | 66 struct private_yuvhwdata { |
65 int port; | 67 int port; |
68 #ifndef NO_SHARED_MEMORY | |
69 int yuv_use_mitshm; | |
66 XShmSegmentInfo yuvshm; | 70 XShmSegmentInfo yuvshm; |
71 #endif | |
67 SDL_NAME(XvImage) *image; | 72 SDL_NAME(XvImage) *image; |
68 }; | 73 }; |
74 | |
75 | |
76 #ifndef NO_SHARED_MEMORY | |
77 /* Shared memory error handler routine */ | |
78 static int shm_error; | |
79 static int (*X_handler)(Display *, XErrorEvent *) = NULL; | |
80 static int shm_errhandler(Display *d, XErrorEvent *e) | |
81 { | |
82 if ( e->error_code == BadAccess ) { | |
83 shm_error = True; | |
84 return(0); | |
85 } else | |
86 return(X_handler(d,e)); | |
87 } | |
88 #endif /* !NO_SHARED_MEMORY */ | |
69 | 89 |
70 | 90 |
71 SDL_Overlay *X11_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display) | 91 SDL_Overlay *X11_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display) |
72 { | 92 { |
73 SDL_Overlay *overlay; | 93 SDL_Overlay *overlay; |
74 struct private_yuvhwdata *hwdata; | 94 struct private_yuvhwdata *hwdata; |
75 int xv_port; | 95 int xv_port; |
76 int i, j, k; | 96 int i, j, k; |
77 int adaptors; | 97 int adaptors; |
78 SDL_NAME(XvAdaptorInfo) *ainfo; | 98 SDL_NAME(XvAdaptorInfo) *ainfo; |
99 int bpp; | |
100 #ifndef NO_SHARED_MEMORY | |
79 XShmSegmentInfo *yuvshm; | 101 XShmSegmentInfo *yuvshm; |
102 #endif | |
80 | 103 |
81 /* Look for the XVideo extension with a valid port for this format */ | 104 /* Look for the XVideo extension with a valid port for this format */ |
82 xv_port = -1; | 105 xv_port = -1; |
83 if ( (Success == SDL_NAME(XvQueryExtension)(GFX_Display, &j, &j, &j, &j, &j)) && | 106 if ( (Success == SDL_NAME(XvQueryExtension)(GFX_Display, &j, &j, &j, &j, &j)) && |
84 (Success == SDL_NAME(XvQueryAdaptors)(GFX_Display, | 107 (Success == SDL_NAME(XvQueryAdaptors)(GFX_Display, |
131 } | 154 } |
132 } | 155 } |
133 SDL_NAME(XvFreeAdaptorInfo)(ainfo); | 156 SDL_NAME(XvFreeAdaptorInfo)(ainfo); |
134 } | 157 } |
135 | 158 |
159 /* Precalculate the bpp for the pitch workaround below */ | |
160 switch (format) { | |
161 /* Add any other cases we need to support... */ | |
162 case SDL_YUY2_OVERLAY: | |
163 case SDL_UYVY_OVERLAY: | |
164 case SDL_YVYU_OVERLAY: | |
165 bpp = 2; | |
166 break; | |
167 default: | |
168 bpp = 1; | |
169 break; | |
170 } | |
171 | |
136 #if 0 | 172 #if 0 |
137 /* | 173 /* |
138 * !!! FIXME: | 174 * !!! FIXME: |
139 * "Here are some diffs for X11 and yuv. Note that the last part 2nd | 175 * "Here are some diffs for X11 and yuv. Note that the last part 2nd |
140 * diff should probably be a new call to XvQueryAdaptorFree with ainfo | 176 * diff should probably be a new call to XvQueryAdaptorFree with ainfo |
181 SDL_NAME(XvUngrabPort)(GFX_Display, xv_port, CurrentTime); | 217 SDL_NAME(XvUngrabPort)(GFX_Display, xv_port, CurrentTime); |
182 SDL_OutOfMemory(); | 218 SDL_OutOfMemory(); |
183 SDL_FreeYUVOverlay(overlay); | 219 SDL_FreeYUVOverlay(overlay); |
184 return(NULL); | 220 return(NULL); |
185 } | 221 } |
222 hwdata->port = xv_port; | |
223 #ifndef NO_SHARED_MEMORY | |
186 yuvshm = &hwdata->yuvshm; | 224 yuvshm = &hwdata->yuvshm; |
187 memset(yuvshm, 0, sizeof(*yuvshm)); | 225 memset(yuvshm, 0, sizeof(*yuvshm)); |
188 hwdata->port = xv_port; | |
189 hwdata->image = SDL_NAME(XvShmCreateImage)(GFX_Display, xv_port, format, | 226 hwdata->image = SDL_NAME(XvShmCreateImage)(GFX_Display, xv_port, format, |
190 0, width, height, yuvshm); | 227 0, width, height, yuvshm); |
191 | |
192 #ifdef PITCH_WORKAROUND | 228 #ifdef PITCH_WORKAROUND |
193 if ( hwdata->image != NULL && hwdata->image->pitches[0] != width ) | 229 if ( hwdata->image != NULL && hwdata->image->pitches[0] != (width*bpp) ) { |
230 /* Ajust overlay width according to pitch */ | |
231 XFree(hwdata->image); | |
232 width = hwdata->image->pitches[0] / bpp; | |
233 hwdata->image = SDL_NAME(XvShmCreateImage)(GFX_Display, xv_port, format, | |
234 0, width, height, yuvshm); | |
235 } | |
236 #endif /* PITCH_WORKAROUND */ | |
237 hwdata->yuv_use_mitshm = (hwdata->image != NULL); | |
238 if ( hwdata->yuv_use_mitshm ) { | |
239 yuvshm->shmid = shmget(IPC_PRIVATE, hwdata->image->data_size, | |
240 IPC_CREAT | 0777); | |
241 if ( yuvshm->shmid >= 0 ) { | |
242 yuvshm->shmaddr = (char *)shmat(yuvshm->shmid, 0, 0); | |
243 yuvshm->readOnly = False; | |
244 if ( yuvshm->shmaddr != (char *)-1 ) { | |
245 shm_error = False; | |
246 X_handler = XSetErrorHandler(shm_errhandler); | |
247 XShmAttach(GFX_Display, yuvshm); | |
248 XSync(GFX_Display, True); | |
249 XSetErrorHandler(X_handler); | |
250 if ( shm_error ) | |
251 shmdt(yuvshm->shmaddr); | |
252 } else { | |
253 shm_error = True; | |
254 } | |
255 shmctl(yuvshm->shmid, IPC_RMID, NULL); | |
256 } else { | |
257 shm_error = True; | |
258 } | |
259 if ( shm_error ) { | |
260 XFree(hwdata->image); | |
261 hwdata->yuv_use_mitshm = 0; | |
262 } else { | |
263 hwdata->image->data = yuvshm->shmaddr; | |
264 } | |
265 } | |
266 if ( !hwdata->yuv_use_mitshm ) | |
267 #endif /* NO_SHARED_MEMORY */ | |
194 { | 268 { |
195 /* Ajust overlay width according to pitch */ | 269 hwdata->image = SDL_NAME(XvCreateImage)(GFX_Display, xv_port, format, |
196 switch (format) { | 270 0, width, height); |
197 case SDL_YV12_OVERLAY: | 271 |
198 case SDL_IYUV_OVERLAY: | 272 #ifdef PITCH_WORKAROUND |
199 width = hwdata->image->pitches[0]; | 273 if ( hwdata->image != NULL && hwdata->image->pitches[0] != (width*bpp) ) { |
200 break; | 274 /* Ajust overlay width according to pitch */ |
201 case SDL_YUY2_OVERLAY: | 275 XFree(hwdata->image); |
202 case SDL_UYVY_OVERLAY: | 276 width = hwdata->image->pitches[0] / bpp; |
203 case SDL_YVYU_OVERLAY: | 277 hwdata->image = SDL_NAME(XvCreateImage)(GFX_Display, xv_port, format, |
204 width = hwdata->image->pitches[0] / 2; | 278 0, width, height); |
205 break; | 279 } |
206 default: | 280 #endif /* PITCH_WORKAROUND */ |
207 /* We should never get here (caught above) */ | 281 if ( hwdata->image == NULL ) { |
208 return(NULL); | 282 SDL_SetError("Couldn't create XVideo image"); |
209 } | 283 SDL_FreeYUVOverlay(overlay); |
210 | 284 return(NULL); |
211 XFree(hwdata->image); | 285 } |
212 hwdata->image = SDL_NAME(XvShmCreateImage)(GFX_Display, xv_port, format, | 286 hwdata->image->data = malloc(hwdata->image->data_size); |
213 0, width, height, yuvshm); | 287 if ( hwdata->image->data == NULL ) { |
214 } | 288 SDL_OutOfMemory(); |
215 #endif | 289 SDL_FreeYUVOverlay(overlay); |
216 | 290 return(NULL); |
217 if ( hwdata->image == NULL ) { | 291 } |
218 SDL_OutOfMemory(); | 292 } |
219 SDL_FreeYUVOverlay(overlay); | |
220 return(NULL); | |
221 } | |
222 yuvshm->shmid = shmget(IPC_PRIVATE, hwdata->image->data_size, | |
223 IPC_CREAT | 0777); | |
224 if ( yuvshm->shmid < 0 ) { | |
225 SDL_SetError("Unable to get %d bytes shared memory", | |
226 hwdata->image->data_size); | |
227 SDL_FreeYUVOverlay(overlay); | |
228 return(NULL); | |
229 } | |
230 yuvshm->shmaddr = (char *) shmat(yuvshm->shmid, 0, 0); | |
231 yuvshm->readOnly = False; | |
232 hwdata->image->data = yuvshm->shmaddr; | |
233 | |
234 XShmAttach(GFX_Display, yuvshm); | |
235 XSync(GFX_Display, False); | |
236 shmctl(yuvshm->shmid, IPC_RMID, 0); | |
237 | 293 |
238 /* Find the pitch and offset values for the overlay */ | 294 /* Find the pitch and offset values for the overlay */ |
239 overlay->planes = hwdata->image->num_planes; | 295 overlay->planes = hwdata->image->num_planes; |
240 overlay->pitches = (Uint16 *)malloc(overlay->planes * sizeof(Uint16)); | 296 overlay->pitches = (Uint16 *)malloc(overlay->planes * sizeof(Uint16)); |
241 overlay->pixels = (Uint8 **)malloc(overlay->planes * sizeof(Uint8 *)); | 297 overlay->pixels = (Uint8 **)malloc(overlay->planes * sizeof(Uint8 *)); |
275 int X11_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *dstrect) | 331 int X11_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *dstrect) |
276 { | 332 { |
277 struct private_yuvhwdata *hwdata; | 333 struct private_yuvhwdata *hwdata; |
278 | 334 |
279 hwdata = overlay->hwdata; | 335 hwdata = overlay->hwdata; |
280 SDL_NAME(XvShmPutImage)(GFX_Display, hwdata->port, SDL_Window, SDL_GC, | 336 #ifndef NO_SHARED_MEMORY |
337 if ( hwdata->yuv_use_mitshm ) { | |
338 SDL_NAME(XvShmPutImage)(GFX_Display, hwdata->port, SDL_Window, SDL_GC, | |
281 hwdata->image, 0, 0, overlay->w, overlay->h, | 339 hwdata->image, 0, 0, overlay->w, overlay->h, |
282 dstrect->x, dstrect->y, dstrect->w, dstrect->h, False); | 340 dstrect->x, dstrect->y, dstrect->w, dstrect->h, False); |
341 } | |
342 else | |
343 #endif | |
344 { | |
345 SDL_NAME(XvPutImage)(GFX_Display, hwdata->port, SDL_Window, SDL_GC, | |
346 hwdata->image, 0, 0, overlay->w, overlay->h, | |
347 dstrect->x, dstrect->y, dstrect->w, dstrect->h); | |
348 } | |
283 XSync(GFX_Display, False); | 349 XSync(GFX_Display, False); |
284 return(0); | 350 return(0); |
285 } | 351 } |
286 | 352 |
287 void X11_FreeYUVOverlay(_THIS, SDL_Overlay *overlay) | 353 void X11_FreeYUVOverlay(_THIS, SDL_Overlay *overlay) |
289 struct private_yuvhwdata *hwdata; | 355 struct private_yuvhwdata *hwdata; |
290 | 356 |
291 hwdata = overlay->hwdata; | 357 hwdata = overlay->hwdata; |
292 if ( hwdata ) { | 358 if ( hwdata ) { |
293 SDL_NAME(XvUngrabPort)(GFX_Display, hwdata->port, CurrentTime); | 359 SDL_NAME(XvUngrabPort)(GFX_Display, hwdata->port, CurrentTime); |
294 if ( hwdata->yuvshm.shmaddr ) { | 360 #ifndef NO_SHARED_MEMORY |
361 if ( hwdata->yuv_use_mitshm ) { | |
295 XShmDetach(GFX_Display, &hwdata->yuvshm); | 362 XShmDetach(GFX_Display, &hwdata->yuvshm); |
296 shmdt(hwdata->yuvshm.shmaddr); | 363 shmdt(hwdata->yuvshm.shmaddr); |
297 } | 364 } |
365 #endif | |
298 if ( hwdata->image ) { | 366 if ( hwdata->image ) { |
299 XFree(hwdata->image); | 367 XFree(hwdata->image); |
300 } | 368 } |
301 free(hwdata); | 369 free(hwdata); |
302 } | 370 } |