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