diff mbox

[FFmpeg-devel,3/4] avcodec: Add runtime check for mips msa.

Message ID 1576651151-22927-3-git-send-email-yinshiyou-hf@loongson.cn
State Superseded
Headers show

Commit Message

殷时友 Dec. 18, 2019, 6:39 a.m. UTC
---
 configure                                   |  8 ++++++--
 ffbuild/common.mak                          |  4 ++++
 libavcodec/mips/blockdsp_init_mips.c        |  3 ++-
 libavcodec/mips/h263dsp_init_mips.c         |  5 ++++-
 libavcodec/mips/h264chroma_init_mips.c      |  3 ++-
 libavcodec/mips/h264dsp_init_mips.c         |  3 ++-
 libavcodec/mips/h264pred_init_mips.c        |  3 ++-
 libavcodec/mips/h264qpel_init_mips.c        |  3 ++-
 libavcodec/mips/hevcdsp_init_mips.c         |  3 ++-
 libavcodec/mips/hevcpred_init_mips.c        |  5 ++++-
 libavcodec/mips/hpeldsp_init_mips.c         |  3 ++-
 libavcodec/mips/idctdsp_init_mips.c         |  3 ++-
 libavcodec/mips/me_cmp_init_mips.c          |  5 ++++-
 libavcodec/mips/mpegvideo_init_mips.c       |  3 ++-
 libavcodec/mips/mpegvideoencdsp_init_mips.c |  5 ++++-
 libavcodec/mips/pixblockdsp_init_mips.c     |  3 ++-
 libavcodec/mips/qpeldsp_init_mips.c         |  5 ++++-
 libavcodec/mips/vc1dsp_init_mips.c          |  3 ++-
 libavcodec/mips/videodsp_init.c             |  5 ++++-
 libavcodec/mips/vp3dsp_init_mips.c          |  3 ++-
 libavcodec/mips/vp8dsp_init_mips.c          |  3 ++-
 libavcodec/mips/vp9dsp_init_mips.c          |  3 ++-
 libavutil/cpu.c                             |  2 ++
 libavutil/cpu.h                             |  1 +
 libavutil/mips/cpu.c                        | 23 +++++++++++++++++++----
 libavutil/mips/cpu.h                        |  1 +
 libavutil/tests/cpu.c                       |  1 +
 27 files changed, 86 insertions(+), 26 deletions(-)
diff mbox

Patch

diff --git a/configure b/configure
index cc7a0da..2cdfd32 100755
--- a/configure
+++ b/configure
@@ -5819,14 +5819,17 @@  elif enabled mips; then
 
     enabled mipsfpu && check_inline_asm_flags mipsfpu '"cvt.d.l $f0, $f2"' '-mhard-float'
     enabled mipsfpu && (enabled mips32r5 || enabled mips32r6 || enabled mips64r6) && check_inline_asm_flags mipsfpu '"cvt.d.l $f0, $f1"' '-mfp64'
-    enabled mipsfpu && enabled msa && check_inline_asm_flags msa '"addvi.b $w0, $w1, 1"' '-mmsa' && check_headers msa.h || disable msa
+    enabled mipsfpu && enabled msa && check_inline_asm msa '"addvi.b $w0, $w1, 1"' '-mmsa' && check_headers msa.h || disable msa
     enabled mipsdsp && check_inline_asm_flags mipsdsp '"addu.qb $t0, $t1, $t2"' '-mdsp'
     enabled mipsdspr2 && check_inline_asm_flags mipsdspr2 '"absq_s.qb $t0, $t1"' '-mdspr2'
-    enabled msa && enabled msa2 && check_inline_asm_flags msa2 '"nxbits.any.b $w0, $w0"' '-mmsa2' && check_headers msa2.h || disable msa2
+    enabled msa && enabled msa2 && check_inline_asm msa2 '"nxbits.any.b $w0, $w0"' '-mmsa2' && check_headers msa2.h || disable msa2
 
     if enabled bigendian && enabled msa; then
         disable msa
+        disable msa2
     fi
