Flutter 中利用 MediaCodec 高效解码 H.265 视频的实战指南
·
为什么需要硬件解码 H.265?
根据实测数据,使用 FFmpeg 软解 4K H.265 视频时:
- 中端手机 CPU 占用率高达 70%~90%
- 平均功耗达到 800mW(正常播放的 3 倍)
- 帧率波动范围 ±15fps

技术选型:FFmpeg vs MediaCodec
FFmpeg 软解方案
- 优点:跨平台统一实现
- 缺点:
- 无法调用 DSP/GPU 加速
- 内存复制次数多(平均 3 次/帧)
MediaCodec 硬解方案
- 优点:
- 直接使用硬件解码器
- 支持 Zero-Copy 渲染(Surface 直通)
- 缺点:
- 需要处理 Android 版本碎片化
- 配置参数较复杂
混合架构实现
sequenceDiagram
Flutter->>+Platform: 发送视频数据
Platform->>+MediaCodec: 输入缓冲区入队
MediaCodec-->>-Platform: 输出帧就绪
Platform->>+SurfaceTexture: 更新纹理
SurfaceTexture-->>-Flutter: 渲染新帧
核心代码实现
Flutter 插件基础结构
class H265Decoder {
final MethodChannel _channel = const MethodChannel('h265_decoder');
Future<void> initDecoder(int width, int height) async {
await _channel.invokeMethod('init', {
'width': width,
'height': height,
});
}
}
Android 端关键配置
MediaFormat format = MediaFormat.createVideoFormat("video/hevc", width, height);
format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
MediaCodec decoder = MediaCodec.createDecoderByType("video/hevc");
decoder.configure(format, surface, null, 0);
性能优化实战
缓冲区计算
缓冲区大小 = (width × height × 3/2) × 缓冲帧数
// 例如 1080p 双缓冲:
// (1920 × 1080 × 1.5) × 2 ≈ 6MB
实测数据(骁龙865)
| 分辨率 | 解码方式 | 平均帧率 | 功耗 | |--------|----------|---------|------| | 1080p | 硬解 | 60fps | 200mW| | 4K | 硬解 | 45fps | 350mW| | 4K | 软解 | 18fps | 850mW|
生产环境陷阱
- Android 8.0 以下适配:
- 需要单独处理 COLOR_FormatYUV420Flexible
-
某些设备要求添加 csd-0 头数据
-
资源泄漏防护:
@Override protected void finalize() throws Throwable { releaseDecoder(); super.finalize(); } -
色域转换问题:
- 必须校验 COLOR_Format 支持列表
- 推荐使用 GLSL 做 YUV->RGB 转换
开放性问题
如何实现动态码率适配?建议研究方向:
- 监听 BatteryManager.BATTERY_PROPERTY_CURRENT_NOW
- 根据电量状态切换解码 profile
- 动态调整输出 Surface 分辨率

更多推荐


所有评论(0)