FFmpeg
Loading...
Searching...
No Matches
cpu.c
Go to the documentation of this file.
1/*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19#include "libavutil/cpu.h"
21#include "config.h"
22
23#define CORE_FLAG(f) \
24 (AV_CPU_FLAG_ ## f * (HAVE_ ## f ## _EXTERNAL || HAVE_ ## f ## _INLINE))
25
26#define CORE_CPU_FLAGS \
27 (CORE_FLAG(ARMV5TE) | \
28 CORE_FLAG(ARMV6) | \
29 CORE_FLAG(ARMV6T2) | \
30 CORE_FLAG(VFP) | \
31 CORE_FLAG(VFPV3) | \
32 CORE_FLAG(NEON))
33
34#if defined __linux__ || defined __ANDROID__ || HAVE_ELF_AUX_INFO
35
36#include <stdint.h>
37#include <stdio.h>
38#include <string.h>
39#include "libavutil/avstring.h"
40
41#if HAVE_GETAUXVAL || HAVE_ELF_AUX_INFO
42#include <sys/auxv.h>
43#endif
44
45#ifndef AT_HWCAP
46#define AT_HWCAP 16
47#endif
48
49/* Relevant HWCAP values from <sys/auxv.h> that includes <bits/hwcap.h> */
50#ifndef HWCAP_ARM_VFP
51#define HWCAP_ARM_VFP (1 << 6)
52#endif
53#ifndef HWCAP_ARM_EDSP
54#define HWCAP_ARM_EDSP (1 << 7)
55#endif
56#ifndef HWCAP_ARM_THUMBEE
57#define HWCAP_ARM_THUMBEE (1 << 11)
58#endif
59#ifndef HWCAP_ARM_NEON
60#define HWCAP_ARM_NEON (1 << 12)
61#endif
62#ifndef HWCAP_ARM_VFPv3
63#define HWCAP_ARM_VFPv3 (1 << 13)
64#endif
65#ifndef HWCAP_ARM_TLS
66#define HWCAP_ARM_TLS (1 << 15)
67#endif
68
69static int get_auxval(uint32_t *hwcap)
70{
71#if HAVE_GETAUXVAL || HAVE_ELF_AUX_INFO
72 unsigned long ret = ff_getauxval(AT_HWCAP);
73 if (ret == 0)
74 return -1;
75 *hwcap = ret;
76 return 0;
77#else
78 return -1;
79#endif
80}
81
82#if defined __linux__ || defined __ANDROID__
83static int get_hwcap(uint32_t *hwcap)
84{
85 struct { uint32_t a_type; uint32_t a_val; } auxv;
86 FILE *f = fopen("/proc/self/auxv", "r");
87 int err = -1;
88
89 if (!f)
90 return -1;
91
92 while (fread(&auxv, sizeof(auxv), 1, f) > 0) {
93 if (auxv.a_type == AT_HWCAP) {
94 *hwcap = auxv.a_val;
95 err = 0;
96 break;
97 }
98 }
99
100 fclose(f);
101 return err;
102}
103
104static int get_cpuinfo(uint32_t *hwcap)
105{
106 FILE *f = fopen("/proc/cpuinfo", "r");
107 char buf[200];
108
109 if (!f)
110 return -1;
111
112 *hwcap = 0;
113 while (fgets(buf, sizeof(buf), f)) {
114 if (av_strstart(buf, "Features", NULL)) {
115 if (strstr(buf, " edsp "))
116 *hwcap |= HWCAP_ARM_EDSP;
117 if (strstr(buf, " tls "))
118 *hwcap |= HWCAP_ARM_TLS;
119 if (strstr(buf, " thumbee "))
120 *hwcap |= HWCAP_ARM_THUMBEE;
121 if (strstr(buf, " vfp "))
122 *hwcap |= HWCAP_ARM_VFP;
123 if (strstr(buf, " vfpv3 "))
124 *hwcap |= HWCAP_ARM_VFPv3;
125 if (strstr(buf, " neon ") || strstr(buf, " asimd "))
126 *hwcap |= HWCAP_ARM_NEON;
127 if (strstr(buf, " fp ")) // Listed on 64 bit ARMv8 kernels
128 *hwcap |= HWCAP_ARM_VFP | HWCAP_ARM_VFPv3;
129 break;
130 }
131 }
132 fclose(f);
133 return 0;
134}
135#endif
136
137int ff_get_cpu_flags_arm(void)
138{
139 int flags = CORE_CPU_FLAGS;
140 uint32_t hwcap;
141
142 if (get_auxval(&hwcap) < 0)
143#if defined __linux__ || defined __ANDROID__
144 if (get_hwcap(&hwcap) < 0)
145 if (get_cpuinfo(&hwcap) < 0)
146#endif
147 return flags;
148
149#define check_cap(cap, flag) do { \
150 if (hwcap & HWCAP_ARM_ ## cap) \
151 flags |= AV_CPU_FLAG_ ## flag; \
152 } while (0)
153
154 /* No flags explicitly indicate v6 or v6T2 so check others which
155 imply support. */
156 check_cap(EDSP, ARMV5TE);
157 check_cap(TLS, ARMV6);
158 check_cap(THUMBEE, ARMV6T2);
159 check_cap(VFP, VFP);
160 check_cap(VFPv3, VFPV3);
161 check_cap(NEON, NEON);
162
163 /* The v6 checks above are not reliable so let higher flags
164 trickle down. */
168 /* Some functions use the 'setend' instruction which is deprecated on ARMv8
169 * and serializing on some ARMv7 cores. This ensures such functions
170 * are only enabled on ARMv6. */
172
175
176 /* set the virtual VFPv2 vector mode flag */
179
180 return flags;
181}
182
183#else
184
186{
187 return AV_CPU_FLAG_ARMV5TE * HAVE_ARMV5TE |
188 AV_CPU_FLAG_ARMV6 * HAVE_ARMV6 |
189 AV_CPU_FLAG_ARMV6T2 * HAVE_ARMV6T2 |
190 AV_CPU_FLAG_VFP * HAVE_VFP |
191 AV_CPU_FLAG_VFPV3 * HAVE_VFPV3 |
192 AV_CPU_FLAG_NEON * HAVE_NEON |
193 AV_CPU_FLAG_SETEND * !(HAVE_NEON | HAVE_VFPV3);
194}
195
196#endif
197
199{
200 int flags = av_get_cpu_flags();
201
203 return 16;
204
205 return 8;
206}
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define f(width, name)
Definition cbs_vp8.c:236
#define NULL
Definition coverity.c:32
int av_strstart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str.
Definition avstring.c:36
int ff_get_cpu_flags_arm(void)
Definition cpu.c:185
#define CORE_CPU_FLAGS
Definition cpu.c:26
size_t ff_get_cpu_max_align_arm(void)
Definition cpu.c:198
unsigned long ff_getauxval(unsigned long type)
Definition cpu.c:309
int av_get_cpu_flags(void)
Return the flags which specify extensions supported by the CPU.
Definition cpu.c:109
#define AV_CPU_FLAG_ARMV5TE
Definition cpu.h:68
#define AV_CPU_FLAG_VFPV3
Definition cpu.h:72
#define AV_CPU_FLAG_VFP
Definition cpu.h:71
#define AV_CPU_FLAG_NEON
Definition cpu.h:73
#define AV_CPU_FLAG_SETEND
Definition cpu.h:84
#define AV_CPU_FLAG_ARMV6T2
Definition cpu.h:70
#define AV_CPU_FLAG_VFP_VM
VFPv2 vector mode, deprecated in ARMv7-A and unavailable in various CPUs implementations.
Definition cpu.h:75
#define AV_CPU_FLAG_ARMV6
Definition cpu.h:69
#define AT_HWCAP
Definition cpu.c:50