From a977465dcb7420e683f94c915f0d7e193b09b442 Mon Sep 17 00:00:00 2001 From: Jianjun Zhu Date: Tue, 1 Jun 2021 16:01:51 +0800 Subject: [PATCH 1/9] Add support for WebAssembly build. --- README.md | 3 + talk/owt/BUILD.gn | 10 ++ talk/owt/sdk/wasm/gn/BUILD.gn | 180 +++++++++++++++++++++ talk/owt/sdk/wasm/gn/BUILDCONFIG.gn | 124 ++++++++++++++ talk/owt/sdk/wasm/gn/build_tool_wrapper.py | 76 +++++++++ talk/owt/sdk/wasm/gn/wasm.gni | 156 ++++++++++++++++++ talk/owt/sdk/wasm/gn/wasm_vars.gni | 20 +++ talk/owt/sdk/wasm/main.cc | 16 ++ 8 files changed, 585 insertions(+) create mode 100644 talk/owt/sdk/wasm/gn/BUILD.gn create mode 100644 talk/owt/sdk/wasm/gn/BUILDCONFIG.gn create mode 100644 talk/owt/sdk/wasm/gn/build_tool_wrapper.py create mode 100644 talk/owt/sdk/wasm/gn/wasm.gni create mode 100644 talk/owt/sdk/wasm/gn/wasm_vars.gni create mode 100644 talk/owt/sdk/wasm/main.cc diff --git a/README.md b/README.md index 70142511f..bab25308f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # Open WebRTC Toolkit Native SDK +## About this branch +This branch is working on enabling WebAssembly build. Some WebRTC modules could be used for WebTransport and WebCodecs based streaming. + ## Introduction The Open WebRTC Toolkit(OWT) client SDK for native Windows/Linux/Android/iOS applications is built upon the W3C WebRTC standard to accelerate the development of real time communication applications on these platforms. It supports peer to peer communication, and conference mode communication working with diff --git a/talk/owt/BUILD.gn b/talk/owt/BUILD.gn index da66d208d..386ea89f0 100644 --- a/talk/owt/BUILD.gn +++ b/talk/owt/BUILD.gn @@ -3,6 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 import("//build_overrides/webrtc.gni") +import("//talk/owt/sdk/wasm/gn/wasm.gni") import("//testing/test.gni") # Introduced for using libvpx config files. We only enable libvpx rate @@ -332,6 +333,15 @@ static_library("owt_sdk_p2p") { configs -= [ "//build/config/clang:find_bad_constructs" ] } } + +wasm_lib("owt_wasm") { + name = "owt" + deps = [ "//third_party/webrtc/modules/rtp_rtcp" ] + sources=[ + "sdk/wasm/main.cc", + ] +} + static_library("owt_sdk_conf") { deps = [ ":owt_sdk_base", diff --git a/talk/owt/sdk/wasm/gn/BUILD.gn b/talk/owt/sdk/wasm/gn/BUILD.gn new file mode 100644 index 000000000..cbffd9353 --- /dev/null +++ b/talk/owt/sdk/wasm/gn/BUILD.gn @@ -0,0 +1,180 @@ +# Copyright (C) <2021> Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +# Copyright (C) 2018 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This file is copied from third_party/perfetto/gn/standalone/toolchain/BUILD.gn with modifications. + +import("//build/config/compiler/compiler.gni") +import("wasm.gni") + +template("gcc_like_toolchain") { + toolchain(target_name) { + ar = invoker.ar + cc = invoker.cc + cxx = invoker.cxx + lib_switch = "-l" + lib_dir_switch = "-L" + ld_arg = "" + external_cflags = "" + external_cxxflags = "" + external_ldflags = "" + strip = "" + if (defined(invoker.linker) && invoker.linker != "") { + _invoker_linker = invoker.linker + ld_arg = "-fuse-ld=$_invoker_linker" + } + if (defined(invoker.sysroot) && invoker.sysroot != "") { + _invoker_sysroot = invoker.sysroot + cc = "$cc --sysroot=$_invoker_sysroot" + cxx = "$cxx --sysroot=$_invoker_sysroot" + } + if (defined(invoker.gcc_toolchain) && invoker.gcc_toolchain != "") { + assert(is_clang, "gcc_toolchain can be used only when using clang") + _invoker_gcc_toolchain = invoker.gcc_toolchain + ld_arg = "$ld_arg --gcc-toolchain=$_invoker_gcc_toolchain" + } + if (defined(invoker.external_cflags)) { + external_cflags = invoker.external_cflags + } + if (defined(invoker.external_cxxflags)) { + external_cxxflags = invoker.external_cxxflags + } + if (defined(invoker.external_ldflags)) { + external_ldflags = invoker.external_ldflags + } + if (defined(invoker.strip)) { + strip = invoker.strip + } + + # Object files go in this directory. + object_subdir = "{{target_out_dir}}/{{label_name}}" + + tool("cc") { + depfile = "{{output}}.d" + command = "$cc_wrapper $cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -fno-stack-protector ${external_cflags} -msimd128 -pthread -D__wasm__ -c {{source}} -o {{output}}" + depsformat = "gcc" + outputs = [ "$object_subdir/{{source_name_part}}.o" ] + description = "compile {{source}}" + } + + tool("cxx") { + depfile = "{{output}}.d" + command = "$cc_wrapper $cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} -fno-stack-protector ${external_cflags} -msimd128 -pthread -D__wasm__ ${external_cxxflags} -c {{source}} -o {{output}}" + depsformat = "gcc" + outputs = [ "$object_subdir/{{source_name_part}}.o" ] + description = "compile {{source}}" + } + + tool("asm") { + depfile = "{{output}}.d" + command = "$cc_wrapper $cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{asmflags}} -fno-stack-protector -c {{source}} -o {{output}}" + depsformat = "gcc" + outputs = [ "$object_subdir/{{source_name_part}}.o" ] + description = "assemble {{source}}" + } + + tool("alink") { + if (current_os == "aix") { + # AIX does not support either -D (deterministic output) or response + # files. + command = "$ar -X64 {{arflags}} -r -c -s {{output}} {{inputs}}" + } else { + rspfile = "{{output}}.rsp" + rspfile_content = "{{inputs}}" + command = "$ar {{arflags}} -r -c -s -D {{output}} @\"$rspfile\"" + } + + # Remove the output file first so that ar doesn't try to modify the + # existing file. + if (host_os == "win") { + tool_wrapper_path = + rebase_path("//build/toolchain/win/tool_wrapper.py", root_build_dir) + command = "cmd /c $python_path $tool_wrapper_path delete-file {{output}} && $command" + } else { + command = "rm -f {{output}} && $command" + } + + # Almost all targets build with //build/config/compiler:thin_archive which + # adds -T to arflags. + description = "AR {{output}}" + outputs = [ "{{output_dir}}/{{target_output_name}}{{output_extension}}" ] + + # Shared libraries go in the target out directory by default so we can + # generate different targets with the same name and not have them collide. + default_output_dir = "{{target_out_dir}}" + default_output_extension = ".a" + output_prefix = "lib" + } + + tool("solink") { + soname = "{{target_output_name}}{{output_extension}}" + unstripped_so = "{{root_out_dir}}/$soname" + rpath = "-Wl,-soname,$soname" + if (is_mac) { + rpath = "-Wl,-install_name,@rpath/$soname" + } + command = "$cc_wrapper $cxx $ld_arg -shared ${external_ldflags} -fstack-protector {{inputs}} {{solibs}} {{libs}} $rpath -o $unstripped_so" + outputs = [ unstripped_so ] + output_prefix = "lib" + default_output_extension = ".so" + description = "link $unstripped_so" + if (strip != "") { + stripped_so = "{{root_out_dir}}/stripped/$soname" + outputs += [ stripped_so ] + command += " && $strip -o $stripped_so $unstripped_so" + } + } + + tool("link") { + unstripped_exe = + "{{root_out_dir}}/{{target_output_name}}{{output_extension}}" + command = "$cc_wrapper $cxx $ld_arg ${external_ldflags} {{inputs}} {{solibs}} {{libs}} -o $unstripped_exe" + outputs = [ unstripped_exe ] + description = "link $unstripped_exe" + if (strip != "") { + stripped_exe = "{{root_out_dir}}/stripped/{{target_output_name}}{{output_extension}}" + outputs += [ stripped_exe ] + command += " && $strip -o $stripped_exe $unstripped_exe" + } + } + + tool("stamp") { + command = "touch {{output}}" + description = "stamp {{output}}" + } + + tool("copy") { + command = "cp -af {{source}} {{output}}" + description = "COPY {{source}} {{output}}" + } + + toolchain_args = { + current_cpu = invoker.cpu + current_os = invoker.os + } + } +} + +gcc_like_toolchain("wasm") { + # emsdk_dir and em_config are defined in wasm.gni. + cpu = host_cpu + os = host_os + ar = "emar --em-config $em_config" + cc = "emcc --em-config $em_config" + cxx = "em++ --em-config $em_config" + strip = "" +} diff --git a/talk/owt/sdk/wasm/gn/BUILDCONFIG.gn b/talk/owt/sdk/wasm/gn/BUILDCONFIG.gn new file mode 100644 index 000000000..6f32686c1 --- /dev/null +++ b/talk/owt/sdk/wasm/gn/BUILDCONFIG.gn @@ -0,0 +1,124 @@ +# Copyright (C) 2017 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +declare_args() { + is_debug = true + is_clang = true + is_system_compiler = false + is_lto = false + + # This is defined here because it's needed below for determining the value of + # |is_cross_compiling|. + target_triplet = "" +} + +# Platform detection +if (target_os == "") { + target_os = host_os +} +if (current_os == "") { + current_os = target_os +} + +is_android = current_os == "android" +is_chromeos = current_os == "chromeos" +is_linux = current_os == "linux" +is_linux_host = host_os == "linux" +is_mac = current_os == "mac" +is_mac_host = host_os == "mac" +is_win = current_os == "win" +is_win_host = host_os == "win" + +# Building with Windows/Fuchsia/nacl is currently only supported in the Chromium +# tree so always set this to false. +is_fuchsia = false +is_nacl = false + +if (target_cpu == "") { + target_cpu = host_cpu + if (is_android) { + target_cpu = "arm" + } +} +if (current_cpu == "") { + current_cpu = target_cpu +} + +declare_args() { + # the ossfuzz sanitizer overrides this to true. In that config the + # host/target cpu and arch are identical, but we want to build only the + # targets with the sanitizer/fuzzer flags + is_cross_compiling = + target_cpu != host_cpu || target_os != host_os || target_triplet != "" +} +default_configs = [ + "//gn/standalone:debug_symbols", + "//gn/standalone:default", + "//gn/standalone:c++11", + "//gn/standalone:extra_warnings", + "//gn/standalone:no_exceptions", + "//gn/standalone:no_rtti", + "//gn/standalone:visibility_hidden", + "//gn/standalone/libc++:config", + "//gn/standalone/sanitizers:sanitizers_cflags", +] + +if (is_win) { + default_configs += [ "//gn/standalone:win32_lean_and_mean" ] +} + +if (!is_debug) { + default_configs -= [ "//gn/standalone:debug_symbols" ] + default_configs += [ "//gn/standalone:release" ] +} + +set_defaults("source_set") { + configs = default_configs +} + +set_defaults("static_library") { + configs = default_configs +} + +# Realistically the only shared_library that we build right now is libc++.so +# when use_custom_libcxx=true (on Linux). Hence don't add a dependency on +# libc++ itself on these targets. +set_defaults("shared_library") { + configs = default_configs + configs += [ "//gn/standalone:shared_library" ] + + # note: the following is not a nested config to be removable. + configs += [ "//gn/standalone:android_liblog" ] +} + +set_defaults("executable") { + configs = default_configs + configs += [ "//gn/standalone:executable" ] + + # note: the following is not a nested config to be removable. + configs += [ "//gn/standalone:android_liblog" ] +} + +if (is_win) { + _default_toolchain = "//gn/standalone/toolchain:msvc" +} else { + _default_toolchain = "//gn/standalone/toolchain:gcc_like" +} +set_default_toolchain(_default_toolchain) + +if (is_cross_compiling) { + host_toolchain = "//gn/standalone/toolchain:gcc_like_host" +} else { + host_toolchain = _default_toolchain +} diff --git a/talk/owt/sdk/wasm/gn/build_tool_wrapper.py b/talk/owt/sdk/wasm/gn/build_tool_wrapper.py new file mode 100644 index 000000000..e1abe197f --- /dev/null +++ b/talk/owt/sdk/wasm/gn/build_tool_wrapper.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python +# Copyright (C) 2017 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" Wrapper to invoke compiled build tools from the build system. + +This is just a workaround for GN assuming that all external scripts are +python sources. It is used to invoke tools like the protoc compiler. +""" + +from __future__ import print_function + +import argparse +import os +import subprocess +import sys + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--chdir', default=None) + parser.add_argument('--stamp', default=None) + parser.add_argument('--path', default=None) + parser.add_argument('--noop', default=False, action='store_true') + parser.add_argument('--suppress_stdout', default=False, action='store_true') + parser.add_argument('--suppress_stderr', default=False, action='store_true') + parser.add_argument('cmd', nargs=argparse.REMAINDER) + args = parser.parse_args() + + if args.noop: + return 0 + + if args.chdir and not os.path.exists(args.chdir): + print( + 'Cannot chdir to %s from %s' % (workdir, os.getcwd()), file=sys.stderr) + return 1 + + exe = os.path.abspath(args.cmd[0]) if os.sep in args.cmd[0] else args.cmd[0] + env = os.environ.copy() + if args.path: + env['PATH'] = os.path.abspath(args.path) + os.pathsep + env['PATH'] + + devnull = open(os.devnull, 'wb') + stdout = devnull if args.suppress_stdout else None + stderr = devnull if args.suppress_stderr else None + + try: + proc = subprocess.Popen( + [exe] + args.cmd[1:], + cwd=args.chdir, + env=env, + stderr=stderr, + stdout=stdout) + ret = proc.wait() + if ret == 0 and args.stamp: + with open(args.stamp, 'w'): + os.utime(args.stamp, None) + return ret + except OSError as e: + print('Error running: "%s" (%s)' % (args.cmd[0], e.strerror)) + print('PATH=%s' % env.get('PATH')) + return 127 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/talk/owt/sdk/wasm/gn/wasm.gni b/talk/owt/sdk/wasm/gn/wasm.gni new file mode 100644 index 000000000..370ae68a4 --- /dev/null +++ b/talk/owt/sdk/wasm/gn/wasm.gni @@ -0,0 +1,156 @@ +# Copyright (C) <2021> Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +# Copyright (C) 2018 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This file is copied from https://source.chromium.org/chromium/chromium/src/+/main:third_party/perfetto/gn/standalone/wasm.gni. + +import("//build_overrides/build.gni") +import("wasm_vars.gni") + +# Used by //gn/standalone/toolchain/BUILD.gn . +em_config = rebase_path("/home/jianjunz/code/emsdk/.emscripten", "") +emsdk_dir = rebase_path("//buildtools/linux64/emsdk", "") + +# Defines a WASM library target. +# Args: +# generate_js: when true generates a .wasm file and a .js file that wraps it +# and provides the boilerplate to initialize the module. +# generate_html: when true generates also an example .html file which contains +# a minimal console to interact with the module (useful for testing). +template("wasm_lib") { + assert(defined(invoker.name)) + + # If the name is foo the target_name must be foo_wasm. + assert(invoker.name + "_wasm" == target_name) + _lib_name = invoker.name + if (is_wasm) { + _exports = "['ccall', 'callMain', 'addFunction', 'FS']" + _target_ldflags = [ + "-s", + "WASM=1", + "-s", + "DISABLE_EXCEPTION_CATCHING=1", + "-s", + "NO_DYNAMIC_EXECUTION=1", + "-s", + "INITIAL_MEMORY=33554432", + "-s", + "ALLOW_MEMORY_GROWTH=1", + "-s", + "ALLOW_TABLE_GROWTH=1", + "-s", + "WASM_ASYNC_COMPILATION=0", + "-s", + "EXTRA_EXPORTED_RUNTIME_METHODS=" + _exports, + + # This forces the MEMFS filesystem library to always use typed arrays + # instead of building strings/arrays when appending to a file. This allows + # to deal with pseudo-files larger than 128 MB when calling trace_to_text. + "-s", + "MEMFS_APPEND_TO_TYPED_ARRAYS=1", + + # Reduces global namespace pollution. + "-s", + "MODULARIZE=1", + + "-fno-stack-protector", + + # This is to prevent that two different wasm modules end up generating + # JS that overrides the same global variable (var Module = ...) + "-s", + "EXPORT_NAME=${target_name}", + + "-lworkerfs.js", # For FS.filesystems.WORKERFS + ] + if (is_debug) { + _target_ldflags += [ + "-s", + "ASSERTIONS=2", + "-s", + "SAFE_HEAP=1", + "-s", + "STACK_OVERFLOW_CHECK=1", + "-g4", + "-O0", + ] + } else { + _target_ldflags += [ + "-s", + "ASSERTIONS=1", + "-g2", # Required for getting C++ symbol names. + "-O3", + ] + } + + if (defined(invoker.js_library)) { + _target_ldflags += [ + "--js-library", + invoker.js_library, + ] + } + + _target_cflags = ["-fno-stack-protector"] + if(defined(invoker.cflags)){ + _target_cflags+=invoker.cflags + } + + _vars_to_forward = [ + #"cflags", + "defines", + "deps", + "includes", + "sources", + "include_dirs", + "public_configs", + "testonly", + "visibility", + ] + + executable("${_lib_name}.js") { + forward_variables_from(invoker, _vars_to_forward) + # Fix ldflags. + ldflags = _target_ldflags + cflags = _target_cflags + output_extension = "" + } + + # This is just a workaround to deal with the fact that GN doesn't allow + # spcifying extra outputs for an executable() target. In reality the .wasm + # file here is generated by the executable() target above, together with the + # .js file. This dummy target is here to tell GN "there is a target that + # outputs also the .wasm file", so we can depend on that in copy() targets. + action("${_lib_name}.wasm") { + inputs = [] + deps = [ ":${_lib_name}.js" ] + outputs = [ "$root_out_dir/$_lib_name.wasm" ] + if (is_debug) { + outputs += [ "$root_out_dir/$_lib_name.wasm.map" ] + } + args = [ "--noop" ] + script = "//talk/owt/sdk/wasm/gn/build_tool_wrapper.py" + } + } else { # is_wasm + not_needed(invoker, "*") + } + + group(target_name) { + deps = [ + ":${_lib_name}.js($wasm_toolchain)", + ":${_lib_name}.wasm($wasm_toolchain)", + ] + } +} # template \ No newline at end of file diff --git a/talk/owt/sdk/wasm/gn/wasm_vars.gni b/talk/owt/sdk/wasm/gn/wasm_vars.gni new file mode 100644 index 000000000..7767b4f66 --- /dev/null +++ b/talk/owt/sdk/wasm/gn/wasm_vars.gni @@ -0,0 +1,20 @@ +# Copyright (C) <2021> Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +# Copyright (C) 2018 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +wasm_toolchain = "//talk/owt/sdk/wasm/gn:wasm" +is_wasm = current_toolchain == wasm_toolchain \ No newline at end of file diff --git a/talk/owt/sdk/wasm/main.cc b/talk/owt/sdk/wasm/main.cc new file mode 100644 index 000000000..5404fd344 --- /dev/null +++ b/talk/owt/sdk/wasm/main.cc @@ -0,0 +1,16 @@ +// Copyright (C) <2021> Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 + +#include +#include "third_party/webrtc/rtc_base/strings/json.h" + +int main(int argc, char** argv) { + Json::Value in_s("foo"); + std::string out; + rtc::GetStringFromJson(in_s, &out); + std::cout< Date: Fri, 4 Jun 2021 14:53:07 +0800 Subject: [PATCH 2/9] Enable rtp_rtcp WASM build. --- talk/owt/BUILD.gn | 22 +++-- talk/owt/sdk/wasm/gn/BUILD.gn | 10 +-- talk/owt/sdk/wasm/gn/BUILDCONFIG.gn | 124 ---------------------------- talk/owt/sdk/wasm/gn/wasm.gni | 2 +- talk/owt/sdk/wasm/gn/wasm_vars.gni | 2 +- 5 files changed, 20 insertions(+), 140 deletions(-) delete mode 100644 talk/owt/sdk/wasm/gn/BUILDCONFIG.gn diff --git a/talk/owt/BUILD.gn b/talk/owt/BUILD.gn index 386ea89f0..8cba4f9f3 100644 --- a/talk/owt/BUILD.gn +++ b/talk/owt/BUILD.gn @@ -295,7 +295,7 @@ static_library("owt_sdk_base") { "sdk/base/customizedaudiodevicemodule.h", ] } - if (is_clang) { + if (is_clang && !is_wasm) { configs -= [ "//build/config/clang:find_bad_constructs" ] } if (is_win && is_clang) { @@ -329,17 +329,21 @@ static_library("owt_sdk_p2p") { "sdk/p2p/p2psignalingsenderimpl.cc", "sdk/p2p/p2psignalingsenderimpl.h", ] - if (is_clang) { + if (is_clang && !is_wasm) { configs -= [ "//build/config/clang:find_bad_constructs" ] } } -wasm_lib("owt_wasm") { - name = "owt" - deps = [ "//third_party/webrtc/modules/rtp_rtcp" ] - sources=[ - "sdk/wasm/main.cc", - ] +if (is_wasm) { + wasm_lib("owt_wasm") { + name = "owt" + deps = [ + "//third_party/webrtc/modules/rtp_rtcp:rtp_rtcp", + "//third_party/webrtc/rtc_base:rtc_json", + "//third_party/boringssl", + ] + sources = [ "sdk/wasm/main.cc" ] + } } static_library("owt_sdk_conf") { @@ -366,7 +370,7 @@ static_library("owt_sdk_conf") { "sdk/include/cpp/owt/conference/remotemixedstream.h", "sdk/include/cpp/owt/conference/user.h", ] - if (is_clang) { + if (is_clang && !is_wasm) { configs -= [ "//build/config/clang:find_bad_constructs" ] } diff --git a/talk/owt/sdk/wasm/gn/BUILD.gn b/talk/owt/sdk/wasm/gn/BUILD.gn index cbffd9353..5964d3576 100644 --- a/talk/owt/sdk/wasm/gn/BUILD.gn +++ b/talk/owt/sdk/wasm/gn/BUILD.gn @@ -65,7 +65,7 @@ template("gcc_like_toolchain") { tool("cc") { depfile = "{{output}}.d" - command = "$cc_wrapper $cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -fno-stack-protector ${external_cflags} -msimd128 -pthread -D__wasm__ -c {{source}} -o {{output}}" + command = "$cc_wrapper $cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -fno-stack-protector ${external_cflags} -c {{source}} -o {{output}}" depsformat = "gcc" outputs = [ "$object_subdir/{{source_name_part}}.o" ] description = "compile {{source}}" @@ -73,7 +73,7 @@ template("gcc_like_toolchain") { tool("cxx") { depfile = "{{output}}.d" - command = "$cc_wrapper $cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} -fno-stack-protector ${external_cflags} -msimd128 -pthread -D__wasm__ ${external_cxxflags} -c {{source}} -o {{output}}" + command = "$cc_wrapper $cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} -fno-stack-protector ${external_cflags} ${external_cxxflags} -c {{source}} -o {{output}}" depsformat = "gcc" outputs = [ "$object_subdir/{{source_name_part}}.o" ] description = "compile {{source}}" @@ -173,8 +173,8 @@ gcc_like_toolchain("wasm") { # emsdk_dir and em_config are defined in wasm.gni. cpu = host_cpu os = host_os - ar = "emar --em-config $em_config" - cc = "emcc --em-config $em_config" - cxx = "em++ --em-config $em_config" + ar = "$emsdk_dir/emscripten/emar --em-config $em_config" + cc = "$emsdk_dir/emscripten/emcc --em-config $em_config" + cxx = "$emsdk_dir/emscripten/em++ --em-config $em_config" strip = "" } diff --git a/talk/owt/sdk/wasm/gn/BUILDCONFIG.gn b/talk/owt/sdk/wasm/gn/BUILDCONFIG.gn deleted file mode 100644 index 6f32686c1..000000000 --- a/talk/owt/sdk/wasm/gn/BUILDCONFIG.gn +++ /dev/null @@ -1,124 +0,0 @@ -# Copyright (C) 2017 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -declare_args() { - is_debug = true - is_clang = true - is_system_compiler = false - is_lto = false - - # This is defined here because it's needed below for determining the value of - # |is_cross_compiling|. - target_triplet = "" -} - -# Platform detection -if (target_os == "") { - target_os = host_os -} -if (current_os == "") { - current_os = target_os -} - -is_android = current_os == "android" -is_chromeos = current_os == "chromeos" -is_linux = current_os == "linux" -is_linux_host = host_os == "linux" -is_mac = current_os == "mac" -is_mac_host = host_os == "mac" -is_win = current_os == "win" -is_win_host = host_os == "win" - -# Building with Windows/Fuchsia/nacl is currently only supported in the Chromium -# tree so always set this to false. -is_fuchsia = false -is_nacl = false - -if (target_cpu == "") { - target_cpu = host_cpu - if (is_android) { - target_cpu = "arm" - } -} -if (current_cpu == "") { - current_cpu = target_cpu -} - -declare_args() { - # the ossfuzz sanitizer overrides this to true. In that config the - # host/target cpu and arch are identical, but we want to build only the - # targets with the sanitizer/fuzzer flags - is_cross_compiling = - target_cpu != host_cpu || target_os != host_os || target_triplet != "" -} -default_configs = [ - "//gn/standalone:debug_symbols", - "//gn/standalone:default", - "//gn/standalone:c++11", - "//gn/standalone:extra_warnings", - "//gn/standalone:no_exceptions", - "//gn/standalone:no_rtti", - "//gn/standalone:visibility_hidden", - "//gn/standalone/libc++:config", - "//gn/standalone/sanitizers:sanitizers_cflags", -] - -if (is_win) { - default_configs += [ "//gn/standalone:win32_lean_and_mean" ] -} - -if (!is_debug) { - default_configs -= [ "//gn/standalone:debug_symbols" ] - default_configs += [ "//gn/standalone:release" ] -} - -set_defaults("source_set") { - configs = default_configs -} - -set_defaults("static_library") { - configs = default_configs -} - -# Realistically the only shared_library that we build right now is libc++.so -# when use_custom_libcxx=true (on Linux). Hence don't add a dependency on -# libc++ itself on these targets. -set_defaults("shared_library") { - configs = default_configs - configs += [ "//gn/standalone:shared_library" ] - - # note: the following is not a nested config to be removable. - configs += [ "//gn/standalone:android_liblog" ] -} - -set_defaults("executable") { - configs = default_configs - configs += [ "//gn/standalone:executable" ] - - # note: the following is not a nested config to be removable. - configs += [ "//gn/standalone:android_liblog" ] -} - -if (is_win) { - _default_toolchain = "//gn/standalone/toolchain:msvc" -} else { - _default_toolchain = "//gn/standalone/toolchain:gcc_like" -} -set_default_toolchain(_default_toolchain) - -if (is_cross_compiling) { - host_toolchain = "//gn/standalone/toolchain:gcc_like_host" -} else { - host_toolchain = _default_toolchain -} diff --git a/talk/owt/sdk/wasm/gn/wasm.gni b/talk/owt/sdk/wasm/gn/wasm.gni index 370ae68a4..84e6576f9 100644 --- a/talk/owt/sdk/wasm/gn/wasm.gni +++ b/talk/owt/sdk/wasm/gn/wasm.gni @@ -23,7 +23,7 @@ import("wasm_vars.gni") # Used by //gn/standalone/toolchain/BUILD.gn . em_config = rebase_path("/home/jianjunz/code/emsdk/.emscripten", "") -emsdk_dir = rebase_path("//buildtools/linux64/emsdk", "") +emsdk_dir = rebase_path("/home/jianjunz/code/emsdk/upstream", "") # Defines a WASM library target. # Args: diff --git a/talk/owt/sdk/wasm/gn/wasm_vars.gni b/talk/owt/sdk/wasm/gn/wasm_vars.gni index 7767b4f66..d3ee3ed29 100644 --- a/talk/owt/sdk/wasm/gn/wasm_vars.gni +++ b/talk/owt/sdk/wasm/gn/wasm_vars.gni @@ -17,4 +17,4 @@ # limitations under the License. wasm_toolchain = "//talk/owt/sdk/wasm/gn:wasm" -is_wasm = current_toolchain == wasm_toolchain \ No newline at end of file +# is_wasm = current_toolchain == wasm_toolchain \ No newline at end of file From 0490093cb037ec54405fbeeac7b1d38f2ab707c9 Mon Sep 17 00:00:00 2001 From: Jianjun Zhu Date: Mon, 13 Sep 2021 10:33:52 +0800 Subject: [PATCH 3/9] Add some API for C++/JavaScript interop. --- talk/owt/BUILD.gn | 78 ++++++++++++---------- talk/owt/sdk/wasm/binding.h | 24 +++++++ talk/owt/sdk/wasm/gn/BUILD.gn | 8 +-- talk/owt/sdk/wasm/gn/wasm.gni | 22 ++++-- talk/owt/sdk/wasm/main.cc | 4 +- talk/owt/sdk/wasm/media_session.cc | 32 +++++++++ talk/owt/sdk/wasm/media_session.h | 30 +++++++++ talk/owt/sdk/wasm/rtp_video_receiver.cc | 23 +++++++ talk/owt/sdk/wasm/rtp_video_receiver.h | 26 ++++++++ talk/owt/sdk/wasm/web_transport_session.cc | 20 ++++++ talk/owt/sdk/wasm/web_transport_session.h | 26 ++++++++ 11 files changed, 246 insertions(+), 47 deletions(-) create mode 100644 talk/owt/sdk/wasm/binding.h create mode 100644 talk/owt/sdk/wasm/media_session.cc create mode 100644 talk/owt/sdk/wasm/media_session.h create mode 100644 talk/owt/sdk/wasm/rtp_video_receiver.cc create mode 100644 talk/owt/sdk/wasm/rtp_video_receiver.h create mode 100644 talk/owt/sdk/wasm/web_transport_session.cc create mode 100644 talk/owt/sdk/wasm/web_transport_session.h diff --git a/talk/owt/BUILD.gn b/talk/owt/BUILD.gn index 8cba4f9f3..e10e9479c 100644 --- a/talk/owt/BUILD.gn +++ b/talk/owt/BUILD.gn @@ -9,18 +9,17 @@ import("//testing/test.gni") # Introduced for using libvpx config files. We only enable libvpx rate # controller for VP9 on Windows. if (is_win) { - - if (current_cpu == "x86") { - cpu_arch_full = "ia32" - } else if (current_cpu == "x64") { - cpu_arch_full = "x64" - } else if (current_cpu == "arm") { - if (arm_use_neon) { - cpu_arch_full = "arm-neon" - } else { - cpu_arch_full = "arm" - } - } + if (current_cpu == "x86") { + cpu_arch_full = "ia32" + } else if (current_cpu == "x64") { + cpu_arch_full = "x64" + } else if (current_cpu == "arm") { + if (arm_use_neon) { + cpu_arch_full = "arm-neon" + } else { + cpu_arch_full = "arm" + } + } } if (is_android) { @@ -182,10 +181,10 @@ static_library("owt_sdk_base") { sources += [ "sdk/base/win/base_allocator.cc", "sdk/base/win/base_allocator.h", - "sdk/base/win/d3d_allocator.cc", - "sdk/base/win/d3d_allocator.h", "sdk/base/win/d3d11_allocator.cc", "sdk/base/win/d3d11_allocator.h", + "sdk/base/win/d3d_allocator.cc", + "sdk/base/win/d3d_allocator.h", "sdk/base/win/d3dnativeframe.h", "sdk/base/win/mediacapabilities.cc", "sdk/base/win/mediacapabilities.h", @@ -201,9 +200,9 @@ static_library("owt_sdk_base") { "sdk/base/win/msdkvideoencoderfactory.h", "sdk/base/win/sysmem_allocator.cc", "sdk/base/win/sysmem_allocator.h", - "sdk/base/win/vpedefs.h", "sdk/base/win/vp9ratecontrol.cc", "sdk/base/win/vp9ratecontrol.h", + "sdk/base/win/vpedefs.h", ] public_deps += [ "//third_party/libvpx" ] include_dirs += [ @@ -225,7 +224,7 @@ static_library("owt_sdk_base") { } else { defines += [ "OWT_USE_H265" ] } - + if (owt_use_quic) { defines += [ "OWT_ENABLE_QUIC" ] if (owt_quic_header_root != "") { @@ -243,39 +242,38 @@ static_library("owt_sdk_base") { sources += [ "sdk/base/desktopcapturer.cc", "sdk/base/desktopcapturer.h", - "sdk/base/win/videorendererwin.cc", - "sdk/base/win/videorendererwin.h", - "sdk/base/win/videorendererd3d11.cc", - "sdk/base/win/videorendererd3d11.h", "sdk/base/win/d3d11_manager.h", - "sdk/base/win/device_info_mf.h", "sdk/base/win/device_info_mf.cc", - "sdk/base/win/video_capture_mf.h", + "sdk/base/win/device_info_mf.h", "sdk/base/win/video_capture_mf.cc", + "sdk/base/win/video_capture_mf.h", + "sdk/base/win/videorendererd3d11.cc", + "sdk/base/win/videorendererd3d11.h", + "sdk/base/win/videorendererwin.cc", + "sdk/base/win/videorendererwin.h", ] public_deps += [ "//third_party/webrtc/modules/audio_device:audio_device_module_from_input_and_output" ] - } if (is_linux) { if (owt_msdk_header_root != "") { include_dirs += [ owt_msdk_header_root ] defines += [ "OWT_USE_MSDK" ] sources += [ - "sdk/base/linux/displayutils.cc", - "sdk/base/linux/displayutils.h", "sdk/base/linux/base_allocator.cc", "sdk/base/linux/base_allocator.h", - "sdk/base/linux/vaapi_allocator.cc", - "sdk/base/linux/vaapi_allocator.h", - "sdk/base/linux/msdkvideosession.cc", - "sdk/base/linux/msdkvideosession.h", - "sdk/base/linux/msdkvideodecoderfactory.cc", - "sdk/base/linux/msdkvideodecoderfactory.h", + "sdk/base/linux/displayutils.cc", + "sdk/base/linux/displayutils.h", "sdk/base/linux/msdkvideodecoder.cc", "sdk/base/linux/msdkvideodecoder.h", - "sdk/base/linux/xwindownativeframe.h", + "sdk/base/linux/msdkvideodecoderfactory.cc", + "sdk/base/linux/msdkvideodecoderfactory.h", + "sdk/base/linux/msdkvideosession.cc", + "sdk/base/linux/msdkvideosession.h", + "sdk/base/linux/vaapi_allocator.cc", + "sdk/base/linux/vaapi_allocator.h", "sdk/base/linux/videorenderlinux.cc", "sdk/base/linux/videorenderlinux.h", + "sdk/base/linux/xwindownativeframe.h", ] } } @@ -287,7 +285,7 @@ static_library("owt_sdk_base") { "sdk/base/customizedvideodecoderproxy.h", ] } - if ((is_win || is_linux)) { + if (is_win || is_linux) { sources += [ "sdk/base/customizedaudiocapturer.cc", "sdk/base/customizedaudiocapturer.h", @@ -338,11 +336,21 @@ if (is_wasm) { wasm_lib("owt_wasm") { name = "owt" deps = [ + "//third_party/boringssl", + "//third_party/webrtc/call", "//third_party/webrtc/modules/rtp_rtcp:rtp_rtcp", "//third_party/webrtc/rtc_base:rtc_json", - "//third_party/boringssl", ] - sources = [ "sdk/wasm/main.cc" ] + sources = [ + "sdk/wasm/binding.h", + "sdk/wasm/main.cc", + "sdk/wasm/media_session.cc", + "sdk/wasm/media_session.h", + "sdk/wasm/rtp_video_receiver.cc", + "sdk/wasm/rtp_video_receiver.h", + "sdk/wasm/web_transport_session.cc", + "sdk/wasm/web_transport_session.h", + ] } } diff --git a/talk/owt/sdk/wasm/binding.h b/talk/owt/sdk/wasm/binding.h new file mode 100644 index 000000000..e6e242c3d --- /dev/null +++ b/talk/owt/sdk/wasm/binding.h @@ -0,0 +1,24 @@ +// Copyright (C) <2021> Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 + +#ifndef OWT_WASM_BINDING_H_ +#define OWT_WASM_BINDING_H_ + +#include +#include "talk/owt/sdk/wasm/media_session.h" +#include "talk/owt/sdk/wasm/rtp_video_receiver.h" + +namespace owt { +namespace wasm { + +EMSCRIPTEN_BINDINGS(Owt) { + emscripten::class_("MediaSession").constructor<>(); + emscripten::class_("RtpVideoReceiver") + .function("onRtpPacket", &RtpVideoReceiver::OnRtpPacket); +} + +} // namespace wasm +} // namespace owt + +#endif \ No newline at end of file diff --git a/talk/owt/sdk/wasm/gn/BUILD.gn b/talk/owt/sdk/wasm/gn/BUILD.gn index 5964d3576..08eaeff63 100644 --- a/talk/owt/sdk/wasm/gn/BUILD.gn +++ b/talk/owt/sdk/wasm/gn/BUILD.gn @@ -65,7 +65,7 @@ template("gcc_like_toolchain") { tool("cc") { depfile = "{{output}}.d" - command = "$cc_wrapper $cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -fno-stack-protector ${external_cflags} -c {{source}} -o {{output}}" + command = "$cc_wrapper $cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0 --bind -fno-stack-protector ${external_cflags} -c {{source}} -o {{output}}" depsformat = "gcc" outputs = [ "$object_subdir/{{source_name_part}}.o" ] description = "compile {{source}}" @@ -73,7 +73,7 @@ template("gcc_like_toolchain") { tool("cxx") { depfile = "{{output}}.d" - command = "$cc_wrapper $cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} -fno-stack-protector ${external_cflags} ${external_cxxflags} -c {{source}} -o {{output}}" + command = "$cc_wrapper $cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0 --bind -fno-stack-protector ${external_cflags} ${external_cxxflags} -c {{source}} -o {{output}}" depsformat = "gcc" outputs = [ "$object_subdir/{{source_name_part}}.o" ] description = "compile {{source}}" @@ -81,7 +81,7 @@ template("gcc_like_toolchain") { tool("asm") { depfile = "{{output}}.d" - command = "$cc_wrapper $cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{asmflags}} -fno-stack-protector -c {{source}} -o {{output}}" + command = "$cc_wrapper $cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{asmflags}} -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0 --bind -fno-stack-protector -c {{source}} -o {{output}}" depsformat = "gcc" outputs = [ "$object_subdir/{{source_name_part}}.o" ] description = "assemble {{source}}" @@ -175,6 +175,6 @@ gcc_like_toolchain("wasm") { os = host_os ar = "$emsdk_dir/emscripten/emar --em-config $em_config" cc = "$emsdk_dir/emscripten/emcc --em-config $em_config" - cxx = "$emsdk_dir/emscripten/em++ --em-config $em_config" + cxx = "$emsdk_dir/emscripten/em++ --em-config $em_config --bind -s USE_PTHREADS=1" strip = "" } diff --git a/talk/owt/sdk/wasm/gn/wasm.gni b/talk/owt/sdk/wasm/gn/wasm.gni index 84e6576f9..aee71a635 100644 --- a/talk/owt/sdk/wasm/gn/wasm.gni +++ b/talk/owt/sdk/wasm/gn/wasm.gni @@ -49,12 +49,14 @@ template("wasm_lib") { "-s", "INITIAL_MEMORY=33554432", "-s", - "ALLOW_MEMORY_GROWTH=1", - "-s", "ALLOW_TABLE_GROWTH=1", "-s", "WASM_ASYNC_COMPILATION=0", "-s", + "USE_PTHREADS=1", + "-s", + "LLD_REPORT_UNDEFINED", + "-s", "EXTRA_EXPORTED_RUNTIME_METHODS=" + _exports, # This forces the MEMFS filesystem library to always use typed arrays @@ -75,6 +77,8 @@ template("wasm_lib") { "EXPORT_NAME=${target_name}", "-lworkerfs.js", # For FS.filesystems.WORKERFS + + "--bind", ] if (is_debug) { _target_ldflags += [ @@ -84,7 +88,7 @@ template("wasm_lib") { "SAFE_HEAP=1", "-s", "STACK_OVERFLOW_CHECK=1", - "-g4", + "-gsource-map", "-O0", ] } else { @@ -103,9 +107,12 @@ template("wasm_lib") { ] } - _target_cflags = ["-fno-stack-protector"] - if(defined(invoker.cflags)){ - _target_cflags+=invoker.cflags + _target_cflags = [ + "-fno-stack-protector", + "-pthread", + ] + if (defined(invoker.cflags)) { + _target_cflags += invoker.cflags } _vars_to_forward = [ @@ -122,6 +129,7 @@ template("wasm_lib") { executable("${_lib_name}.js") { forward_variables_from(invoker, _vars_to_forward) + # Fix ldflags. ldflags = _target_ldflags cflags = _target_cflags @@ -153,4 +161,4 @@ template("wasm_lib") { ":${_lib_name}.wasm($wasm_toolchain)", ] } -} # template \ No newline at end of file +} # template diff --git a/talk/owt/sdk/wasm/main.cc b/talk/owt/sdk/wasm/main.cc index 5404fd344..a36521c3d 100644 --- a/talk/owt/sdk/wasm/main.cc +++ b/talk/owt/sdk/wasm/main.cc @@ -2,14 +2,16 @@ // // SPDX-License-Identifier: Apache-2.0 +#include #include #include "third_party/webrtc/rtc_base/strings/json.h" +#include "talk/owt/sdk/wasm/binding.h" int main(int argc, char** argv) { Json::Value in_s("foo"); std::string out; rtc::GetStringFromJson(in_s, &out); - std::cout< Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 + +#include "talk/owt/sdk/wasm/media_session.h" + +namespace owt { +namespace wasm { +MediaSession::MediaSession() + : call_(std::unique_ptr( + webrtc::Call::Create(webrtc::Call::Config(nullptr)))), + video_receiver_(nullptr) {} + +MediaSession::~MediaSession() {} + +RtpVideoReceiver* MediaSession::CreateRtpVideoReceiver() { + webrtc::VideoReceiveStream::Config config(web_transport_session_.get()); + webrtc::TaskQueueBase* task_queue = webrtc::TaskQueueBase::Current(); + if (!task_queue) { + task_queue = rtc::ThreadManager::Instance()->CurrentThread(); + } + std::unique_ptr receiver = + std::make_unique( + task_queue, webrtc::Clock::GetRealTimeClock(), + web_transport_session_.get(), nullptr, nullptr, &config, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr); + video_receiver_ = std::make_unique(std::move(receiver)); + return video_receiver_.get(); +} +} // namespace wasm +} // namespace owt \ No newline at end of file diff --git a/talk/owt/sdk/wasm/media_session.h b/talk/owt/sdk/wasm/media_session.h new file mode 100644 index 000000000..e3ab6b45a --- /dev/null +++ b/talk/owt/sdk/wasm/media_session.h @@ -0,0 +1,30 @@ +// Copyright (C) <2021> Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 + +#ifndef OWT_WASM_MEDIASESSION_H_ +#define OWT_WASM_MEDIASESSION_H_ + +#include "call/call.h" +#include "talk/owt/sdk/wasm/rtp_video_receiver.h" +#include "talk/owt/sdk/wasm/web_transport_session.h" + +namespace owt { +namespace wasm { +// Manages a media session between a web client and OWT server QUIC agent. +class MediaSession { + public: + explicit MediaSession(); + virtual ~MediaSession(); + RtpVideoReceiver* CreateRtpVideoReceiver(); + + private: + std::unique_ptr web_transport_session_; + std::unique_ptr call_; + std::unique_ptr video_receiver_; +}; + +} // namespace wasm +} // namespace owt + +#endif \ No newline at end of file diff --git a/talk/owt/sdk/wasm/rtp_video_receiver.cc b/talk/owt/sdk/wasm/rtp_video_receiver.cc new file mode 100644 index 000000000..633ebcc7c --- /dev/null +++ b/talk/owt/sdk/wasm/rtp_video_receiver.cc @@ -0,0 +1,23 @@ +// Copyright (C) <2021> Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 + +#include "talk/owt/sdk/wasm/rtp_video_receiver.h" +#include +#include "third_party/webrtc/rtc_base/logging.h" + +namespace owt { +namespace wasm { +RtpVideoReceiver::RtpVideoReceiver( + std::unique_ptr receiver) + : receiver_(std::move(receiver)) {} + +bool RtpVideoReceiver::OnRtpPacket(std::vector packet) { + RTC_LOG(LS_INFO) << "On RTP packet, size " << packet.size(); + // TODO: Create `rtp_packet_received` from `packet`. + webrtc::RtpPacketReceived rtp_packet_received; + receiver_->OnRtpPacket(rtp_packet_received); + return false; +} +} // namespace wasm +} // namespace owt \ No newline at end of file diff --git a/talk/owt/sdk/wasm/rtp_video_receiver.h b/talk/owt/sdk/wasm/rtp_video_receiver.h new file mode 100644 index 000000000..fb4675288 --- /dev/null +++ b/talk/owt/sdk/wasm/rtp_video_receiver.h @@ -0,0 +1,26 @@ +// Copyright (C) <2021> Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 + +#ifndef OWT_WASM_RTPVIDEORECEIVER_H_ +#define OWT_WASM_RTPVIDEORECEIVER_H_ + +#include "third_party/webrtc/video/rtp_video_stream_receiver2.h" + +namespace owt { +namespace wasm { +class RtpVideoReceiver { + public: + explicit RtpVideoReceiver( + std::unique_ptr receiver); + virtual ~RtpVideoReceiver() {} + virtual bool OnRtpPacket(std::vector packet); + + private: + std::unique_ptr receiver_; +}; + +} // namespace wasm +} // namespace owt + +#endif \ No newline at end of file diff --git a/talk/owt/sdk/wasm/web_transport_session.cc b/talk/owt/sdk/wasm/web_transport_session.cc new file mode 100644 index 000000000..209815caf --- /dev/null +++ b/talk/owt/sdk/wasm/web_transport_session.cc @@ -0,0 +1,20 @@ +// Copyright (C) <2021> Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 + +#include "talk/owt/sdk/wasm/web_transport_session.h" + +namespace owt { +namespace wasm { + +bool WebTransportSession::SendRtp(const uint8_t* packet, + size_t length, + const webrtc::PacketOptions& options) { + return false; +} +bool WebTransportSession::SendRtcp(const uint8_t* packet, size_t length) { + return false; +} + +} // namespace wasm +} // namespace owt \ No newline at end of file diff --git a/talk/owt/sdk/wasm/web_transport_session.h b/talk/owt/sdk/wasm/web_transport_session.h new file mode 100644 index 000000000..0f65e07fd --- /dev/null +++ b/talk/owt/sdk/wasm/web_transport_session.h @@ -0,0 +1,26 @@ +// Copyright (C) <2021> Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 + +#ifndef OWT_WASM_WEBTRANSPORTSESSION_H_ +#define OWT_WASM_WEBTRANSPORTSESSION_H_ + +#include "third_party/webrtc/api/call/transport.h" + +namespace owt { +namespace wasm { +class WebTransportSession : public webrtc::Transport { + public: + explicit WebTransportSession() {} + virtual ~WebTransportSession() {} + + // Overrides webrtc::Transport. + bool SendRtp(const uint8_t* packet, + size_t length, + const webrtc::PacketOptions& options) override; + bool SendRtcp(const uint8_t* packet, size_t length) override; +}; +} // namespace wasm +} // namespace owt + +#endif \ No newline at end of file From 0f82778ab4944e64160f849dc643187b1b6ab69b Mon Sep 17 00:00:00 2001 From: Jianjun Zhu Date: Wed, 13 Oct 2021 14:36:14 +0800 Subject: [PATCH 4/9] Add wasm APIs for RTP depacketizing. --- talk/owt/BUILD.gn | 2 + talk/owt/sdk/wasm/binding.h | 11 ++++- talk/owt/sdk/wasm/gn/BUILD.gn | 12 +++--- talk/owt/sdk/wasm/gn/wasm.gni | 50 ++++++++++++---------- talk/owt/sdk/wasm/media_session.cc | 47 +++++++++++++------- talk/owt/sdk/wasm/media_session.h | 10 ++++- talk/owt/sdk/wasm/rtp_video_receiver.cc | 42 ++++++++++++++++-- talk/owt/sdk/wasm/rtp_video_receiver.h | 20 +++++++-- talk/owt/sdk/wasm/web_transport_session.cc | 6 ++- talk/owt/sdk/wasm/web_transport_session.h | 10 ++++- 10 files changed, 152 insertions(+), 58 deletions(-) diff --git a/talk/owt/BUILD.gn b/talk/owt/BUILD.gn index e10e9479c..4eb5cbb2c 100644 --- a/talk/owt/BUILD.gn +++ b/talk/owt/BUILD.gn @@ -340,6 +340,8 @@ if (is_wasm) { "//third_party/webrtc/call", "//third_party/webrtc/modules/rtp_rtcp:rtp_rtcp", "//third_party/webrtc/rtc_base:rtc_json", + "//third_party/webrtc/rtc_base:rtc_task_queue_stdlib", + "//third_party/webrtc/api/rtc_event_log:rtc_event_log_factory", ] sources = [ "sdk/wasm/binding.h", diff --git a/talk/owt/sdk/wasm/binding.h b/talk/owt/sdk/wasm/binding.h index e6e242c3d..d17ccced4 100644 --- a/talk/owt/sdk/wasm/binding.h +++ b/talk/owt/sdk/wasm/binding.h @@ -13,9 +13,16 @@ namespace owt { namespace wasm { EMSCRIPTEN_BINDINGS(Owt) { - emscripten::class_("MediaSession").constructor<>(); + emscripten::class_("MediaSession") + .constructor<>() + .function("createRtpVideoReceiver", + &MediaSession::CreateRtpVideoReceiver); emscripten::class_("RtpVideoReceiver") - .function("onRtpPacket", &RtpVideoReceiver::OnRtpPacket); + .smart_ptr>("RtpVideoReceiver") + .function("onRtpPacket", &RtpVideoReceiver::OnRtpPacket, + emscripten::allow_raw_pointers()) + .function("setCompleteFrameCallback", + &RtpVideoReceiver::SetCompleteFrameCallback); } } // namespace wasm diff --git a/talk/owt/sdk/wasm/gn/BUILD.gn b/talk/owt/sdk/wasm/gn/BUILD.gn index 08eaeff63..291f4afff 100644 --- a/talk/owt/sdk/wasm/gn/BUILD.gn +++ b/talk/owt/sdk/wasm/gn/BUILD.gn @@ -65,7 +65,7 @@ template("gcc_like_toolchain") { tool("cc") { depfile = "{{output}}.d" - command = "$cc_wrapper $cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0 --bind -fno-stack-protector ${external_cflags} -c {{source}} -o {{output}}" + command = "$cc_wrapper $cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=1 --bind -fno-stack-protector ${external_cflags} -c {{source}} -o {{output}}" depsformat = "gcc" outputs = [ "$object_subdir/{{source_name_part}}.o" ] description = "compile {{source}}" @@ -73,7 +73,7 @@ template("gcc_like_toolchain") { tool("cxx") { depfile = "{{output}}.d" - command = "$cc_wrapper $cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0 --bind -fno-stack-protector ${external_cflags} ${external_cxxflags} -c {{source}} -o {{output}}" + command = "$cc_wrapper $cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=1 --bind -fno-stack-protector ${external_cflags} ${external_cxxflags} -c {{source}} -o {{output}}" depsformat = "gcc" outputs = [ "$object_subdir/{{source_name_part}}.o" ] description = "compile {{source}}" @@ -81,7 +81,7 @@ template("gcc_like_toolchain") { tool("asm") { depfile = "{{output}}.d" - command = "$cc_wrapper $cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{asmflags}} -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0 --bind -fno-stack-protector -c {{source}} -o {{output}}" + command = "$cc_wrapper $cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{asmflags}} -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=1 --bind -fno-stack-protector -c {{source}} -o {{output}}" depsformat = "gcc" outputs = [ "$object_subdir/{{source_name_part}}.o" ] description = "assemble {{source}}" @@ -142,7 +142,7 @@ template("gcc_like_toolchain") { tool("link") { unstripped_exe = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}" - command = "$cc_wrapper $cxx $ld_arg ${external_ldflags} {{inputs}} {{solibs}} {{libs}} -o $unstripped_exe" + command = "$cc_wrapper $cxx $ld_arg {{ldflags}} ${external_ldflags} {{inputs}} {{solibs}} {{libs}} -o $unstripped_exe" outputs = [ unstripped_exe ] description = "link $unstripped_exe" if (strip != "") { @@ -174,7 +174,7 @@ gcc_like_toolchain("wasm") { cpu = host_cpu os = host_os ar = "$emsdk_dir/emscripten/emar --em-config $em_config" - cc = "$emsdk_dir/emscripten/emcc --em-config $em_config" - cxx = "$emsdk_dir/emscripten/em++ --em-config $em_config --bind -s USE_PTHREADS=1" + cc = "$emsdk_dir/emscripten/emcc --em-config $em_config -pthread" + cxx = "$emsdk_dir/emscripten/em++ --em-config $em_config --bind -pthread" strip = "" } diff --git a/talk/owt/sdk/wasm/gn/wasm.gni b/talk/owt/sdk/wasm/gn/wasm.gni index aee71a635..56d845588 100644 --- a/talk/owt/sdk/wasm/gn/wasm.gni +++ b/talk/owt/sdk/wasm/gn/wasm.gni @@ -38,26 +38,26 @@ template("wasm_lib") { assert(invoker.name + "_wasm" == target_name) _lib_name = invoker.name if (is_wasm) { - _exports = "['ccall', 'callMain', 'addFunction', 'FS']" + _exports = "['writeArrayToMemory']" _target_ldflags = [ "-s", "WASM=1", - "-s", - "DISABLE_EXCEPTION_CATCHING=1", - "-s", - "NO_DYNAMIC_EXECUTION=1", + # "-s", + # "DISABLE_EXCEPTION_CATCHING=1", "-s", "INITIAL_MEMORY=33554432", "-s", "ALLOW_TABLE_GROWTH=1", - "-s", - "WASM_ASYNC_COMPILATION=0", + # "-s", + # "WASM_ASYNC_COMPILATION=0", "-s", "USE_PTHREADS=1", "-s", + "PROXY_TO_PTHREAD=1", + "-s", "LLD_REPORT_UNDEFINED", "-s", - "EXTRA_EXPORTED_RUNTIME_METHODS=" + _exports, + "EXPORTED_RUNTIME_METHODS=" + _exports, # This forces the MEMFS filesystem library to always use typed arrays # instead of building strings/arrays when appending to a file. This allows @@ -66,30 +66,37 @@ template("wasm_lib") { "MEMFS_APPEND_TO_TYPED_ARRAYS=1", # Reduces global namespace pollution. - "-s", - "MODULARIZE=1", + # "-s", + # "MODULARIZE=1", - "-fno-stack-protector", + #"-fno-stack-protector", # This is to prevent that two different wasm modules end up generating # JS that overrides the same global variable (var Module = ...) - "-s", - "EXPORT_NAME=${target_name}", + # "-s", + # "EXPORT_NAME=${target_name}", "-lworkerfs.js", # For FS.filesystems.WORKERFS "--bind", + + "-s", + "PTHREAD_POOL_SIZE=2", + + "-pthread", + + "--source-map-base", ] if (is_debug) { _target_ldflags += [ - "-s", - "ASSERTIONS=2", - "-s", - "SAFE_HEAP=1", - "-s", - "STACK_OVERFLOW_CHECK=1", - "-gsource-map", - "-O0", + # "-s", + # "ASSERTIONS=2", + # "-s", + # "SAFE_HEAP=1", + # "-s", + # "STACK_OVERFLOW_CHECK=1", + # "-gsource-map", + # "-O0", ] } else { _target_ldflags += [ @@ -108,7 +115,6 @@ template("wasm_lib") { } _target_cflags = [ - "-fno-stack-protector", "-pthread", ] if (defined(invoker.cflags)) { diff --git a/talk/owt/sdk/wasm/media_session.cc b/talk/owt/sdk/wasm/media_session.cc index a930a2ee6..d5efd150e 100644 --- a/talk/owt/sdk/wasm/media_session.cc +++ b/talk/owt/sdk/wasm/media_session.cc @@ -3,30 +3,45 @@ // SPDX-License-Identifier: Apache-2.0 #include "talk/owt/sdk/wasm/media_session.h" +#include "third_party/webrtc/api/rtc_event_log/rtc_event_log_factory.h" +#include "third_party/webrtc/api/transport/field_trial_based_config.h" +#include "third_party/webrtc/rtc_base/task_queue_stdlib.h" namespace owt { namespace wasm { MediaSession::MediaSession() - : call_(std::unique_ptr( - webrtc::Call::Create(webrtc::Call::Config(nullptr)))), - video_receiver_(nullptr) {} + : task_queue_factory_(webrtc::CreateTaskQueueStdlibFactory()), + event_log_factory_(std::make_unique( + task_queue_factory_.get())), + event_log_(event_log_factory_->CreateRtcEventLog( + webrtc::RtcEventLog::EncodingType::NewFormat)), + web_transport_session_(std::make_unique()), + call_(nullptr), + receive_statistics_( + webrtc::ReceiveStatistics::Create(webrtc::Clock::GetRealTimeClock())), + receiver_process_thread_(nullptr), + video_receiver_(nullptr) { + RTC_LOG(LS_ERROR) << "Ctor of Media Session. " << __EMSCRIPTEN_PTHREADS__; + rtc::ThreadManager::Instance()->WrapCurrentThread(); + receiver_process_thread_=webrtc::ProcessThread::Create("ReceiverProcessThread"); + webrtc::Call::Config config(event_log_.get()); + config.task_queue_factory = task_queue_factory_.get(); + webrtc::FieldTrialBasedConfig trials; + config.trials = &trials; + call_ = std::unique_ptr(webrtc::Call::Create(config)); +} MediaSession::~MediaSession() {} -RtpVideoReceiver* MediaSession::CreateRtpVideoReceiver() { +std::shared_ptr MediaSession::CreateRtpVideoReceiver() { webrtc::VideoReceiveStream::Config config(web_transport_session_.get()); - webrtc::TaskQueueBase* task_queue = webrtc::TaskQueueBase::Current(); - if (!task_queue) { - task_queue = rtc::ThreadManager::Instance()->CurrentThread(); - } - std::unique_ptr receiver = - std::make_unique( - task_queue, webrtc::Clock::GetRealTimeClock(), - web_transport_session_.get(), nullptr, nullptr, &config, nullptr, - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr); - video_receiver_ = std::make_unique(std::move(receiver)); - return video_receiver_.get(); + config.rtp.local_ssrc = 1; + // TODO: Get a message queue for receiver. + video_receiver_ = std::make_shared( + web_transport_session_.get(), &config, receive_statistics_.get(), + receiver_process_thread_.get(), web_transport_session_.get()); + return video_receiver_; } + } // namespace wasm } // namespace owt \ No newline at end of file diff --git a/talk/owt/sdk/wasm/media_session.h b/talk/owt/sdk/wasm/media_session.h index e3ab6b45a..e90bc67c1 100644 --- a/talk/owt/sdk/wasm/media_session.h +++ b/talk/owt/sdk/wasm/media_session.h @@ -8,6 +8,7 @@ #include "call/call.h" #include "talk/owt/sdk/wasm/rtp_video_receiver.h" #include "talk/owt/sdk/wasm/web_transport_session.h" +#include "third_party/webrtc/api/rtc_event_log/rtc_event_log_factory_interface.h" namespace owt { namespace wasm { @@ -16,12 +17,17 @@ class MediaSession { public: explicit MediaSession(); virtual ~MediaSession(); - RtpVideoReceiver* CreateRtpVideoReceiver(); + std::shared_ptr CreateRtpVideoReceiver(); private: + std::unique_ptr task_queue_factory_; + std::unique_ptr event_log_factory_; + std::unique_ptr event_log_; std::unique_ptr web_transport_session_; std::unique_ptr call_; - std::unique_ptr video_receiver_; + std::unique_ptr receive_statistics_; + std::unique_ptr receiver_process_thread_; + std::shared_ptr video_receiver_; }; } // namespace wasm diff --git a/talk/owt/sdk/wasm/rtp_video_receiver.cc b/talk/owt/sdk/wasm/rtp_video_receiver.cc index 633ebcc7c..d779e1177 100644 --- a/talk/owt/sdk/wasm/rtp_video_receiver.cc +++ b/talk/owt/sdk/wasm/rtp_video_receiver.cc @@ -8,16 +8,50 @@ namespace owt { namespace wasm { + RtpVideoReceiver::RtpVideoReceiver( - std::unique_ptr receiver) - : receiver_(std::move(receiver)) {} + webrtc::Transport* transport, + const webrtc::VideoReceiveStream::Config* config, + webrtc::ReceiveStatistics* rtp_receive_statistics, + webrtc::ProcessThread* process_thread, + webrtc::NackSender* nack_sender) + : receiver_(nullptr), complete_frame_callback_(emscripten::val::null()) { + receiver_ = std::make_unique( + nullptr, webrtc::Clock::GetRealTimeClock(), transport, nullptr, nullptr, + config, rtp_receive_statistics, nullptr, nullptr, process_thread, + nack_sender, nullptr, this, nullptr, nullptr); + webrtc::VideoCodec codec; + codec.codecType = webrtc::VideoCodecType::kVideoCodecH264; + // TODO: Assign payload value dynamically according to server side + // configuration. + receiver_->AddReceiveCodec(127, codec, std::map(), + false); + receiver_->StartReceive(); +} -bool RtpVideoReceiver::OnRtpPacket(std::vector packet) { - RTC_LOG(LS_INFO) << "On RTP packet, size " << packet.size(); +bool RtpVideoReceiver::OnRtpPacket(uintptr_t packet_ptr, size_t packet_size) { + const uint8_t* packet = reinterpret_cast(packet_ptr); // TODO: Create `rtp_packet_received` from `packet`. webrtc::RtpPacketReceived rtp_packet_received; + rtp_packet_received.Parse(packet, packet_size); receiver_->OnRtpPacket(rtp_packet_received); return false; } + +void RtpVideoReceiver::OnCompleteFrame( + std::unique_ptr frame) { + if(complete_frame_callback_.isNull()){ + RTC_LOG(LS_WARNING) << "No callback registered for complete frames."; + return; + } + emscripten::val buffer(emscripten::typed_memory_view( + frame->EncodedImage().size(), frame->EncodedImage().data())); + complete_frame_callback_(buffer); +} + +void RtpVideoReceiver::SetCompleteFrameCallback(emscripten::val callback) { + complete_frame_callback_ = callback; +} + } // namespace wasm } // namespace owt \ No newline at end of file diff --git a/talk/owt/sdk/wasm/rtp_video_receiver.h b/talk/owt/sdk/wasm/rtp_video_receiver.h index fb4675288..33b887939 100644 --- a/talk/owt/sdk/wasm/rtp_video_receiver.h +++ b/talk/owt/sdk/wasm/rtp_video_receiver.h @@ -5,19 +5,31 @@ #ifndef OWT_WASM_RTPVIDEORECEIVER_H_ #define OWT_WASM_RTPVIDEORECEIVER_H_ +#include #include "third_party/webrtc/video/rtp_video_stream_receiver2.h" namespace owt { namespace wasm { -class RtpVideoReceiver { +class RtpVideoReceiver + : public webrtc::RtpVideoStreamReceiver2::OnCompleteFrameCallback { public: - explicit RtpVideoReceiver( - std::unique_ptr receiver); + explicit RtpVideoReceiver(webrtc::Transport* transport, + const webrtc::VideoReceiveStream::Config* config, + webrtc::ReceiveStatistics* rtp_receive_statistics, + webrtc::ProcessThread* process_thread, + webrtc::NackSender* nack_sender); virtual ~RtpVideoReceiver() {} - virtual bool OnRtpPacket(std::vector packet); + virtual bool OnRtpPacket(uintptr_t packet_ptr, size_t packet_size); + + // Overrides webrtc::RtpVideoStreamReceiver2::OnCompleteFrameCallback. + void OnCompleteFrame( + std::unique_ptr frame) override; + + void SetCompleteFrameCallback(emscripten::val callback); private: std::unique_ptr receiver_; + emscripten::val complete_frame_callback_; }; } // namespace wasm diff --git a/talk/owt/sdk/wasm/web_transport_session.cc b/talk/owt/sdk/wasm/web_transport_session.cc index 209815caf..e5ea596ff 100644 --- a/talk/owt/sdk/wasm/web_transport_session.cc +++ b/talk/owt/sdk/wasm/web_transport_session.cc @@ -6,7 +6,7 @@ namespace owt { namespace wasm { - + bool WebTransportSession::SendRtp(const uint8_t* packet, size_t length, const webrtc::PacketOptions& options) { @@ -16,5 +16,9 @@ bool WebTransportSession::SendRtcp(const uint8_t* packet, size_t length) { return false; } +void WebTransportSession::SendNack( + const std::vector& sequence_numbers, + bool buffering_allowed) {} + } // namespace wasm } // namespace owt \ No newline at end of file diff --git a/talk/owt/sdk/wasm/web_transport_session.h b/talk/owt/sdk/wasm/web_transport_session.h index 0f65e07fd..365b91617 100644 --- a/talk/owt/sdk/wasm/web_transport_session.h +++ b/talk/owt/sdk/wasm/web_transport_session.h @@ -6,10 +6,13 @@ #define OWT_WASM_WEBTRANSPORTSESSION_H_ #include "third_party/webrtc/api/call/transport.h" +#include "third_party/webrtc/modules/include/module_common_types.h" namespace owt { namespace wasm { -class WebTransportSession : public webrtc::Transport { + +class WebTransportSession : public webrtc::Transport, + public webrtc::NackSender { public: explicit WebTransportSession() {} virtual ~WebTransportSession() {} @@ -19,7 +22,12 @@ class WebTransportSession : public webrtc::Transport { size_t length, const webrtc::PacketOptions& options) override; bool SendRtcp(const uint8_t* packet, size_t length) override; + + // Overrides webrtc::NackSender. + void SendNack(const std::vector& sequence_numbers, + bool buffering_allowed) override; }; + } // namespace wasm } // namespace owt From 71974f2ba4dafbd74b97bc36d6fb3e0b2e9c8159 Mon Sep 17 00:00:00 2001 From: Jianjun Zhu Date: Thu, 2 Dec 2021 16:38:43 +0800 Subject: [PATCH 5/9] Enable NACK module. --- talk/owt/sdk/wasm/binding.h | 4 +-- talk/owt/sdk/wasm/gn/wasm.gni | 9 ++++-- talk/owt/sdk/wasm/media_session.cc | 42 +++++++++++++++++++------ talk/owt/sdk/wasm/media_session.h | 13 ++++++-- talk/owt/sdk/wasm/rtp_video_receiver.cc | 19 ++++++++--- talk/owt/sdk/wasm/rtp_video_receiver.h | 13 +++++--- 6 files changed, 75 insertions(+), 25 deletions(-) diff --git a/talk/owt/sdk/wasm/binding.h b/talk/owt/sdk/wasm/binding.h index d17ccced4..4cda0ae44 100644 --- a/talk/owt/sdk/wasm/binding.h +++ b/talk/owt/sdk/wasm/binding.h @@ -15,8 +15,8 @@ namespace wasm { EMSCRIPTEN_BINDINGS(Owt) { emscripten::class_("MediaSession") .constructor<>() - .function("createRtpVideoReceiver", - &MediaSession::CreateRtpVideoReceiver); + .function("createRtpVideoReceiver", &MediaSession::CreateRtpVideoReceiver) + .function("setRtcpCallback", &MediaSession::SetRtcpCallback); emscripten::class_("RtpVideoReceiver") .smart_ptr>("RtpVideoReceiver") .function("onRtpPacket", &RtpVideoReceiver::OnRtpPacket, diff --git a/talk/owt/sdk/wasm/gn/wasm.gni b/talk/owt/sdk/wasm/gn/wasm.gni index 56d845588..fab5035f4 100644 --- a/talk/owt/sdk/wasm/gn/wasm.gni +++ b/talk/owt/sdk/wasm/gn/wasm.gni @@ -66,8 +66,11 @@ template("wasm_lib") { "MEMFS_APPEND_TO_TYPED_ARRAYS=1", # Reduces global namespace pollution. - # "-s", - # "MODULARIZE=1", + "-s", + "MODULARIZE=1", + + "-s", + "EXPORT_ES6=1", #"-fno-stack-protector", @@ -81,7 +84,7 @@ template("wasm_lib") { "--bind", "-s", - "PTHREAD_POOL_SIZE=2", + "PTHREAD_POOL_SIZE=5", "-pthread", diff --git a/talk/owt/sdk/wasm/media_session.cc b/talk/owt/sdk/wasm/media_session.cc index d5efd150e..d52077001 100644 --- a/talk/owt/sdk/wasm/media_session.cc +++ b/talk/owt/sdk/wasm/media_session.cc @@ -20,10 +20,11 @@ MediaSession::MediaSession() receive_statistics_( webrtc::ReceiveStatistics::Create(webrtc::Clock::GetRealTimeClock())), receiver_process_thread_(nullptr), - video_receiver_(nullptr) { - RTC_LOG(LS_ERROR) << "Ctor of Media Session. " << __EMSCRIPTEN_PTHREADS__; + video_receiver_(nullptr), + rtcp_callback_(emscripten::val::null()) { rtc::ThreadManager::Instance()->WrapCurrentThread(); - receiver_process_thread_=webrtc::ProcessThread::Create("ReceiverProcessThread"); + receiver_process_thread_ = + webrtc::ProcessThread::Create("ReceiverProcessThread"); webrtc::Call::Config config(event_log_.get()); config.task_queue_factory = task_queue_factory_.get(); webrtc::FieldTrialBasedConfig trials; @@ -31,17 +32,40 @@ MediaSession::MediaSession() call_ = std::unique_ptr(webrtc::Call::Create(config)); } -MediaSession::~MediaSession() {} - std::shared_ptr MediaSession::CreateRtpVideoReceiver() { - webrtc::VideoReceiveStream::Config config(web_transport_session_.get()); + webrtc::VideoReceiveStream::Config config(this); config.rtp.local_ssrc = 1; - // TODO: Get a message queue for receiver. + // Same as `kNackRtpHistoryMs` in third_party/webrtc/media/engine/webrtc_voice_engine.cc. + config.rtp.nack.rtp_history_ms = 5000; + // TODO: Use call_->worker_thread() when libwebrtc is rolled to a newer version. + webrtc::TaskQueueBase* current = webrtc::TaskQueueBase::Current(); + if (!current) + current = rtc::ThreadManager::Instance()->CurrentThread(); + RTC_DCHECK(current); video_receiver_ = std::make_shared( - web_transport_session_.get(), &config, receive_statistics_.get(), - receiver_process_thread_.get(), web_transport_session_.get()); + current, this, &config, receive_statistics_.get(), + receiver_process_thread_.get()); return video_receiver_; } +void MediaSession::SetRtcpCallback(emscripten::val callback) { + rtcp_callback_ = callback; +} + +bool MediaSession::SendRtp(const uint8_t* packet, + size_t length, + const webrtc::PacketOptions& options) { + return false; +} + +bool MediaSession::SendRtcp(const uint8_t* packet, size_t length) { + if (!rtcp_callback_) { + return false; + } + emscripten::val buffer(emscripten::typed_memory_view(length, packet)); + rtcp_callback_(buffer); + return true; +} + } // namespace wasm } // namespace owt \ No newline at end of file diff --git a/talk/owt/sdk/wasm/media_session.h b/talk/owt/sdk/wasm/media_session.h index e90bc67c1..8d7639ba8 100644 --- a/talk/owt/sdk/wasm/media_session.h +++ b/talk/owt/sdk/wasm/media_session.h @@ -5,6 +5,7 @@ #ifndef OWT_WASM_MEDIASESSION_H_ #define OWT_WASM_MEDIASESSION_H_ +#include #include "call/call.h" #include "talk/owt/sdk/wasm/rtp_video_receiver.h" #include "talk/owt/sdk/wasm/web_transport_session.h" @@ -13,11 +14,18 @@ namespace owt { namespace wasm { // Manages a media session between a web client and OWT server QUIC agent. -class MediaSession { +class MediaSession : public webrtc::Transport { public: explicit MediaSession(); - virtual ~MediaSession(); + virtual ~MediaSession() = default; std::shared_ptr CreateRtpVideoReceiver(); + void SetRtcpCallback(emscripten::val callback); + + // Overrides webrtc::Transport. + bool SendRtp(const uint8_t* packet, + size_t length, + const webrtc::PacketOptions& options) override; + bool SendRtcp(const uint8_t* packet, size_t length) override; private: std::unique_ptr task_queue_factory_; @@ -28,6 +36,7 @@ class MediaSession { std::unique_ptr receive_statistics_; std::unique_ptr receiver_process_thread_; std::shared_ptr video_receiver_; + emscripten::val rtcp_callback_; }; } // namespace wasm diff --git a/talk/owt/sdk/wasm/rtp_video_receiver.cc b/talk/owt/sdk/wasm/rtp_video_receiver.cc index d779e1177..1f4e9b839 100644 --- a/talk/owt/sdk/wasm/rtp_video_receiver.cc +++ b/talk/owt/sdk/wasm/rtp_video_receiver.cc @@ -10,16 +10,16 @@ namespace owt { namespace wasm { RtpVideoReceiver::RtpVideoReceiver( + webrtc::TaskQueueBase* current_queue, webrtc::Transport* transport, const webrtc::VideoReceiveStream::Config* config, webrtc::ReceiveStatistics* rtp_receive_statistics, - webrtc::ProcessThread* process_thread, - webrtc::NackSender* nack_sender) + webrtc::ProcessThread* process_thread) : receiver_(nullptr), complete_frame_callback_(emscripten::val::null()) { receiver_ = std::make_unique( - nullptr, webrtc::Clock::GetRealTimeClock(), transport, nullptr, nullptr, - config, rtp_receive_statistics, nullptr, nullptr, process_thread, - nack_sender, nullptr, this, nullptr, nullptr); + current_queue, webrtc::Clock::GetRealTimeClock(), transport, nullptr, + nullptr, config, rtp_receive_statistics, nullptr, nullptr, process_thread, + this, nullptr, this, nullptr, nullptr); webrtc::VideoCodec codec; codec.codecType = webrtc::VideoCodecType::kVideoCodecH264; // TODO: Assign payload value dynamically according to server side @@ -53,5 +53,14 @@ void RtpVideoReceiver::SetCompleteFrameCallback(emscripten::val callback) { complete_frame_callback_ = callback; } +void RtpVideoReceiver::SendNack(const std::vector& sequence_numbers, + bool buffering_allowed) { + // Only buffering_allowed == true is supported. Same as + // https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/video/video_receive_stream2.h;l=157;bpv=1;bpt=1 + RTC_DCHECK(buffering_allowed); + RTC_LOG(LS_INFO)<<"Request packet rtx"; + receiver_->RequestPacketRetransmit(sequence_numbers); +} + } // namespace wasm } // namespace owt \ No newline at end of file diff --git a/talk/owt/sdk/wasm/rtp_video_receiver.h b/talk/owt/sdk/wasm/rtp_video_receiver.h index 33b887939..59e78eca0 100644 --- a/talk/owt/sdk/wasm/rtp_video_receiver.h +++ b/talk/owt/sdk/wasm/rtp_video_receiver.h @@ -11,13 +11,14 @@ namespace owt { namespace wasm { class RtpVideoReceiver - : public webrtc::RtpVideoStreamReceiver2::OnCompleteFrameCallback { + : public webrtc::RtpVideoStreamReceiver2::OnCompleteFrameCallback, + public webrtc::NackSender { public: - explicit RtpVideoReceiver(webrtc::Transport* transport, + explicit RtpVideoReceiver(webrtc::TaskQueueBase* current_queue, + webrtc::Transport* transport, const webrtc::VideoReceiveStream::Config* config, webrtc::ReceiveStatistics* rtp_receive_statistics, - webrtc::ProcessThread* process_thread, - webrtc::NackSender* nack_sender); + webrtc::ProcessThread* process_thread); virtual ~RtpVideoReceiver() {} virtual bool OnRtpPacket(uintptr_t packet_ptr, size_t packet_size); @@ -27,6 +28,10 @@ class RtpVideoReceiver void SetCompleteFrameCallback(emscripten::val callback); + // Overrides webrtc::NackSender. + void SendNack(const std::vector& sequence_numbers, + bool buffering_allowed) override; + private: std::unique_ptr receiver_; emscripten::val complete_frame_callback_; From 64af5f49abd1976f11c06640bbbc98c4dbeafc78 Mon Sep 17 00:00:00 2001 From: Jianjun Zhu Date: Fri, 10 Dec 2021 10:49:14 +0800 Subject: [PATCH 6/9] Set SSRC when create RTP receiver. --- talk/owt/docker/Dockerfile | 27 +++++++++++++++++++++ talk/owt/gn/toolchain/.emscripten | 39 ++++++++++++++++++++++++++++++ talk/owt/sdk/wasm/media_session.cc | 4 ++- talk/owt/sdk/wasm/media_session.h | 3 ++- 4 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 talk/owt/docker/Dockerfile create mode 100644 talk/owt/gn/toolchain/.emscripten diff --git a/talk/owt/docker/Dockerfile b/talk/owt/docker/Dockerfile new file mode 100644 index 000000000..a385d1a13 --- /dev/null +++ b/talk/owt/docker/Dockerfile @@ -0,0 +1,27 @@ +# Copyright (C) <2021> Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +FROM ubuntu:20.04 +SHELL ["/bin/bash", "-c"] +RUN apt-get update && apt-get install -y git curl wget python python3 +RUN mkdir workspace +WORKDIR /workspace +RUN git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git +ENV PATH="$PATH:/workspace/depot_tools" +RUN mkdir owt +WORKDIR /workspace/owt +RUN echo $'solutions = [\n\ + {\n\ + "name" : "src",\n\ + "url" : "https://github.com/open-webrtc-toolkit/owt-client-native.git",\n\ + "deps_file" : "DEPS",\n\ + "managed" : False,\n\ + "custom_deps" : {\n\ + },\n\ + "custom_vars": {},\n\ + },\n\ +]' > .gclient +RUN git config --global user.name owt-bot +RUN git config --global user.email 82484650+owt-bot@users.noreply.github.com +RUN gclient sync diff --git a/talk/owt/gn/toolchain/.emscripten b/talk/owt/gn/toolchain/.emscripten new file mode 100644 index 000000000..ac3a69291 --- /dev/null +++ b/talk/owt/gn/toolchain/.emscripten @@ -0,0 +1,39 @@ +# Copyright (C) 2021 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This is the init script that is passed to `emcc --em-config=.emscripten` +# (Wasm toolchain). It sets vars to locate the various emsdk / llvm dirs. + +import os +import sys +from platform import system + +# We cannot use __file__ here. +this_file = os.getenv('EM_CONFIG') +if this_file is None: + sys.stderr.write('Could not find EM_CONFIG in .emscripten\n') + sys.exit(1) + +root_dir = os.path.dirname(os.path.dirname(os.path.dirname(this_file))) +buildools_os = 'mac' if system().lower() == 'darwin' else 'linux64' +node_path = os.path.join(root_dir, 'buildtools', buildools_os, 'nodejs') +emsdk_path = os.path.join(root_dir, 'buildtools', buildools_os, 'emsdk') + +# Exported vars. +NODE_JS = os.path.join(node_path, 'bin', 'node') +LLVM_ROOT = os.path.join(emsdk_path, 'bin') +BINARYEN_ROOT = emsdk_path +EMSCRIPTEN_ROOT = os.path.join(emsdk_path, 'emscripten') +COMPILER_ENGINE = NODE_JS +JS_ENGINES = [NODE_JS] diff --git a/talk/owt/sdk/wasm/media_session.cc b/talk/owt/sdk/wasm/media_session.cc index d52077001..809131baa 100644 --- a/talk/owt/sdk/wasm/media_session.cc +++ b/talk/owt/sdk/wasm/media_session.cc @@ -32,8 +32,10 @@ MediaSession::MediaSession() call_ = std::unique_ptr(webrtc::Call::Create(config)); } -std::shared_ptr MediaSession::CreateRtpVideoReceiver() { +std::shared_ptr MediaSession::CreateRtpVideoReceiver( + uint32_t remote_ssrc) { webrtc::VideoReceiveStream::Config config(this); + config.rtp.remote_ssrc = remote_ssrc; config.rtp.local_ssrc = 1; // Same as `kNackRtpHistoryMs` in third_party/webrtc/media/engine/webrtc_voice_engine.cc. config.rtp.nack.rtp_history_ms = 5000; diff --git a/talk/owt/sdk/wasm/media_session.h b/talk/owt/sdk/wasm/media_session.h index 8d7639ba8..a46eba051 100644 --- a/talk/owt/sdk/wasm/media_session.h +++ b/talk/owt/sdk/wasm/media_session.h @@ -18,7 +18,8 @@ class MediaSession : public webrtc::Transport { public: explicit MediaSession(); virtual ~MediaSession() = default; - std::shared_ptr CreateRtpVideoReceiver(); + std::shared_ptr CreateRtpVideoReceiver( + uint32_t remote_ssrc); void SetRtcpCallback(emscripten::val callback); // Overrides webrtc::Transport. From 24d2cd83f1c18f8d22a742b0048d3cac055afad9 Mon Sep 17 00:00:00 2001 From: Jianjun Zhu Date: Wed, 5 Jan 2022 12:55:25 +0800 Subject: [PATCH 7/9] Move --bind to targets which need it. --- talk/owt/sdk/wasm/gn/BUILD.gn | 8 ++++---- talk/owt/sdk/wasm/gn/wasm.gni | 18 ++++++++++-------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/talk/owt/sdk/wasm/gn/BUILD.gn b/talk/owt/sdk/wasm/gn/BUILD.gn index 291f4afff..e6b1fcfe9 100644 --- a/talk/owt/sdk/wasm/gn/BUILD.gn +++ b/talk/owt/sdk/wasm/gn/BUILD.gn @@ -65,7 +65,7 @@ template("gcc_like_toolchain") { tool("cc") { depfile = "{{output}}.d" - command = "$cc_wrapper $cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=1 --bind -fno-stack-protector ${external_cflags} -c {{source}} -o {{output}}" + command = "$cc_wrapper $cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=1 -fno-stack-protector ${external_cflags} -c {{source}} -o {{output}}" depsformat = "gcc" outputs = [ "$object_subdir/{{source_name_part}}.o" ] description = "compile {{source}}" @@ -73,7 +73,7 @@ template("gcc_like_toolchain") { tool("cxx") { depfile = "{{output}}.d" - command = "$cc_wrapper $cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=1 --bind -fno-stack-protector ${external_cflags} ${external_cxxflags} -c {{source}} -o {{output}}" + command = "$cc_wrapper $cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=1 -fno-stack-protector ${external_cflags} ${external_cxxflags} -c {{source}} -o {{output}}" depsformat = "gcc" outputs = [ "$object_subdir/{{source_name_part}}.o" ] description = "compile {{source}}" @@ -81,7 +81,7 @@ template("gcc_like_toolchain") { tool("asm") { depfile = "{{output}}.d" - command = "$cc_wrapper $cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{asmflags}} -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=1 --bind -fno-stack-protector -c {{source}} -o {{output}}" + command = "$cc_wrapper $cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{asmflags}} -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=1 -fno-stack-protector -c {{source}} -o {{output}}" depsformat = "gcc" outputs = [ "$object_subdir/{{source_name_part}}.o" ] description = "assemble {{source}}" @@ -175,6 +175,6 @@ gcc_like_toolchain("wasm") { os = host_os ar = "$emsdk_dir/emscripten/emar --em-config $em_config" cc = "$emsdk_dir/emscripten/emcc --em-config $em_config -pthread" - cxx = "$emsdk_dir/emscripten/em++ --em-config $em_config --bind -pthread" + cxx = "$emsdk_dir/emscripten/em++ --em-config $em_config -pthread" strip = "" } diff --git a/talk/owt/sdk/wasm/gn/wasm.gni b/talk/owt/sdk/wasm/gn/wasm.gni index fab5035f4..a68f817da 100644 --- a/talk/owt/sdk/wasm/gn/wasm.gni +++ b/talk/owt/sdk/wasm/gn/wasm.gni @@ -72,6 +72,8 @@ template("wasm_lib") { "-s", "EXPORT_ES6=1", + "--bind", + #"-fno-stack-protector", # This is to prevent that two different wasm modules end up generating @@ -79,16 +81,14 @@ template("wasm_lib") { # "-s", # "EXPORT_NAME=${target_name}", - "-lworkerfs.js", # For FS.filesystems.WORKERFS - - "--bind", + # "-lworkerfs.js", # For FS.filesystems.WORKERFS "-s", - "PTHREAD_POOL_SIZE=5", + "PTHREAD_POOL_SIZE=8", + "-s", + "ALLOW_BLOCKING_ON_MAIN_THREAD=0", "-pthread", - - "--source-map-base", ] if (is_debug) { _target_ldflags += [ @@ -98,8 +98,10 @@ template("wasm_lib") { # "SAFE_HEAP=1", # "-s", # "STACK_OVERFLOW_CHECK=1", - # "-gsource-map", - # "-O0", + "-O0", + "-gsource-map", + "--source-map-base", + "http://jianjunz-nuc-ubuntu.sh.intel.com:9900/out/wasm/", ] } else { _target_ldflags += [ From 1caf2443b1469b6e70c3285b1ebb685f71a1738f Mon Sep 17 00:00:00 2001 From: Jianjun Zhu Date: Wed, 5 Jan 2022 12:55:47 +0800 Subject: [PATCH 8/9] Create MediaSession in main function. --- talk/owt/sdk/wasm/binding.h | 7 ++++--- talk/owt/sdk/wasm/main.cc | 9 +-------- talk/owt/sdk/wasm/media_session.cc | 11 +++++++++++ talk/owt/sdk/wasm/media_session.h | 3 +++ 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/talk/owt/sdk/wasm/binding.h b/talk/owt/sdk/wasm/binding.h index 4cda0ae44..cfc948863 100644 --- a/talk/owt/sdk/wasm/binding.h +++ b/talk/owt/sdk/wasm/binding.h @@ -5,7 +5,6 @@ #ifndef OWT_WASM_BINDING_H_ #define OWT_WASM_BINDING_H_ -#include #include "talk/owt/sdk/wasm/media_session.h" #include "talk/owt/sdk/wasm/rtp_video_receiver.h" @@ -14,9 +13,11 @@ namespace wasm { EMSCRIPTEN_BINDINGS(Owt) { emscripten::class_("MediaSession") - .constructor<>() + .smart_ptr>("MediaSession") .function("createRtpVideoReceiver", &MediaSession::CreateRtpVideoReceiver) - .function("setRtcpCallback", &MediaSession::SetRtcpCallback); + .function("setRtcpCallback", &MediaSession::SetRtcpCallback) + .class_function("get", &MediaSession::Get, + emscripten::allow_raw_pointers()); emscripten::class_("RtpVideoReceiver") .smart_ptr>("RtpVideoReceiver") .function("onRtpPacket", &RtpVideoReceiver::OnRtpPacket, diff --git a/talk/owt/sdk/wasm/main.cc b/talk/owt/sdk/wasm/main.cc index a36521c3d..2c8821a58 100644 --- a/talk/owt/sdk/wasm/main.cc +++ b/talk/owt/sdk/wasm/main.cc @@ -2,17 +2,10 @@ // // SPDX-License-Identifier: Apache-2.0 -#include #include -#include "third_party/webrtc/rtc_base/strings/json.h" #include "talk/owt/sdk/wasm/binding.h" int main(int argc, char** argv) { - Json::Value in_s("foo"); - std::string out; - rtc::GetStringFromJson(in_s, &out); - std::cout << out << std::endl; - - printf("WASM main.\n"); + owt::wasm::MediaSession::Get(); return 0; } \ No newline at end of file diff --git a/talk/owt/sdk/wasm/media_session.cc b/talk/owt/sdk/wasm/media_session.cc index 809131baa..5861b1d0f 100644 --- a/talk/owt/sdk/wasm/media_session.cc +++ b/talk/owt/sdk/wasm/media_session.cc @@ -9,6 +9,7 @@ namespace owt { namespace wasm { + MediaSession::MediaSession() : task_queue_factory_(webrtc::CreateTaskQueueStdlibFactory()), event_log_factory_(std::make_unique( @@ -50,6 +51,16 @@ std::shared_ptr MediaSession::CreateRtpVideoReceiver( return video_receiver_; } +std::once_flag create_media_session_flag; +std::shared_ptr media_session; + +MediaSession* MediaSession::Get() { + std::call_once(create_media_session_flag, + [] { media_session = std::make_shared(); }); + return media_session.get(); +} + + void MediaSession::SetRtcpCallback(emscripten::val callback) { rtcp_callback_ = callback; } diff --git a/talk/owt/sdk/wasm/media_session.h b/talk/owt/sdk/wasm/media_session.h index a46eba051..f21bd81b6 100644 --- a/talk/owt/sdk/wasm/media_session.h +++ b/talk/owt/sdk/wasm/media_session.h @@ -18,6 +18,9 @@ class MediaSession : public webrtc::Transport { public: explicit MediaSession(); virtual ~MediaSession() = default; + + static MediaSession* Get(); + std::shared_ptr CreateRtpVideoReceiver( uint32_t remote_ssrc); void SetRtcpCallback(emscripten::val callback); From 50bcb1cfe7a219c28655faab2e95461ee2e2e8a9 Mon Sep 17 00:00:00 2001 From: Jianjun Zhu Date: Thu, 9 Jun 2022 18:46:06 +0800 Subject: [PATCH 9/9] Add patches for untracked repositories. --- scripts/prepare_dev.py | 6 ++++- .../owt/patches/0018-Support-wasm-build.patch | 25 +++++++++++++++++++ .../owt/patches/0019-Support-wasm-build.patch | 25 +++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 talk/owt/patches/0018-Support-wasm-build.patch create mode 100644 talk/owt/patches/0019-Support-wasm-build.patch diff --git a/scripts/prepare_dev.py b/scripts/prepare_dev.py index d6ed6a8fe..90f1af354 100644 --- a/scripts/prepare_dev.py +++ b/scripts/prepare_dev.py @@ -19,6 +19,8 @@ LIBSRTP_PATH = os.path.join(THIRD_PARTY_PATH, 'libsrtp') FFMPEG_PATH = os.path.join(THIRD_PARTY_PATH, 'ffmpeg') LIBVPX_PATH = os.path.join(THIRD_PARTY_PATH, 'libvpx') +LIBJPEG_TURBO_PATH = os.path.join(THIRD_PARTY_PATH, 'libjpeg_turbo') +NASM_PATH = os.path.join(THIRD_PARTY_PATH, 'nasm') LIBVPX_SOURCE_PATH = os.path.join(LIBVPX_PATH, 'source/libvpx') WEBRTC_OVERRIDES_PATH = os.path.join(THIRD_PARTY_PATH, 'webrtc_overrides') BUILD_PATH = os.path.join(HOME_PATH, 'build') @@ -45,7 +47,9 @@ ('0014-Fix-missing-ffmpeg-configure-item-for-msvc-build.patch', FFMPEG_PATH), ('0015-Remove-custom-d8-dependency.patch', BUILD_PATH), ('0016-Remove-deprecated-create_srcjar-property.patch', THIRD_PARTY_PATH), - ('0017-Build-libvpx-with-RTC-rate-control-impl-included.patch', THIRD_PARTY_PATH) + ('0017-Build-libvpx-with-RTC-rate-control-impl-included.patch', THIRD_PARTY_PATH), + ('0018-Support-wasm-build.patch', LIBJPEG_TURBO_PATH), + ('0019-Support-wasm-build.patch', NASM_PATH) ] def _patch(ignoreFailures=False): diff --git a/talk/owt/patches/0018-Support-wasm-build.patch b/talk/owt/patches/0018-Support-wasm-build.patch new file mode 100644 index 000000000..0db725a93 --- /dev/null +++ b/talk/owt/patches/0018-Support-wasm-build.patch @@ -0,0 +1,25 @@ +From e4850e5a4ae4eb73f7a3625b332241d7cd941c3a Mon Sep 17 00:00:00 2001 +From: Jianjun Zhu +Date: Thu, 9 Jun 2022 18:38:00 +0800 +Subject: [PATCH] Support wasm build. + +--- + BUILD.gn | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/BUILD.gn b/BUILD.gn +index f9c483e..e18123d 100644 +--- a/BUILD.gn ++++ b/BUILD.gn +@@ -277,7 +277,7 @@ static_library("libjpeg") { + + # MemorySanitizer doesn't support assembly code, so keep it disabled in + # MSan builds for now. +- if (is_msan) { ++ if (is_msan || is_wasm) { + sources += [ "jsimd_none.c" ] + } else { + public_deps += [ ":simd" ] +-- +2.36.1 + diff --git a/talk/owt/patches/0019-Support-wasm-build.patch b/talk/owt/patches/0019-Support-wasm-build.patch new file mode 100644 index 000000000..28e5cd857 --- /dev/null +++ b/talk/owt/patches/0019-Support-wasm-build.patch @@ -0,0 +1,25 @@ +From d723c37c9a9be8796036602df510fe1c16e68e92 Mon Sep 17 00:00:00 2001 +From: Jianjun Zhu +Date: Thu, 9 Jun 2022 18:50:34 +0800 +Subject: [PATCH] Support wasm build. + +--- + nasm_assemble.gni | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/nasm_assemble.gni b/nasm_assemble.gni +index 902a6320..d2724feb 100644 +--- a/nasm_assemble.gni ++++ b/nasm_assemble.gni +@@ -67,6 +67,8 @@ if (is_mac || is_ios) { + } else if (current_cpu == "x64") { + _nasm_flags = [ "-fwin64" ] + } ++} else { ++ _nasm_flags = [] + } + + if (is_win) { +-- +2.36.1 +