使用web worker和webassembly技術(shù) (Mac OS)

本菜雞最近在搞FFmpeg嵌入到前端中做解碼,初步的想法是通過(guò)web worker 建一個(gè)解碼的線程專門用于解碼H264數(shù)據(jù),然后主線程負(fù)責(zé)渲染解碼后的數(shù)據(jù)。
首先要在前端中運(yùn)行C代碼,那就要使用webassembly技術(shù),webassembly技術(shù)可以將C/C++、rust代碼編譯為.wasm文件,然后導(dǎo)入到前端中實(shí)現(xiàn)前端運(yùn)行C/C++、rust代碼的效果。而編譯生成.wasm文件需要用到emscripten工具
本文中的emscripten版本如下:

emscripten版本

來(lái)個(gè)簡(jiǎn)單的C代碼:

#include <stdio.h>
int main(int argc, char ** argv) {
    printf("Hello, world!\n");
}
int mytest() {
    printf("this is wasm test!\n");
    return 999;
}

編譯上面的C代碼為wasm文件(最后生成的文件為JS文件,導(dǎo)入這個(gè).js代碼就可以導(dǎo)入.wasm文件):

emcc hello.c -o hello.js -s MODULARIZE=1 -s EXPORT_NAME=Test -s EXTRA_EXPORTED_RUNTIME_METHODS='["ccall"]' -s EXPORTED_FUNCTIONS='["_mytest","_main"]'

新建一個(gè)html文件作為演示:

<!DOCTYPE html>
<html>
    <head>
        <title>wasm</title>
    </head>
    <body>
        <h1>test !</h1>
        <button onclick="test()">send a test</button>
        <button onclick="closeWebworker()">close web worker</button>
    </body>
    <script>
        var worker = null
        window.onload = function () {
            // 新建一個(gè)worker
            worker = new Worker("test.js")
            // 向子線程傳遞數(shù)據(jù)
            worker.postMessage('init')
            worker.onmessage = function (evt) {
                console.log('master reveived msg: ',evt.data)
            }
            var ab = new ArrayBuffer(1);
            // 使用transportObject
            worker.postMessage(ab, [ab]);
        }
        function closeWebworker() {
            worker.terminate()
            worker = null
            console.log('close web worker !!')
        }
        function test() {
            if (worker) {
                worker.postMessage('test')
            } else {
                console.log('web worker has closed !')
            } 
        }
    </script>
</html>

然后是頁(yè)面中用到的test.js

importScripts('hello.js')

var self = this
function Test2() {
    // 初始化worker
    this.initWorker()
}

Test2.prototype.initWorker = function () {
    console.log('初始化worker !')
}

Test2.prototype.init = async function () {
    self.Module = await initModule()
    postMessage('初始化')
    var testBuffer = new ArrayBuffer(32)
    postMessage(testBuffer,[testBuffer])
}

Test2.prototype.mytest = function () {
    console.log(self.Module._mytest())
}

self.test = new Test2

self.onmessage = function (evt) {
    if (self.test === undefined) {
        console.log('init error !', self.test)
        return ;
    }
    console.log(`子線程Reveived msg: ${evt.data}`)
    switch (evt.data) {
        case 'init':
            self.test.init();
            break;
        case 'test':
            self.test.mytest();
            break;
        default:
            break;
    }
}

function onWasmLoaded() {
    if (test) {
       test.mytest();
    } else {
        console.log("[ER] No decoder!");
    }
}

function initModule() {
    return new Promise((r,j) => {
        r(
            Test({
                onRuntimeInitialized: () => {
                    console.log('初始化wasm!')
                },
            })
        )
    })
}

最后整體的項(xiàng)目結(jié)構(gòu):

項(xiàng)目結(jié)構(gòu)

運(yùn)行命令:emrun --no_browser --port 8087 .打開(kāi)localhost:8087查看效果。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容