mirror of https://bitbucket.org/ausocean/av.git
Merged in give-encoder-log (pull request #405)
container/mts: doing logging in MTS encoder Approved-by: Trek Hopton <trek.hopton@gmail.com>
This commit is contained in:
commit
77459d16da
|
@ -47,6 +47,14 @@ const (
|
||||||
audioStreamID = 0xc0 // ADPCM audio stream ID.
|
audioStreamID = 0xc0 // ADPCM audio stream ID.
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// These three constants are used to select between the three different
|
||||||
|
// methods of when the PSI is sent.
|
||||||
|
const (
|
||||||
|
pktBased = iota
|
||||||
|
timeBased
|
||||||
|
nalBased
|
||||||
|
)
|
||||||
|
|
||||||
// Constants used to communicate which media codec will be packetized.
|
// Constants used to communicate which media codec will be packetized.
|
||||||
const (
|
const (
|
||||||
EncodeH264 = iota
|
EncodeH264 = iota
|
||||||
|
@ -142,6 +150,14 @@ var (
|
||||||
pmtTable []byte
|
pmtTable []byte
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type logger interface {
|
||||||
|
Debug(string, ...interface{})
|
||||||
|
Info(string, ...interface{})
|
||||||
|
Warning(string, ...interface{})
|
||||||
|
Error(string, ...interface{})
|
||||||
|
Fatal(string, ...interface{})
|
||||||
|
}
|
||||||
|
|
||||||
// Encoder encapsulates properties of an MPEG-TS generator.
|
// Encoder encapsulates properties of an MPEG-TS generator.
|
||||||
type Encoder struct {
|
type Encoder struct {
|
||||||
dst io.WriteCloser
|
dst io.WriteCloser
|
||||||
|
@ -163,11 +179,14 @@ type Encoder struct {
|
||||||
startTime time.Time
|
startTime time.Time
|
||||||
mediaPid uint16
|
mediaPid uint16
|
||||||
streamID byte
|
streamID byte
|
||||||
|
|
||||||
|
// log is a function that will be used through the encoder code for logging.
|
||||||
|
log logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEncoder returns an Encoder with the specified media type and rate eg. if a video stream
|
// NewEncoder returns an Encoder with the specified media type and rate eg. if a video stream
|
||||||
// calls write for every frame, the rate will be the frame rate of the video.
|
// calls write for every frame, the rate will be the frame rate of the video.
|
||||||
func NewEncoder(dst io.WriteCloser, rate float64, mediaType int, options ...func(*Encoder) error) (*Encoder, error) {
|
func NewEncoder(dst io.WriteCloser, rate float64, mediaType int, log logger, options ...func(*Encoder) error) (*Encoder, error) {
|
||||||
var mPID uint16
|
var mPID uint16
|
||||||
var sID byte
|
var sID byte
|
||||||
psiM := timeBased
|
psiM := timeBased
|
||||||
|
@ -176,18 +195,22 @@ func NewEncoder(dst io.WriteCloser, rate float64, mediaType int, options ...func
|
||||||
mPID = AudioPid
|
mPID = AudioPid
|
||||||
sID = audioStreamID
|
sID = audioStreamID
|
||||||
psiM = pktBased
|
psiM = pktBased
|
||||||
|
log.Debug("configured for audio packetisation")
|
||||||
case EncodeH265:
|
case EncodeH265:
|
||||||
mPID = VideoPid
|
mPID = VideoPid
|
||||||
sID = H265ID
|
sID = H265ID
|
||||||
psiM = nalBased
|
psiM = nalBased
|
||||||
|
log.Debug("configured for h.265 packetisation")
|
||||||
case EncodeH264:
|
case EncodeH264:
|
||||||
mPID = VideoPid
|
mPID = VideoPid
|
||||||
sID = H264ID
|
sID = H264ID
|
||||||
psiM = nalBased
|
psiM = nalBased
|
||||||
|
log.Debug("configured for h.264 packetisation")
|
||||||
case EncodeMJPEG:
|
case EncodeMJPEG:
|
||||||
mPID = VideoPid
|
mPID = VideoPid
|
||||||
sID = MJPEGID
|
sID = MJPEGID
|
||||||
psiM = timeBased
|
psiM = timeBased
|
||||||
|
log.Debug("configured for MJPEG packetisation")
|
||||||
}
|
}
|
||||||
|
|
||||||
pmt := BasePMT
|
pmt := BasePMT
|
||||||
|
@ -204,22 +227,14 @@ func NewEncoder(dst io.WriteCloser, rate float64, mediaType int, options ...func
|
||||||
|
|
||||||
e := &Encoder{
|
e := &Encoder{
|
||||||
dst: dst,
|
dst: dst,
|
||||||
|
|
||||||
writePeriod: time.Duration(float64(time.Second) / rate),
|
writePeriod: time.Duration(float64(time.Second) / rate),
|
||||||
ptsOffset: ptsOffset,
|
ptsOffset: ptsOffset,
|
||||||
|
|
||||||
psiMethod: psiM,
|
psiMethod: psiM,
|
||||||
|
|
||||||
pktCount: 8,
|
pktCount: 8,
|
||||||
|
|
||||||
mediaPid: mPID,
|
mediaPid: mPID,
|
||||||
streamID: sID,
|
streamID: sID,
|
||||||
|
continuity: map[uint16]byte{PatPid: 0, PmtPid: 0, mPID: 0},
|
||||||
continuity: map[uint16]byte{
|
log: log,
|
||||||
PatPid: 0,
|
|
||||||
PmtPid: 0,
|
|
||||||
mPID: 0,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, option := range options {
|
for _, option := range options {
|
||||||
|
@ -228,17 +243,11 @@ func NewEncoder(dst io.WriteCloser, rate float64, mediaType int, options ...func
|
||||||
return nil, fmt.Errorf("option failed with error: %w", err)
|
return nil, fmt.Errorf("option failed with error: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
log.Debug("encoder options applied")
|
||||||
|
|
||||||
return e, nil
|
return e, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// These three constants are used to select between the three different
|
|
||||||
// methods of when the PSI is sent.
|
|
||||||
const (
|
|
||||||
pktBased = iota
|
|
||||||
timeBased
|
|
||||||
nalBased
|
|
||||||
)
|
|
||||||
|
|
||||||
// PacketBasedPSI is an option that can be passed to NewEncoder to select
|
// PacketBasedPSI is an option that can be passed to NewEncoder to select
|
||||||
// packet based PSI writing, i.e. PSI are written to the destination every
|
// packet based PSI writing, i.e. PSI are written to the destination every
|
||||||
// sendCount packets.
|
// sendCount packets.
|
||||||
|
@ -247,6 +256,7 @@ func PacketBasedPSI(sendCount int) func(*Encoder) error {
|
||||||
e.psiMethod = pktBased
|
e.psiMethod = pktBased
|
||||||
e.psiSendCount = sendCount
|
e.psiSendCount = sendCount
|
||||||
e.pktCount = e.psiSendCount
|
e.pktCount = e.psiSendCount
|
||||||
|
e.log.Debug("configured for packet based PSI insertion", "count", sendCount)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -260,6 +270,7 @@ func TimeBasedPSI(dur time.Duration) func(*Encoder) error {
|
||||||
e.psiTime = 0
|
e.psiTime = 0
|
||||||
e.psiSetTime = dur
|
e.psiSetTime = dur
|
||||||
e.startTime = time.Now()
|
e.startTime = time.Now()
|
||||||
|
e.log.Debug("configured for time based PSI insertion")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -269,6 +280,7 @@ func TimeBasedPSI(dur time.Duration) func(*Encoder) error {
|
||||||
func (e *Encoder) Write(data []byte) (int, error) {
|
func (e *Encoder) Write(data []byte) (int, error) {
|
||||||
switch e.psiMethod {
|
switch e.psiMethod {
|
||||||
case pktBased:
|
case pktBased:
|
||||||
|
e.log.Debug("checking packet no. conditions for PSI write", "count", e.pktCount, "PSI count", e.psiSendCount)
|
||||||
if e.pktCount >= e.psiSendCount {
|
if e.pktCount >= e.psiSendCount {
|
||||||
e.pktCount = 0
|
e.pktCount = 0
|
||||||
err := e.writePSI()
|
err := e.writePSI()
|
||||||
|
@ -281,7 +293,7 @@ func (e *Encoder) Write(data []byte) (int, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, fmt.Errorf("could not get type from NAL unit, failed with error: %w", err)
|
return 0, fmt.Errorf("could not get type from NAL unit, failed with error: %w", err)
|
||||||
}
|
}
|
||||||
|
e.log.Debug("checking conditions for PSI write", "AU type", nalType, "needed type", h264dec.NALTypeSPS)
|
||||||
if nalType == h264dec.NALTypeSPS {
|
if nalType == h264dec.NALTypeSPS {
|
||||||
err := e.writePSI()
|
err := e.writePSI()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -289,24 +301,26 @@ func (e *Encoder) Write(data []byte) (int, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case timeBased:
|
case timeBased:
|
||||||
if time.Now().Sub(e.startTime) >= e.psiTime {
|
dur := time.Now().Sub(e.startTime)
|
||||||
|
e.log.Debug("checking time conditions for PSI write")
|
||||||
|
if dur >= e.psiTime {
|
||||||
e.psiTime = e.psiSetTime
|
e.psiTime = e.psiSetTime
|
||||||
e.startTime = time.Now()
|
e.startTime = time.Now()
|
||||||
err := e.writePSI()
|
err := e.writePSI()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
panic("Undefined PSI method")
|
panic("undefined PSI method")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare PES data.
|
// Prepare PES data.
|
||||||
|
pts := e.pts()
|
||||||
pesPkt := pes.Packet{
|
pesPkt := pes.Packet{
|
||||||
StreamID: e.streamID,
|
StreamID: e.streamID,
|
||||||
PDI: hasPTS,
|
PDI: hasPTS,
|
||||||
PTS: e.pts(),
|
PTS: pts,
|
||||||
Data: data,
|
Data: data,
|
||||||
HeaderLength: 5,
|
HeaderLength: 5,
|
||||||
}
|
}
|
||||||
|
@ -329,7 +343,9 @@ func (e *Encoder) Write(data []byte) (int, error) {
|
||||||
if pusi {
|
if pusi {
|
||||||
// If the packet has a Payload Unit Start Indicator
|
// If the packet has a Payload Unit Start Indicator
|
||||||
// flag set then we need to write a PCR.
|
// flag set then we need to write a PCR.
|
||||||
pkt.PCR = e.pcr()
|
pcr := e.pcr()
|
||||||
|
e.log.Debug("new access unit", "PCR", pcr, "PTS", pts)
|
||||||
|
pkt.PCR = pcr
|
||||||
pusi = false
|
pusi = false
|
||||||
}
|
}
|
||||||
_, err := e.dst.Write(pkt.Bytes(e.tsSpace[:PacketSize]))
|
_, err := e.dst.Write(pkt.Bytes(e.tsSpace[:PacketSize]))
|
||||||
|
@ -360,7 +376,8 @@ func (e *Encoder) writePSI() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
e.pktCount++
|
e.pktCount++
|
||||||
pmtTable, err = updateMeta(pmtTable)
|
|
||||||
|
pmtTable, err = updateMeta(pmtTable, e.log)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -379,6 +396,8 @@ func (e *Encoder) writePSI() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
e.pktCount++
|
e.pktCount++
|
||||||
|
|
||||||
|
e.log.Debug("PSI written", "PAT CC", patPkt.CC, "PMT CC", pmtPkt.CC)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -407,15 +426,18 @@ func (e *Encoder) ccFor(pid uint16) byte {
|
||||||
|
|
||||||
// updateMeta adds/updates a metaData descriptor in the given psi bytes using data
|
// updateMeta adds/updates a metaData descriptor in the given psi bytes using data
|
||||||
// contained in the global Meta struct.
|
// contained in the global Meta struct.
|
||||||
func updateMeta(b []byte) ([]byte, error) {
|
func updateMeta(b []byte, log logger) ([]byte, error) {
|
||||||
p := psi.PSIBytes(b)
|
p := psi.PSIBytes(b)
|
||||||
if RealTime.IsSet() {
|
if RealTime.IsSet() {
|
||||||
Meta.Add("ts", strconv.Itoa(int(RealTime.Get().Unix())))
|
t := strconv.Itoa(int(RealTime.Get().Unix()))
|
||||||
|
Meta.Add("ts", t)
|
||||||
|
log.Debug("latest time added to meta", "time", t)
|
||||||
}
|
}
|
||||||
err := p.AddDescriptor(psi.MetadataTag, Meta.Encode())
|
err := p.AddDescriptor(psi.MetadataTag, Meta.Encode())
|
||||||
return []byte(p), err
|
return []byte(p), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) Close() error {
|
func (e *Encoder) Close() error {
|
||||||
|
e.log.Debug("closing encoder")
|
||||||
return e.dst.Close()
|
return e.dst.Close()
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,32 @@ func (d *destination) Write(p []byte) (int, error) {
|
||||||
return len(p), nil
|
return len(p), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// testLogger will allow logging to be done by the testing pkg.
|
||||||
|
type testLogger testing.T
|
||||||
|
|
||||||
|
func (tl *testLogger) Debug(msg string, args ...interface{}) { tl.log("debug", msg, args...) }
|
||||||
|
func (tl *testLogger) Info(msg string, args ...interface{}) { tl.log("info", msg, args...) }
|
||||||
|
func (tl *testLogger) Warning(msg string, args ...interface{}) { tl.log("warning", msg, args...) }
|
||||||
|
func (tl *testLogger) Error(msg string, args ...interface{}) { tl.log("error", msg, args...) }
|
||||||
|
func (tl *testLogger) Fatal(msg string, args ...interface{}) { tl.log("fatal", msg, args...) }
|
||||||
|
|
||||||
|
func (tl *testLogger) log(lvl string, msg string, args ...interface{}) {
|
||||||
|
switch lvl {
|
||||||
|
case "debug", "info", "warning", "error", "fatal":
|
||||||
|
default:
|
||||||
|
panic("invalid log level")
|
||||||
|
}
|
||||||
|
msg = lvl + ": " + msg
|
||||||
|
for i := 0; i < len(args); i++ {
|
||||||
|
msg += " %v"
|
||||||
|
}
|
||||||
|
if len(args) == 0 {
|
||||||
|
tl.Log(msg + "\n")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tl.Logf(msg+"\n", args)
|
||||||
|
}
|
||||||
|
|
||||||
// TestEncodeVideo checks that we can correctly encode some dummy data into a
|
// TestEncodeVideo checks that we can correctly encode some dummy data into a
|
||||||
// valid MPEG-TS stream. This checks for correct MPEG-TS headers and also that the
|
// valid MPEG-TS stream. This checks for correct MPEG-TS headers and also that the
|
||||||
// original data is stored correctly and is retreivable.
|
// original data is stored correctly and is retreivable.
|
||||||
|
@ -101,7 +127,7 @@ func TestEncodeVideo(t *testing.T) {
|
||||||
|
|
||||||
// Create the dst and write the test data to encoder.
|
// Create the dst and write the test data to encoder.
|
||||||
dst := &destination{}
|
dst := &destination{}
|
||||||
e, err := NewEncoder(nopCloser{dst}, 25, EncodeH264, PacketBasedPSI(psiSendCount))
|
e, err := NewEncoder(nopCloser{dst}, 25, EncodeH264, (*testLogger)(t), PacketBasedPSI(psiSendCount))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("could not create MTS encoder, failed with error: %v", err)
|
t.Fatalf("could not create MTS encoder, failed with error: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -165,7 +191,7 @@ func TestEncodePcm(t *testing.T) {
|
||||||
sampleSize := 2
|
sampleSize := 2
|
||||||
blockSize := 16000
|
blockSize := 16000
|
||||||
writeFreq := float64(sampleRate*sampleSize) / float64(blockSize)
|
writeFreq := float64(sampleRate*sampleSize) / float64(blockSize)
|
||||||
e, err := NewEncoder(nopCloser{&buf}, writeFreq, EncodeAudio)
|
e, err := NewEncoder(nopCloser{&buf}, writeFreq, EncodeAudio, (*testLogger)(t))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("could not create MTS encoder, failed with error: %v", err)
|
t.Fatalf("could not create MTS encoder, failed with error: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -269,7 +295,7 @@ const fps = 25
|
||||||
func TestMetaEncode1(t *testing.T) {
|
func TestMetaEncode1(t *testing.T) {
|
||||||
Meta = meta.New()
|
Meta = meta.New()
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
e, err := NewEncoder(nopCloser{&buf}, fps, EncodeH264)
|
e, err := NewEncoder(nopCloser{&buf}, fps, EncodeH264, (*testLogger)(t))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("could not create encoder, failed with error: %v", err)
|
t.Fatalf("could not create encoder, failed with error: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -301,7 +327,7 @@ func TestMetaEncode1(t *testing.T) {
|
||||||
func TestMetaEncode2(t *testing.T) {
|
func TestMetaEncode2(t *testing.T) {
|
||||||
Meta = meta.New()
|
Meta = meta.New()
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
e, err := NewEncoder(nopCloser{&buf}, fps, EncodeH264)
|
e, err := NewEncoder(nopCloser{&buf}, fps, EncodeH264, (*testLogger)(t))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("could not create MTS encoder, failed with error: %v", err)
|
t.Fatalf("could not create MTS encoder, failed with error: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -333,7 +359,7 @@ func TestMetaEncode2(t *testing.T) {
|
||||||
func TestExtractMeta(t *testing.T) {
|
func TestExtractMeta(t *testing.T) {
|
||||||
Meta = meta.New()
|
Meta = meta.New()
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
e, err := NewEncoder(nopCloser{&buf}, fps, EncodeH264)
|
e, err := NewEncoder(nopCloser{&buf}, fps, EncodeH264, (*testLogger)(t))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("could not create MTS encoder, failed with error: %v", err)
|
t.Fatalf("could not create MTS encoder, failed with error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -365,7 +365,7 @@ func TestTrimToMetaRange(t *testing.T) {
|
||||||
|
|
||||||
for i := 0; i < nPSI; i++ {
|
for i := 0; i < nPSI; i++ {
|
||||||
Meta.Add(key, strconv.Itoa((i*2)+1))
|
Meta.Add(key, strconv.Itoa((i*2)+1))
|
||||||
err := writePSIWithMeta(&clip)
|
err := writePSIWithMeta(&clip, t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("did not expect to get error writing PSI, error: %v", err)
|
t.Fatalf("did not expect to get error writing PSI, error: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -472,7 +472,7 @@ func TestSegmentForMeta(t *testing.T) {
|
||||||
} else {
|
} else {
|
||||||
Meta.Delete(key)
|
Meta.Delete(key)
|
||||||
}
|
}
|
||||||
err := writePSIWithMeta(&clip)
|
err := writePSIWithMeta(&clip, t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("did not expect to get error writing PSI, error: %v", err)
|
t.Fatalf("did not expect to get error writing PSI, error: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -668,7 +668,7 @@ func TestFindPSI(t *testing.T) {
|
||||||
}).Bytes()
|
}).Bytes()
|
||||||
|
|
||||||
Meta.Add(metaKey, test.meta)
|
Meta.Add(metaKey, test.meta)
|
||||||
pmtTable, err = updateMeta(pmtTable)
|
pmtTable, err = updateMeta(pmtTable, (*testLogger)(t))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("could not update meta for test %d", i)
|
t.Fatalf("could not update meta for test %d", i)
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ func TestExtract(t *testing.T) {
|
||||||
// We'll add the frame number as meta.
|
// We'll add the frame number as meta.
|
||||||
Meta.Add("frameNum", strconv.Itoa(i))
|
Meta.Add("frameNum", strconv.Itoa(i))
|
||||||
|
|
||||||
err = writePSIWithMeta(&clip)
|
err = writePSIWithMeta(&clip, t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("did not expect error writing psi: %v", err)
|
t.Fatalf("did not expect error writing psi: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -136,7 +136,7 @@ func TestExtract(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// writePSIWithMeta writes PSI to b with updated metadata.
|
// writePSIWithMeta writes PSI to b with updated metadata.
|
||||||
func writePSIWithMeta(b *bytes.Buffer) error {
|
func writePSIWithMeta(b *bytes.Buffer, t *testing.T) error {
|
||||||
// Write PAT.
|
// Write PAT.
|
||||||
pat := Packet{
|
pat := Packet{
|
||||||
PUSI: true,
|
PUSI: true,
|
||||||
|
@ -151,7 +151,7 @@ func writePSIWithMeta(b *bytes.Buffer) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the meta in the pmt table.
|
// Update the meta in the pmt table.
|
||||||
pmtTable, err = updateMeta(pmtTable)
|
pmtTable, err = updateMeta(pmtTable, (*testLogger)(t))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -202,7 +202,7 @@ func TestClipBytes(t *testing.T) {
|
||||||
// We'll add the frame number as meta.
|
// We'll add the frame number as meta.
|
||||||
Meta.Add("frameNum", strconv.Itoa(i))
|
Meta.Add("frameNum", strconv.Itoa(i))
|
||||||
|
|
||||||
err = writePSIWithMeta(&clip)
|
err = writePSIWithMeta(&clip, t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("did not expect error writing psi: %v", err)
|
t.Fatalf("did not expect error writing psi: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,6 +74,14 @@ type Logger interface {
|
||||||
Log(level int8, message string, params ...interface{})
|
Log(level int8, message string, params ...interface{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type encLog struct{ Logger }
|
||||||
|
|
||||||
|
func (el *encLog) Debug(msg string, args ...interface{}) { el.Log(logger.Debug, msg, args...) }
|
||||||
|
func (el *encLog) Info(msg string, args ...interface{}) { el.Log(logger.Info, msg, args...) }
|
||||||
|
func (el *encLog) Warning(msg string, args ...interface{}) { el.Log(logger.Warning, msg, args...) }
|
||||||
|
func (el *encLog) Error(msg string, args ...interface{}) { el.Log(logger.Error, msg, args...) }
|
||||||
|
func (el *encLog) Fatal(msg string, args ...interface{}) { el.Log(logger.Fatal, msg, args...) }
|
||||||
|
|
||||||
// Revid provides methods to control a revid session; providing methods
|
// Revid provides methods to control a revid session; providing methods
|
||||||
// to start, stop and change the state of an instance using the Config struct.
|
// to start, stop and change the state of an instance using the Config struct.
|
||||||
type Revid struct {
|
type Revid struct {
|
||||||
|
@ -117,7 +125,7 @@ type Revid struct {
|
||||||
// bitrate is used for bitrate calculations.
|
// bitrate is used for bitrate calculations.
|
||||||
bitrate bitrate.Calculator
|
bitrate bitrate.Calculator
|
||||||
|
|
||||||
// stop used used to signal stopping when looping an input.
|
// stop is used to signal stopping when looping an input.
|
||||||
stop chan struct{}
|
stop chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,7 +222,7 @@ func (r *Revid) reset(c config.Config) error {
|
||||||
panic("unknown input type")
|
panic("unknown input type")
|
||||||
}
|
}
|
||||||
|
|
||||||
return mts.NewEncoder(dst, float64(fps), st, encOptions...)
|
return mts.NewEncoder(dst, float64(fps), st, &encLog{r.cfg.Logger}, encOptions...)
|
||||||
},
|
},
|
||||||
func(dst io.WriteCloser, fps int) (io.WriteCloser, error) {
|
func(dst io.WriteCloser, fps int) (io.WriteCloser, error) {
|
||||||
return flv.NewEncoder(dst, true, true, fps)
|
return flv.NewEncoder(dst, true, true, fps)
|
||||||
|
|
|
@ -51,7 +51,7 @@ func TestRaspivid(t *testing.T) {
|
||||||
t.Skip("Skipping TestRaspivid since no raspivid found.")
|
t.Skip("Skipping TestRaspivid since no raspivid found.")
|
||||||
}
|
}
|
||||||
|
|
||||||
var logger testLogger
|
var logger simpleLogger
|
||||||
ns, err := netsender.New(&logger, nil, nil, nil)
|
ns, err := netsender.New(&logger, nil, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("netsender.New failed with error %v", err)
|
t.Errorf("netsender.New failed with error %v", err)
|
||||||
|
@ -72,12 +72,12 @@ func TestRaspivid(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// testLogger implements a netsender.Logger.
|
// simpleLogger implements a netsender.Logger.
|
||||||
type testLogger struct{}
|
type simpleLogger struct{}
|
||||||
|
|
||||||
func (tl *testLogger) SetLevel(level int8) {}
|
func (tl *simpleLogger) SetLevel(level int8) {}
|
||||||
|
|
||||||
func (tl *testLogger) Log(level int8, msg string, params ...interface{}) {
|
func (tl *simpleLogger) Log(level int8, msg string, params ...interface{}) {
|
||||||
logLevels := [...]string{"Debug", "Info", "Warn", "Error", "", "", "Fatal"}
|
logLevels := [...]string{"Debug", "Info", "Warn", "Error", "", "", "Fatal"}
|
||||||
if level < -1 || level > 5 {
|
if level < -1 || level > 5 {
|
||||||
panic("Invalid log level")
|
panic("Invalid log level")
|
||||||
|
@ -216,7 +216,7 @@ func TestResetEncoderSenderSetup(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
rv, err := New(config.Config{Logger: &testLogger{}}, nil)
|
rv, err := New(config.Config{Logger: &simpleLogger{}}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected err: %v", err)
|
t.Fatalf("unexpected err: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -225,7 +225,7 @@ func TestResetEncoderSenderSetup(t *testing.T) {
|
||||||
for testNum, test := range tests {
|
for testNum, test := range tests {
|
||||||
// Create a new config and reset revid with it.
|
// Create a new config and reset revid with it.
|
||||||
const dummyURL = "rtmp://dummy"
|
const dummyURL = "rtmp://dummy"
|
||||||
c := config.Config{Logger: &testLogger{}, Outputs: test.outputs, RTMPURL: dummyURL}
|
c := config.Config{Logger: &simpleLogger{}, Outputs: test.outputs, RTMPURL: dummyURL}
|
||||||
err := rv.setConfig(c)
|
err := rv.setConfig(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v for test %v", err, testNum)
|
t.Fatalf("unexpected error: %v for test %v", err, testNum)
|
||||||
|
|
|
@ -98,10 +98,16 @@ func (ts *destination) Write(d []byte) (int, error) {
|
||||||
|
|
||||||
func (ts *destination) Close() error { return nil }
|
func (ts *destination) Close() error { return nil }
|
||||||
|
|
||||||
// dummyLogger will allow logging to be done by the testing pkg.
|
// testLogger will allow logging to be done by the testing pkg.
|
||||||
type dummyLogger testing.T
|
type testLogger testing.T
|
||||||
|
|
||||||
func (dl *dummyLogger) log(lvl int8, msg string, args ...interface{}) {
|
func (tl *testLogger) Debug(msg string, args ...interface{}) { tl.log(logger.Debug, msg, args...) }
|
||||||
|
func (tl *testLogger) Info(msg string, args ...interface{}) { tl.log(logger.Info, msg, args...) }
|
||||||
|
func (tl *testLogger) Warning(msg string, args ...interface{}) { tl.log(logger.Warning, msg, args...) }
|
||||||
|
func (tl *testLogger) Error(msg string, args ...interface{}) { tl.log(logger.Error, msg, args...) }
|
||||||
|
func (tl *testLogger) Fatal(msg string, args ...interface{}) { tl.log(logger.Fatal, msg, args...) }
|
||||||
|
|
||||||
|
func (dl *testLogger) log(lvl int8, msg string, args ...interface{}) {
|
||||||
var l string
|
var l string
|
||||||
switch lvl {
|
switch lvl {
|
||||||
case logger.Warning:
|
case logger.Warning:
|
||||||
|
@ -136,10 +142,10 @@ func TestMTSSenderSegment(t *testing.T) {
|
||||||
dst := &destination{t: t, done: make(chan struct{}), doneAt: numberOfClips}
|
dst := &destination{t: t, done: make(chan struct{}), doneAt: numberOfClips}
|
||||||
const testRBCapacity = 50000000
|
const testRBCapacity = 50000000
|
||||||
nElements := testRBCapacity / rbStartingElementSize
|
nElements := testRBCapacity / rbStartingElementSize
|
||||||
sender := newMTSSender(dst, (*dummyLogger)(t).log, ring.NewBuffer(nElements, rbStartingElementSize, 0), 0)
|
sender := newMTSSender(dst, (*testLogger)(t).log, ring.NewBuffer(nElements, rbStartingElementSize, 0), 0)
|
||||||
|
|
||||||
const psiSendCount = 10
|
const psiSendCount = 10
|
||||||
encoder, err := mts.NewEncoder(sender, 25, mts.EncodeH264, mts.PacketBasedPSI(psiSendCount))
|
encoder, err := mts.NewEncoder(sender, 25, mts.EncodeH264, (*testLogger)(t), mts.PacketBasedPSI(psiSendCount))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("could not create MTS encoder, failed with error: %v", err)
|
t.Fatalf("could not create MTS encoder, failed with error: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -217,10 +223,10 @@ func TestMtsSenderFailedSend(t *testing.T) {
|
||||||
dst := &destination{t: t, testFails: true, failAt: clipToFailAt, done: make(chan struct{})}
|
dst := &destination{t: t, testFails: true, failAt: clipToFailAt, done: make(chan struct{})}
|
||||||
const testRBCapacity = 50000000 // 50MB
|
const testRBCapacity = 50000000 // 50MB
|
||||||
nElements := testRBCapacity / rbStartingElementSize
|
nElements := testRBCapacity / rbStartingElementSize
|
||||||
sender := newMTSSender(dst, (*dummyLogger)(t).log, ring.NewBuffer(nElements, rbStartingElementSize, 0), 0)
|
sender := newMTSSender(dst, (*testLogger)(t).log, ring.NewBuffer(nElements, rbStartingElementSize, 0), 0)
|
||||||
|
|
||||||
const psiSendCount = 10
|
const psiSendCount = 10
|
||||||
encoder, err := mts.NewEncoder(sender, 25, mts.EncodeH264, mts.PacketBasedPSI(psiSendCount))
|
encoder, err := mts.NewEncoder(sender, 25, mts.EncodeH264, (*testLogger)(t), mts.PacketBasedPSI(psiSendCount))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("could not create MTS encoder, failed with error: %v", err)
|
t.Fatalf("could not create MTS encoder, failed with error: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -298,10 +304,10 @@ func TestMtsSenderDiscontinuity(t *testing.T) {
|
||||||
// Create destination, the mtsSender and the mtsEncoder.
|
// Create destination, the mtsSender and the mtsEncoder.
|
||||||
const clipToDelay = 3
|
const clipToDelay = 3
|
||||||
dst := &destination{t: t, sendDelay: 10 * time.Millisecond, delayAt: clipToDelay, done: make(chan struct{})}
|
dst := &destination{t: t, sendDelay: 10 * time.Millisecond, delayAt: clipToDelay, done: make(chan struct{})}
|
||||||
sender := newMTSSender(dst, (*dummyLogger)(t).log, ring.NewBuffer(1, rbStartingElementSize, 0), 0)
|
sender := newMTSSender(dst, (*testLogger)(t).log, ring.NewBuffer(1, rbStartingElementSize, 0), 0)
|
||||||
|
|
||||||
const psiSendCount = 10
|
const psiSendCount = 10
|
||||||
encoder, err := mts.NewEncoder(sender, 25, mts.EncodeH264, mts.PacketBasedPSI(psiSendCount))
|
encoder, err := mts.NewEncoder(sender, 25, mts.EncodeH264, (*testLogger)(t), mts.PacketBasedPSI(psiSendCount))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("could not create MTS encoder, failed with error: %v", err)
|
t.Fatalf("could not create MTS encoder, failed with error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue