mirror of https://bitbucket.org/ausocean/av.git
container/mts: wrote test for FindPSI and corrected bugs
Wrote the FindPSI test which revealed a bug regarding creation of a PMT using comcast gots. This was fixed by writing Payload function and extracting payload of PMT packet before giving to psi.NewPMT.
This commit is contained in:
parent
0825799cfa
commit
c55cd9a64e
|
@ -648,7 +648,11 @@ func Programs(p []byte) (map[uint16]uint16, error) {
|
|||
|
||||
// Streams returns elementary streams defined in a given MPEG-TS PMT packet.
|
||||
func Streams(p []byte) ([]gotspsi.PmtElementaryStream, error) {
|
||||
pmt, err := gotspsi.NewPMT(p)
|
||||
payload, err := Payload(p)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "cannot get packet payload")
|
||||
}
|
||||
pmt, err := gotspsi.NewPMT(payload)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -701,3 +705,23 @@ func pmtPIDs(m map[uint16]uint16) []uint16 {
|
|||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// Errors used by Payload.
|
||||
var ErrNoPayload = errors.New("no payload")
|
||||
|
||||
// Payload returns the payload of an MPEG-TS packet p.
|
||||
// NB: this is not a copy of the payload in the interest of performance.
|
||||
// TODO: offer function that will do copy if we have interests in safety.
|
||||
func Payload(p []byte) ([]byte, error) {
|
||||
c := byte((p[3] & 0x30) >> 4)
|
||||
if c == 2 {
|
||||
return nil, ErrNoPayload
|
||||
}
|
||||
|
||||
// Check if there is an adaptation field.
|
||||
off := 4
|
||||
if p[3]&0x20 == 1 {
|
||||
off = int(5 + p[4])
|
||||
}
|
||||
return p[off:], nil
|
||||
}
|
||||
|
|
|
@ -35,10 +35,13 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/Comcast/gots/packet"
|
||||
gotspsi "github.com/Comcast/gots/psi"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"bitbucket.org/ausocean/av/container/mts/meta"
|
||||
"bitbucket.org/ausocean/av/container/mts/pes"
|
||||
"bitbucket.org/ausocean/av/container/mts/psi"
|
||||
"github.com/Comcast/gots/packet"
|
||||
)
|
||||
|
||||
// TestGetPTSRange checks that GetPTSRange can correctly get the first and last
|
||||
|
@ -530,3 +533,195 @@ func scale(x, y int) rng {
|
|||
((y * 2) + 1) * PacketSize,
|
||||
}
|
||||
}
|
||||
|
||||
func TestFindPSI(t *testing.T) {
|
||||
const (
|
||||
pat = iota
|
||||
pmt
|
||||
media
|
||||
)
|
||||
|
||||
const (
|
||||
metaKey = "key"
|
||||
mediaType = gotspsi.PmtStreamTypeMpeg4Video
|
||||
pmtPID = 3
|
||||
streamPID = 4
|
||||
)
|
||||
|
||||
type want struct {
|
||||
idx int
|
||||
streamType uint8
|
||||
streamPID uint16
|
||||
meta map[string]string
|
||||
err error
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
pkts []int
|
||||
meta string
|
||||
want want
|
||||
}{
|
||||
{
|
||||
pkts: []int{pat, pmt, media, media},
|
||||
meta: "1",
|
||||
want: want{
|
||||
idx: 0,
|
||||
streamType: gotspsi.PmtStreamTypeMpeg4Video,
|
||||
streamPID: 4,
|
||||
meta: map[string]string{
|
||||
"key": "1",
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var clip bytes.Buffer
|
||||
var err error
|
||||
Meta = meta.New()
|
||||
|
||||
for i, test := range tests {
|
||||
// Generate MTS packets for this test.
|
||||
clip.Reset()
|
||||
|
||||
for _, pkt := range test.pkts {
|
||||
switch pkt {
|
||||
case pat:
|
||||
patTable := (&psi.PSI{
|
||||
Pf: 0x00,
|
||||
Tid: 0x00,
|
||||
Ssi: true,
|
||||
Pb: false,
|
||||
Sl: 0x0d,
|
||||
Tss: &psi.TSS{
|
||||
Tide: 0x01,
|
||||
V: 0,
|
||||
Cni: true,
|
||||
Sn: 0,
|
||||
Lsn: 0,
|
||||
Sd: &psi.PAT{
|
||||
Pn: 0x01,
|
||||
Pmpid: pmtPID,
|
||||
},
|
||||
},
|
||||
}).Bytes()
|
||||
|
||||
pat := Packet{
|
||||
PUSI: true,
|
||||
PID: PatPid,
|
||||
CC: 0,
|
||||
AFC: HasPayload,
|
||||
Payload: psi.AddPadding(patTable),
|
||||
}
|
||||
_, err := clip.Write(pat.Bytes(nil))
|
||||
if err != nil {
|
||||
t.Fatalf("could not write PAT to clip for test %d", i)
|
||||
}
|
||||
case pmt:
|
||||
pmtTable := (&psi.PSI{
|
||||
Pf: 0x00,
|
||||
Tid: 0x02,
|
||||
Ssi: true,
|
||||
Sl: 0x12,
|
||||
Tss: &psi.TSS{
|
||||
Tide: 0x01,
|
||||
V: 0,
|
||||
Cni: true,
|
||||
Sn: 0,
|
||||
Lsn: 0,
|
||||
Sd: &psi.PMT{
|
||||
Pcrpid: 0x0100,
|
||||
Pil: 0,
|
||||
Essd: &psi.ESSD{
|
||||
St: mediaType,
|
||||
Epid: streamPID,
|
||||
Esil: 0x00,
|
||||
},
|
||||
},
|
||||
},
|
||||
}).Bytes()
|
||||
|
||||
Meta.Add(metaKey, test.meta)
|
||||
pmtTable, err = updateMeta(pmtTable)
|
||||
if err != nil {
|
||||
t.Fatalf("could not update meta for test %d", i)
|
||||
}
|
||||
|
||||
pmt := Packet{
|
||||
PUSI: true,
|
||||
PID: pmtPID,
|
||||
CC: 0,
|
||||
AFC: HasPayload,
|
||||
Payload: psi.AddPadding(pmtTable),
|
||||
}
|
||||
_, err = clip.Write(pmt.Bytes(nil))
|
||||
if err != nil {
|
||||
t.Fatalf("could not write PMT to clip for test %d", i)
|
||||
}
|
||||
case media:
|
||||
pesPkt := pes.Packet{
|
||||
StreamID: mediaType,
|
||||
PDI: hasPTS,
|
||||
Data: []byte{},
|
||||
HeaderLength: 5,
|
||||
}
|
||||
buf := pesPkt.Bytes(nil)
|
||||
|
||||
pkt := Packet{
|
||||
PUSI: true,
|
||||
PID: uint16(streamPID),
|
||||
RAI: true,
|
||||
CC: 0,
|
||||
AFC: hasAdaptationField | hasPayload,
|
||||
PCRF: true,
|
||||
}
|
||||
pkt.FillPayload(buf)
|
||||
|
||||
_, err := clip.Write(pkt.Bytes(nil))
|
||||
if err != nil {
|
||||
t.Fatalf("did not expect clip write error: %v", err)
|
||||
}
|
||||
default:
|
||||
t.Fatalf("undefined pkt type %d in test %d", pkt, i)
|
||||
}
|
||||
}
|
||||
|
||||
gotIdx, gotStreams, gotMeta, gotErr := FindPSI(clip.Bytes())
|
||||
|
||||
// Check error
|
||||
if errors.Cause(gotErr) != test.want.err {
|
||||
t.Errorf("did not get expected error for test %d\nGot: %v\nWant: %v\n", i, gotErr, test.want.err)
|
||||
}
|
||||
|
||||
// Check idx
|
||||
if gotIdx != test.want.idx {
|
||||
t.Errorf("did not get expected idx for test %d\nGot: %v\nWant: %v\n", i, gotIdx, test.want.idx)
|
||||
}
|
||||
|
||||
// Check stream type and PID
|
||||
if gotStreams == nil {
|
||||
t.Fatalf("gotStreams should not be nil")
|
||||
}
|
||||
|
||||
if len(gotStreams) == 0 {
|
||||
t.Fatalf("gotStreams should not be 0 length")
|
||||
}
|
||||
|
||||
s := gotStreams[0]
|
||||
gotStreamType := s.StreamType()
|
||||
gotStreamPID := s.ElementaryPid()
|
||||
|
||||
if gotStreamType != test.want.streamType {
|
||||
t.Errorf("did not get expected stream type for test %d\nGot: %v\nWant: %v\n", i, gotStreamType, test.want.streamType)
|
||||
}
|
||||
|
||||
if gotStreamPID != test.want.streamPID {
|
||||
t.Errorf("did not get expected stream PID for test %d\nGot: %v\nWant: %v\n", i, gotStreamPID, test.want.streamPID)
|
||||
}
|
||||
|
||||
// Check meta
|
||||
if !reflect.DeepEqual(gotMeta, test.want.meta) {
|
||||
t.Errorf("did not get expected meta for test %d\nGot: %v\nWant: %v\n", i, gotMeta, test.want.meta)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue