ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

optimize.c
Go to the documentation of this file.
00001 /*
00002     optimize: get a grip on the different optimizations
00003 
00004     copyright 2006-9 by the mpg123 project - free software under the terms of the LGPL 2.1
00005     see COPYING and AUTHORS files in distribution or http://mpg123.org
00006     initially written by Thomas Orgis, inspired by 3DNow stuff in mpg123.[hc]
00007 
00008     Currently, this file contains the struct and function to choose an optimization variant and works only when OPT_MULTI is in effect.
00009 */
00010 
00011 #include "mpg123lib_intern.h" /* includes optimize.h */
00012 #include "debug.h"
00013 
00014 /* Must match the enum dectype! */
00015 
00016 /*
00017     It SUCKS having to define these names that way, but compile-time intialization of string arrays is a bitch.
00018     GCC doesn't see constant stuff when it's wiggling in front of it!
00019     Anyhow: Have a script for that:
00020 names="generic generic_dither i386 i486 i586 i586_dither MMX 3DNow 3DNowExt AltiVec SSE x86-64"
00021 for i in $names; do echo "##define dn_${i/-/_} \"$i\""; done
00022 echo -n "static const char* decname[] =
00023 {
00024     \"auto\"
00025     "
00026 for i in $names; do echo -n ", dn_${i/-/_}"; done
00027 echo "
00028     , \"nodec\"
00029 };"
00030 */
00031 #define dn_generic "generic"
00032 #define dn_generic_dither "generic_dither"
00033 #define dn_i386 "i386"
00034 #define dn_i486 "i486"
00035 #define dn_i586 "i586"
00036 #define dn_i586_dither "i586_dither"
00037 #define dn_MMX "MMX"
00038 #define dn_3DNow "3DNow"
00039 #define dn_3DNowExt "3DNowExt"
00040 #define dn_AltiVec "AltiVec"
00041 #define dn_SSE "SSE"
00042 #define dn_x86_64 "x86-64"
00043 #define dn_ARM "ARM"
00044 static const char* decname[] =
00045 {
00046     "auto"
00047     , dn_generic, dn_generic_dither, dn_i386, dn_i486, dn_i586, dn_i586_dither, dn_MMX, dn_3DNow, dn_3DNowExt, dn_AltiVec, dn_SSE, dn_x86_64, dn_ARM
00048     , "nodec"
00049 };
00050 
00051 #if (defined OPT_X86) && (defined OPT_MULTI)
00052 #include "getcpuflags.h"
00053 struct cpuflags cpu_flags;
00054 #else
00055 /* Faking stuff for non-multi builds. The same code for synth function choice is used.
00056    Just no runtime dependency of result... */
00057 char cpu_flags;
00058 #define cpu_i586(s)     1
00059 #define cpu_fpu(s)      1
00060 #define cpu_mmx(s)      1
00061 #define cpu_3dnow(s)    1
00062 #define cpu_3dnowext(s) 1
00063 #define cpu_sse(s)      1
00064 #define cpu_sse2(s)     1
00065 #define cpu_sse3(s)     1
00066 #endif
00067 
00068 /* Ugly macros to build conditional synth function array values. */
00069 
00070 #ifndef NO_8BIT
00071 #define IF8(synth) synth,
00072 #else
00073 #define IF8(synth)
00074 #endif
00075 
00076 #ifndef NO_REAL
00077 #define IFREAL(synth) synth,
00078 #else
00079 #define IFREAL(synth)
00080 #endif
00081 
00082 #ifndef NO_32BIT
00083 #define IF32(synth) synth
00084 #else
00085 #define IF32(synth)
00086 #endif
00087 
00088 #ifndef NO_16BIT
00089 #   define OUT_SYNTHS(synth_16, synth_8, synth_real, synth_32) { synth_16, IF8(synth_8) IFREAL(synth_real) IF32(synth_32) }
00090 #else
00091 #   define OUT_SYNTHS(synth_16, synth_8, synth_real, synth_32) { IF8(synth_8) IFREAL(synth_real) IF32(synth_32) }
00092 #endif
00093 
00094 /* The call of left and right plain synth, wrapped.
00095    This may be replaced by a direct stereo optimized synth. */
00096 int synth_stereo_wrap(real *bandPtr_l, real *bandPtr_r, mpg123_handle *fr)
00097 {
00098     int clip;
00099     clip  = (fr->synth)(bandPtr_l, 0, fr, 0);
00100     clip += (fr->synth)(bandPtr_r, 1, fr, 1);
00101     return clip;
00102 }
00103 
00104 const struct synth_s synth_base =
00105 {
00106     { /* plain */
00107          OUT_SYNTHS(synth_1to1, synth_1to1_8bit, synth_1to1_real, synth_1to1_s32)
00108 #       ifndef NO_DOWNSAMPLE
00109         ,OUT_SYNTHS(synth_2to1, synth_2to1_8bit, synth_2to1_real, synth_2to1_s32)
00110         ,OUT_SYNTHS(synth_4to1, synth_4to1_8bit, synth_4to1_real, synth_4to1_s32)
00111 #       endif
00112 #       ifndef NO_NTOM
00113         ,OUT_SYNTHS(synth_ntom, synth_ntom_8bit, synth_ntom_real, synth_ntom_s32)
00114 #       endif
00115     },
00116     { /* stereo, by default only wrappers over plain synth */
00117          OUT_SYNTHS(synth_stereo_wrap, synth_stereo_wrap, synth_stereo_wrap, synth_stereo_wrap)
00118 #       ifndef NO_DOWNSAMPLE
00119         ,OUT_SYNTHS(synth_stereo_wrap, synth_stereo_wrap, synth_stereo_wrap, synth_stereo_wrap)
00120         ,OUT_SYNTHS(synth_stereo_wrap, synth_stereo_wrap, synth_stereo_wrap, synth_stereo_wrap)
00121 #       endif
00122 #       ifndef NO_NTOM
00123         ,OUT_SYNTHS(synth_stereo_wrap, synth_stereo_wrap, synth_stereo_wrap, synth_stereo_wrap)
00124 #       endif
00125     },
00126     { /* mono2stereo */
00127          OUT_SYNTHS(synth_1to1_mono2stereo, synth_1to1_8bit_mono2stereo, synth_1to1_real_mono2stereo, synth_1to1_s32_mono2stereo)
00128 #       ifndef NO_DOWNSAMPLE
00129         ,OUT_SYNTHS(synth_2to1_mono2stereo, synth_2to1_8bit_mono2stereo, synth_2to1_real_mono2stereo, synth_2to1_s32_mono2stereo)
00130         ,OUT_SYNTHS(synth_4to1_mono2stereo, synth_4to1_8bit_mono2stereo, synth_4to1_real_mono2stereo, synth_4to1_s32_mono2stereo)
00131 #       endif
00132 #       ifndef NO_NTOM
00133         ,OUT_SYNTHS(synth_ntom_mono2stereo, synth_ntom_8bit_mono2stereo, synth_ntom_real_mono2stereo, synth_ntom_s32_mono2stereo)
00134 #       endif
00135     },
00136     { /* mono*/
00137          OUT_SYNTHS(synth_1to1_mono, synth_1to1_8bit_mono, synth_1to1_real_mono, synth_1to1_s32_mono)
00138 #       ifndef NO_DOWNSAMPLE
00139         ,OUT_SYNTHS(synth_2to1_mono, synth_2to1_8bit_mono, synth_2to1_real_mono, synth_2to1_s32_mono)
00140         ,OUT_SYNTHS(synth_4to1_mono, synth_4to1_8bit_mono, synth_4to1_real_mono, synth_4to1_s32_mono)
00141 #       endif
00142 #       ifndef NO_NTOM
00143         ,OUT_SYNTHS(synth_ntom_mono, synth_ntom_8bit_mono, synth_ntom_real_mono, synth_ntom_s32_mono)
00144 #endif
00145     }
00146 };
00147 
00148 #ifdef OPT_X86
00149 /* More plain synths for i386 */
00150 const func_synth plain_i386[r_limit][f_limit] =
00151 { /* plain */
00152      OUT_SYNTHS(synth_1to1_i386, synth_1to1_8bit_i386, synth_1to1_real_i386, synth_1to1_s32_i386)
00153 #   ifndef NO_DOWNSAMPLE
00154     ,OUT_SYNTHS(synth_2to1_i386, synth_2to1_8bit_i386, synth_2to1_real_i386, synth_2to1_s32_i386)
00155     ,OUT_SYNTHS(synth_4to1_i386, synth_4to1_8bit_i386, synth_4to1_real_i386, synth_4to1_s32_i386)
00156 #   endif
00157 #   ifndef NO_NTOM
00158     ,OUT_SYNTHS(synth_ntom, synth_ntom_8bit, synth_ntom_real, synth_ntom_s32)
00159 #   endif
00160 };
00161 #endif
00162 
00163 
00164 enum optdec defdec(void){ return defopt; }
00165 
00166 enum optcla decclass(const enum optdec type)
00167 {
00168     return (type == mmx || type == sse || type == dreidnowext || type == x86_64 ) ? mmxsse : normal;
00169 }
00170 
00171 
00172 static int find_synth(func_synth synth,  const func_synth synths[r_limit][f_limit])
00173 {
00174     enum synth_resample ri;
00175     enum synth_format   fi;
00176     for(ri=0; ri<r_limit; ++ri)
00177     for(fi=0; fi<f_limit; ++fi)
00178     if(synth == synths[ri][fi])
00179     return TRUE;
00180 
00181     return FALSE;
00182 }
00183 
00184 /* Determine what kind of decoder is actually active
00185    This depends on runtime choices which may cause fallback to i386 or generic code. */
00186 static int find_dectype(mpg123_handle *fr)
00187 {
00188     enum optdec type = nodec;
00189     /* Direct and indirect usage, 1to1 stereo decoding.
00190        Concentrating on the plain stereo synth should be fine, mono stuff is derived. */
00191     func_synth basic_synth = fr->synth;
00192 #ifndef NO_8BIT
00193 #ifndef NO_16BIT
00194     if(basic_synth == synth_1to1_8bit_wrap)
00195     basic_synth = fr->synths.plain[r_1to1][f_16]; /* That is what's really below the surface. */
00196 #endif
00197 #endif
00198 
00199     if(FALSE) ; /* Just to initialize the else if ladder. */
00200 #ifndef NO_16BIT
00201 #ifdef OPT_3DNOWEXT
00202     else if(basic_synth == synth_1to1_3dnowext) type = dreidnowext;
00203 #endif
00204 #ifdef OPT_SSE
00205     else if(basic_synth == synth_1to1_sse) type = sse;
00206 #endif
00207 #ifdef OPT_3DNOW
00208     else if(basic_synth == synth_1to1_3dnow) type = dreidnow;
00209 #endif
00210 #ifdef OPT_MMX
00211     else if(basic_synth == synth_1to1_mmx) type = mmx;
00212 #endif
00213 #ifdef OPT_I586_DITHER
00214     else if(basic_synth == synth_1to1_i586_dither) type = ifuenf_dither;
00215 #endif
00216 #ifdef OPT_I586
00217     else if(basic_synth == synth_1to1_i586) type = ifuenf;
00218 #endif
00219 #ifdef OPT_ALTIVEC
00220     else if(basic_synth == synth_1to1_altivec) type = altivec;
00221 #endif
00222 #ifdef OPT_X86_64
00223     else if(basic_synth == synth_1to1_x86_64) type = x86_64;
00224 #endif
00225 #ifdef OPT_ARM
00226     else if(basic_synth == synth_1to1_arm) type = arm;
00227 #endif
00228 #ifdef OPT_GENERIC_DITHER
00229     else if(basic_synth == synth_1to1_dither) type = generic_dither;
00230 #endif
00231 #ifdef OPT_DITHER /* either i586 or generic! */
00232 #ifndef NO_DOWNSAMPLE
00233     else if
00234     (
00235            basic_synth == synth_2to1_dither
00236         || basic_synth == synth_4to1_dither
00237     ) type = generic_dither;
00238 #endif
00239 #endif
00240 #endif /* 16bit */
00241 
00242 #ifndef NO_REAL
00243 #ifdef OPT_SSE
00244     else if(basic_synth == synth_1to1_real_sse) type = sse;
00245 #endif
00246 #ifdef OPT_X86_64
00247     else if(basic_synth == synth_1to1_real_x86_64) type = x86_64;
00248 #endif
00249 #ifdef OPT_ALTIVEC
00250     else if(basic_synth == synth_1to1_real_altivec) type = altivec;
00251 #endif
00252 
00253 #endif /* real */
00254 
00255 #ifndef NO_32BIT
00256 #ifdef OPT_SSE
00257     else if(basic_synth == synth_1to1_s32_sse) type = sse;
00258 #endif
00259 #ifdef OPT_X86_64
00260     else if(basic_synth == synth_1to1_s32_x86_64) type = x86_64;
00261 #endif
00262 #ifdef OPT_ALTIVEC
00263     else if(basic_synth == synth_1to1_s32_altivec) type = altivec;
00264 #endif
00265 #endif /* 32bit */
00266 
00267 #ifdef OPT_X86
00268     else if(find_synth(basic_synth, plain_i386))
00269     type = idrei;
00270 #endif
00271 
00272     else if(find_synth(basic_synth, synth_base.plain))
00273     type = generic;
00274 
00275 
00276 
00277 #ifdef OPT_I486
00278     /* i486 is special ... the specific code is in use for 16bit 1to1 stereo
00279        otherwise we have i386 active... but still, the distinction doesn't matter*/
00280     type = ivier;
00281 #endif
00282 
00283     if(type != nodec)
00284     {
00285         fr->cpu_opts.type = type;
00286         fr->cpu_opts.class = decclass(type);
00287 
00288         debug3("determined active decoder type %i (%s) of class %i", type, decname[type], fr->cpu_opts.class);
00289         return MPG123_OK;
00290     }
00291     else
00292     {
00293         if(NOQUIET) error("Unable to determine active decoder type -- this is SERIOUS b0rkage!");
00294 
00295         fr->err = MPG123_BAD_DECODER_SETUP;
00296         return MPG123_ERR;
00297     }
00298 }
00299 
00300 /* set synth functions for current frame, optimizations handled by opt_* macros */
00301 int set_synth_functions(mpg123_handle *fr)
00302 {
00303     enum synth_resample resample = r_none;
00304     enum synth_format basic_format = f_none; /* Default is always 16bit, or whatever. */
00305 
00306     /* Select the basic output format, different from 16bit: 8bit, real. */
00307     if(FALSE){}
00308 #ifndef NO_16BIT
00309     else if(fr->af.encoding & MPG123_ENC_16)
00310     basic_format = f_16;
00311 #endif
00312 #ifndef NO_8BIT
00313     else if(fr->af.encoding & MPG123_ENC_8)
00314     basic_format = f_8;
00315 #endif
00316 #ifndef NO_REAL
00317     else if(fr->af.encoding & MPG123_ENC_FLOAT)
00318     basic_format = f_real;
00319 #endif
00320 #ifndef NO_32BIT
00321     else if(fr->af.encoding & MPG123_ENC_32)
00322     basic_format = f_32;
00323 #endif
00324 
00325     /* Make sure the chosen format is compiled into this lib. */
00326     if(basic_format == f_none)
00327     {
00328         if(NOQUIET) error("set_synth_functions: This output format is disabled in this build!");
00329 
00330         return -1;
00331     }
00332 
00333     /* Be explicit about downsampling variant. */
00334     switch(fr->down_sample)
00335     {
00336         case 0: resample = r_1to1; break;
00337 #ifndef NO_DOWNSAMPLE
00338         case 1: resample = r_2to1; break;
00339         case 2: resample = r_4to1; break;
00340 #endif
00341 #ifndef NO_NTOM
00342         case 3: resample = r_ntom; break;
00343 #endif
00344     }
00345 
00346     if(resample == r_none)
00347     {
00348         if(NOQUIET) error("set_synth_functions: This resampling mode is not supported in this build!");
00349 
00350         return -1;
00351     }
00352 
00353     debug2("selecting synth: resample=%i format=%i", resample, basic_format);
00354     /* Finally selecting the synth functions for stereo / mono. */
00355     fr->synth = fr->synths.plain[resample][basic_format];
00356     fr->synth_stereo = fr->synths.stereo[resample][basic_format];
00357     fr->synth_mono = fr->af.channels==2
00358         ? fr->synths.mono2stereo[resample][basic_format] /* Mono MPEG file decoded to stereo. */
00359         : fr->synths.mono[resample][basic_format];       /* Mono MPEG file decoded to mono. */
00360 
00361     if(find_dectype(fr) != MPG123_OK) /* Actually determine the currently active decoder breed. */
00362     {
00363         fr->err = MPG123_BAD_DECODER_SETUP;
00364         return MPG123_ERR;
00365     }
00366 
00367     if(frame_buffers(fr) != 0)
00368     {
00369         fr->err = MPG123_NO_BUFFERS;
00370         if(NOQUIET) error("Failed to set up decoder buffers!");
00371 
00372         return MPG123_ERR;
00373     }
00374 
00375 #ifndef NO_8BIT
00376     if(basic_format == f_8)
00377     {
00378         if(make_conv16to8_table(fr) != 0)
00379         {
00380             if(NOQUIET) error("Failed to set up conv16to8 table!");
00381             /* it's a bit more work to get proper error propagation up */
00382             return -1;
00383         }
00384     }
00385 #endif
00386 
00387 #ifdef OPT_MMXORSSE
00388     /* Special treatment for MMX, SSE and 3DNowExt stuff.
00389        The real-decoding SSE for x86-64 uses normal tables! */
00390     if(fr->cpu_opts.class == mmxsse
00391 #   ifndef NO_REAL
00392        && basic_format != f_real
00393 #   endif
00394 #   ifndef NO_32BIT
00395        && basic_format != f_32
00396 #   endif
00397 #   ifdef ACCURATE_ROUNDING
00398        && fr->cpu_opts.type != sse
00399        && fr->cpu_opts.type != x86_64
00400 #   endif
00401       )
00402     {
00403 #ifndef NO_LAYER3
00404         init_layer3_stuff(fr, init_layer3_gainpow2_mmx);
00405 #endif
00406 #ifndef NO_LAYER12
00407         init_layer12_stuff(fr, init_layer12_table_mmx);
00408 #endif
00409         fr->make_decode_tables = make_decode_tables_mmx;
00410     }
00411     else
00412 #endif
00413     {
00414 #ifndef NO_LAYER3
00415         init_layer3_stuff(fr, init_layer3_gainpow2);
00416 #endif
00417 #ifndef NO_LAYER12
00418         init_layer12_stuff(fr, init_layer12_table);
00419 #endif
00420         fr->make_decode_tables = make_decode_tables;
00421     }
00422 
00423     /* We allocated the table buffers just now, so (re)create the tables. */
00424     fr->make_decode_tables(fr);
00425 
00426     return 0;
00427 }
00428 
00429 int frame_cpu_opt(mpg123_handle *fr, const char* cpu)
00430 {
00431     const char* chosen = ""; /* the chosen decoder opt as string */
00432     enum optdec want_dec = nodec;
00433     int done = 0;
00434     int auto_choose = 0;
00435 #ifdef OPT_DITHER
00436     int dithered = FALSE; /* If some dithered decoder is chosen. */
00437 #endif
00438 
00439     want_dec = dectype(cpu);
00440     auto_choose = want_dec == autodec;
00441     /* Fill whole array of synth functions with generic code first. */
00442     fr->synths = synth_base;
00443 
00444 #ifndef OPT_MULTI
00445     {
00446         if(!auto_choose && want_dec != defopt)
00447         {
00448             if(NOQUIET) error2("you wanted decoder type %i, I only have %i", want_dec, defopt);
00449         }
00450         auto_choose = TRUE; /* There will be only one choice anyway. */
00451     }
00452 #endif
00453 
00454     fr->cpu_opts.type = nodec;
00455     /* covers any i386+ cpu; they actually differ only in the synth_1to1 function, mostly... */
00456 #ifdef OPT_X86
00457 
00458 #ifdef OPT_MULTI
00459 #ifndef NO_LAYER3
00460 #if (defined OPT_3DNOW || defined OPT_3DNOWEXT)
00461     fr->cpu_opts.the_dct36 = dct36;
00462 #endif
00463 #endif
00464 #endif
00465 
00466     if(cpu_i586(cpu_flags))
00467     {
00468 #       ifdef OPT_MULTI
00469         debug2("standard flags: 0x%08x\textended flags: 0x%08x", cpu_flags.std, cpu_flags.ext);
00470 #       endif
00471         #ifdef OPT_SSE
00472         if(   !done && (auto_choose || want_dec == sse)
00473            && cpu_sse(cpu_flags) && cpu_mmx(cpu_flags) )
00474         {
00475             chosen = "SSE";
00476             fr->cpu_opts.type = sse;
00477 #           ifndef NO_16BIT
00478             fr->synths.plain[r_1to1][f_16] = synth_1to1_sse;
00479 #           ifdef ACCURATE_ROUNDING
00480             fr->synths.stereo[r_1to1][f_16] = synth_1to1_stereo_sse;
00481 #           endif
00482 #           endif
00483 #           ifndef NO_REAL
00484             fr->synths.plain[r_1to1][f_real] = synth_1to1_real_sse;
00485             fr->synths.stereo[r_1to1][f_real] = synth_1to1_real_stereo_sse;
00486 #           endif
00487 #           ifndef NO_32BIT
00488             fr->synths.plain[r_1to1][f_32] = synth_1to1_s32_sse;
00489             fr->synths.stereo[r_1to1][f_32] = synth_1to1_s32_stereo_sse;
00490 #           endif
00491             done = 1;
00492         }
00493         #endif
00494 #       ifdef OPT_3DNOWEXT
00495         if(   !done && (auto_choose || want_dec == dreidnowext )
00496            && cpu_3dnow(cpu_flags)
00497            && cpu_3dnowext(cpu_flags)
00498            && cpu_mmx(cpu_flags) )
00499         {
00500             chosen = "3DNowExt";
00501             fr->cpu_opts.type = dreidnowext;
00502 #ifdef OPT_MULTI
00503 #           ifndef NO_LAYER3
00504             fr->cpu_opts.the_dct36 = dct36_3dnowext;
00505 #           endif
00506 #endif
00507 #           ifndef NO_16BIT
00508             fr->synths.plain[r_1to1][f_16] = synth_1to1_3dnowext;
00509 #           endif
00510             done = 1;
00511         }
00512         #endif
00513         #ifdef OPT_3DNOW
00514         if(    !done && (auto_choose || want_dec == dreidnow)
00515             && cpu_3dnow(cpu_flags) && cpu_mmx(cpu_flags) )
00516         {
00517             chosen = "3DNow";
00518             fr->cpu_opts.type = dreidnow;
00519 #ifdef OPT_MULTI
00520 #           ifndef NO_LAYER3
00521             fr->cpu_opts.the_dct36 = dct36_3dnow;
00522 #           endif
00523 #endif
00524 #           ifndef NO_16BIT
00525             fr->synths.plain[r_1to1][f_16] = synth_1to1_3dnow;
00526 #           endif
00527             done = 1;
00528         }
00529         #endif
00530         #ifdef OPT_MMX
00531         if(   !done && (auto_choose || want_dec == mmx)
00532            && cpu_mmx(cpu_flags) )
00533         {
00534             chosen = "MMX";
00535             fr->cpu_opts.type = mmx;
00536 #           ifndef NO_16BIT
00537             fr->synths.plain[r_1to1][f_16] = synth_1to1_mmx;
00538 #           endif
00539             done = 1;
00540         }
00541         #endif
00542         #ifdef OPT_I586
00543         if(!done && (auto_choose || want_dec == ifuenf))
00544         {
00545             chosen = "i586/pentium";
00546             fr->cpu_opts.type = ifuenf;
00547 #           ifndef NO_16BIT
00548             fr->synths.plain[r_1to1][f_16] = synth_1to1_i586;
00549 #           endif
00550             done = 1;
00551         }
00552         #endif
00553         #ifdef OPT_I586_DITHER
00554         if(!done && (auto_choose || want_dec == ifuenf_dither))
00555         {
00556             chosen = "dithered i586/pentium";
00557             fr->cpu_opts.type = ifuenf_dither;
00558             dithered = TRUE;
00559 #           ifndef NO_16BIT
00560             fr->synths.plain[r_1to1][f_16] = synth_1to1_i586_dither;
00561 #           ifndef NO_DOWNSAMPLE
00562             fr->synths.plain[r_2to1][f_16] = synth_2to1_dither;
00563             fr->synths.plain[r_4to1][f_16] = synth_4to1_dither;
00564 #           endif
00565 #           endif
00566             done = 1;
00567         }
00568         #endif
00569     }
00570     #ifdef OPT_I486
00571     /* That won't cooperate in multi opt mode - forcing i486 in layer3.c
00572        But still... here it is... maybe for real use in future. */
00573     if(!done && (auto_choose || want_dec == ivier))
00574     {
00575         chosen = "i486";
00576         fr->cpu_opts.type = ivier;
00577         done = 1;
00578     }
00579     #endif
00580     #ifdef OPT_I386
00581     if(!done && (auto_choose || want_dec == idrei))
00582     {
00583         chosen = "i386";
00584         fr->cpu_opts.type = idrei;
00585         done = 1;
00586     }
00587     #endif
00588 
00589     if(done)
00590     {
00591         /*
00592             We have chosen some x86 decoder... fillup some i386 stuff.
00593             There is an open question about using dithered synth_1to1 for 8bit wrappers.
00594             For quality it won't make sense, but wrapped i586_dither wrapped may still be faster...
00595         */
00596         enum synth_resample ri;
00597         enum synth_format   fi;
00598 #       ifndef NO_8BIT
00599 #       ifndef NO_16BIT /* possibility to use a 16->8 wrapper... */
00600         if(fr->synths.plain[r_1to1][f_16] != synth_base.plain[r_1to1][f_16])
00601         {
00602             fr->synths.plain[r_1to1][f_8] = synth_1to1_8bit_wrap;
00603             fr->synths.mono[r_1to1][f_8] = synth_1to1_8bit_wrap_mono;
00604             fr->synths.mono2stereo[r_1to1][f_8] = synth_1to1_8bit_wrap_mono2stereo;
00605         }
00606 #       endif
00607 #       endif
00608         for(ri=0; ri<r_limit; ++ri)
00609         for(fi=0; fi<f_limit; ++fi)
00610         {
00611             if(fr->synths.plain[ri][fi] == synth_base.plain[ri][fi])
00612             fr->synths.plain[ri][fi] = plain_i386[ri][fi];
00613         }
00614     }
00615 
00616 #endif /* OPT_X86 */
00617 
00618 #ifdef OPT_X86_64
00619     if(!done && (auto_choose || want_dec == x86_64))
00620     {
00621         chosen = "x86-64 (SSE)";
00622         fr->cpu_opts.type = x86_64;
00623 #       ifndef NO_16BIT
00624         fr->synths.plain[r_1to1][f_16] = synth_1to1_x86_64;
00625         fr->synths.stereo[r_1to1][f_16] = synth_1to1_stereo_x86_64;
00626 #       endif
00627 #       ifndef NO_REAL
00628         fr->synths.plain[r_1to1][f_real] = synth_1to1_real_x86_64;
00629         fr->synths.stereo[r_1to1][f_real] = synth_1to1_real_stereo_x86_64;
00630 #       endif
00631 #       ifndef NO_32BIT
00632         fr->synths.plain[r_1to1][f_32] = synth_1to1_s32_x86_64;
00633         fr->synths.stereo[r_1to1][f_32] = synth_1to1_s32_stereo_x86_64;
00634 #       endif
00635         done = 1;
00636     }
00637 #endif
00638 
00639 #ifdef OPT_GENERIC_DITHER
00640     if(!done && (auto_choose || want_dec == generic_dither))
00641     {
00642         chosen = "dithered generic";
00643         fr->cpu_opts.type = generic_dither;
00644         dithered = TRUE;
00645 #       ifndef NO_16BIT
00646         fr->synths.plain[r_1to1][f_16] = synth_1to1_dither;
00647 #       ifndef NO_DOWNSAMPLE
00648         fr->synths.plain[r_2to1][f_16] = synth_2to1_dither;
00649         fr->synths.plain[r_4to1][f_16] = synth_4to1_dither;
00650 #       endif
00651 #       endif
00652         done = 1;
00653     }
00654 #endif
00655 
00656 #   ifdef OPT_ALTIVEC
00657     if(!done && (auto_choose || want_dec == altivec))
00658     {
00659         chosen = "AltiVec";
00660         fr->cpu_opts.type = altivec;
00661 #       ifndef NO_16BIT
00662         fr->synths.plain[r_1to1][f_16] = synth_1to1_altivec;
00663         fr->synths.stereo[r_1to1][f_16] = synth_1to1_stereo_altivec;
00664 #       endif
00665 #       ifndef NO_REAL
00666         fr->synths.plain[r_1to1][f_real] = synth_1to1_real_altivec;
00667         fr->synths.stereo[r_1to1][f_real] = synth_1to1_real_stereo_altivec;
00668 #       endif
00669 #       ifndef NO_32BIT
00670         fr->synths.plain[r_1to1][f_32] = synth_1to1_s32_altivec;
00671         fr->synths.stereo[r_1to1][f_32] = synth_1to1_s32_stereo_altivec;
00672 #       endif
00673         done = 1;
00674     }
00675 #   endif
00676 
00677 #   ifdef OPT_ARM
00678     if(!done && (auto_choose || want_dec == arm))
00679     {
00680         chosen = "ARM";
00681         fr->cpu_opts.type = arm;
00682 #       ifndef NO_16BIT
00683         fr->synths.plain[r_1to1][f_16] = synth_1to1_arm;
00684 #       endif
00685         done = 1;
00686     }
00687 #   endif
00688 
00689 #   ifdef OPT_GENERIC
00690     if(!done && (auto_choose || want_dec == generic))
00691     {
00692         chosen = "generic";
00693         fr->cpu_opts.type = generic;
00694         done = 1;
00695     }
00696 #   endif
00697 
00698     fr->cpu_opts.class = decclass(fr->cpu_opts.type);
00699 
00700 #   ifndef NO_8BIT
00701 #   ifndef NO_16BIT /* possibility to use a 16->8 wrapper... */
00702     /* Last chance to use some optimized routine via generic wrappers (for 8bit). */
00703     if(     fr->cpu_opts.type != ifuenf_dither
00704          && fr->cpu_opts.type != generic_dither
00705          && fr->synths.plain[r_1to1][f_16] != synth_base.plain[r_1to1][f_16] )
00706     {
00707         fr->synths.plain[r_1to1][f_8] = synth_1to1_8bit_wrap;
00708         fr->synths.mono[r_1to1][f_8] = synth_1to1_8bit_wrap_mono;
00709         fr->synths.mono2stereo[r_1to1][f_8] = synth_1to1_8bit_wrap_mono2stereo;
00710     }
00711 #   endif
00712 #   endif
00713 
00714 #ifdef OPT_DITHER
00715     if(done && dithered)
00716     {
00717         /* run-time dither noise table generation */
00718         if(!frame_dither_init(fr))
00719         {
00720             if(NOQUIET) error("Dither noise setup failed!");
00721             return 0;
00722         }
00723     }
00724 #endif
00725 
00726     if(done)
00727     {
00728         if(VERBOSE) fprintf(stderr, "Decoder: %s\n", chosen);
00729         return 1;
00730     }
00731     else
00732     {
00733         if(NOQUIET) error("Could not set optimization!");
00734         return 0;
00735     }
00736 }
00737 
00738 enum optdec dectype(const char* decoder)
00739 {
00740     enum optdec dt;
00741     if(   (decoder == NULL)
00742        || (decoder[0] == 0) )
00743     return autodec;
00744 
00745     for(dt=autodec; dt<nodec; ++dt)
00746     if(!strcasecmp(decoder, decname[dt])) return dt;
00747 
00748     return nodec; /* If we found nothing... */
00749 }
00750 
00751 #ifdef OPT_MULTI
00752 
00753 /* same number of entries as full list, but empty at beginning */
00754 static const char *mpg123_supported_decoder_list[] =
00755 {
00756     #ifdef OPT_SSE
00757     NULL,
00758     #endif
00759     #ifdef OPT_3DNOWEXT
00760     NULL,
00761     #endif
00762     #ifdef OPT_3DNOW
00763     NULL,
00764     #endif
00765     #ifdef OPT_MMX
00766     NULL,
00767     #endif
00768     #ifdef OPT_I586
00769     NULL,
00770     #endif
00771     #ifdef OPT_I586_DITHER
00772     NULL,
00773     #endif
00774     #ifdef OPT_I486
00775     NULL,
00776     #endif
00777     #ifdef OPT_I386
00778     NULL,
00779     #endif
00780     #ifdef OPT_ALTIVEC
00781     NULL,
00782     #endif
00783     #ifdef OPT_X86_64
00784     NULL,
00785     #endif
00786     #ifdef OPT_ARM
00787     NULL,
00788     #endif
00789     #ifdef OPT_GENERIC_FLOAT
00790     NULL,
00791     #endif
00792 #   ifdef OPT_GENERIC
00793     NULL,
00794 #   endif
00795 #   ifdef OPT_GENERIC_DITHER
00796     NULL,
00797 #   endif
00798     NULL
00799 };
00800 #endif
00801 
00802 static const char *mpg123_decoder_list[] =
00803 {
00804     #ifdef OPT_SSE
00805     dn_SSE,
00806     #endif
00807     #ifdef OPT_3DNOWEXT
00808     dn_3DNowExt,
00809     #endif
00810     #ifdef OPT_3DNOW
00811     dn_3DNow,
00812     #endif
00813     #ifdef OPT_MMX
00814     dn_MMX,
00815     #endif
00816     #ifdef OPT_I586
00817     dn_i586,
00818     #endif
00819     #ifdef OPT_I586_DITHER
00820     dn_i586_dither,
00821     #endif
00822     #ifdef OPT_I486
00823     dn_i486,
00824     #endif
00825     #ifdef OPT_I386
00826     dn_i386,
00827     #endif
00828     #ifdef OPT_ALTIVEC
00829     dn_AltiVec,
00830     #endif
00831     #ifdef OPT_X86_64
00832     dn_x86_64,
00833     #endif
00834     #ifdef OPT_ARM
00835     dn_ARM,
00836     #endif
00837     #ifdef OPT_GENERIC
00838     dn_generic,
00839     #endif
00840     #ifdef OPT_GENERIC_DITHER
00841     dn_generic_dither,
00842     #endif
00843     NULL
00844 };
00845 
00846 void check_decoders(void )
00847 {
00848 #ifndef OPT_MULTI
00849     /* In non-multi mode, only the full list (one entry) is used. */
00850     return;
00851 #else
00852     const char **d = mpg123_supported_decoder_list;
00853 #ifdef OPT_X86
00854     getcpuflags(&cpu_flags);
00855     if(cpu_i586(cpu_flags))
00856     {
00857         /* not yet: if(cpu_sse2(cpu_flags)) printf(" SSE2");
00858         if(cpu_sse3(cpu_flags)) printf(" SSE3"); */
00859 #ifdef OPT_SSE
00860         if(cpu_sse(cpu_flags)) *(d++) = decname[sse];
00861 #endif
00862 #ifdef OPT_3DNOWEXT
00863         if(cpu_3dnowext(cpu_flags)) *(d++) = decname[dreidnowext];
00864 #endif
00865 #ifdef OPT_3DNOW
00866         if(cpu_3dnow(cpu_flags)) *(d++) = decname[dreidnow];
00867 #endif
00868 #ifdef OPT_MMX
00869         if(cpu_mmx(cpu_flags)) *(d++) = decname[mmx];
00870 #endif
00871 #ifdef OPT_I586
00872         *(d++) = decname[ifuenf];
00873 #endif
00874 #ifdef OPT_I586_DITHER
00875         *(d++) = decname[ifuenf_dither];
00876 #endif
00877     }
00878 #endif
00879 /* just assume that the i486 built is run on a i486 cpu... */
00880 #ifdef OPT_I486
00881     *(d++) = decname[ivier];
00882 #endif
00883 #ifdef OPT_ALTIVEC
00884     *(d++) = decname[altivec];
00885 #endif
00886 /* every supported x86 can do i386, any cpu can do generic */
00887 #ifdef OPT_I386
00888     *(d++) = decname[idrei];
00889 #endif
00890 #ifdef OPT_X86_64
00891     *(d++) = decname[x86_64];
00892 #endif
00893 #ifdef OPT_ARM
00894     *(d++) = decname[arm];
00895 #endif
00896 #ifdef OPT_GENERIC
00897     *(d++) = decname[generic];
00898 #endif
00899 #ifdef OPT_GENERIC_DITHER
00900     *(d++) = decname[generic_dither];
00901 #endif
00902 #endif /* ndef OPT_MULTI */
00903 }
00904 
00905 const char* attribute_align_arg mpg123_current_decoder(mpg123_handle *mh)
00906 {
00907     if(mh == NULL) return NULL;
00908 
00909     return decname[mh->cpu_opts.type];
00910 }
00911 
00912 const char attribute_align_arg **mpg123_decoders(void){ return mpg123_decoder_list; }
00913 const char attribute_align_arg **mpg123_supported_decoders(void)
00914 {
00915 #ifdef OPT_MULTI
00916     return mpg123_supported_decoder_list;
00917 #else
00918     return mpg123_decoder_list;
00919 #endif
00920 }

Generated on Fri May 25 2012 04:32:37 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.