H264码流NALU解析
包
package h264import ("sync"log "github.com/sirupsen/logrus"
)const (DEFAULT_CAP int = 1024 * 1024 * 4// NALU类型NALU_TYPE_SLICE = 1NALU_TYPE_DPA = 2NALU_TYPE_DPB = 3NALU_TYPE_DPC = 4NALU_TYPE_IDR = 5NALU_TYPE_SEI = 6NALU_TYPE_SPS = 7NALU_TYPE_PPS = 8NALU_TYPE_AUD = 9NALU_TYPE_EOSEQ = 10NALU_TYPE_EOSTREAM = 11NALU_TYPE_FILL = 12// 优先级NALU_PRIORITY_DISPOSABLE = 0NALU_PRIRITY_LOW = 1NALU_PRIORITY_HIGH = 2NALU_PRIORITY_HIGHEST = 3
)type NaluHead struct {StartCodeLen intForbidden intReference intUnitType int
}type H264Buffer struct {mutex sync.Mutexdata []bytedataMaxSize intrPtr intnaluHeads []*NaluHead // NALU块信息iFrameIndex []int // I帧索引列表
}func NewH264Buffer(cap int) *H264Buffer {return &H264Buffer{data: make([]byte, 0, cap),dataMaxSize: cap,rPtr: 0,naluHeads: make([]*NaluHead, 0),iFrameIndex: make([]int, 0),}
}func (buf *H264Buffer) Push(d []byte) {buf.mutex.Lock()defer buf.mutex.Unlock()log.Info("H264Buffer push data")if len(d) > buf.dataMaxSize {return}// 计算超出的字节数over := len(buf.data) + len(d) - buf.dataMaxSizeif over > 0 {// 左移超出的字节数buf.data = buf.data[over:]buf.rPtr = buf.rPtr - over}buf.data = append(buf.data, d...)// 更新nalu信息buf.updateNALU()log.Info("I frame indexs: ", buf.iFrameIndex)
}func (buf *H264Buffer) getNALUHead(headIdx int) *NaluHead {return &NaluHead{Forbidden: int(buf.data[headIdx] >> 7),Reference: int((buf.data[headIdx] << 1) >> 6),UnitType: int((buf.data[headIdx] << 3) >> 3),}
}func (buf *H264Buffer) updateNALU() {buf.naluHeads = make([]*NaluHead, 0)buf.iFrameIndex = make([]int, 0)for i := 0; i < len(buf.data)-5; i++ {if buf.data[i] == 0 && buf.data[i+1] == 0 {if buf.data[i+2] == 1 {head := buf.getNALUHead(i + 3)head.StartCodeLen = 3// 起始码长度为3的情况buf.naluHeads = append(buf.naluHeads, head)if head.UnitType == NALU_TYPE_IDR {buf.iFrameIndex = append(buf.iFrameIndex, i)}}if buf.data[i+2] == 0 && buf.data[i+3] == 1 {head := buf.getNALUHead(i + 4)head.StartCodeLen = 4// 起始码长度为4的情况buf.naluHeads = append(buf.naluHeads, head)if head.UnitType == NALU_TYPE_IDR {buf.iFrameIndex = append(buf.iFrameIndex, i)}}}}
}func (buf *H264Buffer) NaluInfo() {buf.mutex.Lock()defer buf.mutex.Unlock()log.Info("|Index\t|\tForbidden\t|\tReference\t|\tUnitType|")for i, v := range buf.naluHeads {reference := "UNKNOW"switch v.Reference {case NALU_PRIORITY_DISPOSABLE:reference = "DISPOSABLE"case NALU_PRIRITY_LOW:reference = "LOW"case NALU_PRIORITY_HIGH:reference = "HIGH"case NALU_PRIORITY_HIGHEST:reference = "HIGHEST"}naluType := "UNKNOW"switch v.UnitType {case NALU_TYPE_SLICE:naluType = "SLICE"case NALU_TYPE_DPA:naluType = "DPA"case NALU_TYPE_DPB:naluType = "DPB"case NALU_TYPE_DPC:naluType = "DPC"case NALU_TYPE_IDR:naluType = "IDR"case NALU_TYPE_SEI:naluType = "SEI"case NALU_TYPE_SPS:naluType = "SPS"case NALU_TYPE_PPS:naluType = "PPS"case NALU_TYPE_AUD:naluType = "AUD"case NALU_TYPE_EOSEQ:naluType = "EOSEQ"case NALU_TYPE_EOSTREAM:naluType = "EOSTREAM"case NALU_TYPE_FILL:naluType = "FILL"}log.Info("|Index: ", i, "\t\t| StartCodeLen: ", v.StartCodeLen, "\t| Forbidden: ", v.Forbidden,"\t| Reference: ", reference, "\t| UnitType: ", naluType)}
}func (buf *H264Buffer) Pop() []byte {buf.mutex.Lock()defer buf.mutex.Unlock()d := buf.data[buf.rPtr:]buf.rPtr = len(buf.data) - 1return d
}func (buf *H264Buffer) PopLastGOP() []byte {buf.mutex.Lock()defer buf.mutex.Unlock()if len(buf.iFrameIndex) == 0 {log.Info("no I Frame")return make([]byte, 0)}idx := buf.iFrameIndex[len(buf.iFrameIndex)-1]d := buf.data[idx:]log.Info("GOP size: ", len(d))return d
}
测试代码
func main() {d, err := ioutil.ReadFile("sintel.h264")if err != nil {log.Fatal(err)}buffer := h264.NewH264Buffer(h264.DEFAULT_CAP)buffer.Push(d)buffer.NaluInfo()
}
H264码流NALU解析相关推荐
- H264码流插入自定义数据(SEI字段)
文章目录 前言 一.H264码流结构 1. 文字说明 2. 码流格式图解 二.自定义数据封装以及H264码流插入 1.将自定义数据封装成SEI字段通用格式即可插入H264码流中 2.编程逻辑 三.附上 ...
- h264码流及h265码流结构分析,NAL头类型分析
视频编码标准规定了编码后码流的语法语义,也就阐明了从比特流提取语法元素并进行解释的方法,也就是视频的解码过程. 1.h264码流结构解析: H.264/AVC(Advanced Video ...
- RTP协议解析和H264码流提取
一. h264基础概念 SODB: 数据比特串-->最原始的编码数据 RBSP: 原始字节序列载荷-->在SODB的后面填加了结尾比特(RBSP trailing bits 一个bit&q ...
- RTP协议全解析(H264码流和PS流
写在前面:RTP的解析,网上找了很多资料,但是都不全,所以我力图整理出一个比较全面的解析, 其中借鉴了很多文章,我都列在了文章最后,在此表示感谢. 互联网的发展离不开大家的无私奉献,我决定从我做起,希 ...
- 【H264/AVC 句法和语义详解】(二):h264码流格式与NALU详解一
上一篇中,我们站在句法元素(或称语法元素)的角度,介绍了H.264的句法和语义,和句法元素的分层结构.在这篇中,我们更进一步,从比特的角度出发,来探索h264码流的组成.通过这篇的学习,我们会初步具备 ...
- 音视频压缩:H264码流层次结构和NALU详解
问题背景: 前面在讲封装格式过程中,都有一个章节讲解如何将H.264的NALU单元如何打包到TS.FLV.RTP中,解装刚好相反,怎么从这些封装格式里面解析出一个个NALU单元.NALU即是编码器的输 ...
- RTP协议全解析(H264码流和PS流)(转)
源: RTP协议全解析(H264码流和PS流) 转载于:https://www.cnblogs.com/LittleTiger/p/10489247.html
- RTP协议全解(H264码流和PS流)
1 视频编码的原理 1.1 一个图像或者一个视频序列进行压缩,产生码流. 对图像的处理即是:帧内预测编码 其预测值P,是由已编码的图像做参考,经运动补偿得到的.预测图像P和当前帧Fn相减,得到两图像的 ...
- Android MediaCodec 解码H264码流播放
视频编解码,编的是什么码?解的又是什么码?有没有想过?现在主流的就是H264码流,Android 采集摄像头原始帧数据 这篇博客讲解的是如何从摄像头从提取YUV画面色值,然后由MediaCodec进行 ...
最新文章
- R语言str_extract函数从字符串中抽取匹配模式的字符串
- asp.net Web API 身份验证 不记名令牌验证 Bearer Token Authentication 简单实现
- python自动化测试框架pytest.pdf_Python 自动化测试框架 unittest 和 pytest 对比
- HTTP Header 详解
- 你觉得你个性上最大的优点是什么?
- Common Used Excel Formulas
- 阿诺德图像加密c语言,基于Arnold置乱的数字图像加密算法(二)
- qt 下log4cplus的使用
- python 之禅 import this
- SQL性能第2篇:查询分析和访问路径制定
- 记一次悲惨的excel导出事件
- 《物联网Android程序开发案例式教程》Demo1:线性布局
- Mac中无法运行旧版本印象笔记:版本太旧 你的本地印象笔记数据是由新版印象笔记管理
- 国外 计算机专业 网站,国外计算机类核心期刊及其网站
- php红包互助源码_完整的微信红包接口API实现(php版)
- 如何把照片压缩到20k一下_如何将照片压缩到20k_手机怎么把照片压缩到20k
- 装饰器模式:藏在漫威电影里的设计模式
- 离散数学 2. 范式、推理
- 审稿人意见回复 Response to revierwers (Updating)
- IM通讯协议总结之三SIMPLE协议