msvs: WinRT support
authorHenrik Gramner <henrik@gramner.com>
Sun, 24 Jan 2016 00:48:18 +0000 (01:48 +0100)
committerHenrik Gramner <henrik@gramner.com>
Mon, 11 Apr 2016 14:58:22 +0000 (16:58 +0200)
To compile x264 for WinRT the following additional steps has to be performed.

 * Ensure that the necessary SDK is installed.

 * Set the correct environment variables in the VS command prompt as shown at
   https://trac.ffmpeg.org/wiki/CompilationGuide/WinRT

 * Add one of the following to --extra-cflags depending on the target OS:
   "-DWINAPI_FAMILY=WINAPI_FAMILY_PC_APP -D_WIN32_WINNT=0x0A00" (Windows 10)
   "-DWINAPI_FAMILY=WINAPI_FAMILY_PC_APP -D_WIN32_WINNT=0x0603" (Windows 8.1)

common/osdep.c
common/osdep.h
common/win32thread.c
common/win32thread.h
configure

index 7835994..074a1f3 100644 (file)
@@ -126,6 +126,7 @@ int x264_stat( const char *path, x264_struct_stat *buf )
     return -1;
 }
 
+#if !HAVE_WINRT
 int x264_vfprintf( FILE *stream, const char *format, va_list arg )
 {
     HANDLE console = NULL;
@@ -167,3 +168,4 @@ int x264_is_pipe( const char *path )
     return 0;
 }
 #endif
+#endif
index dccbb6b..995d03c 100644 (file)
@@ -79,16 +79,20 @@ int x264_rename( const char *oldname, const char *newname );
 #define x264_struct_stat struct _stati64
 #define x264_fstat _fstati64
 int x264_stat( const char *path, x264_struct_stat *buf );
-int x264_vfprintf( FILE *stream, const char *format, va_list arg );
-int x264_is_pipe( const char *path );
 #else
 #define x264_fopen       fopen
 #define x264_rename      rename
 #define x264_struct_stat struct stat
 #define x264_fstat       fstat
 #define x264_stat        stat
-#define x264_vfprintf    vfprintf
-#define x264_is_pipe(x)  0
+#endif
+
+#if defined(_WIN32) && !HAVE_WINRT
+int x264_vfprintf( FILE *stream, const char *format, va_list arg );
+int x264_is_pipe( const char *path );
+#else
+#define x264_vfprintf vfprintf
+#define x264_is_pipe(x) 0
 #endif
 
 #ifdef _MSC_VER
index f25e777..8c43938 100644 (file)
@@ -5,6 +5,7 @@
  *
  * Authors: Steven Walters <kemuri9@gmail.com>
  *          Pegasys Inc. <http://www.pegasys-inc.com>
+ *          Henrik Gramner <henrik@gramner.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * this API does not detect nor utilize more than 64 cpus for systems that have them. */
 
 #include "common.h"
+
+#if HAVE_WINRT
+/* _beginthreadex() is technically the correct option, but it's only available for Desktop applications.
+ * Using CreateThread() as an alternative works on Windows Store and Windows Phone 8.1+ as long as we're
+ * using a dynamically linked MSVCRT which happens to be a requirement for WinRT applications anyway */
+#define _beginthreadex CreateThread
+#define InitializeCriticalSectionAndSpinCount(a, b) InitializeCriticalSectionEx(a, b, CRITICAL_SECTION_NO_DEBUG_INFO)
+#define WaitForSingleObject(a, b) WaitForSingleObjectEx(a, b, FALSE)
+#else
 #include <process.h>
+#endif
 
 /* number of times to spin a thread about to block on a locked mutex before retrying and sleeping if still locked */
 #define X264_SPIN_COUNT 0
 
-/* GROUP_AFFINITY struct */
-typedef struct
-{
-    ULONG_PTR mask; // KAFFINITY = ULONG_PTR
-    USHORT group;
-    USHORT reserved[3];
-} x264_group_affinity_t;
-
-typedef struct
-{
-    /* global mutex for replacing MUTEX_INITIALIZER instances */
-    x264_pthread_mutex_t static_mutex;
-
-    /* function pointers to conditional variable API on windows 6.0+ kernels */
-    void (WINAPI *cond_broadcast)( x264_pthread_cond_t *cond );
-    void (WINAPI *cond_init)( x264_pthread_cond_t *cond );
-    void (WINAPI *cond_signal)( x264_pthread_cond_t *cond );
-    BOOL (WINAPI *cond_wait)( x264_pthread_cond_t *cond, x264_pthread_mutex_t *mutex, DWORD milliseconds );
-} x264_win32thread_control_t;
-
-static x264_win32thread_control_t thread_control;
+/* global mutex for replacing MUTEX_INITIALIZER instances */
+static x264_pthread_mutex_t static_mutex;
 
 /* _beginthreadex requires that the start routine is __stdcall */
 static unsigned __stdcall x264_win32thread_worker( void *arg )
