2011/4/15 Can Wu <[email protected]>
> Sometime adapt to environment is needed, current we need windows user,
> isn't it?
> Maybe we should add automatic detecting for this BAD stuff, instead of new
> protocol.
>
2011/4/15 Luca Barbato <[email protected]
> Sadly windows is stupid, the idea of converting the name from utf8 to
> utf16 and pass it the the right open variant is sound. Having it as
> separate protocol probably is overkill and could be done directly in the
> normal file protocol.
>
FFmpeg devel list suggest that workarounds should be in base FILE protocol
too.
In attach the patch draft that always perform UTF-8 -> UTF-16 conversion on
Windows
and if file not exists tries to use generic open() function (assume the
input
not UTF-8 but in system code-page - for some sort of backward
compatibility).
In base we can also try to validate input filename for UTF-8. But that
doesn't mean
that string in some alien encoding will always fail this check...
Also I'm not sure that Unicode utilities should be inside this file.
Also patch contains the proposal how to add Unicode support for console
tools
(ffmpeg, ffplay and so on).
Patch based on FFmpeg branch but last time I compare with LibAV
- there are no much differences in changed files.
2011/4/15 Måns Rullgård <[email protected]>
> I think it is a stupid idea, just like Windows in the first place. If
> an OS refuses to support unicode filenames in a sane way, its users will
> simply have to accept not having that feature. End of story.
>
OS doesn't refuse Unicode filenames. It supports Unicode filenames a long
time ago.
Just API is different because it was designed to support UTF-16 much early
than Linux
and others decide that UTF-16 for fools (probably thanks to Windows!) and
UTF-8 much better.
And that is NOT the reason to say Windows guys are all stupid so just don't
let them use
Unicode filenames within LibAV and other opposite libraries at all.
-----------------------------------------------
Kirill Gavrilov,
Software designer. <[email protected]>
diff --git a/cmdutils.c b/cmdutils.c
index 5b7b508..6654a31 100644
--- a/cmdutils.c
+++ b/cmdutils.c
@@ -155,6 +155,59 @@ static const OptionDef* find_option(const OptionDef *po, const char *name){
return po;
}
+#if(defined(_WIN32) || defined(__WIN32__))
+void prepare_app_arguments(int *argc_ptr, char ***argv_ptr)
+{
+ char *argstr_flat;
+ char** argv;
+ wchar_t **argvW;
+ int argc;
+ int argId;
+ int aBuffSize;
+ int anOffset;
+
+ argc = 0;
+ argvW = CommandLineToArgvW(GetCommandLineW(), &argc);
+ if(argc <= 0 || argvW == NULL) {
+ return;
+ }
+
+ argId = 0;
+ aBuffSize = 0;
+ /* determine the UTF-8 buffer size (including NULL-termination symbols) */
+ while(argId < argc) {
+ aBuffSize += WideCharToMultiByte(CP_UTF8, 0, argvW[argId++], -1,
+ NULL, 0, NULL, NULL);
+ }
+ /* allocate one-big-buffer */
+ argv = (char** )av_malloc(sizeof(char*) * argc + aBuffSize);
+ argstr_flat = (char* )argv + sizeof(char*) * argc;
+ if(argv == NULL) {
+ return;
+ }
+
+ /* now convert each parameter */
+ argId = 0;
+ anOffset = 0;
+ while(argId < argc) {
+ argv[argId] = &argstr_flat[anOffset];
+ anOffset += WideCharToMultiByte(CP_UTF8, 0, argvW[argId++], -1,
+ &argstr_flat[anOffset], aBuffSize - anOffset, NULL, NULL);
+ }
+ /* release wide-char list */
+ LocalFree(argvW);
+
+ /* setup input arguments */
+ *argc_ptr = argc;
+ *argv_ptr = argv;
+}
+#else
+void prepare_app_arguments(int *argc_ptr, char ***argv_ptr)
+{
+ /* nothing to do */
+}
+#endif /* WIN32 */
+
void parse_options(int argc, char **argv, const OptionDef *options,
void (* parse_arg_function)(const char*))
{
diff --git a/cmdutils.h b/cmdutils.h
index db84f55..32a5af2 100644
--- a/cmdutils.h
+++ b/cmdutils.h
@@ -138,6 +138,15 @@ typedef struct {
void show_help_options(const OptionDef *options, const char *msg, int mask, int value);
/**
+ * 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.
+ */
+void prepare_app_arguments(int *argc_ptr, char ***argv_ptr);
+
+/**
* Parse the command line arguments.
* @param options Array with the definitions required to interpret every
* option of the form: -option_name [argument]
diff --git a/ffmpeg.c b/ffmpeg.c
index 8e44895..d176a83 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -4415,6 +4415,9 @@ int main(int argc, char **argv)
{
int64_t ti;
+ /* perform system-dependent conversions for arguments list */
+ prepare_app_arguments(&argc, &argv);
+
av_log_set_flags(AV_LOG_SKIP_REPEATED);
avcodec_register_all();
diff --git a/ffplay.c b/ffplay.c
index 8a55e7d..ef52ddc 100644
--- a/ffplay.c
+++ b/ffplay.c
@@ -3089,6 +3089,9 @@ int main(int argc, char **argv)
{
int flags;
+ /* perform system-dependent conversions for arguments list */
+ prepare_app_arguments(&argc, &argv);
+
av_log_set_flags(AV_LOG_SKIP_REPEATED);
/* register all codecs, demux and protocols */
diff --git a/ffprobe.c b/ffprobe.c
index 9c2fd43..f37e20e 100644
--- a/ffprobe.c
+++ b/ffprobe.c
@@ -390,6 +390,9 @@ int main(int argc, char **argv)
{
int ret;
+ /* perform system-dependent conversions for arguments list */
+ prepare_app_arguments(&argc, &argv);
+
av_register_all();
#if CONFIG_AVDEVICE
avdevice_register_all();
diff --git a/ffserver.c b/ffserver.c
index a047e73..ae446bd 100644
--- a/ffserver.c
+++ b/ffserver.c
@@ -4690,6 +4690,9 @@ int main(int argc, char **argv)
{
struct sigaction sigact;
+ /* perform system-dependent conversions for arguments list */
+ prepare_app_arguments(&argc, &argv);
+
av_register_all();
show_banner();
diff --git a/libavformat/file.c b/libavformat/file.c
index 9d28a89..0b71ed9 100644
--- a/libavformat/file.c
+++ b/libavformat/file.c
@@ -70,7 +70,7 @@ static int file_open(URLContext *h, const char *filename, int flags)
#ifdef O_BINARY
access |= O_BINARY;
#endif
- fd = open(filename, access, 0666);
+ fd = ff_open_file(filename, access, 0666);
if (fd == -1)
return AVERROR(errno);
h->priv_data = (void *) (intptr_t) fd;
diff --git a/libavformat/os_support.c b/libavformat/os_support.c
index 0b7b59e..e7146ea 100644
--- a/libavformat/os_support.c
+++ b/libavformat/os_support.c
@@ -28,6 +28,47 @@
#include "avformat.h"
#include "os_support.h"
+#if(defined(_WIN32) || defined(__WIN32__))
+#include <windows.h>
+
+int ff_open_file(const char *filenameUtf8, int oflag, int pmode)
+{
+ int fd;
+ int uChars;
+ wchar_t *filenameUtf16;
+
+ /* convert UTF-8 to wide chars */
+ uChars = MultiByteToWideChar(CP_UTF8, 0,
+ filenameUtf8, -1,
+ NULL, 0);
+ if(uChars <= 0) {
+ return -1;
+ }
+ filenameUtf16 = (wchar_t* )av_malloc(sizeof(wchar_t) * uChars);
+ memset(filenameUtf16, 0, sizeof(wchar_t) * uChars);
+ MultiByteToWideChar(CP_UTF8, 0,
+ filenameUtf8, -1,
+ filenameUtf16, uChars);
+
+ fd = _wopen(filenameUtf16, oflag, pmode);
+ av_freep(&filenameUtf16);
+
+ /* filename maybe be in CP_ACP */
+ if(fd == -1 && !(oflag & O_CREAT)) {
+ return open(filenameUtf8, oflag, pmode);
+ }
+
+ return fd;
+}
+#else
+#include <fcntl.h>
+
+int ff_open_file(const char *filename, int oflag, int pmode)
+{
+ return open(filename, oflag, pmode);
+}
+#endif /* WIN32 */
+
#if CONFIG_NETWORK
#include <fcntl.h>
#include <unistd.h>
diff --git a/libavformat/os_support.h b/libavformat/os_support.h
index df32151..ae7e197 100644
--- a/libavformat/os_support.h
+++ b/libavformat/os_support.h
@@ -45,6 +45,16 @@ static inline int is_dos_path(const char *path)
return 0;
}
+/**
+ * System-dependent open file function.
+ * @param filename File path in system-dependent encoding format
+ * should be UTF-8 in Windows
+ * @param oflag Type of operations allowed
+ * @param pmode Permission mode
+ * @return File descriptor for the opened file; -1 indicates an error.
+ */
+int ff_open_file(const char *filename, int oflag, int pmode);
+
#if CONFIG_NETWORK
#if !HAVE_SOCKLEN_T
typedef int socklen_t;
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel