当前位置: 首页 > news >正文

H.265/HEVC NALU结构快速入门:从起始码到Type值识别

📅 更新时间:2025年10月11日
🏷️ 标签:H.265 | HEVC | NALU | 视频编码 | 编解码原理 | WebRTC
🎯 目标:快速理解H.265 NALU基本结构,掌握Type值识别方法

文章目录

  • 📖 前言
  • 🎯 NALU是什么?(快递包裹类比)
    • 简单理解
    • NALU的作用
  • 📦 NALU完整结构
    • 三部分组成
    • 1️⃣ 起始码(Start Code)
      • 是什么?
      • 类比
      • 作用
      • 注意事项
    • 2️⃣ NALU Header(2字节)
      • H.265 vs H.264 核心差异
      • 2字节Header的bit位分布
      • 调试时只需关注Type
    • 3️⃣ NALU数据(Payload)
  • 🔑 Type值详解
    • 什么是Type值?
    • 常见Type值速查表
    • Type值的重要性
      • 对解码器:
      • 对RTP传输(WebRTC):
  • 🔢 Type值提取方法
    • 位运算公式
    • 手工计算步骤
      • 示例:NALU Header第1字节 = `40`
  • 🛠️ 实战:用HxD分析H.265文件
    • 工具准备
    • 实战步骤
      • 第1步:准备H.265文件
      • 第2步:用HxD打开文件
      • 第3步:查找起始码
      • 第4步:查看第一个NALU(VPS)
      • 第5步:继续查看后续NALU
    • 快速识别表(不用计算)
  • 🎯 实战应用场景
    • 场景1:学习H.265格式
    • 场景2:调试WebRTC H.265传输(重要!)
    • 场景3:RTP分片处理
  • 📚 H.264 vs H.265 对比
    • NALU结构差异
    • 为什么差异重要?


📖 前言

在开发WebRTC、视频传输或调试H.265相关项目时,你一定遇到过这样的问题:

  • ❓ H.265文件是怎么组织的?
  • ❓ 什么是NALU?和H.264有什么区别?
  • ❓ 为什么RTP打包/解包需要理解NALU?
  • ❓ 如何用工具查看和分析H.265文件结构?

本文用最简单的方式,通过类比和实战,帮你快速理解H.265 NALU的核心概念。


🎯 NALU是什么?(快递包裹类比)

简单理解

NALU = Network Abstraction Layer Unit(网络抽象层单元)

快递包裹类比最容易理解:

原始视频 → H.265编码 → 一堆NALU包裹就像:
商品 → 打包发货 → 快递包裹1、快递包裹2、快递包裹3...

H.265文件 = 一串NALU包裹连起来


NALU的作用

作用说明
方便传输每个NALU是独立单元,可以单独传输
方便解析起始码分隔,容易定位每个NALU
适应网络支持分片(大NALU可以拆成小包传输)
灵活处理不同Type的NALU可以分别处理

📦 NALU完整结构

三部分组成

┌─────────────┬─────────────┬──────────────┐
│ 起始码      │ NALU Header │ NALU数据     │
│ 4字节       │ 2字节       │ 可变长度     │
│ 00 00 00 01 │ 40 01       │ Payload      │
└─────────────┴─────────────┴──────────────┘

1️⃣ 起始码(Start Code)

是什么?

NALU之间的分隔符,固定为 00 00 00 01(4字节)

类比

快递包裹前的标签(标识开始):
[──标签1──][包裹1][──标签2──][包裹2][──标签3──][包裹3]↑ 这是1号        ↑ 这是2号         ↑ 这是3号NALU前的起始码(标识开始):
[00 00 00 01][NALU1][00 00 00 01][NALU2][00 00 00 01][NALU3]↑ 标识开始   ↑      ↑ 标识开始   ↑      ↑ 标识开始

作用

