logo
0
0
WeChat Login
cuijixiong<cuijixiong@gmail.com>
Update README.md to Chinese version

H.264 FFmpeg ARGB8888 解码器

Go Version License Platform

一个高性能的 Go 库,用于将 H.264 视频流解码为 ARGB8888 (RGBA) 格式,使用嵌入式 FFmpeg 二进制文件。该库提供简单的跨平台 API,无需外部依赖。

✨ 特性

  • 🚀 高性能: 针对实时 H.264 解码进行优化
  • 📦 零依赖: 嵌入式 FFmpeg 二进制文件,无需外部安装
  • 🌍 跨平台: 支持 Windows、Android ARM64 和 Android ARM
  • 🎯 简单 API: 易于使用的接口,基于回调的帧传递
  • 🔄 实时处理: 专为流媒体应用设计
  • 💾 内存高效: 优化的内存使用和流式架构
  • 🛠️ 灵活: 支持自定义帧处理和批处理操作

🚀 快速开始

安装

go get github.com/cnb-cool/h264-ffmpeg-argb8888@v1.0.0

基本使用

package main import ( "fmt" "log" h264decoder "github.com/cnb-cool/h264-ffmpeg-argb8888" ) func main() { // 创建带回调函数的解码器 decoder, err := h264decoder.NewDecoder(1920, 1080, func(frameIndex int, rgbaData []byte, width, height int) { fmt.Printf("收到第 %d 帧: %dx%d, %d 字节\n", frameIndex, width, height, len(rgbaData)) // 在这里处理 RGBA 数据 // 保存到文件、显示或进一步处理 }) if err != nil { log.Fatal(err) } defer decoder.Close() // 启动解码器 if err := decoder.Start(); err != nil { log.Fatal(err) } // 解码 H.264 帧数据 h264Data := []byte{...} // 你的 H.264 帧数据 if err := decoder.DecodeFrame(h264Data); err != nil { log.Printf("解码错误: %v", err) } }

📚 API 文档

核心类型

Decoder

用于 H.264 到 ARGB8888 转换的主要解码器实例。

FrameCallback

type FrameCallback func(frameIndex int, rgbaData []byte, width, height int)

用于接收解码 RGBA 帧的回调函数类型。

主要函数

NewDecoder(width, height int, callback FrameCallback) (*Decoder, error)

创建一个自动检测平台的新 H.264 解码器。

参数:

  • width: 输出帧宽度(像素)
  • height: 输出帧高度(像素)
  • callback: 解码帧时调用的函数

返回值:

  • *Decoder: 解码器实例
  • error: 任何初始化错误

NewDecoderForPlatform(width, height int, targetPlatform string, callback FrameCallback) (*Decoder, error)

为特定目标平台创建新的 H.264 解码器。

参数:

  • width: 输出帧宽度(像素)
  • height: 输出帧高度(像素)
  • targetPlatform: 目标平台("windows_amd64"、"android_arm64"、"android_arm" 或 "" 表示自动检测)
  • callback: 解码帧时调用的函数

解码器方法

Start() error

初始化并启动解码器。必须在 DecodeFrame 之前调用。

DecodeFrame(h264Data []byte) error

解码单个 H.264 帧。解码的 RGBA 数据将通过回调函数传递。

Close() error

停止解码器并释放所有资源。

GetFrameCount() int

返回到目前为止处理的帧数。

IsRunning() bool

返回解码器是否正在运行。

GetErrorChannel() <-chan error

返回用于监控解码器错误的通道。

GetDimensions() (width, height int)

返回配置的输出尺寸。

工具函数

SaveRGBAToPNG(rgbaData []byte, width, height int, filename string) error

将 RGBA 像素数据保存为 PNG 图像文件。

ParseH264Frame(flvData []byte) ([]byte, error)

解析 FLV 样式的 H.264 帧数据并将其转换为带起始码的原始 H.264。

GetSupportedPlatforms() []string

返回所有支持的目标平台列表。

🔧 高级用法

帧缓冲

// 创建帧缓冲区来收集帧 frameBuffer := h264decoder.NewFrameBuffer(50) // 缓冲最多 50 帧 decoder, err := h264decoder.NewDecoder(1920, 1080, func(frameIndex int, rgbaData []byte, width, height int) { // 将帧添加到缓冲区并附带元数据 frameInfo := h264decoder.FrameInfo{ Index: frameIndex, Width: width, Height: height, DataSize: len(rgbaData), Timestamp: time.Now().UnixNano(), } frameBuffer.AddFrame(frameInfo, rgbaData) // 批量处理帧 if frameBuffer.Count() >= 10 { frames := frameBuffer.GetFrames() // 处理批次... frameBuffer.Clear() } })

错误监控

// 在单独的协程中监控错误 go func() { for err := range decoder.GetErrorChannel() { log.Printf("解码器错误: %v", err) } }()

平台特定解码

// 为特定平台创建解码器 decoder, err := h264decoder.NewDecoderForPlatform(1920, 1080, "android_arm64", callback)

🌍 支持的平台

平台GOOSGOARCH描述
Windows 64位windowsamd64Windows 桌面/服务器
Android ARM64linuxarm64Android 设备(64位 ARM)
Android ARMlinuxarmAndroid 设备(32位 ARM)

平台检测

库会根据构建环境自动检测目标平台。你也可以显式指定目标平台:

// 自动检测平台 decoder, err := h264decoder.NewDecoder(1920, 1080, callback) // 显式指定平台 decoder, err := h264decoder.NewDecoderForPlatform(1920, 1080, "windows_amd64", callback) // 列出支持的平台 platforms := h264decoder.GetSupportedPlatforms()

📁 项目结构

h264-ffmpeg-argb8888/ ├── README.md # 本文档 ├── go.mod # Go 模块定义 ├── h264_decoder.go # 主解码器 API ├── utils.go # 工具函数 ├── examples/ # 使用示例 │ ├── basic_usage.go # 基本使用示例 │ └── advanced_usage.go # 高级功能示例 └── processor/ # 内部处理逻辑 ├── rtmp_processor.go # 核心 RTMP/H.264 处理器 ├── embedded_ffmpeg*.go # 平台特定的 FFmpeg 管理器 └── binaries/ # 嵌入式 FFmpeg 二进制文件 ├── windows_amd64/ # Windows 二进制文件 ├── android_arm64/ # Android ARM64 二进制文件 └── android_arm/ # Android ARM 二进制文件

🎯 使用场景

实时视频流

// 实时处理 RTMP/H.264 流 decoder, err := h264decoder.NewDecoder(1920, 1080, func(frameIndex int, rgbaData []byte, width, height int) { // 实时显示帧 displayFrame(rgbaData, width, height) })

视频文件处理

// 处理 H.264 视频文件 for _, h264Frame := range videoFrames { if err := decoder.DecodeFrame(h264Frame); err != nil { log.Printf("帧解码错误: %v", err) } }

帧分析

// 分析解码帧 decoder, err := h264decoder.NewDecoder(1920, 1080, func(frameIndex int, rgbaData []byte, width, height int) { // 执行图像分析 features := analyzeFrame(rgbaData, width, height) processFeatures(features) })

🔍 示例

examples/ 目录包含全面的使用示例:

  • basic_usage.go: 简单的解码器设置和帧处理
  • advanced_usage.go: 帧缓冲、批处理和错误监控

运行示例:

cd examples go run basic_usage.go go run advanced_usage.go

⚡ 性能提示

  1. 重用解码器实例: 创建一次解码器并重用于多个帧
  2. 异步处理: 在单独的协程中处理帧以避免阻塞
  3. 缓冲区管理: 使用帧缓冲区进行批处理
  4. 错误处理: 监控错误通道以及早发现问题
  5. 内存管理: 完成后调用 Close() 释放资源

🐛 故障排除

常见问题

解码器启动失败

  • 检查目标平台是否受支持
  • 验证尺寸是否有效(> 0)
  • 确保回调函数不为 nil

帧解码错误

  • 验证 H.264 数据格式(应包含 NAL 起始码)
  • 检查数据是否损坏或不完整
  • 对 FLV 样式数据使用 ParseH264Frame()

内存问题

  • 完成后调用 decoder.Close()
  • 使用合理限制的帧缓冲区
  • 异步处理帧以避免阻塞

调试信息

// 检查解码器状态 fmt.Printf("运行中: %v\n", decoder.IsRunning()) fmt.Printf("已处理帧数: %d\n", decoder.GetFrameCount()) fmt.Printf("尺寸: %dx%d\n", decoder.GetDimensions()) // 监控错误 go func() { for err := range decoder.GetErrorChannel() { log.Printf("错误: %v", err) } }()

🤝 贡献

欢迎贡献!请随时提交问题、功能请求或拉取请求。

开发设置

  1. 克隆仓库
  2. 安装 Go 1.21 或更高版本
  3. 运行测试: go test ./...
  4. 构建示例: go build ./examples/...

📄 许可证

本项目采用 MIT 许可证 - 详见 LICENSE 文件。

🙏 致谢

  • FFmpeg 项目提供的优秀视频处理能力
  • Go 社区提供的强大标准库
  • 本库的贡献者和用户

📞 支持

如有问题、问题或功能请求,请:

  1. 查看 examples 了解使用模式
  2. 查阅本文档
  3. 在仓库中开启 issue
  4. 联系维护者

用 ❤️ 为 Go 社区制作