[vlc-devel] [PATCH] Cursor integration on X11 video screenshots thanks to xfixes

Rémi Denis-Courmont remi at remlab.net
Fri May 11 12:46:26 CEST 2012


   Hello,

Comments inline...

On Fri, 11 May 2012 11:58:43 +0200, Mehdi Lauters <mehdilauters at gmail.com>
wrote:
> ---
>  modules/access/screen/xcb.c |  116
>  ++++++++++++++++++++++++++++++++++++++++++-
>  1 files changed, 115 insertions(+), 1 deletions(-)
> 
> diff --git a/modules/access/screen/xcb.c b/modules/access/screen/xcb.c
> index c31d380..2fa750b 100644
> --- a/modules/access/screen/xcb.c
> +++ b/modules/access/screen/xcb.c
> @@ -402,7 +402,6 @@ discard:
>      /* Capture screen */
>      xcb_drawable_t drawable =
>          (sys->window != geo->root) ? sys->pixmap : sys->window;
> -    free (geo);

Memory leak...

>  
>      xcb_get_image_reply_t *img;
>      img = xcb_get_image_reply (conn,
> @@ -411,6 +410,121 @@ discard:
>      if (img == NULL)

...here.

>          return;
>  
> +    xcb_generic_error_t     xcbError;
> +
> +    // initializing xfixes (to get the cursor image)
> +    xcb_xfixes_query_version_reply(conn,
> +            xcb_xfixes_query_version(conn,XCB_XFIXES_MAJOR_VERSION,
> +                    XCB_XFIXES_MINOR_VERSION),
> +            NULL);

The XFIXES version is not going to change between two snapshots. Please
check it in the initialization phase just once.

> +
> +    // we ask for pointer informations ( on the same screen or not )
> +    xcb_query_pointer_cookie_t pointerCookie = xcb_query_pointer(conn,
> drawable);

This seems to add an unnecessary RTT. It should be interleaved instead
with the other requests.

> +    xcb_query_pointer_reply_t * pointerReply = xcb_query_pointer_reply
> (conn,
> +            pointerCookie, &xcbError);

> +    if(xcbError.error_code!=0)
> +    {
> +        msg_Warn (demux, "unable to locate cursor");
> +    }

The error is not needed here. The reply will be NULL.

> +    else
> +    {
> +        // if the cursor is on the same screen
> +        if(pointerReply->same_screen == 1)
> +        {
> +            // we get more information about the cursor
> +            xcb_xfixes_get_cursor_image_cookie_t cursorCookie =
> xcb_xfixes_get_cursor_image(conn);

It seems that this too could be interleaved to save one RTT.

> +            xcb_xfixes_get_cursor_image_reply_t* cursorImgReply =
> xcb_xfixes_get_cursor_image_reply (conn, cursorCookie, &xcbError);
> +
> +            if(xcbError.error_code==0)
> +            {
> +                // indices to browse images
> +                int iScreen;
> +                int iPointer=0;
> +
> +                // images data
> +                uint8_t *screenImageData=NULL;
> +                uint8_t *pointerImageData;
> +
> +                // we get the cursor image data
> +                pointerImageData =
> xcb_xfixes_get_cursor_image_cursor_image(cursorImgReply);
> +
> +                // we get screen image data
> +                screenImageData = xcb_get_image_data (img);
> +
> +
> +                //indices to browse the pointer picture
> +                int ixCursor=0,
> +                    iyCursor=0;
> +                // top left corner of the pointer picture on the screen
> picture
> +                int xMinScreen=cursorImgReply->x-cursorImgReply->xhot,
> +                // top right corner of the pointer picture on the
screen
> picture
> +                    yMinScreen=cursorImgReply->y-cursorImgReply->yhot,
> +                // bottom left corner of the pointer picture on the
> screen picture
> +                   
>
xMaxScreen=cursorImgReply->x+(cursorImgReply->width-cursorImgReply->xhot),
> +                // bottom right corner of the pointer picture on the
> screen picture
> +                   
>
yMaxScreen=cursorImgReply->y+(cursorImgReply->width-cursorImgReply->yhot);
> +
> +
> +                // be sure that the entire pointer is on the screenshot
> +                if(!(xMinScreen<0 || yMinScreen <0 || xMaxScreen >
> geo->width
> +                        || yMaxScreen > geo->height))
> +                {
> +
> +                    // we browse the screen picture
> +                    for(int ix=xMinScreen; // to center on the right
point
> +                            ix<xMaxScreen;
> +                            ix++)
> +                    {
> +                        iyCursor=0;
> +                        for(int iy=yMinScreen; // to center on the
right
> point
> +                                iy<yMaxScreen;
> +                                iy++)
> +                        {
> +                            //get the indice of the (ix,iy) pixel in
the
> screen data buffer
> +                            iScreen=iy*geo->width+ix;
> +
> +
> +    //                      //get the relative indice of the cursor
> +                           
> iPointer=iyCursor*cursorImgReply->width+ixCursor;
> +
> +                            // get the indice of the first color of the
> current pixel
> +                            iScreen=iScreen*4;
> +                            iPointer=iPointer*4;
> +
> +                            // /!\ no transparency
> +                            if(((uint8_t
> *)pointerImageData)[iPointer+3]>100)
> +                            {
> +                                // copying pixels colors
> +                                // r
> +                               
> screenImageData[iScreen]=pointerImageData[iPointer];
> +                                // g
> +                               
> screenImageData[iScreen+1]=pointerImageData[iPointer+1];
> +                                // b
> +                               
> screenImageData[iScreen+2]=pointerImageData[iPointer+2];
> +                            }
> +                            iyCursor++;
> +                        }
> +                        ixCursor++;
> +                    }
> +                }
> +                else
> +                {
> +                    msg_Warn (demux, "Cursor not on the picture");
> +                }
> +                free(cursorImgReply);
> +            }
> +            else
> +            {
> +                msg_Warn (demux, "unable to find cursor image");
> +            }
> +        }
> +    }

The banana/pyramid pattern is rather deep here. This deserves a separate
function.

> +
> +    free(pointerReply);
> +    free (geo);
> +
>      uint8_t *data = xcb_get_image_data (img);
>      size_t datalen = xcb_get_image_data_length (img);
>      block_t *block = block_heap_Alloc (img, data + datalen - (uint8_t
>      *)img);

-- 
Rémi Denis-Courmont
Sent from my collocated server



More information about the vlc-devel mailing list