first commit
This commit is contained in:
		
							
								
								
									
										1241
									
								
								format/rtsp/client.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1241
									
								
								format/rtsp/client.go
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										25
									
								
								format/rtsp/conn.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								format/rtsp/conn.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| package rtsp | ||||
|  | ||||
| import ( | ||||
| 	"net" | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| type connWithTimeout struct { | ||||
| 	Timeout time.Duration | ||||
| 	net.Conn | ||||
| } | ||||
|  | ||||
| func (self connWithTimeout) Read(p []byte) (n int, err error) { | ||||
| 	if self.Timeout > 0 { | ||||
| 		self.Conn.SetReadDeadline(time.Now().Add(self.Timeout)) | ||||
| 	} | ||||
| 	return self.Conn.Read(p) | ||||
| } | ||||
|  | ||||
| func (self connWithTimeout) Write(p []byte) (n int, err error) { | ||||
| 	if self.Timeout > 0 { | ||||
| 		self.Conn.SetWriteDeadline(time.Now().Add(self.Timeout)) | ||||
| 	} | ||||
| 	return self.Conn.Write(p) | ||||
| } | ||||
							
								
								
									
										117
									
								
								format/rtsp/sdp/parser.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								format/rtsp/sdp/parser.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,117 @@ | ||||
| package sdp | ||||
|  | ||||
| import ( | ||||
| 	"encoding/base64" | ||||
| 	"encoding/hex" | ||||
| 	"fmt" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/deepch/vdk/av" | ||||
| ) | ||||
|  | ||||
| type Session struct { | ||||
| 	Uri string | ||||
| } | ||||
|  | ||||
| type Media struct { | ||||
| 	AVType             string | ||||
| 	Type               av.CodecType | ||||
| 	TimeScale          int | ||||
| 	Control            string | ||||
| 	Rtpmap             int | ||||
| 	Config             []byte | ||||
| 	SpropParameterSets [][]byte | ||||
| 	PayloadType        int | ||||
| 	SizeLength         int | ||||
| 	IndexLength        int | ||||
| } | ||||
|  | ||||
| func Parse(content string) (sess Session, medias []Media) { | ||||
| 	var media *Media | ||||
|  | ||||
| 	for _, line := range strings.Split(content, "\n") { | ||||
| 		line = strings.TrimSpace(line) | ||||
| 		typeval := strings.SplitN(line, "=", 2) | ||||
| 		if len(typeval) == 2 { | ||||
| 			fields := strings.SplitN(typeval[1], " ", 2) | ||||
|  | ||||
| 			switch typeval[0] { | ||||
| 			case "m": | ||||
| 				if len(fields) > 0 { | ||||
| 					switch fields[0] { | ||||
| 					case "audio", "video": | ||||
| 						medias = append(medias, Media{AVType: fields[0]}) | ||||
| 						media = &medias[len(medias)-1] | ||||
| 						mfields := strings.Split(fields[1], " ") | ||||
| 						if len(mfields) >= 3 { | ||||
| 							media.PayloadType, _ = strconv.Atoi(mfields[2]) | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
|  | ||||
| 			case "u": | ||||
| 				sess.Uri = typeval[1] | ||||
|  | ||||
| 			case "a": | ||||
| 				if media != nil { | ||||
| 					for _, field := range fields { | ||||
| 						keyval := strings.SplitN(field, ":", 2) | ||||
| 						if len(keyval) >= 2 { | ||||
| 							key := keyval[0] | ||||
| 							val := keyval[1] | ||||
| 							switch key { | ||||
| 							case "control": | ||||
| 								media.Control = val | ||||
| 							case "rtpmap": | ||||
| 								media.Rtpmap, _ = strconv.Atoi(val) | ||||
| 							} | ||||
| 						} | ||||
| 						keyval = strings.Split(field, "/") | ||||
| 						if len(keyval) >= 2 { | ||||
| 							key := keyval[0] | ||||
| 							switch strings.ToUpper(key) { | ||||
| 							case "MPEG4-GENERIC": | ||||
| 								media.Type = av.AAC | ||||
| 							case "H264": | ||||
| 								media.Type = av.H264 | ||||
| 							} | ||||
| 							if i, err := strconv.Atoi(keyval[1]); err == nil { | ||||
| 								media.TimeScale = i | ||||
| 							} | ||||
| 							if false { | ||||
| 								fmt.Println("sdp:", keyval[1], media.TimeScale) | ||||
| 							} | ||||
| 						} | ||||
| 						keyval = strings.Split(field, ";") | ||||
| 						if len(keyval) > 1 { | ||||
| 							for _, field := range keyval { | ||||
| 								keyval := strings.SplitN(field, "=", 2) | ||||
| 								if len(keyval) == 2 { | ||||
| 									key := strings.TrimSpace(keyval[0]) | ||||
| 									val := keyval[1] | ||||
| 									switch key { | ||||
| 									case "config": | ||||
| 										media.Config, _ = hex.DecodeString(val) | ||||
| 									case "sizelength": | ||||
| 										media.SizeLength, _ = strconv.Atoi(val) | ||||
| 									case "indexlength": | ||||
| 										media.IndexLength, _ = strconv.Atoi(val) | ||||
| 									case "sprop-parameter-sets": | ||||
| 										fields := strings.Split(val, ",") | ||||
| 										for _, field := range fields { | ||||
| 											val, _ := base64.StdEncoding.DecodeString(field) | ||||
| 											media.SpropParameterSets = append(media.SpropParameterSets, val) | ||||
| 										} | ||||
| 									} | ||||
| 								} | ||||
| 							} | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
|  | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										44
									
								
								format/rtsp/sdp/parser_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								format/rtsp/sdp/parser_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | ||||
| package sdp | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| func TestParse(t *testing.T) { | ||||
| 	infos := Decode(` | ||||
| v=0 | ||||
| o=- 1459325504777324 1 IN IP4 192.168.0.123 | ||||
| s=RTSP/RTP stream from Network Video Server | ||||
| i=mpeg4cif | ||||
| t=0 0 | ||||
| a=tool:LIVE555 Streaming Media v2009.09.28 | ||||
| a=type:broadcast | ||||
| a=control:* | ||||
| a=range:npt=0- | ||||
| a=x-qt-text-nam:RTSP/RTP stream from Network Video Server | ||||
| a=x-qt-text-inf:mpeg4cif | ||||
| m=video 0 RTP/AVP 96 | ||||
| c=IN IP4 0.0.0.0 | ||||
| b=AS:300 | ||||
| a=rtpmap:96 H264/90000 | ||||
| a=fmtp:96 profile-level-id=420029; packetization-mode=1; sprop-parameter-sets=Z00AHpWoKA9k,aO48gA== | ||||
| a=x-dimensions: 720, 480 | ||||
| a=x-framerate: 15 | ||||
| a=control:track1 | ||||
| m=audio 0 RTP/AVP 96 | ||||
| c=IN IP4 0.0.0.0 | ||||
| b=AS:256 | ||||
| a=rtpmap:96 MPEG4-GENERIC/16000/2 | ||||
| a=fmtp:96 streamtype=5;profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3;config=1408 | ||||
| a=control:track2 | ||||
| m=audio 0 RTP/AVP 0 | ||||
| c=IN IP4 0.0.0.0 | ||||
| b=AS:50 | ||||
| a=recvonly | ||||
| a=control:rtsp://109.195.127.207:554/mpeg4cif/trackID=2 | ||||
| a=rtpmap:0 PCMU/8000 | ||||
| a=Media_header:MEDIAINFO=494D4B48010100000400010010710110401F000000FA000000000000000000000000000000000000; | ||||
| a=appversion:1.0 | ||||
| `) | ||||
| 	t.Logf("%v", infos) | ||||
| } | ||||
							
								
								
									
										29
									
								
								format/rtsp/stream.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								format/rtsp/stream.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| package rtsp | ||||
|  | ||||
| import ( | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/deepch/vdk/av" | ||||
| 	"github.com/deepch/vdk/format/rtsp/sdp" | ||||
| ) | ||||
|  | ||||
| type Stream struct { | ||||
| 	av.CodecData | ||||
| 	Sdp    sdp.Media | ||||
| 	client *Client | ||||
|  | ||||
| 	// h264 | ||||
| 	fuStarted  bool | ||||
| 	fuBuffer   []byte | ||||
| 	sps        []byte | ||||
| 	pps        []byte | ||||
| 	spsChanged bool | ||||
| 	ppsChanged bool | ||||
|  | ||||
| 	gotpkt         bool | ||||
| 	pkt            av.Packet | ||||
| 	timestamp      uint32 | ||||
| 	firsttimestamp uint32 | ||||
|  | ||||
| 	lasttime time.Duration | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Andrey Semochkin
					Andrey Semochkin