/* NAME RTMP.go DESCRIPTION See Readme.md AUTHOR Saxon Nelson-Milton 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 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 }