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

151 lines
3.4 KiB

2 years ago
package webrtc
import (
"bytes"
"encoding/binary"
"errors"
"strconv"
// "fmt"
. "github.com/pion/webrtc/v3"
)
// H265
// https://zhuanlan.zhihu.com/p/458497037
const (
NALU_H265_VPS = 0x4001
NALU_H265_SPS = 0x4201
NALU_H265_PPS = 0x4401
NALU_H265_SEI = 0x4e01
NALU_H265_IFRAME = 0x2601
NALU_H265_PFRAME = 0x0201
HEVC_NAL_TRAIL_N = 0
HEVC_NAL_TRAIL_R = 1
HEVC_NAL_TSA_N = 2
HEVC_NAL_TSA_R = 3
HEVC_NAL_STSA_N = 4
HEVC_NAL_STSA_R = 5
HEVC_NAL_BLA_W_LP = 16
HEVC_NAL_BLA_W_RADL = 17
HEVC_NAL_BLA_N_LP = 18
HEVC_NAL_IDR_W_RADL = 19
HEVC_NAL_IDR_N_LP = 20
HEVC_NAL_CRA_NUT = 21
HEVC_NAL_RADL_N = 6
HEVC_NAL_RADL_R = 7
HEVC_NAL_RASL_N = 8
HEVC_NAL_RASL_R = 9
MAXPACKETSIZE = 65536
)
func SendH265FrameData(dc *DataChannel, data []byte, timestamp int64) {
if len(data) > 4 && dc != nil && dc.ReadyState() == DataChannelStateOpen {
var frametypestr string
glength := len(data)
count := glength / MAXPACKETSIZE
rem := glength % MAXPACKETSIZE
packets := count
if rem != 0 {
packets++
}
temptype, frametype, err := GetFrameType(data)
if err != nil {
} else {
frametypestr, err = GetFrameTypeName(frametype)
}
startstr := "h265 start ,FrameType:" + frametypestr + ",nalutype:" + strconv.Itoa(int(temptype)) + ",pts:" + strconv.FormatInt(timestamp, 10) + ",Packetslen:" + strconv.Itoa(glength) + ",packets:" + strconv.Itoa(packets) + ",rem:" + strconv.Itoa(rem)
_ = dc.SendText(startstr)
i := 0
for i = 0; i < count; i++ {
length := i * MAXPACKETSIZE
_ = dc.Send(data[length : length+MAXPACKETSIZE])
}
if rem != 0 {
_ = dc.Send(data[glength-rem : glength])
}
_ = dc.SendText("h265 end")
}
}
func GetFrameType(pdata []byte) (uint8, uint16, error) {
var frametype uint16
destcount := 0
if FindStartCode2(pdata) {
destcount = 3
} else if FindStartCode3(pdata) {
destcount = 4
} else {
return 0, 0, errors.New("not find")
}
temptype := (pdata[destcount] & 0x7E) >> 1
bytesBuffer := bytes.NewBuffer(pdata[destcount : destcount+2])
binary.Read(bytesBuffer, binary.BigEndian, &frametype)
return temptype, frametype, nil
}
func GetFrameTypeName(frametype uint16) (string, error) {
switch frametype {
case NALU_H265_VPS:
return "H265_FRAME_VPS", nil
case NALU_H265_SPS:
return "H265_FRAME_SPS", nil
case NALU_H265_PPS:
return "H265_FRAME_PPS", nil
case NALU_H265_SEI:
return "H265_FRAME_SEI", nil
case NALU_H265_IFRAME:
return "H265_FRAME_I", nil
case NALU_H265_PFRAME:
return "H265_FRAME_P", nil
default:
return "", errors.New("frametype unsupport")
}
}
func FindStartCode2(Buf []byte) bool {
if Buf[0] != 0 || Buf[1] != 0 || Buf[2] != 1 {
return false //判断是否为0x000001,如果是返回1
} else {
return true
}
}
func FindStartCode3(Buf []byte) bool {
if Buf[0] != 0 || Buf[1] != 0 || Buf[2] != 0 || Buf[3] != 1 {
return false //判断是否为0x00000001,如果是返回1
} else {
return true
}
}
func Add3ZoneOne(h265frame []byte) []byte {
var hBuf = [4]byte{0, 0, 0, 1}
var data []byte
for i := range hBuf {
data = append(data, hBuf[i])
}
for i := range h265frame {
data = append(data, h265frame[i])
}
return data
}
func AddBufs(A []byte, B []byte) []byte {
var data []byte
for i := range A {
data = append(data, A[i])
}
for i := range B {
data = append(data, B[i])
}
return data
}
type WebRtcReturn struct {
SessionDescription
IsH265 bool `json:"isH265"`
}