#define DISP /* * video_out_x11.c, X11 interface * * * Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. * * Hacked into mpeg2dec by * * Aaron Holtzman * * 15 & 16 bpp support added by Franck Sicard * * Xv image suuport by Gerd Knorr */ #include #include #include #include "config.h" #include "video_out.h" #include "video_out_internal.h" LIBVO_EXTERN(xv) #include #include #include #include #include "yuv2rgb.h" static vo_info_t vo_info = { "X11/Xv", "xv", "Gerd Knorr ", "" }; /* since it doesn't seem to be defined on some platforms */ int XShmGetEventBase(Display*); /* local data */ static unsigned char *ImageData; /* X11 related variables */ static Display *mydisplay; static Window mywindow; static GC mygc; static XImage *myximage; static int depth, bpp, mode; static XWindowAttributes attribs; #include #include // FIXME: dynamically allocate this stuff static void allocate_xvimage(int); static unsigned int ver,rel,req,ev,err; static unsigned int formats, adaptors,i,xv_port,xv_format; static int win_width,win_height; static XvAdaptorInfo *ai; static XvImageFormatValues *fo; static XvImage *xvimage[1]; #include #include #include static int Shmem_Flag; static int Quiet_Flag; static XShmSegmentInfo Shminfo[1]; static int gXErrorFlag; static int CompletionType = -1; static uint32_t image_width; static uint32_t image_height; static uint32_t image_format; static int get_depth(){ char *name = ":0.0"; if(getenv("DISPLAY")) name = getenv("DISPLAY"); mydisplay = XOpenDisplay(name); if (mydisplay == NULL) return 0; XGetWindowAttributes(mydisplay, DefaultRootWindow(mydisplay), &attribs); depth = attribs.depth; XCloseDisplay(mydisplay); if (depth != 15 && depth != 16 && depth != 24 && depth != 32) depth = 24; printf("X11 Display color depth = %d\n",depth); return depth; } extern void vo_decoration( Display * vo_Display,Window w,int d ); /* connect to server, create and map window, * allocate colors and (shared) memory */ static uint32_t init(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t fullscreen, char *title, uint32_t format) { int screen; // unsigned int fg, bg; char *hello = (title == NULL) ? "Xv rulez" : title; char *name = ":0.0"; XSizeHints hint; XVisualInfo vinfo; XEvent xev; XGCValues xgcv; Colormap theCmap; XSetWindowAttributes xswa; unsigned long xswamask; image_height = height; image_width = width; image_format=format; if(getenv("DISPLAY")) name = getenv("DISPLAY"); mydisplay = XOpenDisplay(name); if (mydisplay == NULL) { fprintf(stderr,"Can't open display\n"); return -1; } screen = DefaultScreen(mydisplay); hint.x = 0; hint.y = 0; hint.width = image_width; hint.height = image_height; hint.flags = PPosition | PSize; /* Get some colors */ // bg = WhitePixel(mydisplay, screen); // fg = BlackPixel(mydisplay, screen); /* Make the window */ XGetWindowAttributes(mydisplay, DefaultRootWindow(mydisplay), &attribs); /* * * depth in X11 terminology land is the number of bits used to * actually represent the colour. * * bpp in X11 land means how many bits in the frame buffer per * pixel. * * ex. 15 bit color is 15 bit depth and 16 bpp. Also 24 bit * color is 24 bit depth, but can be 24 bpp or 32 bpp. */ depth = attribs.depth; if (depth != 15 && depth != 16 && depth != 24 && depth != 32) { /* The root window may be 8bit but there might still be * visuals with other bit depths. For example this is the * case on Sun/Solaris machines. */ depth = 24; } //BEGIN HACK //mywindow = XCreateSimpleWindow(mydisplay, DefaultRootWindow(mydisplay), //hint.x, hint.y, hint.width, hint.height, 4, fg, bg); // XMatchVisualInfo(mydisplay, screen, depth, TrueColor, &vinfo); theCmap = XCreateColormap(mydisplay, RootWindow(mydisplay,screen), vinfo.visual, AllocNone); xswa.background_pixel = 0; xswa.border_pixel = 1; xswa.colormap = theCmap; xswamask = CWBackPixel | CWBorderPixel |CWColormap; mywindow = XCreateWindow(mydisplay, RootWindow(mydisplay,screen), hint.x, hint.y, hint.width, hint.height, 4, depth,CopyFromParent,vinfo.visual,xswamask,&xswa); XSelectInput(mydisplay, mywindow, StructureNotifyMask); /* Tell other applications about this window */ XSetStandardProperties(mydisplay, mywindow, hello, hello, None, NULL, 0, &hint); if ( fullscreen ) vo_decoration( mydisplay,mywindow,0 ); /* Map window. */ XMapWindow(mydisplay, mywindow); /* Wait for map. */ do { XNextEvent(mydisplay, &xev); } while (xev.type != MapNotify || xev.xmap.event != mywindow); XSelectInput(mydisplay, mywindow, NoEventMask); XFlush(mydisplay); XSync(mydisplay, False); mygc = XCreateGC(mydisplay, mywindow, 0L, &xgcv); xv_port = 0; if (Success == XvQueryExtension(mydisplay,&ver,&rel,&req,&ev,&err)) { /* check for Xvideo support */ if (Success != XvQueryAdaptors(mydisplay,DefaultRootWindow(mydisplay), &adaptors,&ai)) { fprintf(stderr,"Xv: XvQueryAdaptors failed"); return -1; } /* check adaptors */ for (i = 0; i < adaptors; i++) { if ((ai[i].type & XvInputMask) && (ai[i].type & XvImageMask) && (xv_port == 0)) xv_port = ai[i].base_id; } /* check image formats */ if (xv_port != 0) { fo = XvListImageFormats(mydisplay, xv_port, (int*)&formats); xv_format=0; for(i = 0; i < formats; i++) { fprintf(stderr, "Xvideo image format: 0x%x (%4.4s) %s\n", fo[i].id, (char*)&fo[i].id, (fo[i].format == XvPacked) ? "packed" : "planar"); if (fo[i].id == format) { xv_format = fo[i].id; // break; } } if (!xv_format) /* no matching image format not */ xv_port = 0; } if (xv_port != 0) { fprintf(stderr,"using Xvideo port %d for hw scaling\n", xv_port); allocate_xvimage(0); /* catch window resizes */ XSelectInput(mydisplay, mywindow, StructureNotifyMask | KeyPressMask); // XSelectInput(mydisplay, mywindow, StructureNotifyMask); win_width = image_width; win_height = image_height; // resize: XMoveResizeWindow(mydisplay,mywindow,0,0,d_width,d_height); return 0; } } printf("Sorry, Xv not supported by this X11 version/driver\n"); printf("******** Try with -vo x11 or -vo sdl *********\n"); return 1; } static const vo_info_t* get_info(void) { return &vo_info; } static void allocate_xvimage(int foo) { /* allocate XvImages. FIXME: no error checking, without * mit-shm this will bomb... */ xvimage[foo] = XvShmCreateImage(mydisplay, xv_port, xv_format, 0, image_width, image_height, &Shminfo[foo]); Shminfo[foo].shmid = shmget(IPC_PRIVATE, xvimage[foo]->data_size, IPC_CREAT | 0777); Shminfo[foo].shmaddr = (char *) shmat(Shminfo[foo].shmid, 0, 0); Shminfo[foo].readOnly = False; xvimage[foo]->data = Shminfo[foo].shmaddr; XShmAttach(mydisplay, &Shminfo[foo]); XSync(mydisplay, False); shmctl(Shminfo[foo].shmid, IPC_RMID, 0); /* so we can do grayscale while testing... */ memset(xvimage[foo]->data,128,xvimage[foo]->data_size); return; } #if 0 static void check_events(void) { Window root; XEvent event; int x, y; unsigned int w, h, b, d; if (XCheckWindowEvent(mydisplay, mywindow, StructureNotifyMask, &event)) { XGetGeometry(mydisplay, mywindow, &root, &x, &y, &w, &h, &b, &d); win_width = w; win_height = h; } } #endif static void flip_page(void) { int i; XEvent Event; char buf[100]; KeySym keySym; XComposeStatus stat; unsigned long vo_KeyTable[512]; while ( XPending( mydisplay ) ) { XNextEvent( mydisplay,&Event ); switch( Event.type ) { case ConfigureNotify: win_width = Event.xconfigure.width; win_height = Event.xconfigure.height; break; case KeyPress: XLookupString( &Event.xkey,buf,sizeof(buf),&keySym,&stat ); vo_keyboard( ( (keySym&0xff00) != 0?( (keySym&0x00ff) + 256 ):( keySym ) ) ); break; } } // check_events(); #ifdef DISP XvShmPutImage(mydisplay, xv_port, mywindow, mygc, xvimage[0], 0, 0, image_width, image_height, 0, 0, win_width, win_height, False); XFlush(mydisplay); #endif return; } //draw_slice(uint8_t *src[], uint32_t slice_num) static uint32_t draw_slice(uint8_t *image[], int stride[], int w,int h,int x,int y) { uint8_t *src; uint8_t *dst; int i; dst = xvimage[0]->data + image_width * y + x; src = image[0]; if(w==stride[0] && w==image_width) memcpy(dst,src,w*h); else for(i=0;idata + image_width * image_height + image_width/2 * y + x; src = image[2]; if(w==stride[2] && w==image_width/2) memcpy(dst,src,w*h); else for(i=0;idata + image_width * image_height * 5 / 4 + image_width/2 * y + x; src = image[1]; if(w==stride[1] && w==image_width/2) memcpy(dst,src,w*h); else for(i=0;idata; s+=image_width*image_height; for(i=0;idata,src[0],image_width*image_height*2); #endif } else { // YV12 planar memcpy(xvimage[0]->data,src[0],image_width*image_height); memcpy(xvimage[0]->data+image_width*image_height,src[2],image_width*image_height/4); memcpy(xvimage[0]->data+image_width*image_height*5/4,src[1],image_width*image_height/4); } return 0; } static uint32_t query_format(uint32_t format) { switch(format){ case IMGFMT_YV12: case IMGFMT_YUY2: // case IMGFMT_RGB|24: // case IMGFMT_BGR|32: return 1; } return 0; } static void uninit(void) { vo_kill_eventhandler(); }