2 * TinyPTC x11 v0.7.3 XVideo with Shared Memory Extension target
3 * Copyright (C) 2002 Fred Howell <foohoo@shaw.ca>
4 * Copyright (C) 2002 Alessandro Gatti <a.gatti@tiscali.it>
6 * http://www.sourceforge.net/projects/tinyptc/
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include <X11/Xutil.h>
33 #include <X11/extensions/XShm.h>
34 #include <X11/extensions/Xvlib.h>
39 #define __PTC_FROM_SOURCE
46 ptc_open (char *title, int width, int height)
48 unsigned int xvver,xvrel,xvreqbase,xvevbase,xverrbase;
51 XvAdaptorInfo *adaptors;
53 XvImageFormatValues *fmts;
56 /* Round down width and height for MMX routine */
58 height -= (height % 2);
63 /* Open a display on the current root window */
64 ptc_display = XOpenDisplay (NULL);
65 if (ptc_display == NULL)
69 /* Get the default screen associated with the previously opened display */
70 ptc_screen = DefaultScreen (ptc_display);
71 /* Get the default visual */
72 ptc_visual = DefaultVisual (ptc_display, ptc_screen);
74 if (XvQueryExtension(ptc_display,&xvver,&xvrel,
75 &xvreqbase,&xvevbase,&xverrbase) != Success) {
78 if (ptc_xv_ok == 0) return 0;
79 /* Check for XShm extension */
80 if (!XShmQueryExtension (ptc_display))
82 XCloseDisplay (ptc_display);
85 /* Get screen dimensions */
86 ptc_screen_width = DisplayWidth (ptc_display, ptc_screen);
87 ptc_screen_height = DisplayHeight (ptc_display, ptc_screen);
88 /* Get the default root window */
89 ptc_root_window = DefaultRootWindow (ptc_display);
90 /* Initialize window's attribute structure */
91 ptc_window_attributes.border_pixel = BlackPixel (ptc_display, ptc_screen);
92 ptc_window_attributes.background_pixel =
93 BlackPixel (ptc_display, ptc_screen);
94 ptc_window_attributes.backing_store = NotUseful;
95 #ifdef __PTC_CENTER_WINDOW__
96 /* Center the window on the screen */
97 ptc_x_position = (ptc_screen_width - width) / 2;
98 ptc_y_position = (ptc_screen_height - height) / 2;
100 /* Dock the window on the top-left corner */
103 #endif /* __PTC_CENTER_WINDOW__ */
104 /* Create the window */
106 XCreateWindow (ptc_display, ptc_root_window, ptc_x_position,
107 ptc_y_position, width, height, 0, ptc_depth, InputOutput,
108 ptc_visual, CWBackPixel | CWBorderPixel | CWBackingStore,
109 &ptc_window_attributes);
110 /* Set the window's name */
111 XStoreName (ptc_display, ptc_window, title);
112 /* Tell the server to report only keypress-related events */
113 XSelectInput (ptc_display, ptc_window, KeyPressMask);
114 /* Initialize window's sizehint definition structure */
115 /* Clear the window */
116 XClearWindow (ptc_display, ptc_window);
117 /* Put the window on top of the others */
118 XMapRaised (ptc_display, ptc_window);
119 /* Clear event queue */
120 XFlush (ptc_display);
121 /* Get the default graphic context */
122 ptc_window_gc = DefaultGC (ptc_display, ptc_screen);
124 if (ptc_xv_ok == 0) break;
125 if (XvQueryAdaptors(ptc_display,ptc_window,&nAdaptors,&adaptors) != Success) {
130 for (i = 0; i < nAdaptors; i++) {
131 for (j = 0; j < adaptors[i].num_ports; j++) {
132 if (!(adaptors[i].type && XvInputMask) || !(adaptors[i].type && XvImageMask)) continue;
133 fmts = XvListImageFormats(ptc_display,adaptors[i].base_id + j, &nFmts);
134 if (fmts == NULL) continue;
135 for (k = 0; k < nFmts; k++) {
136 if (fmts[k].id == 0x32315659) {
137 if (fmts[k].guid[0] != 'Y') break;
138 if (fmts[k].guid[1] != 'V') break;
139 if (fmts[k].guid[2] != '1') break;
140 if (fmts[k].guid[3] != '2') break;
141 if (XvGrabPort(ptc_display,adaptors[i].base_id + j,0) == Success) {
143 ptc_xv_port = adaptors[i].base_id + j;
149 if (ptc_xv_ok == 1) break;
151 if (ptc_xv_ok == 1) break;
153 XvFreeAdaptorInfo(adaptors);
154 if (ptc_xv_ok == 0) {
155 /* Destroy the window */
156 XDestroyWindow (ptc_display, ptc_window);
157 /* Close the display */
158 XCloseDisplay (ptc_display);
163 if (ptc_xv_ok == 0) return 0;
164 /* Get a shared segment */
165 ptc_shm_segment.shmid =
166 shmget (IPC_PRIVATE, width * height + (width * height)/2,
168 /* Save buffer address */
169 ptc_shm_segment.shmaddr = shmat(ptc_shm_segment.shmid,0,0);
170 /* Put the segment in read/write */
171 ptc_shm_segment.readOnly = False;
172 /* Attach the segment to the display */
173 if (!XShmAttach (ptc_display, &ptc_shm_segment))
175 /* Detach the buffer from the segment */
176 shmdt (ptc_shm_segment.shmaddr);
177 /* Remove the segment */
178 shmctl (ptc_shm_segment.shmid, IPC_RMID, 0);
179 /* Destroy the window */
180 XvUngrabPort(ptc_display,ptc_xv_port,0);
181 XDestroyWindow (ptc_display, ptc_window);
182 /* Close the display */
183 XCloseDisplay (ptc_display);
187 ptc_xvimage = XvShmCreateImage(ptc_display,ptc_xv_port,0x32315659,ptc_shm_segment.shmaddr,
188 width,height,&ptc_shm_segment);
189 if (ptc_xvimage == NULL) {
190 /* Detach the buffer from the segment */
191 shmdt (ptc_shm_segment.shmaddr);
192 /* Remove the segment */
193 shmctl (ptc_shm_segment.shmid, IPC_RMID, 0);
194 /* Destroy the window */
195 XvUngrabPort(ptc_display,ptc_xv_port,0);
196 XDestroyWindow (ptc_display, ptc_window);
197 /* Close the display */
198 XCloseDisplay (ptc_display);
202 ptc_viewport_width = width;
203 ptc_viewport_height = height;
207 /* Update the screen */
210 ptc_update (void *buffer)
212 int wsize,hsize,dum1,dum2,dum3,dum4;
213 unsigned char *pin, *py,*pu,*pv,*pfin;
214 int strid8,strid2,stridby2;
216 if (ptc_xv_ok == 1) {
217 if (!XGetGeometry(ptc_display,ptc_window,&wndret,&dum1,&dum2,
218 &wsize,&hsize,&dum3,&dum4)) {
219 wsize = ptc_viewport_width;
220 hsize = ptc_viewport_height;
222 pin = (unsigned char *)buffer;
223 py = ptc_shm_segment.shmaddr;
224 pu = &py[ptc_viewport_width*ptc_viewport_height];
225 pv = &pu[(ptc_viewport_width*ptc_viewport_height)/4];
226 strid8 = ptc_viewport_width*8;
227 strid2 = ptc_viewport_width*2;
228 stridby2 = ptc_viewport_width/2;
232 convert_yv12_mmx(pin,py,pu,pv,ptc_viewport_width);
234 convert_yv12_c(pin,py,pu,pv,ptc_viewport_width);
241 XvShmPutImage(ptc_display,ptc_xv_port,ptc_window,ptc_window_gc,
242 ptc_xvimage,0,0,ptc_viewport_width,ptc_viewport_height,0,0,wsize,hsize,True);
245 if (ptc_process_events ())
256 ptc_process_events (void)
260 /* Check if there are events waiting in the display's queue */
261 if (XPending (ptc_display))
263 /* Get the next event in queue */
264 XNextEvent (ptc_display, &ptc_xevent);
265 /* Check if it's a keypress event */
266 if (ptc_xevent.type == KeyPress)
269 ptc_keysym = XLookupKeysym (&ptc_xevent.xkey, 0);
270 /* Check if the key pressed was a function one */
271 if ((ptc_keysym >> 8) == __PTC_FUNCTION_KEY__)
273 /* Check if it was the escape key */
274 if ((ptc_keysym & 0xFF) == __PTC_ESCAPE_KEY__)
284 /* Close the screen */
289 if (ptc_xv_ok == 1) {
292 /* Detach the segment from the display */
293 XShmDetach (ptc_display, &ptc_shm_segment);
294 /* Destroy the XShmImage */
295 /* Detach the buffer from the segment */
296 shmdt (ptc_shm_segment.shmaddr);
297 /* Remove the segment */
298 shmctl (ptc_shm_segment.shmid, IPC_RMID, 0);
299 XvUngrabPort(ptc_display,ptc_xv_port,0);
300 /* Close the window */
301 XDestroyWindow (ptc_display, ptc_window);
302 XCloseDisplay (ptc_display);
303 /* Deallocate the buffer */
314 /* very slow conversion routine - just for reference */
315 static unsigned int ybufr[256];
316 static unsigned int ybufg[256];
317 static unsigned int ybufb[256];
318 static unsigned char ubuf[512];
319 static unsigned char vbuf[512];
320 static unsigned char *uptr;
321 static unsigned char *vptr;
330 for (i = 0, c = 0; i < 256; i++, c++) {
336 for (j = 0, c = 0; j < 256; j++, c++) {
337 ubuf[j] = ((16122*(c-c2))>>15)+128;
338 vbuf[j] = ((25203*(c-c2))>>15)+128;
341 for (j = 256, c = 1; j < 511; j++, c++) {
342 ubuf[j] = ((16122*(c-c2))>>15)+128;
343 vbuf[j] = ((25203*(c-c2))>>15)+128;
347 void inline getyuv2(unsigned char *c, unsigned char *y, unsigned char *u, unsigned char *v)
349 *y = (ybufr[c[0]] + ybufg[c[1]] + ybufb[c[2]]) >> 15;
354 void convert_yv12_c(void *expix2, unsigned char *py, unsigned char *pu, unsigned char *pv, int width)
356 unsigned char *l,*nl;
358 unsigned char u1,u2,u3,u4;
359 unsigned char v1,v2,v3,v4;
360 unsigned int tmp1,tmp2;
363 l = (unsigned char *)expix2;
370 for (j = 0; j < width; j += 2) {
371 getyuv2(l,&py[0],&u1,&v1);
372 getyuv2(&l[4],&py[1],&u2,&v2);
373 getyuv2(nl,&pny[0],&u3,&v3);
374 getyuv2(&nl[4],&pny[1],&u4,&v4);
375 tmp1 = u1 + u2 + u3 + u4 + 2;
376 tmp2 = v1 + v2 + v3 + v4 + 2;
377 pu[0] = (unsigned char)(tmp1 >> 2);
378 pv[0] = (unsigned char)(tmp2 >> 2);
388 #endif /* !__PTC_MMX__ */
390 #endif /* __PTC_XVSHM__ */