1 /***********************************************************
2 Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts,
3 and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Digital or MIT not be
12 used in advertising or publicity pertaining to distribution of the
13 software without specific, written prior permission.
15 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
16 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
17 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
18 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
19 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
20 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
23 ******************************************************************/
27 ** Xv.c --- Xv library extension module.
31 ** David Carver (Digital Workstation Engineering/Project Athena)
36 ** - changed XvFreeAdaptors to XvFreeAdaptorInfo
37 ** - changed XvFreeEncodings to XvFreeEncodingInfo
40 ** - changed SetPortControl to SetPortAttribute
41 ** - changed GetPortControl to GetPortAttribute
42 ** - changed QueryBestSize
45 ** - version 2.0 upgrade
48 ** - version 1.4 upgrade
54 #include <X11/extensions/Xext.h>
55 #include <X11/extensions/extutil.h>
56 #include <X11/extensions/XShm.h>
58 static XExtensionInfo _xv_info_data;
59 static XExtensionInfo *xv_info = &_xv_info_data;
60 static const char *xv_extension_name = XvName;
62 #define XvCheckExtension(dpy, i, val) \
63 XextCheckExtension(dpy, i, xv_extension_name, val)
65 static char *xv_error_string(Display *dpy, int code, XExtCodes *codes,
67 static int xv_close_display(Display *dpy, XExtCodes *codes);
68 static Bool xv_wire_to_event(Display *dpy, XEvent *host, xEvent *wire);
70 static XExtensionHooks xv_extension_hooks = {
75 NULL, /* create_font */
77 xv_close_display, /* close_display */
78 xv_wire_to_event, /* wire_to_event */
79 NULL, /* event_to_wire */
81 xv_error_string /* error_string */
85 static const char *xv_error_list[] =
87 "BadPort", /* XvBadPort */
88 "BadEncoding", /* XvBadEncoding */
89 "BadControl" /* XvBadControl */
92 static XEXT_GENERATE_CLOSE_DISPLAY (xv_close_display, xv_info)
95 static XEXT_GENERATE_FIND_DISPLAY (xv_find_display, xv_info,
101 static XEXT_GENERATE_ERROR_STRING (xv_error_string, xv_extension_name,
102 XvNumErrors, xv_error_list)
108 unsigned int *p_version,
109 unsigned int *p_revision,
110 unsigned int *p_requestBase,
111 unsigned int *p_eventBase,
112 unsigned int *p_errorBase
114 XExtDisplayInfo *info = xv_find_display(dpy);
115 xvQueryExtensionReq *req;
116 xvQueryExtensionReply rep;
118 XvCheckExtension(dpy, info, XvBadExtension);
122 XvGetReq(QueryExtension, req);
124 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
127 return XvBadExtension;
130 *p_version = rep.version;
131 *p_revision = rep.revision;
132 *p_requestBase = info->codes->major_opcode;
133 *p_eventBase = info->codes->first_event;
134 *p_errorBase = info->codes->first_error;
146 unsigned int *p_nAdaptors,
147 XvAdaptorInfo **p_pAdaptors
149 XExtDisplayInfo *info = xv_find_display(dpy);
150 xvQueryAdaptorsReq *req;
151 xvQueryAdaptorsReply rep;
154 XvAdaptorInfo *pas, *pa;
165 XvCheckExtension(dpy, info, XvBadExtension);
169 XvGetReq(QueryAdaptors, req);
170 req->window = window;
174 if (_XReply(dpy, (xReply *)&rep, 0, xFalse) == 0) {
180 size = rep.length << 2;
181 if ( (buffer = (char *)Xmalloc ((unsigned) size)) == NULL) {
186 _XRead (dpy, buffer, size);
190 /* GET INPUT ADAPTORS */
192 if (rep.num_adaptors == 0) {
195 size = rep.num_adaptors*sizeof(XvAdaptorInfo);
196 if ((pas=(XvAdaptorInfo *)Xmalloc(size))==NULL) {
204 /* INIT ADAPTOR FIELDS */
207 for (ii=0; ii<rep.num_adaptors; ii++) {
208 pa->num_adaptors = 0;
209 pa->name = (char *)NULL;
210 pa->formats = (XvFormat *)NULL;
215 for (ii=0; ii<rep.num_adaptors; ii++) {
216 pa->type = u.pa->type;
217 pa->base_id = u.pa->base_id;
218 pa->num_ports = u.pa->num_ports;
219 pa->num_formats = u.pa->num_formats;
220 pa->num_adaptors = rep.num_adaptors - ii;
222 /* GET ADAPTOR NAME */
224 size = u.pa->name_size;
225 u.buffer += (sz_xvAdaptorInfo + 3) & ~3;
227 if ( (name = (char *)Xmalloc(size+1)) == NULL)
229 XvFreeAdaptorInfo(pas);
235 (void)strncpy(name, u.string, size);
239 u.buffer += (size + 3) & ~3;
243 size = pa->num_formats*sizeof(XvFormat);
244 if ((pfs=(XvFormat *)Xmalloc(size))==NULL) {
245 XvFreeAdaptorInfo(pas);
253 for (jj=0; jj<pa->num_formats; jj++) {
254 pf->depth = u.pf->depth;
255 pf->visual_id = u.pf->visual;
258 u.buffer += (sz_xvFormat + 3) & ~3;
267 *p_nAdaptors = rep.num_adaptors;
279 XvFreeAdaptorInfo(XvAdaptorInfo *pAdaptors)
285 if (!pAdaptors) return;
289 for (ii=0; ii<pAdaptors->num_adaptors; ii++, pa++)
308 unsigned int *p_nEncodings,
309 XvEncodingInfo **p_pEncodings
311 XExtDisplayInfo *info = xv_find_display(dpy);
312 xvQueryEncodingsReq *req;
313 xvQueryEncodingsReply rep;
316 XvEncodingInfo *pes, *pe;
325 XvCheckExtension(dpy, info, XvBadExtension);
329 XvGetReq(QueryEncodings, req);
334 if (_XReply(dpy, (xReply *)&rep, 0, xFalse) == 0) {
340 size = rep.length << 2;
341 if ( (buffer = (char *)Xmalloc ((unsigned) size)) == NULL) {
346 _XRead (dpy, buffer, size);
352 size = rep.num_encodings*sizeof(XvEncodingInfo);
353 if ( (pes = (XvEncodingInfo *)Xmalloc(size)) == NULL) {
360 /* INITIALIZE THE ENCODING POINTER */
363 for (jj=0; jj<rep.num_encodings; jj++) {
364 pe->name = (char *)NULL;
365 pe->num_encodings = 0;
370 for (jj=0; jj<rep.num_encodings; jj++) {
371 pe->encoding_id = u.pe->encoding;
372 pe->width = u.pe->width;
373 pe->height = u.pe->height;
374 pe->rate.numerator = u.pe->rate.numerator;
375 pe->rate.denominator = u.pe->rate.denominator;
376 pe->num_encodings = rep.num_encodings - jj;
378 size = u.pe->name_size;
379 u.buffer += (sz_xvEncodingInfo + 3) & ~3;
381 if ( (name = (char *)Xmalloc(size+1)) == NULL) {
382 XvFreeEncodingInfo(pes);
388 strncpy(name, u.string, size);
393 u.buffer += (size + 3) & ~3;
396 *p_nEncodings = rep.num_encodings;
407 XvFreeEncodingInfo(XvEncodingInfo *pEncodings)
413 if (!pEncodings) return;
417 for (ii=0; ii<pEncodings->num_encodings; ii++, pe++) {
418 if (pe->name) Xfree(pe->name);
431 unsigned int vw, unsigned int vh,
433 unsigned int dw, unsigned int dh
435 XExtDisplayInfo *info = xv_find_display(dpy);
438 XvCheckExtension(dpy, info, XvBadExtension);
444 XvGetReq(PutVideo, req);
471 unsigned int vw, unsigned int vh,
473 unsigned int dw, unsigned int dh
475 XExtDisplayInfo *info = xv_find_display(dpy);
478 XvCheckExtension(dpy, info, XvBadExtension);
484 XvGetReq(PutStill, req);
510 unsigned int vw, unsigned int vh,
512 unsigned int dw, unsigned int dh
514 XExtDisplayInfo *info = xv_find_display(dpy);
517 XvCheckExtension(dpy, info, XvBadExtension);
523 XvGetReq(GetVideo, req);
549 unsigned int vw, unsigned int vh,
551 unsigned int dw, unsigned int dh
553 XExtDisplayInfo *info = xv_find_display(dpy);
556 XvCheckExtension(dpy, info, XvBadExtension);
562 XvGetReq(GetStill, req);
587 XExtDisplayInfo *info = xv_find_display(dpy);
590 XvCheckExtension(dpy, info, XvBadExtension);
594 XvGetReq(StopVideo, req);
596 req->drawable = draw;
610 XExtDisplayInfo *info = xv_find_display(dpy);
615 XvCheckExtension(dpy, info, XvBadExtension);
619 XvGetReq(GrabPort, req);
623 if (_XReply (dpy, (xReply *) &rep, 0, xTrue) == 0)
624 rep.result = GrabSuccess;
640 XExtDisplayInfo *info = xv_find_display(dpy);
641 xvUngrabPortReq *req;
643 XvCheckExtension(dpy, info, XvBadExtension);
647 XvGetReq(UngrabPort, req);
663 XExtDisplayInfo *info = xv_find_display(dpy);
664 xvSelectVideoNotifyReq *req;
666 XvCheckExtension(dpy, info, XvBadExtension);
670 XvGetReq(SelectVideoNotify, req);
671 req->drawable = drawable;
686 XExtDisplayInfo *info = xv_find_display(dpy);
687 xvSelectPortNotifyReq *req;
689 XvCheckExtension(dpy, info, XvBadExtension);
693 XvGetReq(SelectPortNotify, req);
711 XExtDisplayInfo *info = xv_find_display(dpy);
712 xvSetPortAttributeReq *req;
714 XvCheckExtension(dpy, info, XvBadExtension);
718 XvGetReq(SetPortAttribute, req);
720 req->attribute = attribute;
737 XExtDisplayInfo *info = xv_find_display(dpy);
738 xvGetPortAttributeReq *req;
739 xvGetPortAttributeReply rep;
741 XvCheckExtension(dpy, info, XvBadExtension);
745 XvGetReq(GetPortAttribute, req);
747 req->attribute = attribute;
751 if (_XReply(dpy, (xReply *)&rep, 0, xFalse) == 0) {
757 *p_value = rep.value;
774 unsigned int *p_actual_width,
775 unsigned int *p_actual_height
778 XExtDisplayInfo *info = xv_find_display(dpy);
779 xvQueryBestSizeReq *req;
780 xvQueryBestSizeReply rep;
782 XvCheckExtension(dpy, info, XvBadExtension);
786 XvGetReq(QueryBestSize, req);
788 req->motion = motion;
796 if (_XReply(dpy, (xReply *)&rep, 0, xFalse) == 0) {
802 *p_actual_width = rep.actual_width;
803 *p_actual_height = rep.actual_height;
813 XvQueryPortAttributes(Display *dpy, XvPortID port, int *num)
815 XExtDisplayInfo *info = xv_find_display(dpy);
816 xvQueryPortAttributesReq *req;
817 xvQueryPortAttributesReply rep;
818 XvAttribute *ret = NULL;
822 XvCheckExtension(dpy, info, NULL);
826 XvGetReq(QueryPortAttributes, req);
831 if (_XReply(dpy, (xReply *)&rep, 0, xFalse) == 0) {
837 if(rep.num_attributes) {
838 int size = (rep.num_attributes * sizeof(XvAttribute)) + rep.text_size;
840 if((ret = Xmalloc(size))) {
841 char* marker = (char*)(&ret[rep.num_attributes]);
842 xvAttributeInfo Info;
845 for(i = 0; i < rep.num_attributes; i++) {
846 _XRead(dpy, (char*)(&Info), sz_xvAttributeInfo);
847 ret[i].flags = (int)Info.flags;
848 ret[i].min_value = Info.min;
849 ret[i].max_value = Info.max;
850 ret[i].name = marker;
851 _XRead(dpy, marker, Info.size);
856 _XEatData(dpy, rep.length << 2);
865 XvImageFormatValues * XvListImageFormats (
870 XExtDisplayInfo *info = xv_find_display(dpy);
871 xvListImageFormatsReq *req;
872 xvListImageFormatsReply rep;
873 XvImageFormatValues *ret = NULL;
877 XvCheckExtension(dpy, info, NULL);
881 XvGetReq(ListImageFormats, req);
886 if (_XReply(dpy, (xReply *)&rep, 0, xFalse) == 0) {
892 if(rep.num_formats) {
893 int size = (rep.num_formats * sizeof(XvImageFormatValues));
895 if((ret = Xmalloc(size))) {
896 xvImageFormatInfo Info;
899 for(i = 0; i < rep.num_formats; i++) {
900 _XRead(dpy, (char*)(&Info), sz_xvImageFormatInfo);
902 ret[i].type = Info.type;
903 ret[i].byte_order = Info.byte_order;
904 memcpy(&(ret[i].guid[0]), &(Info.guid[0]), 16);
905 ret[i].bits_per_pixel = Info.bpp;
906 ret[i].format = Info.format;
907 ret[i].num_planes = Info.num_planes;
908 ret[i].depth = Info.depth;
909 ret[i].red_mask = Info.red_mask;
910 ret[i].green_mask = Info.green_mask;
911 ret[i].blue_mask = Info.blue_mask;
912 ret[i].y_sample_bits = Info.y_sample_bits;
913 ret[i].u_sample_bits = Info.u_sample_bits;
914 ret[i].v_sample_bits = Info.v_sample_bits;
915 ret[i].horz_y_period = Info.horz_y_period;
916 ret[i].horz_u_period = Info.horz_u_period;
917 ret[i].horz_v_period = Info.horz_v_period;
918 ret[i].vert_y_period = Info.vert_y_period;
919 ret[i].vert_u_period = Info.vert_u_period;
920 ret[i].vert_v_period = Info.vert_v_period;
921 memcpy(&(ret[i].component_order[0]), &(Info.comp_order[0]), 32);
922 ret[i].scanline_order = Info.scanline_order;
926 _XEatData(dpy, rep.length << 2);
935 XvImage * XvCreateImage (
943 XExtDisplayInfo *info = xv_find_display(dpy);
944 xvQueryImageAttributesReq *req;
945 xvQueryImageAttributesReply rep;
948 XvCheckExtension(dpy, info, NULL);
952 XvGetReq(QueryImageAttributes, req);
956 req->height = height;
960 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
966 if((ret = (XvImage*)Xmalloc(sizeof(XvImage) + (rep.num_planes << 3)))) {
968 ret->width = rep.width;
969 ret->height = rep.height;
970 ret->data_size = rep.data_size;
971 ret->num_planes = rep.num_planes;
972 ret->pitches = (int*)(&ret[1]);
973 ret->offsets = ret->pitches + rep.num_planes;
976 _XRead(dpy, (char*)(ret->pitches), rep.num_planes << 2);
977 _XRead(dpy, (char*)(ret->offsets), rep.num_planes << 2);
979 _XEatData(dpy, rep.length << 2);
987 XvImage * XvShmCreateImage (
994 XShmSegmentInfo *shminfo
998 ret = XvCreateImage(dpy, port, id, data, width, height);
1000 if(ret) ret->obdata = (XPointer)shminfo;
1017 unsigned int dest_w,
1020 XExtDisplayInfo *info = xv_find_display(dpy);
1024 XvCheckExtension(dpy, info, XvBadExtension);
1030 XvGetReq(PutImage, req);
1035 req->id = image->id;
1040 req->drw_x = dest_x;
1041 req->drw_y = dest_y;
1042 req->drw_w = dest_w;
1043 req->drw_h = dest_h;
1044 req->width = image->width;
1045 req->height = image->height;
1047 len = (image->data_size + 3) >> 2;
1048 SetReqLen(req, len, len);
1050 /* Yes it's kindof lame that we are sending the whole thing,
1051 but for video all of it may be needed even if displaying
1052 only a subsection, and I don't want to go through the
1053 trouble of creating subregions to send */
1054 Data(dpy, (char *)image->data, image->data_size);
1074 unsigned int dest_w,
1075 unsigned int dest_h,
1078 XExtDisplayInfo *info = xv_find_display(dpy);
1079 XShmSegmentInfo *shminfo = (XShmSegmentInfo *)image->obdata;
1080 xvShmPutImageReq *req;
1082 XvCheckExtension(dpy, info, XvBadExtension);
1088 XvGetReq(ShmPutImage, req);
1093 req->shmseg = shminfo->shmseg;
1094 req->id = image->id;
1099 req->drw_x = dest_x;
1100 req->drw_y = dest_y;
1101 req->drw_w = dest_w;
1102 req->drw_h = dest_h;
1103 req->offset = image->data - shminfo->shmaddr;
1104 req->width = image->width;
1105 req->height = image->height;
1106 req->send_event = send_event;
1116 xv_wire_to_event(Display *dpy, XEvent *host, xEvent *wire)
1118 XExtDisplayInfo *info = xv_find_display(dpy);
1119 XvEvent *re = (XvEvent *)host;
1120 xvEvent *event = (xvEvent *)wire;
1122 XvCheckExtension(dpy, info, False);
1124 switch((event->u.u.type & 0x7F) - info->codes->first_event)
1127 re->xvvideo.type = event->u.u.type & 0x7f;
1128 re->xvvideo.serial =
1129 _XSetLastRequestRead(dpy, (xGenericReply *)event);
1130 re->xvvideo.send_event = ((event->u.u.type & 0x80) != 0);
1131 re->xvvideo.display = dpy;
1132 re->xvvideo.time = event->u.videoNotify.time;
1133 re->xvvideo.reason = event->u.videoNotify.reason;
1134 re->xvvideo.drawable = event->u.videoNotify.drawable;
1135 re->xvvideo.port_id = event->u.videoNotify.port;
1138 re->xvport.type = event->u.u.type & 0x7f;
1140 _XSetLastRequestRead(dpy, (xGenericReply *)event);
1141 re->xvport.send_event = ((event->u.u.type & 0x80) != 0);
1142 re->xvport.display = dpy;
1143 re->xvport.time = event->u.portNotify.time;
1144 re->xvport.port_id = event->u.portNotify.port;
1145 re->xvport.attribute = event->u.portNotify.attribute;
1146 re->xvport.value = event->u.portNotify.value;