diff options
Diffstat (limited to 'mpeglib/lib/util/render/x11/imageXVDesk.cpp')
-rw-r--r-- | mpeglib/lib/util/render/x11/imageXVDesk.cpp | 405 |
1 files changed, 405 insertions, 0 deletions
diff --git a/mpeglib/lib/util/render/x11/imageXVDesk.cpp b/mpeglib/lib/util/render/x11/imageXVDesk.cpp new file mode 100644 index 00000000..e087ba40 --- /dev/null +++ b/mpeglib/lib/util/render/x11/imageXVDesk.cpp @@ -0,0 +1,405 @@ +/* + xfree 4.0 XV extension desk mode + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + +#include "imageXVDesk.h" + +#include <iostream> + +using namespace std; + +ImageXVDesk::ImageXVDesk() { + + lSupport=false; + + ditherWrapper=NULL; + supportedModes = _IMAGE_NONE; + setIdentifier("XV"); + + xWindow = NULL; + +#ifdef X11_XV + keepRatio = false; + +#endif +} + + +ImageXVDesk::~ImageXVDesk() { + if (ditherWrapper != NULL) { + delete ditherWrapper; + } + freeImage(); +} + +void ImageXVDesk::init(XWindow* xWindow, YUVPicture*) +{ +#ifdef X11_XV + this->xWindow=xWindow; + + xv_port=-1; + shmem_flag = 0; + yuv_image=NULL; + yuv_shminfo.shmaddr=NULL; + yuv_shminfo.shmid=-1; + + if (XShmQueryExtension(xWindow->display)) shmem_flag = 1; + if (!shmem_flag) { + printf("no shmem available.\n"); + return; + } + + + if (haveXVSupport(xWindow)==true) { + supportedModes = _IMAGE_DESK | _IMAGE_DOUBLE | _IMAGE_FULL | _IMAGE_RESIZE; + lSupport=true; + } else { + return; + } + + if (ditherWrapper == NULL) { + ditherWrapper=new Dither2YUV(); + } + imageID = -1; +#endif +} + +int ImageXVDesk::support() { + return lSupport; +} + +int ImageXVDesk::openImage(int imageMode) { + + + if (imageMode & _IMAGE_FULL) { + XResizeWindow(xWindow->display, xWindow->window, + xWindow->screenptr->width, xWindow->screenptr->height); + setKeepRatio(true); + } else if (imageMode & _IMAGE_DOUBLE) { + XResizeWindow(xWindow->display, xWindow->window, + xWindow->width * 2, xWindow->height * 2); + setKeepRatio(false); + } else { + setKeepRatio(false); + } + + return true; +} + + +int ImageXVDesk::closeImage() { + freeImage(); + return true; +} + +void ImageXVDesk::ditherImage(YUVPicture* pic) { + +#ifdef X11_XV + int x_return; + int y_return; + int height, dy; + unsigned int border_width_return; + unsigned int depth_return; + unsigned int _w; + unsigned int _h; + Window _dw; + + if (xWindow == NULL) { + cout << "ImageXVDesk::ditherImage - you have to call before dithering an image!" << endl; + return; + } + + // check for not supported formats and if possible convert them + int inputType=pic->getImageType(); + if (inputType == PICTURE_RGB_FLIPPED) { + cout << "xv for flipped rgb not implemented"<<endl; + return; + } + + // create xv image + int id; + if (imageID != pic->getImageType()) { + imageID = pic->getImageType(); + switch (imageID) { + case PICTURE_YUVMODE_CR_CB: + case PICTURE_YUVMODE_CB_CR: + case PICTURE_RGB: + id = GUID_YUV12_PLANAR; + break; + case PICTURE_YUVMODE_YUY2: + id = GUID_YUY2_PACKED; + break; + case PICTURE_YUVMODE_UYVY: + id = GUID_UYVY_PACKED; + break; + default: + cout << "unknown type for yuv image!" << endl; + return; + } + freeImage(); + + createImage(id); + } + + XGetGeometry(xWindow->display,(Drawable)xWindow->window, + &_dw, &x_return, &y_return, &_w, &_h, + &border_width_return, &depth_return); + + // now dither the image + + // we (currently) cannot create yuvPicture _in_ + // the shared segment here we copy it + + unsigned char* image=pic->getImagePtr(); + if (inputType == PICTURE_RGB) { + ditherWrapper->doDither(pic, + DefaultDepth(xWindow->display,xWindow->screennum), + _SIZE_NORMAL, (unsigned char*) yuv_image->data, 0); + } else { + memcpy(yuv_image->data,image,pic->getImageSize()); + } + + if (keepRatio) { + height = (_w * yuv_image->height) / yuv_image->width; + dy = (((int) _h) - height + 1) / 2; + XvShmPutImage(xWindow->display, xv_port,xWindow->window, + xWindow->gc, yuv_image, + 0, 0, yuv_image->width, yuv_image->height, + 0, dy, _w, height, False); + if (dy > 0) { + XFillRectangle(xWindow->display, xWindow->window,xWindow->gc, + 0, 0, _w, dy); + XFillRectangle(xWindow->display, xWindow->window,xWindow->gc, + 0, height+dy-1, _w, dy+1); + } + } else { + XvShmPutImage(xWindow->display, xv_port,xWindow->window, + xWindow->gc, yuv_image, + 0, 0, yuv_image->width, yuv_image->height, + 0, 0, _w, _h, False); + } +#endif +} + + +void ImageXVDesk::putImage() { + + //XFlush(xWindow->display); + XSync(xWindow->display, false); +} + +void ImageXVDesk::setKeepRatio(bool enable) +{ +#ifdef X11_XV + keepRatio = enable; +#endif +} + + +int ImageXVDesk::haveXVSupport(XWindow* xWindow) { +#ifdef X11_XV + int ret; + unsigned int p_version=0; + unsigned int p_release=0; + unsigned int p_request_base=0; + unsigned int p_event_base=0; + unsigned int p_error_base=0; + + unsigned int p_num_adaptors=0; + + /**------------------------------- XV ------------------------------------*/ + + /** query and print Xvideo properties */ + + ret = XvQueryExtension(xWindow->display, + &p_version, &p_release, &p_request_base, + &p_event_base, &p_error_base); + if (ret != Success) { + if (ret == XvBadExtension) { + printf("XvBadExtension returned at XvQueryExtension.\n"); + } else if (ret == XvBadAlloc) { + printf("XvBadAlloc returned at XvQueryExtension.\n"); + } else { + printf("other error happened at XvQueryExtension.\n"); + } + return false; + } + /* + printf("========================================\n"); + printf("XvQueryExtension returned the following:\n"); + printf("p_version : %u\n", p_version); + printf("p_release : %u\n", p_release); + printf("p_request_base : %u\n", p_request_base); + printf("p_event_base : %u\n", p_event_base); + printf("p_error_base : %u\n", p_error_base); + printf("========================================\n"); + */ + + ret = XvQueryAdaptors(xWindow->display, DefaultRootWindow(xWindow->display), + &p_num_adaptors, &ai); + + if (ret != Success) { + if (ret == XvBadExtension) { + printf("XvBadExtension returned at XvQueryExtension.\n"); + } else if (ret == XvBadAlloc) { + printf("XvBadAlloc returned at XvQueryExtension.\n"); + } else { + printf("other error happaned at XvQueryAdaptors.\n"); + } + return false; + } + /* + printf("=======================================\n"); + printf("XvQueryAdaptors returned the following:\n"); + printf("%d adaptors available.\n", p_num_adaptors); + */ + if (p_num_adaptors == 0) { + //cout << "no adaptors found. XV not possible"<<endl; + return false; + } + + unsigned int i; + unsigned int j; + + for (i = 0; i < p_num_adaptors; i++) { + /* + printf(" name: %s\n" + " type: %s%s%s%s%s\n" + " ports: %ld\n" + " first port: %ld\n", + ai[i].name, + (ai[i].type & XvInputMask) ? "input | " : "", + (ai[i].type & XvOutputMask) ? "output | " : "", + (ai[i].type & XvVideoMask) ? "video | " : "", + (ai[i].type & XvStillMask) ? "still | " : "", + (ai[i].type & XvImageMask) ? "image | " : "", + ai[i].num_ports, + ai[i].base_id); + */ + xv_port = ai[i].base_id; + + //printf("adaptor %d ; format list:\n", i); + for (j = 0; j < ai[i].num_formats; j++) { + /* + printf(" depth=%d, visual=%ld\n", + ai[i].formats[j].depth, + ai[i].formats[j].visual_id); + */ + } + unsigned int p; + unsigned int encodings; + int attributes; + int formats; + + for (p = ai[i].base_id; p < ai[i].base_id+ai[i].num_ports; p++) { + + //printf(" encoding list for port %d\n", p); + if (XvQueryEncodings(xWindow->display, p, &encodings, &ei) != Success) { + //printf("XvQueryEncodings failed.\n"); + continue; + } + for (j = 0; j < encodings; j++) { + /* + printf(" id=%ld, name=%s, size=%ldx%ld, numerator=%d, denominator=%d\n", + ei[j].encoding_id, ei[j].name, ei[j].width, ei[j].height, + ei[j].rate.numerator, ei[j].rate.denominator); + */ + } + XvFreeEncodingInfo(ei); + int k; + //printf(" attribute list for port %d\n", p); + at = XvQueryPortAttributes(xWindow->display, p, &attributes); + for (k = 0; k < attributes; k++) { + /* + printf(" name: %s\n" + " flags: %s%s\n" + " min_color: %i\n" + " max_color: %i\n", + at[k].name, + (at[k].flags & XvGettable) ? " get" : "", + (at[k].flags & XvSettable) ? " set" : "", + at[k].min_value, at[k].max_value); + */ + } + if (at) + XFree(at); + + //printf(" image format list for port %d\n", p); + fo = XvListImageFormats(xWindow->display, p, &formats); + for (k = 0; k < formats; k++) { + /* + printf(" 0x%x (%4.4s) %s\n", + fo[k].id, + (char *)&fo[k].id, + (fo[k].format == XvPacked) ? "packed" : "planar"); + */ + } + if (fo) + XFree(fo); + } + printf("\n"); + } + if (p_num_adaptors > 0) + XvFreeAdaptorInfo(ai); + if (xv_port == -1) { + return false; + } +#endif + return true; + +} + + +void ImageXVDesk::freeImage() { +#ifdef X11_XV + if (xWindow == NULL) { + return; + } + if (yuv_shminfo.shmid >=0) { + XShmDetach(xWindow->display,&yuv_shminfo); + if(yuv_shminfo.shmaddr) { + shmdt(yuv_shminfo.shmaddr); + XFree(yuv_image); + yuv_shminfo.shmaddr=NULL; + } + XSync(xWindow->display, False); + yuv_shminfo.shmid=-1; + } +#endif +} + + +void ImageXVDesk::createImage(int id) { +#ifdef X11_XV + if (xWindow == NULL) { + cout << "ImageXVDesk::freeImage - you have to call init before creating an image!" << endl; + return; + } + + yuv_image = XvShmCreateImage(xWindow->display, xv_port, + id, 0, + xWindow->width, + xWindow->height, &yuv_shminfo); + + yuv_shminfo.shmid = shmget(IPC_PRIVATE, + yuv_image->data_size, IPC_CREAT | 0777); + yuv_shminfo.shmaddr = yuv_image->data = + (char*)shmat(yuv_shminfo.shmid, 0, 0); + yuv_shminfo.readOnly = False; + + if (!XShmAttach(xWindow->display, &yuv_shminfo)) { + printf("XShmAttach failed !\n"); + lSupport=false; + return; + } + shmctl(yuv_shminfo.shmid, IPC_RMID, 0); +#endif +} |