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/sdp/pack.go

116 lines
2.8 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.

// Copyright 2021, Chef. All rights reserved.
// https://github.com/q191201771/lal
//
// Use of this source code is governed by a MIT-style license
// that can be found in the License file.
//
// Author: Chef (191201771@qq.com)
package sdp
import (
"encoding/base64"
"encoding/hex"
"fmt"
"strings"
"github.com/q191201771/naza/pkg/nazaerrors"
"github.com/q191201771/lal/pkg/aac"
"github.com/q191201771/lal/pkg/base"
)
// Pack
//
// @param samplingFrequency: 音频采样率注意当前G711U使用这个参数传递AAC的采样率通过 asc 参数传递 TODO(chef): 考虑 AAC 采样率通过 samplingFrequency 传递 202303
func Pack(vps, sps, pps, asc []byte, audioPt base.AvPacketPt, samplingFrequency int) (ctx LogicContext, err error) {
// 判断音频、视频是否存在以及视频是H264还是H265
var hasAudio, hasVideo, isHevc, isAac bool
if sps != nil && pps != nil {
hasVideo = true
if vps != nil {
isHevc = true
}
}
if audioPt != base.AvPacketPtUnknown {
switch audioPt {
case base.AvPacketPtG711U:
hasAudio = true
case base.AvPacketPtAac:
if asc != nil {
isAac = true
hasAudio = true
// 判断AAC的采样率
var ascCtx *aac.AscContext
ascCtx, err = aac.NewAscContext(asc)
if err != nil {
return
}
samplingFrequency, err = ascCtx.GetSamplingFrequency()
if err != nil {
return
}
}
}
}
if !hasAudio && !hasVideo {
err = nazaerrors.Wrap(base.ErrSdp)
return
}
sdpStr := fmt.Sprintf(`v=0
o=- 0 0 IN IP4 127.0.0.1
s=No Name
c=IN IP4 127.0.0.1
t=0 0
a=tool:%s
`, base.LalPackSdp)
streamid := 0
if hasVideo {
if isHevc {
tmpl := `m=video 0 RTP/AVP 98
a=rtpmap:98 H265/90000
a=fmtp:98 profile-id=1;sprop-sps=%s;sprop-pps=%s;sprop-vps=%s
a=control:streamid=%d
`
sdpStr += fmt.Sprintf(tmpl, base64.StdEncoding.EncodeToString(sps), base64.StdEncoding.EncodeToString(pps), base64.StdEncoding.EncodeToString(vps), streamid)
} else {
tmpl := `m=video 0 RTP/AVP 96
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1; sprop-parameter-sets=%s,%s; profile-level-id=640016
a=control:streamid=%d
`
sdpStr += fmt.Sprintf(tmpl, base64.StdEncoding.EncodeToString(sps), base64.StdEncoding.EncodeToString(pps), streamid)
}
streamid++
}
if hasAudio {
if isAac {
tmpl := `m=audio 0 RTP/AVP 97
b=AS:128
a=rtpmap:97 MPEG4-GENERIC/%d/2
a=fmtp:97 profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3; config=%s
a=control:streamid=%d
`
sdpStr += fmt.Sprintf(tmpl, samplingFrequency, hex.EncodeToString(asc), streamid)
} else {
tmpl := `m=audio 0 RTP/AVP 0
a=rtpmap:0 PCMU/%d
a=control:streamid=%d
`
sdpStr += fmt.Sprintf(tmpl, samplingFrequency, streamid)
}
}
raw := []byte(strings.ReplaceAll(sdpStr, "\n", "\r\n"))
ctx, err = ParseSdp2LogicContext(raw)
return
}