1 /*
2  *  display.c
3  *
4  *     Copyright (C) Charles 'Buck' Krasic - April 2000
5  *     Copyright (C) Erik Walthinsen - April 2000
6  *
7  *  This file is part of libdv, a free DV (IEC 61834/SMPTE 314M)
8  *  codec.
9  *
10  *  libdv is free software; you can redistribute it and/or modify it
11  *  under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2, or (at your
13  *  option) any later version.
14  *
15  *  libdv is distributed in the hope that it will be useful, but
16  *  WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  *  General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with GNU Make; see the file COPYING.  If not, write to
22  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  *  The libdv homepage is http://libdv.sourceforge.net/.
25  */
26 
27 /* Most of this file is derived from patches 101018 and 101136 submitted by
28  * Stefan Lucke <lucke@berlin.snafu.de> */
29 
30 
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34 
35 #include <unistd.h>
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <math.h>
39 #include <string.h>
40 
41 #include <libdv/dv_types.h>
42 #include "display.h"
43 
44 #include "libtc/libtc.h"
45 
46 #if HAVE_LIBXV
47 #include <sys/ipc.h>
48 #include <sys/shm.h>
49 #endif
50 
51 // FIXME: Use autoconf for this!!
52 // MacOSX SDL uses native GUI frameworks, but this is an X11
53 // application setup.
54 #ifdef __APPLE__
55 #undef HAVE_SDL
56 #endif
57 
58 static int      dv_display_SDL_init(dv_display_t *dv_dpy, char *w_name, char   *i_name           );
59 static int      dv_display_gdk_init(dv_display_t *dv_dpy, int  *argc,   char ***argv             );
60 
61 #if HAVE_SDL
62 static void dv_center_window(SDL_Surface *screen);
63 #endif
64 
65 #if HAVE_LIBXV
66 
67 #define XV_FORMAT_MASK		0x03
68 #define XV_FORMAT_ASIS		0x00
69 #define XV_FORMAT_NORMAL	0x01
70 #define XV_FORMAT_WIDE		0x02
71 
72 #define XV_SIZE_MASK		0x0c
73 #define XV_SIZE_NORMAL		0x04
74 #define XV_SIZE_QUARTER		0x08
75 
76 #define XV_NOSAWINDOW		0x10	/* not use at the moment	*/
77 
78 #define DV_FORMAT_UNKNOWN	-1
79 #define DV_FORMAT_NORMAL	0
80 #define DV_FORMAT_WIDE		1
81 
82 static void dv_display_event (dv_display_t *dv_dpy);
83 static int dv_display_Xv_init (dv_display_t *dv_dpy, char *w_name,
84 				char   *i_name, int flags, int size);
85 #endif
86 
87 dv_display_t *
dv_display_new(void)88 dv_display_new(void)
89 {
90   dv_display_t *result;
91 
92   result = (dv_display_t *)calloc(1,sizeof(dv_display_t));
93   if(!result) goto no_mem;
94 
95  no_mem:
96   return(result);
97 } /* dv_display_new */
98 
99 void
dv_display_show(dv_display_t * dv_dpy)100 dv_display_show(dv_display_t *dv_dpy) {
101   switch(dv_dpy->lib) {
102   case e_dv_dpy_Xv:
103 #if HAVE_LIBXV
104     dv_display_event(dv_dpy);
105     if (!dv_dpy->dontdraw) {
106       XvShmPutImage(dv_dpy->dpy, dv_dpy->port,
107 		  dv_dpy->win, dv_dpy->gc,
108 		  dv_dpy->xv_image,
109 		  0, 0,					        /* sx, sy */
110 		  dv_dpy->swidth, dv_dpy->sheight,	        /* sw, sh */
111 		  dv_dpy->lxoff,  dv_dpy->lyoff,                /* dx, dy */
112 		  dv_dpy->lwidth, dv_dpy->lheight,	        /* dw, dh */
113 		  True);
114       XFlush(dv_dpy->dpy);
115     }
116 #endif /* HAVE_LIBXV */
117     break;
118   case e_dv_dpy_XShm:
119     break;
120   case e_dv_dpy_gtk:
121     break;
122   case e_dv_dpy_SDL:
123 #if HAVE_SDL
124     {
125       SDL_Event event;
126       if (SDL_PollEvent(&event)) {
127 	if ( event.type == SDL_KEYDOWN ) {
128 	  switch(event.key.keysym.sym) {
129 	    case SDLK_ESCAPE:
130 	    case SDLK_q:
131 	      dv_dpy->dontdraw = 1;
132 	      break;
133 	    default:
134 	      break;
135 	  }
136 	}
137       }
138 
139       if (!dv_dpy->dontdraw) {
140 	SDL_UnlockYUVOverlay(dv_dpy->overlay);
141 	SDL_DisplayYUVOverlay(dv_dpy->overlay, &dv_dpy->rect);
142 	SDL_LockYUVOverlay(dv_dpy->overlay);
143       } else {
144 	SDL_Quit();
145       }
146     }
147 #endif
148     break;
149   default:
150     break;
151   } /* switch */
152 } /* dv_display_show */
153 
154 void
dv_display_exit(dv_display_t * dv_dpy)155 dv_display_exit(dv_display_t *dv_dpy) {
156   if(!dv_dpy)
157     return;
158 
159   switch(dv_dpy->lib) {
160   case e_dv_dpy_Xv:
161 #if HAVE_LIBXV
162 
163     XvStopVideo(dv_dpy->dpy, dv_dpy->port, dv_dpy->win);
164 
165     if(dv_dpy->shminfo.shmaddr)
166       shmdt(dv_dpy->shminfo.shmaddr);
167 
168     if(dv_dpy->shminfo.shmid > 0)
169       shmctl(dv_dpy->shminfo.shmid, IPC_RMID, 0);
170 
171     if(dv_dpy->xv_image)
172       free(dv_dpy->xv_image);
173       dv_dpy->xv_image = NULL;
174 
175 #endif /* HAVE_LIBXV */
176     break;
177   case e_dv_dpy_gtk:
178     break;
179   case e_dv_dpy_XShm:
180     break;
181   case e_dv_dpy_SDL:
182 #if HAVE_SDL
183     SDL_Quit();
184 #endif /* HAVE_SDL */
185     break;
186   } /* switch */
187 
188   free(dv_dpy);
189   dv_dpy = NULL;
190 } /* dv_display_exit */
191 
192 static int
dv_display_gdk_init(dv_display_t * dv_dpy,int * argc,char *** argv)193 dv_display_gdk_init(dv_display_t *dv_dpy, int *argc, char ***argv) {
194 
195   return FALSE;
196 } /* dv_display_gdk_init */
197 
198 #if HAVE_LIBXV
199 
200 static int xv_pause=0;
201 
202 /* ----------------------------------------------------------------------------
203  */
204 static void
dv_display_event(dv_display_t * dv_dpy)205 dv_display_event (dv_display_t *dv_dpy)
206 {
207     int	old_pic_format;
208     KeySym keysym;
209     char buf[16];
210 
211 
212   while (XCheckTypedWindowEvent (dv_dpy->dpy, dv_dpy->win,
213 				 ConfigureNotify, &dv_dpy->event) ||
214   XCheckTypedWindowEvent (dv_dpy->dpy, dv_dpy->win,
215 				 KeyPress, &dv_dpy->event)) {
216     switch (dv_dpy->event.type) {
217       case ConfigureNotify:
218 	dv_dpy->dwidth = dv_dpy->event.xconfigure.width;
219 	dv_dpy->dheight = dv_dpy->event.xconfigure.height;
220         /* --------------------------------------------------------------------
221          * set current picture format to unknown, so that .._check_format
222          * does some work.
223          */
224         old_pic_format = dv_dpy->pic_format;
225         dv_dpy->pic_format = DV_FORMAT_UNKNOWN;
226         dv_display_check_format (dv_dpy, old_pic_format);
227 	break;
228       case KeyPress:
229 
230 	XLookupString (&dv_dpy->event.xkey, buf, 16, &keysym, NULL);
231 
232 	switch(keysym) {
233 
234 	case XK_Escape:
235 	  dv_dpy->dontdraw = 1;
236 	  xv_pause=0;
237 	  XvStopVideo(dv_dpy->dpy, dv_dpy->port, dv_dpy->win);
238 	  XDestroyWindow(dv_dpy->dpy, dv_dpy->win);
239 	  break;
240 
241 	case XK_Q:
242 	case XK_q:
243 	  xv_pause=0;
244 	  dv_dpy->dontdraw = (dv_dpy->dontdraw) ? 0:1;
245 	  break;
246 
247 	case XK_space:
248 	  xv_pause = (xv_pause)?0:1;
249 	  while(xv_pause) {
250 	    dv_display_event(dv_dpy);
251 	    usleep(10000);
252 	  }
253 
254 	default:
255 		break;
256 	}
257 	break;
258       default:
259 	break;
260     } /* switch */
261   } /* while */
262 } /* dv_display_event */
263 
264 #endif /* HAVE_LIBXV */
265 
266 /* ----------------------------------------------------------------------------
267  */
268 void
dv_display_set_norm(dv_display_t * dv_dpy,dv_system_t norm)269 dv_display_set_norm (dv_display_t *dv_dpy, dv_system_t norm)
270 {
271 #if HAVE_LIBXV
272   dv_dpy->sheight = (norm == e_dv_system_625_50) ? 576: 480;
273 #endif /* HAVE_LIBXV */
274 } /* dv_display_set_norm */
275 
276 /* ----------------------------------------------------------------------------
277  */
278 void
dv_display_check_format(dv_display_t * dv_dpy,int pic_format)279 dv_display_check_format(dv_display_t *dv_dpy, int pic_format)
280 {
281 #if HAVE_LIBXV
282   /*  return immediate if ther is no format change or no format
283    * specific flag was set upon initialisation
284    */
285   if (pic_format == dv_dpy->pic_format ||
286       !(dv_dpy->flags & XV_FORMAT_MASK))
287     return;
288 
289   /* --------------------------------------------------------------------
290    * check if there are some aspect ratio constraints
291    */
292   if (dv_dpy->flags & XV_FORMAT_NORMAL) {
293     if (pic_format == DV_FORMAT_NORMAL) {
294       dv_dpy->lxoff = dv_dpy->lyoff = 0;
295       dv_dpy->lwidth = dv_dpy->dwidth;
296       dv_dpy->lheight = dv_dpy->dheight;
297     } else if (pic_format == DV_FORMAT_WIDE) {
298       dv_dpy->lxoff = 0;
299       dv_dpy->lyoff = dv_dpy->dheight / 8;
300       dv_dpy->lwidth = dv_dpy->dwidth;
301       dv_dpy->lheight = (dv_dpy->dheight * 3) / 4;
302     }
303   } else if (dv_dpy->flags & XV_FORMAT_WIDE) {
304     if (pic_format == DV_FORMAT_NORMAL) {
305       dv_dpy->lxoff = dv_dpy->dwidth / 8;
306       dv_dpy->lyoff = 0;
307       dv_dpy->lwidth = (dv_dpy->dwidth * 3) / 4;
308       dv_dpy->lheight = dv_dpy->dheight;
309     } else if (pic_format == DV_FORMAT_WIDE) {
310       dv_dpy->lxoff = dv_dpy->lyoff = 0;
311       dv_dpy->lwidth = dv_dpy->dwidth;
312       dv_dpy->lheight = dv_dpy->dheight;
313     }
314   } else {
315     dv_dpy->lwidth = dv_dpy->dwidth;
316     dv_dpy->lheight = dv_dpy->dheight;
317   }
318   dv_dpy->pic_format = pic_format;
319 #endif /* HAVE_LIBXV */
320 } /* dv_display_check_format */
321 
322 #if HAVE_LIBXV
323 /* ----------------------------------------------------------------------------
324  */
325 static int
dv_display_Xv_init(dv_display_t * dv_dpy,char * w_name,char * i_name,int flags,int size)326 dv_display_Xv_init(dv_display_t *dv_dpy, char *w_name, char *i_name,
327                    int flags, int size) {
328   int		scn_id,
329                 ad_cnt, fmt_cnt,
330                 got_port, got_fmt,
331                 i, k;
332   XGCValues	values;
333   XSizeHints	hints;
334   XWMHints	wmhints;
335   XTextProperty	x_wname, x_iname;
336 
337   XvAdaptorInfo	*ad_info;
338   XvImageFormatValues	*fmt_info;
339 
340   if(!(dv_dpy->dpy = XOpenDisplay(NULL))) {
341     return 0;
342   } /* if */
343 
344   dv_dpy->rwin = DefaultRootWindow(dv_dpy->dpy);
345   scn_id = DefaultScreen(dv_dpy->dpy);
346 
347   /*
348    * So let's first check for an available adaptor and port
349    */
350   if(Success == XvQueryAdaptors(dv_dpy->dpy, dv_dpy->rwin, &ad_cnt, &ad_info)) {
351 
352     for(i = 0, got_port = False; i < ad_cnt; ++i) {
353       tc_log_msg(__FILE__,
354 		 "Xv: %s: ports %ld - %ld",
355 		 ad_info[i].name,
356 		 ad_info[i].base_id,
357 		 ad_info[i].base_id +
358 		 ad_info[i].num_ports - 1);
359 
360       if (dv_dpy->arg_xv_port != 0 &&
361 	      (dv_dpy->arg_xv_port < ad_info[i].base_id ||
362 	       dv_dpy->arg_xv_port >= ad_info[i].base_id+ad_info[i].num_ports)) {
363 	  tc_log_msg(__FILE__,
364 		    "Xv: %s: skipping (looking for port %i)",
365 		    ad_info[i].name,
366 		    dv_dpy->arg_xv_port);
367 	  continue;
368       }
369 
370       if (!(ad_info[i].type & XvImageMask)) {
371 	tc_log_warn(__FILE__,
372 		    "Xv: %s: XvImage NOT in capabilty list (%s%s%s%s%s )",
373 		    ad_info[i].name,
374 		    (ad_info[i].type & XvInputMask) ? " XvInput"  : "",
375 		    (ad_info[i]. type & XvOutputMask) ? " XvOutput" : "",
376 		    (ad_info[i]. type & XvVideoMask)  ?  " XvVideo"  : "",
377 		    (ad_info[i]. type & XvStillMask)  ?  " XvStill"  : "",
378 		    (ad_info[i]. type & XvImageMask)  ?  " XvImage"  : "");
379 	continue;
380       } /* if */
381       fmt_info = XvListImageFormats(dv_dpy->dpy, ad_info[i].base_id,&fmt_cnt);
382       if (!fmt_info || fmt_cnt == 0) {
383 	tc_log_warn(__FILE__, "Xv: %s: NO supported formats", ad_info[i].name);
384 	continue;
385       } /* if */
386       for(got_fmt = False, k = 0; k < fmt_cnt; ++k) {
387 	if (dv_dpy->format == fmt_info[k].id) {
388 	  got_fmt = True;
389 	  break;
390 	} /* if */
391       } /* for */
392       if (!got_fmt) {
393 	char tmpbuf[1000];
394 	*tmpbuf = 0;
395 	for (k = 0; k < fmt_cnt; ++k) {
396 	  tc_snprintf(tmpbuf+strlen(tmpbuf), sizeof(tmpbuf)-strlen(tmpbuf),
397 		      "%s%#08x[%s]", k>0 ? " " : "", fmt_info[k].id,
398 		      fmt_info[k].guid);
399 	}
400 	tc_log_warn(__FILE__,
401 		    "Xv: %s: format %#08x is NOT in format list (%s)",
402 		    ad_info[i].name,
403 		    dv_dpy->format,
404 		    tmpbuf);
405 	continue;
406       } /* if */
407 
408       for(dv_dpy->port = ad_info[i].base_id, k = 0;
409 	  k < ad_info[i].num_ports;
410 	  ++k, ++(dv_dpy->port)) {
411 	if (dv_dpy->arg_xv_port != 0 && dv_dpy->arg_xv_port != dv_dpy->port) continue;
412 	if(!XvGrabPort(dv_dpy->dpy, dv_dpy->port, CurrentTime)) {
413 	  tc_log_msg(__FILE__, "Xv: grabbed port %ld",
414 		     dv_dpy->port);
415 	  got_port = True;
416 	  break;
417 	} /* if */
418       } /* for */
419       if(got_port)
420 	break;
421     } /* for */
422 
423   } else {
424     /* Xv extension probably not present */
425     return 0;
426   } /* else */
427 
428   if(!ad_cnt) {
429     tc_log_warn(__FILE__, "Xv: (ERROR) no adaptor found!");
430     return 0;
431   }
432   if(!got_port) {
433     tc_log_warn(__FILE__, "Xv: (ERROR) could not grab any port!");
434     return 0;
435   }
436 
437   /* --------------------------------------------------------------------------
438    * default settings which allow arbitraray resizing of the window
439    */
440   hints.flags = PSize | PMaxSize | PMinSize;
441   hints.min_width = dv_dpy->width / 16;
442   hints.min_height = dv_dpy->height / 16;
443 
444   /* --------------------------------------------------------------------------
445    * maximum dimensions for Xv support are about 2048x2048
446    */
447   hints.max_width = 2048;
448   hints.max_height = 2048;
449 
450   wmhints.input = True;
451   wmhints.flags = InputHint;
452 
453   XStringListToTextProperty(&w_name, 1 ,&x_wname);
454   XStringListToTextProperty(&i_name, 1 ,&x_iname);
455 
456   /*
457    * default settings: source, destination and logical widht/height
458    * are set to our well known dimensions.
459    */
460   dv_dpy->lwidth = dv_dpy->dwidth = dv_dpy->swidth = dv_dpy->width;
461   dv_dpy->lheight = dv_dpy->dheight = dv_dpy->sheight = dv_dpy->height;
462   dv_dpy->lxoff = dv_dpy->lyoff = 0;
463   dv_dpy-> flags = flags;
464 
465   if (flags & XV_FORMAT_MASK) {
466     dv_dpy->lwidth = dv_dpy->dwidth = 768;
467     dv_dpy->lheight = dv_dpy->dheight = 576;
468     dv_dpy->pic_format = DV_FORMAT_UNKNOWN;
469     if (flags & XV_FORMAT_WIDE) {
470       dv_dpy->lwidth = dv_dpy->dwidth = 1024;
471     }
472   }
473   if (size) {
474     dv_dpy->lwidth  = (int)(((double)dv_dpy->lwidth  * (double)size)/100.0);
475     dv_dpy->lheight = (int)(((double)dv_dpy->lheight * (double)size)/100.0);
476     dv_dpy->dwidth  = (int)(((double)dv_dpy->dwidth  * (double)size)/100.0);
477     dv_dpy->dheight = (int)(((double)dv_dpy->dheight * (double)size)/100.0);
478   }
479   if (flags & XV_FORMAT_MASK) {
480     hints.flags |= PAspect;
481     if (flags & XV_FORMAT_WIDE) {
482       hints.min_aspect.x = hints.max_aspect.x = 1024;
483     } else {
484       hints.min_aspect.x = hints.max_aspect.x = 768;
485     }
486     hints.min_aspect.y = hints.max_aspect.y = 576;
487   }
488 
489   if (!(flags & XV_NOSAWINDOW)) {
490     dv_dpy->win = XCreateSimpleWindow(dv_dpy->dpy,
491 				       dv_dpy->rwin,
492 				       0, 0,
493 				       dv_dpy->dwidth, dv_dpy->dheight,
494 				       0,
495 				       XWhitePixel(dv_dpy->dpy, scn_id),
496 				       XBlackPixel(dv_dpy->dpy, scn_id));
497   } else {
498   }
499   XSetWMProperties(dv_dpy->dpy, dv_dpy->win,
500 		    &x_wname, &x_iname,
501 		    NULL, 0,
502 		    &hints, &wmhints, NULL);
503 
504   XSelectInput(dv_dpy->dpy, dv_dpy->win, ExposureMask | StructureNotifyMask | KeyPressMask);
505   XMapRaised(dv_dpy->dpy, dv_dpy->win);
506   XNextEvent(dv_dpy->dpy, &dv_dpy->event);
507 
508   dv_dpy->gc = XCreateGC(dv_dpy->dpy, dv_dpy->win, 0, &values);
509 
510   /*
511    * Now we do shared memory allocation etc..
512    */
513   dv_dpy->xv_image = XvShmCreateImage(dv_dpy->dpy, dv_dpy->port,
514 					 dv_dpy->format, dv_dpy->pixels[0],
515 				      	 dv_dpy->width, dv_dpy->height,
516 					 &dv_dpy->shminfo);
517 
518   dv_dpy->shminfo.shmid = shmget(IPC_PRIVATE,
519 				     dv_dpy->len,
520 				     IPC_CREAT | 0777);
521 
522   dv_dpy->xv_image->data = dv_dpy->pixels[0] = dv_dpy->shminfo.shmaddr =
523     shmat(dv_dpy->shminfo.shmid, 0, 0);
524 
525   XShmAttach(dv_dpy->dpy, &dv_dpy->shminfo);
526   XSync(dv_dpy->dpy, False);
527 
528   return 1;
529 } /* dv_display_Xv_init */
530 #endif /* HAVE_LIBXV */
531 
532 
533 #if HAVE_SDL
534 
535 static void
dv_center_window(SDL_Surface * screen)536 dv_center_window(SDL_Surface *screen)
537 {
538     SDL_SysWMinfo info;
539 
540     SDL_VERSION(&info.version);
541     if ( SDL_GetWMInfo(&info) > 0 ) {
542         int x, y;
543         int w, h;
544         if ( info.subsystem == SDL_SYSWM_X11 ) {
545             info.info.x11.lock_func();
546             w = DisplayWidth(info.info.x11.display,
547                              DefaultScreen(info.info.x11.display));
548             h = DisplayHeight(info.info.x11.display,
549                              DefaultScreen(info.info.x11.display));
550             x = (w - screen->w)/2;
551             y = (h - screen->h)/2;
552             XMoveWindow(info.info.x11.display, info.info.x11.wmwindow, x, y);
553             info.info.x11.unlock_func();
554         } /* if */
555     } /* if  */
556 } /* dv_center_window */
557 
558 static int
dv_display_SDL_init(dv_display_t * dv_dpy,char * w_name,char * i_name)559 dv_display_SDL_init(dv_display_t *dv_dpy, char *w_name, char *i_name) {
560   const SDL_VideoInfo *video_info;
561   int video_bpp;
562 
563   if(SDL_Init(SDL_INIT_VIDEO) < 0) goto no_sdl;
564   /* Get the "native" video mode */
565   video_info = SDL_GetVideoInfo();
566   switch (video_info->vfmt->BitsPerPixel) {
567   case 16:
568   case 32:
569     video_bpp = video_info->vfmt->BitsPerPixel;
570     break;
571   default:
572     video_bpp = 16;
573     break;
574   } /* switch  */
575   dv_dpy->sdl_screen = SDL_SetVideoMode(dv_dpy->width,dv_dpy->height,
576 					video_bpp,SDL_HWSURFACE);
577   SDL_WM_SetCaption(w_name, i_name);
578   dv_dpy->overlay = SDL_CreateYUVOverlay(dv_dpy->width, dv_dpy->height, dv_dpy->format,
579 					 dv_dpy->sdl_screen);
580   if((!dv_dpy->overlay || (!dv_dpy->overlay->hw_overlay) ||  /* we only want HW overlays */
581       SDL_LockYUVOverlay(dv_dpy->overlay)<0)) {
582     goto no_overlay;
583   } /* if */
584   dv_center_window(dv_dpy->sdl_screen);
585   dv_dpy->rect.x = 0;
586   dv_dpy->rect.y = 0;
587   dv_dpy->rect.w = dv_dpy->overlay->w;
588   dv_dpy->rect.h = dv_dpy->overlay->h;
589   dv_dpy->pixels[0] = dv_dpy->overlay->pixels[0];
590   dv_dpy->pixels[1] = dv_dpy->overlay->pixels[1];
591   dv_dpy->pixels[2] = dv_dpy->overlay->pixels[2];
592   dv_dpy->pitches[0] = dv_dpy->overlay->pitches[0];
593   dv_dpy->pitches[1] = dv_dpy->overlay->pitches[1];
594   dv_dpy->pitches[2] = dv_dpy->overlay->pitches[2];
595   return(True);
596 
597  no_overlay:
598   if(dv_dpy->overlay)
599     SDL_FreeYUVOverlay(dv_dpy->overlay);
600   SDL_Quit();
601  no_sdl:
602   return(False);
603 
604 } /* dv_display_SDL_init */
605 
606 #else
607 
608 static int
dv_display_SDL_init(dv_display_t * dv_dpy,char * w_name,char * i_name)609 dv_display_SDL_init(dv_display_t *dv_dpy, char *w_name, char *i_name) {
610   tc_log_warn(__FILE__,"playdv was compiled without SDL support");
611   return(FALSE);
612 } /* dv_display_SDL_init */
613 
614 #endif /* HAVE_SDL */
615 
616 int
dv_display_init(dv_display_t * dv_dpy,int * argc,char *** argv,int width,int height,dv_sample_t sampling,char * w_name,char * i_name)617 dv_display_init(dv_display_t *dv_dpy, int *argc, char ***argv, int width, int height,
618 		dv_sample_t sampling, char *w_name, char *i_name) {
619 
620   dv_dpy->width = width;
621   dv_dpy->height = height;
622 
623   dv_dpy->dontdraw = 0;
624 
625   switch(sampling) {
626 
627   case e_dv_sample_420:
628     dv_dpy->format = DV_FOURCC_YV12;
629     dv_dpy->len = (dv_dpy->width * dv_dpy->height * 3) / 2;
630     break;
631 
632   default:
633     /* Not possible */
634     break;
635   } /* switch */
636 
637   switch(dv_dpy->arg_display) {
638   case 0:
639     /* Autoselect */
640 #if HAVE_LIBXV
641     /* Try to use Xv first, then SDL */
642     if(dv_display_Xv_init(dv_dpy, w_name, i_name,
643 			  dv_dpy->arg_aspect_val,
644 			  dv_dpy->arg_size_val)) {
645       goto Xv_ok;
646     } else
647 #endif /* HAVE_LIBXV */
648     if(dv_display_SDL_init(dv_dpy, w_name, i_name)) {
649       goto SDL_ok;
650     } else {
651       goto use_gtk;
652     } /* else */
653     break;
654   case 1:
655     /* Gtk */
656     goto use_gtk;
657     break;
658   case 2:
659 #if HAVE_LIBXV
660     /* Xv */
661     if(dv_display_Xv_init(dv_dpy, w_name, i_name,
662 			  dv_dpy->arg_aspect_val,
663 			  dv_dpy->arg_size_val)) {
664       goto Xv_ok;
665     } else {
666       tc_log_error(__FILE__, "Attempt to display via Xv failed");
667       goto fail;
668     }
669 #else /* HAVE_LIBXV */
670     tc_log_error(__FILE__, "Attempt to display via Xv failed");
671     goto fail;
672 #endif /* HAVE_LIBXV */
673     break;
674   case 3:
675     /* SDL */
676     if(dv_display_SDL_init(dv_dpy, w_name, i_name)) {
677       goto SDL_ok;
678     } else {
679       tc_log_error(__FILE__, "Attempt to display via SDL failed");
680       goto fail;
681     }
682     break;
683   default:
684     break;
685   } /* switch */
686 
687 #if HAVE_LIBXV
688  Xv_ok:
689   tc_log_info(__FILE__, " Using Xv for display");
690   dv_dpy->lib = e_dv_dpy_Xv;
691   goto yuv_ok;
692 #endif /* HAVE_LIBXV */
693 
694  SDL_ok:
695   tc_log_info(__FILE__, " Using SDL for display");
696   dv_dpy->lib = e_dv_dpy_SDL;
697   goto yuv_ok;
698 
699  yuv_ok:
700 
701   dv_dpy->color_space = e_dv_color_yuv;
702 
703   switch(dv_dpy->format) {
704   case DV_FOURCC_YUY2:
705     dv_dpy->pitches[0] = width * 2;
706     break;
707   case DV_FOURCC_YV12:
708     dv_dpy->pixels[1] = dv_dpy->pixels[0] + (width * height);
709     dv_dpy->pixels[2] = dv_dpy->pixels[1] + (width * height / 4);
710     dv_dpy->pitches[0] = width;
711     dv_dpy->pitches[1] = width / 2;
712     dv_dpy->pitches[2] = width / 2;
713     break;
714   } /* switch */
715 
716   goto ok;
717 
718  use_gtk:
719 
720   /* Try to use GDK since we couldn't get a HW YUV surface */
721   dv_dpy->color_space = e_dv_color_rgb;
722   dv_dpy->lib = e_dv_dpy_gtk;
723   dv_dpy->len = dv_dpy->width * dv_dpy->height * 3;
724   if(!dv_display_gdk_init(dv_dpy, argc, argv)) {
725     tc_log_error(__FILE__, "Attempt to use gtk for display failed");
726     goto fail;
727   } /* if  */
728   dv_dpy->pitches[0] = width * 3;
729   tc_log_info(__FILE__, " Using gtk for display");
730 
731  ok:
732   return(TRUE);
733 
734  fail:
735   tc_log_error(__FILE__, " Unable to establish a display method");
736   return(FALSE);
737 } /* dv_display_init */
738