📄 video_output_x11.c
字号:
/* Ogle - A video player * Copyright (C) 2000, 2001 Bj鰎n Englund, H錵an Hjort * * This program 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. * * This program 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 <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>#ifdef HAVE_MLIB#include <mlib_types.h>#include <mlib_status.h>#include <mlib_sys.h>#include <mlib_video.h>#include <mlib_algebra.h>#include <mlib_image.h>#else /* ! HAVE_MLIB */#ifdef HAVE_MMX#include "mmx.h"#endif /* HAVE_MMX */#include "c_mlib.h"#endif /* ! HAVE_MLIB */#include <X11/Xlib.h>#include <X11/Xutil.h>#include <X11/keysym.h>#include <X11/extensions/XShm.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/ipc.h>#include <sys/shm.h>#if USE_SOLARIS_XMU #include <X11/Xmu/XmuSolaris.h>#endif#include "common.h"#include "debug_print.h"#include "video_types.h"#include "yuv2rgb.h"#include "screenshot.h"#include "wm_state.h"#include "display.h"#include "ffb_asm.h"#include "video_output.h"#include "video_output_parse_config.h"#define SPU#ifdef SPU#include "spu_mixer.h"#endif#ifdef HAVE_XV#include <X11/extensions/Xv.h>#include <X11/extensions/Xvlib.h>static XvPortID xv_port;static XvImage *xv_image;static unsigned int xv_version;static unsigned int xv_release;static unsigned int xv_request_base;static unsigned int xv_event_base;static unsigned int xv_error_base;static unsigned int xv_num_adaptors;static unsigned int xv_num_formats;static XvAdaptorInfo *xv_adaptor_info;static XvImageFormatValues *xv_formats;static int xv_id;#endif /* HAVE_XV *///ugly hackextern data_q_t *cur_data_q;/*#ifdef HAVE_XVextern yuv_image_t *reserv_image;#endif*//* needed for sun ffb2 */#include <sys/mman.h>static uint32_t *yuyv_fb;static uint32_t *rgb_fb;static int use_ffb2_yuv2rgb = 0;static int use_ffb2_rgb = 0;static int fb_fd;/* end needed for sun ffb2 */extern int XShmGetEventBase(Display *dpy);static int CompletionType;static int xshmeventbase;typedef struct { int x0; int y0; int x1; int y1;} rect_t;typedef struct { int x; int y; unsigned int width; unsigned int height;} area_t;typedef struct { Window win; XImage *ximage; yuv_image_t *image; area_t video_area; area_t window_area; int video_area_resize_allowed; WindowState_t win_state;} window_info;static window_info window;static XVisualInfo vinfo;static XShmSegmentInfo shm_info;static Display *mydisplay = NULL;static int screen_nr;static GC mygc;static char title[100];static int color_depth, pixel_stride, mode;static int screenshot = 0;static int screenshot_spu = 0;static int view_area_mode = 0;static area_t src_view_area;static area_t new_view_area;static struct { int zoom_n; /* Zoom factor. */ int zoom_d; int preserve_aspect; /* Lock aspect. */ int lock_window_size; /* Never change the size of the window. */ int image_width; /* Current destination size. */ int image_height; /* (set in display_change_size */} scale = { 1, 1, 1, 0, 720, 480 };#ifdef HAVE_MLIBstatic int scalemode = MLIB_BILINEAR;#endif /* HAVE_MLIB */static int use_xshm = 1;static int use_xv = 1;extern int msgqid;extern yuv_image_t *image_bufs;extern void display_process_exit(void);extern AspectModeSrc_t aspect_mode;extern ZoomMode_t zoom_mode;extern uint16_t aspect_new_frac_n;extern uint16_t aspect_new_frac_d;extern MsgEventQ_t *msgq;extern MsgEventClient_t input_client;extern InputMask_t input_mask;/* All display modules shall define these functions */void display_init(int padded_width, int padded_height, int picture_buffer_shmid, char *picture_buffer_addr);void display(yuv_image_t *current_image);void display_poll(yuv_image_t *current_image);void display_exit(void);/* Local prototypes */static void draw_win_xv(window_info *dwin);static void draw_win_x11(window_info *dwin);static void display_change_size(yuv_image_t *img, int new_width, int new_height, int resize_window);static Bool true_predicate(Display *dpy, XEvent *ev, XPointer arg){ return True;}static Cursor hidden_cursor;#ifndef MIN#define MIN(a,b) ((a) < (b) ? (a) : (b))#endif#ifndef MAX#define MAX(a,b) ((a) > (b) ? (a) : (b))#endifstatic rect_t clip(rect_t *r1, rect_t *r2){ rect_t r; r.x0 = MAX(r1->x0, r2->x0); r.y0 = MAX(r1->y0, r2->y0); r.x1 = MIN(r1->x1, r2->x1); r.y1 = MIN(r1->y1, r2->y1); if((r.x0 >= r.x1) || (r.y0 >= r.y1)) { r.x0 = 0; r.y0 = 0; r.x1 = 0; r.y1 = 0; } return r;}static void create_transparent_cursor(Display *dpy, Window win){ Pixmap cursor_mask; XColor dummy_col; unsigned char cursor_data[] = { 0x0 }; cursor_mask = XCreateBitmapFromData(dpy, win, cursor_data, 1, 1); hidden_cursor = XCreatePixmapCursor(dpy, cursor_mask, cursor_mask, &dummy_col, &dummy_col, 0, 0); XFreePixmap(dpy, cursor_mask); }static void hide_cursor(Display *dpy, Window win){ XDefineCursor(dpy, win, hidden_cursor);}static void restore_cursor(Display *dpy, Window win){ XUndefineCursor(dpy, win);}static unsigned long req_serial;static int (*prev_xerrhandler)(Display *dpy, XErrorEvent *ev);static int xshm_errorhandler(Display *dpy, XErrorEvent *ev){ if(ev->serial == req_serial) { /* this could be an error to the xshmattach request * we assume that xshm doesn't work, * eg we are using a remote display */ WARNING("req_code: %d\n", ev->request_code); WARNING("minor_code: %d\n", ev->minor_code); WARNING("error_code: %d\n", ev->error_code); use_xshm = 0; WARNING("%s", "Disabling Xshm\n"); return 0; } else { /* if we get another error we should handle it, * so we give it to the previous errorhandler */ ERROR("unexpected error serial: %lu, waited for: %lu\n", ev->serial, req_serial); return prev_xerrhandler(dpy, ev); }}/* This section of the code looks for the Xv extension for hardware * yuv->rgb and scaling. If it is not found, or any suitable adapter * is not found, use_xv will be set to 0. Otherwise it allocates a * xv image and returns. * * The variable use_xv tells if Xv is used */static void display_init_xv(int picture_buffer_shmid, char *picture_buffer_addr, int padded_width, int padded_height){ int xv_found = 0;#ifdef HAVE_XV int i, j; int result; xv_port = 0; /* We have no port yet. */ /* Check for the Xvideo extension */ result = XvQueryExtension(mydisplay, &xv_version, &xv_release, &xv_request_base, &xv_event_base, &xv_error_base); if(result != Success) { WARNING("%s", "Xvideo extension not found\n"); use_xv = 0; return; } NOTE("Found Xv extension %d.%d, checking for suitable adaptors\n", xv_version, xv_release); /* Check for available adaptors */ result = XvQueryAdaptors(mydisplay, DefaultRootWindow (mydisplay), &xv_num_adaptors, &xv_adaptor_info); if(result != Success) { WARNING("%s", "No Xv adaptors found\n"); use_xv = 0; return; } /* Check adaptors */ for(i = 0; i < xv_num_adaptors; i++) { /* Is it usable for displaying XvImages */ if(!(xv_adaptor_info[i].type & XvInputMask) || !(xv_adaptor_info[i].type & XvImageMask)) continue; xv_port = xv_adaptor_info[i].base_id; /* Check image formats of adaptor */ xv_formats = XvListImageFormats(mydisplay, xv_port, &xv_num_formats); for(j = 0; j < xv_num_formats; j++) { if(xv_formats[j].id == 0x32315659) { /* YV12 */ //if(xv_formats[j].id == 0x30323449) { /* I420 */ xv_id = xv_formats[j].id; break; } } /* No matching format found */ if(j == xv_num_formats) continue; NOTE("Xv adaptor \"%s\" port %li image format %i\n", xv_adaptor_info[i].name, xv_port, xv_id); /* Allocate XvImages */ xv_image = XvShmCreateImage(mydisplay, xv_port, xv_id, NULL, padded_width, padded_height, &shm_info); /* Got an Image? */ if(xv_image == NULL) continue; /* Test and see if we really got padded_width x padded_height */ if(xv_image->width != padded_width || xv_image->height != padded_height) { FATAL("XvShmCreateImage got size: %d x %d\n", xv_image->width, xv_image->height); exit(1); } shm_info.shmid = picture_buffer_shmid; shm_info.shmaddr = picture_buffer_addr; /* Set the data pointer to the decoders picture segment. */ // xv_image->data = picture_data->y; shm_info.readOnly = True; /* make sure we don't have any unhandled errors */ XSync(mydisplay, False); /* set error handler so we can check if xshmattach failed */ prev_xerrhandler = XSetErrorHandler(xshm_errorhandler); /* get the serial of the xshmattach request */ req_serial = NextRequest(mydisplay); /* try to attach */ XShmAttach(mydisplay, &shm_info); /* make sure xshmattach has been processed and any errors have been returned to us */ XSync(mydisplay, False); /* revert to the previous xerrorhandler */ XSetErrorHandler(prev_xerrhandler); if(use_xshm) {#if 0 shmctl(shm_info.shmid, IPC_RMID, 0); // only works on Linux..#endif CompletionType = XShmGetEventBase(mydisplay) + ShmCompletion; } xv_found = 1; /* All set up! */ break; }#endif /* HAVE_XV */ if(!xv_found) { use_xv = 0; }} /* This section of the code tries to use the MIT XShm extension for * accellerated transfers to to X. XShm extension is need and only * the actual attach of the shm segment and subsequent usage of * XShmPutImage is conditional on use_shm. * I.e fallback to normal X11 is implicit and uses all the same * structures (ximage creatd by XShmCreateImage). * * The variable use_xshm tells if XShm is used */static void display_init_xshm(){ /* Create shared memory image */ window.ximage = XShmCreateImage(mydisplay, vinfo.visual, color_depth, ZPixmap, NULL, &shm_info, scale.image_width, scale.image_height); /* Got an Image? */ if(window.ximage == NULL) { // TODO: should revert to normal X in this case FATAL("%s", "XShmCreateImage failed\n"); exit(1); } /* Test and see if we really got padded_width x padded_height */ if(window.ximage->width != scale.image_width || window.ximage->height != scale.image_height) { FATAL("XShmCreateImage got size: %d x %d\n", window.ximage->width, window.ximage->height); exit(1); } /* Get a shared memory segment */ shm_info.shmid = shmget(IPC_PRIVATE, window.ximage->bytes_per_line * window.ximage->height, IPC_CREAT | 0777); if(shm_info.shmid == -1) { FATAL("%s", "display_init_xshm\n"); perror("shmget"); exit(1); } /* Attach shared memory segment */ shm_info.shmaddr = (char *) shmat(shm_info.shmid, 0, 0); if(shm_info.shmaddr == ((char *) -1)) { FATAL("%s", "display_init_xshm\n"); perror("shmat"); exit(1); } /* Set the data pointer to the allocated segment. */ window.ximage->data = shm_info.shmaddr; shm_info.readOnly = False; /* make sure we don't have any unhandled errors */ XSync(mydisplay, False); /* set error handler so we can check if xshmattach failed */ prev_xerrhandler = XSetErrorHandler(xshm_errorhandler); /* get the serial of the xshmattach request */ req_serial = NextRequest(mydisplay); /* try to attach */ XShmAttach(mydisplay, &shm_info); /* make sure xshmattach has been processed and any errors have been returned to us */ XSync(mydisplay, False); /* revert to the previous xerrorhandler */ XSetErrorHandler(prev_xerrhandler); CompletionType = XShmGetEventBase(mydisplay) + ShmCompletion; pixel_stride = window.ximage->bits_per_pixel; // If we have blue in the lowest bit then obviously RGB mode = ((window.ximage->blue_mask & 0x01) != 0) ? MODE_RGB : MODE_BGR; #ifdef WORDS_BIGENDIAN if (window.ximage->byte_order != MSBFirst) {#else if (window.ximage->byte_order != LSBFirst) {#endif if(mode == MODE_RGB) { mode = MODE_RGB_ALIEN; } else { mode = MODE_BGR_ALIEN; } } yuv2rgb_init(pixel_stride, mode); mix_subpicture_init(pixel_stride, mode);}void init_config(Display *dpy){ int screen_nr; char *dpy_str; cfg_video_t *cfg_video = NULL; cfg_display_t *cfg_display; cfg_display_t *tmp_display; DpyInfoOrigin_t orig; screen_nr = DefaultScreen(dpy); dpy_str = DisplayString(dpy); if(get_video_config(&cfg_video) == -1) { ERROR("%s", "init_config(): Couldn't read any config files\n"); } DpyInfoInit(dpy, screen_nr); cfg_display = cfg_video->display; tmp_display = cfg_display;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -