背景
公司音视频处理项目大量用到WebAssembly,c++到WebAssembly,做个总结记录。
WebAssembly基本概念
是什么
一种低级的类汇编语言,具有紧凑的二进制格式,可以接近原生的性能运行,并为诸如C / C ++等语言提供一个编译目标
目标特点
1.快速、高效、可移植
2.可读、可调试
3.保持安全-浏览器的同源策略和授权策略
4.不破坏网络
5.可移植性:二进制格式旨在在各种操作系统和指令集架构上高效执行,无论是在网络上还是在网络外
如何适应网络平台
网络平台由两部分组成
1.运行网络程序代码的虚拟机
2.一系列网络程序能够调用从而控制网络浏览器/设备功能,且能让事务发生变化的API(DOM CSSOM WebGL IndexDB WebAudioAPI)
工作流程
1.Emscripten首先把C/C++提供给clang+LLVM——一个成熟的开源C/C++编译器工具链,比如,在OSX上是XCode的一部分。
2.Emscripten将clang+LLVM编译的结果转换为一个.wasm二进制文件。
3.就自身而言,WebAssembly当前不能直接的存取DOM;它只能调用JavaScript,并且只能传入整形和浮点型的原始数据类型作为参数。这就是说,为了使用任何WebAPI,WebAssembly需 要调用到JavaScript,然后由JavaScript调用Web API。因此,Emscripten创建了HTML和JavaScript胶水代码以便完成这些功能。
另外
1.Emscripten实现了流行的C/C++库,SDL,OpenGL,OpenAL,POSIX;
2.如果应用程序使用了OpenGL,HTML文档还会包含一个用来渲染目标的<canvas>标签,其他都是<textarea>
关键概念
1.Module:一个已经被浏览器编译为可执行机器码的WebAssembly二进制代码,模块是状态的,像Blob一样能够被缓存到IndexDB或者在windows和workers之间通过postMessage共享,和es5模块一样可以到出/入
2.Memory:ArrayBuffer,大小可变,本质是连续的字节数组
3.Table:带类型数组,大小可变,表格中的项存储了不能作为原始字节存储在内存里的对象的引用(为了安全和可移植性)
4.Instance :一个模块及其在运行时使用的所有状态,包括内存和一些列导入值,一个实例就像一个已经被加载到了一个拥有一组特定导入的特定的全局变量的ES2015模块
从c++编译为WebAssembly
1.Emscripten 环境安装
a.所需条件Git
b.CMake
c.Python2.7+
d.VisualStidio
2.编译Emscripten [详见](https://developer.mozilla.org/zh-CN/docs/WebAssembly/C_to_wasm)
3.编译样例代码 emcc hello.c -s WASM=1 -o hello.html
4.定义在c中的方法
a.写好目标函数如callTest
b.使用emcc编译
c.使用 Emscripten 中的 ccall() 函数调用
const result = Module.ccall('myFunction')
加载运行WebAssembly代码
1.为了在JavaScript中使用WebAssembly,在编译/实例化之前,首先需要把模块放入内存,使用XMLHttpRequest或者Fetch,模块将会被初始化为带类型数组
2.当前还没有内置的方式让浏览器为你获取模块。当前唯一的方式就是创建一个包含你的WebAssembly模块二进制代码的ArrayBuffer并且使用WebAssembly.instantiate()编译
3.使用fetch
a.使用fetch()全局函数来轻松地获取它,该函数返回一个可以解析为Response对象的promise。
b.使用ArrayBuffer函数把响应(response)转换为带类型数组,该函数返回一个可以解析为带类型数组的promise。
c.最后使用WebAssembly.instantiate()函数一步实现编译和实例化带类型数组。
4.实例化的实用函数
5.运行WebAssembly代码
[使用](WebAssembly.Instance.exports)导出
缓存已经编译的WebAssembly模块
使用IndexDB实现
1.建立缓存库
1.建立数据库
2.在数据库中查找模块
3.存储和实例化模块
4.使用promise
2.缓存wasm模块
小结
一般做音视频的都会用到WebAssembly,Adobe中的ps pr等就是用c++写的,主要使用sdk中的方法,前端调用使其性能更优。
参考