yading@11
|
1 /*
|
yading@11
|
2 * This file is part of Libav.
|
yading@11
|
3 *
|
yading@11
|
4 * Libav is free software; you can redistribute it and/or
|
yading@11
|
5 * modify it under the terms of the GNU Lesser General Public
|
yading@11
|
6 * License as published by the Free Software Foundation; either
|
yading@11
|
7 * version 2.1 of the License, or (at your option) any later version.
|
yading@11
|
8 *
|
yading@11
|
9 * Libav is distributed in the hope that it will be useful,
|
yading@11
|
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
yading@11
|
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
yading@11
|
12 * Lesser General Public License for more details.
|
yading@11
|
13 *
|
yading@11
|
14 * You should have received a copy of the GNU Lesser General Public
|
yading@11
|
15 * License along with Libav; if not, write to the Free Software
|
yading@11
|
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
yading@11
|
17 */
|
yading@11
|
18
|
yading@11
|
19 #include "libavutil/cpu.h"
|
yading@11
|
20 #include "config.h"
|
yading@11
|
21
|
yading@11
|
22 #define CORE_FLAG(f) \
|
yading@11
|
23 (AV_CPU_FLAG_ ## f * (HAVE_ ## f ## _EXTERNAL || HAVE_ ## f ## _INLINE))
|
yading@11
|
24
|
yading@11
|
25 #define CORE_CPU_FLAGS \
|
yading@11
|
26 (CORE_FLAG(ARMV5TE) | \
|
yading@11
|
27 CORE_FLAG(ARMV6) | \
|
yading@11
|
28 CORE_FLAG(ARMV6T2) | \
|
yading@11
|
29 CORE_FLAG(VFP) | \
|
yading@11
|
30 CORE_FLAG(VFPV3) | \
|
yading@11
|
31 CORE_FLAG(NEON))
|
yading@11
|
32
|
yading@11
|
33 #if defined __linux__ || defined __ANDROID__
|
yading@11
|
34
|
yading@11
|
35 #include <stdint.h>
|
yading@11
|
36 #include <stdio.h>
|
yading@11
|
37 #include <string.h>
|
yading@11
|
38 #include "libavutil/avstring.h"
|
yading@11
|
39
|
yading@11
|
40 #define AT_HWCAP 16
|
yading@11
|
41
|
yading@11
|
42 /* Relevant HWCAP values from kernel headers */
|
yading@11
|
43 #define HWCAP_VFP (1 << 6)
|
yading@11
|
44 #define HWCAP_EDSP (1 << 7)
|
yading@11
|
45 #define HWCAP_THUMBEE (1 << 11)
|
yading@11
|
46 #define HWCAP_NEON (1 << 12)
|
yading@11
|
47 #define HWCAP_VFPv3 (1 << 13)
|
yading@11
|
48 #define HWCAP_TLS (1 << 15)
|
yading@11
|
49
|
yading@11
|
50 static int get_hwcap(uint32_t *hwcap)
|
yading@11
|
51 {
|
yading@11
|
52 struct { uint32_t a_type; uint32_t a_val; } auxv;
|
yading@11
|
53 FILE *f = fopen("/proc/self/auxv", "r");
|
yading@11
|
54 int err = -1;
|
yading@11
|
55
|
yading@11
|
56 if (!f)
|
yading@11
|
57 return -1;
|
yading@11
|
58
|
yading@11
|
59 while (fread(&auxv, sizeof(auxv), 1, f) > 0) {
|
yading@11
|
60 if (auxv.a_type == AT_HWCAP) {
|
yading@11
|
61 *hwcap = auxv.a_val;
|
yading@11
|
62 err = 0;
|
yading@11
|
63 break;
|
yading@11
|
64 }
|
yading@11
|
65 }
|
yading@11
|
66
|
yading@11
|
67 fclose(f);
|
yading@11
|
68 return err;
|
yading@11
|
69 }
|
yading@11
|
70
|
yading@11
|
71 static int get_cpuinfo(uint32_t *hwcap)
|
yading@11
|
72 {
|
yading@11
|
73 FILE *f = fopen("/proc/cpuinfo", "r");
|
yading@11
|
74 char buf[200];
|
yading@11
|
75
|
yading@11
|
76 if (!f)
|
yading@11
|
77 return -1;
|
yading@11
|
78
|
yading@11
|
79 *hwcap = 0;
|
yading@11
|
80 while (fgets(buf, sizeof(buf), f)) {
|
yading@11
|
81 if (av_strstart(buf, "Features", NULL)) {
|
yading@11
|
82 if (strstr(buf, " edsp "))
|
yading@11
|
83 *hwcap |= HWCAP_EDSP;
|
yading@11
|
84 if (strstr(buf, " tls "))
|
yading@11
|
85 *hwcap |= HWCAP_TLS;
|
yading@11
|
86 if (strstr(buf, " thumbee "))
|
yading@11
|
87 *hwcap |= HWCAP_THUMBEE;
|
yading@11
|
88 if (strstr(buf, " vfp "))
|
yading@11
|
89 *hwcap |= HWCAP_VFP;
|
yading@11
|
90 if (strstr(buf, " vfpv3 "))
|
yading@11
|
91 *hwcap |= HWCAP_VFPv3;
|
yading@11
|
92 if (strstr(buf, " neon "))
|
yading@11
|
93 *hwcap |= HWCAP_NEON;
|
yading@11
|
94 break;
|
yading@11
|
95 }
|
yading@11
|
96 }
|
yading@11
|
97 fclose(f);
|
yading@11
|
98 return 0;
|
yading@11
|
99 }
|
yading@11
|
100
|
yading@11
|
101 int ff_get_cpu_flags_arm(void)
|
yading@11
|
102 {
|
yading@11
|
103 int flags = CORE_CPU_FLAGS;
|
yading@11
|
104 uint32_t hwcap;
|
yading@11
|
105
|
yading@11
|
106 if (get_hwcap(&hwcap) < 0)
|
yading@11
|
107 if (get_cpuinfo(&hwcap) < 0)
|
yading@11
|
108 return flags;
|
yading@11
|
109
|
yading@11
|
110 #define check_cap(cap, flag) do { \
|
yading@11
|
111 if (hwcap & HWCAP_ ## cap) \
|
yading@11
|
112 flags |= AV_CPU_FLAG_ ## flag; \
|
yading@11
|
113 } while (0)
|
yading@11
|
114
|
yading@11
|
115 /* No flags explicitly indicate v6 or v6T2 so check others which
|
yading@11
|
116 imply support. */
|
yading@11
|
117 check_cap(EDSP, ARMV5TE);
|
yading@11
|
118 check_cap(TLS, ARMV6);
|
yading@11
|
119 check_cap(THUMBEE, ARMV6T2);
|
yading@11
|
120 check_cap(VFP, VFP);
|
yading@11
|
121 check_cap(VFPv3, VFPV3);
|
yading@11
|
122 check_cap(NEON, NEON);
|
yading@11
|
123
|
yading@11
|
124 /* The v6 checks above are not reliable so let higher flags
|
yading@11
|
125 trickle down. */
|
yading@11
|
126 if (flags & (AV_CPU_FLAG_VFPV3 | AV_CPU_FLAG_NEON))
|
yading@11
|
127 flags |= AV_CPU_FLAG_ARMV6T2;
|
yading@11
|
128 if (flags & AV_CPU_FLAG_ARMV6T2)
|
yading@11
|
129 flags |= AV_CPU_FLAG_ARMV6;
|
yading@11
|
130
|
yading@11
|
131 return flags;
|
yading@11
|
132 }
|
yading@11
|
133
|
yading@11
|
134 #else
|
yading@11
|
135
|
yading@11
|
136 int ff_get_cpu_flags_arm(void)
|
yading@11
|
137 {
|
yading@11
|
138 return AV_CPU_FLAG_ARMV5TE * HAVE_ARMV5TE |
|
yading@11
|
139 AV_CPU_FLAG_ARMV6 * HAVE_ARMV6 |
|
yading@11
|
140 AV_CPU_FLAG_ARMV6T2 * HAVE_ARMV6T2 |
|
yading@11
|
141 AV_CPU_FLAG_VFP * HAVE_VFP |
|
yading@11
|
142 AV_CPU_FLAG_VFPV3 * HAVE_VFPV3 |
|
yading@11
|
143 AV_CPU_FLAG_NEON * HAVE_NEON;
|
yading@11
|
144 }
|
yading@11
|
145
|
yading@11
|
146 #endif
|