[x265] Allows for Unicode filenames in Windows (output and stat files).
Mateusz
mateuszb at poczta.onet.pl
Thu Apr 28 10:05:18 CEST 2016
# HG changeset patch
# User Ma0 <mateuszb at poczta.onet.pl>
# Date 1461830370 -7200
# Thu Apr 28 09:59:30 2016 +0200
# Node ID 705b7ba5bad5da71f09292a4ee23544e89dac5b5
# Parent 19cced21060f71e8efe5f2544ccb14f9273fd93c
Allows for Unicode filenames in Windows (output and stat files).
Copy of x264 code for processing Unicode filenames in Windows.
Output file and stat file(s) are very important for GUI makers.
diff -r 19cced21060f -r 705b7ba5bad5 source/common/common.cpp
--- a/source/common/common.cpp Tue Apr 26 15:06:55 2016 -0700
+++ b/source/common/common.cpp Thu Apr 28 09:59:30 2016 +0200
@@ -29,6 +29,8 @@
#if _WIN32
#include <sys/types.h>
#include <sys/timeb.h>
+#include <io.h>
+#include <fcntl.h>
#else
#include <sys/time.h>
#endif
@@ -139,6 +141,90 @@
fputs(buffer, stderr);
}
+#if _WIN32
+/* For Unicode filenames in Windows we convert UTF-8 strings to UTF-16
and we use _w functions.
+ * For other OS we do not make any changes. */
+void general_log_file(const x265_param* param, const char* caller, int
level, const char* fmt, ...)
+{
+ if (param && level > param->logLevel)
+ return;
+ const int bufferSize = 4096;
+ char buffer[bufferSize];
+ int p = 0;
+ const char* log_level;
+ switch (level)
+ {
+ case X265_LOG_ERROR:
+ log_level = "error";
+ break;
+ case X265_LOG_WARNING:
+ log_level = "warning";
+ break;
+ case X265_LOG_INFO:
+ log_level = "info";
+ break;
+ case X265_LOG_DEBUG:
+ log_level = "debug";
+ break;
+ case X265_LOG_FULL:
+ log_level = "full";
+ break;
+ default:
+ log_level = "unknown";
+ break;
+ }
+
+ if (caller)
+ p += sprintf(buffer, "%-4s [%s]: ", caller, log_level);
+ va_list arg;
+ va_start(arg, fmt);
+ vsnprintf(buffer + p, bufferSize - p, fmt, arg);
+ va_end(arg);
+
+ wchar_t buf_utf16[bufferSize];
+ MultiByteToWideChar(CP_UTF8, 0, buffer, -1, buf_utf16,
sizeof(buf_utf16)/sizeof(wchar_t));
+ fflush(stderr);
+ int oldmode = _setmode(_fileno(stderr), _O_U8TEXT);
+ fwprintf(stderr, L"%ls", buf_utf16); // WARNING: due
to bug in msvcrt.dll fputws doesn't work in mingw/gcc
+ fflush(stderr);
+ _setmode(_fileno(stderr), oldmode);
+}
+
+FILE* x265_fopen(const char* fileName, const char* mode)
+{
+ wchar_t buf_utf16[MAX_PATH * 2], mode_utf16[16];
+
+ if (MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, fileName,
-1, buf_utf16, sizeof(buf_utf16)/sizeof(wchar_t)) &&
+ MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, mode, -1,
mode_utf16, sizeof(mode_utf16)/sizeof(wchar_t)))
+ {
+ return _wfopen(buf_utf16, mode_utf16);
+ }
+ return NULL;
+}
+
+int x265_unlink(const char* fileName)
+{
+ wchar_t buf_utf16[MAX_PATH * 2];
+
+ if (MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, fileName,
-1, buf_utf16, sizeof(buf_utf16)/sizeof(wchar_t)))
+ return _wunlink(buf_utf16);
+
+ return -1;
+}
+
+int x265_rename(const char* oldName, const char* newName)
+{
+ wchar_t old_utf16[MAX_PATH * 2], new_utf16[MAX_PATH * 2];
+
+ if (MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, oldName, -1,
old_utf16, sizeof(old_utf16)/sizeof(wchar_t)) &&
+ MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, newName, -1,
new_utf16, sizeof(new_utf16)/sizeof(wchar_t)))
+ {
+ return _wrename(old_utf16, new_utf16);
+ }
+ return -1;
+}
+#endif
+
double x265_ssim2dB(double ssim)
{
double inv_ssim = 1 - ssim;
@@ -177,10 +263,10 @@
size_t fSize;
char *buf = NULL;
- FILE *fh = fopen(filename, "rb");
+ FILE *fh = x265_fopen(filename, "rb");
if (!fh)
{
- x265_log(NULL, X265_LOG_ERROR, "unable to open file %s\n",
filename);
+ x265_log_file(NULL, X265_LOG_ERROR, "unable to open file %s\n",
filename);
return NULL;
}
diff -r 19cced21060f -r 705b7ba5bad5 source/common/common.h
--- a/source/common/common.h Tue Apr 26 15:06:55 2016 -0700
+++ b/source/common/common.h Thu Apr 28 09:59:30 2016 +0200
@@ -404,7 +404,19 @@
/* located in common.cpp */
int64_t x265_mdate(void);
#define x265_log(param, ...) general_log(param, "x265", __VA_ARGS__)
+#define x265_log_file(param, ...) general_log_file(param, "x265",
__VA_ARGS__)
void general_log(const x265_param* param, const char* caller, int
level, const char* fmt, ...);
+#if _WIN32
+void general_log_file(const x265_param* param, const char* caller,
int level, const char* fmt, ...);
+FILE* x265_fopen(const char* fileName, const char* mode);
+int x265_unlink(const char* fileName);
+int x265_rename(const char* oldName, const char* newName);
+#else
+#define general_log_file(param, caller, level, fmt, ...)
general_log(param, caller, level, fmt, __VA_ARGS__)
+#define x265_fopen(fileName, mode) fopen(fileName, mode)
+#define x265_unlink(fileName) unlink(fileName)
+#define x265_rename(oldName, newName) rename(oldName, newName)
+#endif
int x265_exp2fix8(double x);
double x265_ssim2dB(double ssim);
diff -r 19cced21060f -r 705b7ba5bad5 source/encoder/ratecontrol.cpp
--- a/source/encoder/ratecontrol.cpp Tue Apr 26 15:06:55 2016 -0700
+++ b/source/encoder/ratecontrol.cpp Thu Apr 28 09:59:30 2016 +0200
@@ -417,11 +417,11 @@
char *tmpFile = strcatFilename(fileName, ".cutree");
if (!tmpFile)
return false;
- m_cutreeStatFileIn = fopen(tmpFile, "rb");
+ m_cutreeStatFileIn = x265_fopen(tmpFile, "rb");
X265_FREE(tmpFile);
if (!m_cutreeStatFileIn)
{
- x265_log(m_param, X265_LOG_ERROR, "can't open stats
file %s\n", tmpFile);
+ x265_log_file(m_param, X265_LOG_ERROR, "can't open
stats file %s.cutree\n", fileName);
return false;
}
}
@@ -602,11 +602,11 @@
statFileTmpname = strcatFilename(fileName, ".temp");
if (!statFileTmpname)
return false;
- m_statFileOut = fopen(statFileTmpname, "wb");
+ m_statFileOut = x265_fopen(statFileTmpname, "wb");
X265_FREE(statFileTmpname);
if (!m_statFileOut)
{
- x265_log(m_param, X265_LOG_ERROR, "can't open stats
file %s\n", statFileTmpname);
+ x265_log_file(m_param, X265_LOG_ERROR, "can't open
stats file %s.temp\n", fileName);
return false;
}
p = x265_param2string(m_param);
@@ -618,11 +618,11 @@
statFileTmpname = strcatFilename(fileName,
".cutree.temp");
if (!statFileTmpname)
return false;
- m_cutreeStatFileOut = fopen(statFileTmpname, "wb");
+ m_cutreeStatFileOut = x265_fopen(statFileTmpname, "wb");
X265_FREE(statFileTmpname);
if (!m_cutreeStatFileOut)
{
- x265_log(m_param, X265_LOG_ERROR, "can't open
mbtree stats file %s\n", statFileTmpname);
+ x265_log_file(m_param, X265_LOG_ERROR, "can't open
mbtree stats file %s.cutree.temp\n", fileName);
return false;
}
}
@@ -2656,13 +2656,12 @@
int bError = 1;
if (tmpFileName)
{
- unlink(fileName);
- bError = rename(tmpFileName, fileName);
+ x265_unlink(fileName);
+ bError = x265_rename(tmpFileName, fileName);
}
if (bError)
{
- x265_log(m_param, X265_LOG_ERROR, "failed to rename output
stats file to \"%s\"\n",
- fileName);
+ x265_log_file(m_param, X265_LOG_ERROR, "failed to rename
output stats file to \"%s\"\n", fileName);
}
X265_FREE(tmpFileName);
}
@@ -2675,13 +2674,12 @@
int bError = 1;
if (tmpFileName && newFileName)
{
- unlink(newFileName);
- bError = rename(tmpFileName, newFileName);
+ x265_unlink(newFileName);
+ bError = x265_rename(tmpFileName, newFileName);
}
if (bError)
{
- x265_log(m_param, X265_LOG_ERROR, "failed to rename cutree
output stats file to \"%s\"\n",
- newFileName);
+ x265_log_file(m_param, X265_LOG_ERROR, "failed to rename
cutree output stats file to \"%s\"\n", newFileName);
}
X265_FREE(tmpFileName);
X265_FREE(newFileName);
diff -r 19cced21060f -r 705b7ba5bad5 source/output/raw.cpp
--- a/source/output/raw.cpp Tue Apr 26 15:06:55 2016 -0700
+++ b/source/output/raw.cpp Thu Apr 28 09:59:30 2016 +0200
@@ -32,11 +32,11 @@
b_fail = false;
if (!strcmp(fname, "-"))
{
- ofs = &cout;
+ ofs = stdout;
return;
}
- ofs = new ofstream(fname, ios::binary | ios::out);
- if (ofs->fail())
+ ofs = x265_fopen(fname, "wb");
+ if (!ofs || ferror(ofs))
b_fail = true;
}
@@ -51,7 +51,7 @@
for (uint32_t i = 0; i < nalcount; i++)
{
- ofs->write((const char*)nal->payload, nal->sizeBytes);
+ fwrite((const void*)nal->payload, 1, nal->sizeBytes, ofs);
bytes += nal->sizeBytes;
nal++;
}
@@ -65,7 +65,7 @@
for (uint32_t i = 0; i < nalcount; i++)
{
- ofs->write((const char*)nal->payload, nal->sizeBytes);
+ fwrite((const void*)nal->payload, 1, nal->sizeBytes, ofs);
bytes += nal->sizeBytes;
nal++;
}
@@ -75,6 +75,6 @@
void RAWOutput::closeFile(int64_t, int64_t)
{
- if (ofs != &cout)
- delete ofs;
+ if (ofs != stdout)
+ fclose(ofs);
}
diff -r 19cced21060f -r 705b7ba5bad5 source/output/raw.h
--- a/source/output/raw.h Tue Apr 26 15:06:55 2016 -0700
+++ b/source/output/raw.h Thu Apr 28 09:59:30 2016 +0200
@@ -35,7 +35,7 @@
{
protected:
- std::ostream* ofs;
+ FILE* ofs;
bool b_fail;
diff -r 19cced21060f -r 705b7ba5bad5 source/x265.cpp
--- a/source/x265.cpp Tue Apr 26 15:06:55 2016 -0700
+++ b/source/x265.cpp Thu Apr 28 09:59:30 2016 +0200
@@ -451,10 +451,10 @@
this->output = OutputFile::open(outputfn, info);
if (this->output->isFail())
{
- x265_log(param, X265_LOG_ERROR, "failed to open output file
<%s> for writing\n", outputfn);
+ x265_log_file(param, X265_LOG_ERROR, "failed to open output
file <%s> for writing\n", outputfn);
return true;
}
- general_log(param, this->output->getName(), X265_LOG_INFO, "output
file: %s\n", outputfn);
+ general_log_file(param, this->output->getName(), X265_LOG_INFO,
"output file: %s\n", outputfn);
return false;
}
@@ -493,6 +493,39 @@
return 1;
}
+#ifdef _WIN32
+/* Copy of x264 code, which allows for Unicode characters in the
command line.
+ * 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 = (char**)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
+
/* CLI return codes:
*
* 0 - encode successful
@@ -513,6 +546,9 @@
GetConsoleTitle(orgConsoleTitle, CONSOLE_TITLE_SIZE);
SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED |
ES_AWAYMODE_REQUIRED);
+#if _WIN32
+ get_argv_utf8(&argc, &argv);
+#endif
ReconPlay* reconPlay = NULL;
CLIOptions cliopt;
More information about the x265-devel
mailing list