[FFmpeg-devel] [PATCH] avutil: runtime cpu detection for mips

shivraj.patil at imgtec.com shivraj.patil at imgtec.com
Wed Sep 30 15:33:46 CEST 2015


From: Shivraj Patil <shivraj.patil at imgtec.com>

Signed-off-by: Shivraj Patil <shivraj.patil at imgtec.com>
---
 libavcodec/mips/hevcdsp_init_mips.c |    6 +-
 libavutil/cpu.c                     |   35 ++++++++++
 libavutil/cpu.h                     |    8 +++
 libavutil/cpu_internal.h            |    1 +
 libavutil/mips/Makefile             |    1 +
 libavutil/mips/cpu.c                |  124 +++++++++++++++++++++++++++++++++++
 libavutil/mips/cpu.h                |   36 ++++++++++
 7 files changed, 210 insertions(+), 1 deletion(-)
 create mode 100644 libavutil/mips/cpu.c
 create mode 100644 libavutil/mips/cpu.h

diff --git a/libavcodec/mips/hevcdsp_init_mips.c b/libavcodec/mips/hevcdsp_init_mips.c
index 3675b93..499d2e8 100644
--- a/libavcodec/mips/hevcdsp_init_mips.c
+++ b/libavcodec/mips/hevcdsp_init_mips.c
@@ -19,6 +19,7 @@
  */
 
 #include "libavcodec/mips/hevcdsp_mips.h"
+#include "libavutil/mips/cpu.h"
 
 #if HAVE_MSA
 static av_cold void hevc_dsp_init_msa(HEVCDSPContext *c,
@@ -449,6 +450,9 @@ static av_cold void hevc_dsp_init_msa(HEVCDSPContext *c,
 void ff_hevc_dsp_init_mips(HEVCDSPContext *c, const int bit_depth)
 {
 #if HAVE_MSA
-    hevc_dsp_init_msa(c, bit_depth);
+    int cpu_flags = av_get_cpu_flags();
+
+    if (have_msa(cpu_flags))
+        hevc_dsp_init_msa(c, bit_depth);
 #endif  // #if HAVE_MSA
 }
diff --git a/libavutil/cpu.c b/libavutil/cpu.c
index 780368d..1e716c6 100644
--- a/libavutil/cpu.c
+++ b/libavutil/cpu.c
@@ -86,6 +86,8 @@ int av_get_cpu_flags(void)
         flags = ff_get_cpu_flags_ppc();
     if (ARCH_X86)
         flags = ff_get_cpu_flags_x86();
+    if (ARCH_MIPS)
+        flags = ff_get_cpu_flags_mips();
 
     checked = 1;
     return flags;
@@ -156,6 +158,17 @@ int av_parse_cpu_flags(const char *s)
         { "armv8",    NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_ARMV8    },    .unit = "flags" },
         { "neon",     NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_NEON     },    .unit = "flags" },
         { "vfp",      NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_VFP      },    .unit = "flags" },
+#elif ARCH_MIPS
+        { "mipsfpu",  NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MIPSFPU   },   .unit = "flags" },
+        { "mips32r2", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MIPS32R2  },   .unit = "flags" },
+        { "mips32r5", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MIPS32R5  },   .unit = "flags" },
+        { "dspr1",    NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MIPSDSPR1 },   .unit = "flags" },
+        { "dspr2",    NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MIPSDSPR2 },   .unit = "flags" },
+        { "msa",      NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MSA       },   .unit = "flags" },
+#elif ARCH_MIPS64
+        { "mipsfpu",  NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MIPSFPU   },   .unit = "flags" },
+        { "mips64r6", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MIPS64R6  },   .unit = "flags" },
+        { "msa",      NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MSA       },   .unit = "flags" },
 #endif
         { NULL },
     };
@@ -234,6 +247,17 @@ int av_parse_cpu_caps(unsigned *flags, const char *s)
         { "armv8",    NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_ARMV8    },    .unit = "flags" },
         { "neon",     NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_NEON     },    .unit = "flags" },
         { "vfp",      NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_VFP      },    .unit = "flags" },
+#elif ARCH_MIPS
+        { "mipsfpu",  NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MIPSFPU   },   .unit = "flags" },
+        { "mips32r2", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MIPS32R2  },   .unit = "flags" },
+        { "mips32r5", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MIPS32R5  },   .unit = "flags" },
+        { "dspr1",    NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MIPSDSPR1 },   .unit = "flags" },
+        { "dspr2",    NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MIPSDSPR2 },   .unit = "flags" },
+        { "msa",      NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MSA       },   .unit = "flags" },
+#elif ARCH_MIPS64
+        { "mipsfpu",  NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MIPSFPU   },   .unit = "flags" },
+        { "mips64r6", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MIPS64R6  },   .unit = "flags" },
+        { "msa",      NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MSA       },   .unit = "flags" },
 #endif
         { NULL },
     };
