Add support TP-Link Kasa Spot KC401 #545
This commit is contained in:
+2
-3
@@ -1,8 +1,7 @@
|
|||||||
|
|
||||||
.idea/
|
.idea/
|
||||||
|
|
||||||
.tmp/
|
.tmp/
|
||||||
|
|
||||||
go2rtc.yaml
|
go2rtc.yaml
|
||||||
|
|
||||||
go2rtc.json
|
go2rtc.json
|
||||||
|
|
||||||
|
0_test.go
|
||||||
|
|||||||
+25
-3
@@ -2,8 +2,10 @@ package http
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/http/httputil"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -33,12 +35,17 @@ func handleHTTP(rawURL string) (core.Producer, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var chunked bool
|
||||||
|
|
||||||
if rawQuery != "" {
|
if rawQuery != "" {
|
||||||
query := streams.ParseQuery(rawQuery)
|
query := streams.ParseQuery(rawQuery)
|
||||||
|
|
||||||
for _, header := range query["header"] {
|
for _, header := range query["header"] {
|
||||||
key, value, _ := strings.Cut(header, ":")
|
key, value, _ := strings.Cut(header, ":")
|
||||||
req.Header.Add(key, strings.TrimSpace(value))
|
req.Header.Add(key, strings.TrimSpace(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chunked = query.Get("chunked") == "1"
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := tcp.Do(req)
|
res, err := tcp.Do(req)
|
||||||
@@ -61,18 +68,33 @@ func handleHTTP(rawURL string) (core.Producer, error) {
|
|||||||
ext = req.URL.Path[i+1:]
|
ext = req.URL.Path[i+1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var rd io.ReadCloser
|
||||||
|
|
||||||
|
// support buggy clients, like TP-Link cameras with HTTP/1.0 chunked encoding
|
||||||
|
if chunked {
|
||||||
|
rd = struct {
|
||||||
|
io.Reader
|
||||||
|
io.Closer
|
||||||
|
}{
|
||||||
|
httputil.NewChunkedReader(res.Body),
|
||||||
|
res.Body,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rd = res.Body
|
||||||
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case ct == "image/jpeg":
|
case ct == "image/jpeg":
|
||||||
return mjpeg.NewClient(res), nil
|
return mjpeg.NewClient(res), nil
|
||||||
|
|
||||||
case ct == "multipart/x-mixed-replace":
|
case ct == "multipart/x-mixed-replace":
|
||||||
return multipart.Open(res.Body)
|
return multipart.Open(rd)
|
||||||
|
|
||||||
case ct == "application/vnd.apple.mpegurl" || ext == "m3u8":
|
case ct == "application/vnd.apple.mpegurl" || ext == "m3u8":
|
||||||
return hls.OpenURL(req.URL, res.Body)
|
return hls.OpenURL(req.URL, rd)
|
||||||
}
|
}
|
||||||
|
|
||||||
return magic.Open(res.Body)
|
return magic.Open(rd)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleTCP(rawURL string) (core.Producer, error) {
|
func handleTCP(rawURL string) (core.Producer, error) {
|
||||||
|
|||||||
+19
-21
@@ -11,6 +11,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/AlexxIT/go2rtc/pkg/core"
|
"github.com/AlexxIT/go2rtc/pkg/core"
|
||||||
|
"github.com/AlexxIT/go2rtc/pkg/h264"
|
||||||
"github.com/AlexxIT/go2rtc/pkg/h264/annexb"
|
"github.com/AlexxIT/go2rtc/pkg/h264/annexb"
|
||||||
"github.com/pion/rtp"
|
"github.com/pion/rtp"
|
||||||
)
|
)
|
||||||
@@ -166,11 +167,11 @@ func (c *Producer) probe() error {
|
|||||||
c.reader = bufio.NewReader(c.rd)
|
c.reader = bufio.NewReader(c.rd)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
waitVideo := true
|
waitVideo, waitAudio := true, true
|
||||||
waitAudio := true
|
timeout := time.Now().Add(core.ProbeTimeout)
|
||||||
|
|
||||||
for waitVideo || waitAudio {
|
for (waitVideo || waitAudio) && time.Now().Before(timeout) {
|
||||||
header, _, err := c.next()
|
header, body, err := c.next()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -181,26 +182,23 @@ func (c *Producer) probe() error {
|
|||||||
switch ct {
|
switch ct {
|
||||||
case MimeVideo:
|
case MimeVideo:
|
||||||
if !waitVideo {
|
if !waitVideo {
|
||||||
return nil
|
continue
|
||||||
}
|
|
||||||
|
|
||||||
media = &core.Media{
|
|
||||||
Kind: core.KindVideo,
|
|
||||||
Direction: core.DirectionRecvonly,
|
|
||||||
Codecs: []*core.Codec{
|
|
||||||
{
|
|
||||||
Name: core.CodecH264,
|
|
||||||
ClockRate: 90000,
|
|
||||||
PayloadType: core.PayloadTypeRAW,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
waitVideo = false
|
waitVideo = false
|
||||||
|
|
||||||
|
body = annexb.EncodeToAVCC(body, false)
|
||||||
|
codec := h264.AVCCToCodec(body)
|
||||||
|
media = &core.Media{
|
||||||
|
Kind: core.KindVideo,
|
||||||
|
Direction: core.DirectionRecvonly,
|
||||||
|
Codecs: []*core.Codec{codec},
|
||||||
|
}
|
||||||
|
|
||||||
case MimeG711U:
|
case MimeG711U:
|
||||||
if !waitAudio {
|
if !waitAudio {
|
||||||
return nil
|
continue
|
||||||
}
|
}
|
||||||
|
waitAudio = false
|
||||||
|
|
||||||
media = &core.Media{
|
media = &core.Media{
|
||||||
Kind: core.KindAudio,
|
Kind: core.KindAudio,
|
||||||
@@ -212,9 +210,11 @@ func (c *Producer) probe() error {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
waitAudio = false
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
waitVideo = false
|
||||||
|
waitAudio = false
|
||||||
|
|
||||||
media = &core.Media{
|
media = &core.Media{
|
||||||
Kind: core.KindVideo,
|
Kind: core.KindVideo,
|
||||||
Direction: core.DirectionRecvonly,
|
Direction: core.DirectionRecvonly,
|
||||||
@@ -226,8 +226,6 @@ func (c *Producer) probe() error {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
waitVideo = false
|
|
||||||
waitAudio = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Medias = append(c.Medias, media)
|
c.Medias = append(c.Medias, media)
|
||||||
|
|||||||
Reference in New Issue
Block a user