+    enabled msa && append MSAFLAGS "-mmsa"
+    enabled msa2 && append MSAFLAGS "-mmsa2"
 
 elif enabled parisc; then
 
@@ -7362,6 +7365,7 @@  OBJCFLAGS=$OBJCFLAGS
 ASFLAGS=$ASFLAGS
 NVCCFLAGS=$nvccflags
 MMIFLAGS=$MMIFLAGS
+MSAFLAGS=$MSAFLAGS
 AS_C=$AS_C
 AS_O=$AS_O
 OBJCC_C=$OBJCC_C
diff --git a/ffbuild/common.mak b/ffbuild/common.mak
index d3cce1a..5d0b586 100644
--- a/ffbuild/common.mak
+++ b/ffbuild/common.mak
@@ -60,10 +60,14 @@  COMPILE_X86ASM = $(call COMPILE,X86ASM)
 COMPILE_HOSTC = $(call COMPILE,HOSTCC)
 COMPILE_NVCC = $(call COMPILE,NVCC)
 COMPILE_MMI = $(call COMPILE_WITH_FLAG,CC,MMIFLAGS)
+COMPILE_MSA = $(call COMPILE_WITH_FLAG,CC,MSAFLAGS)
 
 %_mmi.o: %_mmi.c
 	$(COMPILE_MMI)
 
+%_msa.o: %_msa.c
+	$(COMPILE_MSA)
+
 %.o: %.c
 	$(COMPILE_C)
 
diff --git a/libavcodec/mips/blockdsp_init_mips.c b/libavcodec/mips/blockdsp_init_mips.c
index 85e928c..ccc2ab3 100644
--- a/libavcodec/mips/blockdsp_init_mips.c
+++ b/libavcodec/mips/blockdsp_init_mips.c
@@ -52,6 +52,7 @@  void ff_blockdsp_init_mips(BlockDSPContext *c)
         blockdsp_init_mmi(c);
 #endif /* HAVE_MMI */
 #if HAVE_MSA
-    blockdsp_init_msa(c);
+    if (MIPS_MSA(cpu_flags))
+        blockdsp_init_msa(c);
 #endif  // #if HAVE_MSA
 }
diff --git a/libavcodec/mips/h263dsp_init_mips.c b/libavcodec/mips/h263dsp_init_mips.c
index 09bd937..a3a6a04 100644
--- a/libavcodec/mips/h263dsp_init_mips.c
+++ b/libavcodec/mips/h263dsp_init_mips.c
@@ -19,6 +19,7 @@ 
  */
 
 #include "h263dsp_mips.h"
+#include "libavutil/mips/cpu.h"
 
 #if HAVE_MSA
 static av_cold void h263dsp_init_msa(H263DSPContext *c)
@@ -30,7 +31,9 @@  static av_cold void h263dsp_init_msa(H263DSPContext *c)
 
 av_cold void ff_h263dsp_init_mips(H263DSPContext *c)
 {
+    int cpu_flags = av_get_cpu_flags();
 #if HAVE_MSA
-    h263dsp_init_msa(c);
+    if (MIPS_MSA(cpu_flags))
+        h263dsp_init_msa(c);
 #endif  // #if HAVE_MSA
 }
diff --git a/libavcodec/mips/h264chroma_init_mips.c b/libavcodec/mips/h264chroma_init_mips.c
index 7c75766..8b75837 100644
--- a/libavcodec/mips/h264chroma_init_mips.c
+++ b/libavcodec/mips/h264chroma_init_mips.c
@@ -61,6 +61,7 @@  av_cold void ff_h264chroma_init_mips(H264ChromaContext *c, int bit_depth)
         h264chroma_init_mmi(c, bit_depth);
 #endif /* HAVE_MMI */
 #if HAVE_MSA
-    h264chroma_init_msa(c, bit_depth);
+    if (MIPS_MSA(cpu_flags))
+        h264chroma_init_msa(c, bit_depth);
 #endif  // #if HAVE_MSA
 }
