realaudio.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:23k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * realaudio.c: a realaudio decoder that uses the realaudio library/dll
  3.  *****************************************************************************
  4.  * Copyright (C) 2005 the VideoLAN team
  5.  * $Id: aa1d1334c31874f3c758be3d6e31b4d1dcdf0c51 $
  6.  *
  7.  * This program is free software; you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License as published by
  9.  * the Free Software Foundation; either version 2 of the License, or
  10.  * (at your option) any later version.
  11.  *
  12.  * This program is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  * GNU General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU General Public License
  18.  * along with this program; if not, write to the Free Software
  19.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  20.  *****************************************************************************/
  21. /*****************************************************************************
  22.  * Preamble
  23.  *****************************************************************************/
  24. #ifdef HAVE_CONFIG_H
  25. # include "config.h"
  26. #endif
  27. #include <vlc_common.h>
  28. #include <vlc_plugin.h>
  29. #include <vlc_aout.h>
  30. #include <vlc_codec.h>
  31. #ifdef LOADER
  32. /* Need the w32dll loader from mplayer */
  33. #   include <wine/winerror.h>
  34. #   include <ldt_keeper.h>
  35. #   include <wine/windef.h>
  36. void *WINAPI LoadLibraryA( char *name );
  37. void *WINAPI GetProcAddress( void *handle, char *func );
  38. int WINAPI FreeLibrary( void *handle );
  39. #endif
  40. #ifndef WINAPI
  41. #   define WINAPI
  42. #endif
  43. #if defined(HAVE_DL_DLOPEN)
  44. #   if defined(HAVE_DLFCN_H) /* Linux, BSD, Hurd */
  45. #       include <dlfcn.h>
  46. #   endif
  47. #   if defined(HAVE_SYS_DL_H)
  48. #       include <sys/dl.h>
  49. #   endif
  50. #endif
  51. /*****************************************************************************
  52.  * Module descriptor
  53.  *****************************************************************************/
  54. static int  Open ( vlc_object_t * );
  55. static void Close( vlc_object_t * );
  56. vlc_module_begin ()
  57.     set_description( N_("RealAudio library decoder") )
  58.     set_capability( "decoder", 10 )
  59.     set_category( CAT_INPUT )
  60.     set_subcategory( SUBCAT_INPUT_VCODEC )
  61.     set_callbacks( Open, Close )
  62. vlc_module_end ()
  63. /*****************************************************************************
  64.  * Local prototypes
  65.  *****************************************************************************/
  66. static int  OpenDll( decoder_t * );
  67. static int  OpenNativeDll( decoder_t *, char *, char * );
  68. static int  OpenWin32Dll( decoder_t *, char *, char * );
  69. static void CloseDll( decoder_t * );
  70. static aout_buffer_t *Decode( decoder_t *, block_t ** );
  71. struct decoder_sys_t
  72. {
  73.     audio_date_t end_date;
  74.     /* Output buffer */
  75.     char *p_out;
  76.     unsigned int i_out;
  77.     /* Codec params */
  78.     void *context;
  79.     short int i_codec_flavor;
  80.     void *dll;
  81.     unsigned long (*raCloseCodec)(void*);
  82.     unsigned long (*raDecode)(void*, char*, unsigned long, char*,
  83.                               unsigned int*, long);
  84.     unsigned long (*raFlush)(unsigned long, unsigned long, unsigned long);
  85.     unsigned long (*raFreeDecoder)(void*);
  86.     void*         (*raGetFlavorProperty)(void*, unsigned long,
  87.                                          unsigned long, int*);
  88.     unsigned long (*raInitDecoder)(void*, void*);
  89.     unsigned long (*raOpenCodec)(void*);
  90.     unsigned long (*raOpenCodec2)(void*, void*);
  91.     unsigned long (*raSetFlavor)(void*, unsigned long);
  92.     void          (*raSetDLLAccessPath)(char*);
  93.     void          (*raSetPwd)(char*, char*);
  94. #if defined(LOADER)
  95.     ldt_fs_t *ldt_fs;
  96. #endif
  97.     void *win32_dll;
  98.     unsigned long (WINAPI *wraCloseCodec)(void*);
  99.     unsigned long (WINAPI *wraDecode)(void*, char*, unsigned long, char*,
  100.                                       unsigned int*, long);
  101.     unsigned long (WINAPI *wraFlush)(unsigned long, unsigned long,
  102.                                      unsigned long);
  103.     unsigned long (WINAPI *wraFreeDecoder)(void*);
  104.     void*         (WINAPI *wraGetFlavorProperty)(void*, unsigned long,
  105.                                                  unsigned long, int*);
  106.     unsigned long (WINAPI *wraInitDecoder)(void*, void*);
  107.     unsigned long (WINAPI *wraOpenCodec)(void*);
  108.     unsigned long (WINAPI *wraOpenCodec2)(void*, void*);
  109.     unsigned long (WINAPI *wraSetFlavor)(void*, unsigned long);
  110.     void          (WINAPI *wraSetDLLAccessPath)(char*);
  111.     void          (WINAPI *wraSetPwd)(char*, char*);
  112. };
  113. /* linux dlls doesn't need packing */
  114. typedef struct /*__attribute__((__packed__))*/ {
  115.     int samplerate;
  116.     short bits;
  117.     short channels;
  118.     short quality;
  119.     /* 2bytes padding here, by gcc */
  120.     int bits_per_frame;
  121.     int packetsize;
  122.     int extradata_len;
  123.     void* extradata;
  124. } ra_init_t;
  125. /* windows dlls need packed structs (no padding) */
  126. typedef struct __attribute__((__packed__)) {
  127.     int samplerate;
  128.     short bits;
  129.     short channels;
  130.     short quality;
  131.     int bits_per_frame;
  132.     int packetsize;
  133.     int extradata_len;
  134.     void* extradata;
  135. } wra_init_t;
  136. void *__builtin_new(unsigned long size) {return malloc(size);}
  137. void __builtin_delete(void *p) {free(p);}
  138. static const int pi_channels_maps[7] =
  139. {
  140.     0,
  141.     AOUT_CHAN_CENTER,
  142.     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
  143.     AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
  144.     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
  145.      | AOUT_CHAN_REARRIGHT,
  146.     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
  147.      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
  148.     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
  149.      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE
  150. };
  151. /*****************************************************************************
  152.  * Open: probe the decoder and return score
  153.  *****************************************************************************
  154.  * Tries to launch a decoder and return score so that the interface is able
  155.  * to choose.
  156.  *****************************************************************************/
  157. static int Open( vlc_object_t *p_this )
  158. {
  159.     decoder_t *p_dec = (decoder_t*)p_this;
  160.     decoder_sys_t *p_sys = p_dec->p_sys;
  161.     switch( p_dec->fmt_in.i_codec )
  162.     {
  163.     case VLC_FOURCC('c','o','o','k'):
  164.     case VLC_FOURCC('a','t','r','c'):
  165.     case VLC_FOURCC('s','i','p','r'):
  166.         break;
  167.     default:
  168.         return VLC_EGENERIC;
  169.     }
  170.     /* Channel detection */
  171.     if( p_dec->fmt_in.audio.i_channels <= 0 ||
  172.         p_dec->fmt_in.audio.i_channels > 6 )
  173.     {
  174.         msg_Err( p_dec, "invalid number of channels (not between 1 and 6): %i",
  175.                  p_dec->fmt_in.audio.i_channels );
  176.         return VLC_EGENERIC;
  177.     }
  178.     p_dec->p_sys = p_sys = calloc( 1, sizeof( *p_sys ) );
  179.     if( !p_sys )
  180.         return VLC_ENOMEM;
  181.     /* Flavor for SIPR codecs */
  182.     p_sys->i_codec_flavor = -1;
  183.     if( p_dec->fmt_in.i_codec == VLC_FOURCC('s','i','p','r') )
  184.     {
  185.         p_sys->i_codec_flavor = p_dec->fmt_in.audio.i_flavor;
  186.         msg_Dbg( p_dec, "Got sipr flavor %d", p_sys->i_codec_flavor );
  187.     }
  188.     if( OpenDll( p_dec ) != VLC_SUCCESS )
  189.     {
  190.         free( p_sys );
  191.         return VLC_EGENERIC;
  192.     }
  193. #ifdef LOADER
  194.     if( p_sys->win32_dll ) Close( p_this );
  195. #endif
  196.     es_format_Init( &p_dec->fmt_out, AUDIO_ES, AOUT_FMT_S16_NE );
  197.     p_dec->fmt_out.audio.i_rate = p_dec->fmt_in.audio.i_rate;
  198.     p_dec->fmt_out.audio.i_channels = p_dec->fmt_in.audio.i_channels;
  199.     p_dec->fmt_out.audio.i_bitspersample =
  200.         p_dec->fmt_in.audio.i_bitspersample;
  201.     p_dec->fmt_out.audio.i_physical_channels =
  202.     p_dec->fmt_out.audio.i_original_channels =
  203.         pi_channels_maps[p_dec->fmt_out.audio.i_channels];
  204.     aout_DateInit( &p_sys->end_date, p_dec->fmt_out.audio.i_rate );
  205.     aout_DateSet( &p_sys->end_date, 0 );
  206.     p_dec->pf_decode_audio = Decode;
  207.     p_sys->p_out = malloc( 4096 * 10 );
  208.     if( !p_sys->p_out )
  209.     {
  210.         free( p_sys );
  211.         return VLC_ENOMEM;
  212.     }
  213.     p_sys->i_out = 0;
  214.     return VLC_SUCCESS;
  215. }
  216. /*****************************************************************************
  217.  * Close:
  218.  *****************************************************************************/
  219. static void Close( vlc_object_t *p_this )
  220. {
  221.     decoder_t *p_dec = (decoder_t*)p_this;
  222.     CloseDll( p_dec );
  223.     free( p_dec->p_sys->p_out );
  224.     free( p_dec->p_sys );
  225. }
  226. /*****************************************************************************
  227.  * OpenDll:
  228.  *****************************************************************************/
  229. static int OpenDll( decoder_t *p_dec )
  230. {
  231.     char *psz_dll;
  232.     int i, i_result;
  233.     /** Find the good path for the dlls.**/
  234.     char *ppsz_path[] =
  235.     {
  236.       ".",
  237. #ifndef WIN32
  238.       "/usr/local/RealPlayer8/Codecs",
  239.       "/usr/RealPlayer8/Codecs",
  240.       "/usr/lib/RealPlayer8/Codecs",
  241.       "/opt/RealPlayer8/Codecs",
  242.       "/usr/lib/RealPlayer9/users/Real/Codecs",
  243.       "/usr/lib/RealPlayer10/codecs",
  244.       "/usr/lib/RealPlayer10GOLD/codecs",
  245.       "/usr/lib/helix/player/codecs",
  246.       "/usr/lib64/RealPlayer8/Codecs",
  247.       "/usr/lib64/RealPlayer9/users/Real/Codecs",
  248.       "/usr/lib64/RealPlayer10/codecs",
  249.       "/usr/lib64/RealPlayer10GOLD/codecs",
  250.       "/usr/lib/win32",
  251.       "/usr/lib/codecs",
  252.       "/usr/local/lib/codecs",
  253. #endif
  254.       NULL,
  255.       NULL,
  256.       NULL
  257.     };
  258. #ifdef WIN32
  259.     char psz_win32_real_codecs[MAX_PATH + 1];
  260.     char psz_win32_helix_codecs[MAX_PATH + 1];
  261.     {
  262.         HKEY h_key;
  263.         DWORD i_type, i_data = MAX_PATH + 1, i_index = 1;
  264.         char *p_data;
  265.         p_data = psz_win32_real_codecs;
  266.         if( RegOpenKeyEx( HKEY_CLASSES_ROOT,
  267.                           _T("Software\RealNetworks\Preferences\DT_Codecs"),
  268.                           0, KEY_READ, &h_key ) == ERROR_SUCCESS )
  269.         {
  270.              if( RegQueryValueEx( h_key, _T(""), 0, &i_type,
  271.                                   (LPBYTE)p_data, &i_data ) == ERROR_SUCCESS &&
  272.                  i_type == REG_SZ )
  273.              {
  274.                  int i_len = strlen( p_data );
  275.                  if( i_len && p_data[i_len-1] == '\' ) p_data[i_len-1] = 0;
  276.                  ppsz_path[i_index++] = p_data;
  277.                  msg_Err( p_dec, "Real: %s", p_data );
  278.              }
  279.              RegCloseKey( h_key );
  280.         }
  281.         p_data = psz_win32_helix_codecs;
  282.         if( RegOpenKeyEx( HKEY_CLASSES_ROOT,
  283.                           _T("Helix\HelixSDK\10.0\Preferences\DT_Codecs"),
  284.                           0, KEY_READ, &h_key ) == ERROR_SUCCESS )
  285.         {
  286.              if( RegQueryValueEx( h_key, _T(""), 0, &i_type,
  287.                                   (LPBYTE)p_data, &i_data ) == ERROR_SUCCESS &&
  288.                  i_type == REG_SZ )
  289.              {
  290.                  int i_len = strlen( p_data );
  291.                  if( i_len && p_data[i_len-1] == '\' ) p_data[i_len-1] = 0;
  292.                  ppsz_path[i_index++] = p_data;
  293.                  msg_Err( p_dec, "Real: %s", p_data );
  294.              }
  295.              RegCloseKey( h_key );
  296.         }
  297.     }
  298. #endif
  299.     /** Try the native libraries first **/
  300. #ifndef WIN32
  301.     for( i = 0; ppsz_path[i]; i++ )
  302.     {
  303.         /* Old format */
  304.         if( asprintf( &psz_dll, "%s/%4.4s.so.6.0", ppsz_path[i],
  305.                   (char *)&p_dec->fmt_in.i_codec ) != -1 )
  306.         {
  307.             i_result = OpenNativeDll( p_dec, ppsz_path[i], psz_dll );
  308.             free( psz_dll );
  309.             if( i_result == VLC_SUCCESS ) return VLC_SUCCESS;
  310.         }
  311.         /* New format */
  312.         if( asprintf( &psz_dll, "%s/%4.4s.so", ppsz_path[i],
  313.                   (char *)&p_dec->fmt_in.i_codec ) != -1 )
  314.         {
  315.             i_result = OpenNativeDll( p_dec, ppsz_path[i], psz_dll );
  316.             free( psz_dll );
  317.             if( i_result == VLC_SUCCESS ) return VLC_SUCCESS;
  318.         }
  319.     }
  320. #endif
  321.     /** Or use the WIN32 dlls **/
  322. #if defined(LOADER) || defined(WIN32)
  323.     for( i = 0; ppsz_path[i]; i++ )
  324.     {
  325.         /* New format */
  326.         if( asprintf( &psz_dll, "%s\%4.4s.dll", ppsz_path[i],
  327.                   (char *)&p_dec->fmt_in.i_codec ) != -1 )
  328.         {
  329.             i_result = OpenWin32Dll( p_dec, ppsz_path[i], psz_dll );
  330.             free( psz_dll );
  331.             if( i_result == VLC_SUCCESS ) return VLC_SUCCESS;
  332.         }
  333.         /* Old format */
  334.         if( asprintf( &psz_dll, "%s\%4.4s3260.dll", ppsz_path[i],
  335.                   (char *)&p_dec->fmt_in.i_codec ) != -1 )
  336.         {
  337.             i_result = OpenWin32Dll( p_dec, ppsz_path[i], psz_dll );
  338.             free( psz_dll );
  339.             if( i_result == VLC_SUCCESS ) return VLC_SUCCESS;
  340.         }
  341.     }
  342. #endif
  343.     return VLC_EGENERIC;
  344. }
  345. static int OpenNativeDll( decoder_t *p_dec, char *psz_path, char *psz_dll )
  346. {
  347. #if defined(HAVE_DL_DLOPEN)
  348.     decoder_sys_t *p_sys = p_dec->p_sys;
  349.     void *handle = 0, *context = 0;
  350.     unsigned int i_result;
  351.     void *p_prop;
  352.     int i_prop;
  353.     ra_init_t init_data =
  354.     {
  355.         p_dec->fmt_in.audio.i_rate,
  356.         p_dec->fmt_in.audio.i_bitspersample,
  357.         p_dec->fmt_in.audio.i_channels,
  358.         100, /* quality */
  359.         p_dec->fmt_in.audio.i_blockalign, /* subpacket size */
  360.         p_dec->fmt_in.audio.i_blockalign, /* coded frame size */
  361.         p_dec->fmt_in.i_extra, p_dec->fmt_in.p_extra
  362.     };
  363.     msg_Dbg( p_dec, "opening library '%s'", psz_dll );
  364.     if( !(handle = dlopen( psz_dll, RTLD_LAZY )) )
  365.     {
  366.         msg_Dbg( p_dec, "couldn't load library '%s' (%s)",
  367.                  psz_dll, dlerror() );
  368.         return VLC_EGENERIC;
  369.     }
  370.     p_sys->raCloseCodec = dlsym( handle, "RACloseCodec" );
  371.     p_sys->raDecode = dlsym( handle, "RADecode" );
  372.     p_sys->raFlush = dlsym( handle, "RAFlush" );
  373.     p_sys->raFreeDecoder = dlsym( handle, "RAFreeDecoder" );
  374.     p_sys->raGetFlavorProperty = dlsym( handle, "RAGetFlavorProperty" );
  375.     p_sys->raOpenCodec = dlsym( handle, "RAOpenCodec" );
  376.     p_sys->raOpenCodec2 = dlsym( handle, "RAOpenCodec2" );
  377.     p_sys->raInitDecoder = dlsym( handle, "RAInitDecoder" );
  378.     p_sys->raSetFlavor = dlsym( handle, "RASetFlavor" );
  379.     p_sys->raSetDLLAccessPath = dlsym( handle, "SetDLLAccessPath" );
  380.     p_sys->raSetPwd = dlsym( handle, "RASetPwd" ); // optional, used by SIPR
  381.     if( !(p_sys->raOpenCodec || p_sys->raOpenCodec2) ||
  382.         !p_sys->raCloseCodec || !p_sys->raInitDecoder ||
  383.         !p_sys->raDecode || !p_sys->raFreeDecoder ||
  384.         !p_sys->raGetFlavorProperty || !p_sys->raSetFlavor
  385.         /* || !p_sys->raFlush || !p_sys->raSetDLLAccessPath */ )
  386.     {
  387.         goto error_native;
  388.     }
  389.     if( p_sys->raOpenCodec2 )
  390.         i_result = p_sys->raOpenCodec2( &context, psz_path );
  391.     else
  392.         i_result = p_sys->raOpenCodec( &context );
  393.     if( i_result )
  394.     {
  395.         msg_Err( p_dec, "decoder open failed, error code: 0x%x", i_result );
  396.         goto error_native;
  397.     }
  398.     i_result = p_sys->raInitDecoder( context, &init_data );
  399.     if( i_result )
  400.     {
  401.         msg_Err( p_dec, "decoder init failed, error code: 0x%x", i_result );
  402.         goto error_native;
  403.     }
  404.     if( p_sys->i_codec_flavor >= 0 )
  405.     {
  406.         i_result = p_sys->raSetFlavor( context, p_sys->i_codec_flavor );
  407.         if( i_result )
  408.         {
  409.             msg_Err( p_dec, "decoder flavor setup failed, error code: 0x%x",
  410.                      i_result );
  411.             goto error_native;
  412.         }
  413.         p_prop = p_sys->raGetFlavorProperty( context, p_sys->i_codec_flavor,
  414.                                              0, &i_prop );
  415.         msg_Dbg( p_dec, "audio codec: [%d] %s",
  416.                  p_sys->i_codec_flavor, (char *)p_prop );
  417.         p_prop = p_sys->raGetFlavorProperty( context, p_sys->i_codec_flavor,
  418.                                              1, &i_prop );
  419.         if( p_prop )
  420.         {
  421.             int i_bps = ((*((int*)p_prop))+4)/8;
  422.             msg_Dbg( p_dec, "audio bitrate: %5.3f kbit/s (%d bps)",
  423.                      (*((int*)p_prop))*0.001f, i_bps );
  424.         }
  425.     }
  426.     p_sys->context = context;
  427.     p_sys->dll = handle;
  428.     return VLC_SUCCESS;
  429.  error_native:
  430.     if( context ) p_sys->raFreeDecoder( context );
  431.     if( context ) p_sys->raCloseCodec( context );
  432.     dlclose( handle );
  433. #endif
  434.     return VLC_EGENERIC;
  435. }
  436. static int OpenWin32Dll( decoder_t *p_dec, char *psz_path, char *psz_dll )
  437. {
  438. #if defined(LOADER) || defined(WIN32)
  439.     decoder_sys_t *p_sys = p_dec->p_sys;
  440.     void *handle = 0, *context = 0;
  441.     unsigned int i_result;
  442.     void *p_prop;
  443.     int i_prop;
  444.     wra_init_t init_data =
  445.     {
  446.         p_dec->fmt_in.audio.i_rate,
  447.         p_dec->fmt_in.audio.i_bitspersample,
  448.         p_dec->fmt_in.audio.i_channels,
  449.         100, /* quality */
  450.         p_dec->fmt_in.audio.i_blockalign, /* subpacket size */
  451.         p_dec->fmt_in.audio.i_blockalign, /* coded frame size */
  452.         p_dec->fmt_in.i_extra, p_dec->fmt_in.p_extra
  453.     };
  454.     msg_Dbg( p_dec, "opening win32 dll '%s'", psz_dll );
  455. #ifdef LOADER
  456.     Setup_LDT_Keeper();
  457. #endif
  458.     if( !(handle = LoadLibraryA( psz_dll )) )
  459.     {
  460.         msg_Dbg( p_dec, "couldn't load dll '%s'", psz_dll );
  461.         return VLC_EGENERIC;
  462.     }
  463.     p_sys->wraCloseCodec = GetProcAddress( handle, "RACloseCodec" );
  464.     p_sys->wraDecode = GetProcAddress( handle, "RADecode" );
  465.     p_sys->wraFlush = GetProcAddress( handle, "RAFlush" );
  466.     p_sys->wraFreeDecoder = GetProcAddress( handle, "RAFreeDecoder" );
  467.     p_sys->wraGetFlavorProperty =
  468.         GetProcAddress( handle, "RAGetFlavorProperty" );
  469.     p_sys->wraOpenCodec = GetProcAddress( handle, "RAOpenCodec" );
  470.     p_sys->wraOpenCodec2 = GetProcAddress( handle, "RAOpenCodec2" );
  471.     p_sys->wraInitDecoder = GetProcAddress( handle, "RAInitDecoder" );
  472.     p_sys->wraSetFlavor = GetProcAddress( handle, "RASetFlavor" );
  473.     p_sys->wraSetDLLAccessPath = GetProcAddress( handle, "SetDLLAccessPath" );
  474.     p_sys->wraSetPwd =
  475.         GetProcAddress( handle, "RASetPwd" ); // optional, used by SIPR
  476.     if( !(p_sys->wraOpenCodec || p_sys->wraOpenCodec2) ||
  477.         !p_sys->wraCloseCodec || !p_sys->wraInitDecoder ||
  478.         !p_sys->wraDecode || !p_sys->wraFreeDecoder ||
  479.         !p_sys->wraGetFlavorProperty || !p_sys->wraSetFlavor
  480.         /* || !p_sys->wraFlush || !p_sys->wraSetDLLAccessPath */ )
  481.     {
  482.         FreeLibrary( handle );
  483.         return VLC_EGENERIC;
  484.     }
  485.     if( p_sys->wraOpenCodec2 )
  486.         i_result = p_sys->wraOpenCodec2( &context, psz_path );
  487.     else
  488.         i_result = p_sys->wraOpenCodec( &context );
  489.     if( i_result )
  490.     {
  491.         msg_Err( p_dec, "decoder open failed, error code: 0x%x", i_result );
  492.         goto error_win32;
  493.     }
  494.     i_result = p_sys->wraInitDecoder( context, &init_data );
  495.     if( i_result )
  496.     {
  497.         msg_Err( p_dec, "decoder init failed, error code: 0x%x", i_result );
  498.         goto error_win32;
  499.     }
  500.     if( p_sys->i_codec_flavor >= 0 )
  501.     {
  502.         i_result = p_sys->wraSetFlavor( context, p_sys->i_codec_flavor );
  503.         if( i_result )
  504.         {
  505.             msg_Err( p_dec, "decoder flavor setup failed, error code: 0x%x",
  506.                      i_result );
  507.             goto error_win32;
  508.         }
  509.         p_prop = p_sys->wraGetFlavorProperty( context, p_sys->i_codec_flavor,
  510.                                               0, &i_prop );
  511.         msg_Dbg( p_dec, "audio codec: [%d] %s",
  512.                  p_sys->i_codec_flavor, (char *)p_prop );
  513.         p_prop = p_sys->wraGetFlavorProperty( context, p_sys->i_codec_flavor,
  514.                                               1, &i_prop );
  515.         if( p_prop )
  516.         {
  517.             int i_bps = ((*((int*)p_prop))+4)/8;
  518.             msg_Dbg( p_dec, "audio bitrate: %5.3f kbit/s (%d bps)",
  519.                      (*((int*)p_prop))*0.001f, i_bps );
  520.         }
  521.     }
  522.     p_sys->context = context;
  523.     p_sys->win32_dll = handle;
  524.     return VLC_SUCCESS;
  525.  error_win32:
  526.     if( context ) p_sys->wraFreeDecoder( context );
  527.     if( context ) p_sys->wraCloseCodec( context );
  528.     FreeLibrary( handle );
  529. #endif
  530.     return VLC_EGENERIC;
  531. }
  532. /*****************************************************************************
  533.  * CloseDll:
  534.  *****************************************************************************/
  535. static void CloseDll( decoder_t *p_dec )
  536. {
  537.     decoder_sys_t *p_sys = p_dec->p_sys;
  538.     if( p_sys->context && p_sys->dll )
  539.     {
  540.         p_sys->raFreeDecoder( p_sys->context );
  541.         p_sys->raCloseCodec( p_sys->context );
  542.     }
  543.     if( p_sys->context && p_sys->win32_dll )
  544.     {
  545.         p_sys->wraFreeDecoder( p_sys->context );
  546.         p_sys->wraCloseCodec( p_sys->context );
  547.     }
  548. #if defined(HAVE_DL_DLOPEN)
  549.     if( p_sys->dll ) dlclose( p_sys->dll );
  550. #endif
  551. #if defined(LOADER) || defined(WIN32)
  552.     if( p_sys->win32_dll ) FreeLibrary( p_sys->win32_dll );
  553. #if 0 //def LOADER /* Segfaults */
  554.     Restore_LDT_Keeper( p_sys->ldt_fs );
  555.     msg_Dbg( p_dec, "Restore_LDT_Keeper" );
  556. #endif
  557. #endif
  558.     p_sys->dll = 0;
  559.     p_sys->win32_dll = 0;
  560.     p_sys->context = 0;
  561. }
  562. /*****************************************************************************
  563.  * DecodeAudio:
  564.  *****************************************************************************/
  565. static aout_buffer_t *Decode( decoder_t *p_dec, block_t **pp_block )
  566. {
  567.     decoder_sys_t *p_sys = p_dec->p_sys;
  568.     aout_buffer_t *p_aout_buffer = 0;
  569.     unsigned int i_result;
  570.     int i_samples;
  571.     block_t *p_block;
  572. #ifdef LOADER
  573.     if( !p_sys->win32_dll && !p_sys->dll )
  574.     {
  575.         /* We must do open and close in the same thread (unless we do
  576.          * Setup_LDT_Keeper in the main thread before all others */
  577.         if( OpenDll( p_dec ) != VLC_SUCCESS )
  578.         {
  579.             /* Fatal */
  580.             p_dec->b_error = true;
  581.             return NULL;
  582.         }
  583.     }
  584. #endif
  585.     if( pp_block == NULL || *pp_block == NULL ) return NULL;
  586.     p_block = *pp_block;
  587.     if( p_sys->dll )
  588.         i_result = p_sys->raDecode( p_sys->context, (char *)p_block->p_buffer,
  589.                                     (unsigned long)p_block->i_buffer,
  590.                                     p_sys->p_out, &p_sys->i_out, -1 );
  591.     else
  592.         i_result = p_sys->wraDecode( p_sys->context, (char *)p_block->p_buffer,
  593.                                      (unsigned long)p_block->i_buffer,
  594.                                      p_sys->p_out, &p_sys->i_out, -1 );
  595. #if 0
  596.     msg_Err( p_dec, "decoded: %i samples (%i)",
  597.              p_sys->i_out * 8 / p_dec->fmt_out.audio.i_bitspersample /
  598.              p_dec->fmt_out.audio.i_channels, i_result );
  599. #endif
  600.     /* Date management */
  601.     if( p_block->i_pts > 0 &&
  602.         p_block->i_pts != aout_DateGet( &p_sys->end_date ) )
  603.     {
  604.         aout_DateSet( &p_sys->end_date, p_block->i_pts );
  605.     }
  606.     if( !aout_DateGet( &p_sys->end_date ) )
  607.     {
  608.         /* We've just started the stream, wait for the first PTS. */
  609.         if( p_block ) block_Release( p_block );
  610.         return NULL;
  611.     }
  612.     i_samples = p_sys->i_out * 8 /
  613.         p_dec->fmt_out.audio.i_bitspersample /p_dec->fmt_out.audio.i_channels;
  614.     p_aout_buffer =
  615.         decoder_NewAudioBuffer( p_dec, i_samples );
  616.     if( p_aout_buffer )
  617.     {
  618.         memcpy( p_aout_buffer->p_buffer, p_sys->p_out, p_sys->i_out );
  619.         /* Date management */
  620.         p_aout_buffer->start_date = aout_DateGet( &p_sys->end_date );
  621.         p_aout_buffer->end_date =
  622.             aout_DateIncrement( &p_sys->end_date, i_samples );
  623.     }
  624.     block_Release( p_block );
  625.     *pp_block = 0;
  626.     return p_aout_buffer;
  627. }