Skip to content

Commit c875da4

Browse files
committed
keep players when pusher been replaced
1 parent 6e05b22 commit c875da4

File tree

7 files changed

+126
-36
lines changed

7 files changed

+126
-36
lines changed

Diff for: easydarwin.ini

+6-1
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,14 @@ timeout=28800
1212
; 是否使能gop cache。如果使能,服务器会缓存最后一个I帧以及其后的非I帧,以提高播放速度。但是可能在高并发的情况下带来内存压力。
1313
gop_cache_enable=1
1414

15-
; 新的session连接时,如果已有同一个PATH的session在推流,则关闭之前的。
15+
; 新的推流器连接时,如果已有同一个推流器(PATH相同)在推流,是否关闭老的推流器。
16+
; 如果为0,则不会关闭老的推流器,新的推流器会被响应406错误,否则会关闭老的推流器,新的推流器会响应成功。
1617
close_old=0
1718

19+
; 当close_old为1时,是否保留被关闭的推流器对应的播放器。
20+
; 如果为0,则原推流器对应的播放器会被断开。否则会被保留下来。注意,如果该选项为1,可能某些播放器会有异常,因为RTP序列可能不一致了。
21+
keep_players=0
22+
1823
; 是否使能向服务器推流或者从服务器播放时验证用户名密码. [注意] 因为服务器端并不保存明文密码,所以推送或者播放时,客户端应该输入密码的md5后的值。
1924
; password should be the hex of md5(original password)
2025
authorization_enable=0

Diff for: main.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ func (p *program) Start(s service.Service) (err error) {
155155
log.Printf("Pull stream err :%v", err)
156156
continue
157157
}
158-
rtsp.GetServer().AddPusher(pusher, false)
158+
rtsp.GetServer().AddPusher(pusher)
159159
//streams = streams[0:i]
160160
//streams = append(streams[:i], streams[i+1:]...)
161161
}

