mirror of
https://github.com/Monibuca/engine.git
synced 2025-09-26 20:41:29 +08:00
109 lines
2.6 KiB
Go
109 lines
2.6 KiB
Go
package engine
|
|
|
|
import (
|
|
"os"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/bluenviron/mediacommon/pkg/codecs/mpeg4audio"
|
|
"github.com/pion/webrtc/v3/pkg/media/rtpdump"
|
|
"go.uber.org/zap"
|
|
"m7s.live/engine/v4/codec"
|
|
"m7s.live/engine/v4/common"
|
|
"m7s.live/engine/v4/track"
|
|
"m7s.live/engine/v4/util"
|
|
)
|
|
|
|
type RTPDumpPublisher struct {
|
|
Publisher
|
|
VCodec codec.VideoCodecID
|
|
ACodec codec.AudioCodecID
|
|
VPayloadType uint8
|
|
APayloadType uint8
|
|
other rtpdump.Packet
|
|
sync.Mutex
|
|
}
|
|
|
|
func (t *RTPDumpPublisher) Feed(file *os.File) {
|
|
|
|
r, h, err := rtpdump.NewReader(file)
|
|
if err != nil {
|
|
t.Stream.Error("RTPDumpPublisher open file error", zap.Error(err))
|
|
return
|
|
}
|
|
t.Lock()
|
|
t.Stream.Info("RTPDumpPublisher open file success", zap.String("file", file.Name()), zap.String("start", h.Start.String()), zap.String("source", h.Source.String()), zap.Uint16("port", h.Port))
|
|
if t.VideoTrack == nil {
|
|
switch t.VCodec {
|
|
case codec.CodecID_H264:
|
|
t.VideoTrack = track.NewH264(t, t.VPayloadType)
|
|
case codec.CodecID_H265:
|
|
t.VideoTrack = track.NewH265(t, t.VPayloadType)
|
|
}
|
|
if t.VideoTrack != nil {
|
|
t.VideoTrack.SetSpeedLimit(500 * time.Millisecond)
|
|
}
|
|
}
|
|
if t.AudioTrack == nil {
|
|
switch t.ACodec {
|
|
case codec.CodecID_AAC:
|
|
at := track.NewAAC(t, t.APayloadType)
|
|
t.AudioTrack = at
|
|
var c mpeg4audio.Config
|
|
c.ChannelCount = 2
|
|
c.SampleRate = 48000
|
|
asc, _ := c.Marshal()
|
|
at.WriteSequenceHead(append([]byte{0xAF, 0x00}, asc...))
|
|
case codec.CodecID_PCMA:
|
|
t.AudioTrack = track.NewG711(t, true, t.APayloadType)
|
|
case codec.CodecID_PCMU:
|
|
t.AudioTrack = track.NewG711(t, false, t.APayloadType)
|
|
}
|
|
if t.AudioTrack != nil {
|
|
t.AudioTrack.SetSpeedLimit(500 * time.Millisecond)
|
|
}
|
|
}
|
|
t.Unlock()
|
|
needLock := true
|
|
for {
|
|
packet, err := r.Next()
|
|
if err != nil {
|
|
t.Stream.Error("RTPDumpPublisher read file error", zap.Error(err))
|
|
return
|
|
}
|
|
if packet.IsRTCP {
|
|
continue
|
|
}
|
|
if needLock {
|
|
t.Lock()
|
|
}
|
|
if t.other.Payload == nil {
|
|
t.other = packet
|
|
t.Unlock()
|
|
needLock = true
|
|
continue
|
|
}
|
|
if packet.Offset >= t.other.Offset {
|
|
t.WriteRTP(t.other.Payload)
|
|
t.other = packet
|
|
t.Unlock()
|
|
needLock = true
|
|
continue
|
|
}
|
|
needLock = false
|
|
t.WriteRTP(packet.Payload)
|
|
}
|
|
}
|
|
func (t *RTPDumpPublisher) WriteRTP(raw []byte) {
|
|
var frame common.RTPFrame
|
|
frame.Unmarshal(raw)
|
|
switch frame.PayloadType {
|
|
case t.VPayloadType:
|
|
t.VideoTrack.WriteRTP(&util.ListItem[common.RTPFrame]{Value: frame})
|
|
case t.APayloadType:
|
|
t.AudioTrack.WriteRTP(&util.ListItem[common.RTPFrame]{Value: frame})
|
|
default:
|
|
t.Stream.Warn("RTPDumpPublisher unknown payload type", zap.Uint8("payloadType", frame.PayloadType))
|
|
}
|
|
}
|