changeset 12120:56e4423f16be

Quartz/MacOSX video output module by Nicolas Plourde
author alex
date Mon, 05 Apr 2004 21:20:19 +0000
parents a035d2616e0b
children 6d4212840048
files configure libvo/video_out.c libvo/vo_quartz.c libvo/vo_quartz.h
diffstat 4 files changed, 668 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/configure	Mon Apr 05 15:32:01 2004 +0000
+++ b/configure	Mon Apr 05 21:20:19 2004 +0000
@@ -2725,6 +2725,7 @@
 	_macosx=no
 	_def_macosx='#undef MACOSX'
 	_noaomodules="macosx $_noaomodules"
+	_novomodules="quartz $_novomodules"
     fi
 fi
 if test "$_macosx" = yes ; then
@@ -2744,10 +2745,13 @@
     _def_macosx='#define MACOSX 1'
     _aosrc="$_aosrc ao_macosx.c"
     _aomodules="macosx $_aomodules"
+    _vosrc="$_vosrc vo_quartz.c"
+    _vomodules="quartz $_vomodules"
   else
     _macosx=no
     _def_macosx='#undef MACOSX'
     _noaomodules="macosx $_noaomodules"
+    _novomodules="quartz $_novomodules"
   fi
 fi
 echores "$_macosx"
--- a/libvo/video_out.c	Mon Apr 05 15:32:01 2004 +0000
+++ b/libvo/video_out.c	Mon Apr 05 21:20:19 2004 +0000
@@ -118,6 +118,9 @@
 #ifdef HAVE_TGA
 extern vo_functions_t video_out_tga;
 #endif
