osdep.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /*****************************************************************************
  2. * osdep.c: platform-specific code
  3. *****************************************************************************
  4. * Copyright (C) 2003-2018 x264 project
  5. *
  6. * Authors: Steven Walters <kemuri9@gmail.com>
  7. * Laurent Aimar <fenrir@via.ecp.fr>
  8. * Henrik Gramner <henrik@gramner.com>
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
  23. *
  24. * This program is also available under a commercial proprietary license.
  25. * For more information, contact us at licensing@x264.com.
  26. *****************************************************************************/
  27. #include "osdep.h"
  28. #ifdef _WIN32
  29. #include <windows.h>
  30. #include <io.h>
  31. #endif
  32. #if SYS_WINDOWS
  33. #include <sys/types.h>
  34. #include <sys/timeb.h>
  35. #else
  36. #include <sys/time.h>
  37. #endif
  38. #include <time.h>
  39. #if PTW32_STATIC_LIB
  40. /* this is a global in pthread-win32 to indicate if it has been initialized or not */
  41. extern int ptw32_processInitialized;
  42. #endif
  43. int64_t x264_mdate( void )
  44. {
  45. #if SYS_WINDOWS
  46. struct timeb tb;
  47. ftime( &tb );
  48. return ((int64_t)tb.time * 1000 + (int64_t)tb.millitm) * 1000;
  49. #elif HAVE_CLOCK_GETTIME
  50. struct timespec ts;
  51. clock_gettime( CLOCK_MONOTONIC, &ts );
  52. return (int64_t)ts.tv_sec * 1000000 + (int64_t)ts.tv_nsec / 1000;
  53. #else
  54. struct timeval tv_date;
  55. gettimeofday( &tv_date, NULL );
  56. return (int64_t)tv_date.tv_sec * 1000000 + (int64_t)tv_date.tv_usec;
  57. #endif
  58. }
  59. #if HAVE_WIN32THREAD || PTW32_STATIC_LIB
  60. /* state of the threading library being initialized */
  61. static volatile LONG threading_is_init = 0;
  62. static void threading_destroy( void )
  63. {
  64. #if PTW32_STATIC_LIB
  65. pthread_win32_thread_detach_np();
  66. pthread_win32_process_detach_np();
  67. #else
  68. x264_win32_threading_destroy();
  69. #endif
  70. }
  71. static int threading_init( void )
  72. {
  73. #if PTW32_STATIC_LIB
  74. /* if static pthread-win32 is already initialized, then do nothing */
  75. if( ptw32_processInitialized )
  76. return 0;
  77. if( !pthread_win32_process_attach_np() )
  78. return -1;
  79. #else
  80. if( x264_win32_threading_init() )
  81. return -1;
  82. #endif
  83. /* register cleanup to run at process termination */
  84. atexit( threading_destroy );
  85. return 0;
  86. }
  87. int x264_threading_init( void )
  88. {
  89. LONG state;
  90. while( (state = InterlockedCompareExchange( &threading_is_init, -1, 0 )) != 0 )
  91. {
  92. /* if already init, then do nothing */
  93. if( state > 0 )
  94. return 0;
  95. }
  96. if( threading_init() < 0 )
  97. {
  98. InterlockedExchange( &threading_is_init, 0 );
  99. return -1;
  100. }
  101. InterlockedExchange( &threading_is_init, 1 );
  102. return 0;
  103. }
  104. #endif
  105. #ifdef _WIN32
  106. /* Functions for dealing with Unicode on Windows. */
  107. FILE *x264_fopen( const char *filename, const char *mode )
  108. {
  109. wchar_t filename_utf16[MAX_PATH];
  110. wchar_t mode_utf16[16];
  111. if( utf8_to_utf16( filename, filename_utf16 ) && utf8_to_utf16( mode, mode_utf16 ) )
  112. return _wfopen( filename_utf16, mode_utf16 );
  113. return NULL;
  114. }
  115. int x264_rename( const char *oldname, const char *newname )
  116. {
  117. wchar_t oldname_utf16[MAX_PATH];
  118. wchar_t newname_utf16[MAX_PATH];
  119. if( utf8_to_utf16( oldname, oldname_utf16 ) && utf8_to_utf16( newname, newname_utf16 ) )
  120. {
  121. /* POSIX says that rename() removes the destination, but Win32 doesn't. */
  122. _wunlink( newname_utf16 );
  123. return _wrename( oldname_utf16, newname_utf16 );
  124. }
  125. return -1;
  126. }
  127. int x264_stat( const char *path, x264_struct_stat *buf )
  128. {
  129. wchar_t path_utf16[MAX_PATH];
  130. if( utf8_to_utf16( path, path_utf16 ) )
  131. return _wstati64( path_utf16, buf );
  132. return -1;
  133. }
  134. #if !HAVE_WINRT
  135. int x264_vfprintf( FILE *stream, const char *format, va_list arg )
  136. {
  137. HANDLE console = NULL;
  138. DWORD mode;
  139. if( stream == stdout )
  140. console = GetStdHandle( STD_OUTPUT_HANDLE );
  141. else if( stream == stderr )
  142. console = GetStdHandle( STD_ERROR_HANDLE );
  143. /* Only attempt to convert to UTF-16 when writing to a non-redirected console screen buffer. */
  144. if( GetConsoleMode( console, &mode ) )
  145. {
  146. char buf[4096];
  147. wchar_t buf_utf16[4096];
  148. va_list arg2;
  149. va_copy( arg2, arg );
  150. int length = vsnprintf( buf, sizeof(buf), format, arg2 );
  151. va_end( arg2 );
  152. if( length > 0 && length < sizeof(buf) )
  153. {
  154. /* WriteConsoleW is the most reliable way to output Unicode to a console. */
  155. int length_utf16 = MultiByteToWideChar( CP_UTF8, 0, buf, length, buf_utf16, sizeof(buf_utf16)/sizeof(wchar_t) );
  156. DWORD written;
  157. WriteConsoleW( console, buf_utf16, length_utf16, &written, NULL );
  158. return length;
  159. }
  160. }
  161. return vfprintf( stream, format, arg );
  162. }
  163. int x264_is_pipe( const char *path )
  164. {
  165. wchar_t path_utf16[MAX_PATH];
  166. if( utf8_to_utf16( path, path_utf16 ) )
  167. return WaitNamedPipeW( path_utf16, 0 );
  168. return 0;
  169. }
  170. #endif
  171. #if defined(_MSC_VER) && _MSC_VER < 1900
  172. /* MSVC pre-VS2015 has broken snprintf/vsnprintf implementations which are incompatible with C99. */
  173. int x264_snprintf( char *s, size_t n, const char *fmt, ... )
  174. {
  175. va_list arg;
  176. va_start( arg, fmt );
  177. int length = x264_vsnprintf( s, n, fmt, arg );
  178. va_end( arg );
  179. return length;
  180. }
  181. int x264_vsnprintf( char *s, size_t n, const char *fmt, va_list arg )
  182. {
  183. int length = -1;
  184. if( n )
  185. {
  186. va_list arg2;
  187. va_copy( arg2, arg );
  188. length = _vsnprintf( s, n, fmt, arg2 );
  189. va_end( arg2 );
  190. /* _(v)snprintf adds a null-terminator only if the length is less than the buffer size. */
  191. if( length < 0 || length >= n )
  192. s[n-1] = '\0';
  193. }
  194. /* _(v)snprintf returns a negative number if the length is greater than the buffer size. */
  195. if( length < 0 )
  196. return _vscprintf( fmt, arg );
  197. return length;
  198. }
  199. #endif
  200. #endif