@@ -334,6 +358,17 @@ static const struct {
     { AV_CPU_FLAG_AVX2,      "avx2"       },
     { AV_CPU_FLAG_BMI1,      "bmi1"       },
     { AV_CPU_FLAG_BMI2,      "bmi2"       },
+#elif ARCH_MIPS
+    { AV_CPU_FLAG_MIPSFPU,   "mipsfpu"    },
+    { AV_CPU_FLAG_MIPS32R2,  "mips32r2"   },
+    { AV_CPU_FLAG_MIPS32R5,  "mips32r5"   },
+    { AV_CPU_FLAG_MIPSDSPR1, "dspr1"      },
+    { AV_CPU_FLAG_MIPSDSPR2, "dspr2"      },
+    { AV_CPU_FLAG_MSA,       "msa"        },
+#elif ARCH_MIPS64
+    { AV_CPU_FLAG_MIPSFPU    "mipsfpu"    },
+    { AV_CPU_FLAG_MIPS64R6   "mips64r6"   },
+    { AV_CPU_FLAG_MSA        "msa"        },
 #endif
     { 0 }
 };
diff --git a/libavutil/cpu.h b/libavutil/cpu.h
index 9403eca..a636d99 100644
--- a/libavutil/cpu.h
+++ b/libavutil/cpu.h
@@ -65,6 +65,14 @@
 #define AV_CPU_FLAG_ARMV8        (1 << 6)
 #define AV_CPU_FLAG_SETEND       (1 <<16)
 
+#define AV_CPU_FLAG_MIPSFPU      (1 << 0)
+#define AV_CPU_FLAG_MIPS32R2     (1 << 1)
+#define AV_CPU_FLAG_MIPS32R5     (1 << 2)
+#define AV_CPU_FLAG_MIPS64R6     (1 << 3)
+#define AV_CPU_FLAG_MIPSDSPR1    (1 << 4)
+#define AV_CPU_FLAG_MIPSDSPR2    (1 << 5)
+#define AV_CPU_FLAG_MSA          (1 << 6)
+
 /**
  * Return the flags which specify extensions supported by the CPU.
  * The returned value is affected by av_force_cpu_flags() if that was used
diff --git a/libavutil/cpu_internal.h b/libavutil/cpu_internal.h
index 2105298..bedbcfb 100644
--- a/libavutil/cpu_internal.h
+++ b/libavutil/cpu_internal.h
@@ -40,5 +40,6 @@ int ff_get_cpu_flags_aarch64(void);
 int ff_get_cpu_flags_arm(void);
 int ff_get_cpu_flags_ppc(void);
 int ff_get_cpu_flags_x86(void);
+int ff_get_cpu_flags_mips(void);
 
 #endif /* AVUTIL_CPU_INTERNAL_H */
diff --git a/libavutil/mips/Makefile b/libavutil/mips/Makefile
index dbfa5aa..c83c6de 100644
--- a/libavutil/mips/Makefile
+++ b/libavutil/mips/Makefile
@@ -1 +1,2 @@
 OBJS += mips/float_dsp_mips.o