@@ -101,9 +93,9 @@ int x264_pthread_mutex_destroy( x264_pthread_mutex_t *mutex )
 
 int x264_pthread_mutex_lock( x264_pthread_mutex_t *mutex )
 {
-    static x264_pthread_mutex_t init = X264_PTHREAD_MUTEX_INITIALIZER;
+    static const x264_pthread_mutex_t init = X264_PTHREAD_MUTEX_INITIALIZER;
     if( !memcmp( mutex, &init, sizeof(x264_pthread_mutex_t) ) )
-        *mutex = thread_control.static_mutex;
+        *mutex = static_mutex;
     EnterCriticalSection( mutex );
     return 0;
 }
@@ -114,6 +106,64 @@ int x264_pthread_mutex_unlock( x264_pthread_mutex_t *mutex )
     return 0;
 }
 
+void x264_win32_threading_destroy( void )
+{
+    x264_pthread_mutex_destroy( &static_mutex );
+    memset( &static_mutex, 0, sizeof(static_mutex) );
+}
+
+#if HAVE_WINRT
+int x264_pthread_cond_init( x264_pthread_cond_t *cond, const x264_pthread_condattr_t *attr )
+{
+    InitializeConditionVariable( cond );
+    return 0;
+}
+
+int x264_pthread_cond_destroy( x264_pthread_cond_t *cond )
+{
+    return 0;
+}
+
+int x264_pthread_cond_broadcast( x264_pthread_cond_t *cond )
+{
+    WakeAllConditionVariable( cond );
+    return 0;
+}
+
+int x264_pthread_cond_signal( x264_pthread_cond_t *cond )
+{
+    WakeConditionVariable( cond );
+    return 0;
+}
+
+int x264_pthread_cond_wait( x264_pthread_cond_t *cond, x264_pthread_mutex_t *mutex )
+{
+    return !SleepConditionVariableCS( cond, mutex, INFINITE );
+}
+
+int x264_win32_threading_init( void )
+{
+    return x264_pthread_mutex_init( &static_mutex, NULL );
+}
+
+int x264_pthread_num_processors_np( void )
+{
+    SYSTEM_INFO si;
+    GetNativeSystemInfo(&si);
+    return si.dwNumberOfProcessors;
+}
+
+#else
+
+static struct
+{
+    /* function pointers to conditional variable API on windows 6.0+ kernels */
+    void (WINAPI *cond_broadcast)( x264_pthread_cond_t *cond );
+    void (WINAPI *cond_init)( x264_pthread_cond_t *cond );
+    void (WINAPI *cond_signal)( x264_pthread_cond_t *cond );
+    BOOL (WINAPI *cond_wait)( x264_pthread_cond_t *cond, x264_pthread_mutex_t *mutex, DWORD milliseconds );
+} thread_control;
+
 /* for pre-Windows 6.0 platforms we need to define and use our own condition variable and api */
 typedef struct
 {
@@ -137,7 +187,7 @@ int x264_pthread_cond_init( x264_pthread_cond_t *cond, const x264_pthread_condat
     x264_win32_cond_t *win32_cond = calloc( 1, sizeof(x264_win32_cond_t) );
     if( !win32_cond )
         return -1;
-    cond->ptr = win32_cond;
+    cond->Ptr = win32_cond;
     win32_cond->semaphore = CreateSemaphoreW( NULL, 0, 0x7fffffff, NULL );
     if( !win32_cond->semaphore )
         return -1;
@@ -161,7 +211,7 @@ int x264_pthread_cond_destroy( x264_pthread_cond_t *cond )
         return 0;
 
     /* non native condition variables */
-    x264_win32_cond_t *win32_cond = cond->ptr;
+    x264_win32_cond_t *win32_cond = cond->Ptr;
     CloseHandle( win32_cond->semaphore );
     CloseHandle( win32_cond->waiters_done );
     x264_pthread_mutex_destroy( &win32_cond->mtx_broadcast );
@@ -180,7 +230,7 @@ int x264_pthread_cond_broadcast( x264_pthread_cond_t *cond )
     }
 
     /* non native condition variables */
-    x264_win32_cond_t *win32_cond = cond->ptr;
+    x264_win32_cond_t *win32_cond = cond->Ptr;
     x264_pthread_mutex_lock( &win32_cond->mtx_broadcast );
     x264_pthread_mutex_lock( &win32_cond->mtx_waiter_count );
     int have_waiter = 0;
@@ -212,7 +262,7 @@ int x264_pthread_cond_signal( x264_pthread_cond_t *cond )
     }
 
     /* non-native condition variables */
-    x264_win32_cond_t *win32_cond = cond->ptr;
+    x264_win32_cond_t *win32_cond = cond->Ptr;
 
     x264_pthread_mutex_lock( &win32_cond->mtx_broadcast );
     x264_pthread_mutex_lock( &win32_cond->mtx_waiter_count );
@@ -234,7 +284,7 @@ int x264_pthread_cond_wait( x264_pthread_cond_t *cond, x264_pthread_mutex_t *mut
         return !thread_control.cond_wait( cond, mutex, INFINITE );
 
     /* non native condition variables */
-    x264_win32_cond_t *win32_cond = cond->ptr;
+    x264_win32_cond_t *win32_cond = cond->Ptr;
 
     x264_pthread_mutex_lock( &win32_cond->mtx_broadcast );
     x264_pthread_mutex_lock( &win32_cond->mtx_waiter_count );
@@ -270,13 +320,7 @@ int x264_win32_threading_init( void )
         thread_control.cond_signal = (void*)GetProcAddress( kernel_dll, "WakeConditionVariable" );
         thread_control.cond_wait = (void*)GetProcAddress( kernel_dll, "SleepConditionVariableCS" );
     }
-    return x264_pthread_mutex_init( &thread_control.static_mutex, NULL );
-}
-
-void x264_win32_threading_destroy( void )
-{
-    x264_pthread_mutex_destroy( &thread_control.static_mutex );
-    memset( &thread_control, 0, sizeof(x264_win32thread_control_t) );
+    return x264_pthread_mutex_init( &static_mutex, NULL );
 }
 
 int x264_pthread_num_processors_np( void )
@@ -289,11 +333,16 @@ int x264_pthread_num_processors_np( void )
 #if ARCH_X86_64
     /* find function pointers to API functions specific to x86_64 platforms, if they exist */
     HANDLE kernel_dll = GetModuleHandleW( L"kernel32.dll" );
-    BOOL (*get_thread_affinity)( HANDLE thread, x264_group_affinity_t *group_affinity ) = (void*)GetProcAddress( kernel_dll, "GetThreadGroupAffinity" );
+    BOOL (*get_thread_affinity)( HANDLE thread, void *group_affinity ) = (void*)GetProcAddress( kernel_dll, "GetThreadGroupAffinity" );
     if( get_thread_affinity )
     {
         /* running on a platform that supports >64 logical cpus */
-        x264_group_affinity_t thread_affinity;
+        struct /* GROUP_AFFINITY */
+        {
+            ULONG_PTR mask; // KAFFINITY = ULONG_PTR
+            USHORT group;
+            USHORT reserved[3];
+        } thread_affinity;
         if( get_thread_affinity( GetCurrentThread(), &thread_affinity ) )
             process_cpus = thread_affinity.mask;
     }
@@ -305,3 +354,4 @@ int x264_pthread_num_processors_np( void )
 
     return cpus ? cpus : 1;
 }
+#endif
index 07cbada..c16ad00 100644 (file)
@@ -45,12 +45,14 @@ typedef CRITICAL_SECTION x264_pthread_mutex_t;
 #define X264_PTHREAD_MUTEX_INITIALIZER {0}
 #define x264_pthread_mutexattr_t int
 
-/* This is the CONDITIONAL_VARIABLE typedef for using Window's native conditional variables on kernels 6.0+.
- * MinGW does not currently have this typedef. */
+#if HAVE_WINRT
+typedef CONDITION_VARIABLE x264_pthread_cond_t;
+#else
 typedef struct
 {
-    void *ptr;
+    void *Ptr;
 } x264_pthread_cond_t;
+#endif
 #define x264_pthread_condattr_t int
 
 int x264_pthread_create( x264_pthread_t *thread, const x264_pthread_attr_t *attr,
index 31f3661..09643db 100755 (executable)
--- a/configure
+++ b/configure
@@ -373,7 +373,7 @@ NL="
 # list of all preprocessor HAVE values we can define
 CONFIG_HAVE="MALLOC_H ALTIVEC ALTIVEC_H MMX ARMV6 ARMV6T2 NEON BEOSTHREAD POSIXTHREAD WIN32THREAD THREAD LOG2F SWSCALE \
              LAVF FFMS GPAC AVS GPL VECTOREXT INTERLACED CPU_COUNT OPENCL THP LSMASH X86_INLINE_ASM AS_FUNC INTEL_DISPATCHER \
-             MSA MMAP"
+             MSA MMAP WINRT"
 
 # parse options
 
@@ -768,6 +768,21 @@ if [ $SYS = WINDOWS ]; then
     if ! rc_check "0 RCDATA {0}" ; then
         RC=""
     fi
+
+    if cpp_check "winapifamily.h" "" "!WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)" ; then
+        [ $compiler = CL ] || die "WinRT requires MSVC"
+        define HAVE_WINRT
+        CFLAGS="$CFLAGS -MD"
+        LDFLAGS="$LDFLAGS -appcontainer"
+        if ! cpp_check "" "" "defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0603" ; then
+            die "_WIN32_WINNT must be defined to at least 0x0603 (Windows 8.1) for WinRT"
+        elif cpp_check "" "" "_WIN32_WINNT >= 0x0A00" ; then
+            # Universal Windows Platform (Windows 10)
+            LDFLAGS="$LDFLAGS -lWindowsApp"
+        fi
+        cli="no"
+        opencl="no"
+    fi
 fi
 
 log_msg "x264 configure script"