解决部分摄像机超时问题
1. 用 “GET_PARAMETER” 方法代替 “OPTIONS”,防止在部分摄像机中得不到响应 2. 动态获取摄像机的超时时间,实际测试中部分摄像机响应头中的timeout=8这会导致超时重连
This commit is contained in:
parent
54128f7cd2
commit
4a8df7e0f7
@ -13,6 +13,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -44,6 +45,7 @@ const (
|
|||||||
PLAY = "PLAY"
|
PLAY = "PLAY"
|
||||||
SETUP = "SETUP"
|
SETUP = "SETUP"
|
||||||
TEARDOWN = "TEARDOWN"
|
TEARDOWN = "TEARDOWN"
|
||||||
|
GET_PARAMETER = "GET_PARAMETER"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RTSPClient struct {
|
type RTSPClient struct {
|
||||||
@ -86,6 +88,7 @@ type RTSPClient struct {
|
|||||||
PreVideoTS int64
|
PreVideoTS int64
|
||||||
PreSequenceNumber int
|
PreSequenceNumber int
|
||||||
FPS int
|
FPS int
|
||||||
|
keepalive int
|
||||||
}
|
}
|
||||||
|
|
||||||
type RTSPClientOptions struct {
|
type RTSPClientOptions struct {
|
||||||
@ -110,6 +113,7 @@ func Dial(options RTSPClientOptions) (*RTSPClient, error) {
|
|||||||
audioIDX: -2,
|
audioIDX: -2,
|
||||||
options: options,
|
options: options,
|
||||||
AudioTimeScale: 8000,
|
AudioTimeScale: 8000,
|
||||||
|
keepalive: getKeepalive(60),
|
||||||
}
|
}
|
||||||
client.headers["User-Agent"] = "Lavf58.20.100"
|
client.headers["User-Agent"] = "Lavf58.20.100"
|
||||||
err := client.parseURL(html.UnescapeString(client.options.URL))
|
err := client.parseURL(html.UnescapeString(client.options.URL))
|
||||||
@ -247,8 +251,8 @@ func (client *RTSPClient) startStream() {
|
|||||||
client.Println("RTSP Client RTP SetDeadline", err)
|
client.Println("RTSP Client RTP SetDeadline", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if int(time.Now().Sub(timer).Seconds()) > 25 {
|
if int(time.Now().Sub(timer).Seconds()) > client.keepalive {
|
||||||
err := client.request(OPTIONS, map[string]string{"Require": "implicit-play"}, client.control, false, true)
|
err := client.request(GET_PARAMETER, map[string]string{"Require": "implicit-play"}, client.control, false, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
client.Println("RTSP Client RTP keep-alive", err)
|
client.Println("RTSP Client RTP keep-alive", err)
|
||||||
return
|
return
|
||||||
@ -391,6 +395,12 @@ func (client *RTSPClient) request(method string, customHeaders map[string]string
|
|||||||
if len(splits) == 2 {
|
if len(splits) == 2 {
|
||||||
if splits[0] == "Content-length" {
|
if splits[0] == "Content-length" {
|
||||||
splits[0] = "Content-Length"
|
splits[0] = "Content-Length"
|
||||||
|
} else if splits[0] == "Session" {
|
||||||
|
timeout := getTimeout(splits[1])
|
||||||
|
if timeout > 0 {
|
||||||
|
client.keepalive = getKeepalive(timeout)
|
||||||
|
client.Println("RTSP Client keepalive:", client.keepalive)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
res[splits[0]] = splits[1]
|
res[splits[0]] = splits[1]
|
||||||
}
|
}
|
||||||
@ -878,3 +888,25 @@ func binSize(val int) []byte {
|
|||||||
binary.BigEndian.PutUint32(buf, uint32(val))
|
binary.BigEndian.PutUint32(buf, uint32(val))
|
||||||
return buf
|
return buf
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func getKeepalive(timeout int) int {
|
||||||
|
keepalive := int(float64(timeout) * 0.45)
|
||||||
|
if keepalive == 0 {
|
||||||
|
keepalive = 1
|
||||||
|
}
|
||||||
|
return keepalive
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTimeout(str string) int {
|
||||||
|
reg1, err := regexp.Compile(`timeout *= *(\d+)`)
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
ret := reg1.FindStringSubmatch(strings.ToLower(str))
|
||||||
|
if len(ret) > 1 {
|
||||||
|
i, _ := strconv.Atoi(ret[1])
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user