Skip to content

Commit

Permalink
Add scripts to compile FFmpeg to WASI
Browse files Browse the repository at this point in the history
  • Loading branch information
SebastiaanYN committed Aug 27, 2022
1 parent 5770684 commit fc2867a
Show file tree
Hide file tree
Showing 11 changed files with 310 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
wasi-sdk
build

*.wasm
6 changes: 6 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
[submodule "FFmpeg"]
path = FFmpeg
url = https://github.com/FFmpeg/FFmpeg.git
[submodule "deps/zlib"]
path = deps/zlib
url = https://github.com/madler/zlib.git
[submodule "deps/x264"]
path = deps/x264
url = https://github.com/ffmpegwasm/x264.git
1 change: 1 addition & 0 deletions deps/x264
Submodule x264 added at 266eb1
1 change: 1 addition & 0 deletions deps/zlib
Submodule zlib added at 21767c
198 changes: 198 additions & 0 deletions patches/file_open.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg 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.
*
* FFmpeg 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 FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "config.h"
#include "internal.h"
#include "mem.h"
#include <stdarg.h>
#include <fcntl.h>
#include <sys/stat.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#if HAVE_IO_H
#include <io.h>
#endif

#ifdef _WIN32
#undef open
#undef lseek
#undef stat
#undef fstat
#include <windows.h>
#include <share.h>
#include <errno.h>
#include "wchar_filename.h"

static int win32_open(const char *filename_utf8, int oflag, int pmode)
{
int fd;
wchar_t *filename_w;

/* convert UTF-8 to wide chars */
if (get_extended_win32_path(filename_utf8, &filename_w))
return -1;
if (!filename_w)
goto fallback;

fd = _wsopen(filename_w, oflag, SH_DENYNO, pmode);
av_freep(&filename_w);

if (fd != -1 || (oflag & O_CREAT))
return fd;

fallback:
/* filename may be in CP_ACP */
return _sopen(filename_utf8, oflag, SH_DENYNO, pmode);
}
#define open win32_open
#endif

int avpriv_open(const char *filename, int flags, ...)
{
int fd;
unsigned int mode = 0;
va_list ap;

va_start(ap, flags);
if (flags & O_CREAT)
mode = va_arg(ap, unsigned int);
va_end(ap);

#ifdef O_CLOEXEC
flags |= O_CLOEXEC;
#endif
#ifdef O_NOINHERIT
flags |= O_NOINHERIT;
#endif

fd = open(filename, flags, mode);
#if HAVE_FCNTL
if (fd != -1) {
if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
av_log(NULL, AV_LOG_DEBUG, "Failed to set close on exec\n");
}
#endif

return fd;
}

typedef struct FileLogContext {
const AVClass *class;
int log_offset;
void *log_ctx;
} FileLogContext;

static const AVClass file_log_ctx_class = {
.class_name = "TEMPFILE",
.item_name = av_default_item_name,
.option = NULL,
.version = LIBAVUTIL_VERSION_INT,
.log_level_offset_offset = offsetof(FileLogContext, log_offset),
.parent_log_context_offset = offsetof(FileLogContext, log_ctx),
};

int avpriv_tempfile(const char *prefix, char **filename, int log_offset, void *log_ctx)
{
FileLogContext file_log_ctx = { &file_log_ctx_class, log_offset, log_ctx };
int fd = -1;
#if !HAVE_MKSTEMP
// void *ptr= tempnam(NULL, prefix);
// if(!ptr)
// ptr= tempnam(".", prefix);
void *ptr = NULL;
*filename = av_strdup(ptr);
#undef free
free(ptr);
#else
size_t len = strlen(prefix) + 12; /* room for "/tmp/" and "XXXXXX\0" */
*filename = av_malloc(len);
#endif
/* -----common section-----*/
if (!*filename) {
av_log(&file_log_ctx, AV_LOG_ERROR, "ff_tempfile: Cannot allocate file name\n");
return AVERROR(ENOMEM);
}
#if !HAVE_MKSTEMP
# ifndef O_BINARY
# define O_BINARY 0
# endif
# ifndef O_EXCL
# define O_EXCL 0
# endif
fd = open(*filename, O_RDWR | O_BINARY | O_CREAT | O_EXCL, 0600);
#else
snprintf(*filename, len, "/tmp/%sXXXXXX", prefix);
fd = mkstemp(*filename);
#if defined(_WIN32) || defined (__ANDROID__) || defined(__DJGPP__)
if (fd < 0) {
snprintf(*filename, len, "./%sXXXXXX", prefix);
fd = mkstemp(*filename);
}
#endif
#endif
/* -----common section-----*/
if (fd < 0) {
int err = AVERROR(errno);
av_log(&file_log_ctx, AV_LOG_ERROR, "ff_tempfile: Cannot open temporary file %s\n", *filename);
av_freep(filename);
return err;
}
return fd; /* success */
}

FILE *avpriv_fopen_utf8(const char *path, const char *mode)
{
int fd;
int access;
const char *m = mode;

switch (*m++) {
case 'r': access = O_RDONLY; break;
case 'w': access = O_CREAT|O_WRONLY|O_TRUNC; break;
case 'a': access = O_CREAT|O_WRONLY|O_APPEND; break;
default :
errno = EINVAL;
return NULL;
}
while (*m) {
if (*m == '+') {
access &= ~(O_RDONLY | O_WRONLY);
access |= O_RDWR;
} else if (*m == 'b') {
#ifdef O_BINARY
access |= O_BINARY;
#endif
} else if (*m) {
errno = EINVAL;
return NULL;
}
m++;
}
fd = avpriv_open(path, access, 0666);
if (fd == -1)
return NULL;
return fdopen(fd, mode);
}

#if FF_API_AV_FOPEN_UTF8
FILE *av_fopen_utf8(const char *path, const char *mode)
{
return avpriv_fopen_utf8(path, mode);
}
#endif
7 changes: 7 additions & 0 deletions scripts/build-deps.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash

set -euo pipefail

for f in ./scripts/deps/*.sh; do
bash "$f"
done
11 changes: 11 additions & 0 deletions scripts/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/bash

set -euo pipefail

cd FFmpeg
cp ../patches/file_open.c ./libavutil/file_open.c
../build/compile.sh
cp ffmpeg ../ffmpeg.wasm
cp ffprobe ../ffprobe.wasm
git reset --hard
cd ..
48 changes: 48 additions & 0 deletions scripts/configure.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/bin/bash

set -euo pipefail

FFMPEG_CONFIG_FLAGS_BASE=(
--target-os=none # use none to prevent any os specific configurations
--arch=x86_32 # use x86_32 to achieve minimal architectural optimization
--enable-cross-compile # enable cross compile
--disable-x86asm # disable x86 asm
--disable-inline-asm # disable inline asm
--disable-stripping # disable stripping
--disable-doc # disable doc
--disable-debug # disable debug info, required by closure
--disable-runtime-cpudetect # disable runtime cpu detect
--disable-autodetect # disable external libraries auto detect
--disable-network # https://github.com/WebAssembly/wasi-sdk/issues/112
# --enable-lto # use link-time optimization
--disable-pthreads
--disable-w32threads
--disable-os2threads
--pkg-config-flags="--static"
--nm=../wasi-sdk/bin/nm
--ar=../wasi-sdk/bin/ar
--ranlib=../wasi-sdk/bin/ranlib
--cc=../wasi-sdk/bin/clang
--cxx=../wasi-sdk/bin/clang++
--objcc=../wasi-sdk/bin/clang
--dep-cc=../wasi-sdk/bin/clang
--enable-gpl
--enable-libx264
--enable-zlib
--extra-cflags="-I../build/include"
--extra-ldflags="-L../build/lib"
--enable-encoder=libx264
--enable-encoder=png
)

mkdir -p build

cd FFmpeg
./configure ${FFMPEG_CONFIG_FLAGS_BASE[@]}

make -n |
sed 's/clang /clang -D_WASI_EMULATED_PROCESS_CLOCKS -lwasi-emulated-process-clocks /g' |
sed 's/clang /clang -D_WASI_EMULATED_SIGNAL -lwasi-emulated-signal /g' |
cat > ../build/compile.sh
chmod +x ../build/compile.sh
cd ..
20 changes: 20 additions & 0 deletions scripts/deps/x264.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/bin/bash

set -euo pipefail

cd deps/x264
CC=../../wasi-sdk/bin/clang \
AR=../../wasi-sdk/bin/ar \
RANLIB=../../wasi-sdk/bin/ranlib \
./configure \
--prefix=../../build \
--host=i686-gnu \
--enable-static \
--disable-cli \
--disable-asm \
--disable-thread \
--extra-cflags="-D_WASI_EMULATED_SIGNAL" \
--extra-ldflags="-lwasi-emulated-signal"
sed -i 's/#define HAVE_MALLOC_H 1/#define HAVE_MALLOC_H 0/g' config.h
make install-lib-static
cd ../..
13 changes: 13 additions & 0 deletions scripts/deps/zlib.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/bash

set -euo pipefail

cd deps/zlib
CC=../../wasi-sdk/bin/clang \
AR=../../wasi-sdk/bin/ar \
RANLIB=../../wasi-sdk/bin/ranlib \
prefix=../../build \
./configure --static
make install
git reset --hard
cd ../..
2 changes: 2 additions & 0 deletions install.sh → scripts/install.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#!/bin/bash

set -euo pipefail

WASI_VERSION=16
WASI_VERSION_FULL=${WASI_VERSION}.0
wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_VERSION}/wasi-sdk-${WASI_VERSION_FULL}-linux.tar.gz
Expand Down

0 comments on commit fc2867a

Please sign in to comment.