?? video_out_x11.c
字號:
/* * video_out_x11.c * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org> * Copyright (C) 2003 Regis Duchesne <hpreg@zoy.org> * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca> * * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. * See http://libmpeg2.sourceforge.net/ for updates. * * mpeg2dec is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * mpeg2dec is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include "config.h"#ifdef LIBVO_X11#include <stdio.h>#include <stdlib.h>#include <X11/Xlib.h>#include <X11/Xutil.h>#include <sys/ipc.h>#include <sys/shm.h>#include <X11/extensions/XShm.h>#include <inttypes.h>/* since it doesn't seem to be defined on some platforms */int XShmGetEventBase (Display *);#ifdef LIBVO_XV#include <string.h> /* strcmp */#include <X11/extensions/Xvlib.h>#define FOURCC_YV12 0x32315659#define FOURCC_UYVY 0x59565955#endif#include "mpeg2.h"#include "video_out.h"#include "mpeg2convert.h"typedef struct { void * data; int wait_completion; XImage * ximage;#ifdef LIBVO_XV XvImage * xvimage;#endif} x11_frame_t;typedef struct x11_instance_s { vo_instance_t vo; x11_frame_t frame[3]; int index; int width; int height; Display * display; Window window; GC gc; XVisualInfo vinfo; XShmSegmentInfo shminfo; int completion_type;#ifdef LIBVO_XV unsigned int adaptors; XvAdaptorInfo * adaptorInfo; XvPortID port; int xv;#endif void (* teardown) (struct x11_instance_s * instance);} x11_instance_t;static int open_display (x11_instance_t * instance, int width, int height){ int major; int minor; Bool pixmaps; XVisualInfo visualTemplate; XVisualInfo * XvisualInfoTable; XVisualInfo * XvisualInfo; int number; int i; XSetWindowAttributes attr; XGCValues gcValues; instance->display = XOpenDisplay (NULL); if (! (instance->display)) { fprintf (stderr, "Can not open display\n"); return 1; } if ((XShmQueryVersion (instance->display, &major, &minor, &pixmaps) == 0) || (major < 1) || ((major == 1) && (minor < 1))) { fprintf (stderr, "No xshm extension\n"); return 1; } instance->completion_type = XShmGetEventBase (instance->display) + ShmCompletion; /* list truecolor visuals for the default screen */#ifdef __cplusplus visualTemplate.c_class = TrueColor;#else visualTemplate.class = TrueColor;#endif visualTemplate.screen = DefaultScreen (instance->display); XvisualInfoTable = XGetVisualInfo (instance->display, VisualScreenMask | VisualClassMask, &visualTemplate, &number); if (XvisualInfoTable == NULL) { fprintf (stderr, "No truecolor visual\n"); return 1; } /* find the visual with the highest depth */ XvisualInfo = XvisualInfoTable; for (i = 1; i < number; i++) if (XvisualInfoTable[i].depth > XvisualInfo->depth) XvisualInfo = XvisualInfoTable + i; instance->vinfo = *XvisualInfo; XFree (XvisualInfoTable); attr.background_pixmap = None; attr.backing_store = NotUseful; attr.border_pixel = 0; attr.event_mask = 0; /* fucking sun blows me - you have to create a colormap there... */ attr.colormap = XCreateColormap (instance->display, RootWindow (instance->display, instance->vinfo.screen), instance->vinfo.visual, AllocNone); instance->window = XCreateWindow (instance->display, DefaultRootWindow (instance->display), 0 /* x */, 0 /* y */, width, height, 0 /* border_width */, instance->vinfo.depth, InputOutput, instance->vinfo.visual, (CWBackPixmap | CWBackingStore | CWBorderPixel | CWEventMask | CWColormap), &attr); instance->gc = XCreateGC (instance->display, instance->window, 0, &gcValues);#ifdef LIBVO_XV instance->adaptors = 0; instance->adaptorInfo = NULL;#endif return 0;}static int shmerror = 0;static int handle_error (Display * display, XErrorEvent * error){ shmerror = 1; return 0;}static void * create_shm (x11_instance_t * instance, int size){ instance->shminfo.shmid = shmget (IPC_PRIVATE, size, IPC_CREAT | 0777); if (instance->shminfo.shmid == -1) goto error; instance->shminfo.shmaddr = (char *) shmat (instance->shminfo.shmid, 0, 0); if (instance->shminfo.shmaddr == (char *)-1) goto error; /* on linux the IPC_RMID only kicks off once everyone detaches the shm */ /* doing this early avoids shm leaks when we are interrupted. */ /* this would break the solaris port though :-/ */ /* shmctl (instance->shminfo.shmid, IPC_RMID, 0); */ /* XShmAttach fails on remote displays, so we have to catch this event */ XSync (instance->display, False); XSetErrorHandler (handle_error); instance->shminfo.readOnly = True; if (! (XShmAttach (instance->display, &(instance->shminfo)))) shmerror = 1; XSync (instance->display, False); XSetErrorHandler (NULL); if (shmerror) { error: fprintf (stderr, "cannot create shared memory\n"); if (instance->shminfo.shmid != -1) { shmdt (instance->shminfo.shmaddr); shmctl (instance->shminfo.shmid, IPC_RMID, 0); } return NULL; } return instance->shminfo.shmaddr;}static void destroy_shm (x11_instance_t * instance){ XShmDetach (instance->display, &(instance->shminfo)); shmdt (instance->shminfo.shmaddr); shmctl (instance->shminfo.shmid, IPC_RMID, 0);}static void x11_event (x11_instance_t * instance) /* XXXXXXXXXXX */{ XEvent event; char * addr; int i; XNextEvent (instance->display, &event); if (event.type == instance->completion_type) { addr = (instance->shminfo.shmaddr + ((XShmCompletionEvent *)&event)->offset); for (i = 0; i < 3; i++) if (addr == instance->frame[i].data) instance->frame[i].wait_completion = 0; }}static void x11_start_fbuf (vo_instance_t * _instance, uint8_t * const * buf, void * id){ x11_instance_t * instance = (x11_instance_t *) _instance; x11_frame_t * frame = (x11_frame_t *) id; while (frame->wait_completion) x11_event (instance);}static void x11_setup_fbuf (vo_instance_t * _instance, uint8_t ** buf, void ** id){ x11_instance_t * instance = (x11_instance_t *) _instance; buf[0] = (uint8_t *) instance->frame[instance->index].data; buf[1] = buf[2] = NULL; *id = instance->frame + instance->index++;}static void x11_draw_frame (vo_instance_t * _instance, uint8_t * const * buf, void * id){ x11_frame_t * frame; x11_instance_t * instance; frame = (x11_frame_t *) id; instance = (x11_instance_t *) _instance; XShmPutImage (instance->display, instance->window, instance->gc, frame->ximage, 0, 0, 0, 0, instance->width, instance->height, True); XFlush (instance->display); frame->wait_completion = 1;}static int x11_alloc_frames (x11_instance_t * instance){ int size; char * alloc; int i; size = 0; alloc = NULL; for (i = 0; i < 3; i++) { instance->frame[i].wait_completion = 0; instance->frame[i].ximage = XShmCreateImage (instance->display, instance->vinfo.visual, instance->vinfo.depth, ZPixmap, NULL /* data */, &(instance->shminfo), instance->width, instance->height); if (instance->frame[i].ximage == NULL) { fprintf (stderr, "Cannot create ximage\n"); return 1; } else if (i == 0) { size = (instance->frame[0].ximage->bytes_per_line * instance->frame[0].ximage->height); alloc = (char *) create_shm (instance, 3 * size); if (alloc == NULL) { XDestroyImage (instance->frame[i].ximage); return 1; } } else if (size != (instance->frame[i].ximage->bytes_per_line * instance->frame[i].ximage->height)) { fprintf (stderr, "unexpected ximage data size\n"); return 1; }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -