diff --git a/container/mts/payload.go b/container/mts/payload.go index f8491ade..9d33fa59 100644 --- a/container/mts/payload.go +++ b/container/mts/payload.go @@ -8,7 +8,8 @@ import ( "github.com/Comcast/gots/pes" ) -// Extract extracts the media from an MPEG-TS clip given by p. +// Extract extracts the media, PTS, stream ID and meta for an MPEG-TS clip given +// by p, and returns as a Clip. The MPEG-TS must contain only complete packets. func Extract(p []byte) (*Clip, error) { l := len(p) // Check that clip is divisible by 188, i.e. contains a series of full MPEG-TS clips. @@ -121,9 +122,9 @@ func (c *Clip) Bytes() []byte { // Errors used in BytesForPTSInterval. var ( - errBadLowerBound = errors.New("'from' cannot be found") - errBadUpperBound = errors.New("'to' cannot be found") - errInvalidPTSRange = errors.New("PTS interval invalid") + errPTSLowerBound = errors.New("PTS 'from' cannot be found") + errPTSUpperBound = errors.New("PTS 'to' cannot be found") + errPTSRange = errors.New("PTS interval invalid") ) // BytesForPTSInterval returns the media data between PTS' from and to. If from @@ -133,7 +134,7 @@ var ( func (c *Clip) BytesForPTSInterval(from, to uint64) ([]byte, error) { // First check that the interval makes sense. if from >= to { - return nil, errInvalidPTSRange + return nil, errPTSRange } // Use binary search to find 'from'. @@ -148,7 +149,7 @@ func (c *Clip) BytesForPTSInterval(from, to uint64) ([]byte, error) { }, ) if idx == n { - return nil, errBadLowerBound + return nil, errPTSLowerBound } // Now get the start index for the backing slice from this Frame. @@ -167,7 +168,7 @@ func (c *Clip) BytesForPTSInterval(from, to uint64) ([]byte, error) { }, ) if idx == n { - return nil, errBadUpperBound + return nil, errPTSUpperBound } // Now get the end index for the backing slice from this Frame, and return @@ -175,3 +176,56 @@ func (c *Clip) BytesForPTSInterval(from, to uint64) ([]byte, error) { end := c.frames[idx+off-1].idx return c.backing[start : end+len(c.frames[idx+off].Media)], nil } + +// Errors that maybe returned from BytesForMetaInterval. +var ( + errMetaRange = errors.New("invalid meta range") + errMetaLowerBound = errors.New("meta 'from' cannot be found") + errMetaUpperBound = errors.New("meta 'to' cannot be found") +) + +func (c *Clip) BytesForMetaInterval(key, from, to string) ([]byte, error) { + // First check that the interval makes sense. + if from >= to { + return nil, errMetaRange + } + + // Use binary search to find 'from'. + n := len(c.frames) + idx := sort.Search( + n, + func(i int) bool { + if c.frames[i].Meta[key] == from { + return true + } + return false + }, + ) + if idx == n { + return nil, errMetaLowerBound + } + + // Now get the start index for the backing slice from this Frame. + start := c.frames[idx].idx + + // Now use binary search again to find 'to'. + off := idx + 1 + n = n - (off) + idx = sort.Search( + n, + func(i int) bool { + if c.frames[i+off].Meta[key] == to { + return true + } + return false + }, + ) + if idx == n { + return nil, errMetaUpperBound + } + + // Now get the end index for the backing slice from this Frame, and return + // segment from backing slice corresponding to start and end. + end := c.frames[idx+off].idx + return c.backing[start : end+len(c.frames[idx+off].Media)], nil +} diff --git a/container/mts/payload_test.go b/container/mts/payload_test.go index 7f7dd968..9cc36b88 100644 --- a/container/mts/payload_test.go +++ b/container/mts/payload_test.go @@ -280,19 +280,19 @@ func TestBytesForPTSInterval(t *testing.T) { from: 10, to: 5, expect: nil, - err: errInvalidPTSRange, + err: errPTSRange, }, { from: 50, to: 70, expect: nil, - err: errBadLowerBound, + err: errPTSLowerBound, }, { from: 5, to: 70, expect: nil, - err: errBadUpperBound, + err: errPTSUpperBound, }, }