[MPlayer-dev-eng] [PATCH] Real Audio/Video support for Mac OS X

Donnie Smith xc0bead2d8130df59 at f4n.org
Fri Jun 18 17:14:22 CEST 2004


On Fri, Jun 18, 2004 at 00:38:23 +0200, Diego Biurrun wrote:
> Please update/recreate your patches, I guess they have a fair chance
> of being accepted.
Patch attached, far less work than I expected, the old patch basically
applied straight off. Therefore, I didn't check the code that
carefully, since I did that last year. I'm sure there's room for
improvements though. 

I'd be surprised if I didn't make any mistakes with the DOCS-patch,
someone familiar with the XML format used (which is new to me): please
check it carefully and suggest possible fixes.

I admit that the pncrt.Shlb-copying (see the DOCS part of the patch)
is somewhat of a kludge, but I couldn't find any better way to fix it
last year. It should be possible to modify the shlb-paths, but I never
succeeded in doing so. If someone is interested, please try to fix it.
Another thing that's not too pretty is the sharing of
load_one_sym_mac() between ad_realaud.c and vd_realvid.c, but as far
as I know, there's no suitable place to put general platform dependant
functions.

When playing Real-media with -ao macosx (which is the default on Mac
OS X) one often gets buffer underruns (causing "chopped" audio):
-verbose 1, gives lots and lots of "AO: [macosx] Buffer underrun".

For me, it only occurs when playing tracks with both audio and video,
suppressing the video track makes the audio play just fine. I think
there might be some latency in the Real video codecs which breaks the
macosx-ao. If someone is interested in investigating, it occurs for me
with samples/real/Ah_My_Goddess_01.rm (but not manonfires.rm, for
example), and more so when the CPU usage is high and the frames of the
movies change fast. (For reference, it should be: koh-i-nih, na na na,
ih neh!)

Note that it does NOT happen with -ao sdl, so I'm blaming it solely on
the macosx ao.

Also, note that RealOne for Mac OS X doesn't ship with all codecs.
Instead, the player downloads them when needed (great "honest" way of
tracking what "uncommon" codecs users are intrested in, I guess). They
are permanently stored though, so you can use them with mplayer once
you have them. Perhaps a package should be created and put on
http://www.mplayerhq.hu/homepage/dload.html ?

Tell me what you think.

Donnie Smith
-------------- next part --------------
--- MPlayer-20040618.orig/libmpcodecs/vd_realvid.c	Fri Apr 30 12:26:26 2004
+++ MPlayer-20040618/libmpcodecs/vd_realvid.c	Fri Jun 18 14:25:35 2004
@@ -14,10 +14,14 @@
 #include "vd_internal.h"
 #include "wine/windef.h"
 
+#ifdef USE_MACSHLB
+#include <CoreServices/CoreServices.h>
+#endif
+
 static vd_info_t info = {
 	"RealVideo decoder",
 	"realvid",
-	"Florian Schneider & A'rpi", // win32 dlls support by alex
+	"Florian Schneider & A'rpi", // win32 dlls support by alex, mac os x shlb support by Donnie Smith
 	"using original closed source codecs for Linux",
 	"binary real video codecs"
 };
@@ -177,6 +181,67 @@
 }
 #endif
 
