From 4807b4fcb6a736852390e21acd431fdd870ed26b Mon Sep 17 00:00:00 2001 From: Saxon Date: Wed, 24 Jul 2019 00:17:57 +0930 Subject: [PATCH 1/6] container/mts/mpegts.go: added some commenting to MediaStreams --- container/mts/mpegts.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/container/mts/mpegts.go b/container/mts/mpegts.go index f2a9ae0b..420f6842 100644 --- a/container/mts/mpegts.go +++ b/container/mts/mpegts.go @@ -636,6 +636,20 @@ func Streams(p []byte) ([]gotspsi.PmtElementaryStream, error) { // after. We also assume that this MPEG-TS stream contains just one program, // but this program may contain different streams, i.e. a video stream + audio // stream. +// +// A gotspsi.PmtElementaryStream will give stream type from +// gotspsi.PmtElementaryStream.StreamType() and PID from +// gotspsi.PmtElementaryStream.ElementaryPid(). +// +// PmtStreamTypes from gots/psi are defined as follows: +// PmtStreamTypeMpeg2VideoH262 uint8 = 2 // H262 +// PmtStreamTypeMpeg4Video uint8 = 27 // H264 +// PmtStreamTypeMpeg4VideoH264 uint8 = 27 // H264 +// PmtStreamTypeMpeg4VideoH265 uint8 = 36 // H265 +// PmtStreamTypeAac uint8 = 15 // AAC +// PmtStreamTypeAc3 uint8 = 129 // DD +// PmtStreamTypeEc3 uint8 = 135 // DD+ +// PmtStreamTypeScte35 uint8 = 134 // SCTE-35 func MediaStreams(p []byte) ([]gotspsi.PmtElementaryStream, error) { pat := p[:PacketSize] pmt := p[PacketSize : 2*PacketSize] From 0825799cfa723e39cd5e53850c540bda258dc7c1 Mon Sep 17 00:00:00 2001 From: Saxon Date: Wed, 24 Jul 2019 12:39:14 +0930 Subject: [PATCH 2/6] container/mts/mpegts.go: renamed IndexPid to FindPSIs and change such that only looked for PSI We have only ever used this function to find PSI so it makes sense to make it exclusive for this. It now also returns the streams found in the PMT. So that we can actually retrieve the PIDs of the media and their types. --- container/mts/mpegts.go | 140 +++++++++++++++++++---------------- container/mts/mpegts_test.go | 4 +- 2 files changed, 80 insertions(+), 64 deletions(-) diff --git a/container/mts/mpegts.go b/container/mts/mpegts.go index 420f6842..009f2ec0 100644 --- a/container/mts/mpegts.go +++ b/container/mts/mpegts.go @@ -178,16 +178,15 @@ func FindPat(d []byte) ([]byte, int, error) { // Errors used by FindPid. var ( - errInvalidLen = errors.New("MPEG-TS data not of valid length") - errCouldNotFind = errors.New("could not find packet with given PID") - errNotConsecutive = errors.New("could not find consecutive PIDs") + ErrInvalidLen = errors.New("MPEG-TS data not of valid length") + errCouldNotFind = errors.New("could not find packet with given PID") ) // FindPid will take a clip of MPEG-TS and try to find a packet with given PID - if one // is found, then it is returned along with its index, otherwise nil, -1 and an error is returned. func FindPid(d []byte, pid uint16) (pkt []byte, i int, err error) { if len(d) < PacketSize { - return nil, -1, errInvalidLen + return nil, -1, ErrInvalidLen } for i = 0; i < len(d); i += PacketSize { p := (uint16(d[i+1]&0x1f) << 8) | uint16(d[i+2]) @@ -205,7 +204,7 @@ func FindPid(d []byte, pid uint16) (pkt []byte, i int, err error) { // nil, -1 and an error is returned. func LastPid(d []byte, pid uint16) (pkt []byte, i int, err error) { if len(d) < PacketSize { - return nil, -1, errInvalidLen + return nil, -1, ErrInvalidLen } for i = len(d) - PacketSize; i >= 0; i -= PacketSize { @@ -218,30 +217,68 @@ func LastPid(d []byte, pid uint16) (pkt []byte, i int, err error) { return nil, -1, errCouldNotFind } -// IndexPid returns the position of one or more consecutive pids, -// along with optional metadata if present. Commonly used to find a -// PAT immediately followed by a PMT. -func IndexPid(d []byte, pids ...uint16) (idx int, m map[string]string, err error) { - idx = -1 - for _, pid := range pids { - if len(d) < PacketSize { - return idx, m, errInvalidLen - } - pkt, i, err := FindPid(d, pid) - if err != nil { - return idx, m, errCouldNotFind - } - if pid == PmtPid { - m, _ = metaFromPMT(pkt) - } - if idx == -1 { - idx = i - } else if i != 0 { - return idx, m, errNotConsecutive - } - d = d[i+PacketSize:] +// Errors used by FindPSI. +var ( + ErrMultiplePrograms = errors.New("more than one program not supported") + ErrNoPrograms = errors.New("no programs in PAT") + ErrNotConsecutive = errors.New("could not find consecutive PIDs") +) + +// FindPSI finds the index of a PAT in an a slice of MPEG-TS and returns, along +// with a map of meta from the PMT and the PmtElementaryStreams, which contain +// the media PIDs and their types. +func FindPSI(d []byte) (int, []gotspsi.PmtElementaryStream, map[string]string, error) { + if len(d) < PacketSize { + return -1, nil, nil, ErrInvalidLen } - return + + // Find the PAT if it exists. + pkt, i, err := FindPid(d, PatPid) + if err != nil { + return -1, nil, nil, errors.Wrap(err, "error finding PAT") + } + + // Let's take this opportunity to check what programs are in this MPEG-TS + // stream, and therefore the PID of the PMT, from which we can get metadata. + // NB: currently we only support one program. + progs, err := Programs(pkt) + if err != nil { + return i, nil, nil, errors.Wrap(err, "cannot get programs from PAT") + } + + if len(progs) == 0 { + return i, nil, nil, ErrNoPrograms + } + + if len(progs) > 1 { + return i, nil, nil, ErrMultiplePrograms + } + + pmtPID := pmtPIDs(progs)[0] + + // Now we can look for the PMT. We want to adjust d so that we're not looking + // at the same data twice. + d = d[i+PacketSize:] + pkt, pmtIdx, err := FindPid(d, pmtPID) + if err != nil { + return i, nil, nil, errors.Wrap(err, "error finding PMT") + } + + // Check that the PMT comes straight after the PAT. + if pmtIdx != 0 { + return i, nil, nil, ErrNotConsecutive + } + + // Now we can try to get meta from the PMT. + meta, _ := metaFromPMT(pkt) + + // Now to get the elementary streams defined for this program. + streams, err := Streams(pkt) + if err != nil { + return i, nil, meta, errors.Wrap(err, "could not get streams from PMT") + } + + return i, streams, meta, nil } // FillPayload takes a channel and fills the packets Payload field until the @@ -610,19 +647,6 @@ func Programs(p []byte) (map[uint16]uint16, error) { } // Streams returns elementary streams defined in a given MPEG-TS PMT packet. -// A gotspsi.PmtElementaryStream will give stream type from -// gotspsi.PmtElementaryStream.StreamType() and PID from -// gotspsi.PmtElementaryStream.ElementaryPid(). -// -// PmtStreamTypes from gots/psi are defined as follows: -// PmtStreamTypeMpeg2VideoH262 uint8 = 2 // H262 -// PmtStreamTypeMpeg4Video uint8 = 27 // H264 -// PmtStreamTypeMpeg4VideoH264 uint8 = 27 // H264 -// PmtStreamTypeMpeg4VideoH265 uint8 = 36 // H265 -// PmtStreamTypeAac uint8 = 15 // AAC -// PmtStreamTypeAc3 uint8 = 129 // DD -// PmtStreamTypeEc3 uint8 = 135 // DD+ -// PmtStreamTypeScte35 uint8 = 134 // SCTE-35 func Streams(p []byte) ([]gotspsi.PmtElementaryStream, error) { pmt, err := gotspsi.NewPMT(p) if err != nil { @@ -636,20 +660,6 @@ func Streams(p []byte) ([]gotspsi.PmtElementaryStream, error) { // after. We also assume that this MPEG-TS stream contains just one program, // but this program may contain different streams, i.e. a video stream + audio // stream. -// -// A gotspsi.PmtElementaryStream will give stream type from -// gotspsi.PmtElementaryStream.StreamType() and PID from -// gotspsi.PmtElementaryStream.ElementaryPid(). -// -// PmtStreamTypes from gots/psi are defined as follows: -// PmtStreamTypeMpeg2VideoH262 uint8 = 2 // H262 -// PmtStreamTypeMpeg4Video uint8 = 27 // H264 -// PmtStreamTypeMpeg4VideoH264 uint8 = 27 // H264 -// PmtStreamTypeMpeg4VideoH265 uint8 = 36 // H265 -// PmtStreamTypeAac uint8 = 15 // AAC -// PmtStreamTypeAc3 uint8 = 129 // DD -// PmtStreamTypeEc3 uint8 = 135 // DD+ -// PmtStreamTypeScte35 uint8 = 134 // SCTE-35 func MediaStreams(p []byte) ([]gotspsi.PmtElementaryStream, error) { pat := p[:PacketSize] pmt := p[PacketSize : 2*PacketSize] @@ -664,18 +674,14 @@ func MediaStreams(p []byte) ([]gotspsi.PmtElementaryStream, error) { } if len(m) == 0 { - return nil, errors.New("no programs contained in PAT") + return nil, ErrNoPrograms } if len(m) > 1 { - return nil, errors.New("more than one program not yet supported") + return nil, ErrMultiplePrograms } - var v uint16 - for _, v = range m { - } - - if pid(pmt) != v { + if pid(pmt) != pmtPIDs(m)[0] { return nil, errors.New("second packet is not desired PMT") } @@ -685,3 +691,13 @@ func MediaStreams(p []byte) ([]gotspsi.PmtElementaryStream, error) { } return s, nil } + +// pmtPIDs returns PMT PIDS from a map containing program number as keys and +// corresponding PMT PIDs as values. +func pmtPIDs(m map[uint16]uint16) []uint16 { + r := make([]uint16, 0, len(m)) + for _, v := range m { + r = append(r, v) + } + return r +} diff --git a/container/mts/mpegts_test.go b/container/mts/mpegts_test.go index 9ce93b5b..3de27cf1 100644 --- a/container/mts/mpegts_test.go +++ b/container/mts/mpegts_test.go @@ -493,7 +493,7 @@ func TestSegmentForMeta(t *testing.T) { } // Now test IndexPid. - i, m, err := IndexPid(clip.Bytes(), PatPid, PmtPid) + i, _, m, err := FindPSI(clip.Bytes()) if err != nil { t.Fatalf("IndexPid failed with error: %v", err) } @@ -507,7 +507,7 @@ func TestSegmentForMeta(t *testing.T) { // Finally, test IndexPid error handling. for _, d := range [][]byte{[]byte{}, make([]byte, PacketSize/2), make([]byte, PacketSize)} { - _, _, err := IndexPid(d, PatPid, PmtPid) + _, _, _, err := FindPSI(d) if err == nil { t.Fatalf("IndexPid expected error") } From c55cd9a64ea5985469dd1aeb59cf531de76bdbcd Mon Sep 17 00:00:00 2001 From: Saxon Date: Fri, 26 Jul 2019 14:16:05 +0930 Subject: [PATCH 3/6] 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. --- container/mts/mpegts.go | 26 ++++- container/mts/mpegts_test.go | 197 ++++++++++++++++++++++++++++++++++- 2 files changed, 221 insertions(+), 2 deletions(-) diff --git a/container/mts/mpegts.go b/container/mts/mpegts.go index 009f2ec0..00315d5c 100644 --- a/container/mts/mpegts.go +++ b/container/mts/mpegts.go @@ -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 +} diff --git a/container/mts/mpegts_test.go b/container/mts/mpegts_test.go index 3de27cf1..e801d6f1 100644 --- a/container/mts/mpegts_test.go +++ b/container/mts/mpegts_test.go @@ -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) + } + } +} From 0cb9a50af81700b86ea977f514111e4a28924302 Mon Sep 17 00:00:00 2001 From: Saxon Date: Mon, 5 Aug 2019 14:11:28 +0930 Subject: [PATCH 4/6] container/mts/mpegts_test.go: added some more interesting test cases for FindPSI --- container/mts/mpegts_test.go | 74 +++++++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 23 deletions(-) diff --git a/container/mts/mpegts_test.go b/container/mts/mpegts_test.go index e801d6f1..791d9de5 100644 --- a/container/mts/mpegts_test.go +++ b/container/mts/mpegts_test.go @@ -574,6 +574,32 @@ func TestFindPSI(t *testing.T) { err: nil, }, }, + { + pkts: []int{media, pat, pmt, media, media}, + meta: "1", + want: want{ + idx: 188, + streamType: gotspsi.PmtStreamTypeMpeg4Video, + streamPID: 4, + meta: map[string]string{ + "key": "1", + }, + err: nil, + }, + }, + { + pkts: []int{pat, media, pmt, media, media}, + meta: "1", + want: want{ + idx: 0, + streamType: gotspsi.PmtStreamTypeMpeg4Video, + streamPID: 4, + meta: map[string]string{ + "key": "1", + }, + err: ErrNotConsecutive, + }, + }, } var clip bytes.Buffer @@ -693,35 +719,37 @@ func TestFindPSI(t *testing.T) { 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) - } + if gotErr == nil { + // 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") - } + // 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") - } + if len(gotStreams) == 0 { + t.Fatalf("gotStreams should not be 0 length") + } - s := gotStreams[0] - gotStreamType := s.StreamType() - gotStreamPID := s.ElementaryPid() + 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 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) - } + 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) + // 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) + } } } } From ed11fac65536078e8f5cb2e60f45ab44388f19eb Mon Sep 17 00:00:00 2001 From: Saxon Date: Tue, 6 Aug 2019 15:38:34 +0930 Subject: [PATCH 5/6] container/mts/mpegts.go: FindPSI now returns a map[uint16]uint8 containing program PIDs and their types instead of []psi.PmtElementaryStream --- container/mts/mpegts.go | 12 ++++++++---- container/mts/mpegts_test.go | 12 +++++++++--- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/container/mts/mpegts.go b/container/mts/mpegts.go index 00315d5c..064c0f9b 100644 --- a/container/mts/mpegts.go +++ b/container/mts/mpegts.go @@ -225,9 +225,8 @@ var ( ) // FindPSI finds the index of a PAT in an a slice of MPEG-TS and returns, along -// with a map of meta from the PMT and the PmtElementaryStreams, which contain -// the media PIDs and their types. -func FindPSI(d []byte) (int, []gotspsi.PmtElementaryStream, map[string]string, error) { +// with a map of meta from the PMT and the stream PIDs and their types. +func FindPSI(d []byte) (int, map[uint16]uint8, map[string]string, error) { if len(d) < PacketSize { return -1, nil, nil, ErrInvalidLen } @@ -278,7 +277,12 @@ func FindPSI(d []byte) (int, []gotspsi.PmtElementaryStream, map[string]string, e return i, nil, meta, errors.Wrap(err, "could not get streams from PMT") } - return i, streams, meta, nil + var streamMap map[uint16]uint8 + for _, s := range streams { + streamMap[s.ElementaryPid()] = s.StreamType() + } + + return i, streamMap, meta, nil } // FillPayload takes a channel and fills the packets Payload field until the diff --git a/container/mts/mpegts_test.go b/container/mts/mpegts_test.go index 791d9de5..66a7f93c 100644 --- a/container/mts/mpegts_test.go +++ b/container/mts/mpegts_test.go @@ -734,9 +734,15 @@ func TestFindPSI(t *testing.T) { t.Fatalf("gotStreams should not be 0 length") } - s := gotStreams[0] - gotStreamType := s.StreamType() - gotStreamPID := s.ElementaryPid() + var ( + gotStreamPID uint16 + gotStreamType uint8 + ) + + for k, v := range gotStreams { + gotStreamPID = k + gotStreamType = v + } 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) From a19c0f4ec31afc4343b663d4801fc29b7d6a6a9a Mon Sep 17 00:00:00 2001 From: Saxon Date: Tue, 6 Aug 2019 15:40:37 +0930 Subject: [PATCH 6/6] container/mts/mpegts.go: fixed nil map bug in FindPSI --- container/mts/mpegts.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/mts/mpegts.go b/container/mts/mpegts.go index 064c0f9b..233a120c 100644 --- a/container/mts/mpegts.go +++ b/container/mts/mpegts.go @@ -277,7 +277,7 @@ func FindPSI(d []byte) (int, map[uint16]uint8, map[string]string, error) { return i, nil, meta, errors.Wrap(err, "could not get streams from PMT") } - var streamMap map[uint16]uint8 + streamMap := make(map[uint16]uint8) for _, s := range streams { streamMap[s.ElementaryPid()] = s.StreamType() }