Add support to play src on cameras with speaker
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
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 := client.(streamer.Consumer)
|
||||
if cons == nil {
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user