mirror of
https://github.com/Monibuca/engine.git
synced 2025-10-05 08:36:56 +08:00
188 lines
5.2 KiB
Go
188 lines
5.2 KiB
Go
package track
|
||
|
||
import (
|
||
"context"
|
||
"time"
|
||
"unsafe"
|
||
|
||
. "m7s.live/engine/v4/common"
|
||
"m7s.live/engine/v4/config"
|
||
"m7s.live/engine/v4/util"
|
||
)
|
||
|
||
type 流速控制 struct {
|
||
起始时间戳 uint32
|
||
起始时间 time.Time
|
||
等待上限 time.Duration
|
||
}
|
||
|
||
func (p *流速控制) 重置(绝对时间戳 uint32) {
|
||
p.起始时间 = time.Now()
|
||
p.起始时间戳 = 绝对时间戳
|
||
// println("重置", p.起始时间.Format("2006-01-02 15:04:05"), p.起始时间戳)
|
||
}
|
||
func (p *流速控制) 时间戳差(绝对时间戳 uint32) time.Duration {
|
||
return time.Duration(绝对时间戳-p.起始时间戳) * time.Millisecond
|
||
}
|
||
func (p *流速控制) 控制流速(绝对时间戳 uint32) {
|
||
数据时间差, 实际时间差 := p.时间戳差(绝对时间戳), time.Since(p.起始时间)
|
||
// println("数据时间差", 数据时间差, "实际时间差", 实际时间差, "绝对时间戳", 绝对时间戳, "起始时间戳", p.起始时间戳, "起始时间", p.起始时间.Format("2006-01-02 15:04:05"))
|
||
// if 实际时间差 > 数据时间差 {
|
||
// p.重置(绝对时间戳)
|
||
// return
|
||
// }
|
||
// 如果收到的帧的时间戳超过实际消耗的时间100ms就休息一下,100ms作为一个弹性区间防止频繁调用sleep
|
||
if 过快毫秒 := (数据时间差 - 实际时间差) / time.Millisecond; 过快毫秒 > 300 {
|
||
if 过快毫秒 > p.等待上限 {
|
||
time.Sleep(time.Millisecond * p.等待上限)
|
||
} else {
|
||
time.Sleep(过快毫秒 * time.Millisecond)
|
||
}
|
||
}
|
||
}
|
||
|
||
// Media 基础媒体Track类
|
||
type Media[T RawSlice] struct {
|
||
Base
|
||
AVRing[T]
|
||
SampleRate uint32
|
||
SSRC uint32
|
||
DecoderConfiguration DecoderConfiguration[T] `json:"-"` //H264(SPS、PPS) H265(VPS、SPS、PPS) AAC(config)
|
||
// util.BytesPool //无锁内存池,用于发布者(在同一个协程中)复用小块的内存,通常是解包时需要临时使用
|
||
RTPMuxer
|
||
RTPDemuxer
|
||
流速控制
|
||
}
|
||
|
||
func (av *Media[T]) SetSpeedLimit(value int) {
|
||
av.等待上限 = time.Duration(value)
|
||
}
|
||
|
||
func (av *Media[T]) SetStuff(stuff ...any) {
|
||
for _, s := range stuff {
|
||
switch v := s.(type) {
|
||
case time.Duration:
|
||
av.Poll = v
|
||
case string:
|
||
av.Name = v
|
||
case int:
|
||
av.AVRing.Init(v)
|
||
av.SSRC = uint32(uintptr(unsafe.Pointer(av)))
|
||
av.等待上限 = time.Duration(config.Global.SpeedLimit)
|
||
case uint32:
|
||
av.SampleRate = v
|
||
case byte:
|
||
av.DecoderConfiguration.PayloadType = v
|
||
case IStream:
|
||
av.Stream = v
|
||
case RTPWriter:
|
||
av.RTPWriter = v
|
||
}
|
||
}
|
||
}
|
||
|
||
func (av *Media[T]) LastWriteTime() time.Time {
|
||
return av.AVRing.RingBuffer.LastValue.Timestamp
|
||
}
|
||
|
||
func (av *Media[T]) Play(ctx context.Context, onMedia func(*AVFrame[T]) error) error {
|
||
for ar := av.ReadRing(); ctx.Err() == nil; ar.MoveNext() {
|
||
ap := ar.Read(ctx)
|
||
if err := onMedia(ap); err != nil {
|
||
// TODO: log err
|
||
return err
|
||
}
|
||
}
|
||
return ctx.Err()
|
||
}
|
||
|
||
func (av *Media[T]) ReadRing() *AVRing[T] {
|
||
return util.Clone(av.AVRing)
|
||
}
|
||
|
||
func (av *Media[T]) GetDecoderConfiguration() DecoderConfiguration[T] {
|
||
return av.DecoderConfiguration
|
||
}
|
||
|
||
func (av *Media[T]) CurrentFrame() *AVFrame[T] {
|
||
return &av.AVRing.RingBuffer.Value
|
||
}
|
||
func (av *Media[T]) PreFrame() *AVFrame[T] {
|
||
return av.AVRing.RingBuffer.LastValue
|
||
}
|
||
|
||
func (av *Media[T]) generateTimestamp() {
|
||
ts := av.AVRing.RingBuffer.Value.RTP[0].Timestamp
|
||
av.AVRing.RingBuffer.Value.PTS = ts
|
||
av.AVRing.RingBuffer.Value.DTS = ts
|
||
}
|
||
|
||
func (av *Media[T]) WriteSlice(slice T) {
|
||
av.Value.AppendRaw(slice)
|
||
}
|
||
|
||
func (av *Media[T]) WriteAVCC(ts uint32, frame AVCCFrame) {
|
||
curValue := &av.Value
|
||
cts := frame.CTS()
|
||
curValue.BytesIn += len(frame)
|
||
curValue.AppendAVCC(frame)
|
||
curValue.DTS = ts * 90
|
||
curValue.PTS = (ts + cts) * 90
|
||
// av.Stream.Tracef("WriteAVCC:ts %d,cts %d,len %d", ts, cts, len(frame))
|
||
}
|
||
|
||
func (av *Media[T]) Flush() {
|
||
curValue, preValue := &av.Value, av.LastValue
|
||
if av.起始时间.IsZero() {
|
||
av.重置(curValue.AbsTime)
|
||
} else {
|
||
curValue.DeltaTime = (curValue.DTS - preValue.DTS) / 90
|
||
println(curValue.DeltaTime ,curValue.DTS , preValue.DTS)
|
||
curValue.AbsTime = preValue.AbsTime + curValue.DeltaTime
|
||
}
|
||
av.Base.Flush(&curValue.BaseFrame)
|
||
if av.等待上限 > 0 {
|
||
av.控制流速(curValue.AbsTime)
|
||
}
|
||
av.Step()
|
||
}
|
||
|
||
func (av *Media[T]) ComplementAVCC() bool {
|
||
return config.Global.EnableAVCC && len(av.Value.AVCC) == 0
|
||
}
|
||
|
||
// 是否需要补完RTP格式
|
||
func (av *Media[T]) ComplementRTP() bool {
|
||
return config.Global.EnableRTP && len(av.Value.RTP) == 0
|
||
}
|
||
|
||
// 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[T]) PacketizeRTP(payloads ...[][]byte) {
|
||
packetCount := len(payloads)
|
||
if cap(av.Value.RTP) < packetCount {
|
||
av.Value.RTP = make([]*RTPFrame, packetCount)
|
||
} else {
|
||
av.Value.RTP = av.Value.RTP[:packetCount]
|
||
}
|
||
for i, pp := range payloads {
|
||
av.rtpSequence++
|
||
packet := av.Value.RTP[i]
|
||
if packet == nil {
|
||
packet = &RTPFrame{}
|
||
av.Value.RTP[i] = packet
|
||
packet.Version = 2
|
||
packet.PayloadType = av.DecoderConfiguration.PayloadType
|
||
packet.Payload = make([]byte, 0, 1200)
|
||
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...)
|
||
}
|
||
}
|
||
}
|