mirror of https://bitbucket.org/ausocean/av.git
revid: senders are now io.Writers
Added a Write method to senders such that they implement io.Writer. The multiSender now takes a slice of io.writers. Also modified revid code and tests to account for this chance.
This commit is contained in:
parent
7c31f6fd6c
commit
3896a5e804
|
@ -184,12 +184,12 @@ func (r *Revid) setupPipeline(mtsEnc func(io.Writer, int) io.Writer, flvEnc func
|
||||||
|
|
||||||
// mtsSenders will hold the senders the require MPEGTS encoding, and flvSenders
|
// mtsSenders will hold the senders the require MPEGTS encoding, and flvSenders
|
||||||
// will hold senders that require FLV encoding.
|
// will hold senders that require FLV encoding.
|
||||||
var mtsSenders, flvSenders []loadSender
|
var mtsSenders, flvSenders []io.Writer
|
||||||
|
|
||||||
// We will go through our outputs and create the corresponding senders to add
|
// We will go through our outputs and create the corresponding senders to add
|
||||||
// to mtsSenders if the output requires MPEGTS encoding, or flvSenders if the
|
// to mtsSenders if the output requires MPEGTS encoding, or flvSenders if the
|
||||||
// output requires FLV encoding.
|
// output requires FLV encoding.
|
||||||
var sender loadSender
|
var sender io.Writer
|
||||||
for _, out := range r.config.Outputs {
|
for _, out := range r.config.Outputs {
|
||||||
switch out {
|
switch out {
|
||||||
case Http:
|
case Http:
|
||||||
|
|
|
@ -278,7 +278,7 @@ func TestResetEncoderSenderSetup(t *testing.T) {
|
||||||
ok := false
|
ok := false
|
||||||
for _, dst := range senders {
|
for _, dst := range senders {
|
||||||
// Get type of sender.
|
// Get type of sender.
|
||||||
senderType, err := typeOfSender(dst)
|
senderType, err := typeOfSender(dst.(loadSender))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("could not get encoders type for test %v, failed with err: %v", testNum, err)
|
t.Fatalf("could not get encoders type for test %v, failed with err: %v", testNum, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ package revid
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -58,12 +59,12 @@ type Log func(level int8, message string, params ...interface{})
|
||||||
// multiSender implements io.Writer. It provides the capacity to send to multiple
|
// multiSender implements io.Writer. It provides the capacity to send to multiple
|
||||||
// senders from a single Write call.
|
// senders from a single Write call.
|
||||||
type multiSender struct {
|
type multiSender struct {
|
||||||
senders []loadSender
|
senders []io.Writer
|
||||||
log Log
|
log Log
|
||||||
}
|
}
|
||||||
|
|
||||||
// newMultiSender returns a pointer to a new multiSender.
|
// newMultiSender returns a pointer to a new multiSender.
|
||||||
func newMultiSender(senders []loadSender, log Log) *multiSender {
|
func newMultiSender(senders []io.Writer, log Log) *multiSender {
|
||||||
return &multiSender{
|
return &multiSender{
|
||||||
senders: senders,
|
senders: senders,
|
||||||
log: log,
|
log: log,
|
||||||
|
@ -74,14 +75,17 @@ func newMultiSender(senders []loadSender, log Log) *multiSender {
|
||||||
// and release on all senders of multiSender.
|
// and release on all senders of multiSender.
|
||||||
func (s *multiSender) Write(d []byte) (int, error) {
|
func (s *multiSender) Write(d []byte) (int, error) {
|
||||||
for i, sender := range s.senders {
|
for i, sender := range s.senders {
|
||||||
sender.load(d)
|
_, err := sender.Write(d)
|
||||||
err := sender.send()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log(logger.Warning, pkg+"send failed", "sender", i, "error", err)
|
s.log(logger.Warning, pkg+"send failed", "sender", i, "error", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, sender := range s.senders {
|
for _, sender := range s.senders {
|
||||||
sender.release()
|
s, ok := sender.(loadSender)
|
||||||
|
if !ok {
|
||||||
|
panic("sender is not a loadSender")
|
||||||
|
}
|
||||||
|
s.release()
|
||||||
}
|
}
|
||||||
return len(d), nil
|
return len(d), nil
|
||||||
}
|
}
|
||||||
|
@ -109,13 +113,8 @@ func (s *minimalHttpSender) send(d []byte) error {
|
||||||
// When a loadSender has finished using the *ring.Chunk
|
// When a loadSender has finished using the *ring.Chunk
|
||||||
// it must be Closed.
|
// it must be Closed.
|
||||||
type loadSender interface {
|
type loadSender interface {
|
||||||
// load assigns the *ring.Chunk to the loadSender.
|
|
||||||
// The load call may fail, but must not mutate the
|
|
||||||
// the chunk.
|
|
||||||
load(d []byte) error
|
load(d []byte) error
|
||||||
|
|
||||||
// send performs a destination-specific send
|
|
||||||
// operation. It must not mutate the chunk.
|
|
||||||
send() error
|
send() error
|
||||||
|
|
||||||
// release releases the *ring.Chunk.
|
// release releases the *ring.Chunk.
|
||||||
|
@ -137,7 +136,19 @@ type fileSender struct {
|
||||||
data []byte
|
data []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func newFileSender(path string) (*fileSender, error) {
|
func (s *fileSender) Write(d []byte) (int, error) {
|
||||||
|
err := s.load(d)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
err = s.send()
|
||||||
|
if err != nil {
|
||||||
|
return len(d), err
|
||||||
|
}
|
||||||
|
return len(d), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func newFileSender(path string) (io.Writer, error) {
|
||||||
f, err := os.Create(path)
|
f, err := os.Create(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -174,6 +185,10 @@ type mtsSender struct {
|
||||||
curPid int
|
curPid int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *mtsSender) Write(d []byte) (int, error) {
|
||||||
|
return write(s, d)
|
||||||
|
}
|
||||||
|
|
||||||
// newMtsSender returns a new mtsSender.
|
// newMtsSender returns a new mtsSender.
|
||||||
func newMtsSender(s Sender, log func(lvl int8, msg string, args ...interface{})) *mtsSender {
|
func newMtsSender(s Sender, log func(lvl int8, msg string, args ...interface{})) *mtsSender {
|
||||||
return &mtsSender{
|
return &mtsSender{
|
||||||
|
@ -357,6 +372,10 @@ func newRtmpSender(url string, timeout uint, retries int, log func(lvl int8, msg
|
||||||
return s, err
|
return s, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *rtmpSender) Write(d []byte) (int, error) {
|
||||||
|
return write(s, d)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *rtmpSender) load(d []byte) error {
|
func (s *rtmpSender) load(d []byte) error {
|
||||||
s.data = d
|
s.data = d
|
||||||
return nil
|
return nil
|
||||||
|
@ -406,6 +425,10 @@ type rtpSender struct {
|
||||||
data []byte
|
data []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *rtpSender) Write(d []byte) (int, error) {
|
||||||
|
return write(s, d)
|
||||||
|
}
|
||||||
|
|
||||||
func newRtpSender(addr string, log func(lvl int8, msg string, args ...interface{}), fps uint) (*rtpSender, error) {
|
func newRtpSender(addr string, log func(lvl int8, msg string, args ...interface{}), fps uint) (*rtpSender, error) {
|
||||||
conn, err := net.Dial("udp", addr)
|
conn, err := net.Dial("udp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -432,3 +455,15 @@ func (s *rtpSender) send() error {
|
||||||
_, err := s.encoder.Write(s.data)
|
_, err := s.encoder.Write(s.data)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func write(s loadSender, d []byte) (int, error) {
|
||||||
|
err := s.load(d)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
err = s.send()
|
||||||
|
if err != nil {
|
||||||
|
return len(d), err
|
||||||
|
}
|
||||||
|
return len(d), nil
|
||||||
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ package revid
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
@ -271,6 +272,10 @@ func newDummyLoadSender(fail bool, retry bool) *dummyLoadSender {
|
||||||
return &dummyLoadSender{failOnSend: fail, failHandled: true, retry: retry}
|
return &dummyLoadSender{failOnSend: fail, failHandled: true, retry: retry}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *dummyLoadSender) Write(d []byte) (int, error) {
|
||||||
|
return write(s, d)
|
||||||
|
}
|
||||||
|
|
||||||
// load takes a byte slice and assigns it to the dummyLoadSenders data slice.
|
// load takes a byte slice and assigns it to the dummyLoadSenders data slice.
|
||||||
func (s *dummyLoadSender) load(d []byte) error {
|
func (s *dummyLoadSender) load(d []byte) error {
|
||||||
s.data = d
|
s.data = d
|
||||||
|
@ -315,7 +320,7 @@ func (s *dummyLoadSender) retrySend() bool { return s.retry }
|
||||||
// TestMultiSenderWrite checks that we can do basic writing to multiple senders
|
// TestMultiSenderWrite checks that we can do basic writing to multiple senders
|
||||||
// using the multiSender.
|
// using the multiSender.
|
||||||
func TestMultiSenderWrite(t *testing.T) {
|
func TestMultiSenderWrite(t *testing.T) {
|
||||||
senders := []loadSender{
|
senders := []io.Writer{
|
||||||
newDummyLoadSender(false, false),
|
newDummyLoadSender(false, false),
|
||||||
newDummyLoadSender(false, false),
|
newDummyLoadSender(false, false),
|
||||||
newDummyLoadSender(false, false),
|
newDummyLoadSender(false, false),
|
||||||
|
|
Loading…
Reference in New Issue