+OBJS += mips/cpu.o
diff --git a/libavutil/mips/cpu.c b/libavutil/mips/cpu.c
new file mode 100644
index 0000000..45ebfe1
--- /dev/null
+++ b/libavutil/mips/cpu.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2015 Manojkumar Bhosale (Manojkumar.Bhosale at imgtec.com)
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "libavutil/cpu.h"
+#include "libavutil/cpu_internal.h"
+#include "libavutil/avstring.h"
+#include "config.h"
+
+#define CORE_FLAG(f) \
+    (AV_CPU_FLAG_ ## f * (HAVE_ ## f || HAVE_ ## f ## _EXTERNAL || HAVE_ ## f ## _INLINE))
+
+#define CORE_CPU_FLAGS      \
+    (CORE_FLAG(MIPSFPU)   | \
+     CORE_FLAG(MIPS32R2)  | \
+     CORE_FLAG(MIPS32R5)  | \
+     CORE_FLAG(MIPS64R6)  | \
+     CORE_FLAG(MIPSDSPR1) | \
+     CORE_FLAG(MIPSDSPR2) | \
+     CORE_FLAG(MSA))
+
+#define HWCAP_VZ        (1 << 0)
+#define HWCAP_EVA       (1 << 1)
+#define HWCAP_HTW       (1 << 2)
+#define HWCAP_FPU       (1 << 3)
+#define HWCAP_MIPS32R2  (1 << 4)
+#define HWCAP_MIPS32R5  (1 << 5)
+#define HWCAP_MIPS64R6  (1 << 6)
+#define HWCAP_DSPR1     (1 << 7)
+#define HWCAP_DSPR2     (1 << 8)
+#define HWCAP_MSA       (1 << 9)
+
+static int get_cpuinfo(uint32_t *hwcap)
+{
+    FILE *f = fopen("/proc/cpuinfo", "r");
+    char buf[200];
+
+    if (!f)
+        return -1;
+
+    *hwcap = 0;
+    while (fgets(buf, sizeof(buf), f)) {
+        if (av_strstart(buf, "isa", NULL)) {
+            if (strstr(buf, "mips32r2"))
+                *hwcap |= HWCAP_MIPS32R2;
+            if (strstr(buf, "mips32r5"))
+                *hwcap |= HWCAP_MIPS32R5;
+            if (strstr(buf, "mips64r6"))
+                *hwcap |= HWCAP_MIPS64R6;
+        }
+
+        if (av_strstart(buf, "ASEs implemented", NULL)) {
+            if (strstr(buf, "vz"))
+                *hwcap |= HWCAP_VZ;
+            if (strstr(buf, "eva"))
+                *hwcap |= HWCAP_EVA;
+            if (strstr(buf, "htw"))
+                *hwcap |= HWCAP_HTW;
+            if (strstr(buf, "msa"))
+            {
+                *hwcap |= HWCAP_MSA;
+                *hwcap |= HWCAP_FPU;
+            }
+            if (strstr(buf, "dsp"))
+                *hwcap |= HWCAP_DSPR1;
+            if (strstr(buf, "dsp2"))
+                *hwcap |= HWCAP_DSPR2;
+            break;
+        }
+    }
+
+    fclose(f);
+    return 0;
+}
+
+int ff_get_cpu_flags_mips(void)
+{
+    int cpuflags = CORE_CPU_FLAGS;
+    int hwcpuflags = 0;
+    uint32_t hwcap;
+
+#if !CONFIG_RUNTIME_CPUDETECT
+    return cpuflags;
+#endif
+
+    if (get_cpuinfo(&hwcap) < 0)
+        return cpuflags;
+
+#define set_cpucap(cap, flag) do {                                    \
+        if ((hwcap & HWCAP_ ## cap) && (cpuflags & CORE_FLAG(flag)))  \
+            hwcpuflags |= AV_CPU_FLAG_ ## flag;                       \
+    } while (0)
+
+    /* add ISA and ASE capabilities in cpuflags */
+    set_cpucap(FPU,      MIPSFPU);
+    set_cpucap(MIPS32R2, MIPS32R2);
+    set_cpucap(MIPS32R5, MIPS32R5);
+    set_cpucap(MIPS64R6, MIPS64R6);
+    set_cpucap(DSPR1,    MIPSDSPR1);
+    set_cpucap(DSPR2,    MIPSDSPR2);
+    set_cpucap(MSA,      MSA);
+
+    return hwcpuflags;
+}
diff --git a/libavutil/mips/cpu.h b/libavutil/mips/cpu.h
new file mode 100644
index 0000000..24813f6
--- /dev/null
+++ b/libavutil/mips/cpu.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015 Manojkumar Bhosale (Manojkumar.Bhosale at imgtec.com)
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVUTIL_MIPS_CPU_H
+#define AVUTIL_MIPS_CPU_H
+
+#include "config.h"
+#include "libavutil/cpu.h"
+#include "libavutil/cpu_internal.h"
+
+#define have_mipsfpu(flags)     CPUEXT(flags, MIPSFPU)
+#define have_mips32r2(flags)    CPUEXT(flags, MIPS32R2)
+#define have_mips32r5(flags)    CPUEXT(flags, MIPS32R5)
+#define have_mips64r6(flags)    CPUEXT(flags, MIPS64R6)
+#define have_mipsdspr1(flags)   CPUEXT(flags, MIPSDSPR1)
+#define have_mipsdspr2(flags)   CPUEXT(flags, MIPSDSPR2)
+#define have_msa(flags)         CPUEXT(flags, MSA)
+
+#endif /* #ifndef AVUTIL_MIPS_CPU_H */
-- 
1.7.9.5



More information about the ffmpeg-devel mailing list