Diff for: routers/streams.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ func (h *APIHandler) StreamStart(c *gin.Context) {
7777
return
7878
}
7979
log.Printf("Pull to push %v success ", form)
80-
rtsp.GetServer().AddPusher(pusher, false)
80+
rtsp.GetServer().AddPusher(pusher)
8181
// save to db.
8282
var stream = models.Stream{
8383
URL: form.URL,

Diff for: rtsp/pusher.go

+56-12
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,12 @@ import (
1212
type Pusher struct {
1313
*Session
1414
*RTSPClient
15-
players map[string]*Player //SessionID <-> Player
16-
playersLock sync.RWMutex
17-
gopCacheEnable bool
18-
gopCache []*RTPPack
19-
gopCacheLock sync.RWMutex
20-
UDPServer *UDPServer
21-
15+
players map[string]*Player //SessionID <-> Player
16+
playersLock sync.RWMutex
17+
gopCacheEnable bool
18+
gopCache []*RTPPack
19+
gopCacheLock sync.RWMutex
20+
UDPServer *UDPServer
2221
spsppsInSTAPaPack bool
2322
cond *sync.Cond
2423
queue []*RTPPack
@@ -187,10 +186,24 @@ func NewPusher(session *Session) (pusher *Pusher) {
187186
cond: sync.NewCond(&sync.Mutex{}),
188187
queue: make([]*RTPPack, 0),
189188
}
189+
pusher.bindSession(session)
190+
return
191+
}
192+
193+
func (pusher *Pusher) bindSession(session *Session) {
194+
pusher.Session = session
190195
session.RTPHandles = append(session.RTPHandles, func(pack *RTPPack) {
196+
if session != pusher.Session {
197+
session.logger.Printf("Session recv rtp to pusher.but pusher got a new session[%v].", pusher.Session.ID)
198+
return
199+
}
191200
pusher.QueueRTP(pack)
192201
})
193202
session.StopHandles = append(session.StopHandles, func() {
203+
if session != pusher.Session {
204+
session.logger.Printf("Session stop to release pusher.but pusher got a new session[%v].", pusher.Session.ID)
205+
return
206+
}
194207
pusher.ClearPlayer()
195208
pusher.Server().RemovePusher(pusher)
196209
pusher.cond.Broadcast()
@@ -199,7 +212,37 @@ func NewPusher(session *Session) (pusher *Pusher) {
199212
pusher.UDPServer = nil
200213
}
201214
})
202-
return
215+
}
216+
217+
func (pusher *Pusher) RebindSession(session *Session) bool {
218+
if pusher.RTSPClient != nil {
219+
pusher.Logger().Printf("call RebindSession[%s] to a Client-Pusher. got false", session.ID)
220+
return false
221+
}
222+
sess := pusher.Session
223+
pusher.bindSession(session)
224+
session.Pusher = pusher
225+
226+
pusher.gopCacheLock.Lock()
227+
pusher.gopCache = make([]*RTPPack, 0)
228+
pusher.gopCacheLock.Unlock()
229+
if sess != nil {
230+
sess.Stop()
231+
}
232+
return true
233+
}
234+
235+
func (pusher *Pusher) RebindClient(client *RTSPClient) bool {
236+
if pusher.Session != nil {
237+
pusher.Logger().Printf("call RebindClient[%s] to a Session-Pusher. got false", client.ID)
238+
return false
239+
}
240+
sess := pusher.RTSPClient
241+
pusher.RTSPClient = client
242+
if sess != nil {
243+
sess.Stop()
244+
}
245+
return true
203246
}
204247

205248
func (pusher *Pusher) QueueRTP(pack *RTPPack) *Pusher {
@@ -312,10 +355,11 @@ func (pusher *Pusher) ClearPlayer() {
312355
}
313356
pusher.players = make(map[string]*Player)
314357
pusher.playersLock.Unlock()
315-
316-
for _, v := range players {
317-
v.Stop()
318-
}
358+
go func() { // do not block
359+
for _, v := range players {
360+
v.Stop()
361+
}
362+
}()
319363
}
320364

321365
func (pusher *Pusher) shouldSequenceStart(rtp *RTPInfo) bool {

Diff for: rtsp/rtsp-client.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ func (client *RTSPClient) Stop() {
501501
client.Conn.Close()
502502
client.Conn = nil
503503
}
504-
if client.UDPServer != nil{
504+
if client.UDPServer != nil {
505505
client.UDPServer.Stop()
506506
client.UDPServer = nil
507507
}

Diff for: rtsp/rtsp-server.go

+20-12
Original file line numberDiff line numberDiff line change
@@ -187,35 +187,43 @@ func (server *Server) Stop() {
187187
close(server.removePusherCh)
188188
}
189189

190-
func (server *Server) AddPusher(pusher *Pusher, closeOld bool) bool {
190+
func (server *Server) AddPusher(pusher *Pusher) bool {
191191
logger := server.logger
192192
added := false
193193
server.pushersLock.Lock()
194-
old, ok := server.pushers[pusher.Path()]
194+
_, ok := server.pushers[pusher.Path()]
195195
if !ok {
196196
server.pushers[pusher.Path()] = pusher
197197
logger.Printf("%v start, now pusher size[%d]", pusher, len(server.pushers))
198198
added = true
199199
} else {
200-
if closeOld {
201-
server.pushers[pusher.Path()] = pusher
202-
logger.Printf("%v start, replace old pusher", pusher)
203-
added = true
204-
}
200+
added = false
205201
}
206202
server.pushersLock.Unlock()
207-
if ok && closeOld {
208-
logger.Printf("old pusher %v stoped", pusher)
209-
old.Stop()
210-
server.removePusherCh <- old
211-
}
212203
if added {
213204
go pusher.Start()
214205
server.addPusherCh <- pusher
215206
}
216207
return added
217208
}
218209

210+
func (server *Server) TryAttachToPusher(session *Session) (int, *Pusher) {
211+
server.pushersLock.Lock()
212+
attached := 0
213+
var pusher *Pusher = nil
214+
if _pusher, ok := server.pushers[session.Path]; ok {
215+
if _pusher.RebindSession(session) {
216+
session.logger.Printf("Attached to a pusher")
217+
attached = 1
218+
pusher = _pusher
219+
} else {
220+
attached = -1
221+
}
222+
}
223+
server.pushersLock.Unlock()
224+
return attached, pusher
225+
}
226+
219227
func (server *Server) RemovePusher(pusher *Pusher) {
220228
logger := server.logger
221229
removed := false

Diff for: rtsp/rtsp-session.go

+41-8
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ func (session *Session) handleRequest(req *Request) {
368368
res := NewResponse(200, "OK", req.Header["CSeq"], session.ID, "")
369369
defer func() {
370370
if p := recover(); p != nil {
371-
logger.Printf("handleRequest err ocurs:%v",p)
371+
logger.Printf("handleRequest err ocurs:%v", p)
372372
res.StatusCode = 500
373373
res.Status = fmt.Sprintf("Inner Server Error, %v", p)
374374
}
@@ -449,13 +449,46 @@ func (session *Session) handleRequest(req *Request) {
449449
session.VCodec = sdp.Codec
450450
logger.Printf("video codec[%s]\n", session.VCodec)
451451
}
452-
session.Pusher = NewPusher(session)
453-
454-
addedToServer := session.Server.AddPusher(session.Pusher, session.closeOld)
455-
if !addedToServer {
456-
logger.Printf("reject pusher.")
457-
res.StatusCode = 406
458-
res.Status = "Not Acceptable"
452+
addPusher := false
453+
if session.closeOld {
454+
r, _ := session.Server.TryAttachToPusher(session)
455+
if r < -1 {
456+
logger.Printf("reject pusher.")
457+
res.StatusCode = 406
458+
res.Status = "Not Acceptable"
459+
} else if r == 0 {
460+
addPusher = true
461+
} else {
462+
logger.Printf("Attached to old pusher")
463+
// 尝试发给客户端ANNOUCE
464+
// players := pusher.GetPlayers()
465+
// for _, v := range players {
466+
// sess := v.Session
467+
468+
// hearers := make(map[string]string)
469+
// hearers["Content-Type"] = "application/sdp"
470+
// hearers["Session"] = sess.ID
471+
// hearers["Content-Length"] = strconv.Itoa(len(v.SDPRaw))
472+
// var req = Request{Method: ANNOUNCE, URL: v.URL, Version: "1.0", Header: hearers, Body: pusher.SDPRaw()}
473+
// sess.connWLock.Lock()
474+
// logger.Println(req.String())
475+
// outBytes := []byte(req.String())
476+
// sess.connRW.Write(outBytes)
477+
// sess.connRW.Flush()
478+
// sess.connWLock.Unlock()
479+
// }
480+
}
481+
} else {
482+
addPusher = true
483+
}
484+
if addPusher {
485+
session.Pusher = NewPusher(session)
486+
addedToServer := session.Server.AddPusher(session.Pusher)
487+
if !addedToServer {
488+
logger.Printf("reject pusher.")
489+
res.StatusCode = 406
490+
res.Status = "Not Acceptable"
491+
}
459492
}
460493
case "DESCRIBE":
461494
session.Type = SESSEION_TYPE_PLAYER

0 commit comments

Comments
 (0)