Add support http/mixed video/audio #545
This commit is contained in:
+14
-81
@@ -1,14 +1,9 @@
|
||||
package mjpeg
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/textproto"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/AlexxIT/go2rtc/pkg/core"
|
||||
"github.com/AlexxIT/go2rtc/pkg/tcp"
|
||||
@@ -34,16 +29,19 @@ func NewClient(res *http.Response) *Client {
|
||||
return &Client{res: res}
|
||||
}
|
||||
|
||||
func (c *Client) startJPEG() error {
|
||||
buf, err := io.ReadAll(c.res.Body)
|
||||
func (c *Client) Handle() error {
|
||||
body, err := io.ReadAll(c.res.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
packet := &rtp.Packet{Header: rtp.Header{Timestamp: now()}, Payload: buf}
|
||||
c.receiver.WriteRTP(packet)
|
||||
pkt := &rtp.Packet{
|
||||
Header: rtp.Header{Timestamp: core.Now90000()},
|
||||
Payload: body,
|
||||
}
|
||||
c.receiver.WriteRTP(pkt)
|
||||
|
||||
c.recv += len(buf)
|
||||
c.recv += len(body)
|
||||
|
||||
req := c.res.Request
|
||||
|
||||
@@ -57,86 +55,21 @@ func (c *Client) startJPEG() error {
|
||||
return errors.New("wrong status: " + res.Status)
|
||||
}
|
||||
|
||||
buf, err = io.ReadAll(res.Body)
|
||||
body, err = io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.recv += len(body)
|
||||
|
||||
if c.receiver != nil {
|
||||
packet = &rtp.Packet{Header: rtp.Header{Timestamp: now()}, Payload: buf}
|
||||
c.receiver.WriteRTP(packet)
|
||||
}
|
||||
|
||||
c.recv += len(buf)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) startMJPEG(boundary string) error {
|
||||
// some cameras add prefix to boundary header:
|
||||
// https://github.com/TheTimeWalker/wallpanel-android
|
||||
if !strings.HasPrefix(boundary, "--") {
|
||||
boundary = "--" + boundary
|
||||
}
|
||||
|
||||
r := bufio.NewReader(c.res.Body)
|
||||
tp := textproto.NewReader(r)
|
||||
|
||||
for !c.closed {
|
||||
s, err := tp.ReadLine()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// fix leading empty line from esp32-cam-webserver
|
||||
// https://github.com/AlexxIT/go2rtc/issues/545
|
||||
if s == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(s, boundary) {
|
||||
return errors.New("wrong boundary: " + s)
|
||||
}
|
||||
|
||||
header, err := tp.ReadMIMEHeader()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s = header.Get("Content-Length")
|
||||
if s == "" {
|
||||
return errors.New("no content length")
|
||||
}
|
||||
|
||||
size, err := strconv.Atoi(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
buf := make([]byte, size)
|
||||
if _, err = io.ReadFull(r, buf); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.receiver != nil {
|
||||
packet := &rtp.Packet{
|
||||
pkt = &rtp.Packet{
|
||||
Header: rtp.Header{Timestamp: core.Now90000()},
|
||||
Payload: buf,
|
||||
Payload: body,
|
||||
}
|
||||
c.receiver.WriteRTP(packet)
|
||||
}
|
||||
|
||||
c.recv += len(buf)
|
||||
|
||||
if _, err = r.Discard(2); err != nil {
|
||||
return err
|
||||
c.receiver.WriteRTP(pkt)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func now() uint32 {
|
||||
return uint32(time.Now().UnixMilli() * 90)
|
||||
}
|
||||
|
||||
+2
-15
@@ -2,8 +2,6 @@ package mjpeg
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/AlexxIT/go2rtc/pkg/core"
|
||||
)
|
||||
@@ -33,19 +31,8 @@ func (c *Client) GetTrack(media *core.Media, codec *core.Codec) (*core.Receiver,
|
||||
}
|
||||
|
||||
func (c *Client) Start() error {
|
||||
ct := c.res.Header.Get("Content-Type")
|
||||
|
||||
// https://github.com/AlexxIT/go2rtc/issues/278
|
||||
if strings.HasPrefix(ct, "image/jpeg") {
|
||||
return c.startJPEG()
|
||||
}
|
||||
|
||||
// added in go1.18
|
||||
if _, s, ok := strings.Cut(ct, "boundary="); ok {
|
||||
return c.startMJPEG(s)
|
||||
}
|
||||
|
||||
return errors.New("wrong Content-Type: " + ct)
|
||||
return c.Handle()
|
||||
}
|
||||
|
||||
func (c *Client) Stop() error {
|
||||
@@ -60,7 +47,7 @@ func (c *Client) Stop() error {
|
||||
|
||||
func (c *Client) MarshalJSON() ([]byte, error) {
|
||||
info := &core.Info{
|
||||
Type: "MJPEG active producer",
|
||||
Type: "JPEG active producer",
|
||||
URL: c.res.Request.URL.String(),
|
||||
RemoteAddr: c.RemoteAddr,
|
||||
UserAgent: c.UserAgent,
|
||||
|
||||
Reference in New Issue
Block a user