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 }