|
@@ -19,6 +19,87 @@
|
|
|
#include "libavutil/cpu.h"
|
|
|
#include "config.h"
|
|
|
|
|
|
+#define CORE_FLAG(f) \
|
|
|
+ (AV_CPU_FLAG_ ## f * (HAVE_ ## f ## _EXTERNAL || HAVE_ ## f ## _INLINE))
|
|
|
+
|
|
|
+#define CORE_CPU_FLAGS \
|
|
|
+ (CORE_FLAG(ARMV5TE) | \
|
|
|
+ CORE_FLAG(ARMV6) | \
|
|
|
+ CORE_FLAG(ARMV6T2) | \
|
|
|
+ CORE_FLAG(VFP) | \
|
|
|
+ CORE_FLAG(VFPV3) | \
|
|
|
+ CORE_FLAG(NEON))
|
|
|
+
|
|
|
+#if defined __linux__ || defined __ANDROID__
|
|
|
+
|
|
|
+#include <stdint.h>
|
|
|
+#include <stdio.h>
|
|
|
+
|
|
|
+#define AT_HWCAP 16
|
|
|
+
|
|
|
+/* Relevant HWCAP values from kernel headers */
|
|
|
+#define HWCAP_VFP (1 << 6)
|
|
|
+#define HWCAP_EDSP (1 << 7)
|
|
|
+#define HWCAP_THUMBEE (1 << 11)
|
|
|
+#define HWCAP_NEON (1 << 12)
|
|
|
+#define HWCAP_VFPv3 (1 << 13)
|
|
|
+#define HWCAP_TLS (1 << 15)
|
|
|
+
|
|
|
+static int get_hwcap(uint32_t *hwcap)
|
|
|
+{
|
|
|
+ struct { uint32_t a_type; uint32_t a_val; } auxv;
|
|
|
+ FILE *f = fopen("/proc/self/auxv", "r");
|
|
|
+ int err = -1;
|
|
|
+
|
|
|
+ if (!f)
|
|
|
+ return -1;
|
|
|
+
|
|
|
+ while (fread(&auxv, sizeof(auxv), 1, f) > 0) {
|
|
|
+ if (auxv.a_type == AT_HWCAP) {
|
|
|
+ *hwcap = auxv.a_val;
|
|
|
+ err = 0;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ fclose(f);
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
+int ff_get_cpu_flags_arm(void)
|
|
|
+{
|
|
|
+ int flags = CORE_CPU_FLAGS;
|
|
|
+ uint32_t hwcap;
|
|
|
+
|
|
|
+ if (get_hwcap(&hwcap) < 0)
|
|
|
+ return flags;
|
|
|
+
|
|
|
+#define check_cap(cap, flag) do { \
|
|
|
+ if (hwcap & HWCAP_ ## cap) \
|
|
|
+ flags |= AV_CPU_FLAG_ ## flag; \
|
|
|
+ } while (0)
|
|
|
+
|
|
|
+ /* No flags explicitly indicate v6 or v6T2 so check others which
|
|
|
+ imply support. */
|
|
|
+ check_cap(EDSP, ARMV5TE);
|
|
|
+ check_cap(TLS, ARMV6);
|
|
|
+ check_cap(THUMBEE, ARMV6T2);
|
|
|
+ check_cap(VFP, VFP);
|
|
|
+ check_cap(VFPv3, VFPV3);
|
|
|
+ check_cap(NEON, NEON);
|
|
|
+
|
|
|
+ /* The v6 checks above are not reliable so let higher flags
|
|
|
+ trickle down. */
|
|
|
+ if (flags & (AV_CPU_FLAG_VFPV3 | AV_CPU_FLAG_NEON))
|
|
|
+ flags |= AV_CPU_FLAG_ARMV6T2;
|
|
|
+ if (flags & AV_CPU_FLAG_ARMV6T2)
|
|
|
+ flags |= AV_CPU_FLAG_ARMV6;
|
|
|
+
|
|
|
+ return flags;
|
|
|
+}
|
|
|
+
|
|
|
+#else
|
|
|
+
|
|
|
int ff_get_cpu_flags_arm(void)
|
|
|
{
|
|
|
return AV_CPU_FLAG_ARMV5TE * HAVE_ARMV5TE |
|
|
@@ -28,3 +109,5 @@ int ff_get_cpu_flags_arm(void)
|
|
|
AV_CPU_FLAG_VFPV3 * HAVE_VFPV3 |
|
|
|
AV_CPU_FLAG_NEON * HAVE_NEON;
|
|
|
}
|
|
|
+
|
|
|
+#endif
|