作用说明
标识开始告诉解析器"新的NALU开始了"
定位边界确定一个NALU在哪结束,下一个在哪开始
方便搜索用工具(如HxD)快速定位所有NALU

注意事项

两种起始码

  • 00 00 00 01(4字节)- 常见
  • 00 00 01(3字节)- 较少见

本文统一使用4字节起始码


2️⃣ NALU Header(2字节)

H.265 vs H.264 核心差异

编码格式NALU Header大小说明
H.2641字节结构简单
H.2652字节支持分层编码,更复杂

这是H.265和H.264在数据格式上最重要的差异!

2字节Header的bit位分布

NALU Header = 2字节 = 16 bits第1字节(8 bits):
┌───┬───┬───┬───┬───┬───┬───┬───┐
│ 0 │ 1 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │  ← 示例:40 (hex)
└───┴───┴───┴───┴───┴───┴───┴───┘7   6   5   4   3   2   1   0   ← bit位编号↓   └────────Type────────┘   ↓F        (bit 1-6)          LayerId高1位第2字节(8 bits):
┌───┬───┬───┬───┬───┬───┬───┬───┐
│ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 1 │  ← 示例:01 (hex)
└───┴───┴───┴───┴───┴───┴───┴───┘7   6   5   4   3   2   1   0   ← bit位编号└────LayerId低5位────┘   └TID─┘(bit 3-7)           (bit 0-2)

字段说明

字段位置长度值范围说明
F第1字节 bit 71位0或1禁止位,通常为0
Type第1字节 bit 1-66位0-63NALU类型 ← 重点!
LayerId第1字节 bit 0 + 第2字节 bit 3-76位0-63空间层ID(分层编码)
TID第2字节 bit 0-23位0-7时间层ID(时间分层)

示例分析(40 01)

  • F = 0(bit 7)
  • F字段实际意义:
    网络传输时,如果检测到错误,可以设置F=1
    接收端看到F=1,直接丢弃这个NALU
    正常情况下,F永远是0
  • Type = 100000 (二进制) = 32 (VPS) ← 我们只关心这个
  • LayerId = 000000 = 0
  • TID = 001 = 1

调试时只需关注Type

Type(6位)= NALU类型,这是最重要的信息!

其他字段(F/LayerId/TID)在基础调试中不太需要关注。


3️⃣ NALU数据(Payload)

存储实际的视频编码数据

  • 参数信息(VPS/SPS/PPS)
  • 图像数据(I帧/P帧/B帧)

长度可变,从几十字节到几十KB不等。


🔑 Type值详解

什么是Type值?

Type值 = NALU的"标签",告诉解码器这个包裹里装的是什么

类比:

快递标签:
- "易碎品" → 小心轻放
- "食品" → 注意保质期
- "文件" → 重要文件NALU Type值:
- 32(VPS) → 视频参数,解码前必须有
- 33(SPS) → 序列参数,解码前必须有
- 34(PPS) → 图像参数,解码前必须有
- 19/20(IDR) → 关键帧,完整画面
- 0/1 → 普通帧,差异数据

常见Type值速查表

Type值名称全称作用特点
32VPSVideo Parameter Set视频级别参数H.265特有 ✨
33SPSSequence Parameter Set序列参数(分辨率等)解码必需
34PPSPicture Parameter Set图像参数解码必需
19/20IDRInstantaneous Decoder RefreshI帧(关键帧)独立解码
0/1TRAILTrailing PictureP/B帧依赖其他帧
49FUFragmentation UnitRTP分片标识WebRTC必知 ⚠️

Type值的重要性

对解码器:

解码器收到NALU → 检查Type值:
├── Type=32/33/34 → 保存参数,用于后续解码
├── Type=19/20 → 这是I帧,独立解码
└── Type=0/1 → 这是P/B帧,需要参考帧

对RTP传输(WebRTC):

