mirror of
https://github.com/Monibuca/engine.git
synced 2025-10-05 08:36:56 +08:00
103 lines
2.5 KiB
Go
103 lines
2.5 KiB
Go
package engine
|
|
|
|
import (
|
|
"io"
|
|
|
|
"go.uber.org/zap"
|
|
"m7s.live/engine/v4/codec/mpegts"
|
|
"m7s.live/engine/v4/track"
|
|
)
|
|
|
|
type TSPublisher struct {
|
|
Publisher
|
|
*mpegts.MpegTsStream
|
|
adts []byte
|
|
}
|
|
|
|
func (t *TSPublisher) Feed(r io.Reader) error {
|
|
return t.MpegTsStream.Feed(r, t.OnPmtStream, t.OnPES)
|
|
}
|
|
|
|
func (t *TSPublisher) OnEvent(event any) {
|
|
switch v := event.(type) {
|
|
case IPublisher:
|
|
t.MpegTsStream = mpegts.NewMpegTsStream()
|
|
if !t.Equal(v) {
|
|
t.AudioTrack = v.getAudioTrack()
|
|
t.VideoTrack = v.getVideoTrack()
|
|
}
|
|
default:
|
|
t.Publisher.OnEvent(event)
|
|
}
|
|
}
|
|
|
|
func (t *TSPublisher) OnPmtStream(s mpegts.MpegTsPmtStream) {
|
|
switch s.StreamType {
|
|
case mpegts.STREAM_TYPE_H264:
|
|
if t.VideoTrack == nil {
|
|
t.VideoTrack = track.NewH264(t.Publisher.Stream)
|
|
}
|
|
case mpegts.STREAM_TYPE_H265:
|
|
if t.VideoTrack == nil {
|
|
t.VideoTrack = track.NewH265(t.Publisher.Stream)
|
|
}
|
|
case mpegts.STREAM_TYPE_AAC:
|
|
if t.AudioTrack == nil {
|
|
t.AudioTrack = track.NewAAC(t.Publisher.Stream)
|
|
}
|
|
case mpegts.STREAM_TYPE_G711A:
|
|
if t.AudioTrack == nil {
|
|
t.AudioTrack = track.NewG711(t.Publisher.Stream, true)
|
|
}
|
|
case mpegts.STREAM_TYPE_G711U:
|
|
if t.AudioTrack == nil {
|
|
t.AudioTrack = track.NewG711(t.Publisher.Stream, false)
|
|
}
|
|
default:
|
|
t.Warn("unsupport stream type:", zap.Uint8("type", s.StreamType))
|
|
}
|
|
}
|
|
|
|
func (t *TSPublisher) OnPES(pes mpegts.MpegTsPESPacket) {
|
|
if pes.Header.Dts == 0 {
|
|
pes.Header.Dts = pes.Header.Pts
|
|
}
|
|
switch pes.Header.StreamID & 0xF0 {
|
|
case mpegts.STREAM_ID_AUDIO:
|
|
if t.AudioTrack != nil {
|
|
switch t.AudioTrack.(type) {
|
|
case *track.AAC:
|
|
if t.adts == nil {
|
|
t.adts = append(t.adts, pes.Payload[:7]...)
|
|
t.AudioTrack.WriteADTS(t.adts)
|
|
}
|
|
current := t.AudioTrack.CurrentFrame()
|
|
current.PTS = uint32(pes.Header.Pts)
|
|
current.DTS = uint32(pes.Header.Dts)
|
|
remainLen := len(pes.Payload)
|
|
current.BytesIn += remainLen
|
|
for remainLen > 0 {
|
|
// AACFrameLength(13)
|
|
// xx xxxxxxxx xxx
|
|
frameLen := (int(pes.Payload[3]&3) << 11) | (int(pes.Payload[4]) << 3) | (int(pes.Payload[5]) >> 5)
|
|
if frameLen > remainLen {
|
|
break
|
|
}
|
|
|
|
t.AudioTrack.WriteSlice(pes.Payload[7:frameLen])
|
|
pes.Payload = pes.Payload[frameLen:remainLen]
|
|
remainLen -= frameLen
|
|
}
|
|
t.AudioTrack.Flush()
|
|
case *track.G711:
|
|
t.AudioTrack.WriteRaw(uint32(pes.Header.Pts), pes.Payload)
|
|
}
|
|
|
|
}
|
|
case mpegts.STREAM_ID_VIDEO:
|
|
if t.VideoTrack != nil {
|
|
t.VideoTrack.WriteAnnexB(uint32(pes.Header.Pts), uint32(pes.Header.Dts), pes.Payload)
|
|
}
|
|
}
|
|
}
|