mirror of
https://github.com/AlexxIT/go2rtc.git
synced 2025-10-06 16:57:29 +08:00
112 lines
2.1 KiB
Go
112 lines
2.1 KiB
Go
// Package h264 - AVCC format related functions
|
|
package h264
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/base64"
|
|
"encoding/binary"
|
|
"encoding/hex"
|
|
|
|
"github.com/AlexxIT/go2rtc/pkg/core"
|
|
"github.com/pion/rtp"
|
|
)
|
|
|
|
func RepairAVCC(codec *core.Codec, handler core.HandlerFunc) core.HandlerFunc {
|
|
sps, pps := GetParameterSet(codec.FmtpLine)
|
|
ps := JoinNALU(sps, pps)
|
|
|
|
return func(packet *rtp.Packet) {
|
|
if NALUType(packet.Payload) == NALUTypeIFrame {
|
|
packet.Payload = Join(ps, packet.Payload)
|
|
}
|
|
handler(packet)
|
|
}
|
|
}
|
|
|
|
func JoinNALU(nalus ...[]byte) (avcc []byte) {
|
|
var i, n int
|
|
|
|
for _, nalu := range nalus {
|
|
if i = len(nalu); i > 0 {
|
|
n += 4 + i
|
|
}
|
|
}
|
|
|
|
avcc = make([]byte, n)
|
|
|
|
n = 0
|
|
for _, nal := range nalus {
|
|
if i = len(nal); i > 0 {
|
|
binary.BigEndian.PutUint32(avcc[n:], uint32(i))
|
|
n += 4 + copy(avcc[n+4:], nal)
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func SplitNALU(avcc []byte) [][]byte {
|
|
var nals [][]byte
|
|
for {
|
|
// get AVC length
|
|
size := int(binary.BigEndian.Uint32(avcc)) + 4
|
|
|
|
// check if multiple items in one packet
|
|
if size < len(avcc) {
|
|
nals = append(nals, avcc[:size])
|
|
avcc = avcc[size:]
|
|
} else {
|
|
nals = append(nals, avcc)
|
|
break
|
|
}
|
|
}
|
|
return nals
|
|
}
|
|
|
|
func NALUTypes(avcc []byte) []byte {
|
|
var types []byte
|
|
for {
|
|
types = append(types, NALUType(avcc))
|
|
|
|
size := 4 + int(binary.BigEndian.Uint32(avcc))
|
|
if size < len(avcc) {
|
|
avcc = avcc[size:]
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
return types
|
|
}
|
|
|
|
func AVCCToCodec(avcc []byte) *core.Codec {
|
|
buf := bytes.NewBufferString("packetization-mode=1")
|
|
|
|
for {
|
|
size := 4 + int(binary.BigEndian.Uint32(avcc))
|
|
|
|
switch NALUType(avcc) {
|
|
case NALUTypeSPS:
|
|
buf.WriteString(";profile-level-id=")
|
|
buf.WriteString(hex.EncodeToString(avcc[5:8]))
|
|
buf.WriteString(";sprop-parameter-sets=")
|
|
buf.WriteString(base64.StdEncoding.EncodeToString(avcc[4:size]))
|
|
case NALUTypePPS:
|
|
buf.WriteString(",")
|
|
buf.WriteString(base64.StdEncoding.EncodeToString(avcc[4:size]))
|
|
}
|
|
|
|
if size < len(avcc) {
|
|
avcc = avcc[size:]
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
|
|
return &core.Codec{
|
|
Name: core.CodecH264,
|
|
ClockRate: 90000,
|
|
FmtpLine: buf.String(),
|
|
PayloadType: core.PayloadTypeRAW,
|
|
}
|
|
}
|