+#ifdef USE_MACSHLB
+void *load_one_sym_mac(char *symbolName, CFragConnectionID *connID);
+static int load_syms_mac(char *path) {
+    void *handle;
+
+    Ptr mainAddr;
+    OSStatus status;
+    FSRef fsref;
+    FSSpec fsspec;
+    OSErr err;
+    Str255 errMessage;
+    CFragConnectionID *connID;
+
+    mp_msg(MSGT_DECVIDEO,MSGL_INFO, "opening mac shlb '%s'\n", path);
+
+    if ( (connID = (CFragConnectionID *)NewPtr( sizeof( CFragConnectionID ))) == nil ) {
+        mp_msg(MSGT_DECVIDEO,MSGL_WARN,"NewPtr() failed.\n" );
+        return 0;
+    }
+
+    rv_handle = connID;
+
+    if ( (status = FSPathMakeRef( path, &fsref, NULL )) != noErr ) {
+        mp_msg(MSGT_DECVIDEO,MSGL_WARN,"FSPathMakeRef() failed with error %d.\n", status );
+        return 0;
+    }
+
+    if ( (status = FSGetCatalogInfo( &fsref, kFSCatInfoNone, NULL, NULL, &fsspec, NULL )) != noErr ) {
+        mp_msg(MSGT_DECVIDEO,MSGL_WARN,"FSGetCatalogInfo() failed with error %d.\n", status );
+        return 0;
+    }
+
+    if ( (err = GetDiskFragment( &fsspec, 0, kCFragGoesToEOF, NULL, kPrivateCFragCopy, connID, &mainAddr, errMessage )) != noErr ) {
+        p2cstrcpy( errMessage, errMessage );
+        mp_msg(MSGT_DECVIDEO,MSGL_WARN,"GetDiskFragment() failed with error %d: %s\n", err, errMessage );
+        return 0;
+    }
+
+    rvyuv_custom_message = load_one_sym_mac("\x19RV20toYUV420CustomMessage", connID);
+    rvyuv_free = load_one_sym_mac("\x10RV20toYUV420Free", connID);
+    rvyuv_hive_message = load_one_sym_mac("\x17RV20toYUV420HiveMessage", connID);
+    rvyuv_init = load_one_sym_mac("\x10RV20toYUV420Init", connID);
+    rvyuv_transform = load_one_sym_mac("\x15RV20toYUV420Transform", connID);
+
+    if(rvyuv_custom_message &&
+       rvyuv_free &&
+       rvyuv_hive_message &&
+       rvyuv_init &&
+       rvyuv_transform)
+    {
+    rv_handle = connID;
+    return 1;
+    }
+
+    mp_msg(MSGT_DECVIDEO,MSGL_WARN,"Error resolving symbols! (version incompatibility?)\n");
+    (void)CloseConnection(connID);
+    return 0; // error
+}
+#endif
+
+
 /* we need exact positions */
 struct rv_init_t {
 	short unk1;
@@ -214,6 +279,9 @@
 #ifdef USE_WIN32DLL
 	    if (!load_syms_windows(sh->codec->dll))
 #endif
+#ifdef USE_MACSHLB
+	    if (!load_syms_mac(path))
+#endif
 	{
 		mp_msg(MSGT_DECVIDEO,MSGL_ERR,MSGTR_MissingDLLcodec,sh->codec->dll);
 		mp_msg(MSGT_DECVIDEO,MSGL_HINT,"Read the RealVideo section of the DOCS!\n");
@@ -270,6 +338,17 @@
 #endif
 #ifdef HAVE_LIBDL
 	if(rv_handle) dlclose(rv_handle);
+#endif
+#ifdef USE_MACSHLB
+	if (rv_handle){
+	    (void)CloseConnection(rv_handle);
+	    DisposePtr((Ptr)rv_handle);
+	}
+	if (rvyuv_custom_message) DisposePtr((Ptr)rvyuv_custom_message);
+	if (rvyuv_free) DisposePtr((Ptr)rvyuv_free);
+	if (rvyuv_hive_message) DisposePtr((Ptr)rvyuv_hive_message);
+	if (rvyuv_init) DisposePtr((Ptr)rvyuv_init);
+	if (rvyuv_transform) DisposePtr((Ptr)rvyuv_transform);
 #endif
 	rv_handle=NULL;
 }
--- MPlayer-20040618.orig/libmpcodecs/ad_realaud.c	Fri Apr 30 12:26:26 2004
+++ MPlayer-20040618/libmpcodecs/ad_realaud.c	Fri Jun 18 14:25:10 2004
@@ -16,10 +16,14 @@
 #include "ad_internal.h"
 #include "wine/windef.h"
 
+#ifdef USE_MACSHLB
+#include <CoreServices/CoreServices.h>
+#endif
+
 static ad_info_t info =  {
 	"RealAudio decoder",
 	"realaud",
-	"A'rpi", // win32 dlls support by alex
+	"A'rpi", // win32 dlls support by alex, mac os x shlb support by Donnie Smith
 	"Florian Schneider",
 	"binary real audio codecs"
 };
@@ -206,6 +210,104 @@
 }
 #endif
 
