mirror of https://bitbucket.org/ausocean/av.git
Wrote rtmpSetupUrl, but need to test
This commit is contained in:
parent
e04ae76dcf
commit
e5696f389d
169
rtmp/rtmp.go
169
rtmp/rtmp.go
|
@ -146,6 +146,18 @@ var setDataFrame = AVC("@setDataFrame")
|
||||||
|
|
||||||
var packetSize = [...]int{12, 8, 4, 1}
|
var packetSize = [...]int{12, 8, 4, 1}
|
||||||
|
|
||||||
|
var RTMPProtocolStringsLower = [...]string{
|
||||||
|
"rtmp",
|
||||||
|
"rtmpt",
|
||||||
|
"rtmpe",
|
||||||
|
"rtmpte",
|
||||||
|
"rtmps",
|
||||||
|
"rtmpts",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"rtmfp",
|
||||||
|
}
|
||||||
|
|
||||||
// Session provides an interface for sending flv tags over rtmp.
|
// Session provides an interface for sending flv tags over rtmp.
|
||||||
type Session interface {
|
type Session interface {
|
||||||
Open() error
|
Open() error
|
||||||
|
@ -318,13 +330,40 @@ func (s *session) Open() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close terminates the rtmp connection
|
||||||
|
func (s *session) Close() error {
|
||||||
|
if s.rtmp == nil {
|
||||||
|
return Err(3)
|
||||||
|
}
|
||||||
|
ret := endSession(s.rtmp)
|
||||||
|
s.rtmp = nil
|
||||||
|
if ret != 0 {
|
||||||
|
return Err(ret)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write writes a frame (flv tag) to the rtmp connection
|
||||||
|
func (s *session) Write(data []byte) (int, error) {
|
||||||
|
if s.rtmp == nil {
|
||||||
|
return 0, Err(3)
|
||||||
|
}
|
||||||
|
if C.RTMP_IsConnected(s.rtmp) == 0 {
|
||||||
|
return 0, Err(1)
|
||||||
|
}
|
||||||
|
//if C.RTMP_Write(s.rtmp,(*C.char)(unsafe.Pointer(&data[0])),C.int(len(data))) == 0 {
|
||||||
|
if rtmpWrite(s.rtmp, data) == 0 {
|
||||||
|
return 0, Err(2)
|
||||||
|
}
|
||||||
|
return len(data), nil
|
||||||
|
}
|
||||||
|
|
||||||
func startSession(rtmp *C.RTMP, u string, timeout uint32) (*C.RTMP, error) {
|
func startSession(rtmp *C.RTMP, u string, timeout uint32) (*C.RTMP, error) {
|
||||||
url := C.CString(u)
|
|
||||||
connect_timeout := C.int(timeout)
|
connect_timeout := C.int(timeout)
|
||||||
rtmp = rtmpAlloc()
|
rtmp = rtmpAlloc()
|
||||||
rtmpInit(rtmp)
|
rtmpInit(rtmp)
|
||||||
rtmp.Link.timeout = connect_timeout
|
rtmp.Link.timeout = connect_timeout
|
||||||
if C.RTMP_SetupURL(rtmp, url) == 0 {
|
if rtmpSetupUrl(rtmp, u) == 0 {
|
||||||
C.RTMP_Close(rtmp)
|
C.RTMP_Close(rtmp)
|
||||||
C.RTMP_Free(rtmp)
|
C.RTMP_Free(rtmp)
|
||||||
return nil, errors.New("rtmp startSession: Failed to setup URL!")
|
return nil, errors.New("rtmp startSession: Failed to setup URL!")
|
||||||
|
@ -366,17 +405,75 @@ func rtmpInit(r *C.RTMP) {
|
||||||
r.Link.swfAge = 30
|
r.Link.swfAge = 30
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close terminates the rtmp connection
|
func rtmpSetupUrl(r *C.RTMP, u string) int32 {
|
||||||
func (s *session) Close() error {
|
length := len(u)
|
||||||
if s.rtmp == nil {
|
url := goStrToCStr(u)
|
||||||
return Err(3)
|
|
||||||
|
var opt, arg AVal
|
||||||
|
var p1, p2 *byte
|
||||||
|
ptr := strchr(url, byte(' '))
|
||||||
|
var ret, len int32
|
||||||
|
var port uint32
|
||||||
|
port = 0
|
||||||
|
|
||||||
|
len = strlen(url)
|
||||||
|
ret = int32(C.RTMP_ParseURL((*C.char)(unsafe.Pointer(url)), &r.Link.protocol, &r.Link.hostname,
|
||||||
|
(*C.uint)(&port), &r.Link.playpath0, &r.Link.app))
|
||||||
|
|
||||||
|
if ret == 0 {
|
||||||
|
return ret
|
||||||
}
|
}
|
||||||
ret := endSession(s.rtmp)
|
|
||||||
s.rtmp = nil
|
r.Link.port = C.ushort(port)
|
||||||
if ret != 0 {
|
r.Link.playpath = r.Link.playpath0
|
||||||
return Err(ret)
|
|
||||||
|
if r.Link.tcUrl.av_len == 0 {
|
||||||
|
r.Link.tcUrl.av_val = url
|
||||||
|
if r.Link.app.av_len != 0 {
|
||||||
|
if int(uintptr(unsafe.Pointer(r.Link.app.av_val))) <
|
||||||
|
int(uintptr(incBytePtr(url, len))) {
|
||||||
|
|
||||||
|
r.Link.tcUrl.av_len = r.Link.app.av_len +
|
||||||
|
int(uintptr(decBytePtr(r.Link.app.av_val, int(uintptr(unsafe.Pointer(url))))))
|
||||||
|
} else {
|
||||||
|
len = r.Link.hostname.av_len + r.Link.app.av_len +
|
||||||
|
int(unsafe.Sizeof("rtmpte://:65535/"))
|
||||||
|
|
||||||
|
r.Link.tcUrl.av_val = (*C.char)(allocate(uintptr(len)))
|
||||||
|
hostname := string(ptrToSlice(unsafe.Pointer(r.Link.hostname.av_val),
|
||||||
|
int(r.Link.hostname.av_len)))
|
||||||
|
|
||||||
|
app := string(ptrToSlice(unsafe.Pointer(r.Link.app.av_val),
|
||||||
|
int(r.Link.app.av_len)))
|
||||||
|
|
||||||
|
fString := fmt.Sprintf("%v://%v:%v/%v",
|
||||||
|
RTMPProtocolStringsLower[r.Link.protocol], hostname, r.Link.port, app)
|
||||||
|
|
||||||
|
r.Link.tcUrl.av_val = (*C.char)(goStrToCStr(fString))
|
||||||
|
r.Link.tcUrl.av_len = len(RTMPProtocolStringsLower[r.Link.protocol]) +
|
||||||
|
len(string("://")) + len(hostname) + len(string(":")) +
|
||||||
|
len(strconv.Itoa(int(r.Link.port))) + len(string("/")) + len(app)
|
||||||
|
|
||||||
|
r.Link.lFlags |= RTMP_LF_FTCU
|
||||||
}
|
}
|
||||||
return nil
|
} else {
|
||||||
|
r.Link.tcUrl.av_len = strlen(url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
C.SocksSetup(r, &r.Link.sockshost)
|
||||||
|
|
||||||
|
if r.Link.port == 0 {
|
||||||
|
switch {
|
||||||
|
case r.Link.Protocol & RRTMP_FEATURE_SSL:
|
||||||
|
r.Link.port = 433
|
||||||
|
case r.Link.protocol & RTMP_FEATURE_HTTP:
|
||||||
|
r.Link.port = 80
|
||||||
|
default:
|
||||||
|
r.Link.port = 1935
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func endSession(rtmp *C.RTMP) uint32 {
|
func endSession(rtmp *C.RTMP) uint32 {
|
||||||
|
@ -389,21 +486,6 @@ func endSession(rtmp *C.RTMP) uint32 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write writes a frame (flv tag) to the rtmp connection
|
|
||||||
func (s *session) Write(data []byte) (int, error) {
|
|
||||||
if s.rtmp == nil {
|
|
||||||
return 0, Err(3)
|
|
||||||
}
|
|
||||||
if C.RTMP_IsConnected(s.rtmp) == 0 {
|
|
||||||
return 0, Err(1)
|
|
||||||
}
|
|
||||||
//if C.RTMP_Write(s.rtmp,(*C.char)(unsafe.Pointer(&data[0])),C.int(len(data))) == 0 {
|
|
||||||
if rtmpWrite(s.rtmp, data) == 0 {
|
|
||||||
return 0, Err(2)
|
|
||||||
}
|
|
||||||
return len(data), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// rtmpWrite writes data to the current rtmp connection encapsulated by r
|
// rtmpWrite writes data to the current rtmp connection encapsulated by r
|
||||||
func rtmpWrite(r *C.RTMP, data []byte) int {
|
func rtmpWrite(r *C.RTMP, data []byte) int {
|
||||||
buf := sliceToPtr(data)
|
buf := sliceToPtr(data)
|
||||||
|
@ -968,6 +1050,41 @@ func avQueue(vals **C.RTMP_METHOD, num *int, av *C.AVal, txn int) {
|
||||||
int(unsafe.Sizeof(rtmpMethodPtr))))).name.av_val = (*C.char)(tmp)
|
int(unsafe.Sizeof(rtmpMethodPtr))))).name.av_val = (*C.char)(tmp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func goStrToCStr(str string) *byte {
|
||||||
|
l := len(str)
|
||||||
|
slice := make([]byte, l+1)
|
||||||
|
ptr := unsafe.Pointer(&[]byte(str)[0])
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
slice[i] = *indxBytePtr(ptr, i)
|
||||||
|
}
|
||||||
|
slice[l] = '\000'
|
||||||
|
return slice
|
||||||
|
}
|
||||||
|
|
||||||
|
func strlen(str *byte) int32 {
|
||||||
|
for i := 0; true; i++ {
|
||||||
|
ptr = indxBytePtr(unsafe.Pointer(str), i)
|
||||||
|
if *ptr == '\000' {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func strchr(str *byte, val byte) *byte {
|
||||||
|
var ptr *byte
|
||||||
|
for i := 0; true; i++ {
|
||||||
|
ptr = indxBytePtr(unsafe.Pointer(str), i)
|
||||||
|
if *ptr == val {
|
||||||
|
return ptr
|
||||||
|
}
|
||||||
|
if *ptr == '\000' {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func allocate(nOfBytes uintptr) unsafe.Pointer {
|
func allocate(nOfBytes uintptr) unsafe.Pointer {
|
||||||
mem := make([]byte, int(nOfBytes))
|
mem := make([]byte, int(nOfBytes))
|
||||||
return unsafe.Pointer(&mem[0])
|
return unsafe.Pointer(&mem[0])
|
||||||
|
|
Loading…
Reference in New Issue