[FFmpeg-cvslog] Handle unicode file names on windows
Kirill Gavrilov
git at videolan.org
Sun Apr 24 03:50:11 CEST 2011
ffmpeg | branch: master | Kirill Gavrilov <gavr.mail at gmail.com> | Wed Apr 20 14:36:44 2011 +0300| [b1ac139d89b9fc55b70ad3411af2f75fe8b17805] | committer: Martin Storsjö
Handle unicode file names on windows
All file names should be in UTF-8 within libavformat.
This is handled by mapping the open() function to an internal one
in os_support.h for windows.
fopen() could be overridden in the same way, but if that would be
used from ffmpeg.c, it would add a dependency on an ff prefixed
internal lavf function.
Signed-off-by: Martin Storsjö <martin at martin.st>
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=b1ac139d89b9fc55b70ad3411af2f75fe8b17805
---
cmdutils.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++
libavformat/os_support.c | 28 ++++++++++++++++++++
libavformat/os_support.h | 5 +++
libavformat/version.h | 2 +-
4 files changed, 97 insertions(+), 1 deletions(-)
diff --git a/cmdutils.c b/cmdutils.c
index f1cbd55..f25f61d 100644
--- a/cmdutils.c
+++ b/cmdutils.c
@@ -155,6 +155,66 @@ static const OptionDef* find_option(const OptionDef *po, const char *name){
return po;
}
+#if defined(_WIN32) && !defined(__MINGW32CE__)
+/* Will be leaked on exit */
+static char** win32_argv_utf8 = NULL;
+static int win32_argc = 0;
+
+/**
+ * Prepare command line arguments for executable.
+ * For Windows - perform wide-char to UTF-8 conversion.
+ * Input arguments should be main() function arguments.
+ * @param argc_ptr Arguments number (including executable)
+ * @param argv_ptr Arguments list.
+ */
+static void prepare_app_arguments(int *argc_ptr, char ***argv_ptr)
+{
+ char *argstr_flat;
+ wchar_t **argv_w;
+ int i, buffsize = 0, offset = 0;
+
+ if (win32_argv_utf8) {
+ *argc_ptr = win32_argc;
+ *argv_ptr = win32_argv_utf8;
+ return;
+ }
+
+ win32_argc = 0;
+ argv_w = CommandLineToArgvW(GetCommandLineW(), &win32_argc);
+ if (win32_argc <= 0 || !argv_w)
+ return;
+
+ /* determine the UTF-8 buffer size (including NULL-termination symbols) */
+ for (i = 0; i < win32_argc; i++)
+ buffsize += WideCharToMultiByte(CP_UTF8, 0, argv_w[i], -1,
+ NULL, 0, NULL, NULL);
+
+ win32_argv_utf8 = av_mallocz(sizeof(char*) * (win32_argc + 1) + buffsize);
+ argstr_flat = (char*)win32_argv_utf8 + sizeof(char*) * (win32_argc + 1);
+ if (win32_argv_utf8 == NULL) {
+ LocalFree(argv_w);
+ return;
+ }
+
+ for (i = 0; i < win32_argc; i++) {
+ win32_argv_utf8[i] = &argstr_flat[offset];
+ offset += WideCharToMultiByte(CP_UTF8, 0, argv_w[i], -1,
+ &argstr_flat[offset],
+ buffsize - offset, NULL, NULL);
+ }
+ win32_argv_utf8[i] = NULL;
+ LocalFree(argv_w);
+
+ *argc_ptr = win32_argc;
+ *argv_ptr = win32_argv_utf8;
+}
+#else
+static inline void prepare_app_arguments(int *argc_ptr, char ***argv_ptr)
+{
+ /* nothing to do */
+}
+#endif /* WIN32 && !__MINGW32CE__ */
+
void parse_options(int argc, char **argv, const OptionDef *options,
void (* parse_arg_function)(const char*))
{
@@ -162,6 +222,9 @@ void parse_options(int argc, char **argv, const OptionDef *options,
int optindex, handleoptions=1;
const OptionDef *po;
+ /* perform system-dependent conversions for arguments list */
+ prepare_app_arguments(&argc, &argv);
+
/* parse options */
optindex = 1;
while (optindex < argc) {
diff --git a/libavformat/os_support.c b/libavformat/os_support.c
index 5a3a1bb..05577b7 100644
--- a/libavformat/os_support.c
+++ b/libavformat/os_support.c
@@ -28,6 +28,34 @@
#include "avformat.h"
#include "os_support.h"
+#if defined(_WIN32) && !defined(__MINGW32CE__)
+#include <windows.h>
+
+#undef open
+int ff_win32_open(const char *filename_utf8, int oflag, int pmode)
+{
+ int fd;
+ int num_chars;
+ wchar_t *filename_w;
+
+ /* convert UTF-8 to wide chars */
+ num_chars = MultiByteToWideChar(CP_UTF8, 0, filename_utf8, -1, NULL, 0);
+ if (num_chars <= 0)
+ return -1;
+ filename_w = av_mallocz(sizeof(wchar_t) * num_chars);
+ MultiByteToWideChar(CP_UTF8, 0, filename_utf8, -1, filename_w, num_chars);
+
+ fd = _wopen(filename_w, oflag, pmode);
+ av_freep(&filename_w);
+
+ /* filename maybe be in CP_ACP */
+ if (fd == -1 && !(oflag & O_CREAT))
+ return open(filename_utf8, oflag, pmode);
+
+ return fd;
+}
+#endif
+
#if CONFIG_NETWORK
#include <fcntl.h>
#include <unistd.h>
diff --git a/libavformat/os_support.h b/libavformat/os_support.h
index dc01e64..521e997 100644
--- a/libavformat/os_support.h
+++ b/libavformat/os_support.h
@@ -45,6 +45,11 @@ static inline int is_dos_path(const char *path)
return 0;
}
+#if defined(_WIN32) && !defined(__MINGW32CE__)
+int ff_win32_open(const char *filename, int oflag, int pmode);
+#define open ff_win32_open
+#endif
+
#if CONFIG_NETWORK
#if !HAVE_SOCKLEN_T
typedef int socklen_t;
diff --git a/libavformat/version.h b/libavformat/version.h
index 9041f92..22b5dc9 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -25,7 +25,7 @@
#define LIBAVFORMAT_VERSION_MAJOR 53
#define LIBAVFORMAT_VERSION_MINOR 0
-#define LIBAVFORMAT_VERSION_MICRO 2
+#define LIBAVFORMAT_VERSION_MICRO 3
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
LIBAVFORMAT_VERSION_MINOR, \
More information about the ffmpeg-cvslog
mailing list