Files
monibuca/plugin/srt/pkg/receiver.go
2024-11-12 10:19:55 +08:00

120 lines
2.7 KiB
Go

package srt
import (
"bytes"
"time"
srt "github.com/datarhei/gosrt"
"m7s.live/v5"
"m7s.live/v5/pkg"
"m7s.live/v5/pkg/codec"
"m7s.live/v5/pkg/task"
mpegts "m7s.live/v5/plugin/hls/pkg/ts"
)
type Receiver struct {
task.Task
Publisher *m7s.Publisher
TSStream mpegts.MpegTsStream
srt.Conn
}
func (r *Receiver) Start() error {
r.TSStream.PESChan = make(chan *mpegts.MpegTsPESPacket, 50)
r.TSStream.PESBuffer = make(map[uint16]*mpegts.MpegTsPESPacket)
go r.readPES()
return nil
}
func (r *Receiver) readPES() {
var videoFrame *pkg.AnnexB
var err error
defer func() {
if err != nil {
r.Stop(err)
}
}()
for pes := range r.TSStream.PESChan {
if r.Err() != nil {
continue
}
if pes.Header.Dts == 0 {
pes.Header.Dts = pes.Header.Pts
}
switch pes.Header.StreamID & 0xF0 {
case mpegts.STREAM_ID_VIDEO:
if videoFrame == nil {
videoFrame = &pkg.AnnexB{
PTS: time.Duration(pes.Header.Pts),
DTS: time.Duration(pes.Header.Dts),
}
for _, s := range r.TSStream.PMT.Stream {
switch s.StreamType {
case mpegts.STREAM_TYPE_H265:
videoFrame.Hevc = true
}
}
} else {
if videoFrame.PTS != time.Duration(pes.Header.Pts) {
if r.Publisher.PubVideo {
err = r.Publisher.WriteVideo(videoFrame)
if err != nil {
return
}
}
videoFrame = &pkg.AnnexB{
PTS: time.Duration(pes.Header.Pts),
DTS: time.Duration(pes.Header.Dts),
Hevc: videoFrame.Hevc,
}
}
}
copy(videoFrame.NextN(len(pes.Payload)), pes.Payload)
default:
var frame pkg.IAVFrame
for _, s := range r.TSStream.PMT.Stream {
switch s.StreamType {
case mpegts.STREAM_TYPE_AAC:
var audioFrame pkg.ADTS
audioFrame.DTS = time.Duration(pes.Header.Dts)
copy(audioFrame.NextN(len(pes.Payload)), pes.Payload)
frame = &audioFrame
case mpegts.STREAM_TYPE_G711A:
var audioFrame pkg.RawAudio
audioFrame.FourCC = codec.FourCC_ALAW
audioFrame.Timestamp = time.Duration(pes.Header.Dts)
copy(audioFrame.NextN(len(pes.Payload)), pes.Payload)
frame = &audioFrame
case mpegts.STREAM_TYPE_G711U:
var audioFrame pkg.RawAudio
audioFrame.FourCC = codec.FourCC_ULAW
audioFrame.Timestamp = time.Duration(pes.Header.Dts)
copy(audioFrame.NextN(len(pes.Payload)), pes.Payload)
frame = &audioFrame
}
}
if frame != nil && r.Publisher.PubAudio {
if err = r.Publisher.WriteAudio(frame); err != nil {
return
}
}
}
}
}
func (r *Receiver) Go() error {
for !r.IsStopped() {
packet, err := r.ReadPacket()
if err != nil {
return err
}
r.TSStream.Feed(bytes.NewReader(packet.Data()))
}
return r.StopReason()
}
func (r *Receiver) Dispose() {
r.Close()
close(r.TSStream.PESChan)
}