multiple windows Xv application keep color only with 64bit os and not for 32bit
Amos Tibaldi
amos.tibaldi at gmail.com
Sat Jan 24 02:38:04 PST 2009
Hello,
I am trying to write a multiple windows Xv application but when there is
more than one window the image is put only onto one of them for 32bit ubuntu
8.04, while for 64bit ubuntu 8.04 the application works correctly and all
windows have their correct image content displayed. What could be the
problem? Here is the code, thanks in advance.
Makefile
all: testxv2
INCLUDES = -I ./ -I /usr/include/X11/
LINKLIBS = -lpthread -lX11 -lXext -lXv
SOURCES := $(wildcard *.cc)
OBJECTS := $(SOURCES:.cc=.o)
CFLAGS := -g
XVWindow.o: XVWindow.cc $(wildcard *.h)
g++ -c $< -o $@ $(INCLUDES) $(CFLAGS)
testxv2.o: testxv2.cc $(wildcard *.h)
g++ -c $< -o $@ $(INCLUDES) $(CFLAGS)
testxv2: Makefile $(OBJECTS) $(wildcard *.h)
g++ -o testxv2 $(OBJECTS) -L/usr/X11R6/lib $(LINKLIBS) $(CFLAGS)
clean:
rm -f *.o testxv2
-------------------------------
XVWindow.cc
#include <iostream>
#include <iomanip>
#include <unistd.h>
#include <stdint.h>
#include <Xatom.h>
#include <XVWindow.h>
using namespace std;
XVWindowsContext xvc;
Bool waitForNotify( Display *, XEvent *e, char *arg )
{
return ( e->type == MapNotify ) && ( e->xmap.window == (Window)arg );
}
XVWindow::XVWindow(int w, int h, char * thename)
{
pthread_mutex_lock(&xvc.ctxMutex);
//pthread_cond_wait(&xvc.ctxCond, &xvc.ctxMutex);
XEvent event;
ImageBuffer = 0;
ImageWidth = WindowWidth = OldWindowWidth = w;
ImageHeight = WindowHeight = OldWindowHeight = h;
window = XCreateWindow( xvc.display,
RootWindow( xvc.display,
xvc.visualInfo.screen ),
0, 0, w, h, 0,
xvc.visualInfo.depth, InputOutput,
xvc.visualInfo.visual,
xvc.mask,
&(xvc.xswa) );
strcpy(name, thename);
char * aname = (char*) malloc(256);
strcpy(aname, thename);
XTextProperty titleprop;
XStringListToTextProperty(&aname, 1, &titleprop);
XSetTextProperty(xvc.display, window, &titleprop, XA_WM_NAME);
XFree(titleprop.value);
free(aname);
XMapWindow( xvc.display, window );
XIfEvent( xvc.display, &event, waitForNotify, (char *)window );
gc = XCreateGC( xvc.display, window, 0L, &xgcv );
pme = this;
xvc.WindowsArray[xvc.NumberOfWindows] = this;
xvc.NumberOfWindows++;
fullscreen = false;
CreateBGImage();
WindowAspectRatio = (float) ((float)ImageWidth)/((float)ImageHeight);
cout << name << " ha aspect ratio " << WindowAspectRatio << endl;
//pthread_cond_signal(&xvc.ctxCond);
pthread_mutex_unlock(&xvc.ctxMutex);
}
void XVWindow::ToggleFullScreen()
{
if(!fullscreen)
{
XMoveResizeWindow(xvc.display, window, 0, 0, xvc.DisplayWidth,
xvc.DisplayHeight);
XRaiseWindow(xvc.display, window);
XFlush(xvc.display);
WindowWidth = xvc.DisplayWidth; WindowHeight = xvc.DisplayHeight;
fullscreen = true;
return;
}
else
{
XMoveResizeWindow(xvc.display, window, 50, 50, ImageWidth,
ImageHeight);
XRaiseWindow(xvc.display, window);
XFlush(xvc.display);
WindowWidth = ImageWidth; WindowHeight = ImageHeight;
fullscreen = false;
}
}
XVWindow::~XVWindow()
{
DestroyBGImage();
XFreeGC( xvc.display, gc );
XDestroyWindow( xvc.display, window );
}
void XVWindow::SetWindowDimension(int w, int h)
{
OldWindowWidth = WindowWidth;
OldWindowHeight = WindowHeight;
WindowWidth = w;
WindowHeight = h;
}
void XVWindow::FixAspectRatioOfWindow()
{
//cout << "swd w=" << w<<" h="<<h<<endl;
int deltax = 0, deltay = 0;
deltax = WindowWidth-OldWindowWidth; deltay =
WindowHeight-OldWindowHeight;
deltax = abs(deltax); deltay = abs(deltay);
cout << "dx=" <<deltax << "dy=" <<deltay<<endl;
if((deltax==0)&&(deltay==0)) return;
if(deltax>deltay)
{
WindowHeight = (unsigned int)
(((float)WindowWidth)/WindowAspectRatio);
}
else
{
WindowWidth = (unsigned int)
(WindowAspectRatio*((float)WindowHeight));
}
cout << "new w dim " << WindowWidth<<"x"<<WindowHeight<<endl;
XWindowChanges xwc; xwc.width = WindowWidth; xwc.height = WindowHeight;
XConfigureWindow(xvc.display, window, CWWidth|CWHeight, &xwc);
}
void RGBToUV(unsigned short int r,
unsigned short int g,
unsigned short int b,
unsigned short int * u,
unsigned short int * v)
{
*u = min(abs(r * -1214 + g * -2384 + b * 3598 + 4096 + 1048576) >> 13,
240);
*v = min(abs(r * 3598 + g * -3013 + b * -585 + 4096 + 1048576) >> 13,
240);
}
void RGBToY(unsigned short int r,
unsigned short int g,
unsigned short int b,
unsigned short int * y
)
{
*y = min(abs(r * 2104 + g * 4130 + b * 802 + 4096 + 131072) >> 13, 235);
}
void XVWindow::SetImagePixel(int x, int y, int r, int g, int b)
{
if((x<0)||(y<0)||(x>=ImageWidth)||(y>=ImageHeight)) return;
unsigned char * p = &ImageBuffer[(ImageWidth*y+x)*3];
p[0] = (unsigned char) r;
p[1] = (unsigned char) g;
p[2] = (unsigned char) b;
}
void XVWindow::GetImagePixel(int x, int y, int * r, int * g, int * b)
{
unsigned char * p = &ImageBuffer[(ImageWidth*y+x)*3];
*r = p[0];
*g = p[1];
*b = p[2];
}
void XVWindow::BGImageSetPixelPair(int x, int y, int r1, int g1, int b1, int
r2, int g2, int b2)
{
unsigned short int u1, u2, u, y1, y2, v1, v2, v;
unsigned char * p = (unsigned char *) BGimage->data;
unsigned int offset = (x << 1) + y * BGimage->pitches[0];
RGBToY(r1,g1,b1,&y1);
RGBToY(r2,g2,b2,&y2);
RGBToUV(r1,g1,b1,&u1,&v1);
RGBToUV(r2,g2,b2,&u2,&v2);
u = (u1+u2)/2;
v = (v1+v2)/2;
p[offset] = u;
p[offset+1]=y1;
p[offset+2]=v;
p[offset+3]=y2;
}
void XVWindow::UpdateWindowOnScreen()
{
pthread_mutex_lock(&xvc.ctxMutex);
//pthread_cond_wait(&xvc.ctxCond, &xvc.ctxMutex);
ReCalculateImage();
RePutImage();
//pthread_cond_signal(&xvc.ctxCond);
pthread_mutex_unlock(&xvc.ctxMutex);
}
void XVWindow::ReCalculateImage()
{
int r1, g1, b1, r2, g2, b2;
for ( int y=0; y<ImageHeight; y++ )
for ( int x=0; x<ImageWidth; x+=2 )
{
//cout << "x=" << x << " y=" << y <<endl;
GetImagePixel(x, y, &r1, &g1, &b1);
GetImagePixel(x+1, y, &r2, &g2, &b2);
//cout << "r1 = " << r1 << " g1 = " << g1 << " b1= " << b1 <<endl;
BGImageSetPixelPair(x, y, r1, g1, b1, r2, g2, b2);
}
}
void XVWindow::RePutImage()
{
XvPutImage( xvc.display, xvc.port, window, gc,
BGimage, 0, 0, ImageWidth, ImageHeight,
0, 0, WindowWidth, WindowHeight );
}
void XVWindow::CreateBGImage()
{
BGimage = (XvImage *)XvCreateImage( xvc.display, xvc.port, xvc.format,
NULL,
ImageWidth, ImageHeight );
BGimage->data = (char *)malloc( BGimage->data_size );
ImageBuffer = (unsigned char *) malloc(ImageWidth*ImageHeight*3);
printf("%s ha IB %p (size %d)\n", name, ImageBuffer,
ImageWidth*ImageHeight*3);
}
void XVWindow::DestroyBGImage()
{
free( BGimage->data );
XFree( BGimage );
free (ImageBuffer);
}
static Atom xv_intern_atom_if_exists( Display *display, XvPortID port,
char const *atom_name )
{
XvAttribute * attributes;
int attrib_count,i;
Atom xv_atom = None;
attributes = XvQueryPortAttributes( display, port, &attrib_count );
if( attributes!=NULL )
{
for ( i = 0; i < attrib_count; ++i )
{
if ( strcmp(attributes[i].name, atom_name ) == 0 )
{
xv_atom = XInternAtom( display, atom_name, False );
break; // found what we want, break out
}
}
XFree( attributes );
}
return xv_atom;
}
XVWindow * GetWindowPointer(Window w)
{
int i;
for(i=0; i<xvc.NumberOfWindows; i++)
{
if(xvc.WindowsArray[i]->window == w) return
xvc.WindowsArray[i]->pme;
}
return 0;
}
void XVWindowsContextInitialize()
{
xvc.display = XOpenDisplay( NULL );
unsigned int ver, rel, req, ev, err;
bool retVal =
( XvQueryExtension( xvc.display, &ver, &rel, &req, &ev, &err ) ==
Success );
if ( !retVal )
exit(-1);
unsigned int adaptors;
xvc.ai = NULL;
{
bool retVal =
( XvQueryAdaptors( xvc.display, DefaultRootWindow( xvc.display ),
&adaptors,
&(xvc.ai) ) == Success );
if ( !retVal )
exit(-1);
};
xvc.port = 0;
for ( int i=0; i<adaptors; i++ ) {
if ( ( xvc.ai[i].type & ( XvInputMask | XvImageMask ) ) ==
( XvInputMask | XvImageMask ) ) {
for ( int p=xvc.ai[i].base_id; p<xvc.ai[i].base_id+xvc.ai[i].num_ports;
p++ )
if ( !XvGrabPort( xvc.display, p, CurrentTime ) ) {
xvc.port = p;
break;
};
if ( xvc.port != 0 )
break;
};
};
if ( !xvc.port )
exit(-1);
int colourkey = 0;
Atom xvColorKey = xv_intern_atom_if_exists( xvc.display, xvc.port,
"XV_COLORKEY" );
if ( xvColorKey != None ) {
if ( XvGetPortAttribute( xvc.display, xvc.port, xvColorKey, &colourkey )
!=
Success )
exit(-1);
Atom xvAutoPaint = xv_intern_atom_if_exists( xvc.display, xvc.port,
"XV_AUTOPAINT_COLORKEY" );
if ( xvAutoPaint != None ) {
XvSetPortAttribute( xvc.display, xvc.port, xvAutoPaint, 1 );
xvColorKey = None;
};
} else {
}
unsigned int formats;
xvc.fo = 0;
xvc.fo = XvListImageFormats( xvc.display, xvc.port, (int *)&formats );
if ( !(xvc.fo) )
exit(-1);
xvc.format = 0;
for ( int i=0; i<formats; i++ ) {
cout << "Format " <<i<< "is of type " << (int)(xvc.fo[i].type==XvYUV)
<<endl;
if ( xvc.fo[i].id == 0x59565955 ) {
xvc.format = xvc.fo[i].id;
};
};
if ( !xvc.format )
exit(-1);
int depth;
XWindowAttributes attribs;
XGetWindowAttributes( xvc.display, DefaultRootWindow( xvc.display ),
&attribs );
depth = attribs.depth;
if (depth != 15 && depth != 16 && depth != 24 && depth != 32) depth =
24;
XMatchVisualInfo( xvc.display, DefaultScreen( xvc.display ), depth,
TrueColor,
&(xvc.visualInfo ));
xvc.colourMap =
XCreateColormap( xvc.display, DefaultRootWindow( xvc.display ),
xvc.visualInfo.visual,
AllocNone );
xvc.xswa.colormap = xvc.colourMap;
xvc.xswa.border_pixel = 0;
xvc.xswa.background_pixel = colourkey;
xvc.xswa.event_mask = ExposureMask | StructureNotifyMask | KeyPressMask |
ButtonReleaseMask;
xvc.mask = CWBorderPixel | CWColormap | CWEventMask;
if ( xvColorKey != None ) xvc.mask |= CWBackPixel;
xvc.DisplayWidth = XDisplayWidth(xvc.display, DefaultScreen(xvc.display));
xvc.DisplayHeight = XDisplayHeight(xvc.display,
DefaultScreen(xvc.display));
cout << "SCREEN " << xvc.DisplayWidth << "x" << xvc.DisplayHeight <<
endl;
}
void * XVWindowThreadProcedure(void*data)
{
XVWindowsContextInitialize();
xvc.can_start = true;
bool quit = false;
int c=0;
do {
pthread_mutex_lock(&xvc.ctxMutex);
//pthread_cond_wait(&xvc.ctxCond, &xvc.ctxMutex);
XEvent event;
XVWindow * pw;
if ( XCheckMaskEvent( xvc.display,
KeyPressMask | ExposureMask | StructureNotifyMask
| ButtonReleaseMask,
&event ) ) {
switch ( event.type ) {
case ConfigureNotify:
pw = GetWindowPointer(event.xconfigure.window);
pw->SetWindowDimension(event.xconfigure.width,
event.xconfigure.height);
pw->RePutImage();
break;
case ButtonRelease:
pw = GetWindowPointer(event.xbutton.window);
pw->FixAspectRatioOfWindow();
break;
case Expose:
pw = GetWindowPointer(event.xexpose.window);
pw->RePutImage();
break;
case KeyPress:
// cout << "press " << event.xkey.keycode << endl;
if ( event.xkey.keycode == 0x09 )
quit = true;
if ( event.xkey.keycode == 0x29 )
{
pw = GetWindowPointer(event.xkey.window);
pw->ToggleFullScreen();
}
if( event.xkey.keycode == 0x26 )
{
pw = GetWindowPointer(event.xkey.window);
pw->FixAspectRatioOfWindow();
}
break;
default:
break;
};
} else {
};
c++;
//pthread_cond_signal(&xvc.ctxCond);
pthread_mutex_unlock(&xvc.ctxMutex);
} while ( !quit );
cerr << "# frames = " << c << endl;
xvc.can_exit = true;
}
void LaunchXVWindowThread()
{
pthread_mutex_init(&xvc.ctxMutex, 0);
pthread_cond_init(&xvc.ctxCond, 0);
xvc.can_start = xvc.can_exit = false;
pthread_create(&xvc.xvwindowThread, 0, XVWindowThreadProcedure, &xvc);
}
void XVWindowsContextUnInitialize()
{
pthread_join(xvc.xvwindowThread, 0);
XvUngrabPort( xvc.display, xvc.port, CurrentTime );
XFreeColormap( xvc.display, xvc.colourMap );
XvFreeAdaptorInfo(xvc.ai);
XFree(xvc.fo);
XCloseDisplay( xvc.display );
}
--------------------
XVWindow.h
#ifndef XVWINDOW_H
#define XVWINDOW_H
#include <X11/Xlib.h>
#include <X11/extensions/Xv.h>
#include <X11/extensions/Xvlib.h>
#include <X11/Xutil.h>
#include <pthread.h>
class XVWindow
{
private:
char name[256];
XGCValues xgcv;
GC gc;
XvImage * BGimage;
unsigned char * ImageBuffer;
unsigned int WindowWidth, WindowHeight, OldWindowWidth, OldWindowHeight;
int ImageWidth, ImageHeight;
float WindowAspectRatio;
bool fullscreen;
void CreateBGImage();
void DestroyBGImage();
void ReCalculateImage();
void BGImageSetPixelPair(int x, int y, int r1, int g1, int b1, int r2, int
g2, int b2);
public:
Window window;
XVWindow * pme;
XVWindow(int w, int h, char * name);
~XVWindow();
void SetWindowDimension(int w, int h);
void RePutImage();
void ToggleFullScreen();
void FixAspectRatioOfWindow();
void SetImagePixel(int x, int y, int r, int g, int b);
void GetImagePixel(int x, int y, int * r, int * g, int * b);
void UpdateWindowOnScreen();
};
typedef struct {
Display * display;
XvAdaptorInfo * ai;
XVisualInfo visualInfo;
unsigned long mask;
XSetWindowAttributes xswa;
int NumberOfWindows;
XVWindow * WindowsArray[256];
Colormap colourMap;
XvPortID port;
unsigned int format;
XvImageFormatValues *fo;
unsigned int DisplayWidth, DisplayHeight;
pthread_t xvwindowThread;
pthread_mutex_t ctxMutex;
pthread_cond_t ctxCond;
bool can_start, can_exit;
} XVWindowsContext;
#ifdef __cplusplus
extern"C"{
#endif
void XVWindowsContextInitialize();
void XVWindowsContextUnInitialize();
XVWindow * GetWindowPointer(Window w);
void LaunchXVWindowThread();
#ifdef __cplusplus
}
#endif
#endif
----------------
testxv2.cc
// XVideo test program by Jan Wedekind (jan at wedesoft.de).
//
// Based on
// * http://bellet.info/XVideo/testxv.c
// * http://svn.mplayerhq.hu/mplayer/trunk/libvo/vo_xv.c?view=markup
// * http://svn.mplayerhq.hu/mplayer/trunk/libvo/x11_common.c?view=markup
//
// Compile using
// g++ -o testxv2 testxv2.cc -L/usr/X11R6/lib -lX11 -lXext -lXv
#include <iostream>
#include <iomanip>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/Xv.h>
#include <X11/extensions/Xvlib.h>
#include <unistd.h>
#include <stdint.h>
#include <XVWindow.h>
extern XVWindowsContext xvc;
using namespace std;
int main( int argc, char *argv[] )
{
int
width = 320,
height = 240;
LaunchXVWindowThread();
while(!xvc.can_start);
XVWindow * window = new XVWindow(width, height, (char*)"pippo");
XVWindow * window2 = new XVWindow(width, height, (char*)"pluto");
for(int i=0; i<width;i++)
for(int j=0; j<height;j++)
{
window->SetImagePixel(i, j, 255, 0, 0);
window2->SetImagePixel(i, j, 0, 255, 0);
}
window->UpdateWindowOnScreen();
window2->UpdateWindowOnScreen();
while(!xvc.can_exit);
delete window;
delete window2;
XVWindowsContextUnInitialize();
}
--
Amos Tibaldi
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.x.org/archives/xorg/attachments/20090124/263b9f33/attachment.html>
More information about the xorg
mailing list