2025-04-28 09:11:53 +08:00

161 lines
3.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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