Add 'rtsp/' from commit 'df0f52cf38a45d842291bb72e1adc24de397d1dd'
git-subtree-dir: rtsp git-subtree-mainline: 6b682ae3918d3f153df86e11eb07d386bfcd26b8 git-subtree-split: df0f52cf38a45d842291bb72e1adc24de397d1dd
This commit is contained in:
commit
452846833c
1214
rtsp/client.go
Normal file
1214
rtsp/client.go
Normal file
File diff suppressed because it is too large
Load Diff
25
rtsp/conn.go
Normal file
25
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)
|
||||
}
|
116
rtsp/sdp/parser.go
Normal file
116
rtsp/sdp/parser.go
Normal file
@ -0,0 +1,116 @@
|
||||
package sdp
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"github.com/nareix/av"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
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
rtsp/sdp/parser_test.go
Normal file
44
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
rtsp/stream.go
Normal file
29
rtsp/stream.go
Normal file
@ -0,0 +1,29 @@
|
||||
package rtsp
|
||||
|
||||
import (
|
||||
"github.com/nareix/av"
|
||||
"github.com/nareix/rtsp/sdp"
|
||||
"time"
|
||||
)
|
||||
|
||||
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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user