Fwd: wrong colors with Xv extension and image format id: 0x59565955 (UYVY) from an rgb mapping
Amos Tibaldi
amos.tibaldi at gmail.com
Thu Jan 22 17:59:29 PST 2009
2009/1/22 Tomas Carnecky <tom at dbservice.com>
> On 01/22/2009 07:35 PM, Amos Tibaldi wrote:
>
> You both are right, but for now I obtain only solid color that doesn't
>> correspond to the desired one; here is the code:
>>
>> void RGBToUV(unsigned short int r,
>> unsigned short int g,
>> unsigned short int b,
>> unsigned short int * u,
>> unsigned short int * v)
>> {
>> *u = -0.147 * r +
>> -0.289 * g +
>> 0.436 * b; // min(abs(r * -1214 + g * -2384 + b * 3598 + 4096 + 1048576)
>> >> 13, 240);
>> //(unsigned short int)(-0.147f*(float)r-0.289f*(float)g+0.436f*(float)b);
>> *v = 0.615 * r +
>> -0.515 * g +
>> -0.100 * b;
>> //min(abs(r * 3598 + g * -3013 + b * -585 + 4096 + 1048576) >> 13, 240);
>> //(unsigned short int)(0.615f*(float)r-0.515f*(float)g-0.100f*(float)b);
>> }
>> void RGBToY(unsigned short int r,
>> unsigned short int g,
>> unsigned short int b,
>> unsigned short int * y
>> )
>> {
>> *y = 0.299 * r +
>> 0.587 * g +
>> 0.114 * b; // min(abs(r * 2104 + g * 4130 + b * 802 + 4096 + 131072) >>
>> 13, 235);
>> //(unsigned short int)(0.299f*(float)r+0.587f*(float)g+0.114f*(float)b);
>> }
>>
>> void XVWindow::Redraw()
>> {
>> unsigned short int u, y1, y2, v;
>> /*RGBToY(255,0,0,&y1);
>> RGBToY(255,0,0,&y2);
>> RGBToUV(255,0,0,&u,&v);*/
>> /* RGBToY(0,255,0,&y1);
>> RGBToY(0,255,0,&y2);
>> RGBToUV(0,255,0,&u,&v); */
>> RGBToY(0,0,255,&y1);
>> RGBToY(0,0,255,&y2);
>> RGBToUV(0,0,255,&u,&v);
>>
>> unsigned char * p = (unsigned char *) BGimage->data;
>> for ( int y=0; y<ImageHeight; y++ , p += BGimage->pitches[0] )
>> for ( int x=0; x<ImageWidth; x++ )
>> {
>> p [ (x << 1) + 3 ] = y2;
>> p [ (x << 1) + 2 ] = v;
>> p [ (x << 1) + 1 ] = y1;
>> p [ (x << 1) ] = u;
>> }
>>
>> counter++;
>> XvPutImage( xvc.display, xvc.port, window, gc,
>> BGimage, 0, 0, ImageWidth, ImageHeight,
>> 0, 0, WindowWidth, WindowHeight );
>> }
>>
>> I cannot understand but it works only if I use (x<<1). What can I do to
>> associate the colours correctly?
>>
>
> ImageWidth is the width in pixels, but in each iteration you fill in two
> pixels. So you either need 'x<ImageWidth/2' in the for() loop or use 'x/2'
> which is what you did.
>
> Also, keep in mind that you are filling only the first line of the whole
> image. The rest of the image probably has undefined/random colors. That you
> are seeing wrong colors could have several causes. Your formulas could be
> wrong (take a look at ffmpeg, xvid or any other projects that have
> rgb-to-yuv functions and borrow their code), endian issues (try YUYV or
> VYVU) or others.
>
> If in doubt, paste the minimal possible sample of your code that compiles
> and runs so we can test it.
>
> tom
>
> I have tried t look at ffmpeg and xvid but there is no code for YUV 8b
each. Only for YUV444. Here is the compilable code, if you can help, the
program shows a violet window, while it should not.
tibaldi at core2duoE:~/XVideoTest$ cat Makefile
all: testxv2
INCLUDES = -I ./ -I /usr/include/X11/
LINKLIBS = -lpthread -lX11 -lXext -lXv
SOURCES := $(wildcard *.cc)
OBJECTS := $(SOURCES:.cc=.o)
XVWindow.o: XVWindow.cc $(wildcard *.h)
g++ -c $< -o $@ $(INCLUDES)
testxv2.o: testxv2.cc $(wildcard *.h)
g++ -c $< -o $@ $(INCLUDES)
testxv2: Makefile $(OBJECTS) $(wildcard *.h)
g++ -o testxv2 $(OBJECTS) -L/usr/X11R6/lib $(LINKLIBS)
clean:
rm -f *.o testxv2
tibaldi at core2duoE:~/XVideoTest$ cat 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");
while(!xvc.can_exit);
delete window;
delete window2;
XVWindowsContextUnInitialize();
}
tibaldi at core2duoE:~/XVideoTest$ cat 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>
#define GUID_YUV12_PLANAR 0x32315659
#define GUID_UYVY_PLANAR 0x59565955
class XVWindow
{
private:
char name[256];
XGCValues xgcv;
GC gc;
XvImage * BGimage;
unsigned int WindowWidth, WindowHeight, OldWindowWidth, OldWindowHeight;
int ImageWidth, ImageHeight;
float WindowAspectRatio;
bool fullscreen;
public:
Window window;
XVWindow * pme;
XVWindow(int w, int h, char * name);
~XVWindow();
void CreateBGImage(int w, int h);
void SetWindowDimension(int w, int h);
void Redraw();
void ToggleFullScreen();
void FixAspectRatioOfWindow();
};
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 RedrawAllWindows();
void LaunchXVWindowThread();
#ifdef __cplusplus
}
#endif
#endif
tibaldi at core2duoE:~/XVideoTest$ cat XVWindow.cc
#include <iostream>
#include <iomanip>
#include <unistd.h>
#include <stdint.h>
#include <Xatom.h>
#include <XVWindow.h>
using namespace std;
XVWindowsContext xvc;
void RedrawAllWindows()
{
int i;
for(i=0; i<xvc.NumberOfWindows; i++)
xvc.WindowsArray[i]->pme->Redraw();
}
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;
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(ImageWidth, ImageHeight);
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()
{
free( BGimage->data );
XFree( BGimage );
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 = -0.147 * r +
-0.289 * g +
0.436 * b; // min(abs(r * -1214 + g * -2384 + b * 3598 + 4096 +
1048576) >> 13, 240);
//(unsigned short
int)(-0.147f*(float)r-0.289f*(float)g+0.436f*(float)b);
*v = 0.615 * r +
-0.515 * g +
-0.100 * b;
//min(abs(r * 3598 + g * -3013 + b * -585 + 4096 + 1048576) >> 13, 240);
//(unsigned short int)(0.615f*(float)r-0.515f*(float)g-0.100f*(float)b);
}
void RGBToY(unsigned short int r,
unsigned short int g,
unsigned short int b,
unsigned short int * y
)
{
*y = 0.299 * r +
0.587 * g +
0.114 * b; // min(abs(r * 2104 + g * 4130 + b * 802 + 4096 +
131072) >> 13, 235);
//(unsigned short int)(0.299f*(float)r+0.587f*(float)g+0.114f*(float)b);
}
void XVWindow::Redraw()
{
unsigned short int u, y1, y2, v;
/*RGBToY(255,0,0,&y1);
RGBToY(255,0,0,&y2);
RGBToUV(255,0,0,&u,&v);*/
/* RGBToY(0,255,0,&y1);
RGBToY(0,255,0,&y2);
RGBToUV(0,255,0,&u,&v); */
RGBToY(0,0,255,&y1);
RGBToY(0,0,255,&y2);
RGBToUV(0,0,255,&u,&v);
unsigned char * p = (unsigned char *) BGimage->data;
for ( int y=0; y<ImageHeight; y++ , p += BGimage->pitches[0] )
for ( int x=0; x<ImageWidth; x+=2 )
{
p [ (x << 1) + 3 ] = y2;
p [ (x << 1) + 2 ] = v;
p [ (x << 1) + 1 ] = y1;
p [ (x << 1) ] = u;
}
XvPutImage( xvc.display, xvc.port, window, gc,
BGimage, 0, 0, ImageWidth, ImageHeight,
0, 0, WindowWidth, WindowHeight );
}
void XVWindow::CreateBGImage(int w, int h)
{
BGimage = (XvImage *)XvCreateImage( xvc.display, xvc.port, xvc.format,
NULL,
w, h );
BGimage->data = (char *)malloc( BGimage->data_size );
ImageWidth = w;
ImageHeight = h;
}
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 PrintImageFormatCharacteristics(XvImageFormatValues * ifvp)
{
cout << "ysb " << ifvp->y_sample_bits << "; ";
cout << "usb " << ifvp->u_sample_bits << "; ";
cout << "vsb " << ifvp->v_sample_bits << "; ";
cout << "hyp " << ifvp->horz_y_period << "; ";
cout << "hup " << ifvp->horz_u_period << "; ";
cout << "hvp " << ifvp->horz_v_period << "; ";
cout << "vyp " << ifvp->vert_y_period << "; ";
cout << "vup " << ifvp->vert_u_period << "; ";
cout << "vvp " << ifvp->vert_v_period << "; ";
cout << "\'";
for(int i=0; i<32; i++)
cout<< ifvp->component_order[i] ;
cout << "\'" ;
cout << "slo: " << ifvp->scanline_order; /* XvTopToBottom,
XvBottomToTop */
cout << endl;
}
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 == GUID_UYVY_PLANAR ) {
xvc.format = xvc.fo[i].id;
PrintImageFormatCharacteristics(&xvc.fo[i]);
};
};
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)
{
cout <<"A"<<endl;
XVWindowsContextInitialize();
xvc.can_start = true;
cout <<"b"<<endl;
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->Redraw();
break;
case ButtonRelease:
pw = GetWindowPointer(event.xbutton.window);
pw->FixAspectRatioOfWindow();
break;
case Expose:
// cout<<"Expose"<<endl;
pw = GetWindowPointer(event.xexpose.window);
pw->Redraw();
// cout<<"Expose end"<<endl;
break;
case KeyPress:
// cout << "press " << event.xkey.keycode << endl;
if ( event.xkey.keycode == 0x09 )
quit = true;
if ( event.xkey.keycode == 0x29 )
{
// cout << "GoFullScreen" << endl;
pw = GetWindowPointer(event.xkey.window);
pw->ToggleFullScreen();
}
if( event.xkey.keycode == 0x26 )
{
pw = GetWindowPointer(event.xkey.window);
pw->FixAspectRatioOfWindow();
}
break;
default:
break;
};
} else {
RedrawAllWindows();
};
// cout <<"fine"<<endl;
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 );
}
Can you help me, please? Thanks in advance
--
Amos Tibaldi
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.x.org/archives/xorg/attachments/20090123/9bd6a00f/attachment.html>
More information about the xorg
mailing list