av/rtmp/RTMP.go

115 lines
3.2 KiB
Go

/*
NAME
RTMP.go
DESCRIPTION
See Readme.md
AUTHOR
Saxon Nelson-Milton <saxon@ausocean.org>
LICENSE
RTMP.go is Copyright (C) 2017 the Australian Ocean Lab (AusOcean)
It is free software: you can redistribute it and/or modify them
under the terms of the GNU General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
It is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with revid in gpl.txt. If not, see [GNU licenses](http://www.gnu.org/licenses).
*/
package rtmp
// #cgo CFLAGS: -I/home/pi/go/src/bitbucket.org/AusOcean/av/rtmp/
// #cgo CFLAGS: -I/home/pi/go/src/bitbucket.org/ausocean/av/rtmp/rtmp_c/librtmp
// #cgo LDFLAGS: /home/pi/go/src/bitbucket.org/ausocean/av/rtmp/rtmp_c/librtmp/librtmp.a
// #cgo LDFLAGS: -lssl -lcrypto -lz
// #include <RTMPWrapper.h>
import "C"
import (
"errors"
_ "fmt"
"sync"
"unsafe"
)
// RTMPSession provides a crude interface for sending flv tags over rtmp
type RTMPSession interface {
StartSession() error
WriteFrame(data []byte, dataLength uint) error
EndSession() error
}
// rtmpSession provides parameters required for an rtmp communication session
type rtmpSession struct {
url string
timeout uint
running bool
mutex *sync.Mutex
}
// NewRTMPSession returns a new instance of an rtmpSession struct
func NewRTMPSession(url string, connectTimeout uint) (session *rtmpSession) {
session = new(rtmpSession)
session.url = url
session.timeout = connectTimeout
session.mutex = &sync.Mutex{}
return
}
// StartSession establishes an rtmp connection with the url passed into the
// constructor
func (s *rtmpSession) StartSession() error {
if !s.running {
if !uintToBool(uint(C.RTMP_start_session(C.CString(s.url), C.uint(s.timeout)))) {
return errors.New("RTMP start error! Check rtmp log for details!")
}
s.running = true
} else {
return errors.New("Tried to start rtmp session, but already started!")
}
return nil
}
// WriteFrame writes a frame (flv tag) to the rtmp connection
// TODO: Remove mutex
func (s *rtmpSession) WriteFrame(data []byte, dataLength uint) error {
s.mutex.Lock()
defer s.mutex.Unlock()
if s.running {
dataCopy := make([]byte, len(data))
copy(dataCopy, data)
if !uintToBool(uint(C.RTMP_write_frame((*C.char)(unsafe.Pointer(&dataCopy[0])), C.uint(dataLength)))) {
return errors.New("RTMP write error! Check rtmp log for details!")
}
} else {
return errors.New("RTMP session not running, can't write!")
}
return nil
}
// EndSession terminates the rtmp connection
func (s *rtmpSession) EndSession() error {
if s.running {
if !uintToBool(uint(C.RTMP_end_session())) {
return errors.New("RTMP end session error! Check rtmp log for details!")
}
s.running = false
} else {
return errors.New("Tried to stop rtmp session, but not running!")
}
return nil
}
// uintToBool takes a uint and returns the bool equivalent
func uintToBool(x uint) bool {
return x != 0
}