视频流传输:H.264/H.265编码、MediaCodec硬编解码、RTP/RTSP协议、低延迟传输方案
车机互联中,视频流传输是最核心也最棘手的一环。你想啊,手机屏幕要投射到车机上,还得实时响应触摸操作,延迟稍微高一点,用户体验就崩了。我最早做这个模块时,踩了不少坑,今天就把这些经验掰开揉碎讲给你听。
为什么视频流传输这么重要?
说白了,车机互联的本质就是「手机的画面搬到车机上」。无论是导航、音乐还是视频通话,底层都是视频流在跑。如果编码选不对、协议不合适,画面卡顿、延迟高、花屏,用户直接骂娘。
我见过不少团队,上来就选H.264,觉得成熟稳定。但实际跑起来,车机芯片解码能力参差不齐,有的老芯片解码1080p都费劲。所以,选编码方案前,先摸清目标车机的硬件底牌。
H.264 vs H.265:怎么选?
这两个编码标准,是当前视频传输的绝对主力。我直接说结论:
| 特性 | H.264 (AVC) | H.265 (HEVC) |
|---|---|---|
| 压缩率 | 基准 | 提升约50% |
| 解码复杂度 | 低 | 高(约2-3倍) |
| 硬件支持 | 几乎所有车机芯片 | 较新芯片才支持 |
| 延迟表现 | 优秀 | 略高(编码更耗时) |
| 带宽需求 | 较高 | 低(同等画质) |
我的建议:如果车机芯片支持H.265硬解码,优先用H.265。带宽省一半,画质还更好。但如果是老车机(比如2018年前的),老老实实用H.264,别折腾。
我记得有一次,客户非要上H.265,结果车机解码一帧要30ms,直接导致端到端延迟飙到200ms+。后来切回H.264,延迟降到80ms,客户才满意。嗯,技术选型不能只看纸面参数。
MediaCodec硬编解码实战
Android上做视频编解码,绕不开MediaCodec。它支持硬件加速,性能远好于软编软解。我直接给一段核心代码,你照着用就行。
// 创建编码器
MediaCodec encoder = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_VIDEO_AVC);
MediaFormat format = MediaFormat.createVideoFormat(
MediaFormat.MIMETYPE_VIDEO_AVC, 1280, 720);
format.setInteger(MediaFormat.KEY_BIT_RATE, 2000000); // 2Mbps
format.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1); // 关键帧间隔1秒
format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
encoder.start();
// 输入数据(从Surface获取)
Surface inputSurface = encoder.createInputSurface();
// ... 渲染画面到inputSurface ...
// 获取编码后的数据
MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
int outputIndex = encoder.dequeueOutputBuffer(info, 10000);
if (outputIndex >= 0) {
ByteBuffer outputData = encoder.getOutputBuffer(outputIndex);
// 这里outputData就是H.264/H.265码流
// 可以封装成RTP包发送
encoder.releaseOutputBuffer(outputIndex, false);
}
避坑指南:我曾经把KEY_I_FRAME_INTERVAL设成0,结果编码器只在场景切换时生成关键帧。车机端解码器等不到关键帧,画面一直花屏。后来改成1秒一个关键帧,问题解决。记住,车机互联场景下,关键帧间隔不要超过2秒。
RTP/RTSP协议:传输层的选择
视频流编码好了,怎么传过去?RTP/RTSP是经典方案。RTP负责传数据,RTSP负责控制(播放、暂停、快进)。
为什么选RTP?因为它支持实时传输,有时间戳和序列号,能抗丢包。你想想看,车机互联时网络环境复杂,Wi-Fi信号不稳定、蓝牙干扰,丢包是常态。RTP的序列号机制,能帮解码器判断哪些包丢了,做丢包隐藏。
RTSP则用来建立会话。流程很简单:
- 手机端启动RTSP Server,监听端口(比如554)
- 车机端发送DESCRIBE请求,获取媒体描述
- 车机端发送SETUP请求,建立传输通道
- 车机端发送PLAY请求,开始接收RTP流
- 手机端持续发送RTP包,车机端解码渲染
我习惯用libVLC或自定义的轻量RTSP库。Android上可以用android.net.rtp包,但功能有限,建议用第三方库。
低延迟传输方案:核心优化点
车机互联对延迟极其敏感。我定个标准:端到端延迟(从手机触摸到车机画面响应)不超过100ms,否则用户能明显感觉到卡顿。
怎么做到?我总结几个关键优化点:
- 编码参数调优:关闭B帧(只保留I帧和P帧),B帧会引入延迟。设置
KEY_LATENCY为0,强制低延迟模式。 - 网络传输优化:使用UDP而非TCP。TCP重传机制会引入延迟,UDP丢包就丢包,解码器做丢包隐藏。
- 解码渲染优化:车机端使用SurfaceView而非TextureView,SurfaceView有独立的渲染线程,延迟更低。
- 缓冲区控制:解码器缓冲区不要太大。我一般设成3帧,再多就丢帧。缓冲区越大,延迟越高。
注意:低延迟和高画质是矛盾的。你追求低延迟,就得牺牲画质。我一般把码率控制在2-4Mbps,分辨率1080p,帧率30fps。这个配置在大多数车机上都能跑出80ms左右的延迟。
知识体系总览
下面这张图,把视频流传输的核心逻辑串起来了。你对照着看,心里就有谱了。
实战中的坑与解法
最后分享几个我踩过的坑,你遇到了直接抄答案:
- 花屏问题:车机端解码器收到不完整的关键帧,画面花掉。解法:手机端发送关键帧时,用RTP的MARKER位标记帧结束,车机端等收到完整帧再解码。
- 音画不同步:视频流和音频流各自走RTP,时间戳没对齐。解法:用NTP时间戳同步,手机端和车机端都参考同一时钟源。
- Wi-Fi干扰:车机连了车载Wi-Fi,手机开热点,两者互相干扰。解法:用5GHz频段,或者走USB有线连接(延迟最低,能到20ms)。
嗯,视频流传输这块,说难不难,说简单也不简单。核心就是编码选对、协议选对、参数调优。你按我上面说的做,基本不会出大问题。如果遇到具体报错,欢迎来公众号找我聊。