diff --git a/.github/workflows/emscripten.yml b/.github/workflows/emscripten.yml index 7c7d3fb536..07131585b6 100644 --- a/.github/workflows/emscripten.yml +++ b/.github/workflows/emscripten.yml @@ -9,7 +9,7 @@ on: jobs: emscripten: env: - EMSCRIPTEN_VERSION: 1.37.26 + EMSCRIPTEN_VERSION: 3.1.43 runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v3 diff --git a/build-emscripten.sh b/build-emscripten.sh index 0992c02046..d94604b834 100755 --- a/build-emscripten.sh +++ b/build-emscripten.sh @@ -2,52 +2,116 @@ set -e DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -CORES=$(nproc --all) +CORES="${CORES:-`nproc --all`}" +ENABLE_LIBDE265="${ENABLE_LIBDE265:-1}" +LIBDE265_VERSION="${LIBDE265_VERSION:-1.0.12}" +ENABLE_AOM="${ENABLE_AOM:-0}" +AOM_VERSION="${AOM_VERSION:-3.6.1}" +STANDALONE="${STANDALONE:-0}" +DEBUG="${DEBUG:-0}" +USE_WASM="${USE_WASM:-1}" + echo "Build using ${CORES} CPU cores" -LIBDE265_VERSION=1.0.8 -[ -s "libde265-${LIBDE265_VERSION}.tar.gz" ] || curl \ - -L \ - -o libde265-${LIBDE265_VERSION}.tar.gz \ - https://github.com/strukturag/libde265/releases/download/v${LIBDE265_VERSION}/libde265-${LIBDE265_VERSION}.tar.gz -if [ ! -s "libde265-${LIBDE265_VERSION}/libde265/.libs/libde265.so" ]; then - tar xf libde265-${LIBDE265_VERSION}.tar.gz - cd libde265-${LIBDE265_VERSION} - [ -x configure ] || ./autogen.sh - emconfigure ./configure --disable-sse --disable-dec265 --disable-sherlock265 - emmake make -j${CORES} - cd .. +LIBRARY_LINKER_FLAGS="" +LIBRARY_INCLUDE_FLAGS="" + +CONFIGURE_ARGS_LIBDE265="" +if [ "$ENABLE_LIBDE265" = "1" ]; then + [ -s "libde265-${LIBDE265_VERSION}.tar.gz" ] || curl \ + -L \ + -o libde265-${LIBDE265_VERSION}.tar.gz \ + https://github.com/strukturag/libde265/releases/download/v${LIBDE265_VERSION}/libde265-${LIBDE265_VERSION}.tar.gz + if [ ! -s "libde265-${LIBDE265_VERSION}/libde265/.libs/libde265.so" ]; then + tar xf libde265-${LIBDE265_VERSION}.tar.gz + cd libde265-${LIBDE265_VERSION} + [ -x configure ] || ./autogen.sh + emconfigure ./configure --disable-sse --disable-dec265 --disable-sherlock265 + emmake make -j${CORES} + cd .. + fi + CONFIGURE_ARGS_LIBDE265="-DLIBDE265_INCLUDE_DIR=${DIR}/libde265-${LIBDE265_VERSION} -DLIBDE265_LIBRARY=-L${DIR}/libde265-${LIBDE265_VERSION}/libde265/.libs" + LIBRARY_LINKER_FLAGS="$LIBRARY_LINKER_FLAGS -lde265" + LIBRARY_INCLUDE_FLAGS="$LIBRARY_INCLUDE_FLAGS -L${DIR}/libde265-${LIBDE265_VERSION}/libde265/.libs" +fi + +CONFIGURE_ARGS_AOM="" +if [ "$ENABLE_AOM" = "1" ]; then + [ -s "aom-${AOM_VERSION}.tar.gz" ] || curl \ + -L \ + -o aom-${AOM_VERSION}.tar.gz \ + "https://aomedia.googlesource.com/aom/+archive/v${AOM_VERSION}.tar.gz" + if [ ! -s "aom-${AOM_VERSION}/libaom.a" ]; then + mkdir -p aom-${AOM_VERSION}/aom-source + tar xf aom-${AOM_VERSION}.tar.gz -C aom-${AOM_VERSION}/aom-source + cd aom-${AOM_VERSION} + + emcmake cmake aom-source \ + -DENABLE_CCACHE=1 \ + -DAOM_TARGET_CPU=generic \ + -DENABLE_DOCS=0 \ + -DENABLE_TESTS=0 \ + -DENABLE_EXAMPLES=0 \ + -DENABLE_TESTDATA=0 \ + -DENABLE_TOOLS=0 \ + -DCONFIG_MULTITHREAD=0 \ + -DCONFIG_RUNTIME_CPU_DETECT=0 \ + -DBUILD_SHARED_LIBS=1 \ + -DCMAKE_BUILD_TYPE=Release + + emmake make -j${CORES} + + cd .. + fi + + CONFIGURE_ARGS_AOM="-DAOM_INCLUDE_DIR=${DIR}/aom-${AOM_VERSION}/aom-source -DAOM_LIBRARY=-L${DIR}/aom-${AOM_VERSION}" + LIBRARY_LINKER_FLAGS="$LIBRARY_LINKER_FLAGS -laom" + LIBRARY_INCLUDE_FLAGS="$LIBRARY_INCLUDE_FLAGS -L${DIR}/aom-${AOM_VERSION}" fi -CONFIGURE_ARGS="-DENABLE_MULTITHREADING_SUPPORT=OFF -DWITH_GDK_PIXBUF=OFF -DWITH_EXAMPLES=OFF -DBUILD_SHARED_LIBS=ON" -#export PKG_CONFIG_PATH="${DIR}/libde265-${LIBDE265_VERSION}" +EXTRA_EXE_LINKER_FLAGS="-lembind" +EXTRA_COMPILER_FLAGS="" +if [ "$STANDALONE" = "1" ]; then + EXTRA_EXE_LINKER_FLAGS="" + EXTRA_COMPILER_FLAGS="-D__EMSCRIPTEN_STANDALONE_WASM__=1" +fi +CONFIGURE_ARGS="-DENABLE_MULTITHREADING_SUPPORT=OFF -DWITH_GDK_PIXBUF=OFF -DWITH_EXAMPLES=OFF -DBUILD_SHARED_LIBS=ON -DENABLE_PLUGIN_LOADING=OFF" emcmake cmake $CONFIGURE_ARGS \ - -DLIBDE265_INCLUDE_DIR="${DIR}/libde265-${LIBDE265_VERSION}" \ - -DLIBDE265_LIBRARY="-L${DIR}/libde265-${LIBDE265_VERSION}/libde265/.libs" + -DCMAKE_C_FLAGS="${EXTRA_COMPILER_FLAGS}" \ + -DCMAKE_CXX_FLAGS="${EXTRA_COMPILER_FLAGS}" \ + -DCMAKE_EXE_LINKER_FLAGS="${LIBRARY_LINKER_FLAGS} ${EXTRA_EXE_LINKER_FLAGS}" \ + $CONFIGURE_ARGS_LIBDE265 \ + $CONFIGURE_ARGS_AOM + emmake make -j${CORES} -export TOTAL_MEMORY=16777216 +LIBHEIFA="libheif/libheif.a" +EXPORTED_FUNCTIONS=$($EMSDK/upstream/bin/llvm-nm $LIBHEIFA --format=just-symbols | grep "^heif_\|^de265_\|^aom_" | grep "[^:]$" | sed 's/^/_/' | paste -sd "," -) echo "Running Emscripten..." -emcc libheif/libheif.so \ - --bind \ - --closure 0 \ - -s NO_EXIT_RUNTIME=1 \ - -s TOTAL_MEMORY=${TOTAL_MEMORY} \ + +BUILD_FLAGS="-lembind -o libheif.js --pre-js pre.js --post-js post.js -sWASM=$USE_WASM" +RELEASE_BUILD_FLAGS="-O3" + +if [ "$STANDALONE" = "1" ]; then + echo "Building in standalone (non-web) build mode" + BUILD_FLAGS="$BUILD_FLAGS -s STANDALONE_WASM=1 -s WASM=1 -o libheif.wasm --no-entry" +fi + +if [ "$DEBUG" = "1" ]; then + echo "Building in debug mode" + RELEASE_BUILD_FLAGS="--profile -g" +fi + +emcc "$LIBHEIFA" \ + -s EXPORTED_FUNCTIONS="$EXPORTED_FUNCTIONS,_free,_malloc,_memcpy" \ -s ALLOW_MEMORY_GROWTH=1 \ - -s ASSERTIONS=0 \ - -s INVOKE_RUN=0 \ - -s DOUBLE_MODE=0 \ - -s PRECISE_F32=0 \ - -s DISABLE_EXCEPTION_CATCHING=1 \ - -s USE_CLOSURE_COMPILER=0 \ - -s LEGACY_VM_SUPPORT=1 \ + -s ERROR_ON_UNDEFINED_SYMBOLS=0 \ + -s LLD_REPORT_UNDEFINED \ --memory-init-file 0 \ - -O3 \ -std=c++11 \ - -L${DIR}/libde265-${LIBDE265_VERSION}/libde265/.libs \ - -lde265 \ - --pre-js pre.js \ - --post-js post.js \ - -o libheif.js + $LIBRARY_INCLUDE_FLAGS \ + $LIBRARY_LINKER_FLAGS \ + $BUILD_FLAGS \ + $RELEASE_BUILD_FLAGS diff --git a/libheif/heif.cc b/libheif/heif.cc index 954c6c9a15..30f3b0401d 100644 --- a/libheif/heif.cc +++ b/libheif/heif.cc @@ -33,7 +33,7 @@ #include #include -#if defined(__EMSCRIPTEN__) +#if defined(__EMSCRIPTEN__) && !defined(__EMSCRIPTEN_STANDALONE_WASM__) #include "heif_emscripten.h" #endif diff --git a/libheif/heif_emscripten.h b/libheif/heif_emscripten.h index 23e4262153..42b7417205 100644 --- a/libheif/heif_emscripten.h +++ b/libheif/heif_emscripten.h @@ -112,7 +112,7 @@ static emscripten::val heif_js_decode_image(struct heif_image_handle* handle, result.set("width", width); int height = heif_image_get_height(image, heif_channel_Y); result.set("height", height); - std::string data; + std::basic_string data; result.set("chroma", heif_image_get_chroma_format(image)); result.set("colorspace", heif_image_get_colorspace(image)); switch (heif_image_get_colorspace(image)) { @@ -127,7 +127,7 @@ static emscripten::val heif_js_decode_image(struct heif_image_handle* handle, const uint8_t* plane_v = heif_image_get_plane_readonly(image, heif_channel_Cr, &stride_v); data.resize((width * height) + (2 * round_odd(width) * round_odd(height))); - char* dest = const_cast(data.data()); + unsigned char* dest = const_cast(data.data()); strided_copy(dest, plane_y, width, height, stride_y); strided_copy(dest + (width * height), plane_u, round_odd(width), round_odd(height), stride_u); @@ -142,7 +142,7 @@ static emscripten::val heif_js_decode_image(struct heif_image_handle* handle, const uint8_t* plane_rgb = heif_image_get_plane_readonly(image, heif_channel_interleaved, &stride_rgb); data.resize(width * height * 3); - char* dest = const_cast(data.data()); + unsigned char* dest = const_cast(data.data()); strided_copy(dest, plane_rgb, width * 3, height, stride_rgb); } break; @@ -153,7 +153,7 @@ static emscripten::val heif_js_decode_image(struct heif_image_handle* handle, const uint8_t* plane_grey = heif_image_get_plane_readonly(image, heif_channel_Y, &stride_grey); data.resize(width * height); - char* dest = const_cast(data.data()); + unsigned char* dest = const_cast(data.data()); strided_copy(dest, plane_grey, width, height, stride_grey); } break; diff --git a/post.js b/post.js index 3c0e70fec8..fd733a5841 100644 --- a/post.js +++ b/post.js @@ -175,40 +175,6 @@ var libheif = { } }; -var key; - -// Expose enum values. -var enums = { - "heif_error_code": true, - "heif_suberror_code": true, - "heif_compression_format": true, - "heif_chroma": true, - "heif_colorspace": true, - "heif_channel": true -}; -var e; -for (e in enums) { - if (!enums.hasOwnProperty(e)) { - continue; - } - for (key in Module[e]) { - if (!Module[e].hasOwnProperty(key) || - key === "values") { - continue; - } - - libheif[key] = Module[e][key]; - } -} - -// Expose internal C API. -for (key in Module) { - if (enums.hasOwnProperty(key) || key.indexOf("heif_") !== 0) { - continue; - } - libheif[key] = Module[key]; -} - // don't pollute the global namespace delete this['Module']; diff --git a/pre.js b/pre.js index 25e608e583..3978ad958f 100644 --- a/pre.js +++ b/pre.js @@ -29,5 +29,47 @@ var Module = { console.error(text); }, canvas: {}, - noInitialRun: true + noInitialRun: true, + onRuntimeInitialized: function() { + // Expose enum values. + var enums = { + "heif_error_code": true, + "heif_suberror_code": true, + "heif_compression_format": true, + "heif_chroma": true, + "heif_colorspace": true, + "heif_channel": true + }; + var e; + for (e in enums) { + if (!enums.hasOwnProperty(e)) { + continue; + } + + for (key in this[e]) { + if (!this[e].hasOwnProperty(key) || + key === "values") { + continue; + } + + libheif[key] = this[e][key]; + } + } + + // Expose internal C API. + for (key in this) { + if (enums.hasOwnProperty(key.slice(1)) || key.indexOf("_heif_") !== 0) { + continue; + } + libheif[key.slice(1)] = this[key]; + } + + // Expose embind API. + for (key in Module) { + if (enums.hasOwnProperty(key) || key.indexOf("heif_") !== 0) { + continue; + } + libheif[key] = Module[key]; + } + } }; diff --git a/scripts/install-emscripten.sh b/scripts/install-emscripten.sh index d3b638e624..066c77f463 100755 --- a/scripts/install-emscripten.sh +++ b/scripts/install-emscripten.sh @@ -11,7 +11,6 @@ fi LIBSTDC_BASE=http://de.archive.ubuntu.com/ubuntu/pool/main/g/gcc-5 EMSDK_DOWNLOAD=https://github.com/emscripten-core/emsdk.git -EMSDK_VERSION=3.1.29 CODENAME=$(/usr/bin/lsb_release --codename --short) if [ "$CODENAME" = "trusty" ] && [ ! -e "/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21" ]; then @@ -33,13 +32,13 @@ if [ ! -d emsdk ]; then fi cd emsdk -echo "Updating SDK base to ${EMSDK_VERSION} ..." +echo "Updating SDK base to ${VERSION} ..." git checkout main git pull --verbose -git checkout ${EMSDK_VERSION} +git checkout ${VERSION} -echo "Installing SDK version ${VERSION} ..." -./emsdk install sdk-fastcomp-${VERSION}-64bit +echo "Installing SDK version latest ..." +./emsdk install ${VERSION} -echo "Activating SDK version ${VERSION} ..." -./emsdk activate sdk-fastcomp-${VERSION}-64bit +echo "Activating SDK version latest ..." +./emsdk activate ${VERSION}