@@ -17,6 +17,7 @@ package urlpull
1717import (
1818 "context"
1919 "strings"
20+ "sync"
2021 "time"
2122
2223 "github.com/frostbyte73/core"
@@ -29,6 +30,11 @@ import (
2930
3031var (
3132 supportedMimeTypes = []string {
33+
34+ // BEGIN OPENVIDU BLOCK
35+ "application/x-rtp" , // RTSP streams have this mime type
36+ // END OPENVIDU BLOCK
37+
3238 "audio/x-m4a" ,
3339 "application/x-hls" ,
3440 "video/quicktime" ,
4248)
4349
4450type URLSource struct {
51+ // BEGIN OPENVIDU BLOCK
52+ srcAudio * gst.Element
53+ Rtspsrc * gst.Element
54+ // END OPENVIDU BLOCK
55+
4556 params * params.Params
4657 src * gst.Element
4758 pad * gst.Pad
@@ -85,10 +96,163 @@ func NewURLSource(ctx context.Context, p *params.Params) (*URLSource, error) {
8596 }
8697 }
8798 }
99+
100+ // BEGIN OPENVIDU BLOCK
101+ } else if strings .HasPrefix (p .Url , "rtsp://" ) || strings .HasPrefix (p .Url , "rtsps://" ) {
102+
103+ elem , err = gst .NewElementWithName ("rtspsrc" , "rtspsrc" )
104+ if err != nil {
105+ return nil , err
106+ }
107+ err = elem .SetProperty ("location" , p .Url )
108+ if err != nil {
109+ return nil , err
110+ }
111+ err = elem .SetProperty ("latency" , uint (2000 ))
112+ if err != nil {
113+ return nil , err
114+ }
115+ err = elem .SetProperty ("drop-on-latency" , true )
116+ if err != nil {
117+ return nil , err
118+ }
119+ err = elem .SetProperty ("port-range" , "0-0" )
120+ if err != nil {
121+ return nil , err
122+ }
123+ // END OPENVIDU BLOCK
124+
88125 } else {
89126 return nil , errors .ErrUnsupportedURLFormat
90127 }
91128
129+ // BEGIN OPENVIDU BLOCK
130+ if strings .HasPrefix (p .Url , "rtsp://" ) || strings .HasPrefix (p .Url , "rtsps://" ) {
131+ // Video
132+ videoqueue , _ := gst .NewElementWithName ("queue2" , "videoqueue" )
133+ bin .Add (videoqueue )
134+ // Create video queue ghost sink
135+ videoqueuesink := videoqueue .GetStaticPad ("sink" )
136+ if videoqueuesink == nil {
137+ return nil , errors .ErrUnableToAddPad
138+ }
139+ videoqueueghostsink := gst .NewGhostPad ("sink" , videoqueuesink )
140+ bin .AddPad (videoqueueghostsink .Pad )
141+ // Create video queue ghost source
142+ videoqueuesrc := videoqueue .GetStaticPad ("src" )
143+ if videoqueuesrc == nil {
144+ return nil , errors .ErrUnableToAddPad
145+ }
146+ videoqueueghostsrc := gst .NewGhostPad ("src" , videoqueuesrc )
147+ if ! bin .AddPad (videoqueueghostsrc .Pad ) {
148+ return nil , errors .ErrUnableToAddPad
149+ }
150+
151+ // Audio
152+ audiobin := gst .NewBin ("audioinput" )
153+ audioqueue , _ := gst .NewElementWithName ("queue2" , "audioqueue" )
154+ audiobin .Add (audioqueue )
155+ // Create audio queue ghost sink
156+ audioqueuesink := audioqueue .GetStaticPad ("sink" )
157+ if audioqueuesink == nil {
158+ return nil , errors .ErrUnableToAddPad
159+ }
160+ audioqueueghostsink := gst .NewGhostPad ("sink" , audioqueuesink )
161+ audiobin .AddPad (audioqueueghostsink .Pad )
162+ // Create audio queue ghost source
163+ audioqueuesrc := audioqueue .GetStaticPad ("src" )
164+ if audioqueuesrc == nil {
165+ return nil , errors .ErrUnableToAddPad
166+ }
167+ audioqueueghostsrc := gst .NewGhostPad ("src" , audioqueuesrc )
168+ if ! audiobin .AddPad (audioqueueghostsrc .Pad ) {
169+ return nil , errors .ErrUnableToAddPad
170+ }
171+
172+ var mu sync.Mutex
173+
174+ elem .Connect ("pad-added" , func (src * gst.Element , pad * gst.Pad ) {
175+
176+ padName := pad .GetName ()
177+
178+ logger .Infow ("rtspsrc pad-added" , "padName" , padName )
179+
180+ var queue * gst.Element
181+ var sinkPad * gst.Pad
182+ var getQueueErr error
183+ isAudio := false
184+ isVideo := false
185+
186+ pad .GetCurrentCaps ().ForEach (func (features * gst.CapsFeatures , structure * gst.Structure ) bool {
187+ value , getMediaErr := structure .GetValue ("media" )
188+ if getMediaErr != nil {
189+ logger .Errorw ("failed to get media value from caps" , getMediaErr )
190+ return false
191+ }
192+ if value == "audio" {
193+ isAudio = true
194+ return true
195+ } else if value == "video" {
196+ isVideo = true
197+ return true
198+ } else {
199+ logger .Errorw ("pad unrecognized media type" , nil , "media" , value )
200+ return false
201+ }
202+ })
203+
204+ mu .Lock ()
205+ defer mu .Unlock ()
206+
207+ if isAudio {
208+ sinkPad = audiobin .GetStaticPad ("sink" )
209+ queue , getQueueErr = audiobin .GetElementByName ("audioqueue" )
210+ } else if isVideo {
211+ sinkPad = bin .GetStaticPad ("sink" )
212+ queue , getQueueErr = bin .GetElementByName ("videoqueue" )
213+ } else {
214+ logger .Errorw ("pad media type not audio nor video" , nil , "padName" , padName )
215+ return
216+ }
217+
218+ if sinkPad == nil {
219+ logger .Errorw ("failed to get sink pad" , nil )
220+ return
221+ }
222+ if getQueueErr != nil {
223+ logger .Errorw ("failed to get queue element" , err )
224+ return
225+ }
226+
227+ if sinkPad .IsLinked () {
228+ var kind string
229+ if isAudio {
230+ kind = "audio"
231+ } else {
232+ kind = "video"
233+ }
234+ logger .Warnw ("sink pad of kind " + kind + " is already linked" , nil )
235+ logger .Warnw ("this usually means that the source is sending multiple streams of the same kind" , nil )
236+ return
237+ }
238+
239+ padLinkReturnValue := pad .Link (sinkPad )
240+ if padLinkReturnValue != gst .PadLinkOK && padLinkReturnValue != gst .PadLinkWasLinked {
241+ logger .Errorw ("failed to link pad" , nil , "padLinkReturnValue" , padLinkReturnValue )
242+ return
243+ }
244+ queue .SyncStateWithParent ()
245+ })
246+
247+ return & URLSource {
248+ params : p ,
249+ src : bin .Element ,
250+ srcAudio : audiobin .Element ,
251+ Rtspsrc : elem ,
252+ }, nil
253+ }
254+ // END OPENVIDU BLOCK
255+
92256 queue , err := gst .NewElement ("queue2" )
93257 if err != nil {
94258 return nil , err
@@ -135,6 +299,14 @@ func NewURLSource(ctx context.Context, p *params.Params) (*URLSource, error) {
135299}
136300
137301func (u * URLSource ) GetSources () []* gst.Element {
302+ // BEGIN OPENVIDU BLOCK
303+ if u .srcAudio != nil {
304+ return []* gst.Element {
305+ u .src ,
306+ u .srcAudio ,
307+ }
308+ }
309+ // END OPENVIDU BLOCK
138310 return []* gst.Element {
139311 u .src ,
140312 }
0 commit comments