BIG core logic rewrite

This commit is contained in:
Alexey Khit
2023-03-17 06:48:02 +03:00
parent 2146ea470b
commit 12a7b96289
107 changed files with 3000 additions and 3024 deletions
+29 -23
View File
@@ -1,17 +1,19 @@
package mpegts
import (
"github.com/AlexxIT/go2rtc/pkg/streamer"
"github.com/AlexxIT/go2rtc/pkg/core"
"net/http"
)
type Client struct {
streamer.Element
core.Listener
medias []*streamer.Media
tracks map[byte]*streamer.Track
medias []*core.Media
receivers []*core.Receiver
res *http.Response
recv int
}
func NewClient(res *http.Response) *Client {
@@ -19,46 +21,50 @@ func NewClient(res *http.Response) *Client {
}
func (c *Client) Handle() error {
if c.tracks == nil {
c.tracks = map[byte]*streamer.Track{}
}
reader := NewReader()
b := make([]byte, 1024*1024*256) // 256K
probe := streamer.NewProbe(c.medias == nil)
probe := core.NewProbe(c.medias == nil)
for probe == nil || probe.Active() {
n, err := c.res.Body.Read(b)
if err != nil {
return err
}
c.recv += n
reader.AppendBuffer(b[:n])
reading:
for {
packet := reader.GetPacket()
if packet == nil {
break
}
track := c.tracks[packet.PayloadType]
if track == nil {
// count track on probe state even if not support it
probe.Append(packet.PayloadType)
media := GetMedia(packet)
if media == nil {
continue // unsupported codec
for _, receiver := range c.receivers {
if receiver.ID == packet.PayloadType {
receiver.WriteRTP(packet)
continue reading
}
track = streamer.NewTrack(media, nil)
c.medias = append(c.medias, media)
c.tracks[packet.PayloadType] = track
}
_ = track.WriteRTP(packet)
// count track on probe state even if not support it
probe.Append(packet.PayloadType)
media := GetMedia(packet)
if media == nil {
continue // unsupported codec
}
c.medias = append(c.medias, media)
receiver := core.NewReceiver(media, media.Codecs[0])
receiver.ID = packet.PayloadType
c.receivers = append(c.receivers, receiver)
receiver.WriteRTP(packet)
//log.Printf("[AVC] %v, len: %d, pts: %d ts: %10d", h264.Types(packet.Payload), len(packet.Payload), pkt.PTS, packet.Timestamp)
}
+14 -14
View File
@@ -1,8 +1,8 @@
package mpegts
import (
"github.com/AlexxIT/go2rtc/pkg/core"
"github.com/AlexxIT/go2rtc/pkg/h264"
"github.com/AlexxIT/go2rtc/pkg/streamer"
"github.com/pion/rtp"
"time"
)
@@ -13,7 +13,7 @@ const (
)
const (
StreamTypePrivate = 0x06 // PCMU or PCMA from FFmpeg
StreamTypePrivate = 0x06 // PCMU or PCMA or FLAC from FFmpeg
StreamTypeAAC = 0x0F
StreamTypeH264 = 0x1B
StreamTypePCMATapo = 0x90
@@ -153,34 +153,34 @@ func ParseTime(b []byte) uint32 {
return (uint32(b[0]&0x0E) << 29) | (uint32(b[1]) << 22) | (uint32(b[2]&0xFE) << 14) | (uint32(b[3]) << 7) | (uint32(b[4]) >> 1)
}
func GetMedia(pkt *rtp.Packet) *streamer.Media {
var codec *streamer.Codec
func GetMedia(pkt *rtp.Packet) *core.Media {
var codec *core.Codec
var kind string
switch pkt.PayloadType {
case StreamTypeH264:
codec = &streamer.Codec{
Name: streamer.CodecH264,
codec = &core.Codec{
Name: core.CodecH264,
ClockRate: 90000,
PayloadType: streamer.PayloadTypeRAW,
PayloadType: core.PayloadTypeRAW,
FmtpLine: h264.GetFmtpLine(pkt.Payload),
}
kind = streamer.KindVideo
kind = core.KindVideo
case StreamTypePCMATapo:
codec = &streamer.Codec{
Name: streamer.CodecPCMA,
codec = &core.Codec{
Name: core.CodecPCMA,
ClockRate: 8000,
}
kind = streamer.KindAudio
kind = core.KindAudio
default:
return nil
}
return &streamer.Media{
return &core.Media{
Kind: kind,
Direction: streamer.DirectionSendonly,
Codecs: []*streamer.Codec{codec},
Direction: core.DirectionRecvonly,
Codecs: []*core.Codec{codec},
}
}
+25 -25
View File
@@ -21,28 +21,28 @@ func dec(s string) []byte {
return b
}
func TestStream(t *testing.T) {
// ffmpeg
annexb := dec("00000001 09f0 00000001 6764001fac2484014016ec0440000003004000000c23c60c92 00000001 68ee32c8b0 000001 6588808003 00000001 09")
avc, i := ParseAVC(annexb)
assert.Equal(t, dec("00000019 6764001fac2484014016ec0440000003004000000c23c60c92 00000005 68ee32c8b0 00000005 6588808003"), avc)
assert.Equal(t, dec("00000001 09"), annexb[i:])
// http mpeg ts
annexb = dec("00000001 0950 000001 6764001facd2014016e8400000fa400030e081 000001 68ea8f2c 000001 65b8400eff 00000001 09")
avc, i = ParseAVC(annexb)
assert.Equal(t, dec("00000013 6764001facd2014016e8400000fa400030e081 00000004 68ea8f2c 00000005 65b8400eff"), avc)
assert.Equal(t, dec("00000001 09"), annexb[i:])
// tapo TC60
annexb = dec("00000001 67640028ac1ad00a00b74dc0404050000003001000000301e8f1422a 00000001 68ee04c92240 00000001 45b80000d0 00000001 67")
avc, i = ParseAVC(annexb)
assert.Equal(t, dec("0000001C 67640028ac1ad00a00b74dc0404050000003001000000301e8f1422a 00000006 68ee04c92240 00000005 45b80000d0"), avc)
assert.Equal(t, dec("00000001 67"), annexb[i:])
// Tapo ?
annexb = dec("00000001 674d0032e90048014742000007d2000138d108 00000001 68ea8f20 00000001 65b8400cff 00000001 67")
avc, i = ParseAVC(annexb)
assert.Equal(t, dec("00000013 674d0032e90048014742000007d2000138d108 00000004 68ea8f20 00000005 65b8400cff"), avc)
assert.Equal(t, dec("00000001 67"), annexb[i:])
}
//func TestStream(t *testing.T) {
// // ffmpeg
// annexb := dec("00000001 09f0 00000001 6764001fac2484014016ec0440000003004000000c23c60c92 00000001 68ee32c8b0 000001 6588808003 00000001 09")
// avc, i := ParseAVC(annexb)
// assert.Equal(t, dec("00000019 6764001fac2484014016ec0440000003004000000c23c60c92 00000005 68ee32c8b0 00000005 6588808003"), avc)
// assert.Equal(t, dec("00000001 09"), annexb[i:])
//
// // http mpeg ts
// annexb = dec("00000001 0950 000001 6764001facd2014016e8400000fa400030e081 000001 68ea8f2c 000001 65b8400eff 00000001 09")
// avc, i = ParseAVC(annexb)
// assert.Equal(t, dec("00000013 6764001facd2014016e8400000fa400030e081 00000004 68ea8f2c 00000005 65b8400eff"), avc)
// assert.Equal(t, dec("00000001 09"), annexb[i:])
//
// // tapo TC60
// annexb = dec("00000001 67640028ac1ad00a00b74dc0404050000003001000000301e8f1422a 00000001 68ee04c92240 00000001 45b80000d0 00000001 67")
// avc, i = ParseAVC(annexb)
// assert.Equal(t, dec("0000001C 67640028ac1ad00a00b74dc0404050000003001000000301e8f1422a 00000006 68ee04c92240 00000005 45b80000d0"), avc)
// assert.Equal(t, dec("00000001 67"), annexb[i:])
//
// // Tapo ?
// annexb = dec("00000001 674d0032e90048014742000007d2000138d108 00000001 68ea8f20 00000001 65b8400cff 00000001 67")
// avc, i = ParseAVC(annexb)
// assert.Equal(t, dec("00000013 674d0032e90048014742000007d2000138d108 00000004 68ea8f20 00000005 65b8400cff"), avc)
// assert.Equal(t, dec("00000001 67"), annexb[i:])
//}
+21 -6
View File
@@ -1,20 +1,21 @@
package mpegts
import (
"github.com/AlexxIT/go2rtc/pkg/streamer"
"encoding/json"
"github.com/AlexxIT/go2rtc/pkg/core"
)
func (c *Client) GetMedias() []*streamer.Media {
func (c *Client) GetMedias() []*core.Media {
return c.medias
}
func (c *Client) GetTrack(media *streamer.Media, codec *streamer.Codec) *streamer.Track {
for _, track := range c.tracks {
func (c *Client) GetTrack(media *core.Media, codec *core.Codec) (*core.Receiver, error) {
for _, track := range c.receivers {
if track.Codec == codec {
return track
return track, nil
}
}
return nil
return nil, core.ErrCantGetTrack
}
func (c *Client) Start() error {
@@ -22,5 +23,19 @@ func (c *Client) Start() error {
}
func (c *Client) Stop() error {
for _, receiver := range c.receivers {
receiver.Close()
}
return c.Close()
}
func (c *Client) MarshalJSON() ([]byte, error) {
info := &core.Info{
Type: "MPEG-TS active producer",
URL: c.res.Request.URL.String(),
Medias: c.medias,
Receivers: c.receivers,
Recv: c.recv,
}
return json.Marshal(info)
}
+70 -48
View File
@@ -3,24 +3,26 @@ package mpegts
import (
"bytes"
"encoding/hex"
"encoding/json"
"github.com/AlexxIT/go2rtc/pkg/aac"
"github.com/AlexxIT/go2rtc/pkg/core"
"github.com/AlexxIT/go2rtc/pkg/h264"
"github.com/AlexxIT/go2rtc/pkg/streamer"
"github.com/deepch/vdk/av"
"github.com/deepch/vdk/codec/aacparser"
"github.com/deepch/vdk/codec/h264parser"
"github.com/deepch/vdk/format/ts"
"github.com/pion/rtp"
"sync/atomic"
"time"
)
type Consumer struct {
streamer.Element
core.Listener
UserAgent string
RemoteAddr string
senders []*core.Sender
buf *bytes.Buffer
muxer *ts.Muxer
mimeType string
@@ -28,35 +30,36 @@ type Consumer struct {
start bool
init []byte
send uint32
send int
}
func (c *Consumer) GetMedias() []*streamer.Media {
return []*streamer.Media{
func (c *Consumer) GetMedias() []*core.Media {
return []*core.Media{
{
Kind: streamer.KindVideo,
Direction: streamer.DirectionRecvonly,
Codecs: []*streamer.Codec{
{Name: streamer.CodecH264},
Kind: core.KindVideo,
Direction: core.DirectionSendonly,
Codecs: []*core.Codec{
{Name: core.CodecH264},
},
},
//{
// Kind: streamer.KindAudio,
// Direction: streamer.DirectionRecvonly,
// Codecs: []*streamer.Codec{
// {Name: streamer.CodecAAC},
// Kind: core.KindAudio,
// Direction: core.DirectionSendonly,
// Codecs: []*core.Codec{
// {Name: core.CodecAAC},
// },
//},
}
}
func (c *Consumer) AddTrack(media *streamer.Media, track *streamer.Track) *streamer.Track {
codec := track.Codec
func (c *Consumer) AddTrack(media *core.Media, _ *core.Codec, track *core.Receiver) error {
trackID := int8(len(c.streams))
switch codec.Name {
case streamer.CodecH264:
sps, pps := h264.GetParameterSet(codec.FmtpLine)
handler := core.NewSender(media, track.Codec)
switch track.Codec.Name {
case core.CodecH264:
sps, pps := h264.GetParameterSet(track.Codec.FmtpLine)
stream, err := h264parser.NewCodecDataFromSPSAndPPS(sps, pps)
if err != nil {
return nil
@@ -66,21 +69,21 @@ func (c *Consumer) AddTrack(media *streamer.Media, track *streamer.Track) *strea
c.mimeType += ","
}
c.mimeType += "avc1." + h264.GetProfileLevelID(codec.FmtpLine)
c.mimeType += "avc1." + h264.GetProfileLevelID(track.Codec.FmtpLine)
c.streams = append(c.streams, stream)
pkt := av.Packet{Idx: trackID, CompositionTime: time.Millisecond}
ts2time := time.Second / time.Duration(codec.ClockRate)
ts2time := time.Second / time.Duration(track.Codec.ClockRate)
push := func(packet *rtp.Packet) error {
handler.Handler = func(packet *rtp.Packet) {
if packet.Version != h264.RTPPacketVersionAVC {
return nil
return
}
if !c.start {
return nil
return
}
pkt.Data = packet.Payload
@@ -91,28 +94,26 @@ func (c *Consumer) AddTrack(media *streamer.Media, track *streamer.Track) *strea
pkt.Time = newTime
if err = c.muxer.WritePacket(pkt); err != nil {
return err
return
}
// clone bytes from buffer, so next packet won't overwrite it
buf := append([]byte{}, c.buf.Bytes()...)
atomic.AddUint32(&c.send, uint32(len(buf)))
c.Fire(buf)
c.send += len(buf)
c.buf.Reset()
return nil
}
if codec.IsRTP() {
wrapper := h264.RTPDepay(track)
push = wrapper(push)
if track.Codec.IsRTP() {
handler.Handler = h264.RTPDepay(track.Codec, handler.Handler)
} else {
handler.Handler = h264.RepairAVC(track.Codec, handler.Handler)
}
return track.Bind(push)
case streamer.CodecAAC:
s := streamer.Between(codec.FmtpLine, "config=", ";")
case core.CodecAAC:
s := core.Between(track.Codec.FmtpLine, "config=", ";")
b, err := hex.DecodeString(s)
if err != nil {
@@ -133,11 +134,11 @@ func (c *Consumer) AddTrack(media *streamer.Media, track *streamer.Track) *strea
pkt := av.Packet{Idx: trackID, CompositionTime: time.Millisecond}
ts2time := time.Second / time.Duration(codec.ClockRate)
ts2time := time.Second / time.Duration(track.Codec.ClockRate)
push := func(packet *rtp.Packet) error {
handler.Handler = func(packet *rtp.Packet) {
if !c.start {
return nil
return
}
pkt.Data = packet.Payload
@@ -147,29 +148,31 @@ func (c *Consumer) AddTrack(media *streamer.Media, track *streamer.Track) *strea
}
pkt.Time = newTime
if err := c.muxer.WritePacket(pkt); err != nil {
return err
if err = c.muxer.WritePacket(pkt); err != nil {
return
}
// clone bytes from buffer, so next packet won't overwrite it
buf := append([]byte{}, c.buf.Bytes()...)
atomic.AddUint32(&c.send, uint32(len(buf)))
c.Fire(buf)
c.send += len(buf)
c.buf.Reset()
return nil
}
if codec.IsRTP() {
wrapper := aac.RTPDepay(track)
push = wrapper(push)
if track.Codec.IsRTP() {
handler.Handler = aac.RTPDepay(handler.Handler)
}
return track.Bind(push)
default:
panic("unsupported codec")
}
panic("unsupported codec")
handler.HandleRTP(track)
c.senders = append(c.senders, handler)
return nil
}
func (c *Consumer) MimeCodecs() string {
@@ -192,3 +195,22 @@ func (c *Consumer) Init() ([]byte, error) {
func (c *Consumer) Start() {
c.start = true
}
func (c *Consumer) Stop() error {
for _, sender := range c.senders {
sender.Close()
}
return nil
}
func (c *Consumer) MarshalJSON() ([]byte, error) {
info := &core.Info{
Type: "TS passive consumer",
RemoteAddr: c.RemoteAddr,
UserAgent: c.UserAgent,
Medias: c.GetMedias(),
Senders: c.senders,
Send: c.send,
}
return json.Marshal(info)
}