# FFmpegSharp **Repository Path**: Eviav/FFmpegSharp ## Basic Information - **Project Name**: FFmpegSharp - **Description**: 基于 FFmpeg.AutoGen 实现 解码 - **Primary Language**: C# - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-03-13 - **Last Updated**: 2026-03-13 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # FFmpegSharp 解码器文档 > 🤖 以下内容由AI生成 ## 1. 概述 FFmpegSharp 是一个基于 FFmpeg 的 .NET 封装库 `7.1.1`,提供了方便的视频解码功能。本文档将详细介绍库中的三种解码器类、支持的流格式、PacketData 类以及 H264/H265 编码相关内容。 ## 2. 解码器类介绍 ### 2.1 FileDecoder **功能**:用于解码本地视频文件。 **适用场景**: - 本地视频文件播放 - 视频文件信息获取 - 视频帧提取 **特点**: - 支持 Seek 定位 - 支持获取视频元数据 - 支持硬件加速解码 **核心方法**: - `Seek(TimeSpan position)`:定位到指定时间点 - `SeekToFrame(long frameNumber)`:定位到指定帧号 - `SeekToPercentage(double percentage)`:定位到指定百分比位置 - `GetVideoInfo()`:获取视频文件的详细信息 **示例**: ```csharp // 初始化解码器 var decoder = new FileDecoder("video.mp4"); // 获取视频信息 var info = decoder.GetVideoInfo(); Console.WriteLine($"视频时长: {info.Duration}"); Console.WriteLine($"分辨率: {info.Width}x{info.Height}"); // 定位到50%位置 decoder.SeekToPercentage(0.5); ``` ### 2.2 UrlDecoder **功能**:用于解码/提取流在线播放地址(rtmp/rtsp/http-flv/srt 等在线地址)。 **适用场景**: - RTMP 直播流 - RTSP 监控流 - SRT 低延迟传输流 - HTTP 流媒体 - 等等在线地址 **特点**: - 支持多种网络协议 - 可配置硬件加速 - 自动处理网络延迟和缓冲 **特殊处理**: - 对 SRT 协议设置特殊参数(latency=200ms) - 对 SRT 和 RTSP 协议设置特殊的格式选项 **示例**: ```csharp // 初始化 RTMP 流解码器 var rtmpDecoder = new UrlDecoder("rtmp://example.com/live/stream"); // 初始化 SRT 流解码器 var srtDecoder = new UrlDecoder("srt://example.com:8888"); ``` ### 2.3 RawDecoder **功能**:用于解码自定义数据流,支持 AVCC + Annex B 格式。 **适用场景**: - 从网络接收的裸流数据 - 自定义封装格式的视频数据 - 需要手动管理解码过程的场景 **支持输出格式**: - RGB/BGR24 格式(适用于 GDI 渲染) - YUV420P 格式(适用于 WPF 等渲染) - 原始 AVFrame 帧 **核心方法**: - `SetExtradata(byte[]? extradata)`:设置解码器的扩展数据 - `TryDecodeRGB24(AVCodecID codecID, byte[] buffer, out byte[]? rgb, out int width, out int height)`:解码为 RGB24 格式 - `TryDecodeoYUV(AVCodecID codecID, byte[] buffer, out byte[]? yuv, out int width, out int height)`:解码为 YUV420P 格式 - `TryDecode(AVCodecID codecID, byte[] buffer, out AVFrame? frame)`:解码为原始 AVFrame **示例**: ```csharp // 初始化裸流解码器 var decoder = new RawDecoder(); // 设置 SPS/PPS 等扩展数据(用于 H.264/H.265) decoder.SetExtradata(spsPpsData); // 解码 H.264 数据 if (decoder.TryDecodeRGB24(AVCodecID.AV_CODEC_ID_H264, h264Data, out var rgb, out var width, out var height)) { // 使用解码后的 RGB 数据 Console.WriteLine($"解码成功,分辨率: {width}x{height}"); } ``` ## 3. 流格式详解 ### 3.1 AVCC 格式 **定义**:AVCC(Advanced Video Coding Container)是一种视频编码容器格式,通常用于 MP4 等容器中。 **特点**: - 使用长度前缀(4字节)来指示每个 NAL 单元的长度 - 不包含起始码(0x00000001 或 0x000001) - 通常包含 SPS(序列参数集)和 PPS(图像参数集)作为扩展数据 **结构**: ``` +---------------+---------------+---------------+ | 长度前缀(4B) | NAL 单元数据 | 长度前缀(4B) | ... +---------------+---------------+---------------+ ``` **应用场景**: - MP4 容器格式 - FLV 容器格式 - 通过网络传输的视频流(如 WebRTC) ### 3.2 Annex B 格式 **定义**:Annex B 是 H.264/H.265 标准中的一种字节流格式,使用起始码来分隔 NAL 单元。 **特点**: - 使用起始码(0x00000001 或 0x000001)来标记每个 NAL 单元的开始 - 不包含长度前缀 - 通常用于 MPEG-TS、RTP 等传输协议 **结构**: ``` +---------------+---------------+---------------+ | 起始码(3-4B) | NAL 单元数据 | 起始码(3-4B) | ... +---------------+---------------+---------------+ ``` **应用场景**: - MPEG-TS 容器格式 - RTP 传输协议 - 大多数网络流媒体协议 ### 3.3 两者的区别和转换 | 特性 | AVCC 格式 | Annex B 格式 | |------|-----------|-------------| | 分隔方式 | 长度前缀 | 起始码 | | 数据大小 | 固定长度前缀(4字节) | 可变长度起始码(3-4字节) | | 扩展数据 | 通常包含 SPS/PPS | 通常不包含 SPS/PPS | | 适用容器 | MP4、FLV | MPEG-TS、RTP | | 网络传输 | 适合有序、可靠的传输 | 适合可能丢包的网络环境 | **转换**: - AVCC → Annex B:使用 `h264_mp4toannexb` 或 `hevc_mp4toannexb` 过滤器 - Annex B → AVCC:使用 `h264_annexb_to_mp4` 或 `hevc_annexb_to_mp4` 过滤器 **在 RawDecoder 中的实现**: - 通过检测 extradata 的第一个字节是否为 1 来判断是否为 AVCC 格式 - 如果是 AVCC 格式,会自动初始化相应的位流过滤器(h264_mp4toannexb 或 hevc_mp4toannexb) ## 4. PacketData 类详解 **功能**:表示一个媒体数据包,包含压缩的视频或音频数据以及相关的元数据。 **主要属性**: | 属性 | 类型 | 描述 | |------|------|------| | Data | byte[] | 压缩数据 | | StreamIndex | int | 流索引 | | MediaType | AVMediaType | 媒体类型(视频/音频/字幕等) | | IsKeyFrame | bool | 是否为关键帧(I帧) | | PTS | long | 显示时间戳(PTS) | | DTS | long | 解码时间戳(DTS) | | Duration | long | 数据包时长(以TimeBase为单位) | | Size | int | 数据包大小(字节) | | Pos | long | 数据在文件中的位置 | | TimeBase | AVRational | 时间基 | **应用场景**: - 在 StreamDecoder 中用于存储和传递解码前的原始数据包 - 用于分析和处理媒体流数据 - 用于自定义解码流程中的数据传递 **示例**: ```csharp // 处理 PacketData void ProcessPacket(PacketData packet) { if (packet.MediaType == AVMediaType.AVMEDIA_TYPE_VIDEO) { Console.WriteLine($"视频数据包: 大小={packet.Size} 字节, 是关键帧={packet.IsKeyFrame}"); // 可以将 packet.Data 传递给 RawDecoder 进行解码 var decoder = new RawDecoder(); decoder.TryDecode(AVCodecID.AV_CODEC_ID_H264, packet.Data, out var frame); } } ``` ## 5. H264/H265 编码介绍 ### 5.1 H.264 (AVC) **定义**:H.264 是由 ITU-T 和 ISO/IEC 联合开发的视频编码标准,也称为 AVC(Advanced Video Coding)。 **特点**: - 高压缩率:相比 MPEG-2 可节省 50% 以上的带宽 - 广泛的设备支持:几乎所有现代设备都支持 H.264 解码 - 良好的网络适应性:支持多种码率和分辨率 **关键概念**: - NAL 单元(Network Abstraction Layer):视频数据的基本单位 - SPS(Sequence Parameter Set):包含序列级别的参数,如分辨率、帧率等 - PPS(Picture Parameter Set):包含图像级别的参数 - I 帧:关键帧,包含完整的图像信息 - P 帧:预测帧,基于前一帧的差异信息 - B 帧:双向预测帧,基于前后帧的差异信息 ### 5.2 H.265 (HEVC) **定义**:H.265 是 H.264 的继任者,也称为 HEVC(High Efficiency Video Coding)。 **特点**: - 更高的压缩率:相比 H.264 可节省 40-50% 的带宽 - 支持更高的分辨率:最高支持 8192x4320(8K)分辨率 - 更好的编码效率:采用更复杂的编码算法 **关键改进**: - 更大的编码单元(CU):最大支持 64x64 - 更灵活的编码结构:支持四叉树分割 - 更多的预测模式:包括帧内和帧间预测 - 更高效的变换和量化:采用基于上下文的自适应二进制算术编码(CABAC) ### 5.3 在 FFmpegSharp 中的应用 **解码支持**: - H.264:使用 `AV_CODEC_ID_H264` - H.265:使用 `AV_CODEC_ID_HEVC` **流格式支持**: - 支持 AVCC 格式(通过 extradata 提供 SPS/PPS) - 支持 Annex B 格式(直接解码) **硬件加速**: - 支持各种硬件加速设备类型,如 CUDA、D3D11 等 ## 6. 代码示例 ### 6.1 使用 FileDecoder 解码本地文件 ```csharp using FFmpegSharp; using FFmpeg.AutoGen; // 初始化解码器 var decoder = new FileDecoder("sample.mp4"); // 获取视频信息 var info = decoder.GetVideoInfo(); Console.WriteLine($"视频信息:"); Console.WriteLine($" 路径: {info.FilePath}"); Console.WriteLine($" 编码: {info.CodecName}"); Console.WriteLine($" 分辨率: {info.Width}x{info.Height}"); Console.WriteLine($" 时长: {info.Duration}"); Console.WriteLine($" 帧率: {info.FrameRate} fps"); Console.WriteLine($" 总帧数: {info.TotalFrames}"); // 定位到中间位置 decoder.SeekToPercentage(0.5); // 开始解码 while (decoder.Try(out var frame)) { // 处理解码后的帧 Console.WriteLine($"解码帧: {frame.width}x{frame.height}"); // 这里可以添加渲染或处理逻辑 // 避免无限循环,仅解码10帧 if (frameCount++ >= 10) break; } // 释放资源 decoder.Dispose(); ``` ### 6.2 使用 UrlDecoder 解码网络流 ```csharp using FFmpegSharp; using FFmpeg.AutoGen; // 初始化 RTSP 流解码器 var decoder = new UrlDecoder("rtsp://example.com:554/stream"); Console.WriteLine("开始接收并解码网络流..."); // 持续解码 while (true) { if (decoder.Try(out var frame)) { // 处理解码后的帧 Console.WriteLine($"解码帧: {frame.width}x{frame.height}"); // 这里可以添加渲染或处理逻辑 } else { // 解码失败,可能是网络问题,短暂休息 Thread.Sleep(10); } } ``` ### 6.3 使用 RawDecoder 解码自定义数据流 ```csharp using FFmpegSharp; using FFmpeg.AutoGen; // 初始化裸流解码器 var decoder = new RawDecoder(); // 假设我们从网络接收 H.264 数据 byte[] spsPpsData = GetSpsPpsData(); // 包含 SPS 和 PPS 的数据 decoder.SetExtradata(spsPpsData); // 持续接收和解码数据 while (true) { byte[] h264Data = ReceiveH264Data(); // 从网络接收的 H.264 数据 if (decoder.TryDecodeRGB24(AVCodecID.AV_CODEC_ID_H264, h264Data, out var rgb, out var width, out var height)) { // 处理解码后的 RGB 数据 Console.WriteLine($"解码成功: {width}x{height}"); // 这里可以添加渲染逻辑 RenderRGBData(rgb, width, height); } else { Console.WriteLine("解码失败"); } } ``` ## 7. 总结 FFmpegSharp 提供了三种功能强大的解码器类,满足不同场景的视频解码需求: - **FileDecoder**:适用于本地视频文件的解码,支持丰富的定位功能和元数据获取。 - **UrlDecoder**:适用于网络流媒体的解码,支持多种网络协议和自动网络错误处理。 - **RawDecoder**:适用于自定义数据流的解码,支持 AVCC 和 Annex B 两种流格式,提供灵活的输出选项。 库支持 H.264 和 H.265 等主流视频编码格式,通过 PacketData 类可以方便地处理和传递媒体数据包。 通过合理选择解码器类和流格式,可以满足各种视频解码场景的需求,从本地文件播放到网络流媒体处理,再到自定义数据流的解码。