mirror of
https://github.com/Monibuca/engine.git
synced 2025-10-06 17:16:55 +08:00

2、Track增加离线状态,当发布者离线时,Track状态改为离线状态,当发布者重新上线时,Track状态改为在线状态。 3、Track在恢复在线后,记录时间戳的差值,保持后续时间戳和之前的连续。 4、进一步优化订阅者读取音视频同步逻辑。
121 lines
3.2 KiB
Go
121 lines
3.2 KiB
Go
package track
|
||
|
||
import (
|
||
"github.com/pion/rtp"
|
||
"go.uber.org/zap"
|
||
. "m7s.live/engine/v4/common"
|
||
"m7s.live/engine/v4/config"
|
||
"m7s.live/engine/v4/util"
|
||
)
|
||
|
||
const RTPMTU = 1400
|
||
|
||
func (av *Media) UnmarshalRTPPacket(p *rtp.Packet) (frame *RTPFrame) {
|
||
if av.PayloadType != p.PayloadType {
|
||
av.Warn("RTP PayloadType error", zap.Uint8("want", av.PayloadType), zap.Uint8("got", p.PayloadType))
|
||
return
|
||
}
|
||
frame = &RTPFrame{
|
||
Packet: *p,
|
||
}
|
||
av.Value.BytesIn += len(p.Payload) + 12
|
||
return av.recorderRTP(frame)
|
||
}
|
||
|
||
func (av *Media) UnmarshalRTP(raw []byte) (frame *RTPFrame) {
|
||
var p rtp.Packet
|
||
err := p.Unmarshal(raw)
|
||
if err != nil {
|
||
av.Warn("RTP Unmarshal error", zap.Error(err))
|
||
return
|
||
}
|
||
return av.UnmarshalRTPPacket(&p)
|
||
}
|
||
|
||
func (av *Media) writeRTPFrame(frame *RTPFrame) {
|
||
av.Value.RTP.PushValue(*frame)
|
||
av.WriteRTPFrame(frame)
|
||
if frame.Marker {
|
||
av.SpesificTrack.generateTimestamp(frame.Timestamp)
|
||
av.SpesificTrack.Flush()
|
||
}
|
||
}
|
||
|
||
// WriteRTPPack 写入已反序列化的RTP包
|
||
func (av *Media) WriteRTPPack(p *rtp.Packet) {
|
||
for frame := av.UnmarshalRTPPacket(p); frame != nil; frame = av.nextRTPFrame() {
|
||
av.writeRTPFrame(frame)
|
||
}
|
||
}
|
||
|
||
// WriteRTP 写入未反序列化的RTP包
|
||
func (av *Media) WriteRTP(raw []byte) {
|
||
for frame := av.UnmarshalRTP(raw); frame != nil; frame = av.nextRTPFrame() {
|
||
av.writeRTPFrame(frame)
|
||
}
|
||
}
|
||
|
||
// https://www.cnblogs.com/moonwalk/p/15903760.html
|
||
// Packetize packetizes the payload of an RTP packet and returns one or more RTP packets
|
||
func (av *Media) PacketizeRTP(payloads ...[][]byte) {
|
||
packetCount := len(payloads)
|
||
for i, pp := range payloads {
|
||
av.rtpSequence++
|
||
rtpItem := av.rtpPool.Get()
|
||
packet := &rtpItem.Value
|
||
if packet.Payload == nil {
|
||
packet.Payload = make([]byte, 0, RTPMTU)
|
||
packet.Version = 2
|
||
packet.PayloadType = av.PayloadType
|
||
packet.SSRC = av.SSRC
|
||
}
|
||
packet.Payload = packet.Payload[:0]
|
||
packet.SequenceNumber = av.rtpSequence
|
||
packet.Timestamp = av.Value.PTS
|
||
packet.Marker = i == packetCount-1
|
||
for _, p := range pp {
|
||
packet.Payload = append(packet.Payload, p...)
|
||
}
|
||
av.Value.RTP.Push(rtpItem)
|
||
}
|
||
}
|
||
|
||
type RTPDemuxer struct {
|
||
lastSeq uint16 //上一个收到的序号,用于乱序重排
|
||
lastSeq2 uint16 //记录上上一个收到的序列号
|
||
乱序重排 util.RTPReorder[*RTPFrame]
|
||
}
|
||
|
||
// 获取缓存中下一个rtpFrame
|
||
func (av *RTPDemuxer) nextRTPFrame() (frame *RTPFrame) {
|
||
if config.Global.RTPReorder {
|
||
return av.乱序重排.Pop()
|
||
}
|
||
return
|
||
}
|
||
|
||
// 对RTP包乱序重排
|
||
func (av *RTPDemuxer) recorderRTP(frame *RTPFrame) *RTPFrame {
|
||
if config.Global.RTPReorder {
|
||
return av.乱序重排.Push(frame.SequenceNumber, frame)
|
||
} else {
|
||
if av.lastSeq == 0 {
|
||
av.lastSeq = frame.SequenceNumber
|
||
} else if frame.SequenceNumber == av.lastSeq2+1 { // 本次序号是上上次的序号+1 说明中间隔了一个错误序号(某些rtsp流中的rtcp包写成了rtp包导致的)
|
||
av.lastSeq = frame.SequenceNumber
|
||
} else {
|
||
av.lastSeq2 = av.lastSeq
|
||
av.lastSeq = frame.SequenceNumber
|
||
if av.lastSeq != av.lastSeq2+1 { //序号不连续
|
||
// av.Stream.Warn("RTP SequenceNumber error", av.lastSeq2, av.lastSeq)
|
||
return frame
|
||
}
|
||
}
|
||
return frame
|
||
}
|
||
}
|
||
|
||
type RTPMuxer struct {
|
||
rtpSequence uint16 //用于生成下一个rtp包的序号
|
||
}
|