[x264-devel] [Git][videolan/x264][master] 3 commits: mp4: Fix compiling with recent GPAC versions

Anton Mitrofanov gitlab at videolan.org
Sun Oct 25 18:09:51 CET 2020



Anton Mitrofanov pushed to branch master at VideoLAN / x264


Commits:
2726e45d by Henrik Gramner at 2020-09-12T19:23:55+02:00
mp4: Fix compiling with recent GPAC versions

- - - - -
d198931a by Henrik Gramner at 2020-09-12T19:23:57+02:00
mp4: Remove GPAC Windows Unicode compatibility shim

GPAC has native UTF-8 support nowadays.

Also move the compatibility code to input/avs.c since that's the only
remaining code that uses it now.

- - - - -
7ab4c928 by Henrik Gramner at 2020-09-27T23:32:10+02:00
Add support for long filenames on Windows 10

- - - - -


7 changed files:

- Makefile
- common/osdep.h
- input/avs.c
- output/mp4.c
- x264.c
- + x264res.manifest
- x264res.rc


Changes:

=====================================
Makefile
=====================================
@@ -7,6 +7,7 @@ vpath %.h $(SRCPATH)
 vpath %.S $(SRCPATH)
 vpath %.asm $(SRCPATH)
 vpath %.rc $(SRCPATH)
+vpath %.manifest $(SRCPATH)
 
 CFLAGS += $(CFLAGSPROF)
 LDFLAGS += $(LDFLAGSPROF)
@@ -312,7 +313,7 @@ $(OBJS) $(OBJASM) $(OBJSO) $(OBJCLI) $(OBJCHK) $(OBJCHK_8) $(OBJCHK_10) $(OBJEXA
 %.dll.o: %.rc x264.h
 	$(RC) $(RCFLAGS)$@ -DDLL $<
 
-%.o: %.rc x264.h
+%.o: %.rc x264.h x264res.manifest
 	$(RC) $(RCFLAGS)$@ $<
 
 .depend: config.mak


=====================================
common/osdep.h
=====================================
@@ -116,30 +116,65 @@ static inline int x264_snprintf( char *s, size_t n, const char *fmt, ... )
 #endif
 
 #ifdef _WIN32
-#define utf8_to_utf16( utf8, utf16 )\
-    MultiByteToWideChar( CP_UTF8, MB_ERR_INVALID_CHARS, utf8, -1, utf16, sizeof(utf16)/sizeof(wchar_t) )
-
 /* Functions for dealing with Unicode on Windows. */
-static inline FILE *x264_fopen( const char *filename, const char *mode )
+static inline wchar_t *x264_utf8_to_utf16( const char *utf8 )
 {
-    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 );
+    int len = MultiByteToWideChar( CP_UTF8, MB_ERR_INVALID_CHARS, utf8, -1, NULL, 0 );
+    if( len )
+    {
+        wchar_t *utf16 = malloc( len * sizeof( wchar_t ) );
+        if( utf16 )
+        {
+            if( MultiByteToWideChar( CP_UTF8, MB_ERR_INVALID_CHARS, utf8, -1, utf16, len ) )
+                return utf16;
+            free( utf16 );
+        }
+    }
     return NULL;
 }
 
+static inline wchar_t *x264_utf8_to_utf16_try_buf( const char *utf8, wchar_t *buf_utf16, int buf_len ) {
+    if( MultiByteToWideChar( CP_UTF8, MB_ERR_INVALID_CHARS, utf8, -1, buf_utf16, buf_len ) )
+        return buf_utf16;
+    return x264_utf8_to_utf16( utf8 );
+}
+
+#define x264_fopen( filename, mode ) x264_fopen_internal( filename, L##mode )
+static inline FILE *x264_fopen_internal( const char *filename, const wchar_t *mode_utf16 )
+{
+    FILE *f = NULL;
+    wchar_t filename_buf[MAX_PATH];
+    wchar_t *filename_utf16 = x264_utf8_to_utf16_try_buf( filename, filename_buf, MAX_PATH );
+    if( filename_utf16 )
+    {
+        f = _wfopen( filename_utf16, mode_utf16 );
+        if( filename_utf16 != filename_buf )
+            free( filename_utf16 );
+    }
+    return f;
+}
+
 static inline 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 ) )
+    int ret = -1;
+    wchar_t oldname_buf[MAX_PATH];
+    wchar_t *oldname_utf16 = x264_utf8_to_utf16_try_buf( oldname, oldname_buf, MAX_PATH );
+    if( oldname_utf16 )
     {
-        /* POSIX says that rename() removes the destination, but Win32 doesn't. */
-        _wunlink( newname_utf16 );
-        return _wrename( oldname_utf16, newname_utf16 );
+        wchar_t newname_buf[MAX_PATH];
+        wchar_t *newname_utf16 = x264_utf8_to_utf16_try_buf( newname, newname_buf, MAX_PATH );
+        if( newname_utf16 )
+        {
+            /* POSIX says that rename() removes the destination, but Win32 doesn't. */
+            _wunlink( newname_utf16 );
+            ret = _wrename( oldname_utf16, newname_utf16 );
+            if( newname_utf16 != newname_buf )
+                free( newname_utf16 );
+        }
+        if( oldname_utf16 != oldname_buf )
+            free( oldname_utf16 );
     }
