00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
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)
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
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
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
00083 char *p_out;
00084 unsigned int i_out;
00085
00086
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
00127 typedef struct {
00128 int samplerate;
00129 short bits;
00130 short channels;
00131 short quality;
00132
00133 int bits_per_frame;
00134 int packetsize;
00135 int extradata_len;
00136 void* extradata;
00137 } ra_init_t;
00138
00139
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
00170
00171
00172
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
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
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
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
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,
00363 p_dec->fmt_in.audio.i_blockalign,
00364 p_dec->fmt_in.audio.i_blockalign,
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" );
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 )
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,
00468 p_dec->fmt_in.audio.i_blockalign,
00469 p_dec->fmt_in.audio.i_blockalign,
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" );
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 )
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
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
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
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
00617
00618 if( OpenDll( p_dec ) != VLC_SUCCESS )
00619 {
00620
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
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
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
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 }