Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  * (most) Xvideo extention code is here.
  3  *
  4  * (c) 2001 Gerd Knorr <kraxel@bytesex.org>
  5  */
  6 
  7 #include "config.h"
  8 
  9 #ifdef HAVE_LIBXV
 10 
 11 #include <stdio.h>
 12 #include <stdlib.h>
 13 #include <unistd.h>
 14 #include <string.h>
 15 #include <pthread.h>
 16 #include <sys/ipc.h>
 17 #include <sys/shm.h>
 18 
 19 #include <X11/Xlib.h>
 20 #include <X11/Xatom.h>
 21 #include <X11/Intrinsic.h>
 22 #include <X11/Shell.h>
 23 #include <X11/extensions/XShm.h>
 24 #include <X11/extensions/Xv.h>
 25 #include <X11/extensions/Xvlib.h>
 26 
 27 #include "grab-ng.h"
 28 #include "commands.h"    /* FIXME: global *drv vars */
 29 #include "atoms.h"
 30 #include "xv.h"
 31 
 32 extern Display    *dpy;
 33 int               have_xv;
 34 
 35 const struct ng_vid_driver xv_driver;
 36 
 37 static int              ver, rel, req, ev, err, grabbed;
 38 static int              adaptors;
 39 static int              attributes;
 40 static XvAdaptorInfo        *ai;
 41 static XvEncodingInfo       *ei;
 42 static XvAttribute          *at;
 43 
 44 static int
 45 xv_overlay(void *handle, struct ng_video_fmt *fmt, int x, int y,
 46            struct OVERLAY_CLIP *oc, int count, int aspect)
 47 {
 48     if (debug)
 49         fprintf(stderr,"Ouch: xv_overlay called\n");
 50     return 0;
 51 }
 52 
 53 /* ********************************************************************* */
 54 
 55 struct ENC_MAP {
 56     int norm;
 57     int input;
 58     int encoding;
 59 };
 60 
 61 struct xv_handle {
 62     /* port */
 63     int                  vi_adaptor;
 64     XvPortID             vi_port;
 65     GC                   vi_gc;
 66     
 67     /* attributes */
 68     int                  nattr;
 69     struct ng_attribute  *attr;
 70     Atom xv_encoding;
 71     Atom xv_freq;
 72     Atom xv_colorkey;
 73 
 74     /* encoding */
 75     struct ENC_MAP       *enc_map;
 76     int                  norm, input, enc;
 77     int                  encodings;
 78 };
 79 
 80 static const struct XVATTR {
 81     int   id;
 82     int   type;
 83     char  *atom;
 84 } xvattr[] = {
 85     { ATTR_ID_COLOR,    ATTR_TYPE_INTEGER, "XV_COLOR"       },
 86     { ATTR_ID_COLOR,    ATTR_TYPE_INTEGER, "XV_SATURATION"  },
 87     { ATTR_ID_HUE,      ATTR_TYPE_INTEGER, "XV_HUE",        },
 88     { ATTR_ID_BRIGHT,   ATTR_TYPE_INTEGER, "XV_BRIGHTNESS", },
 89     { ATTR_ID_CONTRAST, ATTR_TYPE_INTEGER, "XV_CONTRAST",   },
 90     { ATTR_ID_MUTE,     ATTR_TYPE_BOOL,    "XV_MUTE",       },
 91     { ATTR_ID_VOLUME,   ATTR_TYPE_INTEGER, "XV_VOLUME",     },
 92     { -1,               -1,                "XV_COLORKEY",   },
 93     { -1,               -1,                "XV_FREQ",       },
 94     { -1,               -1,                "XV_ENCODING",   },
 95     {}
 96 };
 97 
 98 static int xv_read_attr(struct ng_attribute *attr)
 99 {
100     struct xv_handle *h   = attr->handle;
101     const XvAttribute *at = attr->priv;
102     Atom atom;
103     int value = 0;
104 
105     if (NULL != at) {
106         atom = XInternAtom(dpy, at->name, False);
107         XvGetPortAttribute(dpy, h->vi_port,atom,&value);
108         if (debug)
109             fprintf(stderr,"xv: get %s: %d\n",at->name,value);
110         
111     } else if (attr->id == ATTR_ID_NORM) {
112         value = h->norm;
113         
114     } else if (attr->id == ATTR_ID_INPUT) {
115         value = h->input;
116 
117     }
118     return value;
119 }
120 
121 static void xv_write_attr(struct ng_attribute *attr, int value)
122 {
123     struct xv_handle *h   = attr->handle;
124     const XvAttribute *at = attr->priv;
125     Atom atom;
126     int i;
127 
128     if (NULL != at) {
129         atom = XInternAtom(dpy, at->name, False);
130         XvSetPortAttribute(dpy, h->vi_port,atom,value);
131         if (debug)
132             fprintf(stderr,"xv: set %s: %d\n",at->name,value);
133 
134     } else if (attr->id == ATTR_ID_NORM || attr->id == ATTR_ID_INPUT) {
135         if (attr->id == ATTR_ID_NORM)
136             h->norm  = value;
137         if (attr->id == ATTR_ID_INPUT)
138             h->input = value;
139         for (i = 0; i < h->encodings; i++) {
140             if (h->enc_map[i].norm  == h->norm &&
141                 h->enc_map[i].input == h->input) {
142                 h->enc = i;
143                 XvSetPortAttribute(dpy,h->vi_port,h->xv_encoding,h->enc);
144                 break;
145             }
146         }
147     }
148     /* needed for proper timing on the
149        "mute - wait - switch - wait - unmute" channel switches */
150     XSync(dpy,False);
151 }
152 
153 static void
154 xv_add_attr(struct xv_handle *h, int id, int type,
155             int defval, struct STRTAB *choices, XvAttribute *at)
156 {
157     int i;
158     
159     h->attr = realloc(h->attr,(h->nattr+2) * sizeof(struct ng_attribute));
160     memset(h->attr+h->nattr,0,sizeof(struct ng_attribute)*2);
161     if (at) {
162         h->attr[h->nattr].priv    = at;
163         for (i = 0; xvattr[i].atom != NULL; i++)
164             if (0 == strcmp(xvattr[i].atom,at->name))
165                 break;
166         if (-1 == xvattr[i].type)
167             /* ignore this one */
168             return;
169         if (NULL != xvattr[i].atom) {
170             h->attr[h->nattr].id      = xvattr[i].id;
171             h->attr[h->nattr].type    = xvattr[i].type;
172             h->attr[h->nattr].priv    = at;
173             if (ATTR_TYPE_INTEGER == h->attr[h->nattr].type) {
174                 h->attr[h->nattr].min = at->min_value;
175                 h->attr[h->nattr].max = at->max_value;
176             }
177         } else {
178             /* unknown */
179             return;
180         }
181     }
182 
183     if (id)
184         h->attr[h->nattr].id      = id;
185     if (type)
186         h->attr[h->nattr].type    = type;
187     if (defval)
188         h->attr[h->nattr].defval  = defval;
189     if (choices)
190         h->attr[h->nattr].choices = choices;
191     if (h->attr[h->nattr].id < ATTR_ID_COUNT)
192         h->attr[h->nattr].name    = ng_attr_to_desc[h->attr[h->nattr].id];
193 
194     h->attr[h->nattr].read    = xv_read_attr;
195     h->attr[h->nattr].write   = xv_write_attr;
196     h->attr[h->nattr].handle  = h;
197     h->nattr++;
198 }
199 
200 static unsigned long
201 xv_getfreq(void *handle)
202 {
203     struct xv_handle *h = handle;
204     unsigned int freq;
205 
206     XvGetPortAttribute(dpy,h->vi_port,h->xv_freq,&freq);
207     return freq;
208 }
209 
210 static void
211 xv_setfreq(void *handle, unsigned long freq)
212 {
213     struct xv_handle *h = handle;
214 
215     XvSetPortAttribute(dpy,h->vi_port,h->xv_freq,freq);
216     XSync(dpy,False);
217 }
218 
219 static int
220 xv_tuned(void *handle)
221 {
222     /* don't know ... */
223     return 0;
224 }
225 
226 void
227 xv_video(Window win, int dw, int dh, int on)
228 {
229     struct xv_handle *h = h_drv; /* FIXME */
230     int sx,sy,dx,dy;
231     int sw,sh;
232     
233     if (on) {
234         sx = sy = dx = dy = 0;
235         sw = dw;
236         sh = dh;
237         if (-1 != h->enc) {
238             sw = ei[h->enc].width;
239             sh = ei[h->enc].height;
240         }
241         if (NULL == h->vi_gc)
242             h->vi_gc = XCreateGC(dpy, win, 0, NULL);
243         ng_ratio_fixup(&dw,&dh,&dx,&dy);
244         if (0 == grabbed)
245             if (Success == XvGrabPort(dpy,h->vi_port,CurrentTime))
246                 grabbed = 1;
247         if (1 == grabbed) {
248             XvPutVideo(dpy,h->vi_port,win,h->vi_gc,
249                        sx,sy,sw,sh, dx,dy,dw,dh);
250             if (debug)
251                 fprintf(stderr,"Xvideo: video: win=0x%lx, "
252                         "src=%dx%d+%d+%d dst=%dx%d+%d+%d\n",
253                         win, sw,sh,sx,sy, dw,dh,dx,dy);
254         } else {
255             fprintf(stderr,"Xvideo: port %ld busy\n",h->vi_port);
256         }
257     } else {
258         if (grabbed) {
259             XClearArea(dpy,win,0,0,0,0,False);
260             XvStopVideo(dpy,h->vi_port,win);
261             XvUngrabPort(dpy,h->vi_port,CurrentTime);
262             grabbed = 0;
263             if (debug)
264                 fprintf(stderr,"Xvideo: video off\n");
265         }
266     }
267 }
268 
269 static int
270 xv_strlist_add(struct STRTAB **tab, char *str)
271 {
272     int i;
273 
274     if (NULL == *tab) {
275         *tab = malloc(sizeof(struct STRTAB)*2);
276         i = 0;
277     } else {
278         for (i = 0; (*tab)[i].str != NULL; i++)
279             if (0 == strcasecmp((*tab)[i].str,str))
280                 return (*tab)[i].nr;
281         *tab = realloc(*tab,sizeof(struct STRTAB)*(i+2));
282     }
283     (*tab)[i].nr  = i;
284     (*tab)[i].str = strdup(str);
285     (*tab)[i+1].nr  = -1;
286     (*tab)[i+1].str = NULL;
287     return i;
288 }
289 
290 static int xv_close(void *handle) { return 0; }
291 
292 static int xv_flags(void *handle)
293 {
294     struct xv_handle *h = handle;
295     int ret = 0;
296 
297     ret |= CAN_OVERLAY;
298     if (h->xv_freq != None)
299         ret |= CAN_TUNE;
300     return ret;
301 }
302 
303 static struct ng_attribute* xv_attrs(void *handle)
304 {
305     struct xv_handle *h  = handle;
306     return h->attr;
307 }
308 
309 /* ********************************************************************* */
310 
311 void xv_video_init(unsigned int port, int hwscan)
312 {
313     struct xv_handle *handle;
314     struct STRTAB *norms  = NULL;
315     struct STRTAB *inputs = NULL;
316     char *h;
317     int n, i, vi_port = -1, vi_adaptor = -1;
318 
319     if (Success != XvQueryExtension(dpy,&ver,&rel,&req,&ev,&err)) {
320         if (debug)
321             fprintf(stderr,"Xvideo: Server has no Xvideo extention support\n");
322         return;
323     }
324     if (Success != XvQueryAdaptors(dpy,DefaultRootWindow(dpy),&adaptors,&ai)) {
325         fprintf(stderr,"Xvideo: XvQueryAdaptors failed");
326         exit(1);
327     }
328     if (debug)
329         fprintf(stderr,"Xvideo: %d adaptors available.\n",adaptors);
330     for (i = 0; i < adaptors; i++) {
331         if (debug)
332             fprintf(stderr,"Xvideo: %s:%s%s%s%s%s, ports %ld-%ld\n",
333                     ai[i].name,
334                     (ai[i].type & XvInputMask)  ? " input"  : "",
335                     (ai[i].type & XvOutputMask) ? " output" : "",
336                     (ai[i].type & XvVideoMask)  ? " video"  : "",
337                     (ai[i].type & XvStillMask)  ? " still"  : "",
338                     (ai[i].type & XvImageMask)  ? " image"  : "",
339                     ai[i].base_id,
340                     ai[i].base_id+ai[i].num_ports-1);
341         if (hwscan) {
342             /* just print some info's about the Xvideo port */
343             n = fprintf(stderr,"port %ld-%ld",
344                         ai[i].base_id,ai[i].base_id+ai[i].num_ports-1);
345             if ((ai[i].type & XvInputMask) &&
346                 (ai[i].type & XvVideoMask))
347                 fprintf(stderr,"%*s[ -xvport %ld ]",40-n,"",ai[i].base_id);
348             fprintf(stderr,"\n");
349             if ((ai[i].type & XvInputMask) &&
350                 (ai[i].type & XvVideoMask))
351                 fprintf(stderr,"    type : Xvideo, video overlay\n");
352             if ((ai[i].type & XvInputMask) &&
353                 (ai[i].type & XvImageMask))
354                 fprintf(stderr,"    type : Xvideo, image scaler\n");
355             fprintf(stderr,"    name : %s\n",ai[i].name);
356             fprintf(stderr,"\n");
357             continue;
358         }
359         
360         if ((ai[i].type & XvInputMask) &&
361             (ai[i].type & XvVideoMask) &&
362             (vi_port == -1)) {
363             if (0 == port) {
364                 vi_port = ai[i].base_id;
365                 vi_adaptor = i;
366             } else if (port >= ai[i].base_id  &&
367                        port <  ai[i].base_id+ai[i].num_ports) {
368                 vi_port = port;
369                 vi_adaptor = i;
370             } else {
371                 if (debug)
372                     fprintf(stderr,"Xvideo: skipping ports %ld-%ld (configured other: %d)\n",
373                             ai[i].base_id, ai[i].base_id+ai[i].num_ports-1, port);
374             }
375         }
376     }
377     if (hwscan)
378         return;
379 
380     /* *** video port *** */
381     if (vi_port == -1) {
382         if (debug)
383             fprintf(stderr,"Xvideo: no usable video port found\n");
384     } else {
385         if (debug)
386             fprintf(stderr,"Xvideo: using port %d for video\n",vi_port);
387         handle = malloc(sizeof(struct xv_handle));
388         memset(handle,0,sizeof(struct xv_handle));
389         handle->vi_port     = vi_port;
390         handle->vi_adaptor  = vi_adaptor;
391         handle->xv_encoding = None;
392         handle->xv_freq     = None;
393         handle->xv_colorkey = None;
394         handle->enc         = -1;
395         handle->norm        = -1;
396         handle->input       = -1;
397 
398         /* query encoding list */
399         if (Success != XvQueryEncodings(dpy, vi_port,
400                                         &handle->encodings, &ei)) {
401             fprintf(stderr,"Oops: XvQueryEncodings failed\n");
402             exit(1);
403         }
404         handle->enc_map = malloc(sizeof(struct ENC_MAP)*handle->encodings);
405         for (i = 0; i < handle->encodings; i++) {
406             if (NULL != (h = strrchr(ei[i].name,'-'))) {
407                 *(h++) = 0;
408                 handle->enc_map[i].input = xv_strlist_add(&inputs,h);
409             }
410             handle->enc_map[i].norm = xv_strlist_add(&norms,ei[i].name);
411             handle->enc_map[i].encoding = ei[i].encoding_id;
412         }
413 
414         /* build atoms */
415         at = XvQueryPortAttributes(dpy,vi_port,&attributes);
416         for (i = 0; i < attributes; i++) {
417             if (debug)
418                 fprintf(stderr,"  %s%s%s, %i -> %i\n",
419                         at[i].name,
420                         (at[i].flags & XvGettable) ? " get" : "",
421                         (at[i].flags & XvSettable) ? " set" : "",
422                         at[i].min_value,at[i].max_value);
423             if (0 == strcmp("XV_ENCODING",at[i].name))
424                 handle->xv_encoding = XV_ENCODING;
425             if (0 == strcmp("XV_FREQ",at[i].name))
426                 handle->xv_freq     = XV_FREQ;
427 #if 0
428             if (0 == strcmp("XV_COLORKEY",at[i].name))
429                 handle->xv_colorkey = XV_COLORKEY;
430 #endif
431             xv_add_attr(handle, 0, 0, 0, NULL, at+i);
432         }
433 
434         if (handle->xv_encoding != None) {
435             if (norms)
436                 xv_add_attr(handle, ATTR_ID_NORM, ATTR_TYPE_CHOICE,
437                             0, norms, NULL);
438             if (inputs)
439                 xv_add_attr(handle, ATTR_ID_INPUT, ATTR_TYPE_CHOICE,
440                             0, inputs, NULL);
441         }
442 #if 0
443         if (xv_colorkey != None) {
444             XvGetPortAttribute(dpy,vi_port,xv_colorkey,&xv.colorkey);
445             fprintf(stderr,"Xvideo: colorkey: %x\n",xv.colorkey);
446         }
447 #endif
448         have_xv = 1;
449         drv   = &xv_driver;
450         h_drv = handle;
451         f_drv = xv_flags(h_drv);
452         add_attrs(xv_attrs(h_drv));
453     }
454 }
455 
456 /* ********************************************************************* */
457 
458 #if 0
459 static Window icon_win;
460 static int icon_width,icon_height;
461 
462 static void
463 icon_event(Widget widget, XtPointer client_data, XEvent *event, Boolean *d)
464 {
465     switch (event->type) {
466     case Expose:
467         if (debug)
468             fprintf(stderr,"icon expose\n");
469         xv_video(icon_win, icon_width, icon_height, 1);
470         break;
471     case MapNotify:
472         if (debug)
473             fprintf(stderr,"icon map\n");
474         xv_video(icon_win, icon_width, icon_height, 1);
475         break;
476     case UnmapNotify:
477         if (debug)
478             fprintf(stderr,"icon unmap\n");
479         break;
480     default:
481         fprintf(stderr,"icon other\n");
482         break;
483     }
484 }
485 
486 void
487 init_icon_window(Widget shell,WidgetClass class)
488 {
489     Window root = RootWindowOfScreen(XtScreen(shell));
490     Widget widget;
491     XIconSize *is;
492     int i,count;
493 
494     if (XGetIconSizes(XtDisplay(shell),root,&is,&count)) {
495         for (i = 0; i < count; i++) {
496             fprintf(stderr,"icon size: min=%dx%d - max=%dx%d - inc=%dx%d\n",
497                     is[i].min_width, is[i].min_height,
498                     is[i].max_width, is[i].max_height,
499                     is[i].width_inc, is[i].height_inc);
500         }
501         icon_width  = is[0].max_width;
502         icon_height = is[0].max_height;
503         if (icon_width * 3 > icon_height * 4) {
504             while (icon_width * 3 > icon_height * 4 &&
505                    icon_width - is[0].width_inc > is[0].min_width)
506                 icon_width -= is[0].width_inc;
507         } else {
508             while (icon_width * 3 < icon_height * 4 &&
509                    icon_height - is[0].height_inc > is[0].min_height)
510                 icon_height -= is[0].height_inc;
511         }
512     } else {
513         icon_width  = 64;
514         icon_height = 48;
515     }
516     fprintf(stderr,"icon init %dx%d\n",icon_width,icon_height);
517     
518     icon_win = XCreateWindow(XtDisplay(shell),root,
519                              0,0,icon_width,icon_height,1,
520                              CopyFromParent,InputOutput,CopyFromParent,
521                              0,NULL);
522     widget = XtVaCreateWidget("icon",class,shell,NULL);
523     XtRegisterDrawable(XtDisplay(shell),icon_win,widget);
524     XtAddEventHandler(widget,StructureNotifyMask | ExposureMask,
525                       False,icon_event,NULL);
526     XSelectInput(XtDisplay(shell),icon_win,
527                  StructureNotifyMask | ExposureMask);
528     XtVaSetValues(shell,XtNiconWindow,icon_win,NULL);
529 }
530 #endif
531 
532 /* ********************************************************************* */
533 
534 const struct ng_vid_driver xv_driver = {
535     name:          "Xvideo",
536     close:         xv_close,
537 
538     capabilities:  xv_flags,
539     list_attrs:    xv_attrs,
540 
541     overlay:       xv_overlay,
542 
543     getfreq:       xv_getfreq,
544     setfreq:       xv_setfreq,
545     is_tuned:      xv_tuned,
546 };
547 
548 #else /* HAVE_LIBXV */
549 
550 int               have_xv = 0;
551 
552 #endif /* HAVE_LIBXV */
553 
  This page was automatically generated by the LXR engine.