Commit 5318241a authored by Mehdi Sabwat's avatar Mehdi Sabwat
Browse files

update demo and refactor

- add code for offscreen canvas and emscripten fs
- add the ability to change libvlc options before the main is executed
- patches are applied to 4deb73b6f62ce8fe8dea84ab0b0a138b79af4550
(passes the ci without breaking other platforms)
- prepare patches for vlc upstream
- change the build script to support libvlc "in tree" build
- add build archive to simplify deployment

wip patches will be removed in the MR and hopefully, the tested hash updated
parent ff12c4ef
# Ignore build dirs
vlc/
emsdk/
build/
# and files
experimental.data
experimental.html
experimental.js
experimental.wasm
experimental.worker.js
experimental.wasm.map
......@@ -3,9 +3,75 @@ var progressElement = document.getElementById('progress');
var spinnerElement = document.getElementById('spinner');
var Module = {
preRun: [],
postRun: [],
print: (function() {
noInitialRun: true,
preRun: [ function() {
// add libvlc options:
var flag = 0
args = document.getElementById("libvlc_opts").value.split(" ")
for (index in args) {
if ( args[index].includes("emscriptenfs") === false) {
document.getElementById("fileManager").style.display = "none";
document.getElementById("nativeFsFileManager").style.display = "none";
}
Module["arguments"].push(args[index]);
}
document.getElementById("libvlc_opts").addEventListener('change', function(event) {
args = document.getElementById("libvlc_opts").value.split(" ")
for (index in args) {
if ( args[index].includes("emscriptenfs") === false) {
document.getElementById("fileManager").style.display = "none";
document.getElementById("nativeFsFileManager").style.display = "none";
}
Module["arguments"].push(args[index]);
}
alert("libvlc set with options: " + Module["arguments"] + "please reload the page if you want to change them again.")
// noInitialRun is set, we call the main here:
if (flag == 0) {
callMain(Module["arguments"])
flag = 1;
}
});
document.getElementById("libvlc_init").addEventListener('click', function(event) {
// make sure main is not called again
if (flag == 0) {
callMain(Module["arguments"])
flag = 1;
}
});
if (window.chooseFileSystemEntries === undefined) {
document.getElementById("nativeFsFileManager").style.display = "none";
}
else {
document.getElementById("fileManager").style.display = "none";
}
document.getElementById("fileManager").addEventListener('change', function(event) {
Module["fileHandle"] = event.target.files[0];
console.log("file api : sent file handle all pthread workers");
}, false);
document.getElementById("nativeFsFileManager").addEventListener('click', async (e) => {
Module["fileHandle"] = await window.chooseFileSystemEntries();
console.log("native fs: sent file handle all pthread workers");
});
}],
postRun: [ function() {
// this should be set only if offscreen_canvas is activated
/* var bitmapcontext = document.getElementById("canvas").getContext("bitmaprenderer");
addEventListener('worker_message', function(msg) {
var bitmap = msg.detail;
bitmapcontext.transferFromImageBitmap(bitmap);
});
// This should run after the wasm module is instantiated
// before, the Pthread object won't be available
PThread.receiveObjectTransfer = function (data) {
let event = new CustomEvent('worker_message', {
detail: data.msg
});
window.dispatchEvent(event);
}
*/ }],
fileHandle: undefined,
print: (function() {
var element = document.getElementById('output');
if (element) element.value = ''; // clear browser cache
return function(text) {
......@@ -70,4 +136,4 @@ window.onerror = function(event) {
Module.setStatus = function(text) {
if (text) Module.printErr('[post-exception status] ' + text);
};
};
\ No newline at end of file
};
#! /bin/sh
set -e
## FUNCTIONS
#!/bin/bash
diagnostic()
{
......@@ -15,175 +12,121 @@ checkfail()
exit 1
fi
}
WORK_DIR=$PWD
# Download the portable SDK and uncompress it
apply_patch() {
diagnostic "Applying $1..."
git am -3 $1 || git am --skip
}
VLCJS_DIR=$(pwd)
PROJECT_DIR=$VLCJS_DIR/build
TESTED_HASH="4deb73b6f62ce8fe8dea84ab0b0a138b79af4550"
OFFSCREEN="OFFSCREEN_FRAMEBUFFER=1"
# download emscripten sdk
if [ ! -d emsdk ]; then
diagnostic "emsdk not found. Fetching it"
git clone http://github.com/emscripten-core/emsdk.git emsdk
cd emsdk && ./emsdk update-tags && ./emsdk install tot-upstream && ./emsdk activate tot-upstream
cd $VLCJS_DIR/emsdk && ./emsdk update-tags && ./emsdk install latest && ./emsdk activate latest
checkfail "emsdk: fetch failed"
diagnotsic "applying emsripten-fs patch"
cd upstream/emscripten && \
patch -p1 < $VLCJS_DIR/vlc_patches/emscripten-nativefs.patch
checkfail "could not apply emscripten-fs patch"
cd $VLCJS_DIR
diagnostic "successfully downloaded and patched toolchain"
fi
cd $WORK_DIR
TESTED_HASH="7bad2a86"
# Go go go vlc
. emsdk/emsdk_env.sh
# download vlc
if [ ! -d vlc ]; then
diagnostic "VLC source not found, cloning"
git clone http://git.videolan.org/git/vlc.git vlc || checkfail "VLC source: git clone failed"
cd vlc
diagnostic "VLC source: resetting to the TESTED_HASH commit (${TESTED_HASH})"
git reset --hard ${TESTED_HASH} || checkfail "VLC source: TESTED_HASH ${TESTED_HASH} not found"
cd ..
git clone http://git.videolan.org/git/vlc.git vlc
checkfail "vlc source: git clone failed"
fi
cd vlc
# 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
# VLC tools
export PATH=`pwd`/extras/tools/build/bin:$PATH
echo "Building tools"
cd extras/tools
./bootstrap
checkfail "buildsystem tools: bootstrap failed"
make $MAKEFLAGS
checkfail "buildsystem tools: make"
cd $WORK_DIR
diagnostic "Setting the environment"
source emsdk/emsdk_env.sh
export PKG_CONFIG_PATH=$EMSDK/emscripten/incoming/system/lib/pkgconfig
export PKG_CONFIG_LIBDIR=$PWD/vlc/contrib/wasm32_unknowm_emscripten/lib/pkgconfig
export PKG_CONFIG_PATH_CUSTOM=$PKG_CONFIG_LIBDIR
# Check that clang is working
clang --version
diagnostic "Patching"
cd vlc
# patching vlc
if [ -d ../vlc_patches ] && [ "$(ls -A ../vlc_patches)" ]; then
# core patches
git am -3 ../vlc_patches/0001-contrib-add-emscripten-target.patch
git am -3 ../vlc_patches/0002-contrib-add-ffmpeg-configuration-options-for-wasm-em.patch
git am -3 ../vlc_patches/0003-contrib-delete-empty-variable.patch
git am -3 ../vlc_patches/0006-configure-Create-a-target-for-emscripten-in-the-conf.patch
git am -3 ../vlc_patches/0007-core-initial-core-build-for-emscripten-based-on-POSI.patch
git am -3 ../vlc_patches/0008-compat-add-sigwait-support-for-emscripten.patch
git am -3 ../vlc_patches/0009-compat-add-clock_nanosleep-support.patch
git am -3 ../vlc_patches/0010-emscripten-add-vlc_getProxyUrl-stub.patch
git am -3 ../vlc_patches/0011-configure-disable-deprecated-GL-functions-for-emscri.patch
git am -3 ../vlc_patches/0012-logger-add-emscripten-module.patch
git am -3 ../vlc_patches/0013-window-add-emscripten-type.patch
git am -3 ../vlc_patches/0014-vout-add-emscripten-gl-es2-and-window-modules.patch
git am -3 ../vlc_patches/0015-vlc_common-add-weak-attribute-support-for-wasm.patch
git am -3 ../vlc_patches/0016-Add-meson_system_name-for-emscripten.patch
cd $VLCJS_DIR/vlc
# Add OPENAL support
git am -3 ../vlc_patches/openal/*
diagnostic "applying vlc patches"
git reset --hard ${TESTED_HASH}
checkfail "vlc.js: could not reset to ${TESTED_HASH}"
apply_patch $VLCJS_DIR/vlc_patches/0001-nacl-remove-deprecated-platform.patch
apply_patch $VLCJS_DIR/vlc_patches/0002-wasm-emscripten-Create-a-target-for-emscripten-in-th.patch
apply_patch $VLCJS_DIR/vlc_patches/0003-compat-add-clock_nanosleep-sigwait-support-for-emscr.patch
apply_patch $VLCJS_DIR/vlc_patches/0004-core-initial-core-build-for-emscripten-based-on-POSI.patch
apply_patch $VLCJS_DIR/vlc_patches/0005-contrib-add-emscripten-support-for-openjpeg.patch
apply_patch $VLCJS_DIR/vlc_patches/0006-contrib-add-ffmpeg-configuration-options-for-wasm-em.patch
apply_patch $VLCJS_DIR/vlc_patches/0007-demux-disable-ytdl-module.patch
apply_patch $VLCJS_DIR/vlc_patches/0008-logger-add-emscripten-module.patch
apply_patch $VLCJS_DIR/vlc_patches/0009-aout-add-an-openal-audio-module.patch
apply_patch $VLCJS_DIR/vlc_patches/0010-aout-add-audio-worklet-support.patch
apply_patch $VLCJS_DIR/vlc_patches/0011-vout-add-emscripten-gl-es2-module.patch
apply_patch $VLCJS_DIR/vlc_patches/0015-extras-add-wasm-emscripten-build-script.patch
#wip:
apply_patch $VLCJS_DIR/vlc_patches/0016-fixup-add-.bc-suffix-for-module-compilation.patch
apply_patch $VLCJS_DIR/vlc_patches/0017-fixup-temporarily-disable-dav1d.patch
checkfail "vlc.js: there was an issue while applying patches"
cd $VLCJS_DIR
fi
# BOOTSTRAP
# TODO: patches for emscriptenfs + offscreen_canvas
#apply_patch 0012-vout-add-offscreen-canvas-initial-support.patch
#apply_patch 0015-access-initial-emscripten-file-api-support.patch
if [ ! -f configure ]; then
echo "Bootstraping"
./bootstrap
checkfail "vlc: bootstrap failed"
fi
############
# Contribs #
############
echo "Building the contribs"
mkdir -p contrib/contrib-emscripten
cd contrib/contrib-emscripten
../bootstrap --disable-disc --disable-gpl --disable-sout \
--disable-network \
--host=wasm32-unknown-emscripten --build=x86_64-linux
checkfail "contribs: bootstrap failed"
emmake make list
emmake make $MAKEFLAGS fetch
checkfail "contribs: make fetch failed"
emmake make $MAKEFLAGS .ffmpeg
checkfail "contribs: make failed"
cd ../../
# Build
mkdir -p build-emscripten && cd build-emscripten
OPTIONS="
--host=wasm32-unknown-emscripten
--enable-debug
--enable-gles2
--disable-lua
--disable-ssp
--disable-nls
--disable-sout
--disable-vlm
--disable-addonmanagermodules
--enable-avcodec
--enable-merge-ffmpeg
--disable-swscale
--disable-a52
--disable-x264
--disable-xcb
--disable-alsa
--disable-macosx
--disable-sparkle
--disable-qt
--disable-screen
--disable-xcb
--disable-pulse
--disable-alsa
--disable-oss
--disable-vlc"
# --disable-xvideo Unknown option
# Note :
# search.h is a blacklisted module
# time.h is a blacklisted module
# shm.h is a blacklisted module
# ssp is not supported on the wasm backend
emconfigure ../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
emmake make ${MAKEFLAGS}
diagnostic "Generating module list"
cd ../..
./generate_modules_list.sh
cd vlc/build-emscripten
emcc vlc-modules.c -o vlc-modules.bc -pthread
cd ../..
#build libvlc
# TODO: add this in the script if the triplet is not supported
# cp ../config.sub vlc/autotools/config.sub
. $VLCJS_DIR/vlc/extras/package/wasm-emscripten/build.sh
cp -r $VLCJS_DIR/vlc/include $VLCJS_DIR/build/.
cd $VLCJS_DIR
url="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"
#download media
if [ ! -f BigBuckBunny.mp4 ]; then
diagnostic "Downloading mediafile..."
curl ${url} -o BigBuckBunny.mp4
cp BigBuckBunny.mp4 $VLCJS_DIR/build/build-emscripten/.
checkfail "failed to download mediafile!"
diagnostic "Success: mediafile downloaded"
fi
# copy Dolby_Canyon.vob
diagnostic "getting video"
cd vlc/build-emscripten/
curl ${url} -o BigBuckBunny.mp4
cd $WORK_DIR
diagnostic "Generating executable"
cp main.c vlc/build-emscripten/
./create_main.sh
# ci build procedure + cp vlc/include
diagnostic "vlc.js: build vlc.js"
cd $VLCJS_DIR/build/build-emscripten
# for release: add -Os
# for source maps to work, the preloaded file shouldn't be too heavy
# if not serving locally localhost:6931 should be changed
# if you can if you want to use the sanitizer add:
# -fsanitize=address -s ALLOW_MEMORY_GROWTH=1
emcc -s USE_PTHREADS=1 -s TOTAL_MEMORY=1GB \
-s MAX_WEBGL_VERSION=2 -s MIN_WEBGL_VERSION=2 \
-s ${OFFSCREEN} --profiling-funcs \
-s ASSERTIONS=2 -s SAFE_HEAP=1 -s STACK_OVERFLOW_CHECK=1 \
-g4 --source-map-base http://localhost:6931/ \
-I $PROJECT_DIR/include/ -I $PROJECT_DIR/wasm32-unknown-emscripten/include/ $VLCJS_DIR/main.c \
$PROJECT_DIR/build-emscripten/lib/.libs/libvlc.a \
$PROJECT_DIR/build-emscripten/vlc-modules.bc $PROJECT_DIR/build-emscripten/modules/.libs/*.a \
$PROJECT_DIR/wasm32-unknown-emscripten/lib/*.a \
$PROJECT_DIR/build-emscripten/src/.libs/libvlccore.a \
$PROJECT_DIR/build-emscripten/compat/.libs/libcompat.a \
-o $VLCJS_DIR/experimental.js --bind --emrun --preload-file $VLCJS_DIR/build/build-emscripten/BigBuckBunny.mp4
checkfail "could not compile vlc.js"
cd $VLCJS_DIR
diagnostic "successfully compiled vlc.js"
diagnostic "creating archives"
tar -cvjSf $VLCJS_DIR/vlc-contrib-alpha.tar.bz2 $VLCJS_DIR/build/wasm32-unknown-emscripten
checkfail "error: could not create contrib archive"
zip -r build.zip assets/* experimental.* vlc.html
checkfail "error: could not create build archive"
diagnostic "successfully created archives"
emrun --no_browser vlc.html
diagnostic "vlc.js: serving demo"
#!/bin/bash
set -e
## FUNCTIONS
diagnostic()
{
echo "$@" 1>&2;
}
checkfail()
{
if [ ! $? -eq 0 ];then
diagnostic "$1"
exit 1
fi
}
source emsdk/emsdk_env.sh
if [ ! -d vlc ]; then
diagnostic "vlc must exists. Execute compile.sh"
exit 1
fi
PROJECT_DIR=$(pwd)/vlc
cd vlc/build-emscripten
# for release, remove profiling-funcs and add -Os
emcc -s USE_PTHREADS=1 -s TOTAL_MEMORY=1GB \
-s OFFSCREEN_FRAMEBUFFER=1 --profiling-funcs \
-I $PROJECT_DIR/include/ -I $PROJECT_DIR/contrib/wasm32-unknown-emscripten/include/ main.c \
$PROJECT_DIR/build-emscripten/lib/.libs/libvlc.a \
vlc-modules.bc $PROJECT_DIR/build-emscripten/modules/.libs/*.a \
$PROJECT_DIR/contrib/wasm32-unknown-emscripten/lib/*.a \
$PROJECT_DIR/build-emscripten/src/.libs/libvlccore.a \
$PROJECT_DIR/build-emscripten/compat/.libs/libcompat.a \
-o ../../experimental.html --emrun --preload-file BigBuckBunny.mp4
#!/bin/bash
set -e
## FUNCTIONS
diagnostic()
{
echo "$@" 1>&2;
}
checkfail()
{
if [ ! $? -eq 0 ];then
diagnostic "$1"
exit 1
fi
}
get_symbol()
{
echo "$1" | grep vlc_entry_$2 | cut -d " " -f 3
}
source emsdk/emsdk_env.sh
if [ ! -d vlc ]; then
diagnostic "vlc must exists. Execute compile.sh"
exit 1
fi
cd vlc
PROJECT_DIR=$(pwd)
NM="$EMSDK/upstream/bin/llvm-nm"
cd build-emscripten/modules/.libs
# create module list
echo "creating module list"
touch $PROJECT_DIR/build-emscripten/vlc-modules.c
echo -e "// This file is autogenerated" > $PROJECT_DIR/build-emscripten/vlc-modules.c
echo -e "#include <unistd.h>\n\n" >> $PROJECT_DIR/build-emscripten/vlc-modules.c
BUILTINS="const void *vlc_static_modules[] = {\n"
LDFLAGS=""
DEFINITIONS=""
VLCMODULES=""
i=""
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+="\$PROJECT_DIR/build-emscripten/modules/.libs/$file "
done;
cd ../..
BUILTINS="$BUILTINS NULL\n};\n"
echo -e "$DEFINITIONS\n$BUILTINS" >> $PROJECT_DIR/build-emscripten/vlc-modules.c
......@@ -6,88 +6,98 @@
#include <emscripten.h>
#include <emscripten/html5.h>
libvlc_media_player_t *mp;
libvlc_instance_t *libvlc;
libvlc_time_t t = -1;
char flag = 1;
typedef struct ctrl_sys_t {
libvlc_time_t t;
char flag; // todo: make it an enum INIT/PAUSED/PLAYING
char init_flag;
char **vlc_options;
int opts_count;
} ctrl_sys_t;
static void iter()
{
if (libvlc_media_player_get_time(mp) == t) {
static void iter(void *userData) {
ctrl_sys_t* sys = (ctrl_sys_t *)userData;
/*
if (libvlc_media_player_get_time(sys->mp) == sys->t) {
// when enable, the js does not respond.
//libvlc_media_player_release( mp );
//libvlc_release( libvlc );
emscripten_cancel_main_loop();
}
t = libvlc_media_player_get_time(mp);
sys->t = libvlc_media_player_get_time(sys->mp);
*/
}
static EM_BOOL play_pause_handler(int eventType, const EmscriptenMouseEvent *e, void *userData)
{
(void) e;
(void) userData; // To use when mp won't be a global.
if (eventType == EMSCRIPTEN_EVENT_CLICK)
{
if (flag == 1)
{
libvlc_media_player_play(mp);
flag = 0;
}
// Don't do that until you implement a/v synchro.
// libvlc_media_player_pause(mp);
// flag = 1;
}
return 0;
}
static EM_BOOL play_pause_handler(int eventType, const EmscriptenMouseEvent *e, void *userData) {
(void) e;
ctrl_sys_t* sys = (ctrl_sys_t *)userData;
int main() {
if (eventType == EMSCRIPTEN_EVENT_CLICK) {
if ( sys->flag == 1 ) {
/* We don't want to the main thread stop even if the main function exit.
* If this thread stop, all proxyfied functions wont be called.
*/
EM_ASM(Module['noExitRuntime']=true);
emscripten_set_element_css_size("#canvas", 720, 540);
libvlc_media_t *m;
char const *vlc_argv[] = {
"-vvv",
"--no-spu",
"--no-osd",
"-Idummy",
"--ignore-config",
};
libvlc = libvlc_new( ARRAY_SIZE( vlc_argv ), vlc_argv );
if (libvlc == NULL)
{
fprintf( stderr, "unable to create libvlc instance" );
return -1;
}
m = libvlc_media_new_path( libvlc, "./BigBuckBunny.mp4" );
if (m == NULL)
{
fprintf(stderr, "unable to create media");
return -1;
sys->flag = 0;
}
}
mp = libvlc_media_player_new_from_media( m );
if (mp == NULL)
{
fprintf(stderr, "unable to create media player");
return -1;
return 0;
}
static EM_BOOL libvlc_init(int eventType, const EmscriptenMouseEvent *e, void *userData) {
(void) e;
libvlc_instance_t *libvlc;
libvlc_media_t *m;
libvlc_media_player_t *mp;
ctrl_sys_t* sys = (ctrl_sys_t *)userData;
if (eventType == EMSCRIPTEN_EVENT_CLICK) {
if (sys->init_flag == 1) {
const char *args[sys->opts_count];
int count = 0;
memcpy(args + count, sys->vlc_options + 1, (sys->opts_count - 1) * sizeof (*(sys->vlc_options)));
count += (sys->opts_count - 1);
args[count] = NULL;
libvlc = libvlc_new( count, args );
if (libvlc == NULL) {
fprintf( stderr, "unable to create libvlc instance" );
return -1;
}
m = libvlc_media_new_path( libvlc, args[count-1]);
if (m == NULL) {
fprintf(stderr, "unable to create media");
return -1;
}
mp = libvlc_media_player_new_from_media( m );
if (mp == NULL) {
fprintf(stderr, "unable to create media player");
return -1;
}
libvlc_media_release( m );
m = libvlc_media_player_get_media(mp);
libvlc_media_player_play(mp);
sys->init_flag = 0;
}
}
libvlc_media_release( m );
m = libvlc_media_player_get_media(mp);