+
+#ifdef USE_MACSHLB
+/*
+ Helper function to create a function pointer (from a null terminated (!)
+ pascal string) like GetProcAddress(). Some assembler is required due
+ to different calling conventions, for further details, see 
+ http://developer.apple.com/ samplecode/CFM_MachO_CFM/listing1.html .
+
+ Caller is expected to DisposePtr(mfp).
+ N.B.: Code is used by vd_realaud.c as well.
+*/
+void *load_one_sym_mac(char *symbolName, CFragConnectionID *connID) {
+    OSErr err;
+    Ptr symbolAddr;
+    CFragSymbolClass symbolClass;
+    UInt32  *mfp;
+
+    if ( (err = FindSymbol( *connID, symbolName, 
+                            &symbolAddr, &symbolClass )) != noErr ) {
+        mp_msg(MSGT_DECVIDEO,MSGL_V,"FindSymbol( \"%s\" ) failed with error code %d.\n", symbolName + 1, err );
+        return NULL;
+    }
+
+    if ( (mfp = (UInt32 *)NewPtr( 6 * sizeof(UInt32) )) == nil )
+        return NULL;
+
+    mfp[0] = 0x3D800000 | ((UInt32)symbolAddr >> 16);
+    mfp[1] = 0x618C0000 | ((UInt32)symbolAddr & 0xFFFF);
+    mfp[2] = 0x800C0000;
+    mfp[3] = 0x804C0004;
+    mfp[4] = 0x7C0903A6;
+    mfp[5] = 0x4E800420;
+    MakeDataExecutable( mfp, 6 * sizeof(UInt32) );
+
+    return( mfp );
+}
+
+static int load_syms_mac(char *path)
+{
+    Ptr mainAddr;
+    OSStatus status;
+    FSRef fsref;
+    FSSpec fsspec;
+    OSErr err;
+    Str255 errMessage;
+    CFragConnectionID *connID;
+
+    mp_msg(MSGT_DECVIDEO, MSGL_INFO, "opening mac shlb '%s'\n", path);
+
+    if ( (connID = (CFragConnectionID *)NewPtr( sizeof( CFragConnectionID ))) == nil ) {
+        mp_msg(MSGT_DECVIDEO,MSGL_WARN,"NewPtr() failed.\n" );
+        return 0;
+    }
+
+    if ( (status = FSPathMakeRef( path, &fsref, NULL )) != noErr ) {
+        mp_msg(MSGT_DECVIDEO,MSGL_WARN,"FSPathMakeRef() failed with error %d.\n", status );
+        return 0;
+    }
+
+    if ( (status = FSGetCatalogInfo( &fsref, kFSCatInfoNone, NULL, NULL, &fsspec, NULL )) != noErr ) {
+        mp_msg(MSGT_DECVIDEO,MSGL_WARN,"FSGetCatalogInfo() failed with error %d.\n", status );
+        return 0;
+    }
+
+    if ( (err = GetDiskFragment( &fsspec, 0, kCFragGoesToEOF, NULL, kPrivateCFragCopy, connID, &mainAddr, errMessage )) != noErr ) {
+
+        p2cstrcpy( errMessage, errMessage );
+        mp_msg(MSGT_DECVIDEO,MSGL_WARN,"GetDiskFragment() failed with error %d: %s\n", err, errMessage );
+        return 0;
+    }
+
+    raCloseCodec = load_one_sym_mac( "\xcRACloseCodec", connID);
+    raDecode = load_one_sym_mac("\x8RADecode", connID);
+    raFlush = load_one_sym_mac("\x7RAFlush", connID);
+    raFreeDecoder = load_one_sym_mac("\xdRAFreeDecoder", connID);
+    raGetFlavorProperty = load_one_sym_mac("\x13RAGetFlavorProperty", connID);
+    raOpenCodec = load_one_sym_mac("\xbRAOpenCodec", connID);
+    raOpenCodec2 = load_one_sym_mac("\xcRAOpenCodec2", connID);
+    raInitDecoder = load_one_sym_mac("\xdRAInitDecoder", connID);
+    raSetFlavor = load_one_sym_mac("\xbRASetFlavor", connID);
+    raSetDLLAccessPath = load_one_sym_mac("\x10SetDLLAccessPath", connID);
+    raSetPwd = load_one_sym_mac("\x8RASetPwd", connID); // optional, used by SIPR
+
+    if (raCloseCodec && raDecode && /*raFlush && */raFreeDecoder &&
+    raGetFlavorProperty && (raOpenCodec || raOpenCodec2) && raSetFlavor &&
+    /*raSetDLLAccessPath &&*/ raInitDecoder)
+    {
+    rv_handle = connID;
+    return 1;
+    }
+
+    mp_msg(MSGT_DECAUDIO,MSGL_WARN,"Cannot resolve symbols - incompatible shlb: %s\n",path);
+    (void)CloseConnection(connID);
+    return 0;
+}
+
+#endif
+
 static int preinit(sh_audio_t *sh){
   // let's check if the driver is available, return 0 if not.
   // (you should do that if you use external lib(s) which is optional)
@@ -226,6 +328,9 @@
 #ifdef USE_WIN32DLL
 	if (!load_syms_windows(sh->codec->dll))
 #endif
+#ifdef USE_MACSHLB
+	if (!load_syms_mac(path))
+#endif
     {
 	mp_msg(MSGT_DECVIDEO, MSGL_ERR, MSGTR_MissingDLLcodec, sh->codec->dll);
 	mp_msg(MSGT_DECVIDEO, MSGL_HINT, "Read the RealAudio section of the DOCS!\n");
@@ -293,7 +398,7 @@
 	((short*)(sh->wf+1))[4], // codec data length
 	((char*)(sh->wf+1))+10 // extras
     };
-#ifdef USE_WIN32DLL
+#if defined(USE_WIN32DLL) || defined(USE_MACSHLB)
     wra_init_t winit_data={
 	sh->wf->nSamplesPerSec,
 	sh->wf->wBitsPerSample,
@@ -304,11 +409,17 @@
 	((short*)(sh->wf+1))[4], // codec data length
 	((char*)(sh->wf+1))+10 // extras
     };
+#endif
+#ifdef USE_MACSHLB
+	result=raInitDecoder(sh->context,&winit_data);
+#else
+#ifdef USE_WIN32DLL
     if (dll_type == 1)
 	result=wraInitDecoder(sh->context,&winit_data);
     else
 #endif
     result=raInitDecoder(sh->context,&init_data);
+#endif
     if(result){
       mp_msg(MSGT_DECAUDIO,MSGL_WARN,"Decoder init failed, error code: 0x%X\n",result);
       return 0;
@@ -394,6 +505,21 @@
 
     if (raFreeDecoder) raFreeDecoder(sh->context);
     if (raCloseCodec) raCloseCodec(sh->context);
+
+#ifdef USE_MACSHLB
+    if (rv_handle){
+      (void)CloseConnection(rv_handle);
+      DisposePtr((Ptr)rv_handle);
+    }
+    if (raCloseCodec) DisposePtr((Ptr)raCloseCodec);
+    if (raDecode) DisposePtr((Ptr)raDecode);
+    if (raFlush) DisposePtr((Ptr)raFlush);
+    if (raFreeDecoder) DisposePtr((Ptr)raFreeDecoder);
+    if (raGetFlavorProperty) DisposePtr((Ptr)raGetFlavorProperty);
+    if (raOpenCodec) DisposePtr((Ptr)raOpenCodec);
+    if (raOpenCodec2) DisposePtr((Ptr)raOpenCodec2);
+    if (raInitDecoder) DisposePtr((Ptr)raInitDecoder);
+#endif
 
 #ifdef USE_WIN32DLL
     if (dll_type == 1)
--- MPlayer-20040618.orig/DOCS/xml/en/codecs.xml	Wed May 12 00:50:05 2004
+++ MPlayer-20040618/DOCS/xml/en/codecs.xml	Fri Jun 18 13:56:17 2004
@@ -428,7 +428,15 @@
 <note><para>
 <application>RealPlayer</application> libraries currently
 <emphasis role="bold">only work with Linux, FreeBSD, NetBSD and Cygwin on the x86,
-Alpha and PowerPC (Linux/Alpha and Linux/PowerPC have been tested) platforms</emphasis>.
+Alpha and PowerPC (Linux/Alpha and Linux/PowerPC have been tested) platforms and with Mac OS X</emphasis>.
+</para>
+<para>
+On Mac OS X you must make sure <command>pncrt.Shlb</command> (including it's resource fork!) is in the same directory
+as the Real codecs. Copy them using, for example
+<command>ditto -rsrcFork "RealOne Player.app/Contents/MacOS/pncrt.Shlb" "RealOne Player.app/Contents/MacOS/Library/Codecs"</command>
+Not doing so, or forgetting to copy the resource fork, will result in errors such as:
+<command>GetDiskFragment() failed with error -2804: &lt;&lt;Unknown disk fragment&gt;&gt;&lt;&lt;Unknown disk
+fragment&gt;&gt;&lt;pncrt.Shlb&gt;&lt;&gt;</command>
 </para></note>
 </sect3>
 
--- MPlayer-20040618.orig/configure	Tue Jun 15 09:01:02 2004
+++ MPlayer-20040618/configure	Fri Jun 18 13:49:00 2004
@@ -191,6 +191,7 @@
   --enable-jpeg		 enable jpeg input/output support [autodetect]
   --enable-liblzo	 enable external liblzo support [autodetect]
   --disable-win32        disable Win32 DLL support [autodetect]
+  --disable-macshlb      disable Mac OS X SHLB support [autodetect]
   --disable-dshow        disable Win32/DirectShow support [autodetect]
   --disable-qtx          disable Quicktime codecs [autodetect]
   --disable-xanim        disable XAnim DLL support [autodetect]
@@ -1201,6 +1202,7 @@
 _alsa=auto
 _fastmemcpy=yes
 _unrarlib=yes
+_macshlb=auto
 _win32=auto
 _dshow=yes
 _select=yes
@@ -1584,6 +1586,8 @@
   --disable-mmx) # 3Dnow! and MMX2 require MMX
         _3dnow=no _3dnowex=no _mmx=no _mmx2=no ;;
 
+  --enable-macshlb) _macshlb=yes ;;
+  --disable-macshlb) _macshlb=no ;;
   --enable-win32) _win32=yes ;;
   --disable-win32) _win32=no _dshow=no ;;
   --enable-dshow) _win32=yes _dshow=yes ;;
