diff --git a/pkg/base/avpacket.go b/pkg/base/avpacket.go index 046cb32..5f6a2e9 100644 --- a/pkg/base/avpacket.go +++ b/pkg/base/avpacket.go @@ -11,6 +11,7 @@ package base import ( "encoding/hex" "fmt" + "github.com/q191201771/naza/pkg/nazabytes" ) @@ -20,9 +21,10 @@ type AvPacketPt int const ( AvPacketPtUnknown AvPacketPt = -1 + AvPacketPtG711A AvPacketPt = 8 // g711a AvPacketPtAvc AvPacketPt = 96 // h264 AvPacketPtHevc AvPacketPt = 98 // h265 - AvPacketPtAac AvPacketPt = 97 + AvPacketPtAac AvPacketPt = 97 // aac ) func (a AvPacketPt) ReadableString() string { diff --git a/pkg/rtprtcp/rtp_unpacker.go b/pkg/rtprtcp/rtp_unpacker.go index 590bddf..19179e7 100644 --- a/pkg/rtprtcp/rtp_unpacker.go +++ b/pkg/rtprtcp/rtp_unpacker.go @@ -21,6 +21,7 @@ var ( _ IRtpUnpackContainer = &RtpUnpackContainer{} _ IRtpUnpackerProtocol = &RtpUnpackerAac{} _ IRtpUnpackerProtocol = &RtpUnpackerAvcHevc{} + _ IRtpUnpackerProtocol = &RtpUnpackerRaw{} ) type IRtpUnpacker interface { @@ -75,6 +76,8 @@ func DefaultRtpUnpackerFactory(payloadType base.AvPacketPt, clockRate int, maxSi switch payloadType { case base.AvPacketPtAac: protocol = NewRtpUnpackerAac(payloadType, clockRate, onAvPacket) + case base.AvPacketPtG711A: + protocol = NewRtpUnpackerRaw(payloadType, clockRate, onAvPacket) case base.AvPacketPtAvc: fallthrough case base.AvPacketPtHevc: diff --git a/pkg/rtprtcp/rtp_unpacker_raw.go b/pkg/rtprtcp/rtp_unpacker_raw.go new file mode 100644 index 0000000..44d5bf8 --- /dev/null +++ b/pkg/rtprtcp/rtp_unpacker_raw.go @@ -0,0 +1,40 @@ +package rtprtcp + +import "github.com/q191201771/lal/pkg/base" + +type RtpUnpackerRaw struct { + payloadType base.AvPacketPt + clockRate int + onAvPacket OnAvPacket +} + +func NewRtpUnpackerRaw(payloadType base.AvPacketPt, clockRate int, onAvPacket OnAvPacket) *RtpUnpackerRaw { + return &RtpUnpackerRaw{ + payloadType: payloadType, + clockRate: clockRate, + onAvPacket: onAvPacket, + } +} + +func (unpacker *RtpUnpackerRaw) CalcPositionIfNeeded(pkt *RtpPacket) { + // noop +} + +func (unpacker *RtpUnpackerRaw) TryUnpackOne(list *RtpPacketList) (unpackedFlag bool, unpackedSeq uint16) { + p := list.Head.Next // first + if p == nil { + return false, 0 + } + + // 暂时认为一个rtp为一帧数据(G711A/G711U) + b := p.Packet.Body() + var outPkt base.AvPacket + outPkt.PayloadType = unpacker.payloadType + outPkt.Timestamp = int64(p.Packet.Header.Timestamp / uint32(unpacker.clockRate/1000)) + outPkt.Payload = b + unpacker.onAvPacket(outPkt) + + list.Head.Next = p.Next + list.Size-- + return true, p.Packet.Header.Seq +} diff --git a/pkg/rtsp/avpacket_queue.go b/pkg/rtsp/avpacket_queue.go index 3ef9aad..c7d528a 100644 --- a/pkg/rtsp/avpacket_queue.go +++ b/pkg/rtsp/avpacket_queue.go @@ -64,6 +64,8 @@ func (a *AvPacketQueue) Feed(pkt base.AvPacket) { pkt.Timestamp -= a.videoBaseTs _ = a.videoQueue.PushBack(pkt) + case base.AvPacketPtG711A: + fallthrough case base.AvPacketPtAac: if pkt.Timestamp < a.audioBaseTs { Log.Warnf("audio ts rotate. pktTS=%d, audioBaseTs=%d, videoBaseTs=%d, audioQueue=%d, videoQueue=%d", diff --git a/pkg/sdp/parse_logic.go b/pkg/sdp/parse_logic.go index c63cc86..521711f 100644 --- a/pkg/sdp/parse_logic.go +++ b/pkg/sdp/parse_logic.go @@ -125,8 +125,22 @@ func ParseSdp2LogicContext(b []byte) (LogicContext, error) { } else { Log.Warnf("aac afmtp not exist.") } + } else if strings.EqualFold(md.ARtpMap.EncodingName, ARtpMapEncodingNameG711A) { + // 例子:a=rtpmap:8 PCMA/8000/1 + // rtmpmap中有PCMA字段表示G711A + ret.audioPayloadTypeBase = base.AvPacketPtG711A } else { - ret.audioPayloadTypeBase = base.AvPacketPtUnknown + if md.M.PT == 8 { + // ffmpeg推流情况下不会填充rtpmap字段,m中pt值为8也可以表示是PCMA,采样率默认为8000Hz + // RFC3551中表明G711A固定pt值为8 + ret.audioPayloadTypeBase = base.AvPacketPtG711A + ret.audioPayloadTypeOrigin = 8 + if ret.AudioClockRate == 0 { + ret.AudioClockRate = 8000 + } + } else { + ret.audioPayloadTypeBase = base.AvPacketPtUnknown + } } case "video": ret.hasVideo = true diff --git a/pkg/sdp/parse_raw.go b/pkg/sdp/parse_raw.go index c014422..a2114e5 100644 --- a/pkg/sdp/parse_raw.go +++ b/pkg/sdp/parse_raw.go @@ -29,6 +29,7 @@ type MediaDesc struct { type M struct { Media string + PT int // 暂时只支持m只有一个pt值的情况 } type ARtpMap struct { @@ -88,6 +89,7 @@ func ParseM(s string) (ret M, err error) { return ret, nazaerrors.Wrap(base.ErrSdp) } ret.Media = items[0] + ret.PT, _ = strconv.Atoi(items[3]) return } diff --git a/pkg/sdp/sdp.go b/pkg/sdp/sdp.go index 30e7c6f..826bb49 100644 --- a/pkg/sdp/sdp.go +++ b/pkg/sdp/sdp.go @@ -11,7 +11,8 @@ package sdp // rfc4566 const ( - ARtpMapEncodingNameH265 = "H265" - ARtpMapEncodingNameH264 = "H264" - ARtpMapEncodingNameAac = "MPEG4-GENERIC" + ARtpMapEncodingNameH265 = "H265" + ARtpMapEncodingNameH264 = "H264" + ARtpMapEncodingNameAac = "MPEG4-GENERIC" + ARtpMapEncodingNameG711A = "PCMA" )