diff --git a/container/mts/mpegts.go b/container/mts/mpegts.go index 622a19aa..ce832b30 100644 --- a/container/mts/mpegts.go +++ b/container/mts/mpegts.go @@ -443,19 +443,25 @@ func TrimToMetaRange(d []byte, key, from, to string) ([]byte, error) { } } +// SegmentForMeta returns segments of MTS slice d that correspond to a value of +// meta for key and val. Therefore, any sequence of packets corresponding to +// key and val will be appended to the returned [][]byte. func SegmentForMeta(d []byte, key, val string) ([][]byte, error) { var ( - pkt packet.Packet - segmenting bool - res [][]byte - start int + pkt packet.Packet // We copy data to this so that we can use comcast gots stuff. + segmenting bool // If true we are currently in a segment corresponsing to given meta. + res [][]byte // The resultant [][]byte holding the segments. + start int // The start index of the current segment. ) + // Go through packets. for i := 0; i < len(d); i += PacketSize { copy(pkt[:], d[i:i+PacketSize]) if pkt.PID() == PmtPid { _meta, err := ExtractMeta(pkt[:]) switch err { + // If there's no meta or a problem with meta, we consider this the end + // of the segment. case errNoMeta, meta.ErrUnexpectedMetaFormat: if segmenting { res = append(res, d[start:i]) @@ -467,6 +473,9 @@ func SegmentForMeta(d []byte, key, val string) ([][]byte, error) { return nil, err } + // If we've got the meta of interest in the PMT and we're not segmenting + // then start segmenting. If we don't have the meta of interest in the PMT + // and we are segmenting then we want to stop and append the segment to result. if _meta[key] == val && !segmenting { start = i segmenting = true @@ -477,6 +486,8 @@ func SegmentForMeta(d []byte, key, val string) ([][]byte, error) { } } + // We've reached the end of the entire MTS clip so if we're segmenting we need + // to append current segment to res. if segmenting { res = append(res, d[start:len(d)]) } diff --git a/container/mts/mpegts_test.go b/container/mts/mpegts_test.go index 5d74c7ce..1e735095 100644 --- a/container/mts/mpegts_test.go +++ b/container/mts/mpegts_test.go @@ -336,18 +336,20 @@ func TestTrimToMetaRange(t *testing.T) { } } +// TestSegmentForMeta checks that SegmentForMeta can correctly segment some MTS +// data based on a given meta key and value. func TestSegmentForMeta(t *testing.T) { Meta = meta.New() const ( - nPSI = 10 - key = "n" - val = "*" + nPSI = 10 // The number of PSI pairs to write. + key = "n" // The meta key we will work with. + val = "*" // This is the meta value we will look for. ) tests := []struct { - metaVals [nPSI]string - expectIdxs []rng + metaVals [nPSI]string // This represents the meta value for meta pairs (PAT and PMT) + expectIdxs []rng // This gives the expect index ranges for the segments. }{ { metaVals: [nPSI]string{"1", "2", val, val, val, "3", val, val, "4", "4"}, @@ -379,7 +381,10 @@ func TestSegmentForMeta(t *testing.T) { var clip bytes.Buffer for testn, test := range tests { + // We want a clean buffer for each new test, so reset. clip.Reset() + + // Add meta and write PSI to clip. for i := 0; i < nPSI; i++ { if test.metaVals[i] != "" { Meta.Add(key, test.metaVals[i]) @@ -391,26 +396,36 @@ func TestSegmentForMeta(t *testing.T) { t.Fatalf("did not expect to get error writing PSI, error: %v", err) } } + + // Now we get the expected segments using the index ranges from the test. var want [][]byte for _, idxs := range test.expectIdxs { want = append(want, clip.Bytes()[idxs.start:idxs.end]) } + + // Now use the function we're testing to get the segments. got, err := SegmentForMeta(clip.Bytes(), key, val) if err != nil { t.Fatalf("unexpected error: %v", err) } + // Check that segments are OK. if !reflect.DeepEqual(want, got) { t.Errorf("did not get expected result for test %v\nGot: %v\nWant: %v\n", testn, got, want) } } } +// rng describes an index range and is used by TestSegmentForMeta. type rng struct { start int end int } +// scale takes a PSI index (i.e. first PSI is 0, next is 1) and modifies to be +// the index of the first byte of the PSI pair (PAT and PMT) in the byte stream. +// This assumes there are only PSI written consequitively, and is used by +// TestSegmentForMeta. func scale(x, y int) rng { return rng{ ((x * 2) + 1) * PacketSize,