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/rtprtcp/rtp_unpack_container.go

91 lines
2.0 KiB
Go

// Copyright 2020, 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 rtprtcp
type RtpUnpackContainer struct {
unpackerProtocol IRtpUnpackerProtocol
list RtpPacketList
}
func NewRtpUnpackContainer(maxSize int, unpackerProtocol IRtpUnpackerProtocol) *RtpUnpackContainer {
p := &RtpUnpackContainer{
unpackerProtocol: unpackerProtocol,
}
p.list.InitMaxSize(maxSize)
return p
}
// Feed 输入收到的rtp包
func (r *RtpUnpackContainer) Feed(pkt RtpPacket) {
// 过期的包
if r.list.IsStale(pkt.Header.Seq) {
return
}
// 计算位置
r.unpackerProtocol.CalcPositionIfNeeded(&pkt)
// 根据序号插入有序链表
r.list.Insert(pkt)
// 尽可能多的合成顺序的帧
count := 0
for {
if !r.tryUnpackOneSequential() {
break
}
count++
}
// 合成顺序的帧成功了,直接返回
if count > 0 {
return
}
// 缓存达到最大值
if r.list.Full() {
// 尝试合成一帧发生跳跃的帧
packed := r.tryUnpackOne()
if !packed {
// 合成失败了,丢弃一包过期数据
r.list.PopFirst()
return
}
// 合成成功了,再次尝试,尽可能多的合成顺序的帧
for {
if !r.tryUnpackOneSequential() {
break
}
}
}
}
// tryUnpackOneSequential 从队列头部尝试合成一个完整的帧。保证这次合成的帧的首个seq和上次合成帧的尾部seq是连续的
//
func (r *RtpUnpackContainer) tryUnpackOneSequential() bool {
if !r.list.IsFirstSequential() {
return false
}
return r.tryUnpackOne()
}
// tryUnpackOne 从队列头部尝试合成一个完整的帧。不保证这次合成的帧的首个seq和上次合成帧的尾部seq是连续的
//
func (r *RtpUnpackContainer) tryUnpackOne() bool {
unpackedFlag, unpackedSeq := r.unpackerProtocol.TryUnpackOne(&r.list)
if unpackedFlag {
r.list.SetUnpackedSeq(unpackedSeq)
}
return unpackedFlag
}