From 74ee50e539dc06bea6b4bbd2f674c21248c05970 Mon Sep 17 00:00:00 2001 From: Steven Walters Date: Sat, 11 Dec 2010 20:30:29 -0500 Subject: [PATCH] Support for native Windows threads Patch originally by Pegasys Inc. --- Makefile | 8 +- common/cpu.c | 4 +- common/{mdate.c => osdep.c} | 48 ++++++- common/osdep.h | 40 +++--- common/threadpool.h | 2 +- common/win32thread.c | 275 ++++++++++++++++++++++++++++++++++++ common/win32thread.h | 79 +++++++++++ configure | 53 ++++--- encoder/encoder.c | 14 +- encoder/lookahead.c | 2 +- x264.c | 12 +- x264.h | 2 +- 12 files changed, 481 insertions(+), 58 deletions(-) rename common/{mdate.c => osdep.c} (56%) create mode 100644 common/win32thread.c create mode 100644 common/win32thread.h diff --git a/Makefile b/Makefile index c4010289..a66a9eef 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ all: default SRCS = common/mc.c common/predict.c common/pixel.c common/macroblock.c \ common/frame.c common/dct.c common/cpu.c common/cabac.c \ - common/common.c common/mdate.c common/rectangle.c \ + common/common.c common/osdep.c common/rectangle.c \ common/set.c common/quant.c common/deblock.c common/vlc.c \ common/mvpred.c common/bitstream.c \ encoder/analyse.c encoder/me.c encoder/ratecontrol.c \ @@ -34,11 +34,15 @@ ifneq ($(findstring HAVE_AVS 1, $(CONFIG)),) SRCCLI += input/avs.c endif -ifneq ($(findstring HAVE_PTHREAD 1, $(CONFIG)),) +ifneq ($(findstring HAVE_THREAD 1, $(CONFIG)),) SRCCLI += input/thread.c SRCS += common/threadpool.c endif +ifneq ($(findstring HAVE_WIN32THREAD 1, $(CONFIG)),) +SRCS += common/win32thread.c +endif + ifneq ($(findstring HAVE_LAVF 1, $(CONFIG)),) SRCCLI += input/lavf.c endif diff --git a/common/cpu.c b/common/cpu.c index 7ebb2abe..cc652406 100644 --- a/common/cpu.c +++ b/common/cpu.c @@ -337,11 +337,11 @@ uint32_t x264_cpu_detect( void ) int x264_cpu_num_processors( void ) { -#if !HAVE_PTHREAD +#if !HAVE_THREAD return 1; #elif defined(_WIN32) - return pthread_num_processors_np(); + return x264_pthread_num_processors_np(); #elif SYS_LINUX unsigned int bit; diff --git a/common/mdate.c b/common/osdep.c similarity index 56% rename from common/mdate.c rename to common/osdep.c index 702d4474..236bbc66 100644 --- a/common/mdate.c +++ b/common/osdep.c @@ -1,9 +1,10 @@ /***************************************************************************** - * mdate.c: time measurement + * osdep.c: platform-specific code ***************************************************************************** * Copyright (C) 2003-2010 x264 project * - * Authors: Laurent Aimar + * Authors: Steven Walters + * Laurent Aimar * * 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 @@ -32,7 +33,13 @@ #include #include "common.h" -#include "osdep.h" + +#if PTW32_STATIC_LIB +#define WIN32_LEAN_AND_MEAN +#include +/* this is a global in pthread-win32 to indicate if it has been initialized or not */ +extern int ptw32_processInitialized; +#endif int64_t x264_mdate( void ) { @@ -47,3 +54,38 @@ int64_t x264_mdate( void ) #endif } +#if HAVE_WIN32THREAD || PTW32_STATIC_LIB +/* state of the threading library being initialized */ +static volatile LONG x264_threading_is_init = 0; + +static void x264_threading_destroy( void ) +{ +#if PTW32_STATIC_LIB + pthread_win32_thread_detach_np(); + pthread_win32_process_detach_np(); +#else + x264_win32_threading_destroy(); +#endif +} + +int x264_threading_init( void ) +{ + /* if already init, then do nothing */ + if( InterlockedCompareExchange( &x264_threading_is_init, 1, 0 ) ) + return 0; +#if PTW32_STATIC_LIB + /* if static pthread-win32 is already initialized, then do nothing */ + if( ptw32_processInitialized ) + return 0; + if( !pthread_win32_process_attach_np() ) + return -1; +#else + if( x264_win32_threading_init() ) + return -1; +#endif + /* register cleanup to run at process termination */ + atexit( x264_threading_destroy ); + + return 0; +} +#endif diff --git a/common/osdep.h b/common/osdep.h index fbe8e96c..cc51847e 100644 --- a/common/osdep.h +++ b/common/osdep.h @@ -106,7 +106,7 @@ #endif /* threads */ -#if SYS_BEOS +#if HAVE_BEOSTHREAD #include #define x264_pthread_t thread_id static inline int x264_pthread_create( x264_pthread_t *t, void *a, void *(*f)(void *), void *d ) @@ -119,22 +119,9 @@ static inline int x264_pthread_create( x264_pthread_t *t, void *a, void *(*f)(vo } #define x264_pthread_join(t,s) { long tmp; \ wait_for_thread(t,(s)?(long*)(*(s)):&tmp); } -#ifndef usleep -#define usleep(t) snooze(t) -#endif -#define HAVE_PTHREAD 1 -#elif HAVE_PTHREAD +#elif HAVE_POSIXTHREAD #include -#define USE_REAL_PTHREAD 1 - -#else -#define x264_pthread_t int -#define x264_pthread_create(t,u,f,d) 0 -#define x264_pthread_join(t,s) -#endif //SYS_* - -#if USE_REAL_PTHREAD #define x264_pthread_t pthread_t #define x264_pthread_create pthread_create #define x264_pthread_join pthread_join @@ -151,8 +138,19 @@ static inline int x264_pthread_create( x264_pthread_t *t, void *a, void *(*f)(vo #define x264_pthread_attr_t pthread_attr_t #define x264_pthread_attr_init pthread_attr_init #define x264_pthread_attr_destroy pthread_attr_destroy +#define x264_pthread_num_processors_np pthread_num_processors_np #define X264_PTHREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER + +#elif HAVE_WIN32THREAD +#include "win32thread.h" + #else +#define x264_pthread_t int +#define x264_pthread_create(t,u,f,d) 0 +#define x264_pthread_join(t,s) +#endif //HAVE_*THREAD + +#if !HAVE_POSIXTHREAD && !HAVE_WIN32THREAD #define x264_pthread_mutex_t int #define x264_pthread_mutex_init(m,f) 0 #define x264_pthread_mutex_destroy(m) @@ -169,6 +167,12 @@ static inline int x264_pthread_create( x264_pthread_t *t, void *a, void *(*f)(vo #define X264_PTHREAD_MUTEX_INITIALIZER 0 #endif +#if HAVE_WIN32THREAD || PTW32_STATIC_LIB +int x264_threading_init( void ); +#else +#define x264_threading_init() 0 +#endif + #define WORD_SIZE sizeof(void*) #define asm __asm__ @@ -270,7 +274,7 @@ static ALWAYS_INLINE void x264_prefetch( void *p ) #define x264_prefetch(x) #endif -#if USE_REAL_PTHREAD +#if HAVE_POSIXTHREAD #if SYS_MINGW #define x264_lower_thread_priority(p)\ {\ @@ -284,7 +288,9 @@ static ALWAYS_INLINE void x264_prefetch( void *p ) #else #include #define x264_lower_thread_priority(p) { UNUSED int nice_ret = nice(p); } -#endif /* USE_REAL_PTHREAD */ +#endif /* SYS_MINGW */ +#elif HAVE_WIN32THREAD +#define x264_lower_thread_priority(p) SetThreadPriority( GetCurrentThread(), X264_MAX( -2, -p ) ) #else #define x264_lower_thread_priority(p) #endif diff --git a/common/threadpool.h b/common/threadpool.h index 0cb19790..fcebe5cc 100644 --- a/common/threadpool.h +++ b/common/threadpool.h @@ -28,7 +28,7 @@ typedef struct x264_threadpool_t x264_threadpool_t; -#if HAVE_PTHREAD +#if HAVE_THREAD int x264_threadpool_init( x264_threadpool_t **p_pool, int threads, void (*init_func)(void *), void *init_arg ); void x264_threadpool_run( x264_threadpool_t *pool, void *(*func)(void *), void *arg ); diff --git a/common/win32thread.c b/common/win32thread.c new file mode 100644 index 00000000..1679c4e3 --- /dev/null +++ b/common/win32thread.c @@ -0,0 +1,275 @@ +/***************************************************************************** + * win32thread.c: windows threading + ***************************************************************************** + * Copyright (C) 2010 x264 project + * + * Authors: Steven Walters + * Pegasys Inc. + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA. + * + * This program is also available under a commercial proprietary license. + * For more information, contact us at licensing@x264.com. + *****************************************************************************/ + +/* TODO: work with windows 7 x86_64's (and later systems) awkward + * way of handling systems with >64 logical processors */ + +#include "common.h" +#include + +/* 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 + +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; + +/* _beginthreadex requires that the start routine is __stdcall */ +static __stdcall unsigned x264_win32thread_worker( void *arg ) +{ + x264_pthread_t *h = arg; + h->ret = h->func( h->arg ); + return 0; +} + +int x264_pthread_create( x264_pthread_t *thread, const x264_pthread_attr_t *attr, + void *(*start_routine)( void* ), void *arg ) +{ + thread->func = start_routine; + thread->arg = arg; + thread->handle = (void*)_beginthreadex( NULL, 0, x264_win32thread_worker, thread, 0, NULL ); + return !thread->handle; +} + +int x264_pthread_join( x264_pthread_t thread, void **value_ptr ) +{ + DWORD ret = WaitForSingleObject( thread.handle, INFINITE ); + if( ret != WAIT_OBJECT_0 ) + return -1; + if( value_ptr ) + *value_ptr = thread.ret; + CloseHandle( thread.handle ); + return 0; +} + +int x264_pthread_mutex_init( x264_pthread_mutex_t *mutex, const x264_pthread_mutexattr_t *attr ) +{ + return !InitializeCriticalSectionAndSpinCount( mutex, X264_SPIN_COUNT ); +} + +int x264_pthread_mutex_destroy( x264_pthread_mutex_t *mutex ) +{ + DeleteCriticalSection( mutex ); + return 0; +} + +int x264_pthread_mutex_lock( x264_pthread_mutex_t *mutex ) +{ + static x264_pthread_mutex_t init = X264_PTHREAD_MUTEX_INITIALIZER; + if( !memcmp( mutex, &init, sizeof(x264_pthread_mutex_t) ) ) + *mutex = thread_control.static_mutex; + EnterCriticalSection( mutex ); + return 0; +} + +int x264_pthread_mutex_unlock( x264_pthread_mutex_t *mutex ) +{ + LeaveCriticalSection( mutex ); + return 0; +} + +/* for pre-Windows 6.0 platforms we need to define and use our own condition variable and api */ +typedef struct +{ + x264_pthread_mutex_t mtx_broadcast; + x264_pthread_mutex_t mtx_waiter_count; + int waiter_count; + HANDLE semaphore; + HANDLE waiters_done; + int is_broadcast; +} x264_win32_cond_t; + +int x264_pthread_cond_init( x264_pthread_cond_t *cond, const x264_pthread_condattr_t *attr ) +{ + if( thread_control.cond_init ) + { + thread_control.cond_init( cond ); + return 0; + } + + /* non native condition variables */ + x264_win32_cond_t *win32_cond = calloc( 1, sizeof(x264_win32_cond_t) ); + if( !win32_cond ) + return -1; + cond->ptr = win32_cond; + win32_cond->semaphore = CreateSemaphore( NULL, 0, 0x7fffffff, NULL ); + if( !win32_cond->semaphore ) + return -1; + + if( x264_pthread_mutex_init( &win32_cond->mtx_waiter_count, NULL ) ) + return -1; + if( x264_pthread_mutex_init( &win32_cond->mtx_broadcast, NULL ) ) + return -1; + + win32_cond->waiters_done = CreateEvent( NULL, FALSE, FALSE, NULL ); + if( !win32_cond->waiters_done ) + return -1; + + return 0; +} + +int x264_pthread_cond_destroy( x264_pthread_cond_t *cond ) +{ + /* native condition variables do not destroy */ + if( thread_control.cond_init ) + return 0; + + /* non native condition variables */ + 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 ); + x264_pthread_mutex_destroy( &win32_cond->mtx_waiter_count ); + free( win32_cond ); + + return 0; +} + +int x264_pthread_cond_broadcast( x264_pthread_cond_t *cond ) +{ + if( thread_control.cond_broadcast ) + { + thread_control.cond_broadcast( cond ); + return 0; + } + + /* non native condition variables */ + 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; + + if( win32_cond->waiter_count ) + { + win32_cond->is_broadcast = 1; + have_waiter = 1; + } + + if( have_waiter ) + { + ReleaseSemaphore( win32_cond->semaphore, win32_cond->waiter_count, NULL ); + x264_pthread_mutex_unlock( &win32_cond->mtx_waiter_count ); + WaitForSingleObject( win32_cond->waiters_done, INFINITE ); + win32_cond->is_broadcast = 0; + } + else + x264_pthread_mutex_unlock( &win32_cond->mtx_waiter_count ); + return x264_pthread_mutex_unlock( &win32_cond->mtx_broadcast ); +} + +int x264_pthread_cond_signal( x264_pthread_cond_t *cond ) +{ + if( thread_control.cond_signal ) + { + thread_control.cond_signal( cond ); + return 0; + } + + /* non-native condition variables */ + x264_win32_cond_t *win32_cond = cond->ptr; + x264_pthread_mutex_lock( &win32_cond->mtx_waiter_count ); + int have_waiter = win32_cond->waiter_count; + x264_pthread_mutex_unlock( &win32_cond->mtx_waiter_count ); + + if( have_waiter ) + ReleaseSemaphore( win32_cond->semaphore, 1, NULL ); + return 0; +} + +int x264_pthread_cond_wait( x264_pthread_cond_t *cond, x264_pthread_mutex_t *mutex ) +{ + if( thread_control.cond_wait ) + return !thread_control.cond_wait( cond, mutex, INFINITE ); + + /* non native condition variables */ + x264_win32_cond_t *win32_cond = cond->ptr; + + x264_pthread_mutex_lock( &win32_cond->mtx_broadcast ); + x264_pthread_mutex_unlock( &win32_cond->mtx_broadcast ); + + x264_pthread_mutex_lock( &win32_cond->mtx_waiter_count ); + win32_cond->waiter_count++; + x264_pthread_mutex_unlock( &win32_cond->mtx_waiter_count ); + + // unlock the external mutex + x264_pthread_mutex_unlock( mutex ); + WaitForSingleObject( win32_cond->semaphore, INFINITE ); + + x264_pthread_mutex_lock( &win32_cond->mtx_waiter_count ); + win32_cond->waiter_count--; + int last_waiter = !win32_cond->waiter_count && win32_cond->is_broadcast; + x264_pthread_mutex_unlock( &win32_cond->mtx_waiter_count ); + + if( last_waiter ) + SetEvent( win32_cond->waiters_done ); + + // lock the external mutex + return x264_pthread_mutex_lock( mutex ); +} + +int x264_win32_threading_init( void ) +{ + /* find function pointers to API functions, if they exist */ + HANDLE kernel_dll = GetModuleHandle( TEXT( "kernel32.dll" ) ); + thread_control.cond_init = (void*)GetProcAddress( kernel_dll, "InitializeConditionVariable" ); + if( thread_control.cond_init ) + { + /* we're on a windows 6.0+ kernel, acquire the rest of the functions */ + thread_control.cond_broadcast = (void*)GetProcAddress( kernel_dll, "WakeAllConditionVariable" ); + 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) ); +} + +int x264_pthread_num_processors_np() +{ + DWORD_PTR process_cpus, system_cpus; + if( GetProcessAffinityMask( GetCurrentProcess(), &process_cpus, &system_cpus ) ) + { + int cpus = 0; + for( DWORD_PTR bit = 1; bit; bit <<= 1 ) + cpus += !!(process_cpus & bit); + return cpus; + } + return 1; +} diff --git a/common/win32thread.h b/common/win32thread.h new file mode 100644 index 00000000..1312cb4b --- /dev/null +++ b/common/win32thread.h @@ -0,0 +1,79 @@ +/***************************************************************************** + * win32thread.h: windows threading + ***************************************************************************** + * Copyright (C) 2010 x264 project + * + * Authors: Steven Walters + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA. + * + * This program is also available under a commercial proprietary license. + * For more information, contact us at licensing@x264.com. + *****************************************************************************/ + +#ifndef X264_WIN32THREAD_H +#define X264_WIN32THREAD_H + +#define WIN32_LEAN_AND_MEAN +#include +/* the following macro is used within x264 */ +#undef ERROR + +typedef struct +{ + void *handle; + void *(*func)( void* arg ); + void *arg; + void *ret; +} x264_pthread_t; +#define x264_pthread_attr_t int + +/* the conditional variable api for windows 6.0+ uses critical sections and not mutexes */ +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. */ +typedef struct +{ + void *ptr; +} x264_pthread_cond_t; +#define x264_pthread_condattr_t int + +int x264_pthread_create( x264_pthread_t *thread, const x264_pthread_attr_t *attr, + void *(*start_routine)( void* ), void *arg ); +int x264_pthread_join( x264_pthread_t thread, void **value_ptr ); + +int x264_pthread_mutex_init( x264_pthread_mutex_t *mutex, const x264_pthread_mutexattr_t *attr ); +int x264_pthread_mutex_destroy( x264_pthread_mutex_t *mutex ); +int x264_pthread_mutex_lock( x264_pthread_mutex_t *mutex ); +int x264_pthread_mutex_unlock( x264_pthread_mutex_t *mutex ); + +int x264_pthread_cond_init( x264_pthread_cond_t *cond, const x264_pthread_condattr_t *attr ); +int x264_pthread_cond_destroy( x264_pthread_cond_t *cond ); +int x264_pthread_cond_broadcast( x264_pthread_cond_t *cond ); +int x264_pthread_cond_wait( x264_pthread_cond_t *cond, x264_pthread_mutex_t *mutex ); +int x264_pthread_cond_signal( x264_pthread_cond_t *cond ); + +#define x264_pthread_attr_init(a) 0 +#define x264_pthread_attr_destroy(a) 0 + +int x264_win32_threading_init( void ); +void x264_win32_threading_destroy( void ); + +int x264_pthread_num_processors_np( void ); + +#endif diff --git a/configure b/configure index 4e308192..0bab3e11 100755 --- a/configure +++ b/configure @@ -12,7 +12,8 @@ echo " --disable-lavf disables libavformat support" echo " --disable-ffms disables ffmpegsource support" echo " --disable-gpac disables gpac support" echo " --disable-gpl disables GPL-only features" -echo " --disable-pthread disables multithreaded encoding" +echo " --disable-thread disables multithreaded encoding" +echo " --enable-win32thread use win32threads (windows only)" echo " --disable-swscale disables swscale support" echo " --disable-asm disables platform-specific assembly optimizations" echo " --enable-debug adds -g, doesn't strip" @@ -152,7 +153,7 @@ lavf="auto" ffms="auto" gpac="auto" gpl="yes" -pthread="auto" +thread="auto" swscale="auto" asm="auto" debug="no" @@ -172,7 +173,7 @@ cross_prefix="" EXE="" # list of all preprocessor HAVE values we can define -CONFIG_HAVE="MALLOC_H ALTIVEC ALTIVEC_H MMX ARMV6 ARMV6T2 NEON PTHREAD LOG2F VISUALIZE SWSCALE LAVF FFMS GPAC GF_MALLOC AVS GPL" +CONFIG_HAVE="MALLOC_H ALTIVEC ALTIVEC_H MMX ARMV6 ARMV6T2 NEON BEOSTHREAD POSIXTHREAD WIN32THREAD THREAD LOG2F VISUALIZE SWSCALE LAVF FFMS GPAC GF_MALLOC AVS GPL" # parse options @@ -221,8 +222,11 @@ for opt do --extra-ldflags=*) LDFLAGS="$LDFLAGS ${opt#--extra-ldflags=}" ;; - --disable-pthread) - pthread="no" + --disable-thread) + thread="no" + ;; + --enable-win32thread) + thread="win32" ;; --disable-swscale) swscale="no" @@ -515,42 +519,57 @@ fi # autodetect options that weren't forced nor disabled +# pthread-win32 is lgpl, prevent its use if --disable-gpl is specified and targeting windows +[ "$SYS" = "MINGW" -a "$gpl" = "no" -a "$thread" = "auto" ] && thread="win32" + libpthread="" -if test "$pthread" = "auto" ; then - pthread="no" +if [ "$thread" = "auto" ]; then + thread="no" case $SYS in BEOS) - pthread="yes" + thread="beos" + define HAVE_BEOSTHREAD ;; MINGW) if cc_check pthread.h -lpthread "pthread_create(0,0,0,0);" ; then - pthread="yes" + thread="posix" libpthread="-lpthread" elif cc_check pthread.h -lpthreadGC2 "pthread_create(0,0,0,0);" ; then - pthread="yes" + thread="posix" libpthread="-lpthreadGC2" elif cc_check pthread.h "-lpthreadGC2 -lwsock32 -DPTW32_STATIC_LIB" "pthread_create(0,0,0,0);" ; then - pthread="yes" + thread="posix" libpthread="-lpthreadGC2 -lwsock32" define PTW32_STATIC_LIB elif cc_check pthread.h "-lpthreadGC2 -lws2_32 -DPTW32_STATIC_LIB" "pthread_create(0,0,0,0);" ; then - pthread="yes" + thread="posix" libpthread="-lpthreadGC2 -lws2_32" define PTW32_STATIC_LIB + else + # default to native threading if pthread-win32 is unavailable + thread="win32" fi ;; OPENBSD) - cc_check pthread.h -pthread && pthread="yes" && libpthread="-pthread" + cc_check pthread.h -pthread && thread="posix" && libpthread="-pthread" ;; *) - cc_check pthread.h -lpthread && pthread="yes" && libpthread="-lpthread" + cc_check pthread.h -lpthread && thread="posix" && libpthread="-lpthread" ;; esac fi -if test "$pthread" = "yes" ; then - define HAVE_PTHREAD +if [ "$thread" = "posix" ]; then LDFLAGS="$LDFLAGS $libpthread" + define HAVE_POSIXTHREAD +fi +if [ "$thread" = "win32" ]; then + if [ "$SYS" = "MINGW" ]; then + define HAVE_WIN32THREAD + else + thread="no" + fi fi +[ "$thread" != "no" ] && define HAVE_THREAD if cc_check "math.h" "-Werror" "return log2f(2);" ; then define HAVE_LOG2F @@ -835,7 +854,7 @@ lavf: $lavf ffms: $ffms gpac: $gpac gpl: $gpl -pthread: $pthread +thread: $thread filters: $filters debug: $debug gprof: $gprof diff --git a/encoder/encoder.c b/encoder/encoder.c index b0689c93..8c01210a 100644 --- a/encoder/encoder.c +++ b/encoder/encoder.c @@ -359,7 +359,7 @@ fail: return -1; } -#if HAVE_PTHREAD +#if HAVE_THREAD static void x264_encoder_thread_init( x264_t *h ) { if( h->param.i_sync_lookahead ) @@ -430,8 +430,8 @@ static int x264_validate_parameters( x264_t *h ) h->param.i_threads = x264_clip3( h->param.i_threads, 1, X264_THREAD_MAX ); if( h->param.i_threads > 1 ) { -#if !HAVE_PTHREAD - x264_log( h, X264_LOG_WARNING, "not compiled with pthread support!\n"); +#if !HAVE_THREAD + x264_log( h, X264_LOG_WARNING, "not compiled with thread support!\n"); h->param.i_threads = 1; #endif /* Avoid absurdly small thread slices as they can reduce performance @@ -661,7 +661,7 @@ static int x264_validate_parameters( x264_t *h ) } if( h->param.rc.b_stat_read ) h->param.rc.i_lookahead = 0; -#if HAVE_PTHREAD +#if HAVE_THREAD if( h->param.i_sync_lookahead < 0 ) h->param.i_sync_lookahead = h->param.i_bframe + 1; h->param.i_sync_lookahead = X264_MIN( h->param.i_sync_lookahead, X264_LOOKAHEAD_MAX ); @@ -928,6 +928,12 @@ x264_t *x264_encoder_open( x264_param_t *param ) if( param->param_free ) param->param_free( param ); + if( x264_threading_init() ) + { + x264_log( h, X264_LOG_ERROR, "unable to initialize threading\n" ); + goto fail; + } + if( x264_validate_parameters( h ) < 0 ) goto fail; diff --git a/encoder/lookahead.c b/encoder/lookahead.c index e136d08e..0cd64d9b 100644 --- a/encoder/lookahead.c +++ b/encoder/lookahead.c @@ -64,7 +64,7 @@ static void x264_lookahead_update_last_nonb( x264_t *h, x264_frame_t *new_nonb ) new_nonb->i_reference_count++; } -#if HAVE_PTHREAD +#if HAVE_THREAD static void x264_lookahead_slicetype_decide( x264_t *h ) { x264_stack_align( x264_slicetype_decide, h ); diff --git a/x264.c b/x264.c index e584c0b4..97695bc6 100644 --- a/x264.c +++ b/x264.c @@ -254,10 +254,7 @@ int main( int argc, char **argv ) cli_opt_t opt; int ret; -#if PTW32_STATIC_LIB - pthread_win32_process_attach_np(); - pthread_win32_thread_attach_np(); -#endif + FAIL_IF_ERROR( x264_threading_init(), "unable to initialize threading\n" ) #ifdef _WIN32 _setmode(_fileno(stdin), _O_BINARY); @@ -273,11 +270,6 @@ int main( int argc, char **argv ) ret = encode( ¶m, &opt ); -#if PTW32_STATIC_LIB - pthread_win32_thread_detach_np(); - pthread_win32_process_detach_np(); -#endif - return ret; } @@ -1403,7 +1395,7 @@ generic_option: else FAIL_IF_ERROR( !info.vfr && input_opt.timebase, "--timebase is incompatible with cfr input\n" ) /* init threaded input while the information about the input video is unaltered by filtering */ -#if HAVE_PTHREAD +#if HAVE_THREAD if( info.thread_safe && (b_thread_input || param->i_threads > 1 || (param->i_threads == X264_THREADS_AUTO && x264_cpu_num_processors() > 1)) ) { diff --git a/x264.h b/x264.h index fc37c863..0926ead4 100644 --- a/x264.h +++ b/x264.h @@ -41,7 +41,7 @@ #include "x264_config.h" -#define X264_BUILD 111 +#define X264_BUILD 112 /* x264_t: * opaque handler for encoder */ -- 2.39.5