Added support for remote XVideo (thanks Frederic!)
--HG-- extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%40814
This commit is contained in:
parent
4434a0e564
commit
b2cf21a244
1 changed files with 115 additions and 47 deletions
|
@ -32,9 +32,11 @@ static char rcsid =
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
|
#ifndef NO_SHARED_MEMORY
|
||||||
#include <sys/ipc.h>
|
#include <sys/ipc.h>
|
||||||
#include <sys/shm.h>
|
#include <sys/shm.h>
|
||||||
#include <X11/extensions/XShm.h>
|
#include <X11/extensions/XShm.h>
|
||||||
|
#endif
|
||||||
#include <XFree86/extensions/Xvlib.h>
|
#include <XFree86/extensions/Xvlib.h>
|
||||||
|
|
||||||
#include "SDL_error.h"
|
#include "SDL_error.h"
|
||||||
|
@ -63,11 +65,29 @@ static struct private_yuvhwfuncs x11_yuvfuncs = {
|
||||||
|
|
||||||
struct private_yuvhwdata {
|
struct private_yuvhwdata {
|
||||||
int port;
|
int port;
|
||||||
|
#ifndef NO_SHARED_MEMORY
|
||||||
|
int yuv_use_mitshm;
|
||||||
XShmSegmentInfo yuvshm;
|
XShmSegmentInfo yuvshm;
|
||||||
|
#endif
|
||||||
SDL_NAME(XvImage) *image;
|
SDL_NAME(XvImage) *image;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef NO_SHARED_MEMORY
|
||||||
|
/* Shared memory error handler routine */
|
||||||
|
static int shm_error;
|
||||||
|
static int (*X_handler)(Display *, XErrorEvent *) = NULL;
|
||||||
|
static int shm_errhandler(Display *d, XErrorEvent *e)
|
||||||
|
{
|
||||||
|
if ( e->error_code == BadAccess ) {
|
||||||
|
shm_error = True;
|
||||||
|
return(0);
|
||||||
|
} else
|
||||||
|
return(X_handler(d,e));
|
||||||
|
}
|
||||||
|
#endif /* !NO_SHARED_MEMORY */
|
||||||
|
|
||||||
|
|
||||||
SDL_Overlay *X11_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display)
|
SDL_Overlay *X11_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display)
|
||||||
{
|
{
|
||||||
SDL_Overlay *overlay;
|
SDL_Overlay *overlay;
|
||||||
|
@ -76,7 +96,10 @@ SDL_Overlay *X11_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, S
|
||||||
int i, j, k;
|
int i, j, k;
|
||||||
int adaptors;
|
int adaptors;
|
||||||
SDL_NAME(XvAdaptorInfo) *ainfo;
|
SDL_NAME(XvAdaptorInfo) *ainfo;
|
||||||
|
int bpp;
|
||||||
|
#ifndef NO_SHARED_MEMORY
|
||||||
XShmSegmentInfo *yuvshm;
|
XShmSegmentInfo *yuvshm;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Look for the XVideo extension with a valid port for this format */
|
/* Look for the XVideo extension with a valid port for this format */
|
||||||
xv_port = -1;
|
xv_port = -1;
|
||||||
|
@ -133,6 +156,19 @@ SDL_Overlay *X11_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, S
|
||||||
SDL_NAME(XvFreeAdaptorInfo)(ainfo);
|
SDL_NAME(XvFreeAdaptorInfo)(ainfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Precalculate the bpp for the pitch workaround below */
|
||||||
|
switch (format) {
|
||||||
|
/* Add any other cases we need to support... */
|
||||||
|
case SDL_YUY2_OVERLAY:
|
||||||
|
case SDL_UYVY_OVERLAY:
|
||||||
|
case SDL_YVYU_OVERLAY:
|
||||||
|
bpp = 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
bpp = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/*
|
/*
|
||||||
* !!! FIXME:
|
* !!! FIXME:
|
||||||
|
@ -183,57 +219,77 @@ SDL_Overlay *X11_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, S
|
||||||
SDL_FreeYUVOverlay(overlay);
|
SDL_FreeYUVOverlay(overlay);
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
hwdata->port = xv_port;
|
||||||
|
#ifndef NO_SHARED_MEMORY
|
||||||
yuvshm = &hwdata->yuvshm;
|
yuvshm = &hwdata->yuvshm;
|
||||||
memset(yuvshm, 0, sizeof(*yuvshm));
|
memset(yuvshm, 0, sizeof(*yuvshm));
|
||||||
hwdata->port = xv_port;
|
|
||||||
hwdata->image = SDL_NAME(XvShmCreateImage)(GFX_Display, xv_port, format,
|
hwdata->image = SDL_NAME(XvShmCreateImage)(GFX_Display, xv_port, format,
|
||||||
0, width, height, yuvshm);
|
0, width, height, yuvshm);
|
||||||
|
#ifdef PITCH_WORKAROUND
|
||||||
|
if ( hwdata->image != NULL && hwdata->image->pitches[0] != (width*bpp) ) {
|
||||||
|
/* Ajust overlay width according to pitch */
|
||||||
|
XFree(hwdata->image);
|
||||||
|
width = hwdata->image->pitches[0] / bpp;
|
||||||
|
hwdata->image = SDL_NAME(XvShmCreateImage)(GFX_Display, xv_port, format,
|
||||||
|
0, width, height, yuvshm);
|
||||||
|
}
|
||||||
|
#endif /* PITCH_WORKAROUND */
|
||||||
|
hwdata->yuv_use_mitshm = (hwdata->image != NULL);
|
||||||
|
if ( hwdata->yuv_use_mitshm ) {
|
||||||
|
yuvshm->shmid = shmget(IPC_PRIVATE, hwdata->image->data_size,
|
||||||
|
IPC_CREAT | 0777);
|
||||||
|
if ( yuvshm->shmid >= 0 ) {
|
||||||
|
yuvshm->shmaddr = (char *)shmat(yuvshm->shmid, 0, 0);
|
||||||
|
yuvshm->readOnly = False;
|
||||||
|
if ( yuvshm->shmaddr != (char *)-1 ) {
|
||||||
|
shm_error = False;
|
||||||
|
X_handler = XSetErrorHandler(shm_errhandler);
|
||||||
|
XShmAttach(GFX_Display, yuvshm);
|
||||||
|
XSync(GFX_Display, True);
|
||||||
|
XSetErrorHandler(X_handler);
|
||||||
|
if ( shm_error )
|
||||||
|
shmdt(yuvshm->shmaddr);
|
||||||
|
} else {
|
||||||
|
shm_error = True;
|
||||||
|
}
|
||||||
|
shmctl(yuvshm->shmid, IPC_RMID, NULL);
|
||||||
|
} else {
|
||||||
|
shm_error = True;
|
||||||
|
}
|
||||||
|
if ( shm_error ) {
|
||||||
|
XFree(hwdata->image);
|
||||||
|
hwdata->yuv_use_mitshm = 0;
|
||||||
|
} else {
|
||||||
|
hwdata->image->data = yuvshm->shmaddr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( !hwdata->yuv_use_mitshm )
|
||||||
|
#endif /* NO_SHARED_MEMORY */
|
||||||
|
{
|
||||||
|
hwdata->image = SDL_NAME(XvCreateImage)(GFX_Display, xv_port, format,
|
||||||
|
0, width, height);
|
||||||
|
|
||||||
#ifdef PITCH_WORKAROUND
|
#ifdef PITCH_WORKAROUND
|
||||||
if ( hwdata->image != NULL && hwdata->image->pitches[0] != width )
|
if ( hwdata->image != NULL && hwdata->image->pitches[0] != (width*bpp) ) {
|
||||||
{
|
/* Ajust overlay width according to pitch */
|
||||||
/* Ajust overlay width according to pitch */
|
XFree(hwdata->image);
|
||||||
switch (format) {
|
width = hwdata->image->pitches[0] / bpp;
|
||||||
case SDL_YV12_OVERLAY:
|
hwdata->image = SDL_NAME(XvCreateImage)(GFX_Display, xv_port, format,
|
||||||
case SDL_IYUV_OVERLAY:
|
0, width, height);
|
||||||
width = hwdata->image->pitches[0];
|
}
|
||||||
break;
|
#endif /* PITCH_WORKAROUND */
|
||||||
case SDL_YUY2_OVERLAY:
|
if ( hwdata->image == NULL ) {
|
||||||
case SDL_UYVY_OVERLAY:
|
SDL_SetError("Couldn't create XVideo image");
|
||||||
case SDL_YVYU_OVERLAY:
|
SDL_FreeYUVOverlay(overlay);
|
||||||
width = hwdata->image->pitches[0] / 2;
|
return(NULL);
|
||||||
break;
|
}
|
||||||
default:
|
hwdata->image->data = malloc(hwdata->image->data_size);
|
||||||
/* We should never get here (caught above) */
|
if ( hwdata->image->data == NULL ) {
|
||||||
return(NULL);
|
SDL_OutOfMemory();
|
||||||
}
|
SDL_FreeYUVOverlay(overlay);
|
||||||
|
return(NULL);
|
||||||
XFree(hwdata->image);
|
}
|
||||||
hwdata->image = SDL_NAME(XvShmCreateImage)(GFX_Display, xv_port, format,
|
|
||||||
0, width, height, yuvshm);
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if ( hwdata->image == NULL ) {
|
|
||||||
SDL_OutOfMemory();
|
|
||||||
SDL_FreeYUVOverlay(overlay);
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
yuvshm->shmid = shmget(IPC_PRIVATE, hwdata->image->data_size,
|
|
||||||
IPC_CREAT | 0777);
|
|
||||||
if ( yuvshm->shmid < 0 ) {
|
|
||||||
SDL_SetError("Unable to get %d bytes shared memory",
|
|
||||||
hwdata->image->data_size);
|
|
||||||
SDL_FreeYUVOverlay(overlay);
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
yuvshm->shmaddr = (char *) shmat(yuvshm->shmid, 0, 0);
|
|
||||||
yuvshm->readOnly = False;
|
|
||||||
hwdata->image->data = yuvshm->shmaddr;
|
|
||||||
|
|
||||||
XShmAttach(GFX_Display, yuvshm);
|
|
||||||
XSync(GFX_Display, False);
|
|
||||||
shmctl(yuvshm->shmid, IPC_RMID, 0);
|
|
||||||
|
|
||||||
/* Find the pitch and offset values for the overlay */
|
/* Find the pitch and offset values for the overlay */
|
||||||
overlay->planes = hwdata->image->num_planes;
|
overlay->planes = hwdata->image->num_planes;
|
||||||
|
@ -277,9 +333,19 @@ int X11_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *dstrect)
|
||||||
struct private_yuvhwdata *hwdata;
|
struct private_yuvhwdata *hwdata;
|
||||||
|
|
||||||
hwdata = overlay->hwdata;
|
hwdata = overlay->hwdata;
|
||||||
SDL_NAME(XvShmPutImage)(GFX_Display, hwdata->port, SDL_Window, SDL_GC,
|
#ifndef NO_SHARED_MEMORY
|
||||||
|
if ( hwdata->yuv_use_mitshm ) {
|
||||||
|
SDL_NAME(XvShmPutImage)(GFX_Display, hwdata->port, SDL_Window, SDL_GC,
|
||||||
hwdata->image, 0, 0, overlay->w, overlay->h,
|
hwdata->image, 0, 0, overlay->w, overlay->h,
|
||||||
dstrect->x, dstrect->y, dstrect->w, dstrect->h, False);
|
dstrect->x, dstrect->y, dstrect->w, dstrect->h, False);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
SDL_NAME(XvPutImage)(GFX_Display, hwdata->port, SDL_Window, SDL_GC,
|
||||||
|
hwdata->image, 0, 0, overlay->w, overlay->h,
|
||||||
|
dstrect->x, dstrect->y, dstrect->w, dstrect->h);
|
||||||
|
}
|
||||||
XSync(GFX_Display, False);
|
XSync(GFX_Display, False);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
@ -291,10 +357,12 @@ void X11_FreeYUVOverlay(_THIS, SDL_Overlay *overlay)
|
||||||
hwdata = overlay->hwdata;
|
hwdata = overlay->hwdata;
|
||||||
if ( hwdata ) {
|
if ( hwdata ) {
|
||||||
SDL_NAME(XvUngrabPort)(GFX_Display, hwdata->port, CurrentTime);
|
SDL_NAME(XvUngrabPort)(GFX_Display, hwdata->port, CurrentTime);
|
||||||
if ( hwdata->yuvshm.shmaddr ) {
|
#ifndef NO_SHARED_MEMORY
|
||||||
|
if ( hwdata->yuv_use_mitshm ) {
|
||||||
XShmDetach(GFX_Display, &hwdata->yuvshm);
|
XShmDetach(GFX_Display, &hwdata->yuvshm);
|
||||||
shmdt(hwdata->yuvshm.shmaddr);
|
shmdt(hwdata->yuvshm.shmaddr);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if ( hwdata->image ) {
|
if ( hwdata->image ) {
|
||||||
XFree(hwdata->image);
|
XFree(hwdata->image);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue