diff --git a/Dockerfile b/Dockerfile index 32f26f8..94382f3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -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. diff --git a/Makefile b/Makefile index 79177bc..52b0dfb 100644 --- a/Makefile +++ b/Makefile @@ -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 \ No newline at end of file diff --git a/src/ffprobe-wasm-wrapper.cpp b/src/ffprobe-wasm-wrapper.cpp index 054de73..5cc1c4b 100644 --- a/src/ffprobe-wasm-wrapper.cpp +++ b/src/ffprobe-wasm-wrapper.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -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); diff --git a/www/.gitignore b/www/.gitignore index 26d0a1d..2b323f1 100644 --- a/www/.gitignore +++ b/www/.gitignore @@ -22,5 +22,5 @@ pnpm-debug.log* *.sln *.sw? -public/*.js +public/*-wasm*.js public/*.wasm \ No newline at end of file diff --git a/www/package-lock.json b/www/package-lock.json index e28c85d..2241ef2 100644 --- a/www/package-lock.json +++ b/www/package-lock.json @@ -1,6 +1,6 @@ { "name": "ffprobe-wasm", - "version": "0.2.1", + "version": "0.3.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/www/package.json b/www/package.json index 5048396..22e8f09 100644 --- a/www/package.json +++ b/www/package.json @@ -1,6 +1,6 @@ { "name": "ffprobe-wasm", - "version": "0.2.1", + "version": "0.3.0", "scripts": { "serve": "vue-cli-service serve", "build": "vue-cli-service build", diff --git a/www/public/ffprobe-worker.js b/www/public/ffprobe-worker.js new file mode 100644 index 0000000..33c32e4 --- /dev/null +++ b/www/public/ffprobe-worker.js @@ -0,0 +1,72 @@ +onmessage = (e) => { + const type = e.data[0]; + const file = e.data[1]; + + let data; + + switch (type) { + case 'get_file_info': + // Mount FS for files. + if (!FS.analyzePath('/work').exists) { + FS.mkdir('/work'); + } + FS.mount(WORKERFS, { files: [file] }, '/work'); + + // Call the wasm module. + const info = Module.get_file_info('/work/' + file.name); + + // Remap streams into collection. + const s = []; + for (let i = 0; i < info.streams.size(); i++) { + s.push(info.streams.get(i)); + } + + const versions = { + libavutil: Module.avutil_version(), + libavcodec: Module.avcodec_version(), + libavformat: Module.avformat_version(), + }; + + // Send back data response. + data = { + ...info, + streams: s, + versions, + } + postMessage(data); + + // Cleanup mount. + FS.unmount('/work'); + break; + + case 'get_frames': + if (!FS.analyzePath('/work').exists) { + FS.mkdir('/work'); + } + FS.mount(WORKERFS, { files: [file] }, '/work'); + + const offset = e.data[2]; + const frames = Module.get_frames('/work/' + file.name, offset); + + // Remap frames into collection. + const f = []; + for (let i = 0; i < frames.frames.size(); i++) { + f.push(frames.frames.get(i)); + } + + data = { + ...frames, + frames: f, + } + postMessage(data); + + // Cleanup mount. + FS.unmount('/work'); + break; + + default: + break; + } + +} +self.importScripts('ffprobe-wasm.js'); // Load ffprobe into worker context. \ No newline at end of file diff --git a/www/public/index.html b/www/public/index.html index 06fa9ec..4123528 100644 --- a/www/public/index.html +++ b/www/public/index.html @@ -12,7 +12,6 @@ We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.
- diff --git a/www/src/components/File.vue b/www/src/components/File.vue index 79f5c05..a039411 100644 --- a/www/src/components/File.vue +++ b/www/src/components/File.vue @@ -12,23 +12,17 @@ > - - -
+
Selected file: {{ file ? `${file.name}: ${file.size} bytes` : '' }}
-
+
- +
@@ -49,37 +43,19 @@ export default { return { file: null, data: null, - progress: 0, - showProgress: false, + info: null, } }, - computed: { - info() { - return this.data && window.Module.get_file_info(); + created() { + this.$worker.onmessage = (e) => { + this.info = e.data; } }, methods: { onFile(event) { this.data = null; - this.progress = 0; - 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); + this.$worker.postMessage([ 'get_file_info', file ]); } } } diff --git a/www/src/components/Frames.vue b/www/src/components/Frames.vue index 7680b7f..7380f9a 100644 --- a/www/src/components/Frames.vue +++ b/www/src/components/Frames.vue @@ -1,62 +1,69 @@