github.com/cnotch/ipchub@v1.1.0/service/rtsp/rtptransport.go (about) 1 // Copyright (c) 2019,CAOHONGJU All rights reserved. 2 // Use of this source code is governed by a MIT-style 3 // license that can be found in the LICENSE file. 4 5 package rtsp 6 7 import ( 8 "errors" 9 "strconv" 10 "strings" 11 12 "github.com/cnotch/ipchub/utils/scan" 13 ) 14 15 // RTPTransportType RTP 传输模式 16 type RTPTransportType int 17 18 // SessionMode 会话模式 19 type SessionMode int 20 21 // 通讯类型 22 const ( 23 RTPUnknownTrans RTPTransportType = iota 24 RTPTCPUnicast // TCP 25 RTPUDPUnicast // UDP 26 RTPMulticast // 组播 27 ) 28 29 // 会话类型 30 const ( 31 UnknownSession SessionMode = iota 32 PlaySession // 播放 33 RecordSession // 录像 34 ) 35 36 // RTPTransport RTP传输设置 37 type RTPTransport struct { 38 Mode SessionMode 39 Append bool 40 Type RTPTransportType 41 Channels [rtpChannelCount]int 42 ClientPorts [rtpChannelCount]int 43 ServerPorts [rtpChannelCount]int 44 45 // 组播相关设置 46 Ports [rtpChannelCount]int // 组播端口 47 MulticastIP string // 组播地址 224.0.1.0~238.255.255.255 48 TTL int 49 Source string // 组播源地址 50 } 51 52 func parseRange(p string) (begin int, end int) { 53 begin = -1 54 end = -1 55 56 var s1, s2 string 57 index := strings.IndexByte(p, '-') 58 if index < 0 { 59 s1 = p 60 } else { 61 s1 = strings.TrimSpace(p[:index]) 62 s2 = strings.TrimSpace(p[index+1:]) 63 } 64 var err error 65 if len(s1) > 0 { 66 begin, err = strconv.Atoi(s1) 67 if err != nil { 68 begin = -1 69 } 70 } 71 if len(s2) > 0 { 72 end, err = strconv.Atoi(s2) 73 if err != nil { 74 end = -1 75 } 76 } 77 return 78 } 79 80 // ParseTransport 解析Setup中的传输配置 81 func (t *RTPTransport) ParseTransport(rtpType int, ts string) (err error) { 82 if t.Mode == UnknownSession { 83 t.Mode = PlaySession 84 } 85 86 // 确定传输类型 87 index := strings.IndexByte(ts, ';') 88 if index < 0 { 89 return errors.New("malformed trannsport") 90 } 91 transportSpec := strings.TrimSpace(ts[:index]) 92 ts = ts[index+1:] 93 94 if transportSpec == "RTP/AVP/TCP" { 95 t.Type = RTPTCPUnicast 96 } else if transportSpec == "RTP/AVP" || transportSpec == "RTP/AVP/UDP" { 97 t.Type = RTPMulticast // 默认组播 98 } else { 99 return errors.New("malformed trannsport") 100 } 101 102 // 扫描参数 103 advance := ts 104 token := "" 105 continueScan := true 106 for continueScan { 107 advance, token, continueScan = scan.Semicolon.Scan(advance) 108 if token == "unicast" && t.Type == RTPMulticast { 109 t.Type = RTPUDPUnicast 110 continue 111 } 112 if token == "multicast" && t.Type == RTPTCPUnicast { 113 err = errors.New("malformed trannsport") 114 continue 115 } 116 if token == "append" { 117 t.Append = true 118 continue 119 } 120 121 k, v, _ := scan.EqualPair.Scan(token) 122 switch k { 123 case "mode": 124 if v == "record" { 125 t.Mode = RecordSession 126 } else { 127 t.Mode = PlaySession 128 } 129 case "interleaved": 130 begin, end := parseRange(v) 131 if begin >= 0 { 132 t.Channels[rtpType] = begin 133 } 134 if end >= 0 { 135 t.Channels[rtpType+1] = end 136 } 137 if begin < 0 { 138 err = errors.New("malformed trannsport") 139 } 140 case "client_port": 141 t.ClientPorts[rtpType], t.ClientPorts[rtpType+1] = parseRange(v) 142 if t.ClientPorts[rtpType] < 0 { 143 err = errors.New("malformed trannsport") 144 } 145 case "server_port": 146 t.ServerPorts[rtpType], t.ServerPorts[rtpType+1] = parseRange(v) 147 if t.ServerPorts[rtpType] < 0 { 148 err = errors.New("malformed trannsport") 149 } 150 case "port": 151 t.Ports[rtpType], t.Ports[rtpType+1] = parseRange(v) 152 if t.Ports[rtpType] < 0 { 153 err = errors.New("malformed trannsport") 154 } 155 case "destination": 156 t.MulticastIP = v 157 case "source": 158 t.Source = v 159 case "ttl": 160 t.TTL, _ = strconv.Atoi(v) 161 } 162 } 163 return 164 }