123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325 |
- package codec
- import (
- "bytes"
- "errors"
- "io"
- "m7s.live/engine/v4/util"
- "m7s.live/engine/v4/util/bits/pio"
- )
- // Start Code + NAL Unit -> NALU Header + NALU Body
- // RTP Packet -> NALU Header + NALU Body
- // NALU Body -> Slice Header + Slice data
- // Slice data -> flags + Macroblock layer1 + Macroblock layer2 + ...
- // Macroblock layer1 -> mb_type + PCM Data
- // Macroblock layer2 -> mb_type + Sub_mb_pred or mb_pred + Residual Data
- // Residual Data ->
- type H264NALUType byte
- func (b H264NALUType) Or(b2 byte) byte {
- return byte(b) | b2
- }
- func (b H264NALUType) Offset() int {
- switch b {
- case NALU_STAPA:
- return 1
- case NALU_STAPB:
- return 3
- case NALU_FUA:
- return 2
- case NALU_FUB:
- return 4
- }
- return 0
- }
- func (b H264NALUType) Byte() byte {
- return byte(b)
- }
- func ParseH264NALUType(b byte) H264NALUType {
- return H264NALUType(b & 0x1F)
- }
- func (H264NALUType) Parse(b byte) H264NALUType {
- return H264NALUType(b & 0x1F)
- }
- func (H264NALUType) ParseBytes(bs []byte) H264NALUType {
- return H264NALUType(bs[0] & 0x1F)
- }
- const (
- // NALU Type
- NALU_Unspecified H264NALUType = iota
- NALU_Non_IDR_Picture // 1
- NALU_Data_Partition_A // 2
- NALU_Data_Partition_B // 3
- NALU_Data_Partition_C // 4
- NALU_IDR_Picture // 5
- NALU_SEI // 6
- NALU_SPS // 7
- NALU_PPS // 8
- NALU_Access_Unit_Delimiter // 9
- NALU_Sequence_End // 10
- NALU_Stream_End // 11
- NALU_Filler_Data // 12
- NALU_SPS_Extension // 13
- NALU_Prefix // 14
- NALU_SPS_Subset // 15
- NALU_DPS // 16
- NALU_Reserved1 // 17
- NALU_Reserved2 // 18
- NALU_Not_Auxiliary_Coded // 19
- NALU_Coded_Slice_Extension // 20
- NALU_Reserved3 // 21
- NALU_Reserved4 // 22
- NALU_Reserved5 // 23
- NALU_STAPA // 24
- NALU_STAPB
- NALU_MTAP16
- NALU_MTAP24
- NALU_FUA // 28
- NALU_FUB
- // 24 - 31 NALU_NotReserved
- )
- var (
- NALU_AUD_BYTE = []byte{0x00, 0x00, 0x00, 0x01, 0x09, 0xF0}
- NALU_Delimiter1 = []byte{0x00, 0x00, 0x01}
- NALU_Delimiter2 = []byte{0x00, 0x00, 0x00, 0x01}
- // 0x17 keyframe 7:AVC
- // 0x00 AVC sequence header
- // 0x00 0x00 0x00
- // 0x01 configurationVersion
- // 0x42 AVCProfileIndication
- // 0x00 profile_compatibility
- // 0x1E AVCLevelIndication
- // 0xFF lengthSizeMinusOne
- RTMP_AVC_HEAD = []byte{0x17, 0x00, 0x00, 0x00, 0x00, 0x01, 0x42, 0x00, 0x1E, 0xFF}
- RTMP_KEYFRAME_HEAD = []byte{0x17, 0x01, 0x00, 0x00, 0x00}
- RTMP_NORMALFRAME_HEAD = []byte{0x27, 0x01, 0x00, 0x00, 0x00}
- )
- // H.264/AVC视频编码标准中,整个系统框架被分为了两个层面:视频编码层面(VCL)和网络抽象层面(NAL)
- // NAL - Network Abstract Layer
- // raw byte sequence payload (RBSP) 原始字节序列载荷
- // SplitH264 以0x00000001分割H264裸数据
- func SplitH264(payload []byte) (nalus [][]byte) {
- for _, v := range bytes.SplitN(payload, NALU_Delimiter2, -1) {
- if len(v) == 0 {
- continue
- }
- nalus = append(nalus, bytes.SplitN(v, NALU_Delimiter1, -1)...)
- }
- return
- }
- func BuildH264SeqHeaderFromSpsPps(sps, pps []byte) (seqHeader []byte) {
- lenSPS, lenPPS := len(sps), len(pps)
- seqHeader = append([]byte{}, RTMP_AVC_HEAD...)
- if lenSPS > 3 {
- copy(seqHeader[6:], sps[1:4])
- }
- seqHeader = append(seqHeader, 0xE1, byte(lenSPS>>8), byte(lenSPS))
- seqHeader = append(seqHeader, sps...)
- seqHeader = append(append(seqHeader, 0x01, byte(lenPPS>>8), byte(lenPPS)), pps...)
- return
- }
- // ISO/IEC 14496-15 11(16)/page
- //
- // Advanced Video Coding
- //
- // AVCC
- type AVCDecoderConfigurationRecord struct {
- ConfigurationVersion byte // 8 bits Version
- AVCProfileIndication byte // 8 bits
- ProfileCompatibility byte // 8 bits
- AVCLevelIndication byte // 8 bits
- Reserved1 byte // 6 bits
- LengthSizeMinusOne byte // 2 bits 非常重要,每个NALU包前面都(lengthSizeMinusOne & 3)+1个字节的NAL包长度描述
- Reserved2 byte // 3 bits
- NumOfSequenceParameterSets byte // 5 bits SPS 的个数,计算方法是 numOfSequenceParameterSets & 0x1F
- NumOfPictureParameterSets byte // 8 bits PPS 的个数
- SequenceParameterSetLength uint16 // 16 byte SPS Length
- SequenceParameterSetNALUnit []byte // n byte SPS
- PictureParameterSetLength uint16 // 16 byte PPS Length
- PictureParameterSetNALUnit []byte // n byte PPS
- }
- func (p *AVCDecoderConfigurationRecord) Marshal(b []byte) (n int) {
- b[0] = 1
- b[1] = p.AVCProfileIndication
- b[2] = p.ProfileCompatibility
- b[3] = p.AVCLevelIndication
- b[4] = p.LengthSizeMinusOne | 0xfc
- b[5] = uint8(1) | 0xe0
- n += 6
- pio.PutU16BE(b[n:], p.SequenceParameterSetLength)
- n += 2
- copy(b[n:], p.SequenceParameterSetNALUnit)
- n += len(p.SequenceParameterSetNALUnit)
- b[n] = uint8(1)
- n++
- pio.PutU16BE(b[n:], p.PictureParameterSetLength)
- n += 2
- copy(b[n:], p.PictureParameterSetNALUnit)
- n += len(p.PictureParameterSetNALUnit)
- return
- }
- var ErrDecconfInvalid = errors.New("decode error")
- func (p *AVCDecoderConfigurationRecord) Unmarshal(b []byte) (n int, err error) {
- if len(b) < 7 {
- err = errors.New("not enough len")
- return
- }
- p.AVCProfileIndication = b[1]
- p.ProfileCompatibility = b[2]
- p.AVCLevelIndication = b[3]
- p.LengthSizeMinusOne = b[4] & 0x03
- spscount := int(b[5] & 0x1f)
- n += 6
- var sps, pps [][]byte
- for i := 0; i < spscount; i++ {
- if len(b) < n+2 {
- err = ErrDecconfInvalid
- return
- }
- spslen := util.ReadBE[int](b[n : n+2])
- n += 2
- if len(b) < n+spslen {
- err = ErrDecconfInvalid
- return
- }
- sps = append(sps, b[n:n+spslen])
- n += spslen
- }
- p.SequenceParameterSetLength = uint16(len(sps[0]))
- p.SequenceParameterSetNALUnit = sps[0]
- if len(b) < n+1 {
- err = ErrDecconfInvalid
- return
- }
- ppscount := int(b[n])
- n++
- for i := 0; i < ppscount; i++ {
- if len(b) < n+2 {
- err = ErrDecconfInvalid
- return
- }
- ppslen := util.ReadBE[int](b[n : n+2])
- n += 2
- if len(b) < n+ppslen {
- err = ErrDecconfInvalid
- return
- }
- pps = append(pps, b[n:n+ppslen])
- n += ppslen
- }
- if ppscount >= 1 {
- p.PictureParameterSetLength = uint16(len(pps[0]))
- p.PictureParameterSetNALUnit = pps[0]
- } else {
- err = ErrDecconfInvalid
- }
- return
- }
- type NALUnit struct {
- NALUHeader
- RBSP
- }
- type NALUHeader struct {
- forbidden_zero_bit byte // 1 bit 0
- nal_ref_idc byte // 2 bits nal_unit_type等于6,9,10,11或12的NAL单元其nal_ref_idc都应等于 0
- nal_uint_type byte // 5 bits 包含在 NAL 单元中的 RBSP 数据结构的类型
- }
- type RBSP interface {
- }
- /*
- 0 Unspecified non-VCL
- 1 Coded slice of a non-IDR picture VCL
- 2 Coded slice data partition A VCL
- 3 Coded slice data partition B VCL
- 4 Coded slice data partition C VCL
- 5 Coded slice of an IDR picture VCL
- 6 Supplemental enhancement information (SEI) non-VCL
- 7 Sequence parameter set non-VCL
- 8 Picture parameter set non-VCL
- 9 Access unit delimiter non-VCL
- 10 End of sequence non-VCL
- 11 End of stream non-VCL
- 12 Filler data non-VCL
- 13 Sequence parameter set extension non-VCL
- 14 Prefix NAL unit non-VCL
- 15 Subset sequence parameter set non-VCL
- 16 Depth parameter set non-VCL
- 17..18 Reserved non-VCL
- 19 Coded slice of an auxiliary coded picture without partitioning non-VCL
- 20 Coded slice extension non-VCL
- 21 Coded slice extension for depth view components non-VCL
- 22..23 Reserved non-VCL
- 24..31 Unspecified non-VCL
- 0:未规定
- 1:非IDR图像中不采用数据划分的片段
- 2:非IDR图像中A类数据划分片段
- 3:非IDR图像中B类数据划分片段
- 4:非IDR图像中C类数据划分片段
- 5:IDR图像的片段
- 6:补充增强信息(SEI)
- 7:序列参数集(SPS)
- 8:图像参数集(PPS)
- 9:分割符
- 10:序列结束符
- 11:流结束符
- 12:填充数据
- 13:序列参数集扩展
- 14:带前缀的NAL单元
- 15:子序列参数集
- 16 – 18:保留
- 19:不采用数据划分的辅助编码图像片段
- 20:编码片段扩展
- 21 – 23:保留
- 24 – 31:未规定
- nal_unit_type NAL类型 nal_reference_bit
- 0 未使用 0
- 1 非IDR的片 此片属于参考帧,则不等于0,不属于参考帧,则等与0
- 2 片数据A分区 同上
- 3 片数据B分区 同上
- 4 片数据C分区 同上
- 5 IDR图像的片 5
- 6 补充增强信息单元(SEI) 0
- 7 序列参数集 非0
- 8 图像参数集 非0
- 9 分界符 0
- 10 序列结束 0
- 11 码流结束 0
- 12 填充 0
- 13..23 保留 0
- 24..31 不保留 0
- */
- func ReadPPS(w io.Writer) {
- }
|