I wrote an XMMS visualization plugin called Blursk a couple of years ago.
Now I'm trying to add support for full-screen output via XVideo, with mixed
success.

First the details: I'm running XFree86 4.1.0 under SuSE Linux 7.3.  My
video card is a Voodoo3/3000 AGP.  I normally run it at a resolution of
1600x1200, 16bpp.

The good news is, I can now display a 400x300 image full-screen.  I can
even display it on the root window, like animated wallpaper.  The speed is
good -- about as fast as in a window.  It looks pretty damn cool.

The bad news is, there are some quirks.  The biggest and scariest is that
the X server dies if I try some image sizes.  There doesn't seem to be
any pattern to it.  Odd, even, larger, smaller, same aspect ratio, wide
aspect ratio... They all stand a good chance of killing the server.  By
strategically adding XSync() calls and fprintf() calls to the code, I've
been able to determine that it is dying while processing an XvPutImage()
or XvShmPutImage() request.  (The use of shared memory apparently makes
no difference.)  

This has to be a bug in the X server, XVideo extension, or TDFX driver.
There's no way a client should be able to kill the server.  But DVD
player software is able to use 720x480 images without trouble, so there
must be something I'm doing that's weird.

I'm appending my alloc_image() function, below.  The rest of the
initialization code doesn't care about the image size, so I don't think
it can be faulty.  And the Xv[Shm]PutImage() calls are too simple to have
any bugs this subtle in them, so I'm pretty sure there must be something
wrong in the image allocation.

The image format is always packed YUV, 16 bits per pixel, in YUYV order.
If that matters.  I wouldn't be surprised to learn that DVD players used
a planar layout, or something like that.

Other issues include:

 * Although "xvinfo" reports a maximum image size of 2048x2048, the width
   is actually limited to 1024.  I haven't stress tested the height.  The
   width thing is actually a little weird -- if I request a 1280x480
   image buffer, it doesn't fail; it just gives me a 1024x480 image buffer.
   Is this normal?

 * Filtering (to smooth out the enlarged pixels) is not performed when
   I'm running the display at my usual resolution of 1600x1200.  If I
   switch resolutions via <Ctrl-Alt-KPPlus> and <Ctrl-Alt-KPMinus>,
   the smoothing seems to kick in at 1024x768.  This is true for DVD
   player programs too, not just my XMMS plugin.  But is there some way
   I can detect this?  DVDs look better when played with filtering in a
   1024x768 screen than they do unfiltered in a 1600x1200 screen.

 * By the way, is this extension officially called "XVideo" or "Xv"?  It
   seems to be listed both ways, in different places.

 * I've noticed that, on my Voodoo3 at least, XVideo uses color #0000f8
   as a mask color.  This is pretty cool, because if I run Blursk in the
   root window, I can then use color #0000f8 to let the Blursk animation
   shine through.  For example, "xterm -fg white -bg '#0000f8'" gives me
   an xterm with a transparent background.  Is this standard?  Does XVideo
   always use color #0000f8 for this?  If the color varies, how can I find
   out what it is?  Blursk users might have fun with this.

I should probably point out that my Voodoo3 card has been acting slightly
weird since I replaced my motherboard a few months ago.  3D acceleration
still works, but it is slower than it used to be.  It seems to work fine
under Windows, but I don't use Windows enough to say that with confidence.

----------------------------------------------------------------------------

/* Allocate an XV image buffer */
static xvimg_t *alloc_image(int width, int height)
{
    xvimg_t    *img;

    /* Allocate the xvImg struct */
    img = (xvimg_t *)malloc(sizeof(xvimg_t));

    /* shared memory is different from local memory */
    if (xvOptShm)
    {
        img->mImage = XvShmCreateImage(xvDisplay, xvPort, xvFmtInfo.id,
                                       0, width, height, &img->mShminfo);
        if (!img->mImage) 
        {
            about_error("Could not allocate shared memory image\n"
            "You probably won't be able to use XV with shared memory,\n"
            "but you might get it to work if you disable shared memory\n"
            "via Blursk's [Advanced] dialog.  Perhaps updating your\n"
            "X server or libraries would help.\n");
            free(img);
            return NULL;
        }
        if (img->mImage->width != width || img->mImage->height != height)
        {
            about_error("Tried to allocate %dx%d image, but got %dx%d\n"
            "XVideo usually has a limit on how large an image it can\n"
            "handle.  Sometimes the limit is smaller than the size\n"
            "reported by xvinfo.  Try reducing the size of your Blursk\n"
            "window.  If you're using \"XV doubled\", try switching to\n"
            "plain \"XV\".",
                        width, height,
                        img->mImage->width, img->mImage->height);
            XFree(img->mImage);
            free(img);
            return NULL;
        }

        img->mShminfo.shmid = shmget(IPC_PRIVATE, 
                                     img->mImage->data_size, 
                                     IPC_CREAT | 0777);
        if (img->mShminfo.shmid < 0 )
        {
            about_error("Shared memory error, errno=%d\n"
            "I have no idea how to fix this.  Sorry.\n", errno); 
            XFree(img->mImage);
            free(img);
            return NULL;
        }

        img->mShminfo.shmaddr = (char *)shmat(img->mShminfo.shmid, 0,0);
        if (!img->mShminfo.shmaddr)
        {
            about_error("Shared memory error (address NULL)\n"
            "I have no idea how to fix this.  Sorry.\n");
            shmctl(xvImg->mShminfo.shmid, IPC_RMID,NULL);
            XFree(img->mImage);
            free(img);
            return NULL;
        }

        if (img->mShminfo.shmaddr == ((char *) -1))
        {
            about_error("Shared memory error (address error)\n"
            "I have no idea how to fix this.  Sorry.\n");
            shmctl(xvImg->mShminfo.shmid, IPC_RMID,NULL);
            XFree(img->mImage);
            free(img);
            return NULL;
        }

        img->mShminfo.readOnly = False;
        img->mImage->data = img->mShminfo.shmaddr;

        XShmAttach(xvDisplay, &img->mShminfo);
        XSync(xvDisplay, False);

        shmctl(img->mShminfo.shmid, IPC_RMID, NULL);
    }
    else
    {
        /* allocate the XV image buffer */
        img->mImage = XvCreateImage(xvDisplay, xvPort, xvFmtInfo.id,
                                    0, width, height);
        if (!img->mImage) 
        {
            about_error("Could not allocate local image\n"
            "I have no idea how to fix this.  Sorry.\n");
            free(img);
            return NULL;
        }
        if (img->mImage->width != width || img->mImage->height != height)
        {
            about_error("Tried to allocate %dx%d image, but got %dx%d\n"
            "XVideo usually has a limit on how large an image it can\n"
            "handle.  Sometimes the limit is smaller than the size\n"
            "reported by xvinfo.  Try reducing the size of your Blursk\n"
            "window.  If you're using \"XV doubled\", try switching to\n"
            "plain \"XV\".",
                        width, height,
                        img->mImage->width, img->mImage->height);
            XFree(img->mImage);
            free(img);
            return NULL;
        }

        /* The XV image buffer needs data memory.  Allocate it */
        img->mImage->data = malloc(img->mImage->data_size);
        if (!img->mImage) 
        {
            about_error("Could not allocate local memory for image data\n"
            "I have no idea how to fix this.  Sorry.\n");
            free(img);
            return NULL;
        }
    }
    
    return img;
}
_______________________________________________
Xpert mailing list
[EMAIL PROTECTED]
http://XFree86.Org/mailman/listinfo/xpert

Reply via email to