cpu.c
上传用户:lctgjx
上传日期:2022-06-04
资源大小:8887k
文件大小:11k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*****************************************************************************
  2.  * cpu.c: h264 encoder library
  3.  *****************************************************************************
  4.  * Copyright (C) 2003-2008 x264 project
  5.  *
  6.  * Authors: Loren Merritt <lorenm@u.washington.edu>
  7.  *          Laurent Aimar <fenrir@via.ecp.fr>
  8.  *          Jason Garrett-Glaser <darkshikari@gmail.com>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
  23.  *****************************************************************************/
  24. #if defined(HAVE_PTHREAD) && defined(SYS_LINUX)
  25. #define _GNU_SOURCE
  26. #include <sched.h>
  27. #endif
  28. #ifdef SYS_BEOS
  29. #include <kernel/OS.h>
  30. #endif
  31. #if defined(SYS_MACOSX) || defined(SYS_FREEBSD)
  32. #include <sys/types.h>
  33. #include <sys/sysctl.h>
  34. #endif
  35. #ifdef SYS_OPENBSD
  36. #include <sys/param.h>
  37. #include <sys/sysctl.h>
  38. #include <machine/cpu.h>
  39. #endif
  40. #include "common.h"
  41. #include "cpu.h"
  42. const x264_cpu_name_t x264_cpu_names[] = {
  43.     {"Altivec", X264_CPU_ALTIVEC},
  44. //  {"MMX",     X264_CPU_MMX}, // we don't support asm on mmx1 cpus anymore
  45.     {"MMX2",    X264_CPU_MMX|X264_CPU_MMXEXT},
  46.     {"MMXEXT",  X264_CPU_MMX|X264_CPU_MMXEXT},
  47. //  {"SSE",     X264_CPU_MMX|X264_CPU_MMXEXT|X264_CPU_SSE}, // there are no sse1 functions in x264
  48.     {"SSE2Slow",X264_CPU_MMX|X264_CPU_MMXEXT|X264_CPU_SSE|X264_CPU_SSE2|X264_CPU_SSE2_IS_SLOW},
  49.     {"SSE2",    X264_CPU_MMX|X264_CPU_MMXEXT|X264_CPU_SSE|X264_CPU_SSE2},
  50.     {"SSE2Fast",X264_CPU_MMX|X264_CPU_MMXEXT|X264_CPU_SSE|X264_CPU_SSE2|X264_CPU_SSE2_IS_FAST},
  51.     {"SSE3",    X264_CPU_MMX|X264_CPU_MMXEXT|X264_CPU_SSE|X264_CPU_SSE2|X264_CPU_SSE3},
  52.     {"SSSE3",   X264_CPU_MMX|X264_CPU_MMXEXT|X264_CPU_SSE|X264_CPU_SSE2|X264_CPU_SSE3|X264_CPU_SSSE3},
  53.     {"FastShuffle",   X264_CPU_MMX|X264_CPU_MMXEXT|X264_CPU_SSE|X264_CPU_SSE2|X264_CPU_SHUFFLE_IS_FAST},
  54.     {"SSE4.1",  X264_CPU_MMX|X264_CPU_MMXEXT|X264_CPU_SSE|X264_CPU_SSE2|X264_CPU_SSE3|X264_CPU_SSSE3|X264_CPU_SSE4},
  55.     {"SSE4.2",  X264_CPU_MMX|X264_CPU_MMXEXT|X264_CPU_SSE|X264_CPU_SSE2|X264_CPU_SSE3|X264_CPU_SSSE3|X264_CPU_SSE4|X264_CPU_SSE42},
  56.     {"Cache32", X264_CPU_CACHELINE_32},
  57.     {"Cache64", X264_CPU_CACHELINE_64},
  58.     {"SSEMisalign", X264_CPU_SSE_MISALIGN},
  59.     {"LZCNT", X264_CPU_LZCNT},
  60.     {"Slow_mod4_stack", X264_CPU_STACK_MOD4},
  61.     {"ARMv6", X264_CPU_ARMV6},
  62.     {"NEON",  X264_CPU_NEON},
  63.     {"Fast_NEON_MRC",  X264_CPU_FAST_NEON_MRC},
  64.     {"", 0},
  65. };
  66. #if (defined(ARCH_PPC) && defined(SYS_LINUX)) || (defined(ARCH_ARM) && !defined(HAVE_NEON))
  67. #include <signal.h>
  68. #include <setjmp.h>
  69. static sigjmp_buf jmpbuf;
  70. static volatile sig_atomic_t canjump = 0;
  71. static void sigill_handler( int sig )
  72. {
  73.     if( !canjump )
  74.     {
  75.         signal( sig, SIG_DFL );
  76.         raise( sig );
  77.     }
  78.     canjump = 0;
  79.     siglongjmp( jmpbuf, 1 );
  80. }
  81. #endif
  82. #ifdef HAVE_MMX
  83. extern int  x264_cpu_cpuid_test( void );
  84. extern uint32_t  x264_cpu_cpuid( uint32_t op, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx );
  85. uint32_t x264_cpu_detect( void )
  86. {
  87.     uint32_t cpu = 0;
  88.     uint32_t eax, ebx, ecx, edx;
  89.     uint32_t vendor[4] = {0};
  90.     int max_extended_cap;
  91.     int cache;
  92. #ifndef ARCH_X86_64
  93.     if( !x264_cpu_cpuid_test() )
  94.         return 0;
  95. #endif
  96.     x264_cpu_cpuid( 0, &eax, vendor+0, vendor+2, vendor+1 );
  97.     if( eax == 0 )
  98.         return 0;
  99.     x264_cpu_cpuid( 1, &eax, &ebx, &ecx, &edx );
  100.     if( edx&0x00800000 )
  101.         cpu |= X264_CPU_MMX;
  102.     else
  103.         return 0;
  104.     if( edx&0x02000000 )
  105.         cpu |= X264_CPU_MMXEXT|X264_CPU_SSE;
  106.     if( edx&0x04000000 )
  107.         cpu |= X264_CPU_SSE2;
  108.     if( ecx&0x00000001 )
  109.         cpu |= X264_CPU_SSE3;
  110.     if( ecx&0x00000200 )
  111.         cpu |= X264_CPU_SSSE3;
  112.     if( ecx&0x00080000 )
  113.         cpu |= X264_CPU_SSE4;
  114.     if( ecx&0x00100000 )
  115.         cpu |= X264_CPU_SSE42;
  116.     if( cpu & X264_CPU_SSSE3 )
  117.         cpu |= X264_CPU_SSE2_IS_FAST;
  118.     if( cpu & X264_CPU_SSE4 )
  119.         cpu |= X264_CPU_SHUFFLE_IS_FAST;
  120.     x264_cpu_cpuid( 0x80000000, &eax, &ebx, &ecx, &edx );
  121.     max_extended_cap = eax;
  122.     if( !strcmp((char*)vendor, "AuthenticAMD") && max_extended_cap >= 0x80000001 )
  123.     {
  124.         x264_cpu_cpuid( 0x80000001, &eax, &ebx, &ecx, &edx );
  125.         if( edx&0x00400000 )
  126.             cpu |= X264_CPU_MMXEXT;
  127.         if( cpu & X264_CPU_SSE2 )
  128.         {
  129.             if( ecx&0x00000040 ) /* SSE4a */
  130.             {
  131.                 cpu |= X264_CPU_SSE2_IS_FAST;
  132.                 cpu |= X264_CPU_SSE_MISALIGN;
  133.                 cpu |= X264_CPU_LZCNT;
  134.                 cpu |= X264_CPU_SHUFFLE_IS_FAST;
  135.                 x264_cpu_mask_misalign_sse();
  136.             }
  137.             else
  138.                 cpu |= X264_CPU_SSE2_IS_SLOW;
  139.         }
  140.     }
  141.     if( !strcmp((char*)vendor, "GenuineIntel") )
  142.     {
  143.         int family, model, stepping;
  144.         x264_cpu_cpuid( 1, &eax, &ebx, &ecx, &edx );
  145.         family = ((eax>>8)&0xf) + ((eax>>20)&0xff);
  146.         model  = ((eax>>4)&0xf) + ((eax>>12)&0xf0);
  147.         stepping = eax&0xf;
  148.         /* 6/9 (pentium-m "banias"), 6/13 (pentium-m "dothan"), and 6/14 (core1 "yonah")
  149.          * theoretically support sse2, but it's significantly slower than mmx for
  150.          * almost all of x264's functions, so let's just pretend they don't. */
  151.         if( family==6 && (model==9 || model==13 || model==14) )
  152.         {
  153.             cpu &= ~(X264_CPU_SSE2|X264_CPU_SSE3);
  154.             assert(!(cpu&(X264_CPU_SSSE3|X264_CPU_SSE4)));
  155.         }
  156.     }
  157.     if( (!strcmp((char*)vendor, "GenuineIntel") || !strcmp((char*)vendor, "CyrixInstead")) && !(cpu&X264_CPU_SSE42))
  158.     {
  159.         /* cacheline size is specified in 3 places, any of which may be missing */
  160.         x264_cpu_cpuid( 1, &eax, &ebx, &ecx, &edx );
  161.         cache = (ebx&0xff00)>>5; // cflush size
  162.         if( !cache && max_extended_cap >= 0x80000006 )
  163.         {
  164.             x264_cpu_cpuid( 0x80000006, &eax, &ebx, &ecx, &edx );
  165.             cache = ecx&0xff; // cacheline size
  166.         }
  167.         if( !cache )
  168.         {
  169.             // Cache and TLB Information
  170.             static const char cache32_ids[] = { 0x0a, 0x0c, 0x41, 0x42, 0x43, 0x44, 0x45, 0x82, 0x83, 0x84, 0x85, 0 };
  171.             static const char cache64_ids[] = { 0x22, 0x23, 0x25, 0x29, 0x2c, 0x46, 0x47, 0x49, 0x60, 0x66, 0x67, 0x68, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7c, 0x7f, 0x86, 0x87, 0 };
  172.             uint32_t buf[4];
  173.             int max, i=0, j;
  174.             do {
  175.                 x264_cpu_cpuid( 2, buf+0, buf+1, buf+2, buf+3 );
  176.                 max = buf[0]&0xff;
  177.                 buf[0] &= ~0xff;
  178.                 for(j=0; j<4; j++)
  179.                     if( !(buf[j]>>31) )
  180.                         while( buf[j] )
  181.                         {
  182.                             if( strchr( cache32_ids, buf[j]&0xff ) )
  183.                                 cache = 32;
  184.                             if( strchr( cache64_ids, buf[j]&0xff ) )
  185.                                 cache = 64;
  186.                             buf[j] >>= 8;
  187.                         }
  188.             } while( ++i < max );
  189.         }
  190.         if( cache == 32 )
  191.             cpu |= X264_CPU_CACHELINE_32;
  192.         else if( cache == 64 )
  193.             cpu |= X264_CPU_CACHELINE_64;
  194.         else
  195.             fprintf( stderr, "x264 [warning]: unable to determine cacheline sizen" );
  196.     }
  197. #ifdef BROKEN_STACK_ALIGNMENT
  198.     cpu |= X264_CPU_STACK_MOD4;
  199. #endif
  200.     return cpu;
  201. }
  202. #elif defined( ARCH_PPC )
  203. #if defined(SYS_MACOSX) || defined(SYS_OPENBSD)
  204. #include <sys/sysctl.h>
  205. uint32_t x264_cpu_detect( void )
  206. {
  207.     /* Thank you VLC */
  208.     uint32_t cpu = 0;
  209. #ifdef SYS_OPENBSD
  210.     int      selectors[2] = { CTL_MACHDEP, CPU_ALTIVEC };
  211. #else
  212.     int      selectors[2] = { CTL_HW, HW_VECTORUNIT };
  213. #endif
  214.     int      has_altivec = 0;
  215.     size_t   length = sizeof( has_altivec );
  216.     int      error = sysctl( selectors, 2, &has_altivec, &length, NULL, 0 );
  217.     if( error == 0 && has_altivec != 0 )
  218.     {
  219.         cpu |= X264_CPU_ALTIVEC;
  220.     }
  221.     return cpu;
  222. }
  223. #elif defined( SYS_LINUX )
  224. uint32_t x264_cpu_detect( void )
  225. {
  226.     static void (* oldsig)( int );
  227.     oldsig = signal( SIGILL, sigill_handler );
  228.     if( sigsetjmp( jmpbuf, 1 ) )
  229.     {
  230.         signal( SIGILL, oldsig );
  231.         return 0;
  232.     }
  233.     canjump = 1;
  234.     asm volatile( "mtspr 256, %0nt"
  235.                   "vand 0, 0, 0nt"
  236.                   :
  237.                   : "r"(-1) );
  238.     canjump = 0;
  239.     signal( SIGILL, oldsig );
  240.     return X264_CPU_ALTIVEC;
  241. }
  242. #endif
  243. #elif defined( ARCH_ARM )
  244. void x264_cpu_neon_test();
  245. int x264_cpu_fast_neon_mrc_test();
  246. uint32_t x264_cpu_detect( void )
  247. {
  248.     int flags = 0;
  249. #ifdef HAVE_ARMV6
  250.     flags |= X264_CPU_ARMV6;
  251.     // don't do this hack if compiled with -mfpu=neon
  252. #ifndef HAVE_NEON
  253.     static void (* oldsig)( int );
  254.     oldsig = signal( SIGILL, sigill_handler );
  255.     if( sigsetjmp( jmpbuf, 1 ) )
  256.     {
  257.         signal( SIGILL, oldsig );
  258.         return flags;
  259.     }
  260.     canjump = 1;
  261.     x264_cpu_neon_test();
  262.     canjump = 0;
  263.     signal( SIGILL, oldsig );
  264. #endif
  265.     flags |= X264_CPU_NEON;
  266.     // fast neon -> arm (Cortex-A9) detection relies on user access to the
  267.     // cycle counter; this assumes ARMv7 performance counters.
  268.     // NEON requires at least ARMv7, ARMv8 may require changes here, but
  269.     // hopefully this hacky detection method will have been replaced by then.
  270.     // Note that there is potential for a race condition if another program or
  271.     // x264 instance disables or reinits the counters while x264 is using them,
  272.     // which may result in incorrect detection and the counters stuck enabled.
  273.     flags |= x264_cpu_fast_neon_mrc_test() ? X264_CPU_FAST_NEON_MRC : 0;
  274.     // TODO: write dual issue test? currently it's A8 (dual issue) vs. A9 (fast mrc)
  275. #endif
  276.     return flags;
  277. }
  278. #else
  279. uint32_t x264_cpu_detect( void )
  280. {
  281.     return 0;
  282. }
  283. #endif
  284. #ifndef HAVE_MMX
  285. void x264_emms( void )
  286. {
  287. }
  288. #endif
  289. int x264_cpu_num_processors( void )
  290. {
  291. #if !defined(HAVE_PTHREAD)
  292.     return 1;
  293. #elif defined(_WIN32)
  294.     return pthread_num_processors_np();
  295. #elif defined(SYS_LINUX)
  296.     unsigned int bit;
  297.     int np;
  298.     cpu_set_t p_aff;
  299.     memset( &p_aff, 0, sizeof(p_aff) );
  300.     sched_getaffinity( 0, sizeof(p_aff), &p_aff );
  301.     for( np = 0, bit = 0; bit < sizeof(p_aff); bit++ )
  302.         np += (((uint8_t *)&p_aff)[bit / 8] >> (bit % 8)) & 1;
  303.     return np;
  304. #elif defined(SYS_BEOS)
  305.     system_info info;
  306.     get_system_info( &info );
  307.     return info.cpu_count;
  308. #elif defined(SYS_MACOSX) || defined(SYS_FREEBSD) || defined(SYS_OPENBSD)
  309.     int numberOfCPUs;
  310.     size_t length = sizeof( numberOfCPUs );
  311. #ifdef SYS_OPENBSD
  312.     int mib[2] = { CTL_HW, HW_NCPU };
  313.     if( sysctl(mib, 2, &numberOfCPUs, &length, NULL, 0) )
  314. #else
  315.     if( sysctlbyname("hw.ncpu", &numberOfCPUs, &length, NULL, 0) )
  316. #endif
  317.     {
  318.         numberOfCPUs = 1;
  319.     }
  320.     return numberOfCPUs;
  321. #else
  322.     return 1;
  323. #endif
  324. }