@@ -4852,7 +4856,20 @@
   _ld_faad=
 fi
 
-
+echocheck "Mac OS X codec SHLB support"
+if test "$_macshlb" = auto ; then
+  if test "$_macosx" = yes ; then
+    _macshlb=yes
+  else
+    _macshlb=no
+  fi
+fi
+echores "$_macshlb"
+if test "$_macshlb" = yes ; then
+  _def_macshlb='#define USE_MACSHLB 1'
+else
+  _def_macshlb='#undef USE_MACSHLB'
+fi
 
 if test "$_win32" = auto ; then
   if x86 ; then
@@ -5000,18 +5017,19 @@
 echocheck "RealPlayer DLL"
 if test "$_real" = auto ; then
   _real=no
-  if test "$_dl" = yes || test "$_win32" = yes ; then
+  if test "$_dl" = yes || test "$_win32" = yes || test "$_macshlb" = yes ; then
 #  if test "$_dl" = yes  ; then
-    if linux || freebsd || netbsd || win32 ; then
+    if linux || freebsd || netbsd || win32 || darwin ; then
       _real=yes
     else
-      echores "no (tested only on Linux/FreeBSD/NetBSD/Cygwin/MinGW)"
+      echores "no (tested only on Linux/FreeBSD/NetBSD/Cygwin/MinGW/Darwin)"
     fi
     if test "$_real" = yes ; then
       if test -z "$_reallibdir" ; then
 	for I in "$_libdir/codecs" "$_libdir/real" /usr/lib/real \
 	  /usr/lib/RealPlayer{9,8,}/Codecs /usr/local/RealPlayer{9,8,}/Codecs \
 	  /usr/local/lib/RealPlayer{9,8,}/Codecs /opt/RealPlayer{9,8,}/{Real/,}Codecs \
