mirror of
https://github.com/AlexxIT/go2rtc.git
synced 2025-09-26 20:31:11 +08:00
63 lines
1.5 KiB
Go
63 lines
1.5 KiB
Go
package tapo
|
|
|
|
import (
|
|
"bytes"
|
|
"strconv"
|
|
|
|
"github.com/AlexxIT/go2rtc/pkg/core"
|
|
"github.com/AlexxIT/go2rtc/pkg/mpegts"
|
|
"github.com/pion/rtp"
|
|
)
|
|
|
|
func (c *Client) AddTrack(media *core.Media, _ *core.Codec, track *core.Receiver) error {
|
|
if c.sender == nil {
|
|
if err := c.SetupBackchannel(); err != nil {
|
|
return err
|
|
}
|
|
|
|
muxer := mpegts.NewMuxer()
|
|
pid := muxer.AddTrack(mpegts.StreamTypePCMATapo)
|
|
if err := c.WriteBackchannel(muxer.GetHeader()); err != nil {
|
|
return err
|
|
}
|
|
|
|
c.sender = core.NewSender(media, track.Codec)
|
|
c.sender.Handler = func(packet *rtp.Packet) {
|
|
b := muxer.GetPayload(pid, packet.Timestamp, packet.Payload)
|
|
_ = c.WriteBackchannel(b)
|
|
}
|
|
}
|
|
|
|
c.sender.HandleRTP(track)
|
|
return nil
|
|
}
|
|
|
|
func (c *Client) SetupBackchannel() (err error) {
|
|
// if conn1 is not used - we will use it for backchannel
|
|
// or we need to start another conn for session2
|
|
if c.session1 != "" {
|
|
if c.conn2, err = c.newConn(); err != nil {
|
|
return
|
|
}
|
|
} else {
|
|
c.conn2 = c.conn1
|
|
}
|
|
|
|
c.session2, err = c.Request(c.conn2, []byte(`{"params":{"talk":{"mode":"aec"},"method":"get"},"seq":3,"type":"request"}`))
|
|
return
|
|
}
|
|
|
|
func (c *Client) WriteBackchannel(body []byte) (err error) {
|
|
// TODO: fixme (size)
|
|
buf := bytes.NewBuffer(nil)
|
|
buf.WriteString("----client-stream-boundary--\r\n")
|
|
buf.WriteString("Content-Type: audio/mp2t\r\n")
|
|
buf.WriteString("X-If-Encrypt: 0\r\n")
|
|
buf.WriteString("X-Session-Id: " + c.session2 + "\r\n")
|
|
buf.WriteString("Content-Length: " + strconv.Itoa(len(body)) + "\r\n\r\n")
|
|
buf.Write(body)
|
|
|
|
_, err = buf.WriteTo(c.conn2)
|
|
return
|
|
}
|