123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- // 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,
- }
- }
|