diff --git a/libavcodec/mips/h264dsp_init_mips.c b/libavcodec/mips/h264dsp_init_mips.c
index 3ed4d76..7796b09 100644
--- a/libavcodec/mips/h264dsp_init_mips.c
+++ b/libavcodec/mips/h264dsp_init_mips.c
@@ -145,6 +145,7 @@  av_cold void ff_h264dsp_init_mips(H264DSPContext *c, const int bit_depth,
         h264dsp_init_mmi(c, bit_depth, chroma_format_idc);
 #endif /* HAVE_MMI */
 #if HAVE_MSA
-    h264dsp_init_msa(c, bit_depth, chroma_format_idc);
+    if (MIPS_MSA(cpu_flags))
+        h264dsp_init_msa(c, bit_depth, chroma_format_idc);
 #endif  // #if HAVE_MSA
 }
diff --git a/libavcodec/mips/h264pred_init_mips.c b/libavcodec/mips/h264pred_init_mips.c
index 30aefe5..11f7073 100644
--- a/libavcodec/mips/h264pred_init_mips.c
+++ b/libavcodec/mips/h264pred_init_mips.c
@@ -150,6 +150,7 @@  av_cold void ff_h264_pred_init_mips(H264PredContext *h, int codec_id,
         h264_pred_init_mmi(h, codec_id, bit_depth, chroma_format_idc);
 #endif /* HAVE_MMI */
 #if HAVE_MSA
-    h264_pred_init_msa(h, codec_id, bit_depth, chroma_format_idc);
+    if (MIPS_MSA(cpu_flags))
+        h264_pred_init_msa(h, codec_id, bit_depth, chroma_format_idc);
 #endif  // #if HAVE_MSA
 }
diff --git a/libavcodec/mips/h264qpel_init_mips.c b/libavcodec/mips/h264qpel_init_mips.c
index 4f62766..b29cc63 100644
--- a/libavcodec/mips/h264qpel_init_mips.c
+++ b/libavcodec/mips/h264qpel_init_mips.c
@@ -247,6 +247,7 @@  av_cold void ff_h264qpel_init_mips(H264QpelContext *c, int bit_depth)
         h264qpel_init_mmi(c, bit_depth);
 #endif /* HAVE_MMI */
 #if HAVE_MSA
-    h264qpel_init_msa(c, bit_depth);
+    if (MIPS_MSA(cpu_flags))
+        h264qpel_init_msa(c, bit_depth);
 #endif  // #if HAVE_MSA
 }
diff --git a/libavcodec/mips/hevcdsp_init_mips.c b/libavcodec/mips/hevcdsp_init_mips.c
index 7f7c699..fbfa3a6 100644
--- a/libavcodec/mips/hevcdsp_init_mips.c
+++ b/libavcodec/mips/hevcdsp_init_mips.c
@@ -527,6 +527,7 @@  void ff_hevc_dsp_init_mips(HEVCDSPContext *c, const int bit_depth)
         hevc_dsp_init_mmi(c, bit_depth);
 #endif  // #if HAVE_MMI
 #if HAVE_MSA
-    hevc_dsp_init_msa(c, bit_depth);
+    if (MIPS_MSA(cpu_flags))
+        hevc_dsp_init_msa(c, bit_depth);
 #endif  // #if HAVE_MSA
 }
diff --git a/libavcodec/mips/hevcpred_init_mips.c b/libavcodec/mips/hevcpred_init_mips.c
index e987698..85a7215 100644
--- a/libavcodec/mips/hevcpred_init_mips.c
+++ b/libavcodec/mips/hevcpred_init_mips.c
@@ -21,6 +21,7 @@ 
 #include "config.h"
 #include "libavutil/attributes.h"
 #include "libavcodec/mips/hevcpred_mips.h"
+#include "libavutil/mips/cpu.h"
 
 #if HAVE_MSA
 static av_cold void hevc_pred_init_msa(HEVCPredContext *c, const int bit_depth)