+	  {~,}/Applications/RealOne\ Player.app/Contents/MacOS/Library/Codecs \
 	  "$_win32libdir"; do
           if test -d "$I" ; then
             _reallibdir="$I"
@@ -6366,6 +6384,9 @@
 
 /* Mac OS X specific features */
 $_def_macosx
+
+/* Mac OS X SHLB support */
+$_def_macshlb
 
 /* Build our Win32-loader */
 $_def_win32_loader
--- MPlayer-20040618.orig/etc/codecs.conf	Fri Jun 11 10:09:24 2004
+++ MPlayer-20040618/etc/codecs.conf	Fri Jun 18 16:57:06 2004
@@ -1072,6 +1072,14 @@
   dll "drv43260.dll"
   out I420
 
+videocodec rv40mac
+  info "Mac OS X RealPlayer 9 RV40 decoder"
+  status working
+  fourcc RV40,rv40
+  driver realvid
+  dll "drv4.shlb"
+  out I420
+
 videocodec rv30
   info "Linux RealPlayer 8 RV30 decoder"
   status working
@@ -1088,6 +1096,14 @@
   dll "drv33260.dll"
   out I420
 
+videocodec rv30mac
+  info "Mac OS X RealPlayer 9 RV30 decoder"
+  status working
+  fourcc RV30,rv30
+  driver realvid
+  dll "drv3.shlb"
+  out I420
+
 videocodec rv20
   info "Linux RealPlayer 8 RV20 decoder"
   status working
