From 31fbf936a3b953fa5272569c5e32581db111dbb7 Mon Sep 17 00:00:00 2001 From: xiangxud <365603975@qq.com> Date: Sat, 20 Aug 2022 17:48:04 +0800 Subject: [PATCH] H265.js need end } --- README.md | 42 +++++++++++++++++++++++++++++++++++------- test/h265.js | 3 ++- test/main.html | 2 +- test/parameter.js | 2 +- 4 files changed, 39 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 535c827..6f34e21 100644 --- a/README.md +++ b/README.md @@ -1,35 +1,47 @@ # 1 简介 -借助于WebAssembly(简称Wasm)技术,实现在浏览器端调用ffmpeg接口完成H.265码流到YUV数据的解码。 + +借助于WebAssembly(简称Wasm)技术,实现在浏览器端调用ffmpeg接口完成H.265码流到YUV数据的解码。 总体流程如下: ![Decode With FFmpeg and WASM](./doc/wasm.jpg "页面通过wasm调用FFmpeg流程图") # 2 依赖 + ## 2.1 [WebAssembly (Wasm)](https://webassembly.org/) -按照官网的定义,WebAssembly (wasm) 是一个可移植、体积小、加载快并且兼容 Web 的全新格式。通过wasm,可以在浏览器里执行原生代码(例如C、C++)。 + +按照官网的定义,WebAssembly (wasm) 是一个可移植、体积小、加载快并且兼容 Web 的全新格式。通过wasm,可以在浏览器里执行原生代码(例如C、C++)。 目前,wasm技术已经得到主流浏览器的广泛支持(数据来源[Can I Use](https://www.caniuse.com/#search=WebAssembly))。 ![Browser Suport For WASM](./doc/caniuse_wasm.jpg "主流浏览器对wasm的支持") + ## 2.2 FFmpeg -FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。 -我们代码里主要使用FFmpeg来做解码(decode)。为了减小体积,最终编译生成的wasm里包含的是裁剪过的FFmpeg,主要包含以下几个库: + +FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。我们代码里主要使用FFmpeg来做解码(decode)。为了减小体积,最终编译生成的wasm里包含的是裁剪过的FFmpeg,主要包含以下几个库: + - libavcodec: 编解码(最重要的库) - libavutil: 工具库(大部分库都需要这个库的支持) - libswscale: 视频像素数据格式转换 # 3 具体实现 + ## 3.1 接口 + 编译生成的wasm文件对外提供四个接口: + - openDecoder:初始化解码器; - decodeData:解码传入的H.265码流数据; - flushDecoder:清空缓存数据; -- closeDecoder:关闭解码器; +- closeDecoder:关闭解码器; ## 3.2 实现细节 + 解码过程中使用到的FFmpeg API及解码流程如下图所示: ![decoder](./doc/decode_video.jpg "调用FFmpeg API解码流程") ## 3.3 如何使用 -最终的编译结果是两个文件,一个是包含ffmpeg库的wasm文件,另一个是胶水代码(js文件)。页面里引用js文件时,胶水代码会加载wasm。 -Javascript与WASM的数据交互: + +最终的编译结果是两个文件,一个是包含ffmpeg库的wasm文件,另一个是胶水代码(js文件)。页面里引用js文件时,胶水代码会加载wasm。 +Javascript与WASM的数据交互: + + ```js // 发送: var cacheBuffer = Module._malloc(data.length); @@ -63,12 +75,15 @@ var ret = Module._openDecoder(codecType, videoCallback, LOG_LEVEL_WASM) ``` # 4 编译 + ## 4.1 安装Wasm工具链Emscripten + 安装步骤可参考其[官方文档](https://emscripten.org/docs/getting_started/downloads.html),目前支持 Windows, MacOS, Linux。 建议版本:1.38.45, 编译运行都没问题。 ## 4.2 下载FFmpeg + ```bash mkdir goldvideo cd goldvideo @@ -76,9 +91,13 @@ git clone https://git.ffmpeg.org/ffmpeg.git cd ffmpeg git checkout -b 4.1 origin/release/4.1 ``` + 这里切到了4.1分支。 + ## 4.3 下载本文的代码 + 保证FFmpeg目录和代码目录平级。 + ```bash git clone http://github.com/goldvideo/decoder_wasm.git cd decoder_wasm @@ -89,8 +108,11 @@ cd decoder_wasm │ ├─ffmpeg │ ├─decoder_wasm ``` + ## 4.4 编译 + 进入代码目录,根据需要,以下命令三选一执行: + ```bash ./build_decoder_264.sh //支持解码 H.264 ./build_decoder_265.sh //支持解码 H.265 @@ -98,7 +120,9 @@ cd decoder_wasm ``` # 5 测试 + ## 5.1 WebGL + H5使用Canvas来绘图,但是默认的2d模式只能绘制RGB格式,使用FFmpeg解码出来的视频数据是YUV格式,想要渲染出来需要进行颜色空间转换,可以使用FFmpeg的libswscale模块进行转换。 为了提升性能,这里使用了WebGL来硬件加速,主要参考了这个项目,做了一些修改: https://github.com/p4prasoon/YUV-Webgl-Video-Player @@ -108,6 +132,7 @@ H5使用Canvas来绘图,但是默认的2d模式只能绘制RGB格式,使用F npm install npm start ``` + ## 5.3 测试页面: ``` @@ -115,6 +140,9 @@ http://localhost:3000/test/main.html ``` # 6 参考项目 + [WasmVideoPlayer](https://github.com/sonysuqin/WasmVideoPlayer). +[https://github.com/goldvideo/decoder_wasm](https://github.com/goldvideo/decoder_wasm "https://github.com/goldvideo/decoder_wasm") + # webrtc_H265player diff --git a/test/h265.js b/test/h265.js index a665de1..a5e436a 100644 --- a/test/h265.js +++ b/test/h265.js @@ -147,6 +147,7 @@ function initH265DC(pc,player) { bWorking=false; }; +} function handleUpdates(canvas, dc) { setInterval(function () { @@ -154,5 +155,5 @@ function handleUpdates(canvas, dc) { dc.send(JSON.stringify({ type: "h265" })); // frame update request } }, 500); -} +}; diff --git a/test/main.html b/test/main.html index 221509d..04a32ac 100644 --- a/test/main.html +++ b/test/main.html @@ -22,7 +22,7 @@
服务器名称: 拉 流 名 称: - 设 备 名 称: + 设 备 名 称: 数 据 发 送:
数 据 接 收:
diff --git a/test/parameter.js b/test/parameter.js index 8cad25d..9b956d0 100644 --- a/test/parameter.js +++ b/test/parameter.js @@ -86,7 +86,7 @@ var ICEServerkvm = [ }, { urls: ["turn:192.168.0.18:3478"], //urls: ["turn:192.168.0.20:3478"], - username: "kvm", + username: "media", credential: "123456" } ];