@@ -43,7 +44,9 @@  static av_cold void hevc_pred_init_msa(HEVCPredContext *c, const int bit_depth)
 
 void ff_hevc_pred_init_mips(HEVCPredContext *c, const int bit_depth)
 {
+    int cpu_flags = av_get_cpu_flags();
 #if HAVE_MSA
-    hevc_pred_init_msa(c, bit_depth);
+    if (MIPS_MSA(cpu_flags))
+        hevc_pred_init_msa(c, bit_depth);
 #endif  // #if HAVE_MSA
 }
diff --git a/libavcodec/mips/hpeldsp_init_mips.c b/libavcodec/mips/hpeldsp_init_mips.c
index 3614d5c..ea08f5d 100644
--- a/libavcodec/mips/hpeldsp_init_mips.c
+++ b/libavcodec/mips/hpeldsp_init_mips.c
@@ -120,6 +120,7 @@  void ff_hpeldsp_init_mips(HpelDSPContext *c, int flags)
         ff_hpeldsp_init_mmi(c, flags);
 #endif  // #if HAVE_MMI
 #if HAVE_MSA
-    ff_hpeldsp_init_msa(c, flags);
+    if (MIPS_MSA(cpu_flags))
+        ff_hpeldsp_init_msa(c, flags);
 #endif  // #if HAVE_MSA
 }
diff --git a/libavcodec/mips/idctdsp_init_mips.c b/libavcodec/mips/idctdsp_init_mips.c
index 7aa4c52..9c2e2e1 100644
--- a/libavcodec/mips/idctdsp_init_mips.c
+++ b/libavcodec/mips/idctdsp_init_mips.c
@@ -72,6 +72,7 @@  av_cold void ff_idctdsp_init_mips(IDCTDSPContext *c, AVCodecContext *avctx,
         idctdsp_init_mmi(c, avctx, high_bit_depth);
 #endif /* HAVE_MMI */
 #if HAVE_MSA
-    idctdsp_init_msa(c, avctx, high_bit_depth);
+    if (MIPS_MSA(cpu_flags))
+        idctdsp_init_msa(c, avctx, high_bit_depth);
 #endif  // #if HAVE_MSA
 }
diff --git a/libavcodec/mips/me_cmp_init_mips.c b/libavcodec/mips/me_cmp_init_mips.c
index 219a0dc..b12b48a 100644
--- a/libavcodec/mips/me_cmp_init_mips.c
+++ b/libavcodec/mips/me_cmp_init_mips.c
@@ -19,6 +19,7 @@ 
  */
 
 #include "me_cmp_mips.h"
+#include "libavutil/mips/cpu.h"
 
 #if HAVE_MSA
 static av_cold void me_cmp_msa(MECmpContext *c, AVCodecContext *avctx)
@@ -50,7 +51,9 @@  static av_cold void me_cmp_msa(MECmpContext *c, AVCodecContext *avctx)
 
 av_cold void ff_me_cmp_init_mips(MECmpContext *c, AVCodecContext *avctx)
 {
+    int cpu_flags = av_get_cpu_flags();
 #if HAVE_MSA
-    me_cmp_msa(c, avctx);
+    if (MIPS_MSA(cpu_flags))
+        me_cmp_msa(c, avctx);
 #endif  // #if HAVE_MSA
 }
diff --git a/libavcodec/mips/mpegvideo_init_mips.c b/libavcodec/mips/mpegvideo_init_mips.c
index 271e26c..c227935 100644
--- a/libavcodec/mips/mpegvideo_init_mips.c
+++ b/libavcodec/mips/mpegvideo_init_mips.c
@@ -56,6 +56,7 @@  av_cold void ff_mpv_common_init_mips(MpegEncContext *s)
         dct_unquantize_init_mmi(s);
 #endif /* HAVE_MMI */
 #if HAVE_MSA
-    dct_unquantize_init_msa(s);
+    if (MIPS_MSA(cpu_flags))
+        dct_unquantize_init_msa(s);
 #endif  // #if HAVE_MSA
 }
