Windows, unlike most other operating systems, uses UTF-16 for Unicode strings while x264 is designed for UTF-8.
This patch does the following in order to handle things like Unicode filenames:
* Keep strings internally as UTF-8.
* Retrieve the CLI command line as UTF-16 and convert it to UTF-8.
* Always use Unicode versions of Windows API functions and convert strings to UTF-16 when calling them.
* Attempt to use legacy 8.3 short filenames for external libraries without Unicode support.
break;
}
fprintf( stderr, "x264 [%s]: ", psz_prefix );
- vfprintf( stderr, psz_fmt, arg );
+ x264_vfprintf( stderr, psz_fmt, arg );
}
/****************************************************************************
int b_error = 0;
size_t i_size;
char *buf;
- FILE *fh = fopen( filename, "rb" );
+ FILE *fh = x264_fopen( filename, "rb" );
if( !fh )
return NULL;
b_error |= fseek( fh, 0, SEEK_END ) < 0;
#ifdef _WIN32
#include <windows.h>
-#define ocl_open LoadLibrary( "OpenCL" )
+#define ocl_open LoadLibraryW( L"OpenCL" )
#define ocl_close FreeLibrary
#define ocl_address GetProcAddress
#else
static cl_program x264_opencl_cache_load( x264_t *h, const char *dev_name, const char *dev_vendor, const char *driver_version )
{
/* try to load cached program binary */
- FILE *fp = fopen( h->param.psz_clbin_file, "rb" );
+ FILE *fp = x264_fopen( h->param.psz_clbin_file, "rb" );
if( !fp )
return NULL;
* is also saved in the cache file so we do not reuse stale binaries */
static void x264_opencl_cache_save( x264_t *h, cl_program program, const char *dev_name, const char *dev_vendor, const char *driver_version )
{
- FILE *fp = fopen( h->param.psz_clbin_file, "wb" );
+ FILE *fp = x264_fopen( h->param.psz_clbin_file, "wb" );
if( !fp )
{
x264_log( h, X264_LOG_INFO, "OpenCL: unable to open clbin file for write\n" );
goto fail;
}
- FILE *log_file = fopen( "x264_kernel_build_log.txt", "w" );
+ FILE *log_file = x264_fopen( "x264_kernel_build_log.txt", "w" );
if( !log_file )
{
x264_log( h, X264_LOG_WARNING, "OpenCL: Compilation failed, unable to create file x264_kernel_build_log.txt\n" );
int ret = 0;
#ifdef _WIN32
- hDLL = LoadLibrary( "atiadlxx.dll" );
+ hDLL = LoadLibraryW( L"atiadlxx.dll" );
if( !hDLL )
- hDLL = LoadLibrary( "atiadlxy.dll" );
+ hDLL = LoadLibraryW( L"atiadlxy.dll" );
#else
hDLL = dlopen( "libatiadlxx.so", RTLD_LAZY|RTLD_GLOBAL );
#endif
*
* Authors: Steven Walters <kemuri9@gmail.com>
* Laurent Aimar <fenrir@via.ecp.fr>
+ * 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
#include "common.h"
+#ifdef _WIN32
+#include <windows.h>
+#include <io.h>
+#endif
+
#if SYS_WINDOWS
#include <sys/types.h>
#include <sys/timeb.h>
#include <time.h>
#if PTW32_STATIC_LIB
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
/* this is a global in pthread-win32 to indicate if it has been initialized or not */
extern int ptw32_processInitialized;
#endif
{}
#endif
#endif
+
+#ifdef _WIN32
+/* Functions for dealing with Unicode on Windows. */
+FILE *x264_fopen( const char *filename, const char *mode )
+{
+ wchar_t filename_utf16[MAX_PATH];
+ wchar_t mode_utf16[16];
+ if( utf8_to_utf16( filename, filename_utf16 ) && utf8_to_utf16( mode, mode_utf16 ) )
+ return _wfopen( filename_utf16, mode_utf16 );
+ return NULL;
+}
+
+int x264_rename( const char *oldname, const char *newname )
+{
+ wchar_t oldname_utf16[MAX_PATH];
+ wchar_t newname_utf16[MAX_PATH];
+ if( utf8_to_utf16( oldname, oldname_utf16 ) && utf8_to_utf16( newname, newname_utf16 ) )
+ {
+ /* POSIX says that rename() removes the destination, but Win32 doesn't. */
+ _wunlink( newname_utf16 );
+ return _wrename( oldname_utf16, newname_utf16 );
+ }
+ return -1;
+}
+
+int x264_stat( const char *path, x264_struct_stat *buf )
+{
+ wchar_t path_utf16[MAX_PATH];
+ if( utf8_to_utf16( path, path_utf16 ) )
+ return _wstati64( path_utf16, buf );
+ return -1;
+}
+
+int x264_vfprintf( FILE *stream, const char *format, va_list arg )
+{
+ HANDLE console = NULL;
+ DWORD mode;
+
+ if( stream == stdout )
+ console = GetStdHandle( STD_OUTPUT_HANDLE );
+ else if( stream == stderr )
+ console = GetStdHandle( STD_ERROR_HANDLE );
+
+ /* Only attempt to convert to UTF-16 when writing to a non-redirected console screen buffer. */
+ if( GetConsoleMode( console, &mode ) )
+ {
+ char buf[4096];
+ wchar_t buf_utf16[4096];
+
+ int length = vsnprintf( buf, sizeof(buf), format, arg );
+ if( length > 0 && length < sizeof(buf) )
+ {
+ /* WriteConsoleW is the most reliable way to output Unicode to a console. */
+ int length_utf16 = MultiByteToWideChar( CP_UTF8, 0, buf, length, buf_utf16, sizeof(buf_utf16)/sizeof(wchar_t) );
+ WriteConsoleW( console, buf_utf16, length_utf16, NULL, NULL );
+ return length;
+ }
+ }
+ return vfprintf( stream, format, arg );
+}
+#endif
*
* Authors: Loren Merritt <lorenm@u.washington.edu>
* Laurent Aimar <fenrir@via.ecp.fr>
+ * 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
#include <stdio.h>
#include <sys/stat.h>
#include <inttypes.h>
+#include <stdarg.h>
#include "config.h"
#define log2(x) (log(x)/0.693147180559945)
#endif
-#ifdef _WIN32
-#include <io.h> // _setmode()
-#include <fcntl.h> // _O_BINARY
-#endif
-
#ifdef __ICL
#define inline __inline
#define strcasecmp _stricmp
#if !defined(isfinite) && (SYS_OPENBSD || SYS_SunOS)
#define isfinite finite
#endif
+
#ifdef _WIN32
-#define rename(src,dst) (unlink(dst), rename(src,dst)) // POSIX says that rename() removes the destination, but win32 doesn't.
#ifndef strtok_r
#define strtok_r(str,delim,save) strtok(str,delim)
#endif
+
+#define utf8_to_utf16( utf8, utf16 )\
+ MultiByteToWideChar( CP_UTF8, MB_ERR_INVALID_CHARS, utf8, -1, utf16, sizeof(utf16)/sizeof(wchar_t) )
+FILE *x264_fopen( const char *filename, const char *mode );
+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 );
+#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
#endif
#ifdef __ICL
static inline uint8_t x264_is_regular_file( FILE *filehandle )
{
- struct stat file_stat;
- if( fstat( fileno( filehandle ), &file_stat ) )
+ x264_struct_stat file_stat;
+ if( x264_fstat( fileno( filehandle ), &file_stat ) )
return -1;
return S_ISREG( file_stat.st_mode );
}
static inline uint8_t x264_is_regular_file_path( const char *filename )
{
- struct stat file_stat;
- if( stat( filename, &file_stat ) )
+ x264_struct_stat file_stat;
+ if( x264_stat( filename, &file_stat ) )
return -1;
return S_ISREG( file_stat.st_mode );
}
int x264_win32_threading_init( void )
{
/* find function pointers to API functions, if they exist */
- HANDLE kernel_dll = GetModuleHandle( TEXT( "kernel32.dll" ) );
+ HANDLE kernel_dll = GetModuleHandleW( L"kernel32.dll" );
thread_control.cond_init = (void*)GetProcAddress( kernel_dll, "InitializeConditionVariable" );
if( thread_control.cond_init )
{
* On platforms that support processor grouping, use GetThreadGroupAffinity to get the current thread's affinity instead. */
#if ARCH_X86_64
/* find function pointers to API functions specific to x86_64 platforms, if they exist */
- HANDLE kernel_dll = GetModuleHandle( TEXT( "kernel32.dll" ) );
+ HANDLE kernel_dll = GetModuleHandleW( L"kernel32.dll" );
BOOL (*get_thread_affinity)( HANDLE thread, x264_group_affinity_t *group_affinity ) = (void*)GetProcAddress( kernel_dll, "GetThreadGroupAffinity" );
if( get_thread_affinity )
{
#ifndef X264_WIN32THREAD_H
#define X264_WIN32THREAD_H
-#define WIN32_LEAN_AND_MEAN
#include <windows.h>
/* the following macro is used within x264 */
#undef ERROR
else
SYS="WINDOWS"
DEVNULL="NUL"
+ LDFLAGSCLI="$LDFLAGSCLI -lshell32"
RC="${RC-${cross_prefix}windres}"
fi
;;
SYS="WINDOWS"
EXE=".exe"
DEVNULL="NUL"
+ LDFLAGSCLI="$LDFLAGSCLI -lshell32"
[ $compiler = ICL ] && RC="${RC-rc}" || RC="${RC-${cross_prefix}windres}"
;;
sunos*|solaris*)
if [ "$avs" = "auto" ] ; then
avs="no"
# cygwin can use avisynth if it can use LoadLibrary
- if [ $SYS = WINDOWS ] || ([ $SYS = CYGWIN ] && cc_check windows.h "" "LoadLibrary(0);") ; then
+ if [ $SYS = WINDOWS ] || ([ $SYS = CYGWIN ] && cc_check windows.h "" "LoadLibraryW(0);") ; then
avs="avisynth"
define HAVE_AVS
define USE_AVXSYNTH 0
fi
log_ok
# cygwin can use opencl if it can use LoadLibrary
- if [ $SYS = WINDOWS ] || ([ $SYS = CYGWIN ] && cc_check windows.h "" "LoadLibrary(0);") ; then
+ if [ $SYS = WINDOWS ] || ([ $SYS = CYGWIN ] && cc_check windows.h "" "LoadLibraryW(0);") ; then
opencl="yes"
define HAVE_OPENCL
elif [ "$SYS" = "LINUX" -o "$SYS" = "MACOSX" ] ; then
static void x264_frame_dump( x264_t *h )
{
- FILE *f = fopen( h->param.psz_dump_yuv, "r+b" );
+ FILE *f = x264_fopen( h->param.psz_dump_yuv, "r+b" );
if( !f )
return;
if( h->param.psz_dump_yuv )
{
/* create or truncate the reconstructed video file */
- FILE *f = fopen( h->param.psz_dump_yuv, "w" );
+ FILE *f = x264_fopen( h->param.psz_dump_yuv, "w" );
if( !f )
{
x264_log( h, X264_LOG_ERROR, "dump_yuv: can't write to %s\n", h->param.psz_dump_yuv );
char *mbtree_stats_in = x264_strcat_filename( h->param.rc.psz_stat_in, ".mbtree" );
if( !mbtree_stats_in )
return -1;
- rc->p_mbtree_stat_file_in = fopen( mbtree_stats_in, "rb" );
+ rc->p_mbtree_stat_file_in = x264_fopen( mbtree_stats_in, "rb" );
x264_free( mbtree_stats_in );
if( !rc->p_mbtree_stat_file_in )
{
if( !rc->psz_stat_file_tmpname )
return -1;
- rc->p_stat_file_out = fopen( rc->psz_stat_file_tmpname, "wb" );
+ rc->p_stat_file_out = x264_fopen( rc->psz_stat_file_tmpname, "wb" );
if( rc->p_stat_file_out == NULL )
{
x264_log( h, X264_LOG_ERROR, "ratecontrol_init: can't open stats file\n" );
if( !rc->psz_mbtree_stat_file_tmpname || !rc->psz_mbtree_stat_file_name )
return -1;
- rc->p_mbtree_stat_file_out = fopen( rc->psz_mbtree_stat_file_tmpname, "wb" );
+ rc->p_mbtree_stat_file_out = x264_fopen( rc->psz_mbtree_stat_file_tmpname, "wb" );
if( rc->p_mbtree_stat_file_out == NULL )
{
x264_log( h, X264_LOG_ERROR, "ratecontrol_init: can't open mbtree stats file\n" );
b_regular_file = x264_is_regular_file( rc->p_stat_file_out );
fclose( rc->p_stat_file_out );
if( h->i_frame >= rc->num_entries && b_regular_file )
- if( rename( rc->psz_stat_file_tmpname, h->param.rc.psz_stat_out ) != 0 )
+ if( x264_rename( rc->psz_stat_file_tmpname, h->param.rc.psz_stat_out ) != 0 )
{
x264_log( h, X264_LOG_ERROR, "failed to rename \"%s\" to \"%s\"\n",
rc->psz_stat_file_tmpname, h->param.rc.psz_stat_out );
b_regular_file = x264_is_regular_file( rc->p_mbtree_stat_file_out );
fclose( rc->p_mbtree_stat_file_out );
if( h->i_frame >= rc->num_entries && b_regular_file )
- if( rename( rc->psz_mbtree_stat_file_tmpname, rc->psz_mbtree_stat_file_name ) != 0 )
+ if( x264_rename( rc->psz_mbtree_stat_file_tmpname, rc->psz_mbtree_stat_file_name ) != 0 )
{
x264_log( h, X264_LOG_ERROR, "failed to rename \"%s\" to \"%s\"\n",
rc->psz_mbtree_stat_file_tmpname, rc->psz_mbtree_stat_file_name );
#define avs_address dlsym
#else
#include <windows.h>
-#define avs_open LoadLibrary( "avisynth" )
+#define avs_open LoadLibraryW( L"avisynth" )
#define avs_close FreeLibrary
#define avs_address GetProcAddress
#endif
static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, cli_input_opt_t *opt )
{
- FILE *fh = fopen( psz_filename, "r" );
+ FILE *fh = x264_fopen( psz_filename, "r" );
if( !fh )
return -1;
FAIL_IF_ERROR( !x264_is_regular_file( fh ), "AVS input is incompatible with non-regular file `%s'\n", psz_filename );
if( avs_version <= 0 )
return -1;
x264_cli_log( "avs", X264_LOG_DEBUG, "using avisynth version %.2f\n", avs_version );
+
+#ifdef _WIN32
+ /* Avisynth doesn't support Unicode filenames. */
+ char ansi_filename[MAX_PATH];
+ FAIL_IF_ERROR( !x264_ansi_filename( psz_filename, ansi_filename, MAX_PATH, 0 ), "invalid ansi filename\n" );
+ AVS_Value arg = avs_new_value_string( ansi_filename );
+#else
AVS_Value arg = avs_new_value_string( psz_filename );
+#endif
+
AVS_Value res;
char *filename_ext = get_filename_extension( psz_filename );
*
* Authors: Mike Gurlitz <mike.gurlitz@gmail.com>
* Steven Walters <kemuri9@gmail.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
#ifdef _WIN32
#include <windows.h>
-#else
-#define SetConsoleTitle(t)
#endif
typedef struct
char buf[200];
sprintf( buf, "ffms [info]: indexing input file [%.1f%%]", 100.0 * current / total );
fprintf( stderr, "%s \r", buf+5 );
- SetConsoleTitle( buf );
+ x264_cli_set_console_title( buf );
fflush( stderr );
return 0;
}
ffms_hnd_t *h = calloc( 1, sizeof(ffms_hnd_t) );
if( !h )
return -1;
+
+#ifdef __MINGW32__
+ /* FFMS supports UTF-8 filenames, but it uses std::fstream internally which is broken with Unicode in MinGW. */
FFMS_Init( 0, 0 );
+ char src_filename[MAX_PATH];
+ char idx_filename[MAX_PATH];
+ FAIL_IF_ERROR( !x264_ansi_filename( psz_filename, src_filename, MAX_PATH, 0 ), "invalid ansi filename\n" );
+ if( opt->index_file )
+ FAIL_IF_ERROR( !x264_ansi_filename( opt->index_file, idx_filename, MAX_PATH, 1 ), "invalid ansi filename\n" );
+#else
+ FFMS_Init( 0, 1 );
+ char *src_filename = psz_filename;
+ char *idx_filename = opt->index_file;
+#endif
+
FFMS_ErrorInfo e;
e.BufferSize = 0;
int seekmode = opt->seek ? FFMS_SEEK_NORMAL : FFMS_SEEK_LINEAR_NO_RW;
FFMS_Index *idx = NULL;
if( opt->index_file )
{
- struct stat index_s, input_s;
- if( !stat( opt->index_file, &index_s ) && !stat( psz_filename, &input_s ) &&
+ x264_struct_stat index_s, input_s;
+ if( !x264_stat( opt->index_file, &index_s ) && !x264_stat( psz_filename, &input_s ) &&
input_s.st_mtime < index_s.st_mtime )
- idx = FFMS_ReadIndex( opt->index_file, &e );
+ idx = FFMS_ReadIndex( idx_filename, &e );
}
if( !idx )
{
if( opt->progress )
{
- idx = FFMS_MakeIndex( psz_filename, 0, 0, NULL, NULL, 0, update_progress, &h->time, &e );
+ idx = FFMS_MakeIndex( src_filename, 0, 0, NULL, NULL, 0, update_progress, &h->time, &e );
fprintf( stderr, " \r" );
}
else
- idx = FFMS_MakeIndex( psz_filename, 0, 0, NULL, NULL, 0, NULL, NULL, &e );
+ idx = FFMS_MakeIndex( src_filename, 0, 0, NULL, NULL, 0, NULL, NULL, &e );
FAIL_IF_ERROR( !idx, "could not create index\n" )
- if( opt->index_file && FFMS_WriteIndex( opt->index_file, idx, &e ) )
+ if( opt->index_file && FFMS_WriteIndex( idx_filename, idx, &e ) )
x264_cli_log( "ffms", X264_LOG_WARNING, "could not write index file\n" );
}
int trackno = FFMS_GetFirstTrackOfType( idx, FFMS_TYPE_VIDEO, &e );
FAIL_IF_ERROR( trackno < 0, "could not find video track\n" )
- h->video_source = FFMS_CreateVideoSource( psz_filename, trackno, idx, 1, seekmode, &e );
+ h->video_source = FFMS_CreateVideoSource( src_filename, trackno, idx, 1, seekmode, &e );
FAIL_IF_ERROR( !h->video_source, "could not create video source\n" )
h->track = FFMS_GetTrackFromVideo( h->video_source );
if( !strcmp( psz_filename, "-" ) )
h->fh = stdin;
else
- h->fh = fopen( psz_filename, "rb" );
+ h->fh = x264_fopen( psz_filename, "rb" );
if( h->fh == NULL )
return -1;
timecode_input.picture_alloc = h->input.picture_alloc;
timecode_input.picture_clean = h->input.picture_clean;
- tcfile_in = fopen( psz_filename, "rb" );
+ tcfile_in = x264_fopen( psz_filename, "rb" );
FAIL_IF_ERROR( !tcfile_in, "can't open `%s'\n", psz_filename )
else if( !x264_is_regular_file( tcfile_in ) )
{
if( !strcmp( psz_filename, "-" ) )
h->fh = stdin;
else
- h->fh = fopen(psz_filename, "rb");
+ h->fh = x264_fopen(psz_filename, "rb");
if( h->fh == NULL )
return -1;
if( !strcmp( filename, "-" ) )
c->fp = stdout;
else
- c->fp = fopen( filename, "wb" );
+ c->fp = x264_fopen( filename, "wb" );
if( !c->fp )
{
free( c );
if( !strcmp( filename, "-" ) )
w->fp = stdout;
else
- w->fp = fopen( filename, "wb" );
+ w->fp = x264_fopen( filename, "wb" );
if( !w->fp )
{
mk_destroy_contexts( w );
mp4_hnd_t *p_mp4;
*p_handle = NULL;
- FILE *fh = fopen( psz_filename, "w" );
+ FILE *fh = x264_fopen( psz_filename, "w" );
if( !fh )
return -1;
FAIL_IF_ERR( !x264_is_regular_file( fh ), "mp4", "MP4 output is incompatible with non-regular file `%s'\n", psz_filename )
return -1;
memset( p_mp4, 0, sizeof(mp4_hnd_t) );
+
+#ifdef _WIN32
+ /* GPAC doesn't support Unicode filenames. */
+ char ansi_filename[MAX_PATH];
+ FAIL_IF_ERR( !x264_ansi_filename( psz_filename, ansi_filename, MAX_PATH, 1 ), "mp4", "invalid ansi filename\n" )
+ p_mp4->p_file = gf_isom_open( ansi_filename, GF_ISOM_OPEN_WRITE, NULL );
+#else
p_mp4->p_file = gf_isom_open( psz_filename, GF_ISOM_OPEN_WRITE, NULL );
+#endif
p_mp4->b_dts_compress = opt->use_dts_compress;
{
if( !strcmp( psz_filename, "-" ) )
*p_handle = stdout;
- else if( !(*p_handle = fopen( psz_filename, "w+b" )) )
+ else if( !(*p_handle = x264_fopen( psz_filename, "w+b" )) )
return -1;
return 0;
* Steven Walters <kemuri9@gmail.com>
* Fiona Glaser <fiona@x264.com>
* Kieran Kunhya <kieran@kunhya.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
* For more information, contact us at licensing@x264.com.
*****************************************************************************/
+#ifdef _WIN32
+/* The following two defines must be located before the inclusion of any system header files. */
+#define WINVER 0x0500
+#define _WIN32_WINNT 0x0500
+#include <windows.h>
+#include <io.h> /* _setmode() */
+#include <fcntl.h> /* _O_BINARY */
+#endif
+
#include <signal.h>
#define _GNU_SOURCE
#include <getopt.h>
#define FAIL_IF_ERROR( cond, ... ) FAIL_IF_ERR( cond, "x264", __VA_ARGS__ )
-#ifdef _WIN32
-#include <windows.h>
-#else
-#define GetConsoleTitle(t,n)
-#define SetConsoleTitle(t)
-#endif
-
#if HAVE_LAVF
#undef DECLARE_ALIGNED
#include <libavformat/avformat.h>
#include <ffms.h>
#endif
+#ifdef _WIN32
+#define CONSOLE_TITLE_SIZE 200
+static wchar_t org_console_title[CONSOLE_TITLE_SIZE] = L"";
+
+void x264_cli_set_console_title( const char *title )
+{
+ wchar_t title_utf16[CONSOLE_TITLE_SIZE];
+ if( utf8_to_utf16( title, title_utf16 ) )
+ SetConsoleTitleW( title_utf16 );
+}
+
+static int utf16_to_ansi( const wchar_t *utf16, char *ansi, int size )
+{
+ int invalid;
+ return WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, utf16, -1, ansi, size, NULL, &invalid ) && !invalid;
+}
+
+/* Some external libraries doesn't support Unicode in filenames,
+ * as a workaround we can try to get an ANSI filename instead. */
+int x264_ansi_filename( const char *filename, char *ansi_filename, int size, int create_file )
+{
+ wchar_t filename_utf16[MAX_PATH];
+ if( utf8_to_utf16( filename, filename_utf16 ) )
+ {
+ if( create_file )
+ {
+ /* Create the file using the Unicode filename if it doesn't already exist. */
+ FILE *fh = _wfopen( filename_utf16, L"ab" );
+ if( fh )
+ fclose( fh );
+ }
+
+ /* Check if the filename already is valid ANSI. */
+ if( utf16_to_ansi( filename_utf16, ansi_filename, size ) )
+ return 1;
+
+ /* Check for a legacy 8.3 short filename. */
+ int short_length = GetShortPathNameW( filename_utf16, filename_utf16, MAX_PATH );
+ if( short_length > 0 && short_length < MAX_PATH )
+ if( utf16_to_ansi( filename_utf16, ansi_filename, size ) )
+ return 1;
+ }
+ return 0;
+}
+
+/* Retrieve command line arguments as UTF-8. */
+static int get_argv_utf8( int *argc_ptr, char ***argv_ptr )
+{
+ int ret = 0;
+ wchar_t **argv_utf16 = CommandLineToArgvW( GetCommandLineW(), argc_ptr );
+ if( argv_utf16 )
+ {
+ int argc = *argc_ptr;
+ int offset = (argc+1) * sizeof(char*);
+ int size = offset;
+
+ for( int i = 0; i < argc; i++ )
+ size += WideCharToMultiByte( CP_UTF8, 0, argv_utf16[i], -1, NULL, 0, NULL, NULL );
+
+ char **argv = *argv_ptr = malloc( size );
+ if( argv )
+ {
+ for( int i = 0; i < argc; i++ )
+ {
+ argv[i] = (char*)argv + offset;
+ offset += WideCharToMultiByte( CP_UTF8, 0, argv_utf16[i], -1, argv[i], size-offset, NULL, NULL );
+ }
+ argv[argc] = NULL;
+ ret = 1;
+ }
+ LocalFree( argv_utf16 );
+ }
+ return ret;
+}
+#endif
+
/* Ctrl-C handler */
static volatile int b_ctrl_c = 0;
static int b_exit_on_ctrl_c = 0;
static void sigint_handler( int a )
{
if( b_exit_on_ctrl_c )
- exit(0);
+ {
+#ifdef _WIN32
+ SetConsoleTitleW( org_console_title );
+#endif
+ exit( 0 );
+ }
b_ctrl_c = 1;
}
-static char UNUSED originalCTitle[200] = "";
-
typedef struct {
int b_progress;
int i_seek;
fprintf( stderr, "%s [%s]: ", name, s_level );
va_list arg;
va_start( arg, fmt );
- vfprintf( stderr, fmt, arg );
+ x264_vfprintf( stderr, fmt, arg );
va_end( arg );
}
return;
va_list arg;
va_start( arg, fmt );
- vfprintf( stderr, fmt, arg );
+ x264_vfprintf( stderr, fmt, arg );
va_end( arg );
}
FAIL_IF_ERROR( x264_threading_init(), "unable to initialize threading\n" )
#ifdef _WIN32
- _setmode(_fileno(stdin), _O_BINARY);
- _setmode(_fileno(stdout), _O_BINARY);
-#endif
+ FAIL_IF_ERROR( !get_argv_utf8( &argc, &argv ), "unable to convert command line to UTF-8\n" )
- GetConsoleTitle( originalCTitle, sizeof(originalCTitle) );
+ GetConsoleTitleW( org_console_title, CONSOLE_TITLE_SIZE );
+ _setmode( _fileno( stdin ), _O_BINARY );
+ _setmode( _fileno( stdout ), _O_BINARY );
+ _setmode( _fileno( stderr ), _O_BINARY );
+#endif
/* Parse command line */
if( parse( argc, argv, ¶m, &opt ) < 0 )
ret = -1;
+#ifdef _WIN32
/* Restore title; it can be changed by input modules */
- SetConsoleTitle( originalCTitle );
+ SetConsoleTitleW( org_console_title );
+#endif
/* Control-C handler */
signal( SIGINT, sigint_handler );
if( opt.qpfile )
fclose( opt.qpfile );
- SetConsoleTitle( originalCTitle );
+#ifdef _WIN32
+ SetConsoleTitleW( org_console_title );
+ free( argv );
+#endif
return ret;
}
b_regular = b_regular && x264_is_regular_file_path( filename );
if( b_regular )
{
- FILE *f = fopen( filename, "r" );
+ FILE *f = x264_fopen( filename, "r" );
if( f )
{
b_regular = x264_is_regular_file( f );
input_opt.index_file = optarg;
break;
case OPT_QPFILE:
- opt->qpfile = fopen( optarg, "rb" );
+ opt->qpfile = x264_fopen( optarg, "rb" );
FAIL_IF_ERROR( !opt->qpfile, "can't open qpfile `%s'\n", optarg )
if( !x264_is_regular_file( opt->qpfile ) )
{
tcfile_name = optarg;
break;
case OPT_TCFILE_OUT:
- opt->tcfile_out = fopen( optarg, "wb" );
+ opt->tcfile_out = x264_fopen( optarg, "wb" );
FAIL_IF_ERROR( !opt->tcfile_out, "can't open `%s'\n", optarg )
break;
case OPT_TIMEBASE:
eta/3600, (eta/60)%60, eta%60 );
}
else
- {
sprintf( buf, "x264 %d frames: %.2f fps, %.2f kb/s", i_frame, fps, bitrate );
- }
fprintf( stderr, "%s \r", buf+5 );
- SetConsoleTitle( buf );
+ x264_cli_set_console_title( buf );
fflush( stderr ); // needed in windows
return i_time;
}
#include "x264_config.h"
-#define X264_BUILD 137
+#define X264_BUILD 138
/* Application developers planning to link against a shared library version of
* libx264 from a Microsoft Visual Studio or similar development environment
int b_constrained_intra;
int i_cqm_preset;
- char *psz_cqm_file; /* JM format */
+ char *psz_cqm_file; /* filename (in UTF-8) of CQM file, JM format */
uint8_t cqm_4iy[16]; /* used only if i_cqm_preset == X264_CQM_CUSTOM */
uint8_t cqm_4py[16];
uint8_t cqm_4ic[16];
int i_log_level;
int b_visualize;
int b_full_recon; /* fully reconstruct frames, even when not necessary for encoding. Implied by psz_dump_yuv */
- char *psz_dump_yuv; /* filename for reconstructed frames */
+ char *psz_dump_yuv; /* filename (in UTF-8) for reconstructed frames */
/* Encoder analyser parameters */
struct
/* 2pass */
int b_stat_write; /* Enable stat writing in psz_stat_out */
- char *psz_stat_out;
+ char *psz_stat_out; /* output filename (in UTF-8) of the 2pass stats file */
int b_stat_read; /* Read stat from psz_stat_in and use it */
- char *psz_stat_in;
+ char *psz_stat_in; /* input filename (in UTF-8) of the 2pass stats file */
/* 2pass params (same as ffmpeg ones) */
float f_qcompress; /* 0.0 => cbr, 1.0 => constant qp */
int b_opencl; /* use OpenCL when available */
int i_opencl_device; /* specify count of GPU devices to skip, for CLI users */
void *opencl_device_id; /* pass explicit cl_device_id as void*, for API users */
- char *psz_clbin_file; /* compiled OpenCL kernel cache file */
+ char *psz_clbin_file; /* filename (in UTF-8) of the compiled OpenCL kernel cache file */
/* Slicing parameters */
int i_slice_max_size; /* Max size per slice in bytes; includes estimated NAL overhead. */
void x264_cli_log( const char *name, int i_level, const char *fmt, ... );
void x264_cli_printf( int i_level, const char *fmt, ... );
+#ifdef _WIN32
+void x264_cli_set_console_title( const char *title );
+int x264_ansi_filename( const char *filename, char *ansi_filename, int size, int create_file );
+#else
+#define x264_cli_set_console_title( title )
+#endif
+
#define RETURN_IF_ERR( cond, name, ret, ... )\
if( cond )\
{\
*****************************************************************************
* Copyright (C) 2012-2013 x264 project
*
- * Authors: Henrik Gramner <hengar-6@student.ltu.se>
+ * Authors: 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
BEGIN
BLOCK "StringFileInfo"
BEGIN
- BLOCK "040904E4"
+ BLOCK "040904B0"
BEGIN
VALUE "CompanyName", "x264 project"
#ifdef DLL
BLOCK "VarFileInfo"
BEGIN
- VALUE "Translation", 0x0409, 0x04E4
+ VALUE "Translation", 0x0409, 0x04B0 /* U.S. English (Unicode) */
END
END