You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdemultimedia/mpeglib/lib/util/render/x11/imageXVDesk.cpp

406 lines
9.8 KiB

/*
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
}