Refactor to load wasm module in a web worker to prevent blocking main browser thread. Update FS to use WORKERFS.

This commit is contained in:
Alf
2020-12-21 22:38:14 -08:00
parent 8dadddcb24
commit 3a7d96443c
6 changed files with 26 additions and 48 deletions

View File

@@ -1,4 +1,4 @@
FROM emscripten/emsdk as build
FROM emscripten/emsdk:2.0.11 as build
ARG FFMPEG_VERSION=4.3.1
ARG X264_VERSION=20170226-2245-stable
@@ -30,7 +30,7 @@ RUN cd /tmp/ && \
wget http://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.gz && \
tar zxf ffmpeg-${FFMPEG_VERSION}.tar.gz && rm ffmpeg-${FFMPEG_VERSION}.tar.gz
ARG CFLAGS="-s USE_PTHREADS -O3 -I${PREFIX}/include"
ARG CFLAGS="-s USE_PTHREADS=1 -O3 -I${PREFIX}/include"
ARG LDFLAGS="$CFLAGS -L${PREFIX}/lib -s INITIAL_MEMORY=33554432"
# Compile ffmpeg.

View File

@@ -6,7 +6,8 @@ dist/ffprobe-wasm.js:
-I/opt/ffmpeg/include/ \
-s EXTRA_EXPORTED_RUNTIME_METHODS="[FS, cwrap, ccall, getValue, setValue, writeAsciiToMemory]" \
-s INITIAL_MEMORY=268435456 \
-lavcodec -lavformat -lavfilter -lavdevice -lswresample -lswscale -lavutil -lm -lx264 \
-pthread \
-lavcodec -lavformat -lavfilter -lavdevice -lswresample -lswscale -lavutil -lm -lx264 -pthread \
-lworkerfs.js \
-o dist/ffprobe-wasm.js \
src/ffprobe-wasm-wrapper.cpp

View File

@@ -1,5 +1,6 @@
#include <vector>
#include <string>
#include <vector>
#include <inttypes.h>
#include <emscripten.h>
#include <emscripten/bind.h>
@@ -65,8 +66,8 @@ typedef struct FramesResponse {
int nb_frames;
} FramesResponse;
FileInfoResponse get_file_info() {
FILE *file = fopen("file", "rb");
FileInfoResponse get_file_info(std::string filename) {
FILE *file = fopen(filename.c_str(), "rb");
if (!file) {
printf("cannot open file\n");
}
@@ -79,9 +80,8 @@ FileInfoResponse get_file_info() {
// Open the file and read header.
int ret;
if ((ret = avformat_open_input(&pFormatContext, "file", NULL, NULL)) < 0) {
printf("ERROR: could not open the file. Error: %d\n", ret);
printf("%s", av_err2str(ret));
if ((ret = avformat_open_input(&pFormatContext, filename.c_str(), NULL, NULL)) < 0) {
printf("ERROR: %s\n", av_err2str(ret));
}
// Get stream info from format.
@@ -135,10 +135,10 @@ FileInfoResponse get_file_info() {
return r;
}
FramesResponse get_frames(int offset) {
FramesResponse get_frames(std::string filename, int offset) {
av_log_set_level(AV_LOG_QUIET); // No logging output for libav.
FILE *file = fopen("file", "rb");
FILE *file = fopen(filename.c_str(), "rb");
if (!file) {
printf("cannot open file\n");
}
@@ -151,9 +151,8 @@ FramesResponse get_frames(int offset) {
// Open the file and read header.
int ret;
if ((ret = avformat_open_input(&pFormatContext, "file", NULL, NULL)) < 0) {
printf("ERROR: could not open the file. Error: %d\n", ret);
printf("%s", av_err2str(ret));
if ((ret = avformat_open_input(&pFormatContext, filename.c_str(), NULL, NULL)) < 0) {
printf("ERROR: %s\n", av_err2str(ret));
}
// Get stream info from format.
@@ -239,7 +238,6 @@ FramesResponse get_frames(int offset) {
return r;
}
EMSCRIPTEN_BINDINGS(constants) {
function("avformat_version", &c_avformat_version);
function("avcodec_version", &c_avcodec_version);

View File

@@ -12,7 +12,6 @@
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<script src="ffprobe-wasm.js"></script>
<!-- built files will be auto injected -->
</body>
</html>

View File

@@ -18,12 +18,12 @@
:value="progress"
max="100"></b-progress>
<div v-if="data">
<div v-if="info">
<div class="mt-3">Selected file: {{ file ? `${file.name}: ${file.size} bytes` : '' }}</div>
<b-tabs class="mt-4">
<b-tab title="Overview" class="mt-2">
<div v-if="data">
<div v-if="info">
<Overview :info="info" />
</div>
</b-tab>
@@ -39,6 +39,8 @@
import Overview from './Overview.vue';
import Frames from './Frames.vue';
const worker = new Worker('ffprobe-worker.js');
export default {
name: 'File',
components: {
@@ -49,13 +51,14 @@ export default {
return {
file: null,
data: null,
info: null,
progress: 0,
showProgress: false,
}
},
computed: {
info() {
return this.data && window.Module.get_file_info();
created() {
worker.onmessage = (e) => {
this.info = e.data;
}
},
methods: {
@@ -65,21 +68,7 @@ export default {
this.showProgress = true;
const file = event.dataTransfer ? event.dataTransfer.files[0] : event.target.files[0];
const reader = new FileReader();
// reader.onload = e => this.$emit("load", event.target.result);
reader.onload = (event) => {
this.progress = 100;
this.data = new Uint8Array(event.target.result);
window.Module.FS.writeFile('file', new Uint8Array(this.data));
setTimeout(() => { this.showProgress = false; }, 2000);
}
reader.onprogress = (event) => {
if (event.lengthComputable) {
this.progress = parseInt(((event.loaded / event.total) * 100), 10);
}
}
reader.readAsArrayBuffer(file);
worker.postMessage([ file ]);
}
}
}

View File

@@ -7,7 +7,7 @@
<b-table stacked :items="items"></b-table>
<h4>Streams</h4>
<b-table striped hover :items="streams"></b-table>
<b-table striped hover :items="info.streams"></b-table>
</div>
</template>
@@ -15,15 +15,6 @@
export default {
name: 'Overview',
props: ['info'],
computed: {
streams() {
const s = [];
for (let i = 0; i < this.info.streams.size(); i++) {
s.push(this.info.streams.get(i));
}
return s;
}
},
data() {
return {
items: [
@@ -38,9 +29,9 @@ export default {
],
versions: [
{
libavutil: window.Module.avutil_version(),
libavcodec: window.Module.avcodec_version(),
libavformat: window.Module.avformat_version(),
libavutil: this.info.versions.libavutil,
libavcodec: this.info.versions.libavcodec,
libavformat: this.info.versions.libavformat,
}
]
}