diff --git a/libavcodec/mips/mpegvideoencdsp_init_mips.c b/libavcodec/mips/mpegvideoencdsp_init_mips.c
index 9bfe94e..cd3fb4c 100644
--- a/libavcodec/mips/mpegvideoencdsp_init_mips.c
+++ b/libavcodec/mips/mpegvideoencdsp_init_mips.c
@@ -20,6 +20,7 @@ 
 
 #include "libavcodec/bit_depth_template.c"
 #include "h263dsp_mips.h"
+#include "libavutil/mips/cpu.h"
 
 #if HAVE_MSA
 static av_cold void mpegvideoencdsp_init_msa(MpegvideoEncDSPContext *c,
@@ -34,7 +35,9 @@  static av_cold void mpegvideoencdsp_init_msa(MpegvideoEncDSPContext *c,
 av_cold void ff_mpegvideoencdsp_init_mips(MpegvideoEncDSPContext *c,
                                           AVCodecContext *avctx)
 {
+    int cpu_flags = av_get_cpu_flags();
 #if HAVE_MSA
-    mpegvideoencdsp_init_msa(c, avctx);
+    if (MIPS_MSA(cpu_flags))
+        mpegvideoencdsp_init_msa(c, avctx);
 #endif  // #if HAVE_MSA
 }
diff --git a/libavcodec/mips/pixblockdsp_init_mips.c b/libavcodec/mips/pixblockdsp_init_mips.c
index dfe094b..8ef18fc 100644
--- a/libavcodec/mips/pixblockdsp_init_mips.c
+++ b/libavcodec/mips/pixblockdsp_init_mips.c
@@ -67,6 +67,7 @@  void ff_pixblockdsp_init_mips(PixblockDSPContext *c, AVCodecContext *avctx,
         pixblockdsp_init_mmi(c, avctx, high_bit_depth);
 #endif /* HAVE_MMI */
 #if HAVE_MSA
-    pixblockdsp_init_msa(c, avctx, high_bit_depth);
+    if (MIPS_MSA(cpu_flags))
+        pixblockdsp_init_msa(c, avctx, high_bit_depth);
 #endif  // #if HAVE_MSA
 }
diff --git a/libavcodec/mips/qpeldsp_init_mips.c b/libavcodec/mips/qpeldsp_init_mips.c
index 140e8f8..d5f0994 100644
--- a/libavcodec/mips/qpeldsp_init_mips.c
+++ b/libavcodec/mips/qpeldsp_init_mips.c
@@ -19,6 +19,7 @@ 
  */
 
 #include "qpeldsp_mips.h"
+#include "libavutil/mips/cpu.h"
 
 #if HAVE_MSA
 static av_cold void qpeldsp_init_msa(QpelDSPContext *c)
@@ -161,7 +162,9 @@  static av_cold void qpeldsp_init_msa(QpelDSPContext *c)
 
 void ff_qpeldsp_init_mips(QpelDSPContext *c)
 {
+    int cpu_flags = av_get_cpu_flags();
 #if HAVE_MSA
-    qpeldsp_init_msa(c);
+    if (MIPS_MSA(cpu_flags))
+        qpeldsp_init_msa(c);
 #endif  // #if HAVE_MSA
 }
diff --git a/libavcodec/mips/vc1dsp_init_mips.c b/libavcodec/mips/vc1dsp_init_mips.c
index 2fa7e2c..972d72f 100644
--- a/libavcodec/mips/vc1dsp_init_mips.c
+++ b/libavcodec/mips/vc1dsp_init_mips.c
@@ -128,6 +128,7 @@  av_cold void ff_vc1dsp_init_mips(VC1DSPContext *dsp)
         vc1dsp_init_mmi(dsp);
 #endif /* HAVE_MMI */
 #if HAVE_MSA
-    vc1dsp_init_msa(dsp);
+    if (MIPS_MSA(cpu_flags))
+        vc1dsp_init_msa(dsp);
 #endif /* HAVE_MSA */
 }
diff --git a/libavcodec/mips/videodsp_init.c b/libavcodec/mips/videodsp_init.c
index 8170404..dc90464 100644
--- a/libavcodec/mips/videodsp_init.c
+++ b/libavcodec/mips/videodsp_init.c
@@ -22,6 +22,7 @@ 
 #include "libavutil/attributes.h"
 #include "libavutil/mips/asmdefs.h"
 #include "libavcodec/videodsp.h"
+#include "libavutil/mips/cpu.h"
 
 #if HAVE_MSA
 static void prefetch_mips(uint8_t *mem, ptrdiff_t stride, int h)
@@ -45,7 +46,9 @@  static void prefetch_mips(uint8_t *mem, ptrdiff_t stride, int h)
 
 av_cold void ff_videodsp_init_mips(VideoDSPContext *ctx, int bpc)
 {
+    int cpu_flags = av_get_cpu_flags();
 #if HAVE_MSA
-    ctx->prefetch = prefetch_mips;
+    if (MIPS_MSA(cpu_flags))
+        ctx->prefetch = prefetch_mips;
 #endif  // #if HAVE_MSA
 }
diff --git a/libavcodec/mips/vp3dsp_init_mips.c b/libavcodec/mips/vp3dsp_init_mips.c
index 8f15a32..4bab977 100644
--- a/libavcodec/mips/vp3dsp_init_mips.c
+++ b/libavcodec/mips/vp3dsp_init_mips.c
@@ -58,6 +58,7 @@  av_cold void ff_vp3dsp_init_mips(VP3DSPContext *c, int flags)
         vp3dsp_init_mmi(c, flags);
 #endif /* HAVE_MMI */
 #if HAVE_MSA
-    vp3dsp_init_msa(c, flags);
+    if (MIPS_MSA(cpu_flags))
+        vp3dsp_init_msa(c, flags);
 #endif /* HAVE_MSA */
 }