-    return -1;
+    return ret;
 }
 
 #define x264_struct_stat struct _stati64
@@ -147,10 +182,16 @@ static inline int x264_rename( const char *oldname, const char *newname )
 
 static inline 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 ret = -1;
+    wchar_t path_buf[MAX_PATH];
+    wchar_t *path_utf16 = x264_utf8_to_utf16_try_buf( path, path_buf, MAX_PATH );
+    if( path_utf16 )
+    {
+        ret = _wstati64( path_utf16, buf );
+        if( path_utf16 != path_buf )
+            free( path_utf16 );
+    }
+    return ret;
 }
 #else
 #define x264_fopen       fopen
@@ -197,18 +238,43 @@ static inline int x264_vfprintf( FILE *stream, const char *format, va_list arg )
     return vfprintf( stream, format, arg );
 }
 
-static inline int x264_is_pipe( const char *path )
+static inline int x264_is_regular_file_path( const char *path )
 {
-    wchar_t path_utf16[MAX_PATH];
-    if( utf8_to_utf16( path, path_utf16 ) )
-        return WaitNamedPipeW( path_utf16, 0 );
-    return 0;
+    int ret = -1;
+    wchar_t path_buf[MAX_PATH];
+    wchar_t *path_utf16 = x264_utf8_to_utf16_try_buf( path, path_buf, MAX_PATH );
+    if( path_utf16 )
+    {
+        x264_struct_stat buf;
+        if( _wstati64( path_utf16, &buf ) )
+            ret = !WaitNamedPipeW( path_utf16, 0 );
+        else
+            ret = S_ISREG( buf.st_mode );
+        if( path_utf16 != path_buf )
+            free( path_utf16 );
+    }
+    return ret;
 }
 #else
 #define x264_vfprintf vfprintf
-#define x264_is_pipe(x) 0
+
+static inline int x264_is_regular_file_path( const char *filename )
+{
+    x264_struct_stat file_stat;
+    if( x264_stat( filename, &file_stat ) )
+        return 1;
+    return S_ISREG( file_stat.st_mode );
+}
 #endif
 
+static inline int x264_is_regular_file( FILE *filehandle )
+{
+    x264_struct_stat file_stat;
+    if( x264_fstat( fileno( filehandle ), &file_stat ) )
+        return 1;
+    return S_ISREG( file_stat.st_mode );
+}
+
 #define x264_glue3_expand(x,y,z) x##_##y##_##z
 #define x264_glue3(x,y,z) x264_glue3_expand(x,y,z)
 
@@ -510,20 +576,4 @@ static ALWAYS_INLINE void x264_prefetch( void *p )
 #define x264_lower_thread_priority(p)
 #endif
 
-static inline int x264_is_regular_file( FILE *filehandle )
-{
-    x264_struct_stat file_stat;
-    if( x264_fstat( fileno( filehandle ), &file_stat ) )
-        return 1;
-    return S_ISREG( file_stat.st_mode );
-}
-
-static inline int x264_is_regular_file_path( const char *filename )
-{
-    x264_struct_stat file_stat;
-    if( x264_stat( filename, &file_stat ) )
-        return !x264_is_pipe( filename );
-    return S_ISREG( file_stat.st_mode );
-}
-
 #endif /* X264_OSDEP_H */


=====================================
input/avs.c
=====================================
@@ -253,6 +253,52 @@ static float get_avs_version( avs_hnd_t *h )
 #endif
 }
 
