From dd087464dd8dd0d93ac03a4cb30b404ee619924f Mon Sep 17 00:00:00 2001 From: Mehdi Sabwat Date: Wed, 4 Nov 2020 17:40:30 +0100 Subject: [PATCH 01/16] nacl: remove deprecated platform This commit removes conditional code for the Nacl platform, in the core and contribs. https://blog.chromium.org/2020/08/changes-to-chrome-app-support-timeline.html --- compat/flockfile.c | 11 ----- compat/getpid.c | 2 - compat/pathconf.c | 40 ---------------- compat/recvmsg.c | 79 -------------------------------- compat/sendmsg.c | 61 ------------------------ compat/sigwait.c | 4 +- configure.ac | 11 +---- contrib/bootstrap | 3 -- contrib/src/ass/rules.mak | 6 --- contrib/src/ffmpeg/rules.mak | 4 -- contrib/src/fontconfig/rules.mak | 4 -- contrib/src/gcrypt/rules.mak | 6 --- contrib/src/gmp/rules.mak | 5 -- contrib/src/gnutls/rules.mak | 4 -- contrib/src/gpg-error/rules.mak | 9 ---- contrib/src/mpg123/rules.mak | 4 -- contrib/src/postproc/rules.mak | 4 -- include/vlc_fixups.h | 24 +--------- m4/dolt.m4 | 2 +- src/Makefile.am | 13 ------ src/network/getaddrinfo.c | 3 +- 21 files changed, 7 insertions(+), 292 deletions(-) delete mode 100644 compat/pathconf.c diff --git a/compat/flockfile.c b/compat/flockfile.c index 1db85a23a1..f3c4fff284 100644 --- a/compat/flockfile.c +++ b/compat/flockfile.c @@ -54,17 +54,6 @@ int putc_unlocked (int c, FILE *stream) { return _putc_nolock (c, stream); } - -#elif defined __native_client__ -void flockfile (FILE *stream) -{ - _flockfile(stream); -} - -void funlockfile (FILE *stream) -{ - _funlockfile(stream); -} #else # error flockfile not implemented on your platform! #endif diff --git a/compat/getpid.c b/compat/getpid.c index d6275e7df3..5645d50bb4 100644 --- a/compat/getpid.c +++ b/compat/getpid.c @@ -31,8 +31,6 @@ pid_t getpid (void) { #if defined (_WIN32) return (pid_t) GetCurrentProcessId (); -#elif defined (__native_client__) - return 1; #else # error Unimplemented! #endif diff --git a/compat/pathconf.c b/compat/pathconf.c deleted file mode 100644 index 34f990ab19..0000000000 --- a/compat/pathconf.c +++ /dev/null @@ -1,40 +0,0 @@ -/***************************************************************************** - * pathconf.c: POSIX pathconf() replacement - ***************************************************************************** - * Copyright (C) 2017 VLC authors and VideoLAN - * - * Authors: Dennis Hamester - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. - *****************************************************************************/ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include - -#ifdef __native_client__ -long pathconf (const char *path, int name) -{ - VLC_UNUSED(path); - VLC_UNUSED(name); - return -1; -} -#elif defined(_WIN32) -/* Windows does not have pathconf, but that is OK */ -#else -# error pathconf not implemented on your platform! -#endif diff --git a/compat/recvmsg.c b/compat/recvmsg.c index 1c348fcee2..d110232f1e 100644 --- a/compat/recvmsg.c +++ b/compat/recvmsg.c @@ -83,85 +83,6 @@ ssize_t recvmsg(int fd, struct msghdr *msg, int flags) return -1; } -#elif defined __native_client__ -#include -#include -#include -#include -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#ifdef HAVE_SYS_UIO_H -#include -#endif - -ssize_t recvmsg(int fd, struct msghdr *msg, int flags) -{ - if (msg->msg_controllen != 0) - { - errno = ENOSYS; - return -1; - } - - if ((msg->msg_iovlen <= 0) || (msg->msg_iovlen > IOV_MAX)) - { - errno = EMSGSIZE; - return -1; - } - - size_t full_size = 0; - for (int i = 0; i < msg->msg_iovlen; ++i) - full_size += msg->msg_iov[i].iov_len; - - if (full_size > SSIZE_MAX) { - errno = EINVAL; - return -1; - } - - /** - * We always allocate here, because whether recv/recvfrom allow NULL message - * or not is unspecified. - */ - char *data = malloc(full_size ? full_size : 1); - if (!data) { - errno = ENOMEM; - return -1; - } - - ssize_t res; - if (msg->msg_name) - res = recvfrom(fd, data, full_size, flags, msg->msg_name, &msg->msg_namelen); - else - res = recv(fd, data, full_size, flags); - - if (res > 0) { - size_t left; - if ((size_t)res <= full_size) { - left = res; - msg->msg_flags = 0; - } - else { - left = full_size; - msg->msg_flags = MSG_TRUNC; - } - - const char *src = data; - for (int i = 0; (i < msg->msg_iovlen) && (left > 0); ++i) - { - size_t to_copy = msg->msg_iov[i].iov_len; - if (to_copy > left) - to_copy = left; - - memcpy(msg->msg_iov[i].iov_base, src, to_copy); - src += to_copy; - left -= to_copy; - } - } - - free(data); - return res; -} - #else #error recvmsg not implemented on your platform! #endif diff --git a/compat/sendmsg.c b/compat/sendmsg.c index 0b08ce0942..3b5a6c42fd 100644 --- a/compat/sendmsg.c +++ b/compat/sendmsg.c @@ -73,67 +73,6 @@ ssize_t sendmsg(int fd, const struct msghdr *msg, int flags) return -1; } -#elif defined __native_client__ -#include -#include -#include -#include -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#ifdef HAVE_SYS_UIO_H -#include -#endif - -ssize_t sendmsg(int fd, const struct msghdr *msg, int flags) -{ - if (msg->msg_controllen != 0) - { - errno = ENOSYS; - return -1; - } - - if ((msg->msg_iovlen <= 0) || (msg->msg_iovlen > IOV_MAX)) - { - errno = EMSGSIZE; - return -1; - } - - size_t full_size = 0; - for (int i = 0; i < msg->msg_iovlen; ++i) - full_size += msg->msg_iov[i].iov_len; - - if (full_size > SSIZE_MAX) { - errno = EINVAL; - return -1; - } - - /** - * We always allocate here, because whether send/sento allow NULL message or - * not is unspecified. - */ - char *data = malloc(full_size ? full_size : 1); - if (!data) { - errno = ENOMEM; - return -1; - } - - size_t tmp = 0; - for (int i = 0; i < msg->msg_iovlen; ++i) { - memcpy(data + tmp, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len); - tmp += msg->msg_iov[i].iov_len; - } - - ssize_t res; - if (msg->msg_name) - res = sendto(fd, data, full_size, flags, msg->msg_name, msg->msg_namelen); - else - res = send(fd, data, full_size, flags); - - free(data); - return res; -} - #else #error sendmsg not implemented on your platform! #endif diff --git a/compat/sigwait.c b/compat/sigwait.c index e5a082d2d6..30e0205dac 100644 --- a/compat/sigwait.c +++ b/compat/sigwait.c @@ -24,8 +24,8 @@ # include #endif -#ifdef __native_client__ -/* NaCl has no working sigwait, but SIGPIPE, for which vlc uses sigwait +#if defined(__EMSCRIPTEN__) +/* Emscripten has no working sigwait, but SIGPIPE, for which vlc uses sigwait * currently, is never generated in NaCl. So for SIGPIPE it's safe to instantly * return, for all others run into an assertion. */ diff --git a/configure.ac b/configure.ac index 77f227a41b..d5bac76609 100644 --- a/configure.ac +++ b/configure.ac @@ -371,13 +371,6 @@ case "${host_os}" in X86ASMFLAGS="-f aout" X86ASMDEFS="-DARCH_X86_32=1 -DARCH_X86_64=0 -DPREFIX" ;; - *nacl*) - SYS=nacl - AC_DEFINE([_XOPEN_SOURCE], [700], [POSIX and XPG 7th edition]) - AC_LIBOBJ([sigwait]) - AC_LIBOBJ([recvmsg]) - AC_LIBOBJ([sendmsg]) - ;; *) SYS="${host_os}" ;; @@ -427,7 +420,6 @@ AM_CONDITIONAL([HAVE_IOS], [test "${HAVE_IOS}" = "1"]) AM_CONDITIONAL([HAVE_OSX], [test "${HAVE_OSX}" = "1"]) AM_CONDITIONAL([HAVE_TVOS], [test "${HAVE_TVOS}" = "1"]) -AM_CONDITIONAL([HAVE_NACL], [test "${SYS}" = "nacl"]) AM_CONDITIONAL([HAVE_LIBANL], [test "${HAVE_LIBANL}" = "1"]) AM_CONDITIONAL([HAVE_WIN32], [test "${SYS}" = "mingw32"]) @@ -697,7 +689,8 @@ need_libc=false dnl Check for usual libc functions AC_CHECK_FUNCS([accept4 dup3 fcntl flock fstatat fstatvfs fork getmntent_r getenv getpwuid_r isatty memalign mkostemp mmap open_memstream newlocale pipe2 pread posix_fadvise posix_madvise setlocale stricmp strnicmp strptime uselocale wordexp]) -AC_REPLACE_FUNCS([aligned_alloc atof atoll dirfd fdopendir flockfile fsync getdelim getpid lfind lldiv memrchr nrand48 poll posix_memalign recvmsg rewind sendmsg setenv strcasecmp strcasestr strdup strlcpy strndup strnlen strnstr strsep strtof strtok_r strtoll swab tdestroy tfind timegm timespec_get strverscmp pathconf]) +AC_REPLACE_FUNCS([aligned_alloc atof atoll dirfd fdopendir flockfile fsync getdelim getpid lfind lldiv memrchr nrand48 poll posix_memalign recvmsg rewind sendmsg setenv strcasecmp strcasestr strdup strlcpy strndup strnlen strnstr strsep strtof strtok_r strtoll swab tdestroy tfind timegm timespec_get strverscmp]) + AC_REPLACE_FUNCS([gettimeofday]) AC_CHECK_FUNC(fdatasync,, [AC_DEFINE(fdatasync, fsync, [Alias fdatasync() to fsync() if missing.]) diff --git a/contrib/bootstrap b/contrib/bootstrap index e395a02652..72ca130520 100755 --- a/contrib/bootstrap +++ b/contrib/bootstrap @@ -355,9 +355,6 @@ case "${OS}" in *solaris*) add_make_enabled "HAVE_SOLARIS" ;; - *nacl*) - add_make_enabled "HAVE_NACL" - ;; esac # diff --git a/contrib/src/ass/rules.mak b/contrib/src/ass/rules.mak index 364afbad17..fc6a90bb03 100644 --- a/contrib/src/ass/rules.mak +++ b/contrib/src/ass/rules.mak @@ -23,14 +23,8 @@ WITH_FONTCONFIG = 0 WITH_HARFBUZZ = 1 WITH_DWRITE = 1 else -ifdef HAVE_NACL WITH_FONTCONFIG = 1 WITH_HARFBUZZ = 1 -WITH_ASS_ASM = 0 -else -WITH_FONTCONFIG = 1 -WITH_HARFBUZZ = 1 -endif endif endif endif diff --git a/contrib/src/ffmpeg/rules.mak b/contrib/src/ffmpeg/rules.mak index 178a47656c..aa445154d6 100644 --- a/contrib/src/ffmpeg/rules.mak +++ b/contrib/src/ffmpeg/rules.mak @@ -209,10 +209,6 @@ endif FFMPEGCONF += --target-os=sunos --enable-pic endif -ifdef HAVE_NACL -FFMPEGCONF+=--disable-inline-asm --disable-asm --target-os=linux -endif - # Build PKGS += ffmpeg ifeq ($(call need_pkg,"libavcodec >= $(FFMPEG_LAVC_MIN) libavformat >= 53.21.0 libswscale"),) diff --git a/contrib/src/fontconfig/rules.mak b/contrib/src/fontconfig/rules.mak index 08b6a04cc0..b761d44bd5 100644 --- a/contrib/src/fontconfig/rules.mak +++ b/contrib/src/fontconfig/rules.mak @@ -50,10 +50,6 @@ FONTCONFIG_ENV += LIBXML2_CFLAGS=`xml2-config --cflags` FONTCONFIG_ENV += LIBXML2_LIBS=`xml2-config --libs` endif -ifdef HAVE_NACL -FONTCONFIG_ENV += ac_cv_func_random=no -endif - DEPS_fontconfig = freetype2 $(DEPS_freetype2) libxml2 $(DEPS_libxml2) .fontconfig: fontconfig diff --git a/contrib/src/gcrypt/rules.mak b/contrib/src/gcrypt/rules.mak index e710f90e70..c9c9be3efa 100644 --- a/contrib/src/gcrypt/rules.mak +++ b/contrib/src/gcrypt/rules.mak @@ -72,12 +72,6 @@ ifeq ($(ARCH),aarch64) GCRYPT_CONF += --disable-arm-crypto-support endif endif -ifdef HAVE_NACL -GCRYPT_CONF += --disable-asm --disable-aesni-support ac_cv_func_syslog=no --disable-sse41-support -GCRYPT_CONF += --disable-avx-support --disable-avx2-support --disable-padlock-support -GCRYPT_CONF += --disable-amd64-as-feature-detection --disable-drng-support -GCRYPT_CONF += --disable-pclmul-support -endif .gcrypt: gcrypt # Reconfiguring this requires a git repo to be available, to diff --git a/contrib/src/gmp/rules.mak b/contrib/src/gmp/rules.mak index de2ce20175..11fe8acdfa 100644 --- a/contrib/src/gmp/rules.mak +++ b/contrib/src/gmp/rules.mak @@ -13,11 +13,6 @@ ifeq ($(ARCH),mips64el) GMP_CONF += --disable-assembly endif endif -ifdef HAVE_NACL -ifeq ($(ARCH),x86_64) -GMP_CONF += --disable-assembly -endif -endif ifdef HAVE_WIN32 ifeq ($(ARCH),arm) diff --git a/contrib/src/gnutls/rules.mak b/contrib/src/gnutls/rules.mak index ae2b07afd0..363562c89d 100644 --- a/contrib/src/gnutls/rules.mak +++ b/contrib/src/gnutls/rules.mak @@ -75,10 +75,6 @@ ifeq ($(ARCH),aarch64) endif endif -ifdef HAVE_NACL - GNUTLS_CONF += --disable-hardware-acceleration -endif - .gnutls: gnutls cd $< && $(GNUTLS_ENV) ./configure $(GNUTLS_CONF) cd $< && $(MAKE) -C gl install diff --git a/contrib/src/gpg-error/rules.mak b/contrib/src/gpg-error/rules.mak index a22c778632..0efda5449b 100644 --- a/contrib/src/gpg-error/rules.mak +++ b/contrib/src/gpg-error/rules.mak @@ -34,15 +34,6 @@ else cp $@/src/syscfg/lock-obj-pub.arm-unknown-linux-androideabi.h $@/src/syscfg/lock-obj-pub.linux-android.h endif endif -ifdef HAVE_NACL -ifeq ($(ARCH),i386) # 32bits intel - cp $@/src/syscfg/lock-obj-pub.i686-pc-linux-gnu.h $@/src/syscfg/lock-obj-pub.nacl.h -else -ifeq ($(ARCH),x86_64) - cp $@/src/syscfg/lock-obj-pub.x86_64-pc-linux-gnu.h $@/src/syscfg/lock-obj-pub.nacl.h -endif -endif -endif GPGERROR_CONF := $(HOSTCONF) \ --disable-nls \ diff --git a/contrib/src/mpg123/rules.mak b/contrib/src/mpg123/rules.mak index 7a9ce99c19..54f9891aa5 100644 --- a/contrib/src/mpg123/rules.mak +++ b/contrib/src/mpg123/rules.mak @@ -30,10 +30,6 @@ MPG123CONF += --with-cpu=generic_dither endif endif -ifdef HAVE_NACL -MPG123CONF += ac_cv_header_sys_select_h=no -endif - $(TARBALLS)/mpg123-$(MPG123_VERSION).tar.bz2: $(call download_pkg,$(MPG123_URL),mpg123) diff --git a/contrib/src/postproc/rules.mak b/contrib/src/postproc/rules.mak index 655acd5217..4ad433e8c4 100644 --- a/contrib/src/postproc/rules.mak +++ b/contrib/src/postproc/rules.mak @@ -103,10 +103,6 @@ ifdef HAVE_SOLARIS POSTPROCCONF += --enable-pic endif -ifdef HAVE_NACL -POSTPROCCONF += --target-os=linux -endif - # Build ifdef GPL diff --git a/include/vlc_fixups.h b/include/vlc_fixups.h index 9149c7519f..60dd6e9d27 100644 --- a/include/vlc_fixups.h +++ b/include/vlc_fixups.h @@ -33,7 +33,7 @@ /* C++11 says there's no need to define __STDC_*_MACROS when including * inttypes.h and stdint.h. */ -#if defined (__cplusplus) && (defined(__MINGW32__) || defined(__UCLIBC__) || defined(__native_client__)) +#if defined (__cplusplus) && (defined(__MINGW32__) || defined(__UCLIBC__)) # ifndef __STDC_FORMAT_MACROS # define __STDC_FORMAT_MACROS 1 # endif @@ -121,15 +121,6 @@ extern "C" { # define VLC_NOTHROW #endif -/* signal.h */ -#if !defined(HAVE_SIGWAIT) && defined(__native_client__) -/* NaCl does not define sigwait in signal.h. We need to include it here to - * define sigwait, because sigset_t is allowed to be either an integral or a - * struct. */ -#include -int sigwait(const sigset_t *set, int *sig); -#endif - /* stddef.h */ #if !defined (__cplusplus) && !defined (HAVE_MAX_ALIGN_T) typedef struct { @@ -269,10 +260,6 @@ pid_t getpid (void) VLC_NOTHROW; int fsync (int fd); #endif -#ifndef HAVE_PATHCONF -long pathconf (const char *path, int name); -#endif - /* dirent.h */ #ifndef HAVE_DIRFD int (dirfd) (DIR *); @@ -324,10 +311,6 @@ void *aligned_alloc(size_t, size_t); #define aligned_free(ptr) free(ptr) #endif -#if defined(__native_client__) && defined(__cplusplus) -# define HAVE_USELOCALE -#endif - #if !defined(HAVE_NEWLOCALE) && defined(HAVE_CXX_LOCALE_T) && defined(__cplusplus) # include # define HAVE_NEWLOCALE @@ -393,11 +376,6 @@ int inet_pton(int, const char *, void *); const char *inet_ntop(int, const void *, char *, socklen_t); #endif -/* NaCl has a broken netinet/tcp.h, so TCP_NODELAY is not set */ -#if defined(__native_client__) && !defined( HAVE_NETINET_TCP_H ) -# define TCP_NODELAY 1 -#endif - #ifndef HAVE_STRUCT_POLLFD enum { diff --git a/m4/dolt.m4 b/m4/dolt.m4 index ff28bef516..9bd7db6097 100644 --- a/m4/dolt.m4 +++ b/m4/dolt.m4 @@ -21,7 +21,7 @@ AS_IF([test x$GCC != xyes], [dolt_supported=no]) AS_CASE([$host], [*-*-linux*|*-*-freebsd*], [pic_options='-fPIC'], [*-apple-darwin*], [pic_options='-fno-common'], - [*mingw*|*nacl*], [pic_options=''] + [*mingw*], [pic_options=''] [*], [dolt_supported=no] ) AS_IF([test x$dolt_supported = xno], [ diff --git a/src/Makefile.am b/src/Makefile.am index 49947dc6be..ae580acc68 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -431,17 +431,6 @@ libvlccore_la_SOURCES += \ os2/thread.c endif -if HAVE_NACL -libvlccore_la_SOURCES += \ - android/error.c \ - posix/dirs.c \ - posix/filesystem.c \ - posix/netconf.c \ - posix/rand.c \ - posix/specific.c \ - posix/timer.c -endif - if HAVE_DARWIN libvlccore_la_SOURCES += \ darwin/error.c \ @@ -475,7 +464,6 @@ endif if !HAVE_WIN32 if !HAVE_OS2 -if !HAVE_NACL libvlccore_la_SOURCES += \ posix/filesystem.c \ posix/plugin.c \ @@ -508,7 +496,6 @@ endif endif endif endif -endif if ENABLE_SOUT libvlccore_la_SOURCES += \ diff --git a/src/network/getaddrinfo.c b/src/network/getaddrinfo.c index 14496d5b09..c592b884cc 100644 --- a/src/network/getaddrinfo.c +++ b/src/network/getaddrinfo.c @@ -120,8 +120,7 @@ int vlc_getaddrinfo (const char *node, unsigned port, } #if defined (_WIN32) || defined (__OS2__) \ - || defined (__ANDROID__) || defined (__APPLE__) \ - || defined (__native_client__) + || defined (__ANDROID__) || defined (__APPLE__) #warning vlc_getaddrinfo_i11e() not implemented! int vlc_getaddrinfo_i11e(const char *node, unsigned port, const struct addrinfo *hints, struct addrinfo **res) -- GitLab From 431288d5d0cf83e91a3cb8a0f311c5a5a6dd77bb Mon Sep 17 00:00:00 2001 From: Mehdi Sabwat Date: Thu, 6 Jul 2017 14:50:28 +0200 Subject: [PATCH 02/16] wasm-emscripten: Create a target for emscripten in the configure.ac Co-Author: Etienne Brateau - add emscripten target for vlc configure - set toolchain variables for the contrib system + add meson_system_name for emscripten + add CMAKE_SYSTEM_NAME + add RANLIB to toolchain.cmake file --- configure.ac | 15 +++++++++++++++ contrib/bootstrap | 3 +++ contrib/src/main.mak | 18 ++++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/configure.ac b/configure.ac index d5bac76609..63e257cf97 100644 --- a/configure.ac +++ b/configure.ac @@ -371,6 +371,19 @@ case "${host_os}" in X86ASMFLAGS="-f aout" X86ASMDEFS="-DARCH_X86_32=1 -DARCH_X86_64=0 -DPREFIX" ;; + *emscripten*) + SYS=emscripten + CC=emcc + LD=emcc + LDSHARED=emcc + NM=llvm-nm + CPP=emcc + CXX=em++ + AR=emar + RANLIB=emranlib + CFLAGS="${CFLAGS} -pthread" + CXXFLAGS="${CXXFLAGS} -pthread" + ;; *) SYS="${host_os}" ;; @@ -443,6 +456,8 @@ AS_IF([test x$with_pic = xyes], [X86ASMDEFS="${X86ASMDEFS} -DPIC"]) AC_SUBST([X86ASMFLAGS]) AC_SUBST([X86ASMDEFS]) +AM_CONDITIONAL([HAVE_EMSCRIPTEN], [test "${SYS}" = "emscripten"]) + dnl dnl Sadly autoconf does not think about testing foo.exe when ask to test dnl for program foo on win32 diff --git a/contrib/bootstrap b/contrib/bootstrap index 72ca130520..9fcd7e7001 100755 --- a/contrib/bootstrap +++ b/contrib/bootstrap @@ -355,6 +355,9 @@ case "${OS}" in *solaris*) add_make_enabled "HAVE_SOLARIS" ;; + *emscripten*) + add_make_enabled "HAVE_EMSCRIPTEN" + ;; esac # diff --git a/contrib/src/main.mak b/contrib/src/main.mak index fb71479d68..c134611bc0 100644 --- a/contrib/src/main.mak +++ b/contrib/src/main.mak @@ -129,6 +129,16 @@ EXTRA_CFLAGS += -fno-stack-check XCODE_FLAGS += OTHER_CFLAGS=-fno-stack-check endif +ifdef HAVE_EMSCRIPTEN +CC := emcc +CXX := em++ +LD := emcc +AR := emar +RANLIB := emranlib +CFLAGS="-pthread" +CXXFLAGS="-pthread" +endif + ifdef HAVE_MACOSX EXTRA_CXXFLAGS += -stdlib=libc++ ifeq ($(ARCH),aarch64) @@ -564,6 +574,9 @@ endif ifdef HAVE_DARWIN_OS CMAKE_SYSTEM_NAME = Darwin endif +ifdef HAVE_EMSCRIPTEN +CMAKE_SYSTEM_NAME = Emscripten +endif ifdef HAVE_ANDROID CFLAGS += -DANDROID_NATIVE_API_LEVEL=$(ANDROID_API) @@ -608,6 +621,7 @@ endif endif echo "set(CMAKE_C_COMPILER $(CC))" >> $@ echo "set(CMAKE_CXX_COMPILER $(CXX))" >> $@ + echo "set(CMAKE_RANLIB $(RANLIB))" >> $@ ifdef MSYS_BUILD echo "set(CMAKE_FIND_ROOT_PATH `cygpath -m $(PREFIX)`)" >> $@ else @@ -632,12 +646,16 @@ else ifdef HAVE_LINUX # android has also system = linux and defines HAVE_LINUX MESON_SYSTEM_NAME = linux +else +ifdef HAVE_EMSCRIPTEN + MESON_SYSTEM_NAME = emscripten else $(error "No meson system name known for this target") endif endif endif endif +endif crossfile.meson: $(SRC)/gen-meson-crossfile.py $(HOSTVARS_MESON) \ -- GitLab From 8a02db8742d539589e1f46424ae4887c3a4508d7 Mon Sep 17 00:00:00 2001 From: Mehdi Sabwat Date: Wed, 20 May 2020 01:31:35 +0000 Subject: [PATCH 03/16] compat: add clock_nanosleep & sigwait support for emscripten clock_nanosleep() is not supported in emscripten Implementation from : https://code.woboq.org/userspace/glibc/sysdeps/unix/clock_nanosleep.c.html --- compat/clock_nanosleep.c | 9 ++++++--- configure.ac | 2 ++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/compat/clock_nanosleep.c b/compat/clock_nanosleep.c index 494540b8b9..0adc4f9020 100644 --- a/compat/clock_nanosleep.c +++ b/compat/clock_nanosleep.c @@ -20,7 +20,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ -#ifdef __APPLE__ +#if defined(__APPLE__) || defined (__EMSCRIPTEN__) #ifdef HAVE_CONFIG_H # include @@ -32,8 +32,12 @@ #include #include #include -#include +#ifdef __EMSCRIPTEN__ +# define NSEC_PER_SEC 1000000000L +#else +# include +#endif int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *rqtp, struct timespec *rmtp) { @@ -92,5 +96,4 @@ int clock_nanosleep(clockid_t clock_id, int flags, return -1; } } - #endif diff --git a/configure.ac b/configure.ac index 63e257cf97..ae53ea8e16 100644 --- a/configure.ac +++ b/configure.ac @@ -373,6 +373,8 @@ case "${host_os}" in ;; *emscripten*) SYS=emscripten + AC_LIBOBJ([clock_nanosleep]) + AC_LIBOBJ([sigwait]) CC=emcc LD=emcc LDSHARED=emcc -- GitLab From 5fca1f51c8112fbce1b1ccd774f73d456505c3a1 Mon Sep 17 00:00:00 2001 From: Mehdi Sabwat Date: Tue, 27 Apr 2021 15:33:10 +0200 Subject: [PATCH 04/16] core: initial core build for emscripten, based on POSIX posix/sort.c won't be added because qsort_r is not supported. - add vlc_getProxyUrl stub for emscripten - implement vlc_thread_id() for emscripten - add weak attribute support for wasm fixes a mismatch in the prototype of sout_StreamChainNew, and adds a stub for sout_instance_ControlsPace to allow linking without error. --- include/vlc_common.h | 2 +- src/Makefile.am | 17 ++++++++++++++++- src/emscripten/netconf.c | 19 +++++++++++++++++++ src/emscripten/thread.c | 10 ++++++++++ 4 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 src/emscripten/netconf.c create mode 100644 src/emscripten/thread.c diff --git a/include/vlc_common.h b/include/vlc_common.h index f62ff86d04..3f64caa455 100644 --- a/include/vlc_common.h +++ b/include/vlc_common.h @@ -185,7 +185,7 @@ # define VLC_USED #endif -#if defined (__ELF__) || defined (__MACH__) +#if defined (__ELF__) || defined (__MACH__) || defined (__wasm__) # define VLC_WEAK __attribute__((weak)) #else /** diff --git a/src/Makefile.am b/src/Makefile.am index ae580acc68..5a68efae25 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -431,6 +431,19 @@ libvlccore_la_SOURCES += \ os2/thread.c endif +if HAVE_EMSCRIPTEN +libvlccore_la_SOURCES += \ + posix/thread.c \ + posix/getaddrinfo.c \ + posix/error.c \ + posix/dirs.c \ + posix/filesystem.c \ + posix/specific.c \ + posix/timer.c \ + emscripten/netconf.c \ + emscripten/thread.c +endif + if HAVE_DARWIN libvlccore_la_SOURCES += \ darwin/error.c \ @@ -473,8 +486,10 @@ if !HAVE_LINUX libvlccore_la_SOURCES += posix/wait.c endif if !HAVE_ANDROID +if !HAVE_EMSCRIPTEN +libvlccore_la_SOURCES += posix/sort.c +endif libvlccore_la_SOURCES += \ - posix/sort.c \ posix/thread.c if !HAVE_DARWIN libvlccore_la_SOURCES += \ diff --git a/src/emscripten/netconf.c b/src/emscripten/netconf.c new file mode 100644 index 0000000000..4d29b4cb4c --- /dev/null +++ b/src/emscripten/netconf.c @@ -0,0 +1,19 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include + +char *vlc_getProxyUrl(const char *url); + +/** + * Determines the network proxy server to use (if any). + * @param url absolute URL for which to get the proxy server + * @return proxy URL, NULL if no proxy or error + */ +char *vlc_getProxyUrl(const char *url) +{ + VLC_UNUSED(url); + // TODO: add proxy url to url + return NULL; +} diff --git a/src/emscripten/thread.c b/src/emscripten/thread.c new file mode 100644 index 0000000000..b0dc6e9d96 --- /dev/null +++ b/src/emscripten/thread.c @@ -0,0 +1,10 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +unsigned long vlc_thread_id(void) +{ + return (unsigned long)pthread_self(); +} -- GitLab From af6ea8953d4ae6410d0229e966c1d336b7c820c1 Mon Sep 17 00:00:00 2001 From: Mehdi Sabwat Date: Tue, 27 Apr 2021 15:34:23 +0200 Subject: [PATCH 05/16] configure: disable deprecated GL functions for emscripten The build system assumes OpenGL functions are implemented if the headers are defined. Which is wrong, so we need to disable the HAVE_GL marker. we use AM_LINK_IFELSE() because AC_COMPILE will add the "-c" option, and thus in wasm-emscripten this function will appear supported even if it is not. --- configure.ac | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index ae53ea8e16..621b268724 100644 --- a/configure.ac +++ b/configure.ac @@ -3326,13 +3326,16 @@ PKG_CHECK_MODULES([GL], [gl], [ have_gl="yes" ], [ AC_MSG_CHECKING([for OpenGL]) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #ifdef _WIN32 # include #endif #include -]], [ - [int t0 = GL_TEXTURE0;]]) +]], [[ + int t0 = GL_TEXTURE0; + // glColorMaterial is unavailable in webgl, and emscripten + glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); + ]]) ], [ GL_CFLAGS="" have_gl="yes" -- GitLab From 25d44691bb949133fb1b75a670dad3f93adfec00 Mon Sep 17 00:00:00 2001 From: Mehdi Sabwat Date: Tue, 27 Apr 2021 15:35:12 +0200 Subject: [PATCH 06/16] missing: add stub for sout_instance_ControlsPace enable linking when --disable-sout is specified. --- src/missing.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/missing.c b/src/missing.c index 46baa65214..220f708482 100644 --- a/src/missing.c +++ b/src/missing.c @@ -165,6 +165,12 @@ noreturn sout_stream_t *sout_StreamChainNew(vlc_object_t *sout, vlc_assert_unreachable (); } +noreturn bool sout_instance_ControlsPace( sout_instance_t *sout ) +{ + (void) sout; + vlc_assert_unreachable (); +} + int vlc_sdp_Start (struct vlc_memstream *sdp, vlc_object_t *obj, const char *cfg, const struct sockaddr *src, size_t srclen, const struct sockaddr *addr, size_t addrlen) -- GitLab From dabeb4de249acf15e4175045b7dae91376114259 Mon Sep 17 00:00:00 2001 From: Mehdi Sabwat Date: Tue, 19 May 2020 13:24:42 +0000 Subject: [PATCH 07/16] contrib: add emscripten support for openjpeg --- contrib/src/openjpeg/emscripten.patch | 26 ++++++++++++++++++++++++++ contrib/src/openjpeg/rules.mak | 1 + 2 files changed, 27 insertions(+) create mode 100644 contrib/src/openjpeg/emscripten.patch diff --git a/contrib/src/openjpeg/emscripten.patch b/contrib/src/openjpeg/emscripten.patch new file mode 100644 index 0000000000..8150d8d49d --- /dev/null +++ b/contrib/src/openjpeg/emscripten.patch @@ -0,0 +1,26 @@ +From df73904929e9a7c3a48d63beb347fbf3c52b7300 Mon Sep 17 00:00:00 2001 +From: Mehdi Sabwat +Date: Mon, 26 Apr 2021 15:37:44 +0200 +Subject: [PATCH] emscripten: disable big endian test + +This test should not run on the emscripten platform because of : +https://github.com/emscripten-core/emscripten/blob/dff33368427fba16745c8ce52f11484a67b2855d/cmake/Modules/TestBigEndian.cmake#L5 +--- + CMakeLists.txt | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 136d72878..1e3adacda 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -162,8 +162,10 @@ endif() + + #----------------------------------------------------------------------------- + # Big endian test: ++if (!EMSCRIPTEN) + include (${CMAKE_ROOT}/Modules/TestBigEndian.cmake) + TEST_BIG_ENDIAN(OPJ_BIG_ENDIAN) ++endif() + + #----------------------------------------------------------------------------- + # Setup file for setting custom ctest vars diff --git a/contrib/src/openjpeg/rules.mak b/contrib/src/openjpeg/rules.mak index e485651354..42f299ce51 100644 --- a/contrib/src/openjpeg/rules.mak +++ b/contrib/src/openjpeg/rules.mak @@ -22,6 +22,7 @@ endif $(APPLY) $(SRC)/openjpeg/install.patch $(APPLY) $(SRC)/openjpeg/pic.patch $(APPLY) $(SRC)/openjpeg/openjp2_pthread.patch + $(APPLY) $(SRC)/openjpeg/emscripten.patch $(call pkg_static,"./src/lib/openjp2/libopenjp2.pc.cmake.in") $(MOVE) -- GitLab From e18e4aa6e104d0f7c51ff20fcbe06058807b76ee Mon Sep 17 00:00:00 2001 From: Mehdi Sabwat Date: Wed, 4 Sep 2019 19:35:17 +0200 Subject: [PATCH 08/16] contrib: add ffmpeg configuration options for wasm-emscripten We need to specify the pthread flag for compilation and linking, otherwise tests will fail. --- ...001-configure-add-emscripten-support.patch | 33 +++++++++++++++++++ contrib/src/ffmpeg/rules.mak | 6 ++++ 2 files changed, 39 insertions(+) create mode 100644 contrib/src/ffmpeg/0001-configure-add-emscripten-support.patch diff --git a/contrib/src/ffmpeg/0001-configure-add-emscripten-support.patch b/contrib/src/ffmpeg/0001-configure-add-emscripten-support.patch new file mode 100644 index 0000000000..cb8471c90e --- /dev/null +++ b/contrib/src/ffmpeg/0001-configure-add-emscripten-support.patch @@ -0,0 +1,33 @@ +From da7782c47f1f3d84eefb4ccce1c95e40d3b65fde Mon Sep 17 00:00:00 2001 +From: Mehdi Sabwat +Date: Tue, 13 Aug 2019 21:14:56 +0200 +Subject: [PATCH 1/1] configure: add emscripten support + +--- + configure | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/configure b/configure +index 7cea9d4d73..bafcbc87fc 100755 +--- a/configure ++++ b/configure +@@ -4239,6 +4239,7 @@ fi + exesuf() { + case $1 in + mingw32*|mingw64*|win32|win64|cygwin*|*-dos|freedos|opendos|os/2*|symbian) echo .exe ;; ++ emscripten) echo .js ;; + esac + } + +@@ -5428,6 +5429,8 @@ case $target_os in + ;; + minix) + ;; ++ emscripten) ++ ;; + none) + ;; + *) +-- +2.23.0 + diff --git a/contrib/src/ffmpeg/rules.mak b/contrib/src/ffmpeg/rules.mak index aa445154d6..ca8587e80f 100644 --- a/contrib/src/ffmpeg/rules.mak +++ b/contrib/src/ffmpeg/rules.mak @@ -209,6 +209,11 @@ endif FFMPEGCONF += --target-os=sunos --enable-pic endif +ifdef HAVE_EMSCRIPTEN +FFMPEGCONF+=--target-os=emscripten --arch=wasm32 --ranlib=emranlib \ + --extra-ldflags="-pthread" --extra-ldexeflags="-pthread" +endif + # Build PKGS += ffmpeg ifeq ($(call need_pkg,"libavcodec >= $(FFMPEG_LAVC_MIN) libavformat >= 53.21.0 libswscale"),) @@ -239,6 +244,7 @@ endif ifdef USE_LIBAV $(APPLY) $(SRC)/ffmpeg/libav_gsm.patch endif + $(APPLY) $(SRC)/ffmpeg/0001-configure-add-emscripten-support.patch $(MOVE) .ffmpeg: ffmpeg -- GitLab From ac22f26c43b31f1b0dc35a536ab90b024f8853d5 Mon Sep 17 00:00:00 2001 From: Mehdi Sabwat Date: Fri, 16 Apr 2021 11:32:33 +0200 Subject: [PATCH 09/16] modules: disable libvlc_json and ytbdl vlc.js#17 The libjson library is not linkable with emsdk v2.0.17, this commit should be reverted when the ticket is resolved. --- modules/demux/Makefile.am | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/demux/Makefile.am b/modules/demux/Makefile.am index 48f5d7a97d..dbfe923650 100644 --- a/modules/demux/Makefile.am +++ b/modules/demux/Makefile.am @@ -529,9 +529,11 @@ libytdl_plugin_la_SOURCES = demux/ytdl.c libytdl_plugin_la_LIBADD = libvlc_json.la if !HAVE_WIN32 if !HAVE_ANDROID +if !HAVE_EMSCRIPTEN demux_LTLIBRARIES += libytdl_plugin.la endif endif +endif libnoseek_plugin_la_SOURCES = demux/filter/noseek.c demux_LTLIBRARIES += libnoseek_plugin.la @@ -549,4 +551,6 @@ libvlc_json_la_SOURCES = \ libvlc_json_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/demux/json libvlc_json_la_LIBADD = $(LTLIBVLCCORE) ../compat/libcompat.la $(LIBM) libvlc_json_la_LDFLAGS = -static +if !HAVE_EMSCRIPTEN noinst_LTLIBRARIES += libvlc_json.la +endif -- GitLab From d54d427120d132fa214f207efbac68e8c2d10f6b Mon Sep 17 00:00:00 2001 From: Mehdi Sabwat Date: Mon, 9 Nov 2020 22:35:32 +0100 Subject: [PATCH 10/16] logger: add emscripten module --- modules/logger/Makefile.am | 6 +++ modules/logger/emscripten.c | 92 +++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 modules/logger/emscripten.c diff --git a/modules/logger/Makefile.am b/modules/logger/Makefile.am index 4addf6dcfd..87c675abaf 100644 --- a/modules/logger/Makefile.am +++ b/modules/logger/Makefile.am @@ -22,3 +22,9 @@ libandroid_logger_plugin_la_LIBADD = -llog if HAVE_ANDROID logger_LTLIBRARIES += libandroid_logger_plugin.la endif + +libemscripten_logger_plugin_la_SOURCES = logger/emscripten.c + +if HAVE_EMSCRIPTEN +logger_LTLIBRARIES += libemscripten_logger_plugin.la +endif diff --git a/modules/logger/emscripten.c b/modules/logger/emscripten.c new file mode 100644 index 0000000000..8949339aa6 --- /dev/null +++ b/modules/logger/emscripten.c @@ -0,0 +1,92 @@ +/***************************************************************************** + * emscripten.c: Emscripten logger + ***************************************************************************** + * Copyright © 2019 VLC authors and VideoLAN + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include +#include + +#include +#include + +static void EmscriptenPrintMsg(void *opaque, int type, const vlc_log_t *p_item, + const char *format, va_list ap) +{ + int prio; + char *new_format; + char *message; + int verbose = (intptr_t)opaque; + + if (verbose < type) + return; + if (asprintf(&new_format, "[vlc.js: 0x%"PRIxPTR"/0x%"PRIxPTR"] %s %s: %s", + p_item->i_object_id, p_item->tid, p_item->psz_module, + p_item->psz_object_type, format) < 0) + return; + + switch (type) { + case VLC_MSG_ERR: + prio = EM_LOG_ERROR; + break; + case VLC_MSG_WARN: + prio = EM_LOG_WARN; + break; + default: + case VLC_MSG_DBG: + prio = EM_LOG_CONSOLE; + } + + if (vasprintf(&message, new_format, ap) < 0) + { + free(new_format); + return ; + } + free(new_format); + emscripten_log(prio, "%s", message); + free(message); +} + +static const struct vlc_logger_operations ops = { EmscriptenPrintMsg, NULL }; + +static const struct vlc_logger_operations *Open(vlc_object_t *obj, void **sysp) +{ + int verbosity = var_InheritInteger(obj, "verbose"); + + if (verbosity < 0) + return NULL; + + verbosity += VLC_MSG_ERR; + *sysp = (void *)(uintptr_t)verbosity; + + return &ops; +} + +vlc_module_begin() + set_shortname(N_("emlog")) + set_description(N_("Emscripten loggger")) + set_category(CAT_ADVANCED) + set_subcategory(SUBCAT_ADVANCED_MISC) + set_capability("logger", 30) + set_callbacks(Open, NULL) +vlc_module_end () -- GitLab From 2ef1e72bfb0ec6401cbf82ad9ea0d017245f17f6 Mon Sep 17 00:00:00 2001 From: Mehdi Sabwat Date: Tue, 27 Apr 2021 16:19:40 +0200 Subject: [PATCH 11/16] vout: add emscripten window and webgl context --- include/vlc_vout_window.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/vlc_vout_window.h b/include/vlc_vout_window.h index dd4e67a86e..769c3170d1 100644 --- a/include/vlc_vout_window.h +++ b/include/vlc_vout_window.h @@ -64,6 +64,7 @@ enum vout_window_type { VOUT_WINDOW_TYPE_ANDROID_NATIVE /**< Android native window */, VOUT_WINDOW_TYPE_WAYLAND /**< Wayland surface */, VOUT_WINDOW_TYPE_DCOMP /**< Win32 DirectComposition */, + VOUT_WINDOW_TYPE_EMSCRIPTEN_WEBGL /**< Emscripten surface */, }; /** @@ -378,6 +379,7 @@ typedef struct vout_window_t { void *anativewindow; /**< Android native window */ struct wl_surface *wl; /**< Wayland surface (client pointer) */ void *dcomp_visual; /**< Win32 direct composition visual */ + uint32_t em_context; /* Emscripten webgl context */ } handle; /** Display server (mandatory) -- GitLab From a10a30fab084a5ca1c7a08a77f8a26a4e5dd049e Mon Sep 17 00:00:00 2001 From: Mehdi Sabwat Date: Tue, 27 Apr 2021 16:27:19 +0200 Subject: [PATCH 12/16] opengl: set egl display Emscripten does not implement EGL extensions. https://emscripten.org/docs/porting/multimedia_and_graphics/EGL-Support-in-Emscripten.html#egl-extensions --- modules/video_output/opengl/egl_display_generic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/video_output/opengl/egl_display_generic.c b/modules/video_output/opengl/egl_display_generic.c index dfb841feef..730fb381d2 100644 --- a/modules/video_output/opengl/egl_display_generic.c +++ b/modules/video_output/opengl/egl_display_generic.c @@ -52,8 +52,8 @@ static vlc_egl_display_open_fn Open; static int Open(struct vlc_egl_display *display) { -#ifdef __ANDROID__ - /* The default display is refcounted on Android */ +#if defined(__ANDROID__) || defined(__EMSCRIPTEN__) + /* The default display is refcounted on Android and Emscripten */ display->display = eglGetDisplay(EGL_DEFAULT_DISPLAY); #elif defined(EGL_KHR_display_reference) const char *extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); -- GitLab From 02fdda583469e7c02304df7df57e85eb935edc82 Mon Sep 17 00:00:00 2001 From: Mehdi Sabwat Date: Tue, 27 Apr 2021 16:45:02 +0200 Subject: [PATCH 13/16] vout: add emscripten webgl module this module uses the OFFSCREEN_FRAMEBUFFER option which adds a backbuffer to the webgl context, that will be used for rendering. it works as a polyfill for offscreen canvas. --- modules/video_output/Makefile.am | 8 ++ modules/video_output/emscripten.c | 180 ++++++++++++++++++++++++++++++ 2 files changed, 188 insertions(+) create mode 100644 modules/video_output/emscripten.c diff --git a/modules/video_output/Makefile.am b/modules/video_output/Makefile.am index a290ece48d..a605427205 100644 --- a/modules/video_output/Makefile.am +++ b/modules/video_output/Makefile.am @@ -295,6 +295,14 @@ libcaca_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(voutdir)' EXTRA_LTLIBRARIES += libcaca_plugin.la vout_LTLIBRARIES += $(LTLIBcaca) +### Emscripten ### +libemscripten_window_plugin_la_SOURCES = video_output/emscripten.c +libemscripten_window_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(voutdir)' + +if HAVE_EMSCRIPTEN +vout_LTLIBRARIES += libemscripten_window_plugin.la +endif + ### Common ### libflaschen_plugin_la_SOURCES = video_output/flaschen.c diff --git a/modules/video_output/emscripten.c b/modules/video_output/emscripten.c new file mode 100644 index 0000000000..84e1fd97b0 --- /dev/null +++ b/modules/video_output/emscripten.c @@ -0,0 +1,180 @@ +/** + * @file emscripten.c + * @brief Emscripten webgl video output for VLC media player + */ +/***************************************************************************** + * Copyright © 2020 VLC authors and VideoLAN + * + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include +#include +#include +#include +#include + +#include "./opengl/vout_helper.h" + +#include +#include +#include +// eglGetProcAddress +#include + +extern emscripten_GetProcAddress(char *name); + +static const struct vout_window_operations ops = { + //TODO: Implement canvas operations + //vout_window_ReportSize() should be called from here +}; + +typedef struct gl_sys_t +{ + unsigned width; + unsigned height; + + EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context; +} gl_sys_t; + +static int OpenWindow(vout_window_t *wnd) +{ + wnd->type = VOUT_WINDOW_TYPE_EMSCRIPTEN_WEBGL; + wnd->ops = &ops; + + return VLC_SUCCESS; +} + +static void *GetProcAddress(vlc_gl_t *gl, const char *name) +{ + VLC_UNUSED(gl); + + return eglGetProcAddress(name); +} +static int MakeCurrent(vlc_gl_t *gl) +{ + gl_sys_t *sys = gl->sys; + + if (emscripten_webgl_make_context_current(sys->context) != EMSCRIPTEN_RESULT_SUCCESS) + return VLC_EGENERIC; + return VLC_SUCCESS; +} + +static void ReleaseCurrent(vlc_gl_t *gl) +{ + VLC_UNUSED(gl); + emscripten_webgl_make_context_current(0); +} + +static void Swap(vlc_gl_t *gl) +{ + VLC_UNUSED(gl); + emscripten_webgl_commit_frame(); +} + +static void Resize(vlc_gl_t *gl, unsigned w, unsigned h) +{ + VLC_UNUSED(gl); + VLC_UNUSED(w); + VLC_UNUSED(h); +} + +static void Close (vlc_gl_t *gl) +{ + free(gl->sys); +} + +static int Open (vlc_gl_t *gl, unsigned width, unsigned height) +{ + VLC_UNUSED(width), VLC_UNUSED(height); + + EmscriptenWebGLContextAttributes attr; + + emscripten_webgl_init_context_attributes(&attr); + attr.majorVersion=2; + attr.minorVersion=0; + attr.explicitSwapControl = 1; + + vout_window_t *wnd = gl->surface; + + if (wnd->type != VOUT_WINDOW_TYPE_EMSCRIPTEN_WEBGL) + goto error; + + gl_sys_t *sys; + + gl->sys = sys = calloc(1, sizeof(*sys)); + if (!sys) + return VLC_ENOMEM; + + sys->context = emscripten_webgl_create_context("#canvas", &attr); + if (!sys->context) + { + msg_Err(gl, "Failed to make context current"); + goto error; + } + + // Check that the WebGL context is valid + if (emscripten_webgl_make_context_current(sys->context) != EMSCRIPTEN_RESULT_SUCCESS) + { + emscripten_log(EM_LOG_CONSOLE, "failed to make context current"); + goto error; + } + + // Release the context + emscripten_webgl_make_context_current(0); + wnd->handle.em_context = sys->context; + + // Implement egl routines: + gl->make_current = MakeCurrent; + gl->release_current = ReleaseCurrent; + gl->resize = Resize; + gl->swap = Swap; + gl->get_proc_address = GetProcAddress; + gl->destroy = Close; + + return VLC_SUCCESS; +error: + Close(gl); + return VLC_EGENERIC; +} + +/* + * Module descriptor + */ +vlc_module_begin() + set_shortname(N_("Emscripten Window")) + set_description(N_("Emscripten drawing area")) + set_category(CAT_VIDEO) + set_subcategory(SUBCAT_VIDEO_VOUT) + set_capability("vout window", 10) + set_callbacks(OpenWindow, NULL) + + add_submodule () + set_shortname("Emscripten GL") + set_description(N_("Emscripten extension for OpenGL")) + set_category(CAT_VIDEO) + set_subcategory(SUBCAT_VIDEO_VOUT) + set_capability("opengl es2", 50) + set_callback(Open) + add_shortcut("em_webgl") +vlc_module_end() + -- GitLab From d701d69bc4b1a8ffcbb6ebc8c5401addf73a87ca Mon Sep 17 00:00:00 2001 From: Mehdi Sabwat Date: Tue, 29 Aug 2017 13:30:51 +0200 Subject: [PATCH 14/16] aout: add emscripten audio worklet module --- modules/audio_output/Makefile.am | 5 + modules/audio_output/emscripten.cpp | 419 ++++++++++++++++++++++++++++ 2 files changed, 424 insertions(+) create mode 100644 modules/audio_output/emscripten.cpp diff --git a/modules/audio_output/Makefile.am b/modules/audio_output/Makefile.am index 194c421e54..7c87faaea8 100644 --- a/modules/audio_output/Makefile.am +++ b/modules/audio_output/Makefile.am @@ -117,3 +117,8 @@ endif if HAVE_TVOS aout_LTLIBRARIES += libaudiounit_ios_plugin.la endif + +libemworklet_audio_plugin_la_SOURCES = audio_output/emscripten.cpp +if HAVE_EMSCRIPTEN +aout_LTLIBRARIES += libemworklet_audio_plugin.la +endif diff --git a/modules/audio_output/emscripten.cpp b/modules/audio_output/emscripten.cpp new file mode 100644 index 0000000000..8be6c9d54d --- /dev/null +++ b/modules/audio_output/emscripten.cpp @@ -0,0 +1,419 @@ +/***************************************************************************** + * emscripten.c: audio output module using audio worklets + ***************************************************************************** + * Copyright © 2020 VLC authors and VideoLAN + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +/***************************************************************************** + * Preamble + *****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +/***************************************************************************** + * Module descriptor + *****************************************************************************/ +#define STORAGE_SIZE 1024 * 1024 +// Sample rate might change, and it would be good to be able to change it during playback. +#define AUDIO_WORKLET_SAMPLE_RATE 44100 +// Don't know any way to get the browser's supported number of channels. +#define AUDIO_WORKLET_NB_CHANNELS 2 + +using namespace emscripten; +namespace { + EM_BOOL requestAnimationFrame_cb( double time, void *userData ); + + class AWNodeWrapper { + public: + val context = val::undefined(); + val getCtx() const { return context; }; + void setCtx(val v_context) { context = v_context; }; + + uintptr_t sab_ptr; + uintptr_t getSabPtr() const { return sab_ptr; }; + void setSabPtr(uintptr_t p_sab) { sab_ptr = p_sab; }; + + size_t sab_size; + size_t getSabSize() const { return sab_size; }; + void setSabSize(size_t s_size) { sab_size = s_size; }; + + int8_t channels; + int8_t getChannels() const { return channels; }; + void setChannels(int8_t chan) { channels = chan; }; + + AWNodeWrapper(int sample_rate) { + // Prepare audio context options + val audio_ctx_options = val::object(); + audio_ctx_options.set("sampleRate", sample_rate); + + context = val::global("AudioContext").new_(audio_ctx_options); + context.call("suspend"); + } + + val operator()( val undefined_promise_argument ) { + (val)undefined_promise_argument; + + // Prepare AWN Options + val awn_options = val::object(); + val awn_opt_outputChannelCount = val::array(); + awn_opt_outputChannelCount.call("push", channels); + awn_options.set("outputChannelCount", awn_opt_outputChannelCount); + awn_options.set("numberOfInputs", 0); + awn_options.set("numberOfOutputs", 1); + + val AudioNode = val::global("AudioWorkletNode").new_(context, std::string("worklet-processor"), awn_options); + AudioNode.set("channelCount", channels); + + //Prepare postMessage message + val msg = val::object(); + msg.set("type", std::string("recv-audio-queue")); + msg.set("data", val::module_property("wasmMemory")["buffer"]); + msg.set("sab_ptr", sab_ptr); + msg.set("sab_size", sab_size); + + AudioNode["port"].call("postMessage", msg); + AudioNode.call("connect", context["destination"]); + + emscripten_request_animation_frame_loop(requestAnimationFrame_cb, this); + + return val::undefined(); + } + }; + + EMSCRIPTEN_BINDINGS(AWWSCOPE) { + class_("awn_cb_wrapper") + .constructor() + .property("context", &AWNodeWrapper::getCtx, &AWNodeWrapper::setCtx) + .property("sab_ptr", &AWNodeWrapper::getSabPtr, &AWNodeWrapper::setSabPtr) + .property("sab_size", &AWNodeWrapper::getSabSize, &AWNodeWrapper::setSabSize) + .property("channels", &AWNodeWrapper::getChannels, &AWNodeWrapper::setChannels) + .function("awn_call", &AWNodeWrapper::operator()); + }; + + typedef struct aout_sys_t + { + int8_t *sab; + size_t sab_size; + AWNodeWrapper *awn_inst; + float volume; + + } aout_sys_t; + + EM_BOOL requestAnimationFrame_cb( double time, void *userData ) { + (double) time; + AWNodeWrapper *inst = reinterpret_cast(userData); + uint32_t *sab = reinterpret_cast(inst->getSabPtr()); + val view = val(typed_memory_view(inst->getSabSize(), sab)); + val context = inst->getCtx(); + if ( view[0].as() == 1 ) { + context.call("resume"); + sab[0] = 0; + return EM_FALSE; + } + return EM_TRUE; + } + + // For Atomics.store() and .load() only integer types are supported + unsigned int js_index_load(int8_t *sab_ptr, int8_t index, size_t sab_size){ + uint32_t *buffer_view = reinterpret_cast(sab_ptr); + val buffer = val(typed_memory_view(sab_size, buffer_view)); + + return val::global("Atomics").call("load", buffer, index); + } + + void js_index_store(int8_t *sab_ptr, int8_t index, unsigned int value, size_t sab_size) { + uint32_t *buffer_view = reinterpret_cast(sab_ptr); + val buffer = val(typed_memory_view(sab_size, buffer_view)); + + return val::global("Atomics").call("store", buffer, index, value); + } + + // careful when calling this, you cannot wait on any index + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics/wait + unsigned int js_index_wait(int8_t *sab_ptr, int8_t index, size_t sab_size) { + int32_t *buffer_view = reinterpret_cast(sab_ptr); + val buffer = val(typed_memory_view(sab_size, buffer_view)); + + return val::global("Atomics").call("wait", buffer, index); + } + + void Flush( audio_output_t *aout ) + { + aout_sys_t * sys = reinterpret_cast(aout->sys); + bzero(sys->sab, sys->sab_size); + } + + int Start( audio_output_t *aout, audio_sample_format_t *restrict fmt ) + { + aout_sys_t *sys = reinterpret_cast(aout->sys); + unsigned nbChannels = aout_FormatNbChannels(fmt); + + if (( nbChannels == 0 ) || !AOUT_FMT_LINEAR(fmt)) + return VLC_EGENERIC; + fmt->i_format = VLC_CODEC_FL32; + fmt->i_channels = AUDIO_WORKLET_NB_CHANNELS; + fmt->i_rate = AUDIO_WORKLET_SAMPLE_RATE; + + // resume audio context (first start, it is paused when initialized) + js_index_store(sys->sab, 4, (int)sys->volume * 100, sys->sab_size); + js_index_store(sys->sab, 0, 1, sys->sab_size); + + return VLC_SUCCESS; + } + + void Stop (audio_output_t *aout) + { + Flush(aout); + } + + int audio_worklet_push(audio_output_t *aout, const int8_t *data, unsigned data_size) { + aout_sys_t *sys = reinterpret_cast(aout->sys); + int8_t *sab_view = sys->sab + 5 * sizeof(int32_t); + unsigned head = js_index_load(sys->sab, 1, sys->sab_size); + + // TODO: check that we do not write on unconsumed data. + if (head + data_size > STORAGE_SIZE) { + // Copy the part of the data at the buffer end + unsigned data_size_copy_end = STORAGE_SIZE - head; + memcpy(sab_view + head, data, data_size_copy_end); + head = 0; + + // Copy the part of the data at the buffer start + unsigned data_size_copy_start = data_size - data_size_copy_end; + memcpy(sab_view + head, data, data_size_copy_start); + head = data_size_copy_start; + } + else { + memcpy(sab_view + head, data, data_size); + head += data_size; + } + js_index_store(sys->sab, 1, head, sys->sab_size); + return 0; // return success to indicate successful push. + } + + void Play( audio_output_t *aout, block_t *block, vlc_tick_t date) + { + VLC_UNUSED(date); + aout_sys_t *sys = reinterpret_cast(aout->sys); + const int8_t* data = (int8_t *)block->p_buffer; + size_t data_size = block->i_buffer; + + unsigned head = js_index_load(sys->sab, 1, sys->sab_size); + unsigned tail = js_index_load(sys->sab, 2, sys->sab_size); + unsigned new_head = (head + data_size) % STORAGE_SIZE; + if (new_head > tail) + { + // the worklet processor keeps rendering until tail matches head + // it will be notified by an Atomics.notify() from the process() callback + js_index_wait(sys->sab, 3, sys->sab_size); + } + audio_worklet_push(aout, data, data_size); + block_Release(block); + } + + void Pause( audio_output_t *aout, bool paused, vlc_tick_t date ) + { + aout_sys_t * sys = reinterpret_cast(aout->sys); + if (paused == false) { + js_index_store(sys->sab, 0, 0, sys->sab_size); + } + else { + js_index_store(sys->sab, 0, 1, sys->sab_size); + } + VLC_UNUSED(date); + Flush(aout); + } + + int Time_Get( audio_output_t *aout, vlc_tick_t *delay) + { + return aout_TimeGetDefault(aout, delay); + } + + /***************************************************************************** + * CloseAudio: close the audio device + *****************************************************************************/ + void Close( vlc_object_t *obj ) + { + audio_output_t *aout = (audio_output_t *)obj; + struct aout_sys_t *sys = reinterpret_cast(aout->sys); + + delete sys->awn_inst; + free(sys->sab); + free(sys); + } + + int Volume_Set( audio_output_t *aout, float volume) + { + struct aout_sys_t *sys = reinterpret_cast(aout->sys); + + if (volume > 1.0f) + volume = 1.0f; + else if (volume < 0.0f) + volume = 0.0f; + // TODO: implement gain + sys->volume = volume; + js_index_store(sys->sab, 4, (int)volume * 100, sys->sab_size); + aout_VolumeReport(aout, volume); + + return 0; + } + + int Mute_Set( audio_output_t *aout, bool mute) + { + struct aout_sys_t *sys = reinterpret_cast(aout->sys); + + if (mute == 0) + js_index_store(sys->sab, 4, 0, sys->sab_size); + else + js_index_store(sys->sab, 4, (int)sys->volume * 100, sys->sab_size); + aout_MuteReport(aout, mute); + return 0; + } + + + /***************************************************************************** + * Open: open the audio device + ***************************************************************************** + *****************************************************************************/ + int Open( vlc_object_t *obj ) + { + audio_output_t * aout = (audio_output_t *) obj; + + /* Allocate structures */ + aout_sys_t *sys = reinterpret_cast(malloc( sizeof( *sys ) )); + if( unlikely(sys == NULL) ) + return VLC_ENOMEM; + + aout->sys = sys; + aout->start = Start; + aout->stop = Stop; + aout->play = Play; + aout->pause = Pause; + aout->flush = Flush; + aout->time_get = Time_Get; + aout->volume_set = Volume_Set; + aout->mute_set = Mute_Set; + + sys->awn_inst = new AWNodeWrapper(AUDIO_WORKLET_SAMPLE_RATE); + sys->sab_size = 5 * sizeof(int32_t) + STORAGE_SIZE; + sys->sab = reinterpret_cast(malloc( sys->sab_size )); + sys->volume = 1.0f; + + if ( unlikely(sys->sab == NULL) ) + return VLC_ENOMEM; + bzero(sys->sab, sys->sab_size); + + val webaudio_context = sys->awn_inst->getCtx(); + + // Prepare audioWorkletProcessor blob + val document = val::global("document"); + val script = document.call("createElement", std::string("SCRIPT")); + script.set("type", std::string("worklet")); + std::string processorStr = "class Processor extends AudioWorkletProcessor { \ + constructor() { \ + super(); \ + this.port.onmessage = e => { \ + if (e.data.type === 'recv-audio-queue') { \ + this.buf = e.data.data; \ + this.capacity = e.data.sab_size / 4; \ + this.flag = new Uint32Array(this.buf, e.data.sab_ptr, 1); \ + this.head = new Uint32Array(this.buf, e.data.sab_ptr + 4, 1); \ + this.tail = new Uint32Array(this.buf, e.data.sab_ptr + 8, 1); \ + this.can_write = new Int32Array(this.buf, e.data.sab_ptr + 12, 1); \ + this.volume = new Int32Array(this.buf, e.data.sab_ptr + 16, 1); \ + this.storage = new Float32Array(this.buf, e.data.sab_ptr + 20, this.capacity); \ + } else { \ + throw 'unexpected.'; \ + } \ + }; \ + } \ + process(inputs, outputs, parameters) { \ + const output = outputs[0]; \ + const nbChannels = output.length; \ + const nbSamples = output[0].length; \ + if (this.head.buffer.byteLength == 0) { \ + throw new Error('wasmMemory grew'); \ + } \ + var head = Atomics.load(this.head, 0) / 4; \ + var tail = Atomics.load(this.tail, 0) / 4; \ + var i = 0; \ + var volume = (Atomics.load(this.volume, 0) / 4) / 100; \ + while (tail != head && i < nbSamples) \ + { \ + for (let c = 0; c < nbChannels; ++c) { \ + output[c][i] = this.storage[tail] * volume; \ + tail++; \ + if (tail == this.capacity) { \ + tail = 0; \ + } \ + } \ + i++; \ + } \ + Atomics.store(this.tail, 0, tail * 4); \ + Atomics.notify(this.can_write, 0); \ + return true; \ + } \ +} \ +registerProcessor('worklet-processor', Processor);"; + script.set("innerText", processorStr); + val ProcessorTextArray = val::array(); + ProcessorTextArray.call("push", script["innerText"]); + val BlobObject = val::object(); + BlobObject.set("type", std::string("application/javascript")); + val WorkletModuleUrl = val::global("URL").call("createObjectURL", val::global("Blob").new_(ProcessorTextArray, BlobObject)); + + // Prepare audioWorkletProcessor callback + val cb_caller = val::module_property("awn_cb_wrapper").new_(AUDIO_WORKLET_SAMPLE_RATE); + cb_caller.set("context", val(webaudio_context)); + cb_caller.set("sab_ptr", val(reinterpret_cast(sys->sab))); + cb_caller.set("sab_size", val(sys->sab_size)); + cb_caller.set("channels", val(AUDIO_WORKLET_NB_CHANNELS)); + val awn_caller = cb_caller["awn_call"]; + val awn_cb = awn_caller.call("bind", cb_caller); + + // start audio worklet (since the context is suspended, sound won't start now + // Since the WebAudio Context cannot be created in a worker, we create + // it in the main_thread and use the SAB to signal it when we want it to start + webaudio_context["audioWorklet"].call("addModule", WorkletModuleUrl).call("then", awn_cb); + + return VLC_SUCCESS; + } +} + +vlc_module_begin () + set_description( N_("Emscripten Worklet audio output") ) + set_shortname( "emworklet" ) + set_capability( "audio output", 100 ) + set_category( CAT_AUDIO ) + set_subcategory( SUBCAT_AUDIO_AOUT ) + set_callbacks( Open, Close ) +vlc_module_end () -- GitLab From 447f7273cf9c83965c90922fcc69b9cd8090449c Mon Sep 17 00:00:00 2001 From: Mehdi Sabwat Date: Thu, 29 Apr 2021 00:48:05 +0200 Subject: [PATCH 15/16] package: add wasm-emscriten build script --- extras/package/wasm-emscripten/build.sh | 214 ++++++++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100755 extras/package/wasm-emscripten/build.sh diff --git a/extras/package/wasm-emscripten/build.sh b/extras/package/wasm-emscripten/build.sh new file mode 100755 index 0000000000..9f598e4807 --- /dev/null +++ b/extras/package/wasm-emscripten/build.sh @@ -0,0 +1,214 @@ +#! /bin/bash +# Copyright (C) 2003-2021 the VideoLAN team +# +# This file is under the same license as the vlc package. + +diagnostic() +{ + echo "$@" 1>&2; +} + +checkfail() +{ + if [ ! $? -eq 0 ];then + diagnostic "$1" + exit 1 + fi +} + +usage() +{ + echo "Usage: $0 [--mode=(default=1)]" + echo " --mode=1 (default) build all in a new directory " +} + +get_symbol() +{ + echo "$1" | grep vlc_entry_$2 | cut -d " " -f 3 +} + +while test -n "$1" +do + case "$1" in + --help|-h) + usage + exit 0 + ;; + --mode=*) + BUILD_MODE="${1#--mode=}" + ;; + *) + echo "Unrecognized options $1" + usage + exit 1 + ;; + esac + shift +done + +BUILD_MODE=1 + +# Make in // +if [ -z "$MAKEFLAGS" ]; then + UNAMES=$(uname -s) + MAKEFLAGS= + if which nproc >/dev/null; then + MAKEFLAGS=-j`nproc` + elif [ "$UNAMES" == "Darwin" ] && which sysctl >/dev/null; then + MAKEFLAGS=-j`sysctl -n machdep.cpu.thread_count` + fi +fi + +diagnostic "setting up dir paths" + +if [ $(basename $PWD) = "vlc" ]; then #CI + VLC_SRCPATH="$PWD"; + BUILD_PATH="$PWD/extras/package/wasm-emscripten/build"; +elif [ $(basename $PWD) = "wasm-emscripten" ] && [ $(basename $(dirname $PWD)) = "package" ]; then #user + BUILD_PATH="$PWD/build"; + VLC_SRCPATH="$BUILD_PATH/../../../../"; +fi + +mkdir -p $BUILD_PATH + +echo $BUILD_PATH; +echo $VLC_SRCPATH; + +# VLC tools + +mkdir -p $BUILD_PATH/extras/tools +cd $BUILD_PATH/extras/tools +$VLC_SRCPATH/extras/tools/bootstrap +checkfail "vlc tools: bootstrap failed" +make -C $BUILD_PATH/extras/tools ${MAKEFLAGS} +checkfail "vlc tools: make failed" +cd $BUILD_PATH + +# update the PATH +export PATH=$BUILD_PATH/extras/tools/build/bin:$PATH + +# SDK tests + +# checking if config.sub recognizes wasm32-unknown-emscripten +pattern="automake-*" +dirs=( $pattern ) +/usr/share/${dirs[0]}/config.sub wasm32-unknown-emscripten +checkfail "sdk tests: automake does not support emscripten, patch was not applied \n + [https://code.videolan.org/-/snippets/1283]" + +# "checking if emscripten compiler is correctly setup" (for commands in this script) +emcc -v + +# these variables control the features that we want in the static build +CONTRIB_LIST=".ffmpeg .opus .vpx .ogg .dvbpsi .faad2 .dav1d" +# emmake make list to have a list of available contribs +VLC_CONFIGURE_OPTIONS=" + --host=wasm32-unknown-emscripten + --enable-debug + --disable-shared + --enable-dvbpsi + --enable-dav1d --enable-vpx + --enable-merge-ffmpeg --enable-avcodec --enable-avformat + --enable-opus --enable-faad + --enable-gles2 + --disable-xcb + --disable-sout --disable-lua --disable-vlm + --disable-archive --disable-live555 --disable-dc1394 --disable-dv1394 + --disable-linsys --disable-dvdread --disable-dvdnav --disable-bluray + --disable-opencv --disable-smbclient --disable-dsm + --disable-sftp --disable-nfs --disable-smb2 --disable-v4l2 --disable-nvdec --disable-decklink + --disable-vcd --disable-libcddb --disable-screen --disable-vnc + --disable-freerdp --disable-asdcp --disable-gme --disable-sid + --disable-ogg --disable-shout --disable-matroska --disable-mod --disable-mpc --disable-shine + --disable-omxil --disable-rpi-omxil --disable-mad --disable-mpg123 --disable-gst-decode --disable-libva + --disable-dxva2 --disable-d3d11va --disable-swscale --disable-postproc --disable-aom --disable-twolame + --disable-fdkaac --disable-a52 --disable-dca --disable-flac --disable-libmpeg2 --disable-vorbis --disable-tremor + --disable-speex --disable-spatialaudio --disable-theora --disable-oggspots --disable-daala --disable-schroedinger + --disable-png --disable-jpeg --disable-bpg --disable-x262 --disable-x265 --disable-x264 --disable-x26410b --disable-mfx + --disable-fluidsynth --disable-fluidlite --disable-zvbi --disable-telx --disable-aribsub --disable-aribb25 + --disable-kate --disable-tiger --disable-css --disable-libplacebo --disable-vulkan --disable-vdpau --disable-wayland + --disable-sdl-image --disable-freetype --disable-fribidi --disable-harfbuzz --disable-fontconfig --disable-libass --disable-svg + --disable-svgdec --disable-directx--disable-kms --disable-caca --disable-kva --disable-mmal --disable-alsa --disable-oss + --disable-sndio --disable-wasapi --disable-jack --disable-opensles --disable-samplerate --disable-soxr --disable-kai --disable-chromaprint + --disable-chromecast --disable-qt --disable-qt-qml-cache --disable-qt-qml-debug --disable-skins2 --disable-libtar --disable-sparkle + --disable-ncurses --disable-lirc --disable-srt --disable-goom --disable-projectm --disable-vsxu --disable-avahi + --disable-udev --disable-mtp --disable-upnp --disable-microdns --disable-libxml2 --disable-libgcrypt --disable-gnutls --disable-taglib + --disable-secret --disable-kwallet --disable-update-check --disable-notify --disable-medialibrary --disable-vlc --disable-addonmanagermodules + --disable-ssp +" + +# Build vlc contribs + +mkdir -p $BUILD_PATH/contrib-emscripten +cd $BUILD_PATH/contrib-emscripten +$VLC_SRCPATH/contrib/bootstrap --disable-disc --enable-gpl --disable-sout \ + --disable-network \ + --host=wasm32-unknown-emscripten +checkfail "vlc contribs: bootstrap failed" +emmake make ${CONTRIB_LIST} ${MAKEFLAGS} +checkfail "vlc contribs: make failed" + +cd $BUILD_PATH + +# Build libvlc + +BUILDDIR_NAME="build-emscripten" + +mkdir -p $BUILD_PATH/$BUILDDIR_NAME +cd $BUILD_PATH/$BUILDDIR_NAME +$VLC_SRCPATH/bootstrap +checkfail "vlc build: bootstrap failed" +emconfigure $VLC_SRCPATH/configure ${VLC_CONFIGURE_OPTIONS} \ + ac_cv_func_sendmsg=yes ac_cv_func_recvmsg=yes ac_cv_func_if_nameindex=yes ac_cv_header_search_h=no ac_cv_header_time_h=no ac_cv_header_sys_shm_h=no \ + --with-contrib=$BUILD_PATH/wasm32-unknown-emscripten +# Note : +# search.h is a blacklisted module +# time.h is a blacklisted module +# shm.h is a blacklisted module +checkfail "vlc build: configure failed" +emmake make ${MAKEFLAGS} +checkfail "vlc build: make failed" + +cd $BUILD_PATH + +# Build and compile static modules entry points +# start by deleting previous versions so that they are not overwritten +rm -fr $BUILDDIR_NAME/vlc-modules.c $BUILDDIR_NAME/vlc-modules.bc + +NM="$EMSDK/upstream/bin/llvm-nm" +cd $BUILDDIR_NAME/modules/.libs + +# create module list +echo "creating module list" +touch $BUILD_PATH/$BUILDDIR_NAME/vlc-modules.c +printf "// This file is autogenerated\n" > $BUILD_PATH/$BUILDDIR_NAME/vlc-modules.c +printf "#include \n\n" >> $BUILD_PATH/$BUILDDIR_NAME/vlc-modules.c + +BUILTINS="const void *vlc_static_modules[] = {\n" +LDFLAGS="" +DEFINITIONS="" +VLCMODULES="" + +for i in `ls *plugin.a` +do + VLCMODULES="$i $VLCMODULES" +done + +for file in $VLCMODULES + do + symbols=$($NM -g $file) + entryname=$(get_symbol "$symbols" _) + DEFINITIONS+="int $entryname (int (*)(void *, void *, int, ...), void *);\n"; + BUILTINS+=" $entryname,\n" + LDFLAGS+="\$BUILD_PATH/$BUILDDIR_NAME/modules/.libs/$file " + done; + +BUILTINS="$BUILTINS NULL\n};\n" +printf "$DEFINITIONS\n$BUILTINS" >> $BUILD_PATH/$BUILDDIR_NAME/vlc-modules.c + +# compile vlc-modules.c +emcc -pthread -c $BUILD_PATH/$BUILDDIR_NAME/vlc-modules.c -o $BUILD_PATH/$BUILDDIR_NAME/vlc-modules.bc +checkfail "vlc static modules: compilation failed" + +cd $BUILD_PATH +echo "VLC for wasm32-unknown-emscripten build!" -- GitLab From d52c0f63de70f1c1591a784bdf7766a15fef709a Mon Sep 17 00:00:00 2001 From: Mehdi Sabwat Date: Thu, 29 Apr 2021 00:48:33 +0200 Subject: [PATCH 16/16] ci : add wasm32-emscripten job --- extras/ci/gitlab-ci.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/extras/ci/gitlab-ci.yml b/extras/ci/gitlab-ci.yml index 9598ea27e0..bec994114f 100644 --- a/extras/ci/gitlab-ci.yml +++ b/extras/ci/gitlab-ci.yml @@ -20,6 +20,7 @@ variables: VLC_ANDROID_IMAGE: registry.videolan.org/vlc-debian-android:20200529135226 VLC_SNAP_IMAGE: registry.videolan.org/vlc-ubuntu-bionic:20190627090437 VLC_RASPBIAN_IMAGE: registry.videolan.org/vlc-debian-raspbian:20200213203125 + VLC_WASM_EMSCRIPTEN: registry.videolan.org/vlc-debian-wasm-emscripten:20201009174247 .variables-debian: &variables-debian HOST_ARCH: x86_64 @@ -102,6 +103,10 @@ variables: ANDROID_ARCH: x86_64 TRIPLET: x86_64-linux-android +.variables-emscripten-wasm32: &variables-emscripten-wasm32 + HOST_ARCH: wasm32 + TRIPLET: $HOST_ARCH-unknown-emscripten + # Common rules .base-template: stage: build @@ -423,6 +428,21 @@ android-x86_64: extends: .android-common variables: *variables-android-x86_64 +# +# Webassembly +# + +wasm32-emscripten-build : + extends: .base-template + tags: + - wasm32-emscripten-build + image: + name: $VLC_WASM_EMSCRIPTEN + script: + - source $EMSCRIPTEN_SDK/emsdk_env.sh + - ./extras/package/wasm-emscripten/build.sh + - tar -cvjSf contrib/vlc-contrib-alpha.tar.bz2 ./extras/package/wasm-emscripten/build/wasm32-unknown-emscripten + # # VLC Documentation # -- GitLab