+#ifdef MACOSX
+extern vo_functions_t video_out_quartz;
+#endif
 
 vo_functions_t* video_out_drivers[] =
 {
@@ -228,6 +231,9 @@
 #ifdef HAVE_TGA
         &video_out_tga,
 #endif
+#ifdef MACOSX
+	&video_out_quartz,
+#endif
         NULL
 };
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libvo/vo_quartz.c	Mon Apr 05 21:20:19 2004 +0000
@@ -0,0 +1,529 @@
+/* 
+ * vo_quartz.c
+ *
+ * Copyright (c) Nicolas Plourde - January 2004
+ *
+ * MPlayer Mac OSX Quartz video out module.
+ *
+ * TODO: -Fullscreen
+ *       -Better event handling
+ *
+ * Note on performance:
+ *  Right now i can play fullsize dvd video with -framedrop on my 
+ *  iBook G4 800mhz. YUV to RGB converstion will speed up thing alot.
+ *  Another thing is the slow fps when you maximize the window, I was
+ *  not expecting that. I will fix this a.s.a.p. Im new to Mac 
+ *  programming so help is welcome.
+ */
+
+//SYS
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <errno.h>
+
+//OSX
+#include <Carbon/Carbon.h>
+#include <QuickTime/QuickTime.h>
+
+//MPLAYER
+#include "config.h"
+#include "video_out.h"
+#include "video_out_internal.h"
+#include "aspect.h"
+
+#include "../input/input.h"
+#include "../input/mouse.h"
+
+#include "vo_quartz.h"
+
+static vo_info_t info = {
+  "MacOS X (Quartz)",
+  "quartz",
+  "Nicolas Plourde <nicolasplourde@hotmail.com>",
+  ""
+};
+
+LIBVO_EXTERN (quartz)
+static unsigned char *ImageData = NULL;
+
+static uint32_t image_width;
+static uint32_t image_height;
+static uint32_t image_depth;
+static uint32_t image_bytes;
+static uint32_t image_format;
+
+static int int_pause = 0;
+
+int screen_width, screen_height;
+
+WindowRef theWindow;
+CGContextRef context;
+CGRect bounds;
+CGRect winBounds;
+Rect contentRect;
+CGImageRef image;
+CGDataProviderRef dataProviderRef;
+Ptr oldscreenstate;
+RGBColor black = { 0, 0, 0 };
+float winAlpha = 1;
+
+#include "../osdep/keycodes.h"
+extern void mplayer_put_key (int code);
+
+//PROTOTYPE/////////////////////////////////////////////////////////////////
+void resize_window (uint32_t width, uint32_t height);
+static OSStatus MainWindowEventHandler (EventHandlerCallRef nextHandler,
+					EventRef event, void *userData);
+static OSStatus MainKeyEventHandler (EventHandlerCallRef nextHandler,
+				     EventRef event, void *userData);
+
+
+//default window event handler
+static OSStatus
+MainWindowEventHandler (EventHandlerCallRef nextHandler, EventRef event,
+			void *userData)
+{
+  OSStatus err = noErr;
+  WindowRef window;
+  Rect rectPort = { 0, 0, 0, 0 };
+  OSStatus result = eventNotHandledErr;
+  UInt32 class = GetEventClass (event);
+  UInt32 kind = GetEventKind (event);
+
+  GetEventParameter (event, kEventParamDirectObject, typeWindowRef, NULL,
+		     sizeof (WindowRef), NULL, &window);
+  if (window)
+    {
+      GetWindowPortBounds (window, &rectPort);
+    }
+
+  switch (kind)
+    {
+    case kEventWindowActivated:
+
+    case kEventWindowDrawContent:
+      break;
+
+    case kEventWindowClosed:
+      HideWindow (window);
+      mplayer_put_key (KEY_ESC);
+      break;
+
+    case kEventWindowShown:
+      InvalWindowRect (window, &rectPort);
+      break;
+
+    case kEventWindowBoundsChanged:
+      resize_window (rectPort.right, rectPort.bottom);
+      break;
+
+    case kEventWindowZoomed:
+      resize_window (rectPort.right, rectPort.bottom);
+      break;
+
+    default:
+      err = eventNotHandledErr;
+      break;
+    }
+
+  return err;
+}
+
+//keyboard event handler
+static OSStatus
+MainKeyEventHandler (EventHandlerCallRef nextHandler, EventRef event,
+		     void *userData)
+{
+  OSStatus err = noErr;
+  UInt32 macKeyCode;
+
+  GetEventParameter (event, kEventParamKeyCode, typeUInt32, NULL,
+		     sizeof (macKeyCode), NULL, &macKeyCode);
+
+  switch (GetEventKind (event))
+    {
+    case kEventRawKeyDown:
+      {
+	switch (macKeyCode)
+	  {
+	  case QZ_RETURN:
+	    mplayer_put_key (KEY_ENTER);
+	    break;
+	  case QZ_ESCAPE:
+	    EndFullScreen (oldscreenstate, 0);
+	    QuitApplicationEventLoop ();
+	    mplayer_put_key (KEY_ESC);
+	    break;
+	  case QZ_q:
+	    mplayer_put_key ('q');
+	    break;
+	  case QZ_F1:
+	    mplayer_put_key (KEY_F + 1);
+	    break;
+	  case QZ_F2:
+	    mplayer_put_key (KEY_F + 2);
+	    break;
+	  case QZ_F3:
+	    mplayer_put_key (KEY_F + 3);
+	    break;
+	  case QZ_F4:
+	    mplayer_put_key (KEY_F + 4);
+	    break;
+	  case QZ_F5:
+	    mplayer_put_key (KEY_F + 5);
+	    break;
+	  case QZ_F6:
+	    mplayer_put_key (KEY_F + 6);
+	    break;
+	  case QZ_F7:
+	    mplayer_put_key (KEY_F + 7);
+	    break;
+	  case QZ_F8:
+	    mplayer_put_key (KEY_F + 8);
+	    break;
+	  case QZ_F9:
+	    mplayer_put_key (KEY_F + 9);
+	    break;
+	  case QZ_F10:
+	    mplayer_put_key (KEY_F + 10);
+	    break;
+	  case QZ_F11:
+	    mplayer_put_key (KEY_F + 11);
+	    break;
+	  case QZ_F12:
+	    mplayer_put_key (KEY_F + 12);
+	    break;
+	  case QZ_o:
+	    mplayer_put_key ('o');
+	    break;
+	  case QZ_SPACE:
+	    mplayer_put_key (' ');
+	    break;
+	  case QZ_p:
+	    mplayer_put_key ('p');
+	    break;
+	    //case QZ_7: mplayer_put_key(shift_key?'/':'7');
+	    //case QZ_PLUS: mplayer_put_key(shift_key?'*':'+');
+	  case QZ_KP_PLUS:
+	    mplayer_put_key ('+');
+	    break;
+	  case QZ_MINUS:
+	  case QZ_KP_MINUS:
+	    mplayer_put_key ('-');
+	    break;
+	  case QZ_TAB:
+	    mplayer_put_key ('\t');
+	    break;
+	  case QZ_PAGEUP:
+	    mplayer_put_key (KEY_PAGE_UP);
+	    break;
+	  case QZ_PAGEDOWN:
+	    mplayer_put_key (KEY_PAGE_DOWN);
+	    break;
+	  case QZ_UP:
+	    mplayer_put_key (KEY_UP);
+	    break;
+	  case QZ_DOWN:
+	    mplayer_put_key (KEY_DOWN);
+	    break;
+	  case QZ_LEFT:
+	    mplayer_put_key (KEY_LEFT);
+	    break;
+	  case QZ_RIGHT:
+	    mplayer_put_key (KEY_RIGHT);
+	    break;
+	    //case QZ_LESS: mplayer_put_key(shift_key?'>':'<'); break;
+	    //case QZ_GREATER: mplayer_put_key('>'); break;
+	    //case QZ_ASTERISK:
+	  case QZ_KP_MULTIPLY:
+	    mplayer_put_key ('*');
+	    break;
+	  case QZ_SLASH:
+	  case QZ_KP_DIVIDE:
+	    mplayer_put_key ('/');
+	    break;
+	  case QZ_KP0:
+	    mplayer_put_key (KEY_KP0);
+	    break;
+	  case QZ_KP1:
+	    mplayer_put_key (KEY_KP1);
+	    break;
+	  case QZ_KP2:
+	    mplayer_put_key (KEY_KP2);
+	    break;
+	  case QZ_KP3:
+	    mplayer_put_key (KEY_KP3);
+	    break;
+	  case QZ_KP4:
+	    mplayer_put_key (KEY_KP4);
+	    break;
+	  case QZ_KP5:
+	    mplayer_put_key (KEY_KP5);
+	    break;
+	  case QZ_KP6:
+	    mplayer_put_key (KEY_KP6);
+	    break;
+	  case QZ_KP7:
+	    mplayer_put_key (KEY_KP7);
+	    break;
+	  case QZ_KP8:
+	    mplayer_put_key (KEY_KP8);
+	    break;
+	  case QZ_KP9:
+	    mplayer_put_key (KEY_KP9);
+	    break;
+	  case QZ_KP_PERIOD:
+	    mplayer_put_key (KEY_KPDEC);
+	    break;
+	  case QZ_KP_ENTER:
+	    mplayer_put_key (KEY_KPENTER);
+	    break;
+	  case QZ_LEFTBRACKET:
+	    SetWindowAlpha (theWindow, winAlpha -= 0.05);
+	    break;
+	  case QZ_RIGHTBRACKET:
+	    SetWindowAlpha (theWindow, winAlpha += 0.05);
+	    break;
+	  case QZ_f:
+	    break;
+	  default:
+	    break;
+	  }
+      }
+      break;
+    default:
+      err = eventNotHandledErr;
+      break;
+    }
+
+  return err;
+}
+
+static uint32_t
+config (uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height,
+	uint32_t flags, char *title, uint32_t format)
+{
+  WindowAttributes windowAttrs;
+  CFStringRef titleKey;
+  CFStringRef windowTitle;
+  OSStatus result;
+  GDHandle deviceHdl;
+  Rect deviceRect;
+
+  //Get Main device info///////////////////////////////////////////////////
+  deviceHdl = GetMainDevice ();
+  deviceRect = (*deviceHdl)->gdRect;
+
+  screen_width = deviceRect.right;
+  screen_height = deviceRect.bottom;
+
+  //misc mplayer setup/////////////////////////////////////////////////////
+  image_width = width;
+  image_height = height;
+  image_depth = IMGFMT_RGB_DEPTH (format);
+  image_bytes = (IMGFMT_RGB_DEPTH (format) + 7) / 8;
+
+  aspect_save_orig (width, height);
+  aspect_save_prescale (d_width, d_height);
+  aspect_save_screenres (screen_width, screen_height);
+
+  aspect (&d_width, &d_height, A_NOZOOM);
+
+  if (ImageData)
+    free (ImageData);
+  ImageData = malloc (image_width * image_height * image_bytes);
+
+  //Create player window//////////////////////////////////////////////////
+  windowAttrs = kWindowStandardDocumentAttributes
+    | kWindowMetalAttribute
+    | kWindowStandardHandlerAttribute
+    | kWindowInWindowMenuAttribute
+    | kWindowLiveResizeAttribute | kWindowCompositingAttribute;
+
+  SetRect (&contentRect, 0, 0, d_width, d_height);
+  CreateNewWindow (kDocumentWindowClass, windowAttrs, &contentRect,
+		   &theWindow);
+
+  titleKey = CFSTR ("MPlayer");
+  windowTitle = CFCopyLocalizedString (titleKey, NULL);
+  result = SetWindowTitleWithCFString (theWindow, windowTitle);
+  CFRelease (titleKey);
+  CFRelease (windowTitle);
+
+  const EventTypeSpec winEvents[] = {
+    {kEventClassWindow, kEventWindowActivated},
+    {kEventClassWindow, kEventWindowDrawContent},
+    {kEventClassWindow, kEventWindowClosed},
+    {kEventClassWindow, kEventWindowShown},
+    {kEventClassWindow, kEventWindowBoundsChanged},
+    {kEventClassWindow, kEventWindowZoomed}
+  };
+
+  const EventTypeSpec keyEvents[] =
+    { {kEventClassKeyboard, kEventRawKeyDown} };
+  InstallWindowEventHandler (theWindow,
+			     NewEventHandlerUPP (MainWindowEventHandler),
+			     GetEventTypeCount (winEvents), winEvents,
+			     theWindow, NULL);
+  InstallWindowEventHandler (theWindow,
+			     NewEventHandlerUPP (MainKeyEventHandler),
+			     GetEventTypeCount (keyEvents), keyEvents,
+			     theWindow, NULL);
+
+  RepositionWindow (theWindow, NULL, kWindowCascadeOnMainScreen);
+  ShowWindow (theWindow);
+
+  //Setup Quartz context
+  CreateCGContextForPort (GetWindowPort (theWindow), &context);
+
+  //set size and aspect for current window
+  resize_window (d_width, d_height);
+
+  return 0;
+}
+
+//resize drawing context to fit window
+void
+resize_window (uint32_t width, uint32_t height)
+{
+  //this is a "wow it work". Need some improvement.
+  uint32_t d_width;
+  uint32_t d_height;
+  uint32_t size;
+  Rect tmpRect;
+
+  float aspectX;
+  float aspectY;
+
+  aspect (&d_width, &d_height, A_NOZOOM);
+
+  aspectX = (float) ((float) d_width * (width / (float) d_width));
+  aspectY = (float) ((float) d_height * (width / (float) d_width));
+
+  if (aspectY > height)
+    {
+      aspectX = (float) ((float) d_width * (height / (float) d_height));
+      aspectY = (float) ((float) d_height * (height / (float) d_height));
+
+      bounds = CGRectMake ((width - aspectX) / 2, 0, aspectX, aspectY);
+    }
+  else
+    {
+      bounds = CGRectMake (0, (height - aspectY) / 2, aspectX, aspectY);
+    }
+
+  //create a graphic context for the window
+  GetWindowPortBounds (theWindow, &tmpRect);
+  SetPortBounds (GetWindowPort (theWindow), &tmpRect);
+  CreateCGContextForPort (GetWindowPort (theWindow), &context);
+
+  //fill background with black
+  winBounds =
+    CGRectMake (tmpRect.top, tmpRect.left, tmpRect.right, tmpRect.bottom);
+  CGContextSetRGBFillColor (context, 0.0, 0.0, 0.0, 1.0);
+  CGContextFillRect (context, winBounds);
+}
+
+static void
+check_events (void)
+{
+  EventRef theEvent;
+  EventTargetRef theTarget;
+
+  theTarget = GetEventDispatcherTarget ();
+
+  ReceiveNextEvent (0, NULL, kEventDurationNoWait, true, &theEvent);
+  SendEventToEventTarget (theEvent, theTarget);
+  ReleaseEvent (theEvent);
+
+  //if(VO_EVENT_RESIZE) resize_window(vo_dwidth,vo_dheight);
+  if (VO_EVENT_EXPOSE && int_pause)
+    flip_page ();
+}
+
+static void
+draw_osd (void)
+{
+}
+
+static void
+flip_page (void)
+{
+  CGContextFlush (context);
+}
+
+static uint32_t
+draw_slice (uint8_t * src[], int stride[], int w, int h, int x, int y)
+{
+  return -1;
+}
+
+static uint32_t
+draw_frame (uint8_t * src[])
+{
+  //this is very slow. I have to find another way.
+  CGImageAlphaInfo alphaInfo;
+
+  dataProviderRef =
+    CGDataProviderCreateWithData (0, src[0],
+				  image_width * image_height * image_bytes,
+				  0);
+
+  if (image_format == IMGFMT_RGB24)
+    alphaInfo = kCGImageAlphaNone;
+  else if (image_format == IMGFMT_RGB32)
+    alphaInfo = kCGImageAlphaNoneSkipFirst;
+
+  image = CGImageCreate (image_width,
+			 image_height,
+			 8,
+			 image_depth,
+			 ((image_width * image_depth) + 7) / 8,
+			 CGColorSpaceCreateDeviceRGB (),
+			 alphaInfo,
+			 dataProviderRef, 0, 0, kCGRenderingIntentDefault);
+
+  CGContextDrawImage (context, bounds, image);
+
+  return 0;
+}
+
+static uint32_t
+query_format (uint32_t format)
+{
+  image_format = format;
+
+  //Curently supporting only rgb format.
+  if ((format == IMGFMT_RGB24) || (format == IMGFMT_RGB32))
+    return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW;
+  return 0;
+}
+
+
+static void
+uninit (void)
+{
+}
+
+static uint32_t
+preinit (const char *arg)
+{
+  return 0;
+}
+
+static uint32_t
+control (uint32_t request, void *data, ...)
+{
+  switch (request)
+    {
+    case VOCTRL_PAUSE:
+      return (int_pause = 1);
+    case VOCTRL_RESUME:
+      return (int_pause = 0);
+    case VOCTRL_QUERY_FORMAT:
+      return query_format (*((uint32_t *) data));
+    }
+  return VO_NOTIMPL;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libvo/vo_quartz.h	Mon Apr 05 21:20:19 2004 +0000
@@ -0,0 +1,129 @@
+/* 
+ * vo_quartz.h
+ * Mac keyboard def taken from SDL
+ */
+
+#ifndef VO_QUARTZ_H
+#define VO_QUARTZ_H 1
+
+/* These are the Macintosh key scancode constants -- from Inside Macintosh */
+#define QZ_ESCAPE		0x35
+#define QZ_F1			0x7A
+#define QZ_F2			0x78
+#define QZ_F3			0x63
+#define QZ_F4			0x76
+#define QZ_F5			0x60
+#define QZ_F6			0x61
+#define QZ_F7			0x62
+#define QZ_F8			0x64
+#define QZ_F9			0x65
+#define QZ_F10			0x6D
+#define QZ_F11			0x67
+#define QZ_F12			0x6F
+#define QZ_PRINT		0x69
+#define QZ_SCROLLOCK    	0x6B
+#define QZ_PAUSE		0x71
+#define QZ_POWER		0x7F
+#define QZ_BACKQUOTE		0x32
+#define QZ_1			0x12
+#define QZ_2			0x13
+#define QZ_3			0x14
+#define QZ_4			0x15
+#define QZ_5			0x17
+#define QZ_6			0x16
+#define QZ_7			0x1A
+#define QZ_8			0x1C
+#define QZ_9			0x19
+#define QZ_0			0x1D
+#define QZ_MINUS		0x1B
+#define QZ_EQUALS		0x18
+#define QZ_BACKSPACE		0x33
+#define QZ_INSERT		0x72
+#define QZ_HOME			0x73
+#define QZ_PAGEUP		0x74
+#define QZ_NUMLOCK		0x47
+#define QZ_KP_EQUALS		0x51
+#define QZ_KP_DIVIDE		0x4B
+#define QZ_KP_MULTIPLY		0x43
+#define QZ_TAB			0x30
+#define QZ_q			0x0C
+#define QZ_w			0x0D
+#define QZ_e			0x0E
+#define QZ_r			0x0F
+#define QZ_t			0x11
+#define QZ_y			0x10
+#define QZ_u			0x20
+#define QZ_i			0x22
+#define QZ_o			0x1F
+#define QZ_p			0x23
+#define QZ_LEFTBRACKET		0x21
+#define QZ_RIGHTBRACKET		0x1E
+#define QZ_BACKSLASH		0x2A
+#define QZ_DELETE		0x75
+#define QZ_END			0x77
+#define QZ_PAGEDOWN		0x79
+#define QZ_KP7			0x59
+#define QZ_KP8			0x5B
+#define QZ_KP9			0x5C
+#define QZ_KP_MINUS		0x4E
+#define QZ_CAPSLOCK		0x39
+#define QZ_a			0x00
+#define QZ_s			0x01
+#define QZ_d			0x02
+#define QZ_f			0x03
+#define QZ_g			0x05
+#define QZ_h			0x04
+#define QZ_j			0x26
+#define QZ_k			0x28
+#define QZ_l			0x25
+#define QZ_SEMICOLON		0x29
+#define QZ_QUOTE		0x27
+#define QZ_RETURN		0x24
+#define QZ_KP4			0x56
+#define QZ_KP5			0x57
+#define QZ_KP6			0x58
+#define QZ_KP_PLUS		0x45
+#define QZ_LSHIFT		0x38
+#define QZ_z			0x06
+#define QZ_x			0x07
+#define QZ_c			0x08
+#define QZ_v			0x09
+#define QZ_b			0x0B
+#define QZ_n			0x2D
+#define QZ_m			0x2E
+#define QZ_COMMA		0x2B
+#define QZ_PERIOD		0x2F
+#define QZ_SLASH		0x2C
+/* These are the same as the left versions - use left by default */
+#if 0				
+#define QZ_RSHIFT		0x38
+#endif
+#define QZ_UP			0x7E
+#define QZ_KP1			0x53
+#define QZ_KP2			0x54
+#define QZ_KP3			0x55
+#define QZ_KP_ENTER		0x4C
+#define QZ_LCTRL		0x3B
+#define QZ_LALT			0x3A
+#define QZ_LMETA		0x37
+#define QZ_SPACE		0x31
+/* These are the same as the left versions - use left by default */
+#if 0				
+#define QZ_RMETA		0x37
+#define QZ_RALT			0x3A
+#define QZ_RCTRL		0x3B
+#endif
+#define QZ_LEFT			0x7B
+#define QZ_DOWN			0x7D
+#define QZ_RIGHT		0x7C
+#define QZ_KP0			0x52
+#define QZ_KP_PERIOD		0x41
+
+/* Wierd, these keys are on my iBook under MacOS X */
+#define QZ_IBOOK_ENTER		0x34
+#define QZ_IBOOK_LEFT		0x3B
+#define QZ_IBOOK_RIGHT		0x3C
+#define QZ_IBOOK_DOWN		0x3D
+#define QZ_IBOOK_UP		0x3E
+
+#endif /* VO_QUARTZ_H */