Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

realaudio.c

00001 /*****************************************************************************
00002  * realaudio.c: a realaudio decoder that uses the realaudio library/dll
00003  *****************************************************************************
00004  * Copyright (C) 2005 the VideoLAN team
00005  * $Id$
00006  *
00007  * This program is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00020  *****************************************************************************/
00021 
00022 /*****************************************************************************
00023  * Preamble
00024  *****************************************************************************/
00025 #include <vlc/vlc.h>
00026 #include <vlc/aout.h>
00027 #include <vlc/vout.h>
00028 #include <vlc/decoder.h>
00029 
00030 #ifdef LOADER
00031 /* Need the w32dll loader from mplayer */
00032 #   include <wine/winerror.h>
00033 #   include <ldt_keeper.h>
00034 #   include <wine/windef.h>
00035 
00036 void *WINAPI LoadLibraryA( char *name );
00037 void *WINAPI GetProcAddress( void *handle, char *func );
00038 int WINAPI FreeLibrary( void *handle );
00039 #endif
00040 
00041 #ifndef WINAPI
00042 #   define WINAPI
00043 #endif
00044 
00045 #if defined(HAVE_DL_DLOPEN)
00046 #   if defined(HAVE_DLFCN_H) /* Linux, BSD, Hurd */
00047 #       include <dlfcn.h>
00048 #   endif
00049 #   if defined(HAVE_SYS_DL_H)
00050 #       include <sys/dl.h>
00051 #   endif
00052 #endif
00053 
00054 /*****************************************************************************
00055  * Module descriptor
00056  *****************************************************************************/
00057 static int  Open ( vlc_object_t * );
00058 static void Close( vlc_object_t * );
00059 
00060 vlc_module_begin();
00061     set_description( _("RealAudio library decoder") );
00062     set_capability( "decoder", 10 );
00063     set_category( CAT_INPUT );
00064     set_subcategory( SUBCAT_INPUT_VCODEC );
00065     set_callbacks( Open, Close );
00066 vlc_module_end();
00067 
00068 /*****************************************************************************
00069  * Local prototypes
00070  *****************************************************************************/
00071 static int  OpenDll( decoder_t * );
00072 static int  OpenNativeDll( decoder_t *, char *, char * );
00073 static int  OpenWin32Dll( decoder_t *, char *, char * );
00074 static void CloseDll( decoder_t * );
00075 
00076 static aout_buffer_t *Decode( decoder_t *, block_t ** );
00077 
00078 struct decoder_sys_t
00079 {
00080     audio_date_t end_date;
00081 
00082     /* Output buffer */
00083     char *p_out;
00084     unsigned int i_out;
00085 
00086     /* Codec params */
00087     void *context;
00088     int i_codec_flavor;
00089 
00090     void *dll;
00091     unsigned long (*raCloseCodec)(void*);
00092     unsigned long (*raDecode)(void*, char*, unsigned long, char*,
00093                               unsigned int*, long);
00094     unsigned long (*raFlush)(unsigned long, unsigned long, unsigned long);
00095     unsigned long (*raFreeDecoder)(void*);
00096     void*         (*raGetFlavorProperty)(void*, unsigned long,
00097                                          unsigned long, int*);
00098     unsigned long (*raInitDecoder)(void*, void*);
00099     unsigned long (*raOpenCodec)(void*);
00100     unsigned long (*raOpenCodec2)(void*, void*);
00101     unsigned long (*raSetFlavor)(void*, unsigned long);
00102     void          (*raSetDLLAccessPath)(char*);
00103     void          (*raSetPwd)(char*, char*);
00104 
00105 #if defined(LOADER)
00106     ldt_fs_t *ldt_fs;
00107 #endif
00108 
00109     void *win32_dll;
00110     unsigned long WINAPI (*wraCloseCodec)(void*);
00111     unsigned long WINAPI (*wraDecode)(void*, char*, unsigned long, char*,
00112                                       unsigned int*, long);
00113     unsigned long WINAPI (*wraFlush)(unsigned long, unsigned long,
00114                                      unsigned long);
00115     unsigned long WINAPI (*wraFreeDecoder)(void*);
00116     void*         WINAPI (*wraGetFlavorProperty)(void*, unsigned long,
00117                                                  unsigned long, int*);
00118     unsigned long WINAPI (*wraInitDecoder)(void*, void*);
00119     unsigned long WINAPI (*wraOpenCodec)(void*);
00120     unsigned long WINAPI (*wraOpenCodec2)(void*, void*);
00121     unsigned long WINAPI (*wraSetFlavor)(void*, unsigned long);
00122     void          WINAPI (*wraSetDLLAccessPath)(char*);
00123     void          WINAPI (*wraSetPwd)(char*, char*);
00124 };
00125 
00126 /* linux dlls doesn't need packing */
00127 typedef struct /*__attribute__((__packed__))*/ {
00128     int samplerate;
00129     short bits;
00130     short channels;
00131     short quality;
00132     /* 2bytes padding here, by gcc */
00133     int bits_per_frame;
00134     int packetsize;
00135     int extradata_len;
00136     void* extradata;
00137 } ra_init_t;
00138 
00139 /* windows dlls need packed structs (no padding) */
00140 typedef struct __attribute__((__packed__)) {
00141     int samplerate;
00142     short bits;
00143     short channels;
00144     short quality;
00145     int bits_per_frame;
00146     int packetsize;
00147     int extradata_len;
00148     void* extradata;
00149 } wra_init_t;
00150 
00151 void *__builtin_new(unsigned long size) {return malloc(size);}
00152 void __builtin_delete(void *p) {free(p);}
00153 
00154 static int pi_channels_maps[7] =
00155 {
00156     0,
00157     AOUT_CHAN_CENTER,
00158     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
00159     AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
00160     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
00161      | AOUT_CHAN_REARRIGHT,
00162     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
00163      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
00164     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
00165      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE
00166 };
00167 
00168 /*****************************************************************************
00169  * Open: probe the decoder and return score
00170  *****************************************************************************
00171  * Tries to launch a decoder and return score so that the interface is able
00172  * to choose.
00173  *****************************************************************************/
00174 static int Open( vlc_object_t *p_this )
00175 {
00176     decoder_t *p_dec = (decoder_t*)p_this;
00177     decoder_sys_t *p_sys = p_dec->p_sys;
00178 
00179     switch( p_dec->fmt_in.i_codec )
00180     {
00181     case VLC_FOURCC('c','o','o','k'):
00182         break;
00183 
00184     default:
00185         return VLC_EGENERIC;
00186     }
00187 
00188     p_dec->p_sys = p_sys = malloc( sizeof( decoder_sys_t ) );
00189     memset( p_sys, 0, sizeof(decoder_sys_t) );
00190 
00191     p_sys->i_codec_flavor = -1;
00192     if( p_dec->fmt_in.i_codec == VLC_FOURCC('s','i','p','r') )
00193     {
00194         if( p_dec->fmt_in.audio.i_bitspersample > 1531 )
00195             p_sys->i_codec_flavor = 3;
00196         else if( p_dec->fmt_in.audio.i_bitspersample > 937 )
00197             p_sys->i_codec_flavor = 1;
00198         else if( p_dec->fmt_in.audio.i_bitspersample > 719 )
00199             p_sys->i_codec_flavor = 0;
00200         else
00201             p_sys->i_codec_flavor = 2;
00202     }
00203 
00204     if( OpenDll( p_dec ) != VLC_SUCCESS )
00205     {
00206         free( p_sys );
00207         return VLC_EGENERIC;
00208     }
00209 
00210 #ifdef LOADER
00211     if( p_sys->win32_dll ) Close( p_this );
00212 #endif
00213 
00214     es_format_Init( &p_dec->fmt_out, AUDIO_ES, AOUT_FMT_S16_NE );
00215     p_dec->fmt_out.audio.i_rate = p_dec->fmt_in.audio.i_rate;
00216     p_dec->fmt_out.audio.i_channels = p_dec->fmt_in.audio.i_channels;
00217     p_dec->fmt_out.audio.i_bitspersample =
00218         p_dec->fmt_in.audio.i_bitspersample;
00219     p_dec->fmt_out.audio.i_physical_channels =
00220     p_dec->fmt_out.audio.i_original_channels =
00221         pi_channels_maps[p_dec->fmt_out.audio.i_channels];
00222 
00223     aout_DateInit( &p_sys->end_date, p_dec->fmt_out.audio.i_rate );
00224     aout_DateSet( &p_sys->end_date, 0 );
00225 
00226     p_dec->pf_decode_audio = Decode;
00227 
00228     p_sys->p_out = malloc( 4096 * 10 );
00229     p_sys->i_out = 0;
00230 
00231     return VLC_SUCCESS;
00232 }
00233 
00234 /*****************************************************************************
00235  * Close:
00236  *****************************************************************************/
00237 static void Close( vlc_object_t *p_this )
00238 {
00239     decoder_t *p_dec = (decoder_t*)p_this;
00240 
00241     CloseDll( p_dec );
00242     if( p_dec->p_sys->p_out ) free( p_dec->p_sys->p_out );
00243     free( p_dec->p_sys );
00244 }
00245 
00246 /*****************************************************************************
00247  * OpenDll:
00248  *****************************************************************************/
00249 static int OpenDll( decoder_t *p_dec )
00250 {
00251     char *psz_dll;
00252     int i, i_result;
00253 
00254     char *ppsz_path[] =
00255     {
00256       ".",
00257 #ifndef WIN32
00258       "/usr/local/RealPlayer8/Codecs",
00259       "/usr/RealPlayer8/Codecs",
00260       "/usr/lib/RealPlayer8/Codecs",
00261       "/opt/RealPlayer8/Codecs",
00262       "/usr/lib/RealPlayer9/users/Real/Codecs",
00263       "/usr/lib64/RealPlayer8/Codecs",
00264       "/usr/lib64/RealPlayer9/users/Real/Codecs",
00265       "/usr/lib/win32",
00266 #endif
00267       NULL,
00268       NULL,
00269       NULL
00270     };
00271 
00272 #ifdef WIN32
00273     char psz_win32_real_codecs[MAX_PATH + 1];
00274     char psz_win32_helix_codecs[MAX_PATH + 1];
00275 #endif
00276 
00277     for( i = 0; ppsz_path[i]; i++ )
00278     {
00279         asprintf( &psz_dll, "%s/%4.4s.so.6.0", ppsz_path[i],
00280                   (char *)&p_dec->fmt_in.i_codec );
00281         i_result = OpenNativeDll( p_dec, ppsz_path[i], psz_dll );
00282         free( psz_dll );
00283         if( i_result == VLC_SUCCESS ) return VLC_SUCCESS;
00284     }
00285 
00286 #ifdef WIN32
00287     {
00288         HKEY h_key;
00289         DWORD i_type, i_data = MAX_PATH + 1, i_index = 1;
00290         char *p_data;
00291 
00292         p_data = psz_win32_real_codecs;
00293         if( RegOpenKeyEx( HKEY_CLASSES_ROOT,
00294                           _T("Software\\RealNetworks\\Preferences\\DT_Codecs"),
00295                           0, KEY_READ, &h_key ) == ERROR_SUCCESS )
00296         {
00297              if( RegQueryValueEx( h_key, _T(""), 0, &i_type,
00298                                   (LPBYTE)p_data, &i_data ) == ERROR_SUCCESS &&
00299                  i_type == REG_SZ )
00300              {
00301                  int i_len = strlen( p_data );
00302                  if( i_len && p_data[i_len-1] == '\\' ) p_data[i_len-1] = 0;
00303                  ppsz_path[i_index++] = p_data;
00304                  msg_Err( p_dec, "Real: %s", p_data );
00305              }
00306              RegCloseKey( h_key );
00307         }
00308 
00309         p_data = psz_win32_helix_codecs;
00310         if( RegOpenKeyEx( HKEY_CLASSES_ROOT,
00311                           _T("Helix\\HelixSDK\\10.0\\Preferences\\DT_Codecs"),
00312                           0, KEY_READ, &h_key ) == ERROR_SUCCESS )
00313         {
00314              if( RegQueryValueEx( h_key, _T(""), 0, &i_type,
00315                                   (LPBYTE)p_data, &i_data ) == ERROR_SUCCESS &&
00316                  i_type == REG_SZ )
00317              {
00318                  int i_len = strlen( p_data );
00319                  if( i_len && p_data[i_len-1] == '\\' ) p_data[i_len-1] = 0;
00320                  ppsz_path[i_index++] = p_data;
00321                  msg_Err( p_dec, "Real: %s", p_data );
00322              }
00323              RegCloseKey( h_key );
00324         }
00325     }
00326 #endif
00327 
00328     for( i = 0; ppsz_path[i]; i++ )
00329     {
00330         /* New format */
00331         asprintf( &psz_dll, "%s\\%4.4s.dll", ppsz_path[i],
00332                   (char *)&p_dec->fmt_in.i_codec );
00333         i_result = OpenWin32Dll( p_dec, ppsz_path[i], psz_dll );
00334         free( psz_dll );
00335         if( i_result == VLC_SUCCESS ) return VLC_SUCCESS;
00336 
00337         /* Old format */
00338         asprintf( &psz_dll, "%s\\%4.4s3260.dll", ppsz_path[i],
00339                   (char *)&p_dec->fmt_in.i_codec );
00340         i_result = OpenWin32Dll( p_dec, ppsz_path[i], psz_dll );
00341         free( psz_dll );
00342         if( i_result == VLC_SUCCESS ) return VLC_SUCCESS;
00343     }
00344 
00345     return VLC_EGENERIC;
00346 }
00347 
00348 static int OpenNativeDll( decoder_t *p_dec, char *psz_path, char *psz_dll )
00349 {
00350 #if defined(HAVE_DL_DLOPEN)
00351     decoder_sys_t *p_sys = p_dec->p_sys;
00352     void *handle = 0, *context = 0;
00353     unsigned int i_result;
00354     void *p_prop;
00355     int i_prop;
00356 
00357     ra_init_t init_data =
00358     {
00359         p_dec->fmt_in.audio.i_rate,
00360         p_dec->fmt_in.audio.i_bitspersample,
00361         p_dec->fmt_in.audio.i_channels,
00362         100, /* quality */
00363         p_dec->fmt_in.audio.i_blockalign, /* subpacket size */
00364         p_dec->fmt_in.audio.i_blockalign, /* coded frame size */
00365         p_dec->fmt_in.i_extra, p_dec->fmt_in.p_extra
00366     };
00367 
00368     msg_Dbg( p_dec, "opening library '%s'", psz_dll );
00369     if( !(handle = dlopen( psz_dll, RTLD_LAZY )) )
00370     {
00371         msg_Dbg( p_dec, "couldn't load library '%s' (%s)",
00372                  psz_dll, dlerror() );
00373         return VLC_EGENERIC;
00374     }
00375 
00376     p_sys->raCloseCodec = dlsym( handle, "RACloseCodec" );
00377     p_sys->raDecode = dlsym( handle, "RADecode" );
00378     p_sys->raFlush = dlsym( handle, "RAFlush" );
00379     p_sys->raFreeDecoder = dlsym( handle, "RAFreeDecoder" );
00380     p_sys->raGetFlavorProperty = dlsym( handle, "RAGetFlavorProperty" );
00381     p_sys->raOpenCodec = dlsym( handle, "RAOpenCodec" );
00382     p_sys->raOpenCodec2 = dlsym( handle, "RAOpenCodec2" );
00383     p_sys->raInitDecoder = dlsym( handle, "RAInitDecoder" );
00384     p_sys->raSetFlavor = dlsym( handle, "RASetFlavor" );
00385     p_sys->raSetDLLAccessPath = dlsym( handle, "SetDLLAccessPath" );
00386     p_sys->raSetPwd = dlsym( handle, "RASetPwd" ); // optional, used by SIPR
00387 
00388     if( !(p_sys->raOpenCodec || p_sys->raOpenCodec2) ||
00389         !p_sys->raCloseCodec || !p_sys->raInitDecoder ||
00390         !p_sys->raDecode || !p_sys->raFreeDecoder ||
00391         !p_sys->raGetFlavorProperty || !p_sys->raSetFlavor
00392         /* || !p_sys->raFlush || !p_sys->raSetDLLAccessPath */ )
00393     {
00394         goto error_native;
00395     }
00396 
00397     if( p_sys->raOpenCodec2 )
00398         i_result = p_sys->raOpenCodec2( &context, psz_path );
00399     else
00400         i_result = p_sys->raOpenCodec( &context );
00401 
00402     if( i_result )
00403     {
00404         msg_Err( p_dec, "decoder open failed, error code: 0x%x", i_result );
00405         goto error_native;
00406     }
00407 
00408     i_result = p_sys->raInitDecoder( context, &init_data );
00409     if( i_result )
00410     {
00411         msg_Err( p_dec, "decoder init failed, error code: 0x%x", i_result );
00412         goto error_native;
00413     }
00414 
00415     if( p_sys->i_codec_flavor >= 0 )
00416     {
00417         i_result = p_sys->raSetFlavor( context, p_sys->i_codec_flavor );
00418         if( i_result )
00419         {
00420             msg_Err( p_dec, "decoder flavor setup failed, error code: 0x%x",
00421                      i_result );
00422             goto error_native;
00423         }
00424 
00425         p_prop = p_sys->raGetFlavorProperty( context, p_sys->i_codec_flavor,
00426                                              0, &i_prop );
00427         msg_Dbg( p_dec, "audio codec: [%d] %s",
00428                  p_sys->i_codec_flavor, (char *)p_prop );
00429 
00430         p_prop = p_sys->raGetFlavorProperty( context, p_sys->i_codec_flavor,
00431                                              1, &i_prop );
00432         if( p_prop )
00433         {
00434             int i_bps = ((*((int*)p_prop))+4)/8;
00435             msg_Dbg( p_dec, "audio bitrate: %5.3f kbit/s (%d bps)",
00436                      (*((int*)p_prop))*0.001f, i_bps );
00437         }
00438     }
00439 
00440     p_sys->context = context;
00441     p_sys->dll = handle;
00442     return VLC_SUCCESS;
00443 
00444  error_native:
00445     if( context ) p_sys->raFreeDecoder( context );
00446     if( context ) p_sys->raCloseCodec( context );
00447     dlclose( handle );
00448 #endif
00449 
00450     return VLC_EGENERIC;
00451 }
00452 
00453 static int OpenWin32Dll( decoder_t *p_dec, char *psz_path, char *psz_dll )
00454 {
00455 #if defined(LOADER) || defined(WIN32)
00456     decoder_sys_t *p_sys = p_dec->p_sys;
00457     void *handle = 0, *context = 0;
00458     unsigned int i_result;
00459     void *p_prop;
00460     int i_prop;
00461 
00462     wra_init_t init_data =
00463     {
00464         p_dec->fmt_in.audio.i_rate,
00465         p_dec->fmt_in.audio.i_bitspersample,
00466         p_dec->fmt_in.audio.i_channels,
00467         100, /* quality */
00468         p_dec->fmt_in.audio.i_blockalign, /* subpacket size */
00469         p_dec->fmt_in.audio.i_blockalign, /* coded frame size */
00470         p_dec->fmt_in.i_extra, p_dec->fmt_in.p_extra
00471     };
00472 
00473     msg_Dbg( p_dec, "opening win32 dll '%s'", psz_dll );
00474 
00475 #ifdef LOADER
00476     Setup_LDT_Keeper();
00477 #endif
00478 
00479     if( !(handle = LoadLibraryA( psz_dll )) )
00480     {
00481         msg_Dbg( p_dec, "couldn't load dll '%s'", psz_dll );
00482         return VLC_EGENERIC;
00483     }
00484 
00485     p_sys->wraCloseCodec = GetProcAddress( handle, "RACloseCodec" );
00486     p_sys->wraDecode = GetProcAddress( handle, "RADecode" );
00487     p_sys->wraFlush = GetProcAddress( handle, "RAFlush" );
00488     p_sys->wraFreeDecoder = GetProcAddress( handle, "RAFreeDecoder" );
00489     p_sys->wraGetFlavorProperty =
00490         GetProcAddress( handle, "RAGetFlavorProperty" );
00491     p_sys->wraOpenCodec = GetProcAddress( handle, "RAOpenCodec" );
00492     p_sys->wraOpenCodec2 = GetProcAddress( handle, "RAOpenCodec2" );
00493     p_sys->wraInitDecoder = GetProcAddress( handle, "RAInitDecoder" );
00494     p_sys->wraSetFlavor = GetProcAddress( handle, "RASetFlavor" );
00495     p_sys->wraSetDLLAccessPath = GetProcAddress( handle, "SetDLLAccessPath" );
00496     p_sys->wraSetPwd =
00497         GetProcAddress( handle, "RASetPwd" ); // optional, used by SIPR
00498 
00499     if( !(p_sys->wraOpenCodec || p_sys->wraOpenCodec2) ||
00500         !p_sys->wraCloseCodec || !p_sys->wraInitDecoder ||
00501         !p_sys->wraDecode || !p_sys->wraFreeDecoder ||
00502         !p_sys->wraGetFlavorProperty || !p_sys->wraSetFlavor
00503         /* || !p_sys->wraFlush || !p_sys->wraSetDLLAccessPath */ )
00504     {
00505         FreeLibrary( handle );
00506         return VLC_EGENERIC;
00507     }
00508 
00509     if( p_sys->wraOpenCodec2 )
00510         i_result = p_sys->wraOpenCodec2( &context, psz_path );
00511     else
00512         i_result = p_sys->wraOpenCodec( &context );
00513 
00514     if( i_result )
00515     {
00516         msg_Err( p_dec, "decoder open failed, error code: 0x%x", i_result );
00517         goto error_win32;
00518     }
00519 
00520     i_result = p_sys->wraInitDecoder( context, &init_data );
00521     if( i_result )
00522     {
00523         msg_Err( p_dec, "decoder init failed, error code: 0x%x", i_result );
00524         goto error_win32;
00525     }
00526 
00527     if( p_sys->i_codec_flavor >= 0 )
00528     {
00529         i_result = p_sys->wraSetFlavor( context, p_sys->i_codec_flavor );
00530         if( i_result )
00531         {
00532             msg_Err( p_dec, "decoder flavor setup failed, error code: 0x%x",
00533                      i_result );
00534             goto error_win32;
00535         }
00536 
00537         p_prop = p_sys->wraGetFlavorProperty( context, p_sys->i_codec_flavor,
00538                                               0, &i_prop );
00539         msg_Dbg( p_dec, "audio codec: [%d] %s",
00540                  p_sys->i_codec_flavor, (char *)p_prop );
00541 
00542         p_prop = p_sys->wraGetFlavorProperty( context, p_sys->i_codec_flavor,
00543                                               1, &i_prop );
00544         if( p_prop )
00545         {
00546             int i_bps = ((*((int*)p_prop))+4)/8;
00547             msg_Dbg( p_dec, "audio bitrate: %5.3f kbit/s (%d bps)",
00548                      (*((int*)p_prop))*0.001f, i_bps );
00549         }
00550     }
00551 
00552     p_sys->context = context;
00553     p_sys->win32_dll = handle;
00554     return VLC_SUCCESS;
00555 
00556  error_win32:
00557     if( context ) p_sys->wraFreeDecoder( context );
00558     if( context ) p_sys->wraCloseCodec( context );
00559     FreeLibrary( handle );
00560 #endif
00561 
00562     return VLC_EGENERIC;
00563 }
00564 
00565 /*****************************************************************************
00566  * CloseDll:
00567  *****************************************************************************/
00568 static void CloseDll( decoder_t *p_dec )
00569 {
00570     decoder_sys_t *p_sys = p_dec->p_sys;
00571 
00572     if( p_sys->context && p_sys->dll )
00573     {
00574         p_sys->raFreeDecoder( p_sys->context );
00575         p_sys->raCloseCodec( p_sys->context );
00576     }
00577 
00578     if( p_sys->context && p_sys->win32_dll )
00579     {
00580         p_sys->wraFreeDecoder( p_sys->context );
00581         p_sys->wraCloseCodec( p_sys->context );
00582     }
00583 
00584 #if defined(HAVE_DL_DLOPEN)
00585     if( p_sys->dll ) dlclose( p_sys->dll );
00586 #endif
00587 
00588 #if defined(LOADER) || defined(WIN32)
00589     if( p_sys->win32_dll ) FreeLibrary( p_sys->win32_dll );
00590 
00591 #if 0 //def LOADER /* Segfaults */
00592     Restore_LDT_Keeper( p_sys->ldt_fs );
00593     msg_Dbg( p_dec, "Restore_LDT_Keeper" );
00594 #endif
00595 #endif
00596 
00597     p_sys->dll = 0;
00598     p_sys->win32_dll = 0;
00599     p_sys->context = 0;
00600 }
00601 
00602 /*****************************************************************************
00603  * DecodeAudio:
00604  *****************************************************************************/
00605 static aout_buffer_t *Decode( decoder_t *p_dec, block_t **pp_block )
00606 {
00607     decoder_sys_t *p_sys = p_dec->p_sys;
00608     aout_buffer_t *p_aout_buffer = 0;
00609     unsigned int i_result;
00610     int i_samples;
00611     block_t *p_block;
00612 
00613 #ifdef LOADER
00614     if( !p_sys->win32_dll && !p_sys->dll )
00615     {
00616         /* We must do open and close in the same thread (unless we do
00617          * Setup_LDT_Keeper in the main thread before all others */
00618         if( OpenDll( p_dec ) != VLC_SUCCESS )
00619         {
00620             /* Fatal */
00621             p_dec->b_error = VLC_TRUE;
00622             return NULL;
00623         }
00624     }
00625 #endif
00626 
00627     if( pp_block == NULL || *pp_block == NULL ) return NULL;
00628     p_block = *pp_block;
00629 
00630     if( p_sys->dll )
00631         i_result = p_sys->raDecode( p_sys->context, (char *)p_block->p_buffer,
00632                                     (unsigned long)p_block->i_buffer,
00633                                     p_sys->p_out, &p_sys->i_out, -1 );
00634     else
00635         i_result = p_sys->wraDecode( p_sys->context, (char *)p_block->p_buffer,
00636                                      (unsigned long)p_block->i_buffer,
00637                                      p_sys->p_out, &p_sys->i_out, -1 );
00638 
00639 #if 0
00640     msg_Err( p_dec, "decoded: %i samples (%i)",
00641              p_sys->i_out * 8 / p_dec->fmt_out.audio.i_bitspersample /
00642              p_dec->fmt_out.audio.i_channels, i_result );
00643 #endif
00644 
00645     /* Date management */
00646     if( p_block->i_pts > 0 &&
00647         p_block->i_pts != aout_DateGet( &p_sys->end_date ) )
00648     {
00649         aout_DateSet( &p_sys->end_date, p_block->i_pts );
00650     }
00651 
00652     if( !aout_DateGet( &p_sys->end_date ) )
00653     {
00654         /* We've just started the stream, wait for the first PTS. */
00655         if( p_block ) block_Release( p_block );
00656         return NULL;
00657     }
00658 
00659     i_samples = p_sys->i_out * 8 /
00660         p_dec->fmt_out.audio.i_bitspersample /p_dec->fmt_out.audio.i_channels;
00661 
00662     p_aout_buffer =
00663         p_dec->pf_aout_buffer_new( p_dec, i_samples );
00664     if( p_aout_buffer )
00665     {
00666         memcpy( p_aout_buffer->p_buffer, p_sys->p_out, p_sys->i_out );
00667 
00668         /* Date management */
00669         p_aout_buffer->start_date = aout_DateGet( &p_sys->end_date );
00670         p_aout_buffer->end_date =
00671             aout_DateIncrement( &p_sys->end_date, i_samples );
00672     }
00673 
00674     block_Release( p_block );
00675     *pp_block = 0;
00676     return p_aout_buffer;
00677 }

Generated on Tue Dec 20 10:14:29 2005 for vlc-0.8.4a by  doxygen 1.4.2