diff --git a/container/mts/encoder_test.go b/container/mts/encoder_test.go new file mode 100644 index 00000000..f785930d --- /dev/null +++ b/container/mts/encoder_test.go @@ -0,0 +1,144 @@ +/* +NAME + audio_test.go + +AUTHOR + Trek Hopton + +LICENSE + audio_test.go is Copyright (C) 2017-2019 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 in gpl.txt. + If not, see http://www.gnu.org/licenses. +*/ + +package mts + +import ( + "bytes" + "io" + "io/ioutil" + "testing" + + "github.com/Comcast/gots/packet" + "github.com/Comcast/gots/pes" + + "bitbucket.org/ausocean/av/container/mts/meta" +) + +type nopCloser struct{ io.Writer } + +func (nopCloser) Close() error { return nil } + +// TestEncodePcm tests the mpegts encoder's ability to encode pcm audio data. +// It reads and encodes input pcm data into mpegts, then decodes the mpegts and compares the result to the input pcm. +func TestEncodePcm(t *testing.T) { + Meta = meta.New() + + var buf bytes.Buffer + sampleRate := 48000 + sampleSize := 2 + blockSize := 16000 + writeFreq := float64(sampleRate*sampleSize) / float64(blockSize) + e := NewEncoder(nopCloser{&buf}, writeFreq, Audio) + + inPath := "../../../test/test-data/av/input/sweep_400Hz_20000Hz_-3dBFS_5s_48khz.pcm" + inPcm, err := ioutil.ReadFile(inPath) + if err != nil { + t.Errorf("unable to read file: %v", err) + } + + // Break pcm into blocks and encode to mts and get the resulting bytes. + for i := 0; i < len(inPcm); i += blockSize { + if len(inPcm)-i < blockSize { + block := inPcm[i:] + _, err = e.Write(block) + if err != nil { + t.Errorf("unable to write block: %v", err) + } + } else { + block := inPcm[i : i+blockSize] + _, err = e.Write(block) + if err != nil { + t.Errorf("unable to write block: %v", err) + } + } + } + clip := buf.Bytes() + + // Get the first MTS packet to check + var pkt packet.Packet + pesPacket := make([]byte, 0, blockSize) + got := make([]byte, 0, len(inPcm)) + i := 0 + if i+PacketSize <= len(clip) { + copy(pkt[:], clip[i:i+PacketSize]) + } + + // Loop through MTS packets until all the audio data from PES packets has been retrieved + for i+PacketSize <= len(clip) { + + // Check MTS packet + if !(pkt.PID() == audioPid) { + i += PacketSize + if i+PacketSize <= len(clip) { + copy(pkt[:], clip[i:i+PacketSize]) + } + continue + } + if !pkt.PayloadUnitStartIndicator() { + i += PacketSize + if i+PacketSize <= len(clip) { + copy(pkt[:], clip[i:i+PacketSize]) + } + } else { + // Copy the first MTS payload + payload, err := pkt.Payload() + if err != nil { + t.Errorf("unable to get MTS payload: %v", err) + } + pesPacket = append(pesPacket, payload...) + + i += PacketSize + if i+PacketSize <= len(clip) { + copy(pkt[:], clip[i:i+PacketSize]) + } + + // Copy the rest of the MTS payloads that are part of the same PES packet + for (!pkt.PayloadUnitStartIndicator()) && i+PacketSize <= len(clip) { + payload, err = pkt.Payload() + if err != nil { + t.Errorf("unable to get MTS payload: %v", err) + } + pesPacket = append(pesPacket, payload...) + + i += PacketSize + if i+PacketSize <= len(clip) { + copy(pkt[:], clip[i:i+PacketSize]) + } + } + } + // Get the audio data from the current PES packet + pesHeader, err := pes.NewPESHeader(pesPacket) + if err != nil { + t.Errorf("unable to read PES packet: %v", err) + } + got = append(got, pesHeader.Data()...) + pesPacket = pesPacket[:0] + } + + // Compare data from MTS with original data. + if !bytes.Equal(got, inPcm) { + t.Error("data decoded from mts did not match input data") + } +}