WebAssembly 开发环境搭建

简介

WebAssembly 是一种新的编码方式,可以在现代的网络浏览器中运行 - 它是一种低级的类汇编语言,具有紧凑的二进制格式,可以接近原生的性能运行,并为诸如C/C++等语言提供一个编译目标,以便它们可以在 Web 上运行。它也被设计为可以与 JavaScript 共存,允许两者一起工作。

简而言之,对于网络平台而言,WebAssembly 具有巨大的意义——它提供了一条途径,以使得以各种语言编写的代码都可以以接近原生的速度在 Web 中运行。在这种情况下,以前无法以此方式运行的客户端软件都将可以运行在 Web 中。

WebAssembly 被设计为可以和 JavaScript 一起协同工作——通过使用 WebAssembly 的 JavaScript API,你可以把 WebAssembly 模块加载到一个 JavaScript 应用中并且在两者之间共享功能。这允许你在同一个应用中利用 WebAssembly 的性能和威力以及 JavaScript 的表达力和灵活性,即使你可能并不知道如何编写 WebAssembly 代码。

本文展示了将 FFmpeg 应用到 WebAssembly 的例子。

编译环境

https://hub.docker.com/r/emscripten/emsdk/tags

拉取远程镜像

docker pull emscripten/emsdk:2.0.24

启动容器

映射自己的目录

docker run -d -it --name mediawasm -v d:/.../wasmff:/code  emscripten/emsdk:2.0.24 /bin/bash

编译

编译脚本

#!/bin/bash

#set -eo pipefail

WORKPATH=$(cd $(dirname $0); pwd)

DEMO_PATH=$WORKPATH/demo

echo "WORKPATH"=$WORKPATH

rm -rf ${WORKPATH}/demo/mp4encoder.js ${WORKPATH}/demo/mp4encoder.wasm

FFMPEG_ST=yes

EMSDK=/emsdk

THIRD_DIR=${WORKPATH}/lib/third/build

# 生成调试文件
DEBUG="-g -fno-inline -gseparate-dwarf=/code/demo/temp.debug.wasm -s SEPARATE_DWARF_URL=http://localhost:5000/temp.debug.wasm" #--closure 压缩胶水代码,有可能会造成变量重复定义。生产发布可设为1
OPTIM_FLAGS="-O1 $DEBUG --closure 0" if [[ "$FFMPEG_ST" != "yes" ]]; then
EXTRA_FLAGS=(
-pthread
-s USE_PTHREADS=1 # enable pthreads support
-s PROXY_TO_PTHREAD=1 # detach main() from browser/UI main thread
-o ${DEMO_PATH}/mp4encoder.js
)
else
EXTRA_FLAGS=(
-o ${DEMO_PATH}/mp4encoder.js
)
fi FLAGS=(
-I$WORKPATH/lib/ffmpeg-emcc/include -L$WORKPATH/lib/ffmpeg-emcc/lib -I$THIRD_DIR/include -L$THIRD_DIR/lib
-Wno-deprecated-declarations -Wno-pointer-sign -Wno-implicit-int-float-conversion -Wno-switch -Wno-parentheses -Qunused-arguments
-lavdevice -lavfilter -lavformat -lavcodec -lswresample -lswscale -lavutil -lpostproc
-lm -lharfbuzz -lfribidi -lass -lx264 -lx265 -lvpx -lwavpack -lmp3lame -lfdk-aac -lvorbis -lvorbisenc -lvorbisfile -logg -ltheora -ltheoraenc -ltheoradec -lz -lfreetype -lopus -lwebp
$DEMO_PATH/encode_v.c -s FORCE_FILESYSTEM=1
-s WASM=1
-s USE_SDL=2 # use SDL2
-s INVOKE_RUN=0 # not to run the main() in the beginning
-s EXIT_RUNTIME=1 # exit runtime after execution
-s MODULARIZE=1 # 延迟加载 use modularized version to be more flexible
-s EXPORT_NAME="createMP4Encoder" # assign export name for browser
-s EXPORTED_FUNCTIONS="[_main,_malloc,_free]" # export main and proxy_main funcs
-s EXPORTED_RUNTIME_METHODS="[FS, cwrap, ccall, setValue, writeAsciiToMemory]" # export preamble funcs
-s INITIAL_MEMORY=134217728 # 64 KB * 1024 * 16 * 2047 = 2146435072 bytes ~= 2 GB
-s ALLOW_MEMORY_GROWTH=1 # 允许动态扩展内存
--pre-js $WORKPATH/pre.js
--post-js $WORKPATH/post.js
$OPTIM_FLAGS
${EXTRA_FLAGS[@]}
)
echo "FFMPEG_EM_FLAGS=${FLAGS[@]}" emcc "${FLAGS[@]}"
./build-demo.sh

