Skip to content

Commit

Permalink
Handle unicode file names on windows
Browse files Browse the repository at this point in the history
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ö <[email protected]>
  • Loading branch information
gkv311 authored and mstorsjo committed Apr 23, 2011
1 parent 9261e6c commit b1ac139
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 1 deletion.
63 changes: 63 additions & 0 deletions cmdutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,13 +155,76 @@ 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*))
{
const char *opt, *arg;
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) {
Expand Down
28 changes: 28 additions & 0 deletions libavformat/os_support.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
5 changes: 5 additions & 0 deletions libavformat/os_support.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion libavformat/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -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, \
Expand Down

0 comments on commit b1ac139

Please sign in to comment.