mirror of
https://github.com/Monibuca/engine.git
synced 2025-10-05 16:46:58 +08:00
90 lines
2.3 KiB
Go
90 lines
2.3 KiB
Go
package engine
|
|
|
|
import (
|
|
"encoding/binary"
|
|
|
|
. "github.com/Monibuca/engine/v3/avformat"
|
|
)
|
|
|
|
const (
|
|
fuaHeaderSize = 2
|
|
stapaHeaderSize = 1
|
|
stapaNALULengthSize = 2
|
|
|
|
naluTypeBitmask = 0x1F
|
|
naluRefIdcBitmask = 0x60
|
|
fuaStartBitmask = 0x80 //1000 0000
|
|
fuaEndBitmask = 0x40 //0100 0000
|
|
)
|
|
|
|
type NALU struct {
|
|
Publisher
|
|
fuBuffer []byte //用于fua的解析暂存的缓存
|
|
lastTs uint32
|
|
buffer []byte //用于存储分帧的Nalu数据
|
|
}
|
|
|
|
func (r *NALU) writePicture(ts uint32, head, payload []byte) {
|
|
if r.VideoTag == nil {
|
|
return
|
|
}
|
|
if payload[1]&fuaStartBitmask != 0 {
|
|
if len(r.buffer) > 0 {
|
|
r.PushVideo(r.lastTs, r.buffer)
|
|
r.buffer = nil
|
|
}
|
|
r.buffer = append(r.buffer, head...)
|
|
r.lastTs = ts
|
|
}
|
|
nl := len(payload)
|
|
r.buffer = append(r.buffer, byte(nl>>24), byte(nl>>16), byte(nl>>8), byte(nl))
|
|
r.buffer = append(r.buffer, payload...)
|
|
}
|
|
func (r *NALU) WriteNALU(ts uint32, payload []byte) {
|
|
if len(payload) == 0 {
|
|
return
|
|
}
|
|
nalType := payload[0] & naluTypeBitmask
|
|
switch nalType {
|
|
case NALU_STAPA:
|
|
for currOffset, naluSize := stapaHeaderSize, 0; currOffset < len(payload); currOffset += naluSize {
|
|
naluSize = int(binary.BigEndian.Uint16(payload[currOffset:]))
|
|
currOffset += stapaNALULengthSize
|
|
if currOffset+len(payload) < currOffset+naluSize {
|
|
Printf("STAP-A declared size(%d) is larger then buffer(%d)", naluSize, len(payload)-currOffset)
|
|
return
|
|
}
|
|
r.WriteNALU(ts, payload[currOffset:currOffset+naluSize])
|
|
}
|
|
case NALU_FUA:
|
|
if len(payload) < fuaHeaderSize {
|
|
Printf("Payload is not large enough to be FU-A")
|
|
return
|
|
}
|
|
if payload[1]&fuaStartBitmask != 0 {
|
|
naluRefIdc := payload[0] & naluRefIdcBitmask
|
|
fragmentedNaluType := payload[1] & naluTypeBitmask
|
|
r.fuBuffer = append([]byte{}, payload...)
|
|
r.fuBuffer[fuaHeaderSize-1] = naluRefIdc | fragmentedNaluType
|
|
} else {
|
|
r.fuBuffer = append(r.fuBuffer, payload[fuaHeaderSize:]...)
|
|
}
|
|
if payload[1]&fuaEndBitmask != 0 {
|
|
r.WriteNALU(ts, r.fuBuffer[fuaHeaderSize-1:])
|
|
}
|
|
case NALU_SPS:
|
|
r.WriteSPS(payload)
|
|
case NALU_PPS:
|
|
r.WritePPS(payload)
|
|
case NALU_Access_Unit_Delimiter:
|
|
|
|
case NALU_IDR_Picture:
|
|
r.writePicture(ts, RTMP_KEYFRAME_HEAD, payload)
|
|
case NALU_Non_IDR_Picture:
|
|
r.writePicture(ts, RTMP_NORMALFRAME_HEAD, payload)
|
|
case NALU_SEI:
|
|
default:
|
|
Printf("nalType not support yet:%d", nalType)
|
|
}
|
|
}
|