+#ifdef _WIN32
+static char *utf16_to_ansi( const wchar_t *utf16 )
+{
+    BOOL invalid;
+    int len = WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, utf16, -1, NULL, 0, NULL, &invalid );
+    if( len && !invalid )
+    {
+        char *ansi = malloc( len * sizeof( char ) );
+        if( ansi )
+        {
+            if( WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, utf16, -1, ansi, len, NULL, &invalid ) && !invalid )
+                return ansi;
+            free( ansi );
+        }
+    }
+    return NULL;
+}
+
+static char *utf8_to_ansi( const char *filename )
+{
+    char *ansi = NULL;
+    wchar_t *filename_utf16 = x264_utf8_to_utf16( filename );
+    if( filename_utf16 )
+    {
+        /* Check if the filename already is valid ANSI. */
+        if( !(ansi = utf16_to_ansi( filename_utf16 )) )
+        {
+            /* Check for a legacy 8.3 short filename. */
+            int len = GetShortPathNameW( filename_utf16, NULL, 0 );
+            if( len )
+            {
+                wchar_t *short_utf16 = malloc( len * sizeof( wchar_t ) );
+                if( short_utf16 )
+                {
+                    if( GetShortPathNameW( filename_utf16, short_utf16, len ) )
+                        ansi = utf16_to_ansi( short_utf16 );
+                    free( short_utf16 );
+                }
+            }
+        }
+        free( filename_utf16 );
+    }
+    return ansi;
+}
+#endif
+
 static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, cli_input_opt_t *opt )
 {
     FILE *fh = x264_fopen( psz_filename, "r" );
@@ -279,8 +325,8 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
 
 #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" );
+    char *ansi_filename = utf8_to_ansi( psz_filename );
+    FAIL_IF_ERROR( !ansi_filename, "invalid ansi filename\n" );
     AVS_Value arg = avs_new_value_string( ansi_filename );
 #else
     AVS_Value arg = avs_new_value_string( psz_filename );
@@ -292,6 +338,9 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
     if( !strcasecmp( filename_ext, "avs" ) )
     {
         res = h->func.avs_invoke( h->env, "Import", arg, NULL );
+#ifdef _WIN32
+        free( ansi_filename );
+#endif
         FAIL_IF_ERROR( avs_is_error( res ), "%s\n", avs_as_error( res ) );
         /* check if the user is using a multi-threaded script and apply distributor if necessary.
            adapted from avisynth's vfw interface */
@@ -332,6 +381,9 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
             }
             x264_cli_printf( X264_LOG_INFO, "failed\n" );
         }
+#ifdef _WIN32
+        free( ansi_filename );
+#endif
         FAIL_IF_ERROR( !filter[i], "unable to find source filter to open `%s'\n", psz_filename );
     }
     FAIL_IF_ERROR( !avs_is_clip( res ), "`%s' didn't return a video clip\n", psz_filename );


=====================================
output/mp4.c
=====================================
@@ -27,10 +27,6 @@
 #include "output.h"
 #include <gpac/isomedia.h>
 
-#ifdef _WIN32
-#include <windows.h>
-#endif
-
 typedef struct
 {
     GF_ISOFile *p_file;
@@ -181,15 +177,7 @@ static int open_file( char *psz_filename, hnd_t *p_handle, cli_output_opt_t *opt
     if( !p_mp4 )
         return -1;
 
-#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( !(p_mp4->p_sample = gf_isom_sample_new()) )


=====================================
x264.c
=====================================
@@ -80,44 +80,10 @@ 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 ) )
+    if( MultiByteToWideChar( CP_UTF8, MB_ERR_INVALID_CHARS, title, -1, title_utf16, CONSOLE_TITLE_SIZE ) )
         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 )
 {
@@ -354,7 +320,7 @@ static void print_version_info( void )
     printf( "(ffmpegsource %d.%d.%d.%d)\n", FFMS_VERSION >> 24, (FFMS_VERSION & 0xff0000) >> 16, (FFMS_VERSION & 0xff00) >> 8, FFMS_VERSION & 0xff );
 #endif
 #if HAVE_GPAC
-    printf( "(gpac " GPAC_FULL_VERSION ")\n" );
+    printf( "(gpac " GPAC_VERSION ")\n" );
 #endif
 #if HAVE_LSMASH
     printf( "(lsmash %d.%d.%d)\n", LSMASH_VERSION_MAJOR, LSMASH_VERSION_MINOR, LSMASH_VERSION_MICRO );


=====================================
x264res.manifest
=====================================
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+    <assemblyIdentity type="win32" name="VideoLAN.x264" version="1.0.0.0"/>
+    <application xmlns="urn:schemas-microsoft-com:asm.v3">
+        <windowsSettings>
+            <longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
+            <activeCodePage xmlns="http://schemas.microsoft.com/SMI/2019/WindowsSettings">UTF-8</activeCodePage>
+        </windowsSettings>
+    </application>
+</assembly>


=====================================
x264res.rc
=====================================
@@ -35,6 +35,10 @@
 #define str(s) #s
 #define xstr(s) str(s)
 
+#ifndef DLL
+1 RT_MANIFEST "x264res.manifest"
+#endif
+
 VS_VERSION_INFO VERSIONINFO
 FILEVERSION     0, X264_BUILD, X264_REV, X264_REV_DIFF
 PRODUCTVERSION  0, X264_BUILD, X264_REV, X264_REV_DIFF



View it on GitLab: https://code.videolan.org/videolan/x264/-/compare/db0d417728460c647ed4a847222a535b00d3dbcb...7ab4c928ef4511ea5753a36a57c3506d9fd5086b

-- 
View it on GitLab: https://code.videolan.org/videolan/x264/-/compare/db0d417728460c647ed4a847222a535b00d3dbcb...7ab4c928ef4511ea5753a36a57c3506d9fd5086b
You're receiving this email because of your account on code.videolan.org.




More information about the x264-devel mailing list