[FFmpeg-devel] [RFC] use av_get_cpu_flags for real runtime CPU detection in swscale

Janne Grunau janne-ffmpeg
Thu Sep 9 12:23:41 CEST 2010


On Wed, Sep 08, 2010 at 11:42:56PM +0200, Michael Niedermayer wrote:
> On Wed, Sep 08, 2010 at 06:17:27PM +0200, Janne Grunau wrote:
> > Hi,
> > 
> > attached patch implements runtime CPU detection in libswscale. One minor
> > problem is that it changes behaviour on existing code which sets
> > individual flags but obviously not the new SWS_CPU_CAPS_FORCE. I think
> > it's acceptable since the flags have no effect with
> > !CONFIG_RUNTIME_CPUDETECT.
> > 
> > Janne
> 
> >  swscale.h |    3 ++-
> >  utils.c   |   22 +++++++++++++++++++++-
> >  2 files changed, 23 insertions(+), 2 deletions(-)
> > c54cc19db9288e0cce8f8de94ec509442ef9b369  swscale_runtime_cpu_detection.diff
> > diff --git a/swscale.h b/swscale.h
> > index 4e11c9a..ca63796 100644
> > --- a/swscale.h
> > +++ b/swscale.h
> > @@ -30,7 +30,7 @@
> >  #include "libavutil/avutil.h"
> >  
> >  #define LIBSWSCALE_VERSION_MAJOR 0
> > -#define LIBSWSCALE_VERSION_MINOR 11
> > +#define LIBSWSCALE_VERSION_MINOR 12
> >  #define LIBSWSCALE_VERSION_MICRO 0
> >  
> >  #define LIBSWSCALE_VERSION_INT  AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \
> > @@ -93,6 +93,7 @@ const char *swscale_license(void);
> >  #define SWS_CPU_CAPS_ALTIVEC  0x10000000
> >  #define SWS_CPU_CAPS_BFIN     0x01000000
> >  #define SWS_CPU_CAPS_SSE2     0x02000000
> > +#define SWS_CPU_CAPS_FORCE    0x00100000
> >  
> >  #define SWS_MAX_REDUCE_CUTOFF 0.002
> >  
> > diff --git a/utils.c b/utils.c
> > index e9400f8..9375489 100644
> > --- a/utils.c
> > +++ b/utils.c
> > @@ -44,6 +44,7 @@
> >  #include "libavutil/avutil.h"
> >  #include "libavutil/bswap.h"
> >  #include "libavutil/pixdesc.h"
> > +#include "libavutil/cpu.h"
> >  
> >  unsigned swscale_version(void)
> >  {
> > @@ -722,7 +723,26 @@ static int handle_jpeg(enum PixelFormat *format)
> >  
> >  static int update_flags_cpu(int flags)
> >  {
> > -#if !CONFIG_RUNTIME_CPUDETECT //ensure that the flags match the compiled variant if cpudetect is off
> > +#if CONFIG_RUNTIME_CPUDETECT
> > +    int cpuflags;
> > +
> > +    if (!(flags & SWS_CPU_CAPS_FORCE)) {
> > +        flags &= ~(SWS_CPU_CAPS_MMX|SWS_CPU_CAPS_MMX2|SWS_CPU_CAPS_3DNOW|SWS_CPU_CAPS_ALTIVEC|SWS_CPU_CAPS_BFIN);
> > +
> > +        cpuflags = av_get_cpu_flags();
> > +
> > +        if (ARCH_X86 && cpuflags & AV_CPU_FLAG_MMX)
> > +            flags |= SWS_CPU_CAPS_MMX;
> > +        if (ARCH_X86 && cpuflags & AV_CPU_FLAG_MMX2)
> > +            flags |= SWS_CPU_CAPS_MMX2;
> > +        if (ARCH_X86 && cpuflags & AV_CPU_FLAG_3DNOW)
> > +            flags |= SWS_CPU_CAPS_3DNOW;;
> > +        if (ARCH_X86 && cpuflags & AV_CPU_FLAG_SSE2)
> > +            flags |= SWS_CPU_CAPS_SSE2;
> > +        if (ARCH_PPC && cpuflags & AV_CPU_FLAG_ALTIVEC)
> > +            flags |= SWS_CPU_CAPS_ALTIVEC;
> > +    }
> 
> update_flags_cpu() is called on each sws_getCachedContext() and redoing cpu
> detect on each such calls seems hackish

changed see attached patch

> besides a AUTODETECT instead of FORCE would not break API

I guess I can live with AUTODETECT if the API change to AV_CPU_FLAG_ is
ok (together with a change to AV_CPU_FLAG_FORCE).

Janne
-------------- next part --------------
diff --git a/libswscale/swscale.h b/libswscale/swscale.h
index 4e11c9a..6423334 100644
--- a/libswscale/swscale.h
+++ b/libswscale/swscale.h
@@ -30,7 +30,7 @@
 #include "libavutil/avutil.h"
 
 #define LIBSWSCALE_VERSION_MAJOR 0
-#define LIBSWSCALE_VERSION_MINOR 11
+#define LIBSWSCALE_VERSION_MINOR 12
 #define LIBSWSCALE_VERSION_MICRO 0
 
 #define LIBSWSCALE_VERSION_INT  AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \
@@ -93,6 +93,7 @@ const char *swscale_license(void);
 #define SWS_CPU_CAPS_ALTIVEC  0x10000000
 #define SWS_CPU_CAPS_BFIN     0x01000000
 #define SWS_CPU_CAPS_SSE2     0x02000000
+#define SWS_CPU_CAPS_AUTO     0x00100000 //< auto detect CPU extensions
 
 #define SWS_MAX_REDUCE_CUTOFF 0.002
 
diff --git a/libswscale/utils.c b/libswscale/utils.c
index e9400f8..00bd219 100644
--- a/libswscale/utils.c
+++ b/libswscale/utils.c
@@ -44,6 +44,7 @@
 #include "libavutil/avutil.h"
 #include "libavutil/bswap.h"
 #include "libavutil/pixdesc.h"
+#include "libavutil/cpu.h"
 
 unsigned swscale_version(void)
 {
@@ -722,7 +723,37 @@ static int handle_jpeg(enum PixelFormat *format)
 
 static int update_flags_cpu(int flags)
 {
-#if !CONFIG_RUNTIME_CPUDETECT //ensure that the flags match the compiled variant if cpudetect is off
+#if CONFIG_RUNTIME_CPUDETECT
+    static int cpuflags;
+    int tmp_flags;
+
+    if (!cpuflags) {
+        
+        tmp_flags = av_get_cpu_flags();
+
+        if (ARCH_X86 && tmp_flags & AV_CPU_FLAG_MMX)
+            cpuflags |= SWS_CPU_CAPS_MMX;
+        if (ARCH_X86 && tmp_flags & AV_CPU_FLAG_MMX2)
+            cpuflags |= SWS_CPU_CAPS_MMX2;
+        if (ARCH_X86 && tmp_flags & AV_CPU_FLAG_3DNOW)
+            cpuflags |= SWS_CPU_CAPS_3DNOW;;
+        if (ARCH_X86 && tmp_flags & AV_CPU_FLAG_SSE2)
+            cpuflags |= SWS_CPU_CAPS_SSE2;
+        if (ARCH_PPC && tmp_flags & AV_CPU_FLAG_ALTIVEC)
+            cpuflags |= SWS_CPU_CAPS_ALTIVEC;
+        if (ARCH_BFIN)
+            cpuflags |= SWS_CPU_CAPS_BFIN;
+
+        if (!cpuflags)
+            cpuflags = SWS_CPU_CAPS_AUTO;
+    }
+
+    if (flags & SWS_CPU_CAPS_AUTO) {
+        flags &= ~(SWS_CPU_CAPS_MMX|SWS_CPU_CAPS_MMX2|SWS_CPU_CAPS_3DNOW|SWS_CPU_CAPS_ALTIVEC|SWS_CPU_CAPS_BFIN);
+        if (cpuflags != SWS_CPU_CAPS_AUTO)
+            flags |= cpuflags;
+    }
+#else //ensure that the flags match the compiled variant if cpudetect is off
     flags &= ~(SWS_CPU_CAPS_MMX|SWS_CPU_CAPS_MMX2|SWS_CPU_CAPS_3DNOW|SWS_CPU_CAPS_ALTIVEC|SWS_CPU_CAPS_BFIN);
     flags |= ff_hardcodedcpuflags();
 #endif /* CONFIG_RUNTIME_CPUDETECT */



More information about the ffmpeg-devel mailing list