diff --git a/container/mts/payload.go b/container/mts/payload.go index 9d33fa59..9785f2f0 100644 --- a/container/mts/payload.go +++ b/container/mts/payload.go @@ -186,46 +186,28 @@ var ( func (c *Clip) BytesForMetaInterval(key, from, to string) ([]byte, error) { // First check that the interval makes sense. - if from >= to { + 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 + var start, end int + + // Try and find from. + for i := 0; i < len(c.frames); i++ { + f := c.frames[i] + if f.Meta[key] == from { + start = f.idx + + // Now try and find to. + for ; i < len(c.frames); i++ { + f = c.frames[i] + if f.Meta[key] == to { + end = f.idx + return c.backing[start : end+len(f.Media)], nil + } } - return false - }, - ) - if idx == n { - return nil, errMetaLowerBound + return nil, errMetaUpperBound + } } - - // 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 + return nil, errMetaLowerBound } diff --git a/container/mts/payload_test.go b/container/mts/payload_test.go index 9cc36b88..3ae114e7 100644 --- a/container/mts/payload_test.go +++ b/container/mts/payload_test.go @@ -302,16 +302,98 @@ func TestBytesForPTSInterval(t *testing.T) { // First check the error. if err != nil && err != test.err { - t.Errorf("unexpected error: %v for test: %v from BytesForPTSInterval", err, i) + t.Errorf("unexpected error: %v for test: %v", err, i) continue } else if err != test.err { - t.Errorf("expected to get error: %v for test: %v from BytesForPTSInterval", test.err, i) + t.Errorf("expected to get error: %v for test: %v", test.err, i) continue } // Now check data. if test.err == nil && !bytes.Equal(test.expect, got) { - t.Errorf("did not get expected data for test: %v from BytesForPTSInterval.\n Got: %v\n, Want: %v\n", i, got, test.expect) + t.Errorf("did not get expected data for test: %v\n Got: %v\n, Want: %v\n", i, got, test.expect) + } + } +} + +func TestBytesForMetaInterval(t *testing.T) { + const ( + numOfTestFrames = 10 + ptsInterval = 4 + frameSize = 3 + key = "n" + ) + + clip := &Clip{} + + // Generate test frames. + for i := 0; i < numOfTestFrames; i++ { + clip.backing = append(clip.backing, []byte{byte(i), byte(i), byte(i)}...) + clip.frames = append( + clip.frames, + Frame{ + Media: clip.backing[i*frameSize : (i+1)*frameSize], + idx: i * frameSize, + Meta: map[string]string{ + key: strconv.Itoa(i), + }, + }, + ) + } + + // We test each of these scenarios. + tests := []struct { + from string + to string + expect []byte + err error + }{ + { + from: "1", + to: "3", + expect: []byte{ + 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, + 0x03, 0x03, 0x03, + }, + err: nil, + }, + { + from: "1", + to: "1", + expect: nil, + err: errMetaRange, + }, + { + from: "20", + to: "1", + expect: nil, + err: errMetaLowerBound, + }, + { + from: "1", + to: "20", + expect: nil, + err: errMetaUpperBound, + }, + } + + // Run tests. + for i, test := range tests { + got, err := clip.BytesForMetaInterval(key, test.from, test.to) + + // First check the error. + if err != nil && err != test.err { + t.Errorf("unexpected error: %v for test: %v", err, i) + continue + } else if err != test.err { + t.Errorf("expected to get error: %v for test: %v", test.err, i) + continue + } + + // Now check data. + if test.err == nil && !bytes.Equal(test.expect, got) { + t.Errorf("did not get expected data for test: %v\n Got: %v\n, Want: %v\n", i, got, test.expect) } } }