@@ -1104,6 +1120,14 @@
   dll "drv23260.dll"
   out I420
 
+videocodec rv20mac
+  info "Mac OS X RealPlayer 9 RV20 decoder"
+  status working
+  fourcc RV20,rv20
+  driver realvid
+  dll "drv2.shlb"
+  out I420
+
 ; others:
 
 videocodec alpary
@@ -1842,6 +1866,13 @@
   driver realaud
   dll "14_43260.dll"
 
+audiocodec ra144mac
+  info "Mac OS X RealAudio 1.0"
+  status working
+  format 0x345F3431 ; "14_4"
+  driver realaud
+  dll "14_4.shlb"
+
 audiocodec ra288
   info "RealAudio 2.0"
   status working
@@ -1856,6 +1887,13 @@
   driver realaud
   dll "28_83260.dll"
 
+audiocodec ra288mac
+  info "Mac OS X RealAudio 2.0"
+  status working
+  format 0x385F3832 ; "28_8"
+  driver realaud
+  dll "28_8.shlb"
+
 audiocodec mpra1428
   info "RealAudio 1.0 and 2.0 native decoder"
   status working
@@ -1877,6 +1915,13 @@
   driver realaud
   dll "cook3260.dll"
 
+audiocodec racookmac
+  info "Mac OS X RealAudio COOK"
+  status working
+  format 0x6B6F6F63 ; "cook"
+  driver realaud
+  dll "cook.shlb"
+
 audiocodec rasipr
   info "RealAudio Sipro"
   status working
@@ -1891,6 +1936,13 @@
   driver realaud
   dll "sipr3260.dll"
 
+audiocodec rasiprmac
+  info "Mac OS X RealAudio Sipro"
+  status working
+  format 0x72706973 ; "sipr"
+  driver realaud
+  dll "sipr.shlb"
+
 audiocodec raatrc
   info "RealAudio ATRAC3"
   status working
@@ -1904,6 +1956,13 @@
   format 0x63727461 ; "atrc"
   driver realaud
   dll "atrc3260.dll"
+
+audiocodec raatrcmac
+  info "Mac OS X RealAudio ATRAC3"
+  status working
+  format 0x63727461 ; "atrc"
+  driver realaud
+  dll "atrc.shlb"
 
 audiocodec imaadpcm
   info "IMA ADPCM"


More information about the MPlayer-dev-eng mailing list