diff --git a/internal/mpegts/aac.go b/internal/mpegts/aac.go new file mode 100644 index 00000000..3008a658 --- /dev/null +++ b/internal/mpegts/aac.go @@ -0,0 +1,36 @@ +package mpegts + +import ( + "net/http" + + "github.com/AlexxIT/go2rtc/internal/api" + "github.com/AlexxIT/go2rtc/internal/streams" + "github.com/AlexxIT/go2rtc/pkg/aac" + "github.com/AlexxIT/go2rtc/pkg/tcp" + "github.com/rs/zerolog/log" +) + +func apiStreamAAC(w http.ResponseWriter, r *http.Request) { + src := r.URL.Query().Get("src") + stream := streams.Get(src) + if stream == nil { + http.Error(w, api.StreamNotFound, http.StatusNotFound) + return + } + + cons := aac.NewConsumer() + cons.RemoteAddr = tcp.RemoteAddr(r) + cons.UserAgent = r.UserAgent() + + if err := stream.AddConsumer(cons); err != nil { + log.Error().Err(err).Caller().Send() + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + w.Header().Add("Content-Type", "audio/aac") + + _, _ = cons.WriteTo(w) + + stream.RemoveConsumer(cons) +} diff --git a/internal/mpegts/mpegts.go b/internal/mpegts/mpegts.go index b435e021..4d082c27 100644 --- a/internal/mpegts/mpegts.go +++ b/internal/mpegts/mpegts.go @@ -12,6 +12,7 @@ import ( func Init() { api.HandleFunc("api/stream.ts", apiHandle) + api.HandleFunc("api/stream.aac", apiStreamAAC) } func apiHandle(w http.ResponseWriter, r *http.Request) { diff --git a/pkg/aac/consumer.go b/pkg/aac/consumer.go new file mode 100644 index 00000000..e785adc5 --- /dev/null +++ b/pkg/aac/consumer.go @@ -0,0 +1,58 @@ +package aac + +import ( + "io" + + "github.com/AlexxIT/go2rtc/pkg/core" + "github.com/pion/rtp" +) + +type Consumer struct { + core.SuperConsumer + wr *core.WriteBuffer +} + +func NewConsumer() *Consumer { + cons := &Consumer{ + wr: core.NewWriteBuffer(nil), + } + cons.Medias = []*core.Media{ + { + Kind: core.KindAudio, + Direction: core.DirectionSendonly, + Codecs: []*core.Codec{ + {Name: core.CodecAAC}, + }, + }, + } + return cons +} + +func (c *Consumer) AddTrack(media *core.Media, codec *core.Codec, track *core.Receiver) error { + sender := core.NewSender(media, track.Codec) + + sender.Handler = func(pkt *rtp.Packet) { + if n, err := c.wr.Write(pkt.Payload); err == nil { + c.Send += n + } + } + + if track.Codec.IsRTP() { + sender.Handler = RTPToADTS(track.Codec, sender.Handler) + } else { + sender.Handler = EncodeToADTS(track.Codec, sender.Handler) + } + + sender.HandleRTP(track) + c.Senders = append(c.Senders, sender) + return nil +} + +func (c *Consumer) WriteTo(wr io.Writer) (int64, error) { + return c.wr.WriteTo(wr) +} + +func (c *Consumer) Stop() error { + _ = c.SuperConsumer.Close() + return c.wr.Close() +}