Files
lkm/jt1078/jt_packet.go
2025-07-17 09:59:30 +08:00

155 lines
3.0 KiB
Go

package jt1078
import (
"encoding/binary"
"fmt"
"github.com/lkmio/avformat/utils"
"strings"
)
const (
VideoIFrameMark = 0b000
VideoPFrameMark = 0b001
VideoBFrameMark = 0b010
AudioFrameMark = 0b011
TransmissionDataMark = 0b100
PTVideoH264 = 98
PTVideoH265 = 99
PTVideoAVS = 100
PTVideoSVAC = 101
PTAudioG711A = 6
PTAudioG711U = 7
PTAudioG726 = 8
PTAudioG729A = 9
PTAudioAAC = 19
PTAudioMP3 = 25
PTAudioADPCMA = 26
)
// Packet 1078-2016音视频和透传包. 视频帧包头26个字节, 音频帧22个字节, 透传数据14个字节.
type Packet struct {
version int // 2016-sim卡号6字节长度/2019-sim卡号10字节长度
pt byte
packetType byte
seq uint16
ts uint64
subMark byte
simNumber string
channelNumber byte
payload []byte
}
func (p *Packet) Unmarshal(data []byte) error {
length := len(data)
var packetType byte
if p.version == 2019 {
if length < 16 {
return fmt.Errorf("invaild data")
}
packetType = data[15] >> 4 & 0x0F
} else {
if length < 12 {
return fmt.Errorf("invaild data")
}
packetType = data[11] >> 4 & 0x0F
}
var minSize int
if packetType < AudioFrameMark {
minSize = 26
} else if AudioFrameMark == packetType {
minSize = 22
} else if TransmissionDataMark == packetType {
minSize = 14
} else {
return fmt.Errorf("unknown packet type %x", packetType)
}
simNumberLength := 6
if p.version == 2019 {
minSize += 4
simNumberLength += 4
}
if length < minSize {
return fmt.Errorf("invaild data")
}
// x扩展位,固定为0
_ = data[0] >> 4 & 0x1
pt := data[1] & 0x7F
// seq
seq := binary.BigEndian.Uint16(data[2:])
var simNumber string
n := 4
for ; simNumberLength > 0; simNumberLength-- {
simNumber += fmt.Sprintf("%02x", data[n])
n++
}
simNumber = strings.TrimLeft(simNumber, "0")
// channel
channelNumber := data[n]
n++
// subMark
subMark := data[n] & 0x0F
n++
// 时间戳,单位ms
var ts uint64
// 音视频帧才有时间戳字段
if TransmissionDataMark != packetType {
ts = binary.BigEndian.Uint64(data[n:])
n += 8
}
// 与上一帧的间隔时间戳, 视频帧才有此字段
if AudioFrameMark > packetType {
// iFrameInterval
_ = binary.BigEndian.Uint16(data[n:])
n += 2
// lastFrameInterval
_ = binary.BigEndian.Uint16(data[n:])
n += 2
}
// size
_ = binary.BigEndian.Uint16(data[n:])
n += 2
p.pt = pt
p.packetType = packetType
p.seq = seq
p.ts = ts
p.simNumber = simNumber
p.channelNumber = channelNumber
p.subMark = subMark
p.payload = data[n:]
return nil
}
func PT2CodecID(pt byte) (error, utils.AVCodecID) {
switch pt {
case PTVideoH264:
return nil, utils.AVCodecIdH264
case PTVideoH265:
return nil, utils.AVCodecIdH265
case PTAudioG711A:
return nil, utils.AVCodecIdPCMALAW
case PTAudioG711U:
return nil, utils.AVCodecIdPCMMULAW
case PTAudioAAC:
return nil, utils.AVCodecIdAAC
case PTAudioG726:
return nil, utils.AVCodecIdADPCMG726
default:
return fmt.Errorf("the codec %d is not implemented", pt), utils.AVCodecIdNONE
}
}