解决部分摄像机超时问题

1. 用 “GET_PARAMETER” 方法代替 “OPTIONS”,防止在部分摄像机中得不到响应
2. 动态获取摄像机的超时时间,实际测试中部分摄像机响应头中的timeout=8这会导致超时重连
This commit is contained in:
felix 2021-08-19 18:50:56 +08:00 committed by GitHub
parent 54128f7cd2
commit 4a8df7e0f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -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
}