腾讯 TRRO SDK 深度剖析
本文基于腾讯云 TRRO(Tencent Real-time Remote Operation) 工业能源版官方 SDK 发行包、头文件、License 清单与 Demo 工程,结合 现场设备端 / 远端设备端 文档,从 产品定位、产物矩阵、技术栈与依赖、跨平台 C ABI 架构、三通道原理、双端分工 等层面展开。
速览
- 双端模型 :现场 Gateway/Field (
libtrro_field+trro_field.h)+ 远端 Controller/Remote (libtrro_remote+trro_remote.h),C ABI flat API。- 三通道 :MQTT 信令 + WebRTC 音视频 + 独立二进制控制通道(QoS 0/1,带 VCCT/RCCT 度量)。
- 工业能力 :Multipath(视频融合调度 + 控制双发)、
master/guest仲裁、按需推流、最高 8 路、私有化部署。- 底层三分库 :
libtrro_field|remote+librtc_media+librtc_engine;现场端 FFmpeg 3.x 目录 ,远端 Linux 包附带 FFmpeg 6.1.2 系.so。- 版本线索 :官方文档口径 2.4.3 ;Web SDK 包内嵌 2.4.7.0 ;C SDK 运行时
TRRO_getSdkVersion()/TRRO_getVersion()为准。
目录
- [1. 产品定位](#1. 产品定位)
- [2. SDK 版本矩阵与产物包](#2. SDK 版本矩阵与产物包)
- [2.1 官方版本对照](#2.1 官方版本对照)
- [2.2 顶层包结构](#2.2 顶层包结构)
- [3. 技术栈与二进制依赖](#3. 技术栈与二进制依赖)
- [3.5 跨平台 C ABI 与绑定层](#3.5 跨平台 C ABI 与绑定层)
- [4. 系统原理:云管端 + 三通道模型](#4. 系统原理:云管端 + 三通道模型)
- [4.5 多网卡与 Multipath 实现](#4.5 多网卡与 Multipath 实现)
- [4.6 弱网传输(单链路能力)](#4.6 弱网传输(单链路能力))
- [5. 现场设备端(Field / Gateway)](#5. 现场设备端(Field / Gateway))
- [6. 远端设备端(Remote / Controller)](#6. 远端设备端(Remote / Controller))
- [6.4 接管权限流程(master / guest)](#6.4 接管权限流程(master / guest))
- [6.5 各平台 SDK 产物矩阵](#6.5 各平台 SDK 产物矩阵)
- [6.6 官方 Demo 与语言绑定](#6.6 官方 Demo 与语言绑定)
- [6.7 官方 Demo 胶水层实现详解](#6.7 官方 Demo 胶水层实现详解)
- [6.7.1 总览:六种胶水模式](#6.7.1 总览:六种胶水模式)
- [6.7.2 C/C++ 直连(零胶水)](#6.7.2 C/C++ 直连(零胶水))
- [6.7.3 Go CGO(远端)](#6.7.3 Go CGO(远端))
- [6.7.4 Python ctypes(双端)](#6.7.4 Python ctypes(双端))
- [6.7.5 Java JNA(远端 Linux)](#6.7.5 Java JNA(远端 Linux))
- [6.7.6 Android AAR + JNI(双端)](#6.7.6 Android AAR + JNI(双端))
- [6.7.7 Unity 双路径(P/Invoke + AndroidJavaObject)](#6.7.7 Unity 双路径(P/Invoke + AndroidJavaObject))
- [6.7.8 iOS / HarmonyOS / Web(官方封装,Demo 无自研胶水)](#6.7.8 iOS / HarmonyOS / Web(官方封装,Demo 无自研胶水))
- [7. 接入要点与踩坑](#7. 接入要点与踩坑)
- [8. 一句话总结](#8. 一句话总结)
- [9. 延伸阅读](#9. 延伸阅读)
1. 产品定位
腾讯云 实时互动-工业能源版 TRRO 面向工业遥操场景:Robotaxi 安全接管、工程机械远程操控、具身智能数采、机器人运维等。SDK 以 现场网关(Gateway)+ 远端控制器(Controller) 双端模型组织:设备注册上线,远端通过 TRRO_connectField 拉取多路视频并下发控制。
| 维度 | 说明 |
|---|---|
| 产品族 | 腾讯云 TRRO 工业能源版 |
| 典型场景 | 远控、多路监控、数采、运维 |
| API 形态 | C ABI:TRRO_init* / TRRO_connectField() 等;各平台再包 Java/ObjC/Web |
| 鉴权 | device_id + password + certificate + License |
| 控制通道 | 独立二进制控制通道,QoS 0/1,内建 VCCT/RCCT 度量 |
| 多路视频 | 单现场设备最高 8 路 |
| 多网融合 | Multipath + network_bind |
| 接管权限 | master / guest 仲裁 |
| 部署 | 公有云 / 国际站 / 私有化 (server_ip:2883) |
2. SDK 版本矩阵与产物包
TRRO 工业能源版按 现场端 / 远端端 分 SDK 发布,并配套多平台 Demo。官方文档当前版本 2.4.3 ,支持 Linux / Windows / Android / iOS / Web / HarmonyOS (远端设备端文档)。
说明 :部分文档分析素材包可能仅含头文件、配置、License 与 Demo 源码;
.so/.dll/.aar等运行时二进制需从 腾讯云 TRRO 控制台 下载完整 SDK 。下文库名来自官方包内MD5.txt、readme、lib_install.sh与 Demo 引用。
2.1 官方版本对照
| 平台 / 产物 | 版本线索 | 产物形态 | 角色 |
|---|---|---|---|
| 现场 C SDK(Linux aarch64) | 运行时 TRRO_getSdkVersion() |
trro_field.h + libtrro_field.so + sdk_lib/{nvidia,soft,ffmpeg3} |
Gateway 推流 |
| 现场 C SDK(Linux x64) | 同上 | 精简包:头文件 + 配置 + run_loader_x64.sh |
同上 |
| 现场 Android | Demo 分支 v1.1.1 | *.aar(TrroGateway Java API) |
车端/机器人 Android 网关 |
| 远端 C SDK(Linux x64) | 包名 linux_x64_release |
trro_remote.h + libtrro_remote.so + FFmpeg 6.x third_lib/ |
操控端拉流 |
| 远端 C SDK(Windows x64) | 文件夹名 win_x86(实际 x64 DLL) |
trro_remote.dll + 头文件 |
PC 安全员台 |
| 远端 iOS | --- | TRROControl.framework(ObjC:TrroRemote / TrroGateway) |
平板/手机远控 |
| 远端 Web | 外层 v2.4.0_r67,内嵌 2.4.7.0 | index.js + index.d.ts |
浏览器操控台 |
| 远端 Android | Demo v1.1.1 | AAR + com.tencent.trro.api.* |
移动端远控 |
| 远端 HarmonyOS | Demo v1.1.1 | sdklibrary.har + ArkTS com.tencent.trro.api.* |
鸿蒙远控 |
| 远端 Unity | Unity 2021.3+ | remoteuinty-release.aar + Windows Plugins DLL 组 |
云游戏/HMI 原型 |
| 官方文档 | 2.4.3 | API 说明 | --- |
2.2 顶层包结构
典型官方下载目录分为 现场设备端 、远端设备端 、demo 三大类:
text
TRRO 工业能源版 SDK 包
├── 现场设备端/
│ ├── trro-gateway-sdk-release-aarch64/ ← Linux ARM(Jetson nvidia / 通用 soft+RK)
│ └── trro-gateway-sdk-release-x64/ ← Linux x64 现场包
├── 远端设备端/
│ ├── trro-controller-sdk-linux_x64_release/
│ ├── trro_remote_sdk-win_x86/ ← Windows x64
│ ├── TRROControl/ ← iOS Framework
│ └── trro_web_sdk/ ← Web TRROSDK
└── demo/ ← 11 个子工程(C++/Qt/Go/Java/Python/Unity/...)
现场 aarch64 完整包 额外含:trro_sample.cpp、config_gen.py、device.pem、trro_field_license.txt、trro_field_doc/(Doxygen HTML)、GetDeviceInfo 设备指纹工具、run_loader.sh。
3. 技术栈与二进制依赖
3.1 三分库架构
TRRO Native 侧统一拆为 产品封装 + 媒体 + 传输 三个动态库(Windows 为同名 DLL):
| 库 | 现场端 | 远端端 | 职责 |
|---|---|---|---|
| 产品层 | libtrro_field.so |
libtrro_remote.so / trro_remote.dll |
TRRO 业务:MQTT 信令、设备注册、Multipath 配置、控制通道、权限仲裁 |
| 媒体层 | librtc_media.so |
同左 | 采集/编码/解码/渲染、FFmpeg 桥接、硬编硬解适配 |
| 传输层 | librtc_engine.so |
同左 | WebRTC 族 ICE/SRTP、拥塞控制、FEC/NACK、DataChannel 类控制承载 |
现场端 readme 典型链接命令:
bash
g++ trro_sample.cpp -o trro-test -I ./include \
-L ./sdk_lib/ -L ./sdk_lib/soft \
-ltrro_field -lrtc_media -lrtc_engine -pthread -ldl \
-Wl,--rpath-link=./sdk_lib/ffmpeg3
远端 Linux 包另含 lib_install.sh,为 sdk_lib/third_lib/ 下 FFmpeg 6.x 创建 libavcodec.so 等软链。
3.2 核心分层
#mermaid-svg-yJxgFxF89QX6O2Jv{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-yJxgFxF89QX6O2Jv .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-yJxgFxF89QX6O2Jv .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-yJxgFxF89QX6O2Jv .error-icon{fill:#552222;}#mermaid-svg-yJxgFxF89QX6O2Jv .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-yJxgFxF89QX6O2Jv .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-yJxgFxF89QX6O2Jv .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-yJxgFxF89QX6O2Jv .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-yJxgFxF89QX6O2Jv .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-yJxgFxF89QX6O2Jv .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-yJxgFxF89QX6O2Jv .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-yJxgFxF89QX6O2Jv .marker{fill:#333333;stroke:#333333;}#mermaid-svg-yJxgFxF89QX6O2Jv .marker.cross{stroke:#333333;}#mermaid-svg-yJxgFxF89QX6O2Jv svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-yJxgFxF89QX6O2Jv p{margin:0;}#mermaid-svg-yJxgFxF89QX6O2Jv .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-yJxgFxF89QX6O2Jv .cluster-label text{fill:#333;}#mermaid-svg-yJxgFxF89QX6O2Jv .cluster-label span{color:#333;}#mermaid-svg-yJxgFxF89QX6O2Jv .cluster-label span p{background-color:transparent;}#mermaid-svg-yJxgFxF89QX6O2Jv .label text,#mermaid-svg-yJxgFxF89QX6O2Jv span{fill:#333;color:#333;}#mermaid-svg-yJxgFxF89QX6O2Jv .node rect,#mermaid-svg-yJxgFxF89QX6O2Jv .node circle,#mermaid-svg-yJxgFxF89QX6O2Jv .node ellipse,#mermaid-svg-yJxgFxF89QX6O2Jv .node polygon,#mermaid-svg-yJxgFxF89QX6O2Jv .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-yJxgFxF89QX6O2Jv .rough-node .label text,#mermaid-svg-yJxgFxF89QX6O2Jv .node .label text,#mermaid-svg-yJxgFxF89QX6O2Jv .image-shape .label,#mermaid-svg-yJxgFxF89QX6O2Jv .icon-shape .label{text-anchor:middle;}#mermaid-svg-yJxgFxF89QX6O2Jv .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-yJxgFxF89QX6O2Jv .rough-node .label,#mermaid-svg-yJxgFxF89QX6O2Jv .node .label,#mermaid-svg-yJxgFxF89QX6O2Jv .image-shape .label,#mermaid-svg-yJxgFxF89QX6O2Jv .icon-shape .label{text-align:center;}#mermaid-svg-yJxgFxF89QX6O2Jv .node.clickable{cursor:pointer;}#mermaid-svg-yJxgFxF89QX6O2Jv .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-yJxgFxF89QX6O2Jv .arrowheadPath{fill:#333333;}#mermaid-svg-yJxgFxF89QX6O2Jv .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-yJxgFxF89QX6O2Jv .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-yJxgFxF89QX6O2Jv .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-yJxgFxF89QX6O2Jv .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-yJxgFxF89QX6O2Jv .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-yJxgFxF89QX6O2Jv .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-yJxgFxF89QX6O2Jv .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-yJxgFxF89QX6O2Jv .cluster text{fill:#333;}#mermaid-svg-yJxgFxF89QX6O2Jv .cluster span{color:#333;}#mermaid-svg-yJxgFxF89QX6O2Jv div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-yJxgFxF89QX6O2Jv .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-yJxgFxF89QX6O2Jv rect.text{fill:none;stroke-width:0;}#mermaid-svg-yJxgFxF89QX6O2Jv .icon-shape,#mermaid-svg-yJxgFxF89QX6O2Jv .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-yJxgFxF89QX6O2Jv .icon-shape p,#mermaid-svg-yJxgFxF89QX6O2Jv .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-yJxgFxF89QX6O2Jv .icon-shape .label rect,#mermaid-svg-yJxgFxF89QX6O2Jv .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-yJxgFxF89QX6O2Jv .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-yJxgFxF89QX6O2Jv .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-yJxgFxF89QX6O2Jv :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 编解码与处理
信令与接入
媒体引擎
TRRO SDK 封装层
应用层
ICE: host/srflx/prflx/relay
现场业务:相机/CAN/杆量
操控端:HMI/VR/安全员台
libtrro_field.so
trro_field.h
libtrro_remote.so
trro_remote.h
librtc_media.so
采集/编码/解码/渲染
librtc_engine.so
WebRTC 传输栈
MQTT (paho.mqtt.c)
设备注册/在线/配置下发
device.pem 证书链
FFmpeg3
硬编:NVENC / RK / 地平线 / MediaCodec
硬解:NVENC/D3D/MediaCodec
TRRO 云端 SFU/接入
3.2.1 二进制模块依赖链
text
应用
└─ libtrro_field.so / libtrro_remote.so ← TRRO 业务:MQTT、Multipath、控制通道、权限
├─ librtc_media.so ← 编解码、采集、渲染、FFmpeg 桥接
│ ├─ sdk_lib/ffmpeg3/(现场 ARM)或 third_lib/libav*.so.60(远端 Linux)
│ └─ 平台硬编插件(NVENC / RK / MediaCodec / VideoToolbox 等)
└─ librtc_engine.so ← WebRTC 传输:ICE/SRTP/FEC/NACK/DataChannel
└─ OpenSSL + libsrtp(License 披露)
3.3 开源与第三方组件(License 文件披露)
trro_field_license.txt / trro_remote_license.txt 列出主要依赖(节选):
| 组件 | License | 版本/说明 | 用途 |
|---|---|---|---|
| WebRTC | BSD 3-Clause | 内嵌于 librtc_engine |
ICE、SRTP、拥塞控制、JitterBuffer |
| libsrtp | BSD 3-Clause | 随 WebRTC 栈 | SRTP 加解密 |
| FFmpeg | LGPL 2.1+ | 现场包目录名 ffmpeg3 ;License 声明源码 6.1.2 (远端 libavcodec.so.60 等) |
转码、RTSP、软编解、缩放 |
| OpenSSL | Apache 2.0 | 3.0.12(License 中 zip 链接) | TLS、MQTT/HTTPS 证书校验 |
| paho.mqtt.c | EPL/EDL | --- | MQTT 信令(Demo 日志可见 mqtt kickout → kTrroKickout) |
| curl | curl license | --- | HTTP 配置/日志上报 |
| zlib | zlib license | --- | 压缩 |
| cJSON | MIT | --- | JSON 配置解析 |
| spdlog | MIT | --- | 日志 |
FFmpeg 版本说明 :现场 aarch64 包 readme 仍写
sdk_lib/ffmpeg3目录名(历史命名);远端 Controller Linux 包third_lib/使用 FFmpeg 6.x soname(libavcodec.so.60、libavutil.so.58等,与 6.1.2 License 条目一致)。集成时 勿混用 两套 FFmpeg 目录到同一LD_LIBRARY_PATH。
3.4 编解码与传输能力
头文件 trro_field.h 中 TrroCodec 枚举:
| 值 | 枚举 | 说明 |
|---|---|---|
| 0 | Trro_H264 |
H.264 |
| 1 | Trro_H265 |
H.265 |
| 2 | Trro_AV1 |
AV1 |
| 20 | Trro_OPUS |
音频 OPUS |
| 能力 | 现场端 | 远端端 |
|---|---|---|
| 视频编码 | H.264 / H.265 / AV1 硬编 + H.264 软编 | --- |
| 视频解码 | --- | H.264/H.265/AV1,平台硬解 |
| 音频 | OPUS,PCM 外部输入 | PCM 混音回调(TRRO_onRemoteMixAudioFrame,10ms 16bit) |
| 硬编平台 | NVIDIA Jetson(sdk_lib/nvidia)、RK、地平线、Android MediaCodec |
--- |
| 传输 | 抗弱网低延迟 UDP(WebRTC 栈) | 同左 |
| 穿网模式 | ICE:host / srflx / prflx / relay(TRRO_onMediaState 的 stun 字段) |
同左 |
3.5 跨平台 C ABI 与绑定层
与通用 RTC SDK(C++ 抽象类 + Java/ObjC 绑定)不同,TRRO 对外主契约是 C flat API:
c
// trro_remote.h --- extern "C" + 函数指针回调
typedef void (STD_CALL *TRRO_onAllLatencyReport)(void* context, const char* gwid,
int conn_fd, long long latency1, long long latency2,
long long videotime, int rcct);
TRRO_EXPORT int TRRO_connectField(const char* gwid, int streams_num,
int streams_id[], int conn_fds[]);
| 集成方式 | API 面 | 绑定方式 |
|---|---|---|
| Linux/Windows C/C++ | trro_field.h / trro_remote.h |
直接链接 .so/.dll |
| Android | com.tencent.trro.api.TrroGateway / TrroRemote |
AAR + JNI → 同上三分库 |
| iOS | TrroRemote、TrroGateway(ObjC) |
TRROControl.framework |
| Web | TRROSDK class(index.d.ts) |
浏览器 WebRTC + 独立信令栈,非 Native .so |
| HarmonyOS | com.tencent.trro.api.*(ArkTS) |
sdklibrary.har |
| Unity | TrroInterface.cs / TrroDemo.cs |
P/Invoke / Android AAR |
| Go / Python / Java | Demo 工程 | CGO / ctypes / JNA 薄封装(详见 [§6.7](#集成方式 API 面 绑定方式 Linux/Windows C/C++ trro_field.h / trro_remote.h 直接链接 .so/.dll Android com.tencent.trro.api.TrroGateway / TrroRemote AAR + JNI → 同上三分库 iOS TrroRemote、TrroGateway(ObjC) TRROControl.framework Web TRROSDK class(index.d.ts) 浏览器 WebRTC + 独立信令栈,非 Native .so HarmonyOS com.tencent.trro.api.*(ArkTS) sdklibrary.har Unity TrroInterface.cs / TrroDemo.cs P/Invoke / Android AAR Go / Python / Java Demo 工程 CGO / ctypes / JNA 薄封装(详见 §6.7))) |
Windows 头文件对 C# 友好:USE_CSHARP + __stdcall(STD_CALL)导出约定。
#mermaid-svg-pNmRtToWbtQWR5Vu{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-pNmRtToWbtQWR5Vu .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-pNmRtToWbtQWR5Vu .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-pNmRtToWbtQWR5Vu .error-icon{fill:#552222;}#mermaid-svg-pNmRtToWbtQWR5Vu .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-pNmRtToWbtQWR5Vu .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-pNmRtToWbtQWR5Vu .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-pNmRtToWbtQWR5Vu .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-pNmRtToWbtQWR5Vu .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-pNmRtToWbtQWR5Vu .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-pNmRtToWbtQWR5Vu .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-pNmRtToWbtQWR5Vu .marker{fill:#333333;stroke:#333333;}#mermaid-svg-pNmRtToWbtQWR5Vu .marker.cross{stroke:#333333;}#mermaid-svg-pNmRtToWbtQWR5Vu svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-pNmRtToWbtQWR5Vu p{margin:0;}#mermaid-svg-pNmRtToWbtQWR5Vu .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-pNmRtToWbtQWR5Vu .cluster-label text{fill:#333;}#mermaid-svg-pNmRtToWbtQWR5Vu .cluster-label span{color:#333;}#mermaid-svg-pNmRtToWbtQWR5Vu .cluster-label span p{background-color:transparent;}#mermaid-svg-pNmRtToWbtQWR5Vu .label text,#mermaid-svg-pNmRtToWbtQWR5Vu span{fill:#333;color:#333;}#mermaid-svg-pNmRtToWbtQWR5Vu .node rect,#mermaid-svg-pNmRtToWbtQWR5Vu .node circle,#mermaid-svg-pNmRtToWbtQWR5Vu .node ellipse,#mermaid-svg-pNmRtToWbtQWR5Vu .node polygon,#mermaid-svg-pNmRtToWbtQWR5Vu .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-pNmRtToWbtQWR5Vu .rough-node .label text,#mermaid-svg-pNmRtToWbtQWR5Vu .node .label text,#mermaid-svg-pNmRtToWbtQWR5Vu .image-shape .label,#mermaid-svg-pNmRtToWbtQWR5Vu .icon-shape .label{text-anchor:middle;}#mermaid-svg-pNmRtToWbtQWR5Vu .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-pNmRtToWbtQWR5Vu .rough-node .label,#mermaid-svg-pNmRtToWbtQWR5Vu .node .label,#mermaid-svg-pNmRtToWbtQWR5Vu .image-shape .label,#mermaid-svg-pNmRtToWbtQWR5Vu .icon-shape .label{text-align:center;}#mermaid-svg-pNmRtToWbtQWR5Vu .node.clickable{cursor:pointer;}#mermaid-svg-pNmRtToWbtQWR5Vu .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-pNmRtToWbtQWR5Vu .arrowheadPath{fill:#333333;}#mermaid-svg-pNmRtToWbtQWR5Vu .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-pNmRtToWbtQWR5Vu .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-pNmRtToWbtQWR5Vu .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pNmRtToWbtQWR5Vu .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-pNmRtToWbtQWR5Vu .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pNmRtToWbtQWR5Vu .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-pNmRtToWbtQWR5Vu .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-pNmRtToWbtQWR5Vu .cluster text{fill:#333;}#mermaid-svg-pNmRtToWbtQWR5Vu .cluster span{color:#333;}#mermaid-svg-pNmRtToWbtQWR5Vu div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-pNmRtToWbtQWR5Vu .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-pNmRtToWbtQWR5Vu rect.text{fill:none;stroke-width:0;}#mermaid-svg-pNmRtToWbtQWR5Vu .icon-shape,#mermaid-svg-pNmRtToWbtQWR5Vu .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pNmRtToWbtQWR5Vu .icon-shape p,#mermaid-svg-pNmRtToWbtQWR5Vu .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-pNmRtToWbtQWR5Vu .icon-shape .label rect,#mermaid-svg-pNmRtToWbtQWR5Vu .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pNmRtToWbtQWR5Vu .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-pNmRtToWbtQWR5Vu .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-pNmRtToWbtQWR5Vu :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Native 三分库
C ABI 契约层
语言绑定
独立实现
Android Java AAR
iOS TrroRemote
Web TRROSDK.js
Go/Python/JNA/Unity
trro_field.h
trro_remote.h
libtrro_field / libtrro_remote
librtc_media
librtc_engine
TRRO 云端
4. 系统原理:云管端 + 三通道模型
4.1 端到端数据流
远端设备端 libtrro_remote TRRO 云端 MQTT + SFU 现场设备端 libtrro_field 远端设备端 libtrro_remote TRRO 云端 MQTT + SFU 现场设备端 libtrro_field #mermaid-svg-tbufCJTcwYs3z6aw{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-tbufCJTcwYs3z6aw .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-tbufCJTcwYs3z6aw .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-tbufCJTcwYs3z6aw .error-icon{fill:#552222;}#mermaid-svg-tbufCJTcwYs3z6aw .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-tbufCJTcwYs3z6aw .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-tbufCJTcwYs3z6aw .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-tbufCJTcwYs3z6aw .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-tbufCJTcwYs3z6aw .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-tbufCJTcwYs3z6aw .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-tbufCJTcwYs3z6aw .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-tbufCJTcwYs3z6aw .marker{fill:#333333;stroke:#333333;}#mermaid-svg-tbufCJTcwYs3z6aw .marker.cross{stroke:#333333;}#mermaid-svg-tbufCJTcwYs3z6aw svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-tbufCJTcwYs3z6aw p{margin:0;}#mermaid-svg-tbufCJTcwYs3z6aw .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-tbufCJTcwYs3z6aw text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-tbufCJTcwYs3z6aw .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-tbufCJTcwYs3z6aw .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-tbufCJTcwYs3z6aw .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-tbufCJTcwYs3z6aw .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-tbufCJTcwYs3z6aw #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-tbufCJTcwYs3z6aw .sequenceNumber{fill:white;}#mermaid-svg-tbufCJTcwYs3z6aw #sequencenumber{fill:#333;}#mermaid-svg-tbufCJTcwYs3z6aw #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-tbufCJTcwYs3z6aw .messageText{fill:#333;stroke:none;}#mermaid-svg-tbufCJTcwYs3z6aw .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-tbufCJTcwYs3z6aw .labelText,#mermaid-svg-tbufCJTcwYs3z6aw .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-tbufCJTcwYs3z6aw .loopText,#mermaid-svg-tbufCJTcwYs3z6aw .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-tbufCJTcwYs3z6aw .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-tbufCJTcwYs3z6aw .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-tbufCJTcwYs3z6aw .noteText,#mermaid-svg-tbufCJTcwYs3z6aw .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-tbufCJTcwYs3z6aw .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-tbufCJTcwYs3z6aw .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-tbufCJTcwYs3z6aw .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-tbufCJTcwYs3z6aw .actorPopupMenu{position:absolute;}#mermaid-svg-tbufCJTcwYs3z6aw .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-tbufCJTcwYs3z6aw .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-tbufCJTcwYs3z6aw .actor-man circle,#mermaid-svg-tbufCJTcwYs3z6aw line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-tbufCJTcwYs3z6aw :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} ① 信令通道 (MQTT) ② 视频通道 (WebRTC/ICE) ③ 控制通道 (二进制透传) 注册 device_id + 证书 注册 + 拉取在线网关列表 TRRO_connectField(gwid, streams) 按需推流指令 (有人观看才推) H264/H265/AV1 多路编码流 SFU 转发 (不混流) 硬解 + 窗口渲染 / 外部解码回调 TRRO_sendControlData (qos 0/1) TRRO_onControlData 回调 TRRO_sendControlData (状态/回显) TRRO_onReportData 回调
4.2 三通道职责
| 通道 | 协议栈 | 承载内容 |
|---|---|---|
| 信令 | MQTT over TLS | 设备上下线、配置下发、权限、会话协调 |
| 视频/音频 | WebRTC (ICE + SRTP) | 多路编码视频、OPUS 音频 |
| 控制 | SDK 内独立 Data 通道 | 任意二进制(杆量、CAN 帧、关节指令等) |
控制通道是 TRRO 面向遥操的 核心能力。头文件中:
- 现场端:
TRRO_sendControlData(msg, len, qos)/TRRO_registerControlDataCallback - 远端端:
TRRO_sendControlData(gwid, msg, len, qos)/TRRO_registerReportDataCallback - QoS:
0 = unreliable(低延迟、可丢),1 = reliable(可靠传输) - 限流(头文件
trro_error_enum.h/trro_field.h):TRRO_MESSAGE_RATE_EXCEED:发送频率过高(3 秒内超过最大消息数)TRRO_MESSAGE_MAX_EXCEED:1 秒内发送数据量超过上限TRRO_MESSAGE_BYTE_EXCEED:单条或周期内消息长度超限
对应遥操文档中的「~100Hz 控制通道」------这是通道能力上限,实际频率受网络与限流约束。
4.3 关键时延指标(SDK 内建)
远端头文件 TRRO_onAllLatencyReport 定义了工业遥操最关心的口径:
| 指标 | 含义 |
|---|---|
latency1 |
视频上行时延(ms) |
latency2 |
视频上行 + 控制下行 时延 |
vcct(现场端 TRRO_onLatencyReport) |
视频控制闭环 = 视频上行(不含采集)+ 控制下行 |
rcct |
控制信道往返时延 = 控制上行 + 控制下行 |
videotime |
现场设备采集时间戳(帧对齐用) |
user_time |
用户自定义时间戳(外部输入 YUV/编码帧时打入) |
现场 Demo 用 TRRO_externalVideoDataWithUserTime 打用户时间戳,用于帧级对齐:
cpp
TRRO_externalVideoDataWithUserTime(id, data, data_width, data_height, 0, GetTime2(), 0);
4.4 建连过程(远端 SDK 暴露的 ICE 时间线)
TrroConnectCost 结构体把 WebRTC 建连拆成可观测阶段(T0→C9),便于 POC 定位瓶颈:
T0 受理 ConnectPeer
→ C0b 提交 main_loop
→ C1 RtcConfig 请求
→ C3 engine->Join
→ C4 onJoined 成功
→ C5 收到对端 publish
→ C5b 发起订阅
→ C5c 订阅成功
→ C7 ICE 连接中
→ C8 PEER_CONNECTED
→ C9 首帧到达(触发回调)
媒体面走的是 Join → Publish/Subscribe → ICE 的经典 WebRTC SFU 模式,而非 RTMP 推拉流。
4.5 多网卡与 Multipath 实现
TRRO 的 Multipath 不是 「主链路挂了再切备链路」的传统主备,而是 多路径同时可用 :切换下沉到传输栈,会话不断开、应用无感 。官方宣传在 Multipath 场景下网络切换 <50ms (多网聚合与切换)。详细配置见 多网络路径传输。
4.5.1 与主备倒换的差异
| 模式 | 故障感知 → 切换 | 切换时应用层 |
|---|---|---|
| 主备倒换 | 检测超时 → 换路由 → 常触发重连 | 黑屏、会话重建 |
| TRRO Multipath | 副路径已在传 / 调度已就绪 | 无 reconnect |
4.5.2 视频 vs 控制:两种 Multipath 策略
官方对 媒体 与 控制 采用不同策略(同一 network_bind 下):
| 路径 | 配置项 | 策略 | 带宽特点 |
|---|---|---|---|
| 视频/音频 | media_trans_mode |
融合多网 :按各链路 RTT/丢包 调度 到多张网卡 | 通常非全量 N 倍复制 |
| 控制/消息 | dc_double_trans_enable |
默认 消息双发 :同一 PDU 多路径同时发,对端取先到 | 双发时控制带宽约 ≈2× |
json
"network_bind": ["192.168.8.96", "192.168.67.96"],
"media_trans_mode": 1,
"dc_double_trans_enable": 1
media_trans_mode |
含义 | 适用 |
|---|---|---|
| 1(默认) | 5G 增强,切换最快 | 多 5G |
| 2 | 均衡 | 多网质量接近 |
| 3 | 4G 增强 | 多 4G |
dc_double_trans_enable |
含义 |
|---|---|
| 1(默认) | 控制通道双发,延迟敏感 |
| 0 | 关闭双发,控制也走融合调度 |
多网传输在计费上约有 ×1.2 带宽系数(相对单网),可按车队/路段选择性开启。
4.5.3 四层实现架构
#mermaid-svg-RzZzAn0qyxUKgEnp{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-RzZzAn0qyxUKgEnp .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-RzZzAn0qyxUKgEnp .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-RzZzAn0qyxUKgEnp .error-icon{fill:#552222;}#mermaid-svg-RzZzAn0qyxUKgEnp .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-RzZzAn0qyxUKgEnp .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-RzZzAn0qyxUKgEnp .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-RzZzAn0qyxUKgEnp .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-RzZzAn0qyxUKgEnp .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-RzZzAn0qyxUKgEnp .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-RzZzAn0qyxUKgEnp .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-RzZzAn0qyxUKgEnp .marker{fill:#333333;stroke:#333333;}#mermaid-svg-RzZzAn0qyxUKgEnp .marker.cross{stroke:#333333;}#mermaid-svg-RzZzAn0qyxUKgEnp svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-RzZzAn0qyxUKgEnp p{margin:0;}#mermaid-svg-RzZzAn0qyxUKgEnp .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-RzZzAn0qyxUKgEnp .cluster-label text{fill:#333;}#mermaid-svg-RzZzAn0qyxUKgEnp .cluster-label span{color:#333;}#mermaid-svg-RzZzAn0qyxUKgEnp .cluster-label span p{background-color:transparent;}#mermaid-svg-RzZzAn0qyxUKgEnp .label text,#mermaid-svg-RzZzAn0qyxUKgEnp span{fill:#333;color:#333;}#mermaid-svg-RzZzAn0qyxUKgEnp .node rect,#mermaid-svg-RzZzAn0qyxUKgEnp .node circle,#mermaid-svg-RzZzAn0qyxUKgEnp .node ellipse,#mermaid-svg-RzZzAn0qyxUKgEnp .node polygon,#mermaid-svg-RzZzAn0qyxUKgEnp .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-RzZzAn0qyxUKgEnp .rough-node .label text,#mermaid-svg-RzZzAn0qyxUKgEnp .node .label text,#mermaid-svg-RzZzAn0qyxUKgEnp .image-shape .label,#mermaid-svg-RzZzAn0qyxUKgEnp .icon-shape .label{text-anchor:middle;}#mermaid-svg-RzZzAn0qyxUKgEnp .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-RzZzAn0qyxUKgEnp .rough-node .label,#mermaid-svg-RzZzAn0qyxUKgEnp .node .label,#mermaid-svg-RzZzAn0qyxUKgEnp .image-shape .label,#mermaid-svg-RzZzAn0qyxUKgEnp .icon-shape .label{text-align:center;}#mermaid-svg-RzZzAn0qyxUKgEnp .node.clickable{cursor:pointer;}#mermaid-svg-RzZzAn0qyxUKgEnp .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-RzZzAn0qyxUKgEnp .arrowheadPath{fill:#333333;}#mermaid-svg-RzZzAn0qyxUKgEnp .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-RzZzAn0qyxUKgEnp .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-RzZzAn0qyxUKgEnp .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-RzZzAn0qyxUKgEnp .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-RzZzAn0qyxUKgEnp .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-RzZzAn0qyxUKgEnp .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-RzZzAn0qyxUKgEnp .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-RzZzAn0qyxUKgEnp .cluster text{fill:#333;}#mermaid-svg-RzZzAn0qyxUKgEnp .cluster span{color:#333;}#mermaid-svg-RzZzAn0qyxUKgEnp div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-RzZzAn0qyxUKgEnp .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-RzZzAn0qyxUKgEnp rect.text{fill:none;stroke-width:0;}#mermaid-svg-RzZzAn0qyxUKgEnp .icon-shape,#mermaid-svg-RzZzAn0qyxUKgEnp .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-RzZzAn0qyxUKgEnp .icon-shape p,#mermaid-svg-RzZzAn0qyxUKgEnp .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-RzZzAn0qyxUKgEnp .icon-shape .label rect,#mermaid-svg-RzZzAn0qyxUKgEnp .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-RzZzAn0qyxUKgEnp .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-RzZzAn0qyxUKgEnp .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-RzZzAn0qyxUKgEnp :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} TRRO 云端
librtc_engine
config.json
OS / 硬件
网卡1 → 运营商A
网卡2 → 运营商B
策略路由 ip rule + table
network_bind
media_trans_mode
dc_double_trans_enable
源 IP / 网卡绑定
视频:融合调度
控制:双发 + 去重
Multipath 融合网关
SFU 只转发
- OS 层 :每个
network_bindIP 须能 独立出公网(不同 SIM / 不同 CPE WAN)。 - SDK 配置层 :
network_bind开启多网;可选media_trans_mode、dc_double_trans_enable。 - 传输栈 :每链路独立 socket;
TrroMultiNetworkStats上报各 path 的 RTT/丢包/收发字节,供调度决策。 - 云端:Multipath 网关汇聚多 path 上行,与 SFU 转发配合。
4.5.4 OS 多网前置:策略路由
典型车端:多网卡各接不同 CPE,或单网卡多 IP(eth0:0 / eth0:1)+ 按源 IP 选路:
bash
ip rule add from 192.168.8.96 table 10
ip rule add from 192.168.67.96 table 20
ip route add default via 192.168.8.1 dev eth0 table 10
ip route add default via 192.168.67.1 dev eth1 table 20
验收 (官方要求):每个 bind IP 应打出 不同公网 IP:
bash
curl http://cip.cc --interface 192.168.8.96
curl http://cip.cc --interface 192.168.67.96
CPE 侧可参考:单 CPE 多 WAN(VLAN 分网段)或多 CPE 各接不同运营商。
4.5.5 SDK 配置与权限
config_gen.py 中开启示例:
python
json_data["network_bind"] = ["192.168.8.96", "192.168.67.96"]
物联网卡白名单 场景,network_bind 可带 DNS(物联网卡白名单配置):
json
"network_bind": [
"192.168.8.11/192.168.8.1",
"192.168.67.11/192.168.67.1"
]
绑定指定网卡需 cap_net_raw + cap_net_bind_service (或 root),否则 network_bind 可能失效:
bash
sudo setcap cap_net_raw,cap_net_bind_service+ep ./trro-test
4.5.6 运行时观测
现场端注册 按网卡粒度 统计(trro_field.h):
cpp
struct TrroMultiNetworkStats {
char local_ip[16]; int local_port;
char extern_ip[16]; int extern_port;
float rtt; float lost;
unsigned long long send_bytes, recv_bytes;
};
// TRRO_registerMultiNetworkStatsCallback(...)
结合 TRRO_onMediaState 的 stun 字段(0 host / 1 srflx / 2 prflx / 3 relay)可判断各 path 穿网形态。
4.5.7 与标准 WebRTC / MPTCP 对比
| 方案 | 多 SIM / 多网卡 |
|---|---|
| 标准 WebRTC | 无原生 Multipath;断网常 ICE restart |
| MPTCP | 内核层,车载/运营商 NAT 场景少见 |
| TRRO | network_bind + 自研 UDP 栈 融合/双发 + 云端 MP 网关 |
4.5.8 Multipath POC 检查清单
- 硬件:多 CPE / 多 SIM / 多网口(或单口多 IP + 策略路由)
- OS:
curl --interface验证多公网 IP - 配置:
network_bind+ 按需media_trans_mode/dc_double_trans_enable - 权限:
setcap或 root - 运行:注册
TRRO_registerMultiNetworkStatsCallback,观察各 path RTT/lost - 对比:单网 vs 多网 同路线跑 ≥1 周,测卡顿、切换时延、RCCT 尖刺
4.6 弱网传输(单链路能力)
Multipath 解决 多 path 切换 ;单条 path 上 TRRO 依赖 librtc_engine 内嵌 WebRTC 族栈的弱网算法:
| 机制 | 作用 |
|---|---|
| FEC | XOR + RS 类冗余,按帧类型动态 |
| NACK / ARQ | 时间序判丢 + 重传 |
| 拥塞控制 | 改良 GCC + 类 BBR,与编码码率联动 |
| JitterBuffer | 与 FEC/流控联动,初始队列偏浅(低延迟向) |
| SFU | 只转发不混流,减少云端处理时延 |
宣传口径:约 30% 丢包 下卡顿率 <1%(须 POC 实测,不可直接当 SLA)。
5. 现场设备端(Field / Gateway)
头文件 :trro_field.h
角色 :车端、机器人、挖机工控机、数采网关------多路采集编码 + 上行 + 接收控制
5.1 生命周期与信令状态
TRRO_initGwPathWithLicense(config.json, license.txt, mode)
→ TRRO_registerSignalStateCallback → kTrroReady // MQTT 信令就绪
→ TRRO_start() // 启动媒体业务
→ ... 运行 ...
→ TRRO_stop()
SignalState |
含义 |
|---|---|
kTrroReady |
信令连接成功 |
kTrroLost |
断开,SDK 自动重连 |
kTrroReup |
自动重连成功 |
kTrroKickout |
被踢(如 MQTT kickout) |
kTrroAuthFailed |
用户名/密码错误 |
初始化 API 族:TRRO_initGwPath / TRRO_initGwJson / TRRO_initGwPathWithLicense;mode=0 同步阻塞至就绪,mode=-1 异步经 TRRO_onSignalState 通知。
5.2 视频输入模式(streams_config)
config.json / config_gen.py 支持多种 protocol:
| protocol | 含义 | 典型硬件 |
|---|---|---|
v4l2 |
本地相机采集(DMA/MMAP) | USB 相机、GMSL |
outside |
外部喂 YUV(TRRO_externalVideoData*) |
自研 ISP 管线 |
outenc |
外部喂已编码 H264/H265 | 车端硬编后直接注入 |
rtsp_enc |
RTSP 拉流不转码直推 | 网络摄像机 |
| 普通 RTSP | 拉流 + 转码 | 异构源 |
配置示例(config.json 字段):
json
{
"projectid": "xxxx",
"device_id": "xxxx",
"device_streams": 1,
"streams_config": [{
"protocol": "v4l2",
"camera": 0,
"width": 1920, "height": 1080,
"encode_width": 1280, "encode_height": 720,
"bps": 2000, "always_push": 0, "codec": 0
}],
"sdk_mode": "server2",
"cloud_mode": "public"
}
5.3 现场端独有能力
| 能力 | API / 配置 | 原理 |
|---|---|---|
| 按需推流 | always_push: 0 |
远端无人观看时不推,省带宽 |
| 多网 Multipath | network_bind + §4.5 |
多 4G/5G/WiFi;TRRO_registerMultiNetworkStatsCallback |
| ROI 编码 | TRRO_setEncodeRoi |
重点区域高 QP,弱网保关键区域 |
| 接管权限仲裁 | TRRO_setOperationPermission / TRRO_onOperationPermissionRequest |
同时仅一个 master |
| 本地录制 | TRRO_startRecorder(实验性) |
旁路存 H264 |
| NVIDIA 零拷贝 | TRRO_externalVideoDataDmaNative |
Jetson DMA fd 输入 |
| 网络质量探测 | TRRO_testNetworkQuality |
指定流 ID 主动测网 |
| 密码热更新 | TRRO_updatePassword |
运行时更新 MQTT 密码 |
头文件 trro_error_enum.h / trro_field.h 按模块分段定义错误码(配置 0x01*、初始化 0x02*、License、控制限流 TRRO_MESSAGE_* 等),可用 getErrorMsg(code) 转文字。
5.4 sdk_mode 三种模式
| 模式 | 含义 |
|---|---|
p2p |
端到端直连倾向 |
server |
经云端 SFU 转发(私有化常用) |
server2 |
公有云推荐模式(config_gen.py 默认) |
5.5 部署模式与 cloud_mode
cloud_mode |
说明 | 典型配置 |
|---|---|---|
public |
国内公有云 | projectid、certificate、password;配置工具 console.trro.config |
public_intl |
国际站 | config_gen.py 中 use_international=True |
private |
私有化 | server_ip:2883(接入)、rtc_server_ip:rtc_server_port(媒体);最小启动后可经 http://serverip:8190/config_template 在线下发 streams_config |
私有化最小现场配置(readme.md):
json
{
"device_id": "test_gw",
"device_name": "test_gw",
"server_ip": "xxx.xxx.xxx.xxx",
"server_port": 2883
}
License :现场端 TRRO_initGwPathWithLicense;校验失败错误码含 TRRO_INIT_LICENSE_CHECK_*、公有云 TRRO_INIT_PUBLIC_LICENSE_CHECK_*(超时、未绑定、数量不足、过期等)。新用户可申请 2 周免费试用 License(2 个授权)。
断网重连 :现场端自管理------信令 kTrroLost → 自动重连 → kTrroReup;媒体 path 劣化时由 Multipath / 弱网算法恢复,无需应用层 rebuild 会话。
6. 远端设备端(Remote / Controller)
头文件 :trro_remote.h
角色 :安全员 PC、VR 头显、运维平板------拉多路视频 + 下发控制 + 渲染
6.1 生命周期
TRRO_initJson / TRRO_initJsonAsync(config)
→ TRRO_onSignalState(kTrroReady)
→ TRRO_connectField(gwid, streams_num, streams_id[], conn_fds[])
→ TRRO_setWindows(conn_fds[], HWND[], num) // 绑定渲染窗口
→ TRRO_sendControlData(gwid, msg, len, qos) // 下发控制
→ TRRO_disconnect / TRRO_destroy
远端配置比现场端简洁------不负责采集编码 ,只声明自身身份与最大流数(config.json.sample):
json
{
"device_id": "ctrl1",
"device_name": "vin234",
"cloud_mode": "public",
"certificate": "./device.pem",
"projectid": "******",
"password": "******",
"max_streams": 8
}
6.2 远端端独有能力
| 能力 | API | 用途 |
|---|---|---|
| 网关发现 | TRRO_getGwList() / TRRO_getGwInfo(gwid) |
列出在线现场设备 |
| 多路拉流 | TRRO_connectField + conn_fd 数组 |
最高 8 路并行 |
| 内部/外部渲染 | TRRO_setWindows / TRRO_registerRemoteFrameCallback |
窗口硬渲染或自研渲染管线 |
| 外部解码 | TRRO_useExternalDecoder + TRRO_registerRemoteEncodedFrameCallback |
自研 GPU 解码 |
| 权限申请 | TRRO_requestPermission(gwid, master/guest) |
接管前申请 master |
| 诊断 | TRRO_diagRequest → TRRO_OnDiagReport |
排障 JSON 报告 |
| 转推 CDN | TRRO_startMediaPush(conn_fd, rtmp_url) |
旁路录制/监管 |
| 导航线(实验) | TRRO_simpleNavigationLine / TRRO_cameraViewNavigationLine |
工程机械 AR 辅助线 |
| 远程调码率 | TRRO_fieldDeviceEncodeConfig(gwid, stream_id, json) |
操控端动态改现场编码参数 |
6.3 官方能力清单对照
远端设备端文档 列出的能力与头文件一致:视频渲染、H264/H265/AV1 解码、低延迟传输、二进制透传、推流管理、延时/链路报告、本地录制(Android 有,iOS 无)。
现场设备端文档 侧重:视频处理(采集/缩放/剪裁/拼接)、硬编、传输、二进制透传、推流自管理、断网重连。
6.4 接管权限流程(master / guest)
工业遥操要求 同一现场设备同一时刻仅一个 master 可发控;guest 仅观看。
现场设备 TRRO 云端 操控端B 操控端A 现场设备 TRRO 云端 操控端B 操控端A #mermaid-svg-M6F6VFpBvVQoF4IZ{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-M6F6VFpBvVQoF4IZ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-M6F6VFpBvVQoF4IZ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-M6F6VFpBvVQoF4IZ .error-icon{fill:#552222;}#mermaid-svg-M6F6VFpBvVQoF4IZ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-M6F6VFpBvVQoF4IZ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-M6F6VFpBvVQoF4IZ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-M6F6VFpBvVQoF4IZ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-M6F6VFpBvVQoF4IZ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-M6F6VFpBvVQoF4IZ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-M6F6VFpBvVQoF4IZ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-M6F6VFpBvVQoF4IZ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-M6F6VFpBvVQoF4IZ .marker.cross{stroke:#333333;}#mermaid-svg-M6F6VFpBvVQoF4IZ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-M6F6VFpBvVQoF4IZ p{margin:0;}#mermaid-svg-M6F6VFpBvVQoF4IZ .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-M6F6VFpBvVQoF4IZ text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-M6F6VFpBvVQoF4IZ .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-M6F6VFpBvVQoF4IZ .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-M6F6VFpBvVQoF4IZ .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-M6F6VFpBvVQoF4IZ .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-M6F6VFpBvVQoF4IZ #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-M6F6VFpBvVQoF4IZ .sequenceNumber{fill:white;}#mermaid-svg-M6F6VFpBvVQoF4IZ #sequencenumber{fill:#333;}#mermaid-svg-M6F6VFpBvVQoF4IZ #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-M6F6VFpBvVQoF4IZ .messageText{fill:#333;stroke:none;}#mermaid-svg-M6F6VFpBvVQoF4IZ .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-M6F6VFpBvVQoF4IZ .labelText,#mermaid-svg-M6F6VFpBvVQoF4IZ .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-M6F6VFpBvVQoF4IZ .loopText,#mermaid-svg-M6F6VFpBvVQoF4IZ .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-M6F6VFpBvVQoF4IZ .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-M6F6VFpBvVQoF4IZ .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-M6F6VFpBvVQoF4IZ .noteText,#mermaid-svg-M6F6VFpBvVQoF4IZ .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-M6F6VFpBvVQoF4IZ .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-M6F6VFpBvVQoF4IZ .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-M6F6VFpBvVQoF4IZ .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-M6F6VFpBvVQoF4IZ .actorPopupMenu{position:absolute;}#mermaid-svg-M6F6VFpBvVQoF4IZ .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-M6F6VFpBvVQoF4IZ .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-M6F6VFpBvVQoF4IZ .actor-man circle,#mermaid-svg-M6F6VFpBvVQoF4IZ line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-M6F6VFpBvVQoF4IZ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 非 master 调用 sendControlData → TRRO_UNAUTHORIZED TRRO_requestPermission(gwid, master) TRRO_onOperationPermissionRequest TRRO_setOperationPermission(R1, master) TRRO_OnOperationPermissionState(self=master) TRRO_requestPermission(gwid, master) 新 master 覆盖旧 master(仅一个 master)
| 角色 | 权限 | API |
|---|---|---|
| guest | 观看、拉流 | TRRO_connectField |
| master | 观看 + TRRO_sendControlData |
TRRO_requestPermission → 现场端 TRRO_setOperationPermission |
白名单 / 临时观看:TRRO_setSessionPermissionToken(gwid, signature)(未注册设备临时授权)。
6.5 各平台 SDK 产物矩阵
现场设备端(Field / Gateway)
| 平台 | 官方包 | 核心产物 | 备注 |
|---|---|---|---|
| Linux aarch64 | trro-gateway-sdk-release-aarch64 |
trro_field.h + 三分库 + ffmpeg3/ |
sdk_lib/nvidia(Jetson)、sdk_lib/soft(通用 ARM + RK 加速) |
| Linux x64 | trro-gateway-sdk-release-x64 |
同上(无 nvidia/soft 分目录的精简包) | run_loader_x64.sh |
| Android | 控制台 AAR + trro_gateway_demo_android |
TrroGateway Java API |
app/libs/*.aar,minSdk 24 |
远端设备端(Remote / Controller)
| 平台 | 官方包 | 核心产物 | 备注 |
|---|---|---|---|
| Linux x64 | trro-controller-sdk-linux_x64_release |
trro_remote.h + 三分库 + FFmpeg third_lib/ |
lib_install.sh 创建 .so 软链 |
| Windows x64 | trro_remote_sdk-win_x86 |
trro_remote.dll + 头文件 |
文件夹名 win_x86 易误解,MD5 为 x64 DLL |
| iOS | TRROControl.framework |
ObjC:TrroRemote、TrroGateway、TrroMedia |
含 PrivacyInfo.xcprivacy |
| Web | trro_web_sdk_v2.4.0_r67 |
index.js(内嵌 v2.4.7.0)+ TS 声明 |
Chrome/Edge 84+;公有云/国际站/私有化 Demo HTML |
| Android | 控制台 AAR + demo | TrroRemote |
与 Unity 共用 remoteuinty-release.aar |
| HarmonyOS | 控制台 HAR + demo | ArkTS API | 依赖 sdklibrary.har |
| Unity | demo Plugins | Windows:trro_remote.dll、rtc_*.dll、FFmpeg 60/58/9/7/4 系 DLL 组 |
Android:remoteuinty-release.aar;Unity 2021.3+,GLES 3.1 |
Unity Windows 插件依赖链 (Demo meta 引用,须完整拷贝):trro_remote.dll → rtc_media.dll → rtc_engine.dll → avcodec-60.dll / avformat-60.dll / avutil-58.dll / swscale-7.dll 等 + libcurl.dll + OpenGL/DX 运行库。
6.6 官方 Demo 与语言绑定
| Demo 工程 | 平台 | 语言/框架 | 说明 |
|---|---|---|---|
trro_gateway_demo_linux |
Linux | C++ | 外部 YUV/H264/H265/JPEG 推流 |
trro_gateway_demo_android |
Android | Java | 现场 TrroGateway 集成示例 |
trro_gateway_python |
Linux aarch64 | Python ctypes | 需放入现场 SDK 的 nvidia/soft 库路径 |
trro_remote_demo_win_linux |
Linux x64 + Win x64 | Qt 5.13 C++ | 多路拉流、布局、诊断;git 分支 v2.4.1 |
trro_remote_demo_ios |
iOS | ObjC + CocoaPods | 本地 pod 集成 TRROControl + rtc_engine.xcframework |
trro_remote_demo_android |
Android | Java | 远端拉流 |
trro_remote_demo_harmony |
HarmonyOS | ArkTS | 需 sdklibrary.har |
trro_remote_go |
Linux x64 | Go CGO | trro_remote.go 封装 C API |
trro_remote_java |
Linux | Java JNA | TrroJavaAPI.java |
trro_remote_python |
Linux x64/aarch64 + Win x64 | Python | 三套 SDK 目录 |
trro_remote_unity |
Android + Windows | Unity C# | TrroInterface.cs / TrroCallbackInterface.cs |
Web SDK 典型流程 (index.d.ts):初始化 TRROSDK → 配置 CloudMode(public / public_intl / private)→ 连接现场 gateway → 订阅 track → 收发 control data → 断开。信令状态机含 scheduling / scheduled / reconnecting 等,与 Native SignalState(kTrroReady / kTrroLost / kTrroReup)概念对应但枚举名不同。
设备指纹与 License :现场包提供 GetDeviceInfo 工具读取设备指纹;TRRO_initGwPathWithLicense(config, license.txt, mode) 校验 License(错误码 TRRO_INIT_LICENSE_CHECK_*、TRRO_INIT_PUBLIC_LICENSE_CHECK_*)。新用户可申请 2 周免费试用 License(2 个授权)。
6.7 官方 Demo 胶水层实现详解
官方 Demo 仓库的价值之一,是展示 如何把 C flat API 接到各语言运行时 。除 Android / iOS / HarmonyOS / Web 走 官方预封装 SDK 外,Linux/Windows 侧 Demo 普遍采用 「C ABI → 薄绑定 → 业务逻辑」 三层结构;绑定层只负责加载 .so/.dll、声明函数签名、把 C 函数指针回调桥回宿主语言,不重复实现信令/媒体栈。
#mermaid-svg-WylR152dWCvPcDDf{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-WylR152dWCvPcDDf .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-WylR152dWCvPcDDf .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-WylR152dWCvPcDDf .error-icon{fill:#552222;}#mermaid-svg-WylR152dWCvPcDDf .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-WylR152dWCvPcDDf .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-WylR152dWCvPcDDf .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-WylR152dWCvPcDDf .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-WylR152dWCvPcDDf .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-WylR152dWCvPcDDf .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-WylR152dWCvPcDDf .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-WylR152dWCvPcDDf .marker{fill:#333333;stroke:#333333;}#mermaid-svg-WylR152dWCvPcDDf .marker.cross{stroke:#333333;}#mermaid-svg-WylR152dWCvPcDDf svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-WylR152dWCvPcDDf p{margin:0;}#mermaid-svg-WylR152dWCvPcDDf .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-WylR152dWCvPcDDf .cluster-label text{fill:#333;}#mermaid-svg-WylR152dWCvPcDDf .cluster-label span{color:#333;}#mermaid-svg-WylR152dWCvPcDDf .cluster-label span p{background-color:transparent;}#mermaid-svg-WylR152dWCvPcDDf .label text,#mermaid-svg-WylR152dWCvPcDDf span{fill:#333;color:#333;}#mermaid-svg-WylR152dWCvPcDDf .node rect,#mermaid-svg-WylR152dWCvPcDDf .node circle,#mermaid-svg-WylR152dWCvPcDDf .node ellipse,#mermaid-svg-WylR152dWCvPcDDf .node polygon,#mermaid-svg-WylR152dWCvPcDDf .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-WylR152dWCvPcDDf .rough-node .label text,#mermaid-svg-WylR152dWCvPcDDf .node .label text,#mermaid-svg-WylR152dWCvPcDDf .image-shape .label,#mermaid-svg-WylR152dWCvPcDDf .icon-shape .label{text-anchor:middle;}#mermaid-svg-WylR152dWCvPcDDf .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-WylR152dWCvPcDDf .rough-node .label,#mermaid-svg-WylR152dWCvPcDDf .node .label,#mermaid-svg-WylR152dWCvPcDDf .image-shape .label,#mermaid-svg-WylR152dWCvPcDDf .icon-shape .label{text-align:center;}#mermaid-svg-WylR152dWCvPcDDf .node.clickable{cursor:pointer;}#mermaid-svg-WylR152dWCvPcDDf .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-WylR152dWCvPcDDf .arrowheadPath{fill:#333333;}#mermaid-svg-WylR152dWCvPcDDf .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-WylR152dWCvPcDDf .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-WylR152dWCvPcDDf .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-WylR152dWCvPcDDf .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-WylR152dWCvPcDDf .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-WylR152dWCvPcDDf .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-WylR152dWCvPcDDf .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-WylR152dWCvPcDDf .cluster text{fill:#333;}#mermaid-svg-WylR152dWCvPcDDf .cluster span{color:#333;}#mermaid-svg-WylR152dWCvPcDDf div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-WylR152dWCvPcDDf .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-WylR152dWCvPcDDf rect.text{fill:none;stroke-width:0;}#mermaid-svg-WylR152dWCvPcDDf .icon-shape,#mermaid-svg-WylR152dWCvPcDDf .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-WylR152dWCvPcDDf .icon-shape p,#mermaid-svg-WylR152dWCvPcDDf .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-WylR152dWCvPcDDf .icon-shape .label rect,#mermaid-svg-WylR152dWCvPcDDf .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-WylR152dWCvPcDDf .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-WylR152dWCvPcDDf .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-WylR152dWCvPcDDf :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Native 三分库
C ABI
胶水层
Demo 业务层
Qt / Tk / main.go / Demo.java
Go CGO
Python ctypes
Java JNA
Unity P/Invoke
Android AAR JNI
trro_field.h / trro_remote.h
libtrro_field / libtrro_remote
librtc_media + librtc_engine
FFmpeg .so/.dll
6.7.1 总览:六种胶水模式
| Demo 工程 | 端 | 胶水技术 | 加载的 Native | 回调桥接 | Demo 层额外工作 |
|---|---|---|---|---|---|
trro_gateway_demo_linux |
现场 | 无(C++ 直连) | libtrro_field.so + 三分库 + FFmpeg 3.x |
C 函数指针直接注册 | YUV/H264/H265/JPEG 文件推流、控制回环 |
trro_remote_demo_win_linux |
远端 | 无(Qt C++ 直连) | libtrro_remote.so / trro_remote.dll |
Qt lambda → C 回调 | 多路布局、TRRO_setWindows 硬渲染 |
trro_remote_go |
远端 | CGO | 同上 + #cgo LDFLAGS 链 FFmpeg |
C extern → Go //export → Go closure |
类型化 Go API、RegisterAllCallback 批量注册 |
trro_gateway_python |
现场 | ctypes | libtrro_field.so |
@CFUNCTYPE 装饰器 |
run_py.sh 设 LD_LIBRARY_PATH(nvidia/soft) |
trro_remote_python |
远端 | ctypes | libtrro_remote.so / trro_remote.dll |
@CFUNCTYPE |
Linux 自渲染 YUV→RGB;Windows 走 TRRO_setWindows |
trro_remote_java |
远端 | JNA | libtrro_remote.so |
接口 extends Callback 内部类 |
Native.load 映射全量 C API |
trro_gateway_demo_android |
现场 | AAR + JNI | AAR 内 libgateway.so → 三分库 |
Java TrroGatewayListener |
仅调 TrroGateway,不写 JNI |
trro_remote_demo_android |
远端 | AAR + JNI | TrroRemote AAR |
Java TrroRemoteListener |
TXCloudVideoView 硬渲染 |
trro_remote_unity |
远端 | P/Invoke + AndroidJavaObject | Win:trro_remote.dll;Android:remoteuinty-release.aar |
C# delegate / AndroidJavaProxy |
平台 #if 分支、纹理/YUV 自渲染 |
trro_remote_demo_ios |
远端 | ObjC Framework | TRROControl.framework |
Block / delegate(官方封装) | Demo 只调 TrroRemote |
trro_remote_demo_harmony |
远端 | HAR + NAPI | sdklibrary.har |
TrroRemoteListener 接口 |
ArkTS TrroRemote.getInstance() |
| Web SDK Demo | 远端 | 无 Native 胶水 | 浏览器内 JS 栈 | TRROSDK 事件回调 |
独立 WebRTC 实现,非 .so 绑定 |
共性 :所有 Native 绑定最终都落到 trro_field.h / trro_remote.h 的 C 函数 + 函数指针回调;差异只在「谁帮你写这层映射」------自己写(CGO/ctypes/JNA/P/Invoke)还是官方 AAR/Framework/HAR 已写好。
6.7.2 C/C++ 直连(零胶水)
现场 trro_gateway_demo_linux 与 远端 trro_remote_demo_win_linux 是最「原生」的集成方式:直接 #include "trro_field.h" 或 "trro_remote.h",链接 -ltrro_field / -ltrro_remote 及 -lrtc_media -lrtc_engine 与 FFmpeg 依赖。
| 要点 | 现场 C++ Demo | 远端 Qt Demo |
|---|---|---|
| 初始化 | TRRO_initGwPath("./config.json", mode) |
TRRO_init() / TRRO_initJsonPath |
| 推流/拉流 | TRRO_externalVideoData / 编码帧 API |
TRRO_connect + TRRO_setWindows |
| 回调 | 普通 C 函数,如 onControlData 内再 TRRO_sendControlData 回环 |
TRRO_registerOnState 等,Qt 用 C++11 lambda 作函数指针 |
| 构建 | Makefile + run_loader.sh 设库路径 |
QtRemoteDemoApp.pro 按 OS 切换 LIBS / INCLUDEPATH |
适用场景:嵌入式 Linux、工控机、已有 C++ 渲染管线(OpenGL/DirectX)的团队;无 GC、无跨语言回调开销,也是其他语言 Demo 的对照基准。
6.7.3 Go CGO(远端)
trro_remote_go 在 trro/trro_remote.go 中用 CGO 嵌入 C 头文件与静态 inline 注册函数 ,是官方 Demo 里结构最完整的 自研绑定范例。
链接声明(编译期固定依赖链):
go
#cgo CFLAGS: -I./include
#cgo LDFLAGS: -L./sdk_lib -L./sdk_lib/third_lib \
-ltrro_remote -lrtc_media -lrtc_engine \
-lavformat -lavcodec -lavutil -lavdevice -lswresample -lswscale
回调桥接模式(三层):
- C 侧:
static inline void trro_register_go_callback(void* ctx)内调用TRRO_registerAllLatencyCallback(ctx, cgoAllLatencyReportCallback)等,把 C 函数指针指向extern声明。 - Go 侧:
//export cgoAllLatencyReportCallback导出 C 可调用符号,内部C.GoString/C.GoBytes转 Go 类型,再调用户注册的 Go closure。 - 应用层:
test.go中trro.RegisterSignalStateCallback(nil, func(...) { ... })写业务逻辑。
设计要点:
- 包级变量保存各
*Callback函数指针,防止 GC 回收导致 C 侧悬空指针。 RegisterAllCallback一次性注册 8 类回调,避免应用遗漏。- Go 侧对
SignalState、State、Codec等做了 typed enum,比 ctypes/JNA 更接近「SDK 风格 API」。
6.7.4 Python ctypes(双端)
Python Demo 采用标准库 ctypes,无第三方 FFI 依赖;现场与远端各一份脚本,模式高度相似。
现场 trro_gateway_python/trro_sample.py:
python
trro_dll = ctypes.CDLL('libtrro_field.so')
@CFUNCTYPE(None, c_void_p, c_int)
def OnSignalConnectionState(context, signal_state):
if signal_state == 0:
trro_dll.TRRO_registerControlDataCallback(None, OnControlData)
trro_dll.TRRO_start()
- 异步初始化:
mode=-1时先TRRO_registerSignalStateCallback,在signal_state==0后再注册其余回调并TRRO_start。 - 推流:
TRRO_externalVideoData按帧循环喂 YUV;需run_py.sh把sdk_lib/nvidia或soft+ffmpeg3加入LD_LIBRARY_PATH。
远端 trro_remote_python/trro_demo.py:
python
if platform.system() == 'Windows':
trro_dll = ctypes.CDLL('./Win_X64/trro_remote.dll')
sdk_render = True # TRRO_setWindows 硬渲染
else:
trro_dll = ctypes.CDLL('libtrro_remote.so')
sdk_render = False # TRRO_registerRemoteFrameCallback 自渲染
- Linux:注册
image_callback,用 NumPy/PIL 把 I420 转 RGB 在 Tk Canvas 显示。 - Windows:走 SDK 内部窗口渲染,与 Qt Demo 的
TRRO_setWindows同类。 - 需对部分 API 手动设置
argtypes/restype(如TRRO_initJson),否则 ctypes 默认c_int可能传参错误。
6.7.5 Java JNA(远端 Linux)
trro_remote_java 用 JNA (非 JNI 手写)映射 C API:TrroJavaAPI extends Library,Native.load("libtrro_remote.so", TrroJavaAPI.class)。
| 机制 | 说明 |
|---|---|
| API 映射 | 接口方法名与 C 函数名一致,JNA 按名称解析符号 |
| 回调 | 内部类 implements TRRO_onRemoteFrameDataCallback extends Callback;Windows 注释要求改用 StdCallCallback 配合 trro_remote.dll |
| 指针/数组 | 视频帧 Pointer data + getByteArray(0, len);int[] conn_fds 直接映射 |
| 初始化顺序 | TRRO_registerSignalStateCallback 先于 TRRO_initJsonPath(与头文件注释一致) |
Demo 的 Demo.java 展示典型流程:注册回调 → TRRO_initJsonPath("./config.json") → TRRO_getGwList → TRRO_connect → 循环 TRRO_sendControlData。
6.7.6 Android AAR + JNI(双端)
Android Demo 不写 JNI,只依赖控制台下载的 AAR;胶水层在 AAR 内部。
调用链(与解压 AAR 结构一致):
#mermaid-svg-HWIzteVunnf3gTqD{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-HWIzteVunnf3gTqD .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-HWIzteVunnf3gTqD .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-HWIzteVunnf3gTqD .error-icon{fill:#552222;}#mermaid-svg-HWIzteVunnf3gTqD .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-HWIzteVunnf3gTqD .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-HWIzteVunnf3gTqD .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-HWIzteVunnf3gTqD .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-HWIzteVunnf3gTqD .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-HWIzteVunnf3gTqD .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-HWIzteVunnf3gTqD .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-HWIzteVunnf3gTqD .marker{fill:#333333;stroke:#333333;}#mermaid-svg-HWIzteVunnf3gTqD .marker.cross{stroke:#333333;}#mermaid-svg-HWIzteVunnf3gTqD svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-HWIzteVunnf3gTqD p{margin:0;}#mermaid-svg-HWIzteVunnf3gTqD .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-HWIzteVunnf3gTqD .cluster-label text{fill:#333;}#mermaid-svg-HWIzteVunnf3gTqD .cluster-label span{color:#333;}#mermaid-svg-HWIzteVunnf3gTqD .cluster-label span p{background-color:transparent;}#mermaid-svg-HWIzteVunnf3gTqD .label text,#mermaid-svg-HWIzteVunnf3gTqD span{fill:#333;color:#333;}#mermaid-svg-HWIzteVunnf3gTqD .node rect,#mermaid-svg-HWIzteVunnf3gTqD .node circle,#mermaid-svg-HWIzteVunnf3gTqD .node ellipse,#mermaid-svg-HWIzteVunnf3gTqD .node polygon,#mermaid-svg-HWIzteVunnf3gTqD .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-HWIzteVunnf3gTqD .rough-node .label text,#mermaid-svg-HWIzteVunnf3gTqD .node .label text,#mermaid-svg-HWIzteVunnf3gTqD .image-shape .label,#mermaid-svg-HWIzteVunnf3gTqD .icon-shape .label{text-anchor:middle;}#mermaid-svg-HWIzteVunnf3gTqD .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-HWIzteVunnf3gTqD .rough-node .label,#mermaid-svg-HWIzteVunnf3gTqD .node .label,#mermaid-svg-HWIzteVunnf3gTqD .image-shape .label,#mermaid-svg-HWIzteVunnf3gTqD .icon-shape .label{text-align:center;}#mermaid-svg-HWIzteVunnf3gTqD .node.clickable{cursor:pointer;}#mermaid-svg-HWIzteVunnf3gTqD .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-HWIzteVunnf3gTqD .arrowheadPath{fill:#333333;}#mermaid-svg-HWIzteVunnf3gTqD .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-HWIzteVunnf3gTqD .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-HWIzteVunnf3gTqD .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-HWIzteVunnf3gTqD .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-HWIzteVunnf3gTqD .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-HWIzteVunnf3gTqD .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-HWIzteVunnf3gTqD .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-HWIzteVunnf3gTqD .cluster text{fill:#333;}#mermaid-svg-HWIzteVunnf3gTqD .cluster span{color:#333;}#mermaid-svg-HWIzteVunnf3gTqD div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-HWIzteVunnf3gTqD .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-HWIzteVunnf3gTqD rect.text{fill:none;stroke-width:0;}#mermaid-svg-HWIzteVunnf3gTqD .icon-shape,#mermaid-svg-HWIzteVunnf3gTqD .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-HWIzteVunnf3gTqD .icon-shape p,#mermaid-svg-HWIzteVunnf3gTqD .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-HWIzteVunnf3gTqD .icon-shape .label rect,#mermaid-svg-HWIzteVunnf3gTqD .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-HWIzteVunnf3gTqD .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-HWIzteVunnf3gTqD .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-HWIzteVunnf3gTqD :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} System.loadLibrary
Java: TrroGateway / TrroRemote
JNI: libgateway.so / libremote.so
libtrro_field.so / libtrro_remote.so
librtc_media.so + librtc_engine.so
FFmpeg + libc++_shared.so
| 组件 | 现场 Gateway AAR | 远端 Remote AAR |
|---|---|---|
| Java 入口 | com.tencent.trro.api.TrroGateway |
com.tencent.trro.api.TrroRemote |
| Native 桥 | libgateway.so(GatewayNative) |
Remote 侧对应 JNI 库 |
| 捆绑库 | libtrro_field.so、三分库、FFmpeg 6.x 系、libc++_shared.so |
libtrro_remote.so 及同构依赖 |
| ABI | Demo AAR 常见 仅 arm64-v8a | 同左,集成时需与目标设备 ABI 匹配 |
| Demo 用法 | initWithOptions → start(TXCloudVideoView) |
initWithOptions → connectList + TrroRemoteListener |
Unity Android 分支则走 com.tencent.remote.uinty.TrroRemoteUnityAPI (remoteuinty-release.aar),与纯 Java Demo 的 TrroRemote 是 同一 Native 栈、不同 Java 封装。
6.7.7 Unity 双路径(P/Invoke + AndroidJavaObject)
trro_remote_unity/Assets/Demo/TrroInterface.cs 用 预处理器分平台,是「一套 C#、两种胶水」的典型:
| 平台 | 绑定方式 | 关键类型 |
|---|---|---|
| Windows / Editor | [DllImport("trro_remote.dll", CallingConvention = CallingConvention.Cdecl)] |
[UnmanagedFunctionPointer(CallingConvention.StdCall)] delegate |
| Android | new AndroidJavaObject("com.tencent.remote.uinty.TrroRemoteUnityAPI") |
AndroidJavaProxy 实现 TrroUnityListenerInterface |
Windows 路径 :直接 P/Invoke C API,与 C++ Demo 等价;Plugins 目录须带齐 rtc_media.dll、rtc_engine.dll、FFmpeg 60/58/7/4 系 DLL(见 §6.5)。
Android 路径 :C# 不加载 libtrro_remote.so,全部经 Java 层回调;TrroListener 把 onState、onAllLatencyCallback 等转发到 TrroCallbackInterface 单例,再驱动 Unity UI。
注意 :头文件 Windows 导出可用 __stdcall(USE_CSHARP),但 Unity Demo 对 DLL 使用 CallingConvention.Cdecl------以 Demo 实际写法为准,集成时不要混用约定。
6.7.8 iOS / HarmonyOS / Web(官方封装,Demo 无自研胶水)
这三类 Demo 不包含 CGO/ctypes/JNA 式自研绑定,直接消费官方高级 API:
| 平台 | Demo 入口 | 封装形态 | Demo 职责 |
|---|---|---|---|
| iOS | trro_remote_demo_ios |
TRROControl.framework(TrroRemote、TrroGateway ObjC 类) |
CocoaPods 集成;getGwList → 拉流 UI |
| HarmonyOS | trro_remote_demo_harmony |
sdklibrary.har(ArkTS TrroRemote、TrroOptions) |
TrroRemoteListener 实现各回调;TXCloudVideoView 渲染 |
| Web | trro_web_sdk HTML Demo |
TRROSDK(TS 声明 index.d.ts) |
浏览器 WebRTC + 独立信令;与 Native C ABI 无直接链接关系 |
若只需「快速集成」,优先用官方 AAR/Framework/HAR/Web SDK;若需 Linux 服务端/工控进程 深度定制,参考 Go CGO 或 Python ctypes Demo 自建绑定层。
7. 接入要点与踩坑
7.0 完整 SDK 与二进制部署
- 从 TRRO 控制台 下载对应平台 完整 SDK (含
.so/.dll/.aar),Demo 仓库通常 不含 运行时库。 - 现场 aarch64 运行前确认
run_loader.sh的LD_LIBRARY_PATH指向nvidia或soft变体 +ffmpeg3。 - 远端 Linux 首次集成执行
./lib_install.sh [目标目录]创建 FFmpeg 软链。 - Unity/Android 须将 Plugins 下全部 DLL/so 一并打包,缺任一 FFmpeg 依赖会导致加载失败。
7.1 配置生成
- 公有云推荐:控制台配置工具
- 私有化最小配置:
device_id+server_ip:2883,上线后再通过http://serverip:8190/config_template下发视频流配置
7.2 安全
- Demo 中
device_id + password在config.json明文------生产应配合设备证书、License 绑定、一机一密 - 控制通道
master权限必须走TRRO_requestPermission→ 现场端TRRO_setOperationPermission仲裁,避免多操控端冲突;非 master 发控会返回TRRO_UNAUTHORIZED
7.3 多网部署
Multipath 完整原理、配置项与 POC 清单见 §4.5。此处仅列最易踩坑项:
- OS 未配策略路由 :
network_bind写了但两路打出同一公网 IP → Multipath 无效 - 缺权限 :未
setcap/ root → 绑定网卡失败 - 视频与控制策略混淆 :视频是融合调度,控制默认双发;关
dc_double_trans_enable后控制延迟特性会变 - 计费:多网约 ×1.2 带宽系数,可按场景 selective 开启
bash
sudo setcap cap_net_raw,cap_net_bind_service+ep ./trro-test
7.4 初始化模式与线程安全
| API | 模式 | 说明 |
|---|---|---|
现场 TRRO_initGwPath(..., mode=0) |
同步 | 阻塞至信令 kTrroReady |
现场 TRRO_initGwPath(..., mode=-1) |
异步 | 通过 TRRO_onSignalState 通知 |
远端 TRRO_initJsonAsync |
异步 | 结果经 TRRO_onSignalState / TRRO_OnErrorEvent |
回调线程 :TRRO_OnConnectCost、TRRO_OnErrorEvent 等均在 SDK 内部线程触发------勿在回调内阻塞;耗时逻辑转工作线程。
7.5 控制通道限流(易忽略)
除 QoS 0/1 外,头文件还定义(活跃会话下):
- 单条消息长度上限
- 1 秒内 累计发送量上限(超限
TRRO_MESSAGE_MAX_EXCEED) - 3 秒内 消息条数上限(
TRRO_MESSAGE_RATE_EXCEED) - 发送缓冲区满(
TRRO_MESSAGE_BLOCK)
100Hz 控制需应用层 打包聚合 (多轴杆量合并为一帧二进制),而非 100 次/秒单独调用 sendControlData。
7.6 帧级对齐(数采)
推荐路径:
- 采集端用
TRRO_externalVideoDataWithUserTime或TRRO_externalEncodeVideoDataUserTime打统一单调时钟戳 - 控制指令同帧打包或在应用层维护
(user_time, control_state)序列 - 远端通过
TRRO_onAllLatencyReport的videotime+rcct做闭环监控 - POC 验收时区分 G2G vs VCCT vs RCCT
7.7 语言绑定层踩坑(Demo 胶水层)
| 绑定方式 | 常见坑 | 建议 |
|---|---|---|
| ctypes | 未设 argtypes/restype 导致栈破坏或返回值错误 |
对 TRRO_initJson、TRRO_connect 等显式声明;Linux 必须配 LD_LIBRARY_PATH |
| ctypes 回调 | 回调对象被 GC 回收 → 段错误 | 用模块级变量持有 @CFUNCTYPE 函数引用 |
| Go CGO | 回调 closure 未保存到包级变量 | 与 Demo 相同,用全局变量存 *Callback |
| JNA | Linux .so 用 Callback;Windows .dll 需 StdCallCallback |
按 TrroJavaAPI.java 注释切换;回调内避免阻塞 |
| JNA / CGO 线程 | C SDK 在内部线程调回调 | 回调内只做轻量转发,重逻辑丢工作线程(见 §7.4) |
| Unity P/Invoke | 缺 FFmpeg/rtc DLL → DllNotFoundException |
Plugins 整包拷贝(§6.5);CallingConvention 与 Demo 一致 |
| Unity Android | 误在 Android 分支再 P/Invoke .so |
必须走 TrroRemoteUnityAPI + AndroidJavaProxy |
| Android AAR | 仅 arm64-v8a、缺 libc++_shared.so |
核对 AAR 内 jni/ ABI;与 NDK 版本兼容 |
| Python 现场 | nvidia/soft 库选错 | run_py.sh 与 Jetson/通用 ARM 硬件匹配 |
| Python 远端 | Linux 未注册 RemoteFrameCallback 却期望画面 |
Windows 用 TRRO_setWindows;Linux 需自渲染或改走硬渲染 API |
8. 一句话总结
TRRO 是一套面向工业遥操的 C 语言双端 SDK (Web 为独立 JS 实现):现场端 libtrro_field 负责多路采集/编码/按需推流/收控,远端端 libtrro_remote 负责多路拉流/渲染/发控;底层以 WebRTC 三分库(librtc_engine + librtc_media)+ FFmpeg 做低延迟媒体,以 MQTT(paho.mqtt.c) 做设备信令,以 独立二进制控制通道 承载高频遥操数据;Multipath 在 OS 策略路由 + network_bind 之上,对视频做 融合调度 、对控制默认 双发冗余 ,并内建 master/guest 权限、VCCT/RCCT 时延度量 等工业遥操能力。官方支持 Linux / Windows / Android / iOS / Web / HarmonyOS 全栈远控,现场以 Linux ARM/x64 + Android 为主。
9. 延伸阅读
| 资源 | 说明 |
|---|---|
| 多网络路径传输(官方) | network_bind、media_trans_mode、路由示例 |
| 多网聚合与切换(社区) | Multipath 工程原理与 <50ms 切换含义 |
| 物联网卡白名单配置 | 多网 network_bind 带 DNS |
| 免费试用 License | 2 周 2 授权 |
| 腾讯云 TRRO 产品 | 指标、试用、FAQ |
| 现场设备端 SDK 文档 | 官方 API 与能力说明 |
| 远端设备端 SDK 文档 | 官方 API 与能力说明 |
| TRRO 控制台配置工具 | 生成 config.json |
| 腾讯云 TRRO 产品 | 指标、试用、FAQ |
| TRRO 控制台下载 | 各平台完整 SDK |
文档版本对照以官方 2.4.3 文档与 Web SDK 内嵌 2.4.7.0 为准;C Native 以运行时 TRRO_getSdkVersion() 为准。