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

Donnie Smith xc0bead2d8130df59 at f4n.org
Sat Jun 19 14:11:15 CEST 2004


On Sat, Jun 19, 2004 at 11:07:33 +0200, Diego Biurrun wrote:
> Yes, we'll put a codecs package up for download.  Could you prepare
> and upload it to incoming, please?
MacOSXRealPlayerCodecs.zip e03314e26479068a6e90f3f0bda60ef1, 988 kB.
Includes what was in my codecs folder, so there might be some
unnecessary files, but it's pretty small anyhow so to avoid any
potential cross-reference problems I left it as is. Note that it's an
Apple-flavoured ZIP-file, which is necessary to include the resource
forks (it's not too well supported for system <10.3, but at least
everyone can see what's in the file).

I haven't included any instructions, but I guess anyone compiling the
source should be able to figure out that 
{,~}/Library/Application\ Support might be a suitable place to put
them. Btw, configure only checks where RealOne installs them (in it's
own Application bundle), so one would have to specify a custom
location with --with-reallibdir.

> Since I am a pedantic pest when it comes to spelling I would write
> "Win32 DLLs support by alex, Mac OS X shlb support by Donnie Smith",
> but feel free to disregard this ;-).
I agree, I just tried to keep with alex' style, but it's changed now.
(The coding style in those files are a real mess anyhow, tabs and
spaces mixed like crazy. I tried to maintain the "local" style
though.)

> The space in the URL is wrong, while you're at it, you could
> capitalize Pascal and remove the trailing whitespace from the third
> line.
Changed.

> I'd rather use <filename> instead of <command>.
> This will look even better in <screen> instead of <command>
Changed as in your patch.

> > +<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>
> 
> This should also be in <screen> tags and you should insert a linebreak
> at the point where the original message is wrapped, <screen> does not
> wrap lines automatically (similar to <pre> in HTML).
There's no line break (except at the end, of course) in the message
mplayer spits out, so I removed the one that was there. Is this what
you mean? (The message after ":" is returned by the system, so it's
impossible to know for certain what it will be.)

> Don't remove that blank line above echocheck, the readability of the
> configure script is bad enough as it is.
Oops, thanks for noticing.

> Hmm, shouldn't this work on Linux PPC as well?
Perhaps, but GetDiskFragment and all those other functions are Mac OS
specific, not sure if anyone has ported them to Linux PPC.

Thanks for all the suggestions, I've attached a new patch. It's still
for CVS 2004-06-18, but it applies just fine on 2004-06-19 with a 1-2
line offset in configure.

Donnie Smith
-------------- next part --------------
--- MPlayer-20040618.orig/libmpcodecs/vd_realvid.c	Fri Apr 30 12:26:26 2004
+++ MPlayer-20040618/libmpcodecs/vd_realvid.c	Sat Jun 19 12:17:42 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	Sat Jun 19 12:17: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/configure	Tue Jun 15 09:01:02 2004
+++ MPlayer-20040618/configure	Sat Jun 19 12:20:39 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 ;;
@@ -4853,6 +4857,20 @@
 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 +5018,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 +6385,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"
--- MPlayer-20040618.orig/DOCS/xml/en/codecs.xml	Wed May 12 00:50:05 2004
+++ MPlayer-20040618/DOCS/xml/en/codecs.xml	Sat Jun 19 13:35:59 2004
@@ -425,10 +425,20 @@
 specify a unique path with the <option>--with-reallibdir</option> option.
 </para>
 
+<para>
+On Mac OS X you must make sure <filename>pncrt.Shlb</filename> (including it's
+resource fork!) is in the same directory as the Real codecs. Copy it using, for
+example
+<screen>ditto -rsrcFork "RealOne Player.app/Contents/MacOS/pncrt.Shlb" "RealOne Player.app/Contents/MacOS/Library/Codecs"</screen>
+Not doing so, or forgetting to copy the resource fork, will result in errors
+such as: 
+<screen>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;</screen>
+</para>
+
 <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></note>
 </sect3>
 


More information about the MPlayer-dev-eng mailing list