发送端打包:
├── Type=32/33/34 → 优先发送,确保接收端有参数
├── Type=49 → 这是FU分片,需要重组
└── 其他 → 单NALU模式接收端解包:
├── 检查Type=49 → 进入FU重组逻辑
└── 其他 → 直接输出NALU

🔢 Type值提取方法

位运算公式

uint8_t nalu_type = (nalu_header[0] >> 1) & 0x3F;└────┬────┘   └─┬──┘右移1位     取低6

手工计算步骤

示例:NALU Header第1字节 = 40

第1步:转二进制

40 (十六进制) = 0100 0000 (二进制)

第2步:右移1位

0100 0000 >> 1 = 0010 0000↑ 去掉了最右边的bit 0

第3步:取低6位(& 0x3F)

0010 0000 & 0011 1111 = 0010 0000└─0x3F──┘   └─结果──┘

第4步:转十进制

0010 0000 (二进制) = 32 (十进制)

第5步:查表

32 → VPS ✅

🛠️ 实战:用HxD分析H.265文件

工具准备

HxD - 免费十六进制编辑器

  • 下载:https://mh-nexus.de/en/hxd/
  • 大小:约3MB
  • 功能:查看二进制文件、搜索、对比

实战步骤

第1步:准备H.265文件

方法1:用FFmpeg生成测试文件

ffmpeg -i input.mp4 -c:v libx265 -t 10 -frames:v 60 test.h265

方法2:从你的项目获取

// 编码时保存
FILE* file = fopen("output.h265", "wb");
fwrite(packet->data, 1, packet->size, file);

第2步:用HxD打开文件

  1. 右键 test.h265 → 打开方式 → HxD
  2. 或拖拽文件到HxD窗口

第3步:查找起始码

Ctrl+F 打开查找对话框

设置

  1. 点击 “Hex-values”“字节序列” 标签
  2. 在输入框输入:00 00 00 01(空格分隔)
  3. 点击 “查找全部”“Find all”

结果

  • 底部显示所有匹配位置
  • 显示找到的数量(如:Found 62 occurrences)

在这里插入图片描述


第4步:查看第一个NALU(VPS)

双击底部第一个搜索结果(偏移量0)

你会看到:

Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F00000000  00 00 00 01 40 01 0C 01 FF FF 01 60 00 00 03 00└起始码(4B)┘ └NALU Header─┘ └─NALU数据开始...偏移0-3     偏移4-5↑看这2个字节!

识别

  • 起始码:00 00 00 01
  • NALU Header:40 01
  • 第1字节 40 → Type = 32 → VPS

第5步:继续查看后续NALU

典型顺序

NALU 1: 00 00 00 01 40 01 ... → VPS (32)
NALU 2: 00 00 00 01 42 01 ... → SPS (33)
NALU 3: 00 00 00 01 44 01 ... → PPS (34)
NALU 4: 00 00 00 01 26 01 ... → IDR (19)
NALU 5: 00 00 00 01 02 01 ... → TRAIL (1)
...

快速识别表(不用计算)

记住常见的Header第1字节值

Header第1字节计算过程Type值NALU类型记忆
40(40>>1)&3F=20=3232VPS4开头→参数
42(42>>1)&3F=21=3333SPS4开头→参数
44(44>>1)&3F=22=3434PPS4开头→参数
26(26>>1)&3F=13=1919IDR2开头→帧
28(28>>1)&3F=14=2020IDR2开头→帧
62(62>>1)&3F=31=4949FU必记!

🎯 实战应用场景

场景1:学习H.265格式

用HxD分析自己编码的文件

1. 编码生成test.h265
2. 用HxD打开
3. 找起始码
4. 识别NALU类型
5. 理解H.265文件组织方式

场景2:调试WebRTC H.265传输(重要!)

问题:发送端编码正常,接收端无法解码

排查步骤

