补充
这篇文章是几年前做 Android WebRTC + H.265 时留下的操作记录,最近整理旧资料时重新翻了出来,所以重新发一次。
现在这套方案已经过时。主线 libwebrtc 已经有
kVideoCodecH265、H.265 RTP 解包、SPS/PPS/VPS 解析,也已经把 H.265 接进 AndroidMediaCodec编解码工厂。新项目直接使用新版 libwebrtc 即可,不需要再按照下面的方式手动给 WebRTC 补 H.265。
下面正文保留原来的记录,不再按现在的 libwebrtc 修改。
Android WebRTC + H.265 适配记录
项目需要在 Android 上使用 WebRTC 传输 H.265。
Android 本身支持通过 MediaCodec 编解码 HEVC,但 WebRTC 默认没有完整的 H.265 支持。
单独让 MediaCodec 输出 H.265 没有用。
整个链路需要跑通:
Camera
↓
MediaCodec
↓
H.265
↓
WebRTC RTP
↓
Network
↓
WebRTC RTP
↓
H.265
↓
MediaCodec
除了编码器,还要处理 H.265 NALU、RTP Packetizer、Depacketizer、SDP 协商等内容。
没有准备从头修改 WebRTC,直接参考下面这个项目:
bash
https://github.com/ilei131/android_webrtc_h265
项目使用 Open WebRTC Toolkit,也就是 OWT 的 WebRTC 代码来完成 H.265 支持。
整体处理方式:
markdown
OWT WebRTC Source
↓
编译 Android WebRTC
↓
libwebrtc.jar
+
libjingle_peerconnection_so.so
↓
替换 Android 项目原来的 WebRTC
1. 准备环境
使用 Ubuntu 编译。
一开始使用 Ubuntu 18.04 虚拟机,后面 gclient sync 经常卡在依赖下载,直接换香港 Ubuntu 云服务器。
工作目录:
arduino
/home/user
2. 下载 OWT 源码
bash
cd /home/user
git clone https://github.com/open-webrtc-toolkit/owt-client-native.git
将目录改成:
bash
mv owt-client-native src
目录变成:
arduino
/home/user
├── src
WebRTC 和 Chromium 的构建工具默认围绕 src 目录工作,所以这里直接使用这个结构。
3. 下载 depot_tools
WebRTC 构建依赖 Chromium 的 depot_tools。
bash
cd /home/user
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
加入 PATH:
ruby
export PATH=$PATH:/home/user/depot_tools
检查:
bash
which gclient
能够找到 gclient 后继续。
目录:
arduino
/home/user
├── depot_tools
└── src
4. 创建 .gclient
在:
arduino
/home/user
创建:
.gclient
内容:
ini
solutions = [
{
"managed": False,
"name": "src",
"url": "https://github.com/open-webrtc-toolkit/owt-client-native.git",
"custom_deps": {},
"deps_file": "DEPS",
"safesync_url": "",
},
]
target_os = ["android"]
这里需要:
ini
target_os = ["android"]
目标是编译 Android WebRTC。
5. 同步依赖
进入:
bash
cd /home/user/src
执行:
bash
gclient sync
这一步会下载 Chromium、WebRTC 和 Android 编译需要的大量依赖。
如果出现:
bash
DEPS download failed
git fetch failed
connection reset
timeout
先检查网络。
这一步对网络要求不低,本地环境容易卡住。
6. 编译 Android WebRTC
进入:
bash
cd /home/user/src/scripts
执行:
python build_android.py
编译过程会同时处理 Java 和 Native 部分。
需要的不是 APK,而是 WebRTC 本身的 Android 编译产物。
7. 找到编译结果
编译完成后检查:
bash
src/out
主要需要两个文件:
libwebrtc.jar
libjingle_peerconnection_so.so
两者关系:
markdown
Android App
↓
libwebrtc.jar
↓ JNI
libjingle_peerconnection_so.so
↓
WebRTC Native
libwebrtc.jar 提供 Java API。
libjingle_peerconnection_so.so 包含 WebRTC Native 实现,包括大量 RTP、Codec、网络和 JNI 逻辑。
因此不能只替换:
libwebrtc.jar
还要替换:
libjingle_peerconnection_so.so
两个文件最好来自同一次编译。
不要混用不同版本。
8. 替换 Android 项目中的 WebRTC
将原项目使用的 WebRTC jar 替换成:
libwebrtc.jar
然后把 .so 放到对应 ABI:
css
app/src/main/jniLibs/
├── arm64-v8a/
│ └── libjingle_peerconnection_so.so
└── armeabi-v7a/
└── libjingle_peerconnection_so.so
设备如果只使用:
arm64-v8a
则只保留对应版本。
重新编译 APK。
9. 检查设备 H.265 硬件编码能力
WebRTC 支持 H.265 后,还要确认 Android 设备本身有 HEVC Encoder。
可以执行:
adb shell dumpsys media.codec
搜索:
bash
video/hevc
需要确认存在 H.265 编码器,而不只是解码器。
最终链路:
Camera
↓
MediaCodec HEVC Encoder
↓
H.265
↓
WebRTC
↓
RTP
↓
Network
如果硬件没有:
bash
video/hevc encoder
仅修改 WebRTC 也无法获得硬件 H.265 编码。
10. 为什么不能只改 MediaCodec
Android 支持:
arduino
MediaCodec.createEncoderByType("video/hevc");
只能说明系统可以产生 H.265 码流。
WebRTC 还需要处理后面的链路:
H.265
↓
NALU
↓
RTP Packetizer
↓
Network
↓
RTP Depacketizer
↓
NALU
↓
H.265 Decoder
所以问题不是:
Android 能不能编码 H.265
而是:
WebRTC 能不能把 H.265 当成完整的视频 Codec 处理
这也是直接参考 android_webrtc_h265 和 OWT WebRTC 分支的原因。
最后重新编译:
libwebrtc.jar
libjingle_peerconnection_so.so
再替换项目中的原 WebRTC 依赖,完成 Android WebRTC + H.265 的接入。