2025-04-21 15:11:23 +08:00
|
|
|
|
# Video Decode Plugin
|
2025-04-28 01:08:21 +00:00
|
|
|
|
|
2025-04-21 15:11:23 +08:00
|
|
|
|
基于MediaCodec/VideoToolbox的跨平台H.264/H.265视频解码Flutter插件,专为低延迟实时视频流解码设计。
|
2025-04-28 01:08:21 +00:00
|
|
|
|
|
2025-04-21 15:11:23 +08:00
|
|
|
|
[](https://pub.dev/packages/video_decode_plugin)
|
2025-04-28 01:08:21 +00:00
|
|
|
|
|
2025-04-21 15:11:23 +08:00
|
|
|
|
## 特性
|
2025-04-28 01:08:21 +00:00
|
|
|
|
|
2025-04-21 15:11:23 +08:00
|
|
|
|
- 🔄 基于原生解码器的高性能视频解码(Android使用MediaCodec,iOS使用VideoToolbox)
|
|
|
|
|
|
- 🖼️ 支持H.264和H.265(HEVC)视频格式
|
|
|
|
|
|
- ⏱️ 低延迟解码,适用于实时视频流应用
|
|
|
|
|
|
- 📱 跨平台支持(Android和iOS)
|
|
|
|
|
|
- 🔧 高度可配置的解码参数
|
|
|
|
|
|
- 📊 详细的解码统计和诊断信息
|
|
|
|
|
|
- 💡 支持I帧和P帧的单独传入和处理
|
|
|
|
|
|
- 🎞️ 使用Flutter Texture进行高效渲染
|
2025-04-28 01:08:21 +00:00
|
|
|
|
|
2025-04-21 15:11:23 +08:00
|
|
|
|
## 安装
|
2025-04-28 01:08:21 +00:00
|
|
|
|
|
2025-04-21 10:56:28 +08:00
|
|
|
|
```yaml
|
|
|
|
|
|
dependencies:
|
2025-04-21 15:11:23 +08:00
|
|
|
|
video_decode_plugin: ^1.0.0
|
2025-04-21 10:56:28 +08:00
|
|
|
|
```
|
2025-04-28 01:08:21 +00:00
|
|
|
|
|
2025-04-21 15:11:23 +08:00
|
|
|
|
## 快速开始
|
2025-04-28 01:08:21 +00:00
|
|
|
|
|
2025-04-21 15:11:23 +08:00
|
|
|
|
### 初始化解码器
|
2025-04-21 10:56:28 +08:00
|
|
|
|
|
|
|
|
|
|
```dart
|
|
|
|
|
|
import 'package:video_decode_plugin/video_decode_plugin.dart';
|
|
|
|
|
|
|
2025-04-21 15:11:23 +08:00
|
|
|
|
// 创建解码器配置
|
|
|
|
|
|
final config = VideoDecoderConfig(
|
|
|
|
|
|
width: 640, // 视频宽度
|
|
|
|
|
|
height: 480, // 视频高度
|
|
|
|
|
|
codecType: CodecType.h264, // 编解码类型:h264或h265
|
|
|
|
|
|
frameRate: 30, // 目标帧率(可选)
|
|
|
|
|
|
bufferSize: 30, // 缓冲区大小
|
|
|
|
|
|
isDebug: true, // 是否启用详细日志
|
2025-04-21 10:56:28 +08:00
|
|
|
|
);
|
2025-04-28 01:08:21 +00:00
|
|
|
|
|
2025-04-21 15:11:23 +08:00
|
|
|
|
// 初始化解码器,获取纹理ID
|
|
|
|
|
|
final textureId = await VideoDecodePlugin.initDecoder(config);
|
2025-04-28 01:08:21 +00:00
|
|
|
|
|
2025-04-21 15:11:23 +08:00
|
|
|
|
// 设置帧回调
|
|
|
|
|
|
VideoDecodePlugin.setFrameCallback((textureId) {
|
|
|
|
|
|
// 当新帧可用时被调用
|
|
|
|
|
|
setState(() {
|
|
|
|
|
|
// 更新UI
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
```
|
2025-04-28 01:08:21 +00:00
|
|
|
|
|
2025-04-21 15:11:23 +08:00
|
|
|
|
### 渲染视频
|
2025-04-28 01:08:21 +00:00
|
|
|
|
|
2025-04-21 15:11:23 +08:00
|
|
|
|
```dart
|
|
|
|
|
|
// 使用Flutter的Texture组件显示视频
|
|
|
|
|
|
Texture(
|
|
|
|
|
|
textureId: textureId,
|
|
|
|
|
|
filterQuality: FilterQuality.low,
|
|
|
|
|
|
)
|
2025-04-21 10:56:28 +08:00
|
|
|
|
```
|
2025-04-28 01:08:21 +00:00
|
|
|
|
|
2025-04-21 15:11:23 +08:00
|
|
|
|
### 解码视频帧
|
|
|
|
|
|
|
|
|
|
|
|
```dart
|
|
|
|
|
|
// 解码I帧
|
|
|
|
|
|
await VideoDecodePlugin.decodeFrame(
|
|
|
|
|
|
frameData, // Uint8List类型的H.264/H.265帧数据
|
|
|
|
|
|
FrameType.iFrame
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
// 解码P帧
|
|
|
|
|
|
await VideoDecodePlugin.decodeFrame(
|
|
|
|
|
|
frameData, // Uint8List类型的H.264/H.265帧数据
|
|
|
|
|
|
FrameType.pFrame
|
|
|
|
|
|
);
|
|
|
|
|
|
```
|
2025-04-28 01:08:21 +00:00
|
|
|
|
|
2025-04-21 15:11:23 +08:00
|
|
|
|
### 获取解码统计信息
|
2025-04-28 01:08:21 +00:00
|
|
|
|
|
2025-04-21 10:56:28 +08:00
|
|
|
|
```dart
|
2025-04-21 15:11:23 +08:00
|
|
|
|
final stats = await VideoDecodePlugin.getDecoderStats(textureId);
|
|
|
|
|
|
print('已渲染帧数: ${stats['renderedFrames']}');
|
|
|
|
|
|
print('丢弃帧数: ${stats['droppedFrames']}');
|
2025-04-21 10:56:28 +08:00
|
|
|
|
```
|
2025-04-28 01:08:21 +00:00
|
|
|
|
|
2025-04-21 15:11:23 +08:00
|
|
|
|
### 释放资源
|
2025-04-28 01:08:21 +00:00
|
|
|
|
|
2025-04-21 10:56:28 +08:00
|
|
|
|
```dart
|
2025-04-21 15:11:23 +08:00
|
|
|
|
await VideoDecodePlugin.releaseDecoder();
|
2025-04-21 10:56:28 +08:00
|
|
|
|
```
|
2025-04-28 01:08:21 +00:00
|
|
|
|
|
2025-04-21 15:11:23 +08:00
|
|
|
|
## 高级用法
|
|
|
|
|
|
|
|
|
|
|
|
### 多实例支持
|
|
|
|
|
|
|
|
|
|
|
|
插件支持同时创建和管理多个解码器实例:
|
2025-04-21 10:56:28 +08:00
|
|
|
|
|
|
|
|
|
|
```dart
|
2025-04-21 15:11:23 +08:00
|
|
|
|
// 创建第一个解码器
|
|
|
|
|
|
final textureId1 = await VideoDecodePlugin.createDecoder(config1);
|
|
|
|
|
|
|
|
|
|
|
|
// 创建第二个解码器
|
|
|
|
|
|
final textureId2 = await VideoDecodePlugin.createDecoder(config2);
|
|
|
|
|
|
|
|
|
|
|
|
// 为特定纹理ID设置回调
|
|
|
|
|
|
VideoDecodePlugin.setFrameCallbackForTexture(textureId1, (id) {
|
|
|
|
|
|
// 处理第一个解码器的帧
|
2025-04-21 10:56:28 +08:00
|
|
|
|
});
|
2025-04-21 15:11:23 +08:00
|
|
|
|
|
|
|
|
|
|
// 为特定纹理ID解码帧
|
|
|
|
|
|
await VideoDecodePlugin.decodeFrameForTexture(textureId2, frameData, frameType);
|
|
|
|
|
|
|
|
|
|
|
|
// 释放特定解码器
|
|
|
|
|
|
await VideoDecodePlugin.releaseDecoderForTexture(textureId1);
|
2025-04-21 10:56:28 +08:00
|
|
|
|
```
|
2025-04-28 01:08:21 +00:00
|
|
|
|
|
2025-04-21 15:11:23 +08:00
|
|
|
|
### 优化I帧和SPS/PPS处理
|
2025-04-28 01:08:21 +00:00
|
|
|
|
|
2025-04-21 15:11:23 +08:00
|
|
|
|
对于H.264视频流,建议按照以下顺序处理帧:
|
2025-04-28 01:08:21 +00:00
|
|
|
|
|
2025-04-21 15:11:23 +08:00
|
|
|
|
1. 首先发送SPS(序列参数集,NAL类型7)
|
|
|
|
|
|
2. 其次发送PPS(图像参数集,NAL类型8)
|
|
|
|
|
|
3. 然后发送IDR帧(即I帧,NAL类型5)
|
|
|
|
|
|
4. 最后发送P帧(NAL类型1)
|
2025-04-28 01:08:21 +00:00
|
|
|
|
|
2025-04-21 15:11:23 +08:00
|
|
|
|
```dart
|
|
|
|
|
|
// 发送SPS和PPS数据
|
|
|
|
|
|
await VideoDecodePlugin.decodeFrame(spsData, FrameType.iFrame);
|
|
|
|
|
|
await VideoDecodePlugin.decodeFrame(ppsData, FrameType.iFrame);
|
2025-04-28 01:08:21 +00:00
|
|
|
|
|
2025-04-21 15:11:23 +08:00
|
|
|
|
// 发送IDR帧
|
|
|
|
|
|
await VideoDecodePlugin.decodeFrame(idrData, FrameType.iFrame);
|
2025-04-28 01:08:21 +00:00
|
|
|
|
|
2025-04-21 15:11:23 +08:00
|
|
|
|
// 发送P帧
|
|
|
|
|
|
await VideoDecodePlugin.decodeFrame(pFrameData, FrameType.pFrame);
|
|
|
|
|
|
```
|
2025-04-28 01:08:21 +00:00
|
|
|
|
|
2025-04-21 15:11:23 +08:00
|
|
|
|
## 完整示例
|
2025-04-28 01:08:21 +00:00
|
|
|
|
|
2025-04-21 15:11:23 +08:00
|
|
|
|
请参考示例应用,了解如何:
|
|
|
|
|
|
- 从文件或网络流加载H.264视频
|
|
|
|
|
|
- 正确解析和处理NAL单元
|
|
|
|
|
|
- 高效地解码和渲染视频帧
|
|
|
|
|
|
- 监控解码性能并进行故障排除
|
2025-04-28 01:08:21 +00:00
|
|
|
|
|
2025-04-21 15:11:23 +08:00
|
|
|
|
## 支持
|
2025-04-28 01:08:21 +00:00
|
|
|
|
|
2025-04-21 15:11:23 +08:00
|
|
|
|
- Android 5.0 (API级别21)及以上
|
|
|
|
|
|
- iOS 11.0及以上
|
2025-04-28 01:08:21 +00:00
|
|
|
|
|
2025-04-21 10:56:28 +08:00
|
|
|
|
## 注意事项
|
2025-04-28 01:08:21 +00:00
|
|
|
|
|
2025-04-21 15:11:23 +08:00
|
|
|
|
- 视频分辨率受设备硬件限制,较旧设备可能无法支持高分辨率视频
|
|
|
|
|
|
- 硬件解码器可能在某些设备上不可用,插件会自动回退到软件解码
|
|
|
|
|
|
- 对于最佳性能,建议在实际硬件设备上测试,而不仅仅是模拟器
|
2025-04-28 01:08:21 +00:00
|
|
|
|
|
2025-04-21 10:56:28 +08:00
|
|
|
|
## 许可证
|
2025-04-28 01:08:21 +00:00
|
|
|
|
|
2025-04-21 10:56:28 +08:00
|
|
|
|
MIT
|