步骤1:保存编码输出
FILE* f1 = fopen("debug_encode_output.h265", "wb");
fwrite(packet->data, ...);步骤2:保存RTP重组输出
FILE* f2 = fopen("debug_reassembled.h265", "wb");
// RTP解包后写入步骤3:用HxD对比两个文件
- 打开两个文件
- 搜索起始码
- 对比NALU数量
- 对比NALU类型(Type值)
- 定位差异位置

可能发现的问题

  • ❌ VPS/SPS/PPS丢失 → 参数集传输有问题
  • ❌ NALU数量不一致 → 丢包
  • ❌ Type值错误 → FU重组逻辑错误
  • ❌ 某个字节开始不同 → 数据损坏位置

场景3:RTP分片处理

识别FU分片

void ProcessRTPPayload(uint8_t* payload, int size) {// 提取Type值uint8_t nalu_type = (payload[0] >> 1) & 0x3F;if (nalu_type == 49) {// 这是FU分片!需要重组uint8_t fu_header = payload[2];bool S = (fu_header >> 7) & 0x01;  // 开始片bool E = (fu_header >> 6) & 0x01;  // 结束片// 重组逻辑...} else {// 单NALU模式,直接输出}
}

Type=49的处理是WebRTC H.265的关键难点!


📚 H.264 vs H.265 对比

NALU结构差异

项目H.264H.265影响
NALU Header1字节2字节RTP打包逻辑不同
参数集SPS+PPSVPS+SPS+PPSH.265多一个VPS
起始码00 00 00 0100 00 00 01相同
Type位数5位 (0-31)6位 (0-63)H.265支持更多类型
FU类型2849RTP分片Type不同

为什么差异重要?

WebRTC项目常见问题

问题:用H.264的RTP打包/解包逻辑处理H.265错误示例:
if (nalu_type == 28) {  // ❌ 这是H.264的FU Type// FU处理...
}正确示例:
if (nalu_type == 49) {  // ✅ H.265的FU Type// FU处理...
}

结果

  • H.264逻辑无法正确处理H.265的FU分片
  • 导致接收端组帧失败,无法解码

如果您觉得这篇文章对您有帮助,不妨点赞 + 收藏 + 关注,更多音视频开发实战技巧将持续更新 🔥!

http://www.dtcms.com/a/471586.html

相关文章:

  • 初中电脑做网站的软件wordpress商品采集
  • 焦作网站建设哪家公司好网站页面分辨率
  • asp.net 网站建设方案做网站用不用thinkphp
  • Tool Calling和本地MCP服务的调用
  • 陕icp网站建设厦门seo公司网站
  • 商城网站建设目标网站的收费窗口怎么做
  • 长春模板网站建设企业怎样提高网站访问速度
  • 怎么评估一个对象的边界很复杂?代码与指标
  • 计算机基础·数据库系统原理
  • 网站开发vs平台的功能第一素材网
  • 2019网站seo免费学设计的网站
  • 网站同城在线哪里做怀化建设企业网站
  • 营销网站域名设计建设网站需要收费吗
  • LFM2 模型介绍
  • JAVA:DecimalFormat的DEMO(格式化数字)
  • 专业的网站设计制作公司廊坊北京网站建设
  • Python Requests库用法示例:从入门到实战的HTTP请求指南
  • 番禺建网站网站建设的流程分析
  • 婚庆设计网站模板做框架表格网站
  • 敦化建设局网站两学一做纪实评价系统登陆网站
  • 依托 <AI 原生应用架构白皮书>,看 AI 原生应用的发展与实践
  • 重庆卓光网站建设外贸网站支付系统
  • 西安制作网站需要多少钱网站图片大小多少合适
  • 网站开发后端所需要的语言南和邢台网站制作
  • SpringBoot集成:5分钟实现HTML转PDF功能
  • 深圳外贸网站推广公司学做网站书籍
  • 做直播网站视频教程大连网络运营
  • 凤岗做网站国家工商网查询企业信息
  • 个人项目开发(1):使用Spring Secruity实现用户登录
  • 建一个网站大约花多少钱网站建设的整个过程