/* * Xephyr - A kdrive X server thats runs in a host X window. * Authored by Matthew Allum <mallum@openedhand.com> * * Copyright © 2007 OpenedHand Ltd * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of OpenedHand Ltd not be used in * advertising or publicity pertaining to distribution of the software without * specific, written prior permission. OpenedHand Ltd makes no * representations about the suitability of this software for any purpose. It * is provided "as is" without express or implied warranty. * * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL OpenedHand Ltd BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Authors: * Dodji Seketeli <dodji@openedhand.com> */ #ifdef HAVE_CONFIG_H #include <kdrive-config.h> #endif /* * including some server headers (like kdrive-config.h) * might define the macro _XSERVER64 * on 64 bits machines. That macro must _NOT_ be defined for Xlib * client code, otherwise bad things happen. * So let's undef that macro if necessary. */ #ifdef _XSERVER64 #undef _XSERVER64 #endif #include <X11/Xutil.h> #include <X11/Xlibint.h> #include <X11/extensions/Xvlib.h> #include <X11/extensions/Xvproto.h> #include <X11/extensions/Xext.h> #include <X11/extensions/extutil.h> #define _HAVE_XALLOC_DECLS #include "hostx.h" #include "ephyrhostvideo.h" #include "ephyrlog.h" #ifndef TRUE #define TRUE 1 #endif /*TRUE*/ #ifndef FALSE #define FALSE 0 #endif /*FALSE*/ static XExtensionInfo _xv_info_data; static XExtensionInfo *xv_info = &_xv_info_data; static char *xv_extension_name = XvName; static char *xv_error_string(Display *dpy, int code, XExtCodes *codes, char * buf, int n); static int xv_close_display(Display *dpy, XExtCodes *codes); static Bool xv_wire_to_event(Display *dpy, XEvent *host, xEvent *wire); static XExtensionHooks xv_extension_hooks = { NULL, /* create_gc */ NULL, /* copy_gc */ NULL, /* flush_gc */ NULL, /* free_gc */ NULL, /* create_font */ NULL, /* free_font */ xv_close_display, /* close_display */ xv_wire_to_event, /* wire_to_event */ NULL, /* event_to_wire */ NULL, /* error */ xv_error_string /* error_string */ }; static char *xv_error_list[] = { "BadPort", /* XvBadPort */ "BadEncoding", /* XvBadEncoding */ "BadControl" /* XvBadControl */ }; #define XvCheckExtension(dpy, i, val) \ XextCheckExtension(dpy, i, xv_extension_name, val) #define XvGetReq(name, req) \ WORD64ALIGN\ if ((dpy->bufptr + SIZEOF(xv##name##Req)) > dpy->bufmax)\ _XFlush(dpy);\ req = (xv##name##Req *)(dpy->last_req = dpy->bufptr);\ req->reqType = info->codes->major_opcode;\ req->xvReqType = xv_##name; \ req->length = (SIZEOF(xv##name##Req))>>2;\ dpy->bufptr += SIZEOF(xv##name##Req);\ dpy->request++ static XEXT_GENERATE_CLOSE_DISPLAY (xv_close_display, xv_info) static XEXT_GENERATE_FIND_DISPLAY (xv_find_display, xv_info, xv_extension_name, &xv_extension_hooks, XvNumEvents, NULL) static XEXT_GENERATE_ERROR_STRING (xv_error_string, xv_extension_name, XvNumErrors, xv_error_list) struct _EphyrHostXVAdaptorArray { XvAdaptorInfo *adaptors ; unsigned int nb_adaptors ; }; /*heavily copied from libx11*/ #define BUFSIZE 2048 static void ephyrHostXVLogXErrorEvent (Display *a_display, XErrorEvent *a_err_event, FILE *a_fp) { char buffer[BUFSIZ]; char mesg[BUFSIZ]; char number[32]; const char *mtype = "XlibMessage"; register _XExtension *ext = (_XExtension *)NULL; _XExtension *bext = (_XExtension *)NULL; Display *dpy = a_display ; XGetErrorText(dpy, a_err_event->error_code, buffer, BUFSIZ); XGetErrorDatabaseText(dpy, mtype, "XError", "X Error", mesg, BUFSIZ); (void) fprintf(a_fp, "%s: %s\n ", mesg, buffer); XGetErrorDatabaseText(dpy, mtype, "MajorCode", "Request Major code %d", mesg, BUFSIZ); (void) fprintf(a_fp, mesg, a_err_event->request_code); if (a_err_event->request_code < 128) { sprintf(number, "%d", a_err_event->request_code); XGetErrorDatabaseText(dpy, "XRequest", number, "", buffer, BUFSIZ); } else { for (ext = dpy->ext_procs; ext && (ext->codes.major_opcode != a_err_event->request_code); ext = ext->next) ; if (ext) strcpy(buffer, ext->name); else buffer[0] = '\0'; } (void) fprintf(a_fp, " (%s)\n", buffer); if (a_err_event->request_code >= 128) { XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code %d", mesg, BUFSIZ); fputs(" ", a_fp); (void) fprintf(a_fp, mesg, a_err_event->minor_code); if (ext) { sprintf(mesg, "%s.%d", ext->name, a_err_event->minor_code); XGetErrorDatabaseText(dpy, "XRequest", mesg, "", buffer, BUFSIZ); (void) fprintf(a_fp, " (%s)", buffer); } fputs("\n", a_fp); } if (a_err_event->error_code >= 128) { /* kludge, try to find the extension that caused it */ buffer[0] = '\0'; for (ext = dpy->ext_procs; ext; ext = ext->next) { if (ext->error_string) (*ext->error_string)(dpy, a_err_event->error_code, &ext->codes, buffer, BUFSIZ); if (buffer[0]) { bext = ext; break; } if (ext->codes.first_error && ext->codes.first_error < (int)a_err_event->error_code && (!bext || ext->codes.first_error > bext->codes.first_error)) bext = ext; } if (bext) sprintf(buffer, "%s.%d", bext->name, a_err_event->error_code - bext->codes.first_error); else strcpy(buffer, "Value"); XGetErrorDatabaseText(dpy, mtype, buffer, "", mesg, BUFSIZ); if (mesg[0]) { fputs(" ", a_fp); (void) fprintf(a_fp, mesg, a_err_event->resourceid); fputs("\n", a_fp); } /* let extensions try to print the values */ for (ext = dpy->ext_procs; ext; ext = ext->next) { if (ext->error_values) (*ext->error_values)(dpy, a_err_event, a_fp); } } else if ((a_err_event->error_code == BadWindow) || (a_err_event->error_code == BadPixmap) || (a_err_event->error_code == BadCursor) || (a_err_event->error_code == BadFont) || (a_err_event->error_code == BadDrawable) || (a_err_event->error_code == BadColor) || (a_err_event->error_code == BadGC) || (a_err_event->error_code == BadIDChoice) || (a_err_event->error_code == BadValue) || (a_err_event->error_code == BadAtom)) { if (a_err_event->error_code == BadValue) XGetErrorDatabaseText(dpy, mtype, "Value", "Value 0x%x", mesg, BUFSIZ); else if (a_err_event->error_code == BadAtom) XGetErrorDatabaseText(dpy, mtype, "AtomID", "AtomID 0x%x", mesg, BUFSIZ); else XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x", mesg, BUFSIZ); fputs(" ", a_fp); (void) fprintf(a_fp, mesg, a_err_event->resourceid); fputs("\n", a_fp); } XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d", mesg, BUFSIZ); fputs(" ", a_fp); (void) fprintf(a_fp, mesg, a_err_event->serial); XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%d", mesg, BUFSIZ); fputs("\n ", a_fp); (void) fprintf(a_fp, mesg, dpy->request); fputs("\n", a_fp); } static int ephyrHostXVErrorHandler (Display *a_display, XErrorEvent *a_error_event) { EPHYR_LOG_ERROR ("got an error from the host xserver:\n") ; ephyrHostXVLogXErrorEvent (a_display, a_error_event, stderr) ; return Success ; } void ephyrHostXVInit (void) { static Bool s_initialized ; if (s_initialized) return ; XSetErrorHandler (ephyrHostXVErrorHandler) ; s_initialized = TRUE ; } Bool ephyrHostXVQueryAdaptors (EphyrHostXVAdaptorArray **a_adaptors) { EphyrHostXVAdaptorArray *result=NULL ; int ret=0 ; Bool is_ok=FALSE ; EPHYR_RETURN_VAL_IF_FAIL (a_adaptors, FALSE) ; EPHYR_LOG ("enter\n") ; result = Xcalloc (1, sizeof (EphyrHostXVAdaptorArray)) ; if (!result) goto out ; ret = XvQueryAdaptors (hostx_get_display (), DefaultRootWindow (hostx_get_display ()), &result->nb_adaptors, &result->adaptors) ; if (ret != Success) { EPHYR_LOG_ERROR ("failed to query host adaptors: %d\n", ret) ; goto out ; } *a_adaptors = result ; is_ok = TRUE ; out: EPHYR_LOG ("leave\n") ; return is_ok ; } void ephyrHostXVAdaptorArrayDelete (EphyrHostXVAdaptorArray *a_adaptors) { if (!a_adaptors) return ; if (a_adaptors->adaptors) { XvFreeAdaptorInfo (a_adaptors->adaptors) ; a_adaptors->adaptors = NULL ; a_adaptors->nb_adaptors = 0 ; } XFree (a_adaptors) ; } int ephyrHostXVAdaptorArrayGetSize (const EphyrHostXVAdaptorArray *a_this) { EPHYR_RETURN_VAL_IF_FAIL (a_this, -1) ; return a_this->nb_adaptors ; } EphyrHostXVAdaptor* ephyrHostXVAdaptorArrayAt (const EphyrHostXVAdaptorArray *a_this, int a_index) { EPHYR_RETURN_VAL_IF_FAIL (a_this, NULL) ; if (a_index >= a_this->nb_adaptors) return NULL ; return (EphyrHostXVAdaptor*)&a_this->adaptors[a_index] ; } char ephyrHostXVAdaptorGetType (const EphyrHostXVAdaptor *a_this) { EPHYR_RETURN_VAL_IF_FAIL (a_this, -1) ; return ((XvAdaptorInfo*)a_this)->type ; } const char* ephyrHostXVAdaptorGetName (const EphyrHostXVAdaptor *a_this) { EPHYR_RETURN_VAL_IF_FAIL (a_this, NULL) ; return ((XvAdaptorInfo*)a_this)->name ; } EphyrHostVideoFormat* ephyrHostXVAdaptorGetVideoFormats (const EphyrHostXVAdaptor *a_this, int *a_nb_formats) { EphyrHostVideoFormat *formats=NULL ; int nb_formats=0, i=0 ; XVisualInfo *visual_info, visual_info_template ; int nb_visual_info ; EPHYR_RETURN_VAL_IF_FAIL (a_this, NULL) ; nb_formats = ((XvAdaptorInfo*)a_this)->num_formats ; formats = Xcalloc (nb_formats, sizeof (EphyrHostVideoFormat)) ; for (i=0; i < nb_formats; i++) { memset (&visual_info_template, 0, sizeof (visual_info_template)) ; visual_info_template.visualid = ((XvAdaptorInfo*)a_this)->formats[i].visual_id; visual_info = XGetVisualInfo (hostx_get_display (), VisualIDMask, &visual_info_template, &nb_visual_info) ; formats[i].depth = ((XvAdaptorInfo*)a_this)->formats[i].depth ; formats[i].visual_class = visual_info->class ; XFree (visual_info) ; } if (a_nb_formats) *a_nb_formats = nb_formats ; return formats ; } int ephyrHostXVAdaptorGetNbPorts (const EphyrHostXVAdaptor *a_this) { EPHYR_RETURN_VAL_IF_FAIL (a_this, -1) ; return ((XvAdaptorInfo*)a_this)->num_ports ; } int ephyrHostXVAdaptorGetFirstPortID (const EphyrHostXVAdaptor *a_this) { EPHYR_RETURN_VAL_IF_FAIL (a_this, -1) ; return ((XvAdaptorInfo*)a_this)->base_id ; } Bool ephyrHostXVAdaptorHasPutVideo (const EphyrHostXVAdaptor *a_this, Bool *a_result) { EPHYR_RETURN_VAL_IF_FAIL (a_this && a_result, FALSE) ; if (((XvAdaptorInfo*)a_this)->type & XvVideoMask & XvInputMask) *a_result = TRUE ; else *a_result = FALSE ; return TRUE ; } Bool ephyrHostXVAdaptorHasGetVideo (const EphyrHostXVAdaptor *a_this, Bool *a_result) { if (((XvAdaptorInfo*)a_this)->type & XvVideoMask & XvOutputMask) *a_result = TRUE ; else *a_result = FALSE ; return TRUE ; } Bool ephyrHostXVAdaptorHasPutStill (const EphyrHostXVAdaptor *a_this, Bool *a_result) { EPHYR_RETURN_VAL_IF_FAIL (a_this && a_result, FALSE) ; if (((XvAdaptorInfo*)a_this)->type & XvStillMask && XvInputMask) *a_result = TRUE ; else *a_result = FALSE ; return TRUE ; } Bool ephyrHostXVAdaptorHasGetStill (const EphyrHostXVAdaptor *a_this, Bool *a_result) { EPHYR_RETURN_VAL_IF_FAIL (a_this && a_result, FALSE) ; if (((XvAdaptorInfo*)a_this)->type & XvStillMask && XvOutputMask) *a_result = TRUE ; else *a_result = FALSE ; return TRUE ; } Bool ephyrHostXVAdaptorHasPutImage (const EphyrHostXVAdaptor *a_this, Bool *a_result) { EPHYR_RETURN_VAL_IF_FAIL (a_this && a_result, FALSE) ; if (((XvAdaptorInfo*)a_this)->type & XvImageMask && XvInputMask) *a_result = TRUE ; else *a_result = FALSE ; return TRUE ; } Bool ephyrHostXVQueryEncodings (int a_port_id, EphyrHostEncoding **a_encodings, unsigned int *a_num_encodings) { EphyrHostEncoding *encodings=NULL ; XvEncodingInfo *encoding_info=NULL ; unsigned int num_encodings=0, i; int ret=0 ; EPHYR_RETURN_VAL_IF_FAIL (a_encodings && a_num_encodings, FALSE) ; ret = XvQueryEncodings (hostx_get_display (), a_port_id, &num_encodings, &encoding_info) ; if (num_encodings && encoding_info) { encodings = Xcalloc (num_encodings, sizeof (EphyrHostEncoding)) ; for (i=0; i<num_encodings; i++) { encodings[i].id = encoding_info[i].encoding_id ; encodings[i].name = strdup (encoding_info[i].name) ; encodings[i].width = encoding_info[i].width ; encodings[i].height = encoding_info[i].height ; encodings[i].rate.numerator = encoding_info[i].rate.numerator ; encodings[i].rate.denominator = encoding_info[i].rate.denominator ; } } if (encoding_info) { XvFreeEncodingInfo (encoding_info) ; encoding_info = NULL ; } *a_encodings = encodings ; *a_num_encodings = num_encodings ; if (ret != Success) return FALSE ; return TRUE ; } void ephyrHostEncodingsDelete (EphyrHostEncoding *a_encodings, int a_num_encodings) { int i=0 ; if (!a_encodings) return ; for (i=0; i < a_num_encodings; i++) { if (a_encodings[i].name) { xfree (a_encodings[i].name) ; a_encodings[i].name = NULL ; } } xfree (a_encodings) ; } void ephyrHostAttributesDelete (EphyrHostAttribute *a_attributes) { if (!a_attributes) return ; XFree (a_attributes) ; } Bool ephyrHostXVQueryPortAttributes (int a_port_id, EphyrHostAttribute **a_attributes, int *a_num_attributes) { EPHYR_RETURN_VAL_IF_FAIL (a_attributes && a_num_attributes, FALSE) ; *a_attributes = (EphyrHostAttribute*)XvQueryPortAttributes (hostx_get_display (), a_port_id, a_num_attributes); return TRUE ; } Bool ephyrHostXVQueryImageFormats (int a_port_id, EphyrHostImageFormat **a_formats, int *a_num_format) { XvImageFormatValues *result=NULL ; EPHYR_RETURN_VAL_IF_FAIL (a_formats && a_num_format, FALSE) ; result = XvListImageFormats (hostx_get_display (), a_port_id, a_num_format) ; *a_formats = (EphyrHostImageFormat*) result ; return TRUE ; } Bool ephyrHostXVSetPortAttribute (int a_port_id, int a_atom, int a_attr_value) { int res=Success ; EPHYR_LOG ("atom,name,value: (%d,%s,%d)\n", a_atom, XGetAtomName (hostx_get_display (), a_atom), a_attr_value) ; res = XvSetPortAttribute (hostx_get_display (), a_port_id, a_atom, a_attr_value) ; if (res != Success) { EPHYR_LOG_ERROR ("XvSetPortAttribute() failed: %d\n", res) ; return FALSE ; } XFlush (hostx_get_display ()) ; EPHYR_LOG ("leave\n") ; return TRUE ; } Bool ephyrHostXVGetPortAttribute (int a_port_id, int a_atom, int *a_attr_value) { int res=Success ; Bool ret=FALSE ; EPHYR_RETURN_VAL_IF_FAIL (a_attr_value, FALSE) ; EPHYR_LOG ("enter, a_port_id: %d, a_atomid: %d, attr_name: %s\n", a_port_id, a_atom, XGetAtomName (hostx_get_display (), a_atom)) ; res = XvGetPortAttribute (hostx_get_display (), a_port_id, a_atom, a_attr_value) ; if (res != Success) { EPHYR_LOG_ERROR ("XvGetPortAttribute() failed: %d \n", res) ; goto out ; } EPHYR_LOG ("atom,value: (%d, %d)\n", a_atom, *a_attr_value) ; ret = TRUE ; out: EPHYR_LOG ("leave\n") ; return ret ; } Bool ephyrHostXVQueryBestSize (int a_port_id, Bool a_motion, unsigned int a_frame_w, unsigned int a_frame_h, unsigned int a_drw_w, unsigned int a_drw_h, unsigned int *a_actual_w, unsigned int *a_actual_h) { int res=0 ; Bool is_ok=FALSE ; EPHYR_RETURN_VAL_IF_FAIL (a_actual_w && a_actual_h, FALSE) ; EPHYR_LOG ("enter: frame (%dx%d), drw (%dx%d)\n", a_frame_w, a_frame_h, a_drw_w, a_drw_h) ; res = XvQueryBestSize (hostx_get_display (), a_port_id, a_motion, a_frame_w, a_frame_h, a_drw_w, a_drw_h, a_actual_w, a_actual_h) ; if (res != Success) { EPHYR_LOG_ERROR ("XvQueryBestSize() failed: %d\n", res) ; goto out ; } XSync (hostx_get_display (), FALSE) ; EPHYR_LOG ("actual (%dx%d)\n", *a_actual_w, *a_actual_h) ; is_ok = TRUE ; out: EPHYR_LOG ("leave\n") ; return is_ok ; } static Bool xv_wire_to_event(Display *dpy, XEvent *host, xEvent *wire) { XExtDisplayInfo *info = xv_find_display (dpy); XvEvent *re = (XvEvent *)host; xvEvent *event = (xvEvent *)wire; XvCheckExtension(dpy, info, False); switch ((event->u.u.type & 0x7F) - info->codes->first_event) { case XvVideoNotify: re->xvvideo.type = event->u.u.type & 0x7f; re->xvvideo.serial = _XSetLastRequestRead(dpy, (xGenericReply *)event); re->xvvideo.send_event = ((event->u.u.type & 0x80) != 0); re->xvvideo.display = dpy; re->xvvideo.time = event->u.videoNotify.time; re->xvvideo.reason = event->u.videoNotify.reason; re->xvvideo.drawable = event->u.videoNotify.drawable; re->xvvideo.port_id = event->u.videoNotify.port; break; case XvPortNotify: re->xvport.type = event->u.u.type & 0x7f; re->xvport.serial = _XSetLastRequestRead(dpy, (xGenericReply *)event); re->xvport.send_event = ((event->u.u.type & 0x80) != 0); re->xvport.display = dpy; re->xvport.time = event->u.portNotify.time; re->xvport.port_id = event->u.portNotify.port; re->xvport.attribute = event->u.portNotify.attribute; re->xvport.value = event->u.portNotify.value; break; default: return False; } return True ; } Bool ephyrHostXVQueryImageAttributes (int a_port_id, int a_image_id /*image fourcc code*/, unsigned short *a_width, unsigned short *a_height, int *a_image_size, int *a_pitches, int *a_offsets) { Display *dpy = hostx_get_display () ; Bool ret=FALSE ; XExtDisplayInfo *info = xv_find_display (dpy); xvQueryImageAttributesReq *req=NULL; xvQueryImageAttributesReply rep; EPHYR_RETURN_VAL_IF_FAIL (a_width, FALSE) ; EPHYR_RETURN_VAL_IF_FAIL (a_height, FALSE) ; EPHYR_RETURN_VAL_IF_FAIL (a_image_size, FALSE) ; XvCheckExtension (dpy, info, FALSE); LockDisplay (dpy); XvGetReq (QueryImageAttributes, req); req->id = a_image_id; req->port = a_port_id; req->width = *a_width; req->height = *a_height; /* * read the reply */ if (!_XReply (dpy, (xReply *)&rep, 0, xFalse)) { EPHYR_LOG_ERROR ("QeryImageAttribute req failed\n") ; goto out ; } if (a_pitches && a_offsets) { _XRead (dpy, (char*)a_pitches, rep.num_planes << 2); _XRead (dpy, (char*)a_offsets, rep.num_planes << 2); } else { _XEatData(dpy, rep.length << 2); } *a_width = rep.width ; *a_height = rep.height ; *a_image_size = rep.data_size ; ret = TRUE ; out: UnlockDisplay (dpy) ; SyncHandle (); return ret ; } Bool ephyrHostGetAtom (const char* a_name, Bool a_create_if_not_exists, int *a_atom) { int atom=None ; EPHYR_RETURN_VAL_IF_FAIL (a_atom, FALSE) ; atom = XInternAtom (hostx_get_display (), a_name, a_create_if_not_exists); if (atom == None) { return FALSE ; } *a_atom = atom ; return TRUE ; } char* ephyrHostGetAtomName (int a_atom) { return XGetAtomName (hostx_get_display (), a_atom) ; } void ephyrHostFree (void *a_pointer) { if (a_pointer) XFree (a_pointer) ; } Bool ephyrHostXVPutImage (int a_screen_num, int a_port_id, int a_image_id, int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h, int a_src_x, int a_src_y, int a_src_w, int a_src_h, int a_image_width, int a_image_height, unsigned char *a_buf, EphyrHostBox *a_clip_rects, int a_clip_rect_nums ) { Bool is_ok=TRUE ; XvImage *xv_image=NULL ; GC gc=0 ; XGCValues gc_values; Display *dpy = hostx_get_display () ; XRectangle *rects=NULL ; int res = 0 ; EPHYR_RETURN_VAL_IF_FAIL (a_buf, FALSE) ; EPHYR_LOG ("enter, num_clip_rects: %d\n", a_clip_rect_nums) ; memset (&gc_values, 0, sizeof (gc_values)) ; gc = XCreateGC (dpy, hostx_get_window (a_screen_num), 0L, &gc_values); if (!gc) { EPHYR_LOG_ERROR ("failed to create gc \n") ; goto out ; } xv_image = (XvImage*) XvCreateImage (hostx_get_display (), a_port_id, a_image_id, NULL, a_image_width, a_image_height) ; if (!xv_image) { EPHYR_LOG_ERROR ("failed to create image\n") ; goto out ; } xv_image->data = (char*)a_buf ; if (a_clip_rect_nums) { int i=0 ; rects = calloc (a_clip_rect_nums, sizeof (XRectangle)) ; for (i=0; i < a_clip_rect_nums; i++) { rects[i].x = a_clip_rects[i].x1 ; rects[i].y = a_clip_rects[i].y1 ; rects[i].width = a_clip_rects[i].x2 - a_clip_rects[i].x1; rects[i].height = a_clip_rects[i].y2 - a_clip_rects[i].y1; EPHYR_LOG ("(x,y,w,h): (%d,%d,%d,%d)\n", rects[i].x, rects[i].y, rects[i].width, rects[i].height) ; } XSetClipRectangles (dpy, gc, 0, 0, rects, a_clip_rect_nums, YXBanded) ; /*this always returns 1*/ } res = XvPutImage (dpy, a_port_id, hostx_get_window (a_screen_num), gc, xv_image, a_src_x, a_src_y, a_src_w, a_src_h, a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; if (res != Success) { EPHYR_LOG_ERROR ("XvPutImage() failed: %d\n", res) ; goto out ; } is_ok = TRUE ; out: if (xv_image) { XFree (xv_image) ; xv_image = NULL ; } if (gc) { XFreeGC (dpy, gc) ; gc = NULL ; } if (rects) { free (rects) ; rects = NULL ; } EPHYR_LOG ("leave\n") ; return is_ok ; } Bool ephyrHostXVPutVideo (int a_screen_num, int a_port_id, int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) { Bool is_ok=FALSE ; int res=FALSE ; GC gc=0 ; XGCValues gc_values; Display *dpy=hostx_get_display () ; EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; gc = XCreateGC (dpy, hostx_get_window (a_screen_num), 0L, &gc_values); if (!gc) { EPHYR_LOG_ERROR ("failed to create gc \n") ; goto out ; } res = XvPutVideo (dpy, a_port_id, hostx_get_window (a_screen_num), gc, a_vid_x, a_vid_y, a_vid_w, a_vid_h, a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; if (res != Success) { EPHYR_LOG_ERROR ("XvPutVideo() failed: %d\n", res) ; goto out ; } is_ok = TRUE ; out: if (gc) { XFreeGC (dpy, gc) ; gc = NULL ; } return is_ok ; } Bool ephyrHostXVGetVideo (int a_screen_num, int a_port_id, int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) { Bool is_ok=FALSE ; int res=FALSE ; GC gc=0 ; XGCValues gc_values; Display *dpy=hostx_get_display () ; EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; gc = XCreateGC (dpy, hostx_get_window (a_screen_num), 0L, &gc_values); if (!gc) { EPHYR_LOG_ERROR ("failed to create gc \n") ; goto out ; } res = XvGetVideo (dpy, a_port_id, hostx_get_window (a_screen_num), gc, a_vid_x, a_vid_y, a_vid_w, a_vid_h, a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; if (res != Success) { EPHYR_LOG_ERROR ("XvGetVideo() failed: %d\n", res) ; goto out ; } is_ok = TRUE ; out: if (gc) { XFreeGC (dpy, gc) ; gc = NULL ; } return is_ok ; } Bool ephyrHostXVPutStill (int a_screen_num, int a_port_id, int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) { Bool is_ok=FALSE ; int res=FALSE ; GC gc=0 ; XGCValues gc_values; Display *dpy=hostx_get_display () ; EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; gc = XCreateGC (dpy, hostx_get_window (a_screen_num), 0L, &gc_values); if (!gc) { EPHYR_LOG_ERROR ("failed to create gc \n") ; goto out ; } res = XvPutStill (dpy, a_port_id, hostx_get_window (a_screen_num), gc, a_vid_x, a_vid_y, a_vid_w, a_vid_h, a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; if (res != Success) { EPHYR_LOG_ERROR ("XvPutStill() failed: %d\n", res) ; goto out ; } is_ok = TRUE ; out: if (gc) { XFreeGC (dpy, gc) ; gc = NULL ; } return is_ok ; } Bool ephyrHostXVGetStill (int a_screen_num, int a_port_id, int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) { Bool is_ok=FALSE ; int res=FALSE ; GC gc=0 ; XGCValues gc_values; Display *dpy=hostx_get_display () ; EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; gc = XCreateGC (dpy, hostx_get_window (a_screen_num), 0L, &gc_values); if (!gc) { EPHYR_LOG_ERROR ("failed to create gc \n") ; goto out ; } res = XvGetStill (dpy, a_port_id, hostx_get_window (a_screen_num), gc, a_vid_x, a_vid_y, a_vid_w, a_vid_h, a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; if (res != Success) { EPHYR_LOG_ERROR ("XvGetStill() failed: %d\n", res) ; goto out ; } is_ok = TRUE ; out: if (gc) { XFreeGC (dpy, gc) ; gc = NULL ; } return is_ok ; } Bool ephyrHostXVStopVideo (int a_screen_num, int a_port_id) { int ret=0 ; Bool is_ok=FALSE ; Display *dpy = hostx_get_display () ; EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; EPHYR_LOG ("enter\n") ; ret = XvStopVideo (dpy, a_port_id, hostx_get_window (a_screen_num)) ; if (ret != Success) { EPHYR_LOG_ERROR ("XvStopVideo() failed: %d \n", ret) ; goto out ; } is_ok = TRUE ; out: EPHYR_LOG ("leave\n") ; return is_ok ; }