You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lal/pkg/avc/avc.go

97 lines
2.4 KiB
Go

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package avc
import (
"errors"
"github.com/q191201771/nezha/pkg/bele"
"io"
)
var avcErr = errors.New("avc: fxxk")
var NaluStartCode = []byte{0x0, 0x0, 0x0, 0x1}
var NaluUintTypeMapping = map[uint8]string{
1: "SLICE",
5: "IDR",
6: "SEI",
7: "SPS",
8: "PPS",
9: "AUD",
}
// 从 rtmp avc sequence header 中解析 sps 和 pps
// @param <payload> rtmp message的payload部分 或者 flv tag的payload部分
func ParseAVCSeqHeader(payload []byte) (sps, pps []byte, err error) {
// TODO chef: check if read out of <payload> range
if payload[0] != 0x17 || payload[1] != 0x00 || payload[2] != 0 || payload[3] != 0 || payload[4] != 0 {
err = avcErr
return
}
// H.264-AVC-ISO_IEC_14496-15.pdf
// 5.2.4 Decoder configuration information
//configurationVersion := payload[5]
//avcProfileIndication := payload[6]
//profileCompatibility := payload[7]
//avcLevelIndication := payload[8]
//lengthSizeMinusOne := payload[9] & 0x03
index := 10
numOfSPS := int(payload[index] & 0x1F)
index++
// TODO chef: if the situation of multi sps exist?
// only take the last one.
for i := 0; i < numOfSPS; i++ {
lenOfSPS := int(bele.BEUint16(payload[index:]))
index += 2
sps = append(sps, payload[index:index+lenOfSPS]...)
index += lenOfSPS
}
numOfPPS := int(payload[index] & 0x1F)
index++
for i := 0; i < numOfPPS; i++ {
lenOfPPS := int(bele.BEUint16(payload[index:]))
index += 2
pps = append(pps, payload[index:index+lenOfPPS]...)
index += lenOfPPS
}
return
}
// 将rtmp avc数据转换成avc裸流
// @param <payload> rtmp message的payload部分 或者 flv tag的payload部分
func CaptureAVC(w io.Writer, payload []byte) error {
// sps pps
if payload[0] == 0x17 && payload[1] == 0x00 {
sps, pps, err := ParseAVCSeqHeader(payload)
if err != nil {
return err
}
//utilErrors.PanicIfErrorOccur(err)
_, _ = w.Write(NaluStartCode)
_, _ = w.Write(sps)
_, _ = w.Write(NaluStartCode)
_, _ = w.Write(pps)
return nil
}
// payload中可能存在多个nalu
// 先跳过前面type的2字节以及composition time的3字节
for i := 5; i != len(payload); {
naluLen := int(bele.BEUint32(payload[i:]))
i += 4
//naluUintType := payload[i] & 0x1f
//log.Debugf("naluLen:%d t:%d %s\n", naluLen, naluUintType, avc.NaluUintTypeMapping[naluUintType])
_, _ = w.Write(NaluStartCode)
_, _ = w.Write(payload[i : i+naluLen])
i += naluLen
break
}
return nil
}