mirror of
https://github.com/langhuihui/monibuca.git
synced 2025-10-28 07:32:09 +08:00
127 lines
2.8 KiB
Go
127 lines
2.8 KiB
Go
package plugin_gb28181pro
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/emiago/sipgo"
|
|
m7s "m7s.live/v5"
|
|
"m7s.live/v5/pkg/task"
|
|
"m7s.live/v5/pkg/util"
|
|
gb28181 "m7s.live/v5/plugin/gb28181pro/pkg"
|
|
)
|
|
|
|
type Dialog struct {
|
|
task.Job
|
|
Channel *Channel
|
|
gb28181.InviteOptions
|
|
gb *GB28181ProPlugin
|
|
session *sipgo.DialogClientSession
|
|
pullCtx m7s.PullJob
|
|
}
|
|
|
|
func (d *Dialog) GetCallID() string {
|
|
return d.session.InviteRequest.CallID().Value()
|
|
}
|
|
|
|
func (d *Dialog) GetPullJob() *m7s.PullJob {
|
|
return &d.pullCtx
|
|
}
|
|
|
|
func (d *Dialog) Start() (err error) {
|
|
if !d.IsLive() {
|
|
d.pullCtx.PublishConfig.PubType = m7s.PublishTypeVod
|
|
}
|
|
err = d.pullCtx.Publish()
|
|
if err != nil {
|
|
return
|
|
}
|
|
sss := strings.Split(d.pullCtx.RemoteURL, "/")
|
|
deviceId, channelId := sss[0], sss[1]
|
|
if len(sss) == 2 {
|
|
if device, ok := d.gb.devices.Get(deviceId); ok {
|
|
if channel, ok := device.channels.Get(channelId); ok {
|
|
d.Channel = channel
|
|
} else {
|
|
return fmt.Errorf("channel %s not found", channelId)
|
|
}
|
|
} else {
|
|
return fmt.Errorf("device %s not found", deviceId)
|
|
}
|
|
} else if len(sss) == 3 {
|
|
var recordRange util.Range[int]
|
|
err = recordRange.Resolve(sss[2])
|
|
}
|
|
|
|
d.gb.dialogs.Set(d)
|
|
defer d.gb.dialogs.Remove(d)
|
|
if d.gb.MediaPort.Valid() {
|
|
select {
|
|
case d.MediaPort = <-d.gb.tcpPorts:
|
|
defer func() {
|
|
d.gb.tcpPorts <- d.MediaPort
|
|
}()
|
|
default:
|
|
return fmt.Errorf("no available tcp port")
|
|
}
|
|
} else {
|
|
d.MediaPort = d.gb.MediaPort[0]
|
|
}
|
|
|
|
// 调用 PlayStreamCmd
|
|
d.session, err = d.gb.PlayStreamCmd(d.Channel.Device, d.Channel, d.MediaPort)
|
|
if err != nil {
|
|
return fmt.Errorf("play stream failed: %v", err)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (d *Dialog) Run() (err error) {
|
|
d.Channel.Info("before WaitAnswer")
|
|
err = d.session.WaitAnswer(d.gb, sipgo.AnswerOptions{})
|
|
d.Channel.Info("after WaitAnswer")
|
|
if err != nil {
|
|
return
|
|
}
|
|
inviteResponseBody := string(d.session.InviteResponse.Body())
|
|
d.Channel.Info("inviteResponse", "body", inviteResponseBody)
|
|
ds := strings.Split(inviteResponseBody, "\r\n")
|
|
for _, l := range ds {
|
|
if ls := strings.Split(l, "="); len(ls) > 1 {
|
|
if ls[0] == "y" && len(ls[1]) > 0 {
|
|
if _ssrc, err := strconv.ParseInt(ls[1], 10, 0); err == nil {
|
|
d.SSRC = uint32(_ssrc)
|
|
} else {
|
|
d.gb.Error("read invite response y ", "err", err)
|
|
}
|
|
// break
|
|
}
|
|
if ls[0] == "m" && len(ls[1]) > 0 {
|
|
netinfo := strings.Split(ls[1], " ")
|
|
if strings.ToUpper(netinfo[2]) == "TCP/RTP/AVP" {
|
|
d.gb.Debug("device support tcp")
|
|
} else {
|
|
return fmt.Errorf("device not support tcp")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
err = d.session.Ack(d.gb)
|
|
pub := gb28181.NewPSPublisher(d.pullCtx.Publisher)
|
|
pub.Receiver.ListenAddr = fmt.Sprintf(":%d", d.MediaPort)
|
|
pub.Receiver.ListenPort = d.MediaPort
|
|
d.AddTask(&pub.Receiver)
|
|
pub.Demux()
|
|
return
|
|
}
|
|
|
|
func (d *Dialog) GetKey() uint32 {
|
|
return d.SSRC
|
|
}
|
|
|
|
func (d *Dialog) Dispose() {
|
|
d.session.Close()
|
|
}
|