This allows compiling optimised functions for features not enabled
in the core build and selecting these at runtime if the system has
the necessary support.

Signed-off-by: Mans Rullgard <[email protected]>
---
 configure           |  9 +++++++-
 libavutil/arm/cpu.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 68 insertions(+), 1 deletion(-)

diff --git a/configure b/configure
index 99b0e71..6af598f 100755
--- a/configure
+++ b/configure
@@ -1193,6 +1193,7 @@ HAVE_LIST="
     asm_mod_y
     attribute_may_alias
     attribute_packed
+    asm_hwcap_h
     closesocket
     cmov
     CommandLineToArgvW
@@ -1211,6 +1212,7 @@ HAVE_LIST="
     dxva_h
     ebp_available
     ebx_available
+    Elf32_auxv_t
     fast_64bit
     fast_clz
     fast_cmov
@@ -3164,7 +3166,12 @@ EOF
     enabled neon    && check_insn neon    'vadd.i16 q0, q0, q0'
     enabled vfpv3   && check_insn vfpv3   'vmov.f32 s0, #1.0'
 
-    map 'enabled_any ${v}_external ${v}_inline || disable $v' 
$ARCH_EXT_LIST_ARM
+    check_type elf.h Elf32_auxv_t
+    check_header asm/hwcap.h
+
+    enabled_all asm_hwcap_h Elf32_auxv_t ||
+        map 'enabled_any ${v}_external ${v}_inline || disable $v' \
+            $ARCH_EXT_LIST_ARM
 
     check_inline_asm asm_mod_q '"add r0, %Q0, %R0" :: "r"((long long)0)'
     check_inline_asm asm_mod_y '"vmul.i32 d0, d0, %y0" :: "x"(0)'
diff --git a/libavutil/arm/cpu.c b/libavutil/arm/cpu.c
index 33dca1c..c41a048 100644
--- a/libavutil/arm/cpu.c
+++ b/libavutil/arm/cpu.c
@@ -19,6 +19,64 @@
 #include "libavutil/cpu.h"
 #include "config.h"
 
+#if HAVE_ELF32_AUXV_T && HAVE_ASM_HWCAP_H
+#include <stdio.h>
+#include <elf.h>
+#include <asm/hwcap.h>
+
+static int get_hwcap(Elf32_auxv_t *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) {
+            err = 0;
+            break;
+        }
+    }
+
+    fclose(f);
+    return err;
+}
+
+int ff_get_cpu_flags_arm(void)
+{
+    Elf32_auxv_t auxv;
+    int flags = 0;
+
+    if (get_hwcap(&auxv) < 0)
+        return 0;
+
+#define check_cap(cap, flag) do {               \
+        if (auxv.a_un.a_val & 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 +86,5 @@ int ff_get_cpu_flags_arm(void)
            AV_CPU_FLAG_VFPV3   * HAVE_VFPV3   |
            AV_CPU_FLAG_NEON    * HAVE_NEON;
 }
+
+#endif
-- 
1.8.0

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to