Mercurial > mplayer.hg
diff libvo/vo_xv.c @ 1:3b5f5d1c5041
Initial revision
author | arpi_esp |
---|---|
date | Sat, 24 Feb 2001 20:28:24 +0000 |
parents | |
children | 1fc618eba830 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libvo/vo_xv.c Sat Feb 24 20:28:24 2001 +0000 @@ -0,0 +1,457 @@ +#define DISP + +/* + * video_out_x11.c, X11 interface + * + * + * Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. + * + * Hacked into mpeg2dec by + * + * Aaron Holtzman <aholtzma@ess.engr.uvic.ca> + * + * 15 & 16 bpp support added by Franck Sicard <Franck.Sicard@solsoft.fr> + * + * Xv image suuport by Gerd Knorr <kraxel@goldbach.in-berlin.de> + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "config.h" +#include "video_out.h" +#include "video_out_internal.h" + +LIBVO_EXTERN(xv) + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/extensions/XShm.h> +#include <errno.h> +#include "yuv2rgb.h" + +static vo_info_t vo_info = +{ + "X11/Xv", + "xv", + "Gerd Knorr <kraxel@goldbach.in-berlin.de>", + "" +}; + +/* 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 <X11/extensions/Xv.h> +#include <X11/extensions/Xvlib.h> +// 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 <sys/ipc.h> +#include <sys/shm.h> +#include <X11/extensions/XShm.h> + +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;i<h;i++){ + memcpy(dst,src,w); + src+=stride[0]; + dst+=image_width; + } + + x/=2;y/=2;w/=2;h/=2; + + dst = xvimage[0]->data + 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;i<h;i++){ + memcpy(dst,src,w); + src+=stride[2]; + dst+=image_width/2; + } + + dst = xvimage[0]->data + 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;i<h;i++){ + memcpy(dst,src,w); + src+=stride[1]; + dst+=image_width/2; + } + + return 0; +} + + +static uint32_t +draw_frame(uint8_t *src[]) +{ + int foo; + +// check_events(); + + if(xv_format==IMGFMT_YUY2){ + // YUY2 packed, flipped +#if 0 + int i; + unsigned short *s=(unsigned short *)src[0]; + unsigned short *d=(unsigned short *)xvimage[0]->data; + s+=image_width*image_height; + for(i=0;i<image_height;i++){ + s-=image_width; + memcpy(d,s,image_width*2); + d+=image_width; + } +#else + memcpy(xvimage[0]->data,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(); +} + + +