diff --git a/libavcodec/mips/vp8dsp_init_mips.c b/libavcodec/mips/vp8dsp_init_mips.c
index ef1d4d7..ca15662 100644
--- a/libavcodec/mips/vp8dsp_init_mips.c
+++ b/libavcodec/mips/vp8dsp_init_mips.c
@@ -200,6 +200,7 @@  av_cold void ff_vp8dsp_init_mips(VP8DSPContext *dsp)
         vp8dsp_init_mmi(dsp);
 #endif /* HAVE_MMI */
 #if HAVE_MSA
-    vp8dsp_init_msa(dsp);
+    if (MIPS_MSA(cpu_flags))
+        vp8dsp_init_msa(dsp);
 #endif  // #if HAVE_MSA
 }
diff --git a/libavcodec/mips/vp9dsp_init_mips.c b/libavcodec/mips/vp9dsp_init_mips.c
index 86d2c30..5e3e910 100644
--- a/libavcodec/mips/vp9dsp_init_mips.c
+++ b/libavcodec/mips/vp9dsp_init_mips.c
@@ -216,6 +216,7 @@  av_cold void ff_vp9dsp_init_mips(VP9DSPContext *dsp, int bpp)
         vp9dsp_init_mmi(dsp, bpp);
 #endif  // #if HAVE_MMI
 #if HAVE_MSA
-    vp9dsp_init_msa(dsp, bpp);
+    if (MIPS_MSA(cpu_flags))
+        vp9dsp_init_msa(dsp, bpp);
 #endif  // #if HAVE_MSA
 }
diff --git a/libavutil/cpu.c b/libavutil/cpu.c
index 1ce893b..3f09ffd 100644
--- a/libavutil/cpu.c
+++ b/libavutil/cpu.c
@@ -173,6 +173,7 @@  int av_parse_cpu_flags(const char *s)
         { "vfp",      NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_VFP      },    .unit = "flags" },
 #elif ARCH_MIPS
         { "mmi",      NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MMI      },    .unit = "flags" },
+        { "msa",      NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MSA      },    .unit = "flags" },
 #endif
         { NULL },
     };
@@ -256,6 +257,7 @@  int av_parse_cpu_caps(unsigned *flags, const char *s)
         { "vfp",      NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_VFP      },    .unit = "flags" },
 #elif ARCH_MIPS
         { "mmi",      NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MMI      },    .unit = "flags" },
+        { "msa",      NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MSA      },    .unit = "flags" },
 #endif
         { NULL },
     };
diff --git a/libavutil/cpu.h b/libavutil/cpu.h
index ce80b17..8599043 100644
--- a/libavutil/cpu.h
+++ b/libavutil/cpu.h
@@ -71,6 +71,7 @@ 
 #define AV_CPU_FLAG_VFP_VM       (1 << 7) ///< VFPv2 vector mode, deprecated in ARMv7-A and unavailable in various CPUs implementations
 
 #define AV_CPU_FLAG_MMI          (1 << 0)
+#define AV_CPU_FLAG_MSA          (1 << 1)
 #define AV_CPU_FLAG_SETEND       (1 <<16)
 
 /**
diff --git a/libavutil/mips/cpu.c b/libavutil/mips/cpu.c
index 4c2fa24..5d5cf63 100644
--- a/libavutil/mips/cpu.c
+++ b/libavutil/mips/cpu.c
@@ -36,6 +36,7 @@ 
 static int get_cpu_flags_from_cpuinfo(void)
 {
     int flags = 0;
+    int model_name_flag = 0;
     char buf[1024];
 
 # ifdef __linux__
@@ -45,15 +46,29 @@  static int get_cpu_flags_from_cpuinfo(void)
 
     memset(buf, 0, sizeof(buf));
     while (fgets(buf, sizeof(buf), fp)) {
-        if (!strncmp(buf, "model name", strlen("model name"))) {
-            if (strstr(buf, "Loongson-3")) {
+        if(model_name_flag && !strncmp(buf, "ASEs implemented", strlen("ASEs implemented"))) {
+            if (strstr(buf, "loongson-mmi") || strstr(buf, "loongson-ext")) {
                 flags |= AV_CPU_FLAG_MMI;
-            } else if (strstr(buf, "Loongson-2K")  || strstr(buf, "2K1000")) {
+            }
+            if (strstr(buf, "msa")) {
+                flags |= AV_CPU_FLAG_MSA;
+            }
+        } else if (!strncmp(buf, "model name", strlen("model name"))) {
+            /* In case of some kernel havn't add loongson extention in ASEs implemented,
+             * analysis model name is still needed.
+             */
+            if (strstr(buf, "3A4000")) {
+                flags |= AV_CPU_FLAG_MSA | AV_CPU_FLAG_MMI;
+            } else if (strstr(buf, "Loongson-3")) {
                 flags |= AV_CPU_FLAG_MMI;
+            } else if (strstr(buf, "Loongson-2K")  || strstr(buf, "2K1000")) {
+                flags |= AV_CPU_FLAG_MSA | AV_CPU_FLAG_MMI;
             }
-            break;
+            model_name_flag = 1;
         }
+        break;
     }
+
     fclose(fp);
 # endif
     return flags;
diff --git a/libavutil/mips/cpu.h b/libavutil/mips/cpu.h
index e62416a..e7ecc67 100644
--- a/libavutil/mips/cpu.h
+++ b/libavutil/mips/cpu.h
@@ -27,5 +27,6 @@ 
 #include "libavutil/cpu_internal.h"
 
 #define MIPS_MMI(flags)      CPUEXT(flags, MMI)
+#define MIPS_MSA(flags)      CPUEXT(flags, MSA)
 
 #endif /* AVUTIL_MIPS_CPU_H */
diff --git a/libavutil/tests/cpu.c b/libavutil/tests/cpu.c
index 0a4240a..25e0f75 100644
--- a/libavutil/tests/cpu.c
+++ b/libavutil/tests/cpu.c
@@ -76,6 +76,7 @@  static const struct {
     { AV_CPU_FLAG_AVX512,    "avx512"     },
 #elif ARCH_MIPS
     { AV_CPU_FLAG_MMI,       "mmi"        },
+    { AV_CPU_FLAG_MSA,       "msa"        },
 #endif
     { 0 }
 };