Files
go2rtc/cmd/streams/play.go
T
2023-02-17 13:07:07 +03:00

117 lines
2.2 KiB
Go

package streams
import (
"errors"
"github.com/AlexxIT/go2rtc/pkg/streamer"
)
func (s *Stream) Play(source string) error {
s.mu.Lock()
for _, producer := range s.producers {
if producer.state == stateInternal && producer.element != nil {
_ = producer.element.Stop()
}
}
s.mu.Unlock()
if source == "" {
return nil
}
for _, producer := range s.producers {
// start new client
client, err := GetProducer(producer.url)
if err != nil {
return err
}
// check if client support consumer interface
cons, ok := client.(streamer.Consumer)
if !ok {
continue
}
// start new producer
prod, err := GetProducer(source)
if err != nil {
return err
}
if !matchMedia(prod, cons) {
return errors.New("can't match media")
}
s.AddInternalProducer(prod)
s.AddInternalConsumer(cons)
go func() {
_ = prod.Start()
_ = client.Stop()
s.RemoveProducer(prod)
}()
go func() {
_ = client.Start()
_ = prod.Stop()
s.RemoveInternalConsumer(cons)
}()
return nil
}
return errors.New("can't find consumer")
}
func (s *Stream) AddInternalProducer(prod streamer.Producer) {
producer := &Producer{element: prod, state: stateInternal}
s.mu.Lock()
s.producers = append(s.producers, producer)
s.mu.Unlock()
}
func (s *Stream) AddInternalConsumer(cons streamer.Consumer) {
consumer := &Consumer{element: cons}
s.mu.Lock()
s.consumers = append(s.consumers, consumer)
s.mu.Unlock()
}
func (s *Stream) RemoveInternalConsumer(cons streamer.Consumer) {
s.mu.Lock()
for i, consumer := range s.consumers {
if consumer.element == cons {
s.removeConsumer(i)
break
}
}
s.mu.Unlock()
}
func matchMedia(prod streamer.Producer, cons streamer.Consumer) bool {
for _, consMedia := range cons.GetMedias() {
for _, prodMedia := range prod.GetMedias() {
// codec negotiation
prodCodec := prodMedia.MatchMedia(consMedia)
if prodCodec == nil {
continue
}
// setup producer track
prodTrack := prod.GetTrack(prodMedia, prodCodec)
if prodTrack == nil {
return false
}
// setup consumer track
consTrack := cons.AddTrack(consMedia, prodTrack)
if consTrack == nil {
return false
}
return true
}
}
return false
}