mirror of
https://github.com/Monibuca/plugin-rtsp2.git
synced 2025-09-27 12:02:08 +08:00
180 lines
3.9 KiB
Go
180 lines
3.9 KiB
Go
package rtsp2
|
|
|
|
import (
|
|
"github.com/AlexxIT/go2rtc/pkg/core"
|
|
"github.com/AlexxIT/go2rtc/pkg/rtsp"
|
|
"go.uber.org/zap"
|
|
"m7s.live/engine/v4"
|
|
"m7s.live/engine/v4/codec"
|
|
"m7s.live/engine/v4/track"
|
|
)
|
|
|
|
type RTSPClient struct {
|
|
*rtsp.Conn `json:"-" yaml:"-"`
|
|
// DialContext func(ctx context.Context, network, address string) (net.Conn, error) `json:"-" yaml:"-"`
|
|
}
|
|
|
|
type RTSPPuller struct {
|
|
engine.Publisher
|
|
engine.Puller
|
|
RTSPClient
|
|
}
|
|
|
|
func (p *RTSPClient) Disconnect() {
|
|
if p.Conn != nil {
|
|
p.Conn.Close()
|
|
}
|
|
}
|
|
|
|
func (p *RTSPPuller) Connect() (err error) {
|
|
p.Conn = rtsp.NewClient(p.RemoteURL)
|
|
p.SetIO(p.Conn)
|
|
return p.Conn.Dial()
|
|
}
|
|
|
|
func (p *RTSPPuller) Pull() (err error) {
|
|
if err = p.Options(); err != nil {
|
|
return
|
|
}
|
|
if err = p.Describe(); err != nil {
|
|
return
|
|
}
|
|
p.setTracks()
|
|
return p.Start()
|
|
}
|
|
|
|
func (p *RTSPPuller) setTracks() {
|
|
for _, m := range p.Conn.Medias {
|
|
for _, c := range m.Codecs {
|
|
sender := core.NewSender(m, c)
|
|
rec, err := p.Conn.GetTrack(m, c)
|
|
if err != nil {
|
|
p.Error("get track", zap.Error(err))
|
|
continue
|
|
}
|
|
switch c.Name {
|
|
case core.CodecH264:
|
|
p.VideoTrack = track.NewH264(p.Stream, c.PayloadType)
|
|
sender.Handler = p.VideoTrack.WriteRTPPack
|
|
case core.CodecH265:
|
|
p.VideoTrack = track.NewH265(p.Stream, c.PayloadType)
|
|
sender.Handler = p.VideoTrack.WriteRTPPack
|
|
case core.CodecAAC:
|
|
p.AudioTrack = track.NewAAC(p.Stream, c.PayloadType)
|
|
sender.Handler = p.AudioTrack.WriteRTPPack
|
|
case core.CodecPCMA:
|
|
p.AudioTrack = track.NewG711(p.Stream, true, c.PayloadType)
|
|
sender.Handler = p.AudioTrack.WriteRTPPack
|
|
case core.CodecPCMU:
|
|
p.AudioTrack = track.NewG711(p.Stream, false, c.PayloadType)
|
|
sender.Handler = p.AudioTrack.WriteRTPPack
|
|
}
|
|
sender.HandleRTP(rec)
|
|
}
|
|
}
|
|
}
|
|
|
|
type RTSPPusher struct {
|
|
engine.Subscriber
|
|
engine.Pusher
|
|
RTSPClient
|
|
videoSender *core.Receiver
|
|
audioSender *core.Receiver
|
|
}
|
|
|
|
func (p *RTSPPusher) OnEvent(event any) {
|
|
switch v := event.(type) {
|
|
case *track.Audio:
|
|
if p.audioSender != nil {
|
|
break
|
|
}
|
|
var c *core.Codec
|
|
var media *core.Media
|
|
switch v.CodecID {
|
|
case codec.CodecID_AAC:
|
|
c = &core.Codec{
|
|
Name: core.CodecAAC,
|
|
ClockRate: v.SampleRate,
|
|
Channels: uint16(v.Channels),
|
|
PayloadType: v.PayloadType,
|
|
}
|
|
case codec.CodecID_PCMA:
|
|
c = &core.Codec{
|
|
Name: core.CodecPCMA,
|
|
ClockRate: v.SampleRate,
|
|
Channels: uint16(v.Channels),
|
|
PayloadType: v.PayloadType,
|
|
}
|
|
case codec.CodecID_PCMU:
|
|
c = &core.Codec{
|
|
Name: core.CodecPCMU,
|
|
ClockRate: v.SampleRate,
|
|
Channels: uint16(v.Channels),
|
|
PayloadType: v.PayloadType,
|
|
}
|
|
}
|
|
media = &core.Media{
|
|
Kind: "audio",
|
|
Direction: "sendonly",
|
|
Codecs: []*core.Codec{c},
|
|
}
|
|
if p.videoSender == nil {
|
|
media.ID = "0"
|
|
} else {
|
|
media.ID = "1"
|
|
}
|
|
p.audioSender = core.NewReceiver(media, c)
|
|
p.Conn.AddTrack(media, c, p.audioSender)
|
|
p.AddTrack(v)
|
|
case *track.Video:
|
|
if p.videoSender != nil {
|
|
break
|
|
}
|
|
var c *core.Codec
|
|
var media *core.Media
|
|
switch v.CodecID {
|
|
case codec.CodecID_H264:
|
|
c = &core.Codec{
|
|
Name: core.CodecH264,
|
|
ClockRate: v.SampleRate,
|
|
PayloadType: v.PayloadType,
|
|
}
|
|
case codec.CodecID_H265:
|
|
c = &core.Codec{
|
|
Name: core.CodecH265,
|
|
ClockRate: v.SampleRate,
|
|
PayloadType: v.PayloadType,
|
|
}
|
|
}
|
|
media = &core.Media{
|
|
Kind: "video",
|
|
Direction: "sendonly",
|
|
Codecs: []*core.Codec{c},
|
|
}
|
|
if p.audioSender == nil {
|
|
media.ID = "0"
|
|
} else {
|
|
media.ID = "1"
|
|
}
|
|
p.videoSender = core.NewReceiver(media, c)
|
|
p.Conn.AddTrack(media, c, p.videoSender)
|
|
p.AddTrack(v)
|
|
case engine.VideoRTP:
|
|
p.videoSender.WriteRTP(v.Packet)
|
|
case engine.AudioRTP:
|
|
p.audioSender.WriteRTP(v.Packet)
|
|
default:
|
|
p.Subscriber.OnEvent(event)
|
|
}
|
|
}
|
|
|
|
func (p *RTSPPusher) Connect() (err error) {
|
|
p.Conn = rtsp.NewClient(p.RemoteURL)
|
|
p.SetIO(p.Conn)
|
|
return p.Conn.Dial()
|
|
}
|
|
|
|
func (p *RTSPPuller) Push() (err error) {
|
|
return p.Announce()
|
|
}
|