Add support http/mixed video/audio #545

This commit is contained in:
Alexey Khit
2023-08-02 17:57:33 +04:00
parent 2faea1bb69
commit 8778d7c9ab
5 changed files with 334 additions and 103 deletions
+14 -81
View File
@@ -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
View File
@@ -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,