Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1070)

Unified Diff: media/filters/source_buffer_stream_unittest.cc

Issue 1008463002: Fix MSE GC, make it less aggressive, more spec-compliant (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Renderer should return kNoTimestamp when theres no time source yet. Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: media/filters/source_buffer_stream_unittest.cc
diff --git a/media/filters/source_buffer_stream_unittest.cc b/media/filters/source_buffer_stream_unittest.cc
index e360ba547233dc63c43749083e36d6df0ef2733d..1da2c047bf8b24a1593b8a3df89b29d57ed53e8f 100644
--- a/media/filters/source_buffer_stream_unittest.cc
+++ b/media/filters/source_buffer_stream_unittest.cc
@@ -2358,6 +2358,8 @@ TEST_F(SourceBufferStreamTest, GarbageCollection_DeleteFront) {
for (int i = 1; i < 20; i++)
AppendBuffers(i, 1, &kDataA);
+ EXPECT_TRUE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
+
// None of the buffers should trigger garbage collection, so all data should
// be there as expected.
CheckExpectedRanges("{ [0,19) }");
@@ -2370,6 +2372,9 @@ TEST_F(SourceBufferStreamTest, GarbageCollection_DeleteFront) {
// Append 5 buffers to the end of the stream.
AppendBuffers(20, 5, &kDataA);
+ // Run garbage collection
+ EXPECT_TRUE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
+
// GC should have deleted the first 5 buffers.
CheckExpectedRanges("{ [5,24) }");
CheckExpectedBuffers(10, 24, &kDataA);
@@ -2390,6 +2395,8 @@ TEST_F(SourceBufferStreamTest, GarbageCollection_DeleteFrontGOPsAtATime) {
// Add one buffer to put the memory over the cap.
AppendBuffers(20, 1, &kDataA);
+ EXPECT_TRUE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
+
// GC should have deleted the first 5 buffers so that the range still begins
// with a keyframe.
CheckExpectedRanges("{ [5,20) }");
@@ -2399,18 +2406,37 @@ TEST_F(SourceBufferStreamTest, GarbageCollection_DeleteFrontGOPsAtATime) {
}
TEST_F(SourceBufferStreamTest, GarbageCollection_DeleteBack) {
- // Set memory limit to 5 buffers.
- SetMemoryLimit(5);
+ // Set memory limit to 10 buffers.
+ SetMemoryLimit(10);
// Seek to position 0.
Seek(0);
// Append 20 buffers at positions 0 through 19.
- NewSegmentAppend(0, 20, &kDataA);
+ NewSegmentAppend(0, 5, &kDataA);
+ NewSegmentAppend(10, 10, &kDataA);
wolenetz 2015/06/04 00:38:57 nice work!
+ // GC guarantees we keep all buffers between current seek and last append.
+ // Therefore, append buffers at positions 5 to 9 last so that we are allowed
+ // to collect buffers 10 to 19 (since they are now after last append)
+ NewSegmentAppend(5, 5, &kDataA);
- // Should leave the first 5 buffers from 0 to 4 and the last GOP appended.
- CheckExpectedRanges("{ [0,4) [15,19) }");
- CheckExpectedBuffers(0, 4, &kDataA);
+ // Check we have all the buffers
+ CheckExpectedRanges("{ [0,19) }");
+
+ // Run garbage collection
+ EXPECT_TRUE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
+
+ // Should leave the first 5 buffers from 0 to 4.
+ CheckExpectedRanges("{ [0,9) }");
+
+ // Check that GC refuses to collect last append
+ SetMemoryLimit(5);
+ EXPECT_FALSE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
+
+ // Should leave the prior buffers untouched
+ CheckExpectedRanges("{ [0,9) }");
+ CheckExpectedBuffers(0, 9, &kDataA);
+ CheckNoNextBuffer();
}
TEST_F(SourceBufferStreamTest, GarbageCollection_DeleteFrontAndBack) {
@@ -2420,13 +2446,23 @@ TEST_F(SourceBufferStreamTest, GarbageCollection_DeleteFrontAndBack) {
// Seek to position 15.
Seek(15);
- // Append 40 buffers at positions 0 through 39.
- NewSegmentAppend(0, 40, &kDataA);
+ // Append 40 buffers at positions 0 through 39
+ NewSegmentAppend(0, 20, &kDataA);
+ NewSegmentAppend(25, 15, &kDataA);
+ // GC guarantees we keep all buffers between current seek and last append.
+ // Therefore, append buffers at positions 20 to 24 last so that we are allowed
+ // to collect buffers after 24
+ NewSegmentAppend(20, 5, &kDataA);
- // Should leave the GOP containing the seek position and the last GOP
- // appended.
- CheckExpectedRanges("{ [15,19) [35,39) }");
- CheckExpectedBuffers(15, 19, &kDataA);
+ // Check we have all the buffers
+ CheckExpectedRanges("{ [0,39) }");
+
+ // Garbage collect will fail, cannot reduce to 3 buffers
+ EXPECT_FALSE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
+
+ // Should leave the GOP containing the seek position.
+ CheckExpectedRanges("{ [15,24) }");
+ CheckExpectedBuffers(15, 24, &kDataA);
CheckNoNextBuffer();
}
@@ -2440,10 +2476,10 @@ TEST_F(SourceBufferStreamTest, GarbageCollection_DeleteSeveralRanges) {
// Append 5 buffers at positions 20 through 24.
NewSegmentAppend(20, 5);
- // Append 5 buffers at positions 30 through 34.
- NewSegmentAppend(30, 5);
+ // Append 5 buffers at positions 40 through 44.
+ NewSegmentAppend(40, 5);
- CheckExpectedRanges("{ [0,4) [10,14) [20,24) [30,34) }");
+ CheckExpectedRanges("{ [0,4) [10,14) [20,24) [40,44) }");
// Seek to position 21.
wolenetz 2015/06/04 00:38:57 drive-by nit: s/21/20 :)
servolk 2015/06/04 03:03:02 Done.
Seek(20);
@@ -2452,31 +2488,37 @@ TEST_F(SourceBufferStreamTest, GarbageCollection_DeleteSeveralRanges) {
// Set memory limit to 1 buffer.
SetMemoryLimit(1);
- // Append 5 buffers at positions 40 through 44. This will trigger GC.
- NewSegmentAppend(40, 5);
+ // Append 5 buffers at positions 40 through 44.
wolenetz 2015/06/04 00:38:57 nit: s/40 through 44/30 through 34/
servolk 2015/06/04 03:03:01 Done.
+ NewSegmentAppend(30, 5);
+
+ // We will have more than 1 buffer left, GC will fail
+ EXPECT_FALSE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
- // Should delete everything except the GOP containing the current buffer and
- // the last GOP appended.
- CheckExpectedRanges("{ [20,24) [40,44) }");
+ // Should have deleted all buffer ranges before the current buffer and after
+ // last GOP
+ CheckExpectedRanges("{ [20,24) [30,34) }");
CheckExpectedBuffers(21, 24);
CheckNoNextBuffer();
// Continue appending into the last range to make sure it didn't break.
- AppendBuffers(45, 10);
- // Should only save last GOP appended.
- CheckExpectedRanges("{ [20,24) [50,54) }");
+ AppendBuffers(35, 10);
+ EXPECT_FALSE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
+ // Should save everything between read head and last appended
+ CheckExpectedRanges("{ [20,24) [30,44) }");
// Make sure appending before and after the ranges didn't somehow break.
SetMemoryLimit(100);
NewSegmentAppend(0, 10);
- CheckExpectedRanges("{ [0,9) [20,24) [50,54) }");
+ EXPECT_TRUE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
+ CheckExpectedRanges("{ [0,9) [20,24) [30,44) }");
Seek(0);
CheckExpectedBuffers(0, 9);
NewSegmentAppend(90, 10);
- CheckExpectedRanges("{ [0,9) [20,24) [50,54) [90,99) }");
- Seek(50);
- CheckExpectedBuffers(50, 54);
+ EXPECT_TRUE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
+ CheckExpectedRanges("{ [0,9) [20,24) [30,44) [90,99) }");
+ Seek(30);
+ CheckExpectedBuffers(30, 44);
CheckNoNextBuffer();
Seek(90);
CheckExpectedBuffers(90, 99);
@@ -2493,6 +2535,8 @@ TEST_F(SourceBufferStreamTest, GarbageCollection_DeleteAfterLastAppend) {
// Append 2 GOPs starting at 490ms, 30ms apart.
NewSegmentAppend("490K 520 550 580K 610 640");
+ EXPECT_TRUE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
+
CheckExpectedRangesByTimestamp("{ [310,400) [490,670) }");
// Seek to the GOP at 580ms.
@@ -2502,6 +2546,8 @@ TEST_F(SourceBufferStreamTest, GarbageCollection_DeleteAfterLastAppend) {
// So the ranges before GC are "{ [100,280) [310,400) [490,670) }".
NewSegmentAppend("100K 130 160 190K 220 250K");
+ EXPECT_TRUE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
+
// Should save the newly appended GOPs.
CheckExpectedRangesByTimestamp("{ [100,280) [580,670) }");
}
@@ -2520,6 +2566,8 @@ TEST_F(SourceBufferStreamTest, GarbageCollection_DeleteAfterLastAppendMerged) {
// range. So the range before GC is "{ [220,670) }".
NewSegmentAppend("220K 250 280 310K 340 370");
+ EXPECT_TRUE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
+
// Should save the newly appended GOPs.
CheckExpectedRangesByTimestamp("{ [220,400) [580,670) }");
}
@@ -2531,6 +2579,8 @@ TEST_F(SourceBufferStreamTest, GarbageCollection_NoSeek) {
// Append 25 buffers at positions 0 through 24.
NewSegmentAppend(0, 25, &kDataA);
+ EXPECT_TRUE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
+
// GC deletes the first 5 buffers to keep the memory limit within cap.
CheckExpectedRanges("{ [5,24) }");
CheckNoNextBuffer();
@@ -2549,6 +2599,8 @@ TEST_F(SourceBufferStreamTest, GarbageCollection_PendingSeek) {
Seek(15);
CheckNoNextBuffer();
+ EXPECT_TRUE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
+
CheckExpectedRanges("{ [0,9) [25,29) }");
// Set memory limit to 5 buffers.
@@ -2557,6 +2609,8 @@ TEST_F(SourceBufferStreamTest, GarbageCollection_PendingSeek) {
// Append 5 buffers as positions 30 to 34 to trigger GC.
AppendBuffers(30, 5, &kDataA);
+ EXPECT_TRUE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
+
// The current algorithm will delete from the beginning until the memory is
// under cap.
CheckExpectedRanges("{ [30,34) }");
@@ -2567,6 +2621,8 @@ TEST_F(SourceBufferStreamTest, GarbageCollection_PendingSeek) {
// Append data to fulfill seek.
NewSegmentAppend(15, 5, &kDataA);
+ EXPECT_TRUE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
+
// Check to make sure all is well.
CheckExpectedRanges("{ [15,19) [30,34) }");
CheckExpectedBuffers(15, 19, &kDataA);
@@ -2583,22 +2639,26 @@ TEST_F(SourceBufferStreamTest, GarbageCollection_NeedsMoreData) {
// Advance next buffer position to 10.
Seek(0);
+ EXPECT_TRUE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
CheckExpectedBuffers(0, 9, &kDataA);
CheckNoNextBuffer();
// Append 20 buffers at positions 15 through 34.
NewSegmentAppend(15, 20, &kDataA);
- // GC should have saved the keyframe before the current seek position and the
- // data closest to the current seek position. It will also save the last GOP
- // appended.
- CheckExpectedRanges("{ [5,9) [15,19) [30,34) }");
+ // GC should save the keyframe before the current seek position and the data
wolenetz 2015/06/04 00:38:57 nit: there is no seek_pending_, right? s/seek posi
servolk 2015/06/04 03:03:01 Yep, this will hit SBS::ShouldSeekToStartOfBuffere
+ // closest to the current seek position. It will also save all buffers from
+ // current seek to the last GOP appended, which overflows limit and leads to
+ // failure.
+ EXPECT_FALSE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
+ CheckExpectedRanges("{ [5,9) [15,34) }");
// Now fulfill the seek at position 10. This will make GC delete the data
wolenetz 2015/06/04 00:38:57 similar nit ditto: no seek_pending_, right?
servolk 2015/06/04 03:03:01 Yep, see above.
// before position 10 to keep it within cap.
NewSegmentAppend(10, 5, &kDataA);
- CheckExpectedRanges("{ [10,19) [30,34) }");
- CheckExpectedBuffers(10, 19, &kDataA);
+ EXPECT_TRUE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
+ CheckExpectedRanges("{ [10,24) }");
+ CheckExpectedBuffers(10, 24, &kDataA);
}
TEST_F(SourceBufferStreamTest, GarbageCollection_TrackBuffer) {
@@ -2611,6 +2671,8 @@ TEST_F(SourceBufferStreamTest, GarbageCollection_TrackBuffer) {
// Append 18 buffers at positions 0 through 17.
NewSegmentAppend(0, 18, &kDataA);
+ EXPECT_TRUE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
+
// Should leave GOP containing seek position.
CheckExpectedRanges("{ [15,17) }");
@@ -2620,6 +2682,10 @@ TEST_F(SourceBufferStreamTest, GarbageCollection_TrackBuffer) {
// Completely overlap the existing buffers.
NewSegmentAppend(0, 20, &kDataB);
+ // 4 buffers in final GOP, which is more than 3 buffers left in buffer, so GC
wolenetz 2015/06/04 00:38:57 nit: s/4/5 ? buffers left in buffer is also confus
servolk 2015/06/04 03:03:01 Done.
+ // will fail
+ EXPECT_FALSE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
+
// Because buffers 16 and 17 are not keyframes, they are moved to the track
// buffer upon overlap. The source buffer (i.e. not the track buffer) is now
// waiting for the next keyframe.
@@ -2630,6 +2696,9 @@ TEST_F(SourceBufferStreamTest, GarbageCollection_TrackBuffer) {
// Now add a keyframe at position 20.
AppendBuffers(20, 5, &kDataB);
+ // 5 buffers in final GOP, GC will fail
+ EXPECT_FALSE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
+
// Should garbage collect such that there are 5 frames remaining, starting at
// the keyframe.
CheckExpectedRanges("{ [20,24) }");
@@ -2643,33 +2712,34 @@ TEST_F(SourceBufferStreamTest, GarbageCollection_SaveAppendGOP) {
// collected.
SetMemoryLimit(3);
NewSegmentAppend("0K 30 60 90");
+ EXPECT_FALSE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
CheckExpectedRangesByTimestamp("{ [0,120) }");
// Make sure you can continue appending data to this GOP; again, GC should not
// wipe out anything.
AppendBuffers("120D30");
+ EXPECT_FALSE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
CheckExpectedRangesByTimestamp("{ [0,150) }");
- // Set memory limit to 100 and append a 2nd range after this without
- // triggering GC.
- SetMemoryLimit(100);
+ // Append a 2nd range after this without triggering GC.
NewSegmentAppend("200K 230 260 290K 320 350");
CheckExpectedRangesByTimestamp("{ [0,150) [200,380) }");
// Seek to 290ms.
SeekToTimestamp(base::TimeDelta::FromMilliseconds(290));
- // Now set memory limit to 3 and append a GOP in a separate range after the
- // selected range. Because it is after 290ms, this tests that the GOP is saved
- // when deleting from the back.
- SetMemoryLimit(3);
+ // Now append a GOP in a separate range after the selected range and trigger
+ // GC. Because it is after 290ms, this tests that the GOP is saved when
+ // deleting from the back.
NewSegmentAppend("500K 530 560 590");
+ EXPECT_FALSE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
- // Should save GOP with 290ms and last GOP appended.
+ // Should save GOPs between 290ms and the last GOP appended.
CheckExpectedRangesByTimestamp("{ [290,380) [500,620) }");
// Continue appending to this GOP after GC.
AppendBuffers("620D30");
+ EXPECT_FALSE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
CheckExpectedRangesByTimestamp("{ [290,380) [500,650) }");
}
@@ -2685,34 +2755,35 @@ TEST_F(SourceBufferStreamTest, GarbageCollection_SaveAppendGOP_Middle) {
SetMemoryLimit(1);
NewSegmentAppend("80K 110 140");
- // This whole GOP should be saved, and should be able to continue appending
- // data to it.
+ // This whole GOP should be saved after GC, which will fail due to GOP being
+ // larger than 1 buffer
+ EXPECT_FALSE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
CheckExpectedRangesByTimestamp("{ [80,170) }");
+ // We should still be able to continue appending data to GOP
AppendBuffers("170D30");
+ EXPECT_FALSE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
CheckExpectedRangesByTimestamp("{ [80,200) }");
- // Set memory limit to 100 and append a 2nd range after this without
- // triggering GC.
- SetMemoryLimit(100);
+ // Append a 2nd range after this range, without triggering GC.
NewSegmentAppend("400K 430 460 490K 520 550 580K 610 640");
CheckExpectedRangesByTimestamp("{ [80,200) [400,670) }");
// Seek to 80ms to make the first range the selected range.
SeekToTimestamp(base::TimeDelta::FromMilliseconds(80));
- // Now set memory limit to 3 and append a GOP in the middle of the second
- // range. Because it is after the selected range, this tests that the GOP is
- // saved when deleting from the back.
- SetMemoryLimit(3);
+ // Now append a GOP in the middle of the second range and trigger GC. Because
+ // it is after the selected range, this tests that the GOP is saved when
+ // deleting from the back.
NewSegmentAppend("500K 530 560 590");
+ EXPECT_FALSE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
- // Should save the GOP containing the seek point and GOP that was last
- // appended.
- CheckExpectedRangesByTimestamp("{ [80,200) [500,620) }");
+ // Should save the GOPs between the seek point and GOP that was last appended
+ CheckExpectedRangesByTimestamp("{ [80,200) [400,620) }");
// Continue appending to this GOP after GC.
AppendBuffers("620D30");
- CheckExpectedRangesByTimestamp("{ [80,200) [500,650) }");
+ EXPECT_FALSE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
+ CheckExpectedRangesByTimestamp("{ [80,200) [400,650) }");
}
// Test saving the last GOP appended when the GOP containing the next buffer is
@@ -2729,7 +2800,9 @@ TEST_F(SourceBufferStreamTest, GarbageCollection_SaveAppendGOP_Selected1) {
SetMemoryLimit(1);
NewSegmentAppend("0K 30 60");
- // Should save the GOP at 0ms and 90ms.
+ // GC should save the GOP at 0ms and 90ms, and will fail since GOP larger
+ // than 1 buffer
+ EXPECT_FALSE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
CheckExpectedRangesByTimestamp("{ [0,180) }");
// Seek to 0 and check all buffers.
@@ -2742,6 +2815,7 @@ TEST_F(SourceBufferStreamTest, GarbageCollection_SaveAppendGOP_Selected1) {
NewSegmentAppend("180K 210 240");
// Should save the GOP at 90ms and the GOP at 180ms.
+ EXPECT_FALSE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
CheckExpectedRangesByTimestamp("{ [90,270) }");
CheckExpectedBuffers("90K 120 150 180K 210 240");
CheckNoNextBuffer();
@@ -2762,22 +2836,22 @@ TEST_F(SourceBufferStreamTest, GarbageCollection_SaveAppendGOP_Selected2) {
SetMemoryLimit(1);
NewSegmentAppend("90K 120 150");
- // Should save the GOP at 90ms and the GOP at 270ms.
+ // GC should save the GOP at 90ms and 270ms, and will fail since GOP larger
+ // than 1 buffer
+ EXPECT_FALSE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
CheckExpectedRangesByTimestamp("{ [90,180) [270,360) }");
- // Set memory limit to 100 and add 3 GOPs to the end of the selected range
- // at 360ms, 450ms, and 540ms.
- SetMemoryLimit(100);
+ // Add 3 GOPs to the end of the selected range at 360ms, 450ms, and 540ms.
NewSegmentAppend("360K 390 420 450K 480 510 540K 570 600");
CheckExpectedRangesByTimestamp("{ [90,180) [270,630) }");
- // Constrain the memory limit again and overlap the GOP at 450ms to test
- // deleting from the back.
- SetMemoryLimit(1);
+ // Overlap the GOP at 450ms and garbage collect to test deleting from the
+ // back.
NewSegmentAppend("450K 480 510");
+ EXPECT_FALSE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
- // Should save GOP at 270ms and the GOP at 450ms.
- CheckExpectedRangesByTimestamp("{ [270,360) [450,540) }");
+ // Should save GOPs from GOP at 270ms to GOP at 450ms.
+ CheckExpectedRangesByTimestamp("{ [270,540) }");
}
// Test saving the last GOP appended when it is the same as the GOP containing
@@ -2795,8 +2869,9 @@ TEST_F(SourceBufferStreamTest, GarbageCollection_SaveAppendGOP_Selected3) {
SetMemoryLimit(1);
NewSegmentAppend("0K 30");
- // Should save the newly appended GOP, which is also the next GOP that will be
- // returned from the seek request.
+ // GC should save the newly appended GOP, which is also the next GOP that
+ // will be returned from the seek request.
+ EXPECT_FALSE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
CheckExpectedRangesByTimestamp("{ [0,60) }");
// Check the buffers in the range.
@@ -2806,8 +2881,9 @@ TEST_F(SourceBufferStreamTest, GarbageCollection_SaveAppendGOP_Selected3) {
// Continue appending to this buffer.
AppendBuffers("60 90");
- // Should still save the rest of this GOP and should be able to fulfill the
- // read.
+ // GC should still save the rest of this GOP and should be able to fulfill
+ // the read.
+ EXPECT_FALSE(stream_->GarbageCollectIfNeeded(kNoDecodeTimestamp()));
CheckExpectedRangesByTimestamp("{ [0,120) }");
CheckExpectedBuffers("60 90");
CheckNoNextBuffer();

Powered by Google App Engine
This is Rietveld 408576698