From f12378eb20f4a6be8ced29dd0aea6574a266e0f0 Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 24 Jun 2004 09:19:15 +0000 Subject: [PATCH] support for realvideo codecs under macosx, original patch by Donnie Smith git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@12629 b3059339-0415-0410-9bf9-f77b7e298cf2 --- etc/codecs.conf | 59 ++++++++++++++++ libmpcodecs/ad_realaud.c | 143 ++++++++++++++++++++++++++++++++++++++- libmpcodecs/vd_realvid.c | 83 +++++++++++++++++++++-- 3 files changed, 278 insertions(+), 7 deletions(-) diff --git a/etc/codecs.conf b/etc/codecs.conf index 4b55187999..3e5e7a87b6 100644 --- a/etc/codecs.conf +++ b/etc/codecs.conf @@ -1072,6 +1072,14 @@ videocodec rv40win 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 @@ videocodec rv30win 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 @@ videocodec rv20win 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 @@ audiocodec ra144win 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 @@ audiocodec ra288win 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 @@ audiocodec racookwin 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 @@ audiocodec rasiprwin 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 @@ -1905,6 +1957,13 @@ audiocodec raatrcwin 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" status working diff --git a/libmpcodecs/ad_realaud.c b/libmpcodecs/ad_realaud.c index c1a7d8c643..2fa1ca2b09 100644 --- a/libmpcodecs/ad_realaud.c +++ b/libmpcodecs/ad_realaud.c @@ -16,11 +16,15 @@ #include "ad_internal.h" #include "wine/windef.h" +#ifdef USE_MACSHLB +#include +#endif + static ad_info_t info = { "RealAudio decoder", "realaud", - "A'rpi", // win32 dlls support by alex - "Florian Schneider", + "Alex Beregszaszi", + "Florian Schneider, Arpad Gereoffy, Alex Beregszaszi, Donnie Smith", "binary real audio codecs" }; @@ -66,6 +70,7 @@ static void WINAPI (*wraSetPwd)(char*,char*); static int dll_type = 0; /* 0 = unix dlopen, 1 = win32 dll */ #endif + static void *rv_handle = NULL; #if 0 @@ -206,6 +211,113 @@ static int load_syms_windows(char *path) } #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; + char realname[255]; + + if (strlen(symbolName) > 255) + { + mp_mpsg(MSGT_DECVIDEO, MSGL_V, "FindSymbol symbolname overflow\n"); + return NULL; + } + + snprintf(realname, 255, "%c%s", strlen(symbolName), symbolName); + + if ( (err = FindSymbol( *connID, realname, + &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( "RACloseCodec", connID); + raDecode = load_one_sym_mac("RADecode", connID); + raFlush = load_one_sym_mac("RAFlush", connID); + raFreeDecoder = load_one_sym_mac("RAFreeDecoder", connID); + raGetFlavorProperty = load_one_sym_mac("\RAGetFlavorProperty", connID); + raOpenCodec = load_one_sym_mac("RAOpenCodec", connID); + raOpenCodec2 = load_one_sym_mac("RAOpenCodec2", connID); + raInitDecoder = load_one_sym_mac("RAInitDecoder", connID); + raSetFlavor = load_one_sym_mac("RASetFlavor", connID); + raSetDLLAccessPath = load_one_sym_mac("SetDLLAccessPath", connID); + raSetPwd = load_one_sym_mac("RASetPwd", 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) @@ -220,6 +332,10 @@ static int preinit(sh_audio_t *sh){ /* first try to load linux dlls, if failed and we're supporting win32 dlls, then try to load the windows ones */ + +#ifdef USE_MACSHLB + if (strstr(sh->codec->dll,".shlb") && !load_syms_mac(path)) +#endif #ifdef HAVE_LIBDL if (strstr(sh->codec->dll,".dll") || !load_syms_linux(path)) #endif @@ -293,7 +409,7 @@ static int preinit(sh_audio_t *sh){ ((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 +420,17 @@ static int preinit(sh_audio_t *sh){ ((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; @@ -395,6 +517,21 @@ static void uninit(sh_audio_t *sh){ 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) { diff --git a/libmpcodecs/vd_realvid.c b/libmpcodecs/vd_realvid.c index 031b841de3..585a0015da 100644 --- a/libmpcodecs/vd_realvid.c +++ b/libmpcodecs/vd_realvid.c @@ -14,11 +14,15 @@ #include "vd_internal.h" #include "wine/windef.h" +#ifdef USE_MACSHLB +#include +#endif + static vd_info_t info = { "RealVideo decoder", "realvid", - "Florian Schneider & A'rpi", // win32 dlls support by alex - "using original closed source codecs for Linux", + "Alex Beregszaszi", + "Florian Schneider, Arpad Gereoffy, Alex Beregszaszi, Donnie Smith", "binary real video codecs" }; @@ -61,7 +65,7 @@ static unsigned long WINAPI (*wrvyuv_transform)(char*, char*,transform_in_t*,uns #endif static void *rv_handle=NULL; -static int inited; +static int inited=0; #ifdef USE_WIN32DLL static int dll_type = 0; /* 0 = unix dlopen, 1 = win32 dll */ #endif @@ -177,6 +181,64 @@ static int load_syms_windows(char *path) { } #endif +#ifdef USE_MACSHLB +void *load_one_sym_mac(char *symbolName, CFragConnectionID *connID); + +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; + } + + rvyuv_custom_message = load_one_sym_mac("RV20toYUV420CustomMessage", connID); + rvyuv_free = load_one_sym_mac("RV20toYUV420Free", connID); + rvyuv_hive_message = load_one_sym_mac("RV20toYUV420HiveMessage", connID); + rvyuv_init = load_one_sym_mac("RV20toYUV420Init", connID); + rvyuv_transform = load_one_sym_mac("RV20toYUV420Transform", 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; @@ -208,6 +270,9 @@ static int init(sh_video_t *sh){ /* first try to load linux dlls, if failed and we're supporting win32 dlls, then try to load the windows ones */ +#ifdef USE_MACSHLB + if (strstr(sh->codec->dll, ".shlb") && !load_syms_mac(path)) +#endif #ifdef HAVE_LIBDL if(strstr(sh->codec->dll,".dll") || !load_syms_linux(path)) #endif @@ -225,7 +290,6 @@ static int init(sh_video_t *sh){ // if((sh->format!=0x30335652) && !mpcodecs_config_vo(sh,sh->disp_w,sh->disp_h,IMGFMT_I420)) return 0; // init codec: sh->context=NULL; - inited=0; #ifdef USE_WIN32DLL if (dll_type == 1) result=(*wrvyuv_init)(&init_data, &sh->context); @@ -270,6 +334,17 @@ static void uninit(sh_video_t *sh){ #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; }