会在项目目录下生成 mp4encoder.jsmp4encoder.wasm 其中js文件文件为胶水代码,使得C++接口能在浏览器js中调用。实际的C++逻辑存放于wasm文件中。

在容器外的项目目录下, 启动web静态服务器查看效果

调试

介绍

https://developer.chrome.com/blog/wasm-debugging-2020/

下载安装插件

https://goo.gle/wasm-debugging-extension

1、打开开发者工具,设置(F1) -> 实验 -> 勾选 WebAssembly Debug



2、因为项目在Docker下编译,需要把Docker路径映射到本地磁盘





3、打开开发者工具 -> 源代码 -> 左侧file://下即可找到源代码 -> 设置断点 -> 右侧监视添加变量

参数传递

简单参数传递

  //把js string 转成 utf8 array
var getCStringPtr = function (jstr) {
var lengthBytes = lengthBytesUTF8(jstr) + 1;
var p = MP4Encoder._malloc(lengthBytes);
stringToUTF8(jstr, p, lengthBytes);
return p;
}
//allocateUTF8功能相同 //值类型可以直接传递,string必须先转array
var strPtr = getCStringPtr("/tmp/demo2.mp4");
var ret = MP4Encoder._createH264(strPtr, 1920, 1080, 25);

大块内存拷贝

    //js 数组内存
let fileBuffer = new Uint8Array(imagedata.data.buffer);
//wasm 数组内存
let bufferPtr = MP4Encoder._malloc(fileBuffer.length);
//js -> wasm
MP4Encoder.HEAP8.set(fileBuffer, bufferPtr);
var ret = MP4Encoder._addFrame(bufferPtr);

_malloc_free 这些系统方法是模块默认导出的。如果想查看其他方法是否可用,可以控制台打印MP4Encoder模块看其挂载的方法

文件读写

<input type="file" value="选择文件" onchange="inputJsFile(event)"></input>
  var inputJsFile = function (event) {
let file = event.target.files[0]; file.arrayBuffer().then(t=>{
console.log(t)
//创建文件夹
FS.mkdir('/working');
//写入二进制数据到wasm虚拟目录
FS.writeFile('/working/input.txt', new Uint8Array(t), { flags:'w+' });
//查看写入成功
console.log(FS.stat('/working/input.txt'))
//从wasm读取到js
var buff = FS.readFile('/working/input.txt', { encoding: 'binary' });
console.log(buff)
var pStr = getCStringPtr("/working/input.txt");
var ret = MP4Encoder._openTestFile(pStr);
});
}

项目地址

https://github.com/gaobowen/wasmff

扩展阅读

https://developer.mozilla.org/zh-CN/docs/WebAssembly

https://developer.mozilla.org/zh-CN/docs/Web/API/IndexedDB_API

https://emscripten.org/docs/api_reference/index.html

WebAssembly C++开发环境搭建的更多相关文章

  1. python开发环境搭建

    虽然网上有很多python开发环境搭建的文章,不过重复造轮子还是要的,记录一下过程,方便自己以后配置,也方便正在学习中的同事配置他们的环境. 1.准备好安装包 1)上python官网下载python运 ...

  2. IntelliJ IDEA安装及jsp开发环境搭建

    一.前言 现在.net国内市场不怎么好,公司整个.net组技术转型,就个人来说还是更喜欢.net,毕竟不是什么公司都像微软一样财大气粗开发出VS这样的宇宙级IDE供开发者使用,双击sln即可打开项目, ...

  3. Qt for Android开发环境搭建及测试过程记录

    最近学习了Qt的QML编程技术,感觉相较于以前的QtGUI来说更方便一些,使用QML可以将界面与业务逻辑解耦,便于开发. QML支持跨平台,包括支持Android平台,因此可以使用Qt的QML进行An ...

  4. node.js之开发环境搭建

    一.安装linux系统 (已安装linux可跳此步骤) 虚拟机推荐选择:VirtualBox 或者 Vmware (专业版永久激活码:5A02H-AU243-TZJ49-GTC7K-3C61N) 我这 ...

  5. TODO:小程序开发环境搭建

    TODO:小程序开发环境搭建 1.第一步当然是要先注册小程序了 2.登录到小程序 a)完善小程序信息,如名称,图标,描述 3.绑定开发者 4.获取AppID,并设置服务器信息 5.下载并安装开发者工具 ...

  6. Eclipse中Python开发环境搭建

    Eclipse中Python开发环境搭建  目 录  1.背景介绍 2.Python安装 3.插件PyDev安装 4.测试Demo演示 一.背景介绍 Eclipse是一款基于Java的可扩展开发平台. ...

  7. Windows 10 IoT Serials 1 - 针对Minnow Board MAX的Windows 10 IoT开发环境搭建

    目前,微软针对Windows IoT计划支持的硬件包括树莓派2,Minnow Board MAX 和Galileo (Gen 1和Gen 2).其中,Galileo (Gen 1和Gen 2)运行的是 ...

  8. Eclipse swt开发环境搭建

    原料: eclipse swt.下载链接为: Eclipse 4.6.2 Release Build: 4.6.2 配置说明: Developing SWT applications using Ec ...

  9. Ionic- Android 开发环境搭建

    Ionic- Android 开发环境搭建 为时一周的IONIC ADNROID 环境终于在各种处理错误中搭建成功,以下记录下搭建过程中遇到的各种情况的处理办法. 一 首先,当然是enviroment ...

  10. visual studio 2015 + Cordova 开发环境搭建

    简单的写一些,备忘,太折腾了,特别是通过代理上网的我们国内的开发者 1.当然是安装Visual Studio 2015,别忘了选择Tools For Apache Cordova. 对于通过Proxy ...

随机推荐

  1. Jmeter函数助手12-threadNum

    threadNum函数用于获取当前线程编号.该函数没有参数,直接引用即可. 1.线程数可在组件[测试计划->线程组]设置.如下是不传入循环次数的${__threadNum}. "调试取 ...

  2. Label Studio数据标注--通过源码安装

    Label Studio是Heartex公司开发的一款在线数据标注工具,分为社区版(开源)和企业版(云服务,收费),企业版提供了增强的安全性(单点登录.角色基于访问控制.SOC2).团队管理.分析和报 ...

  3. 切记:使用nvidia omniverse时一定要用2T的固态硬盘

    最近在用nvidia omniverse时突然发现这样的一个问题,那就是这个软件实在是太太了,一个组件就4个多GB大小,如果安装几个组件后那么几十GB的硬盘就没有了,同时由于这个体积太大,因此再启动和 ...

  4. AI4Science 再填新成员:谷歌推出天气模型MetNet-3 已落地相关产品、谷歌天气预报模型GraphCast登刊Science —— AI天气预报大模型

    相关: https://zhidx.com/news/40169.html https://zhidx.com/news/40290.html PS. 要知道,华为公司的最高学术成果就是AI天气预报, ...

  5. 关于“内网穿透”的一些知识(续3)—— NAT类型判断

    前文: 关于"内网穿透"的一些知识(续2)-- 端口预测 ------------------------------------------- 本文是对前面几篇文章的补充.这里要 ...

  6. 微软的GitHub Copilot

    随着OpenAI的ChatGPT4 Turbo的发布,基于ChatGPT的Copilot也推出了最新版. ======================================= 帮助文档: h ...

  7. 拈花云科基于 Apache DolphinScheduler 在文旅业态下的实践

    作者|云科NearFar X Lab团队 左益.周志银.洪守伟.陈超.武超 一.导读 无锡拈花云科技服务有限公司(以下简称:拈花云科)是由拈花湾文旅和北京滴普科技共同孵化的文旅目的地数智化服务商.20 ...

  8. RabbitMq高级特性之消费端限流 通俗易懂 超详细 【内含案例】

    RabbitMq高级特性之消费端限流 介绍 消息队列中囤积了大量的消息, 或者某些时刻生产的消息远远大于消费者处理能力的时候, 这个时候如果消费者一次取出大量的消息, 但是客户端又无法处理, 就会出现 ...

  9. [天线原理及设计>基本原理] 3. 辐射方向图或天线方向图

    <Antenna_Theory_Analysis_and_Design_3rd_Constantine_A._Balanis.pdf> 3. 辐射方向图或天线方向图 天线辐射方向图或天线方 ...

  10. ARM汇编:MRS和MSR指令

    1.MSR和MRS指令介绍 MRS 指令:  对状态寄存器CPSR和SPSR进行读操作.通过读CPSR可以获得当前处理器的工作状态.读SPSR寄存器可以获得进入异常前的处理器状态(因为只有异常模式下有 ...