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

Unified Diff: media/filters/source_buffer_stream_unittest.cc

Issue 10952034: Remove lingering frames of old data when appending a new segment (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: response to CR Created 8 years, 3 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
« no previous file with comments | « media/filters/source_buffer_stream.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 96b1826bfbaadfcb89c0d96d999e5e7995515e81..23bd14719a342671cc04cbb2eb8ea8d1d2bc4fd5 100644
--- a/media/filters/source_buffer_stream_unittest.cc
+++ b/media/filters/source_buffer_stream_unittest.cc
@@ -7,6 +7,9 @@
#include <string>
#include "base/logging.h"
+#include "base/string_number_conversions.h"
+#include "base/string_split.h"
+#include "base/string_util.h"
#include "media/base/data_buffer.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -74,10 +77,22 @@ class SourceBufferStreamTest : public testing::Test {
base::TimeDelta(), true, data, kDataSize);
}
+ void NewSegmentAppendOneByOne(const std::string& buffers_to_append) {
+ AppendBuffersOneByOne(buffers_to_append, true);
+ }
+
+ void AppendBuffersOneByOne(const std::string& buffers_to_append) {
+ AppendBuffersOneByOne(buffers_to_append, false);
+ }
+
void Seek(int position) {
stream_->Seek(position * frame_duration_);
}
+ void SeekToTimestamp(base::TimeDelta timestamp) {
+ stream_->Seek(timestamp);
+ }
+
void CheckExpectedRanges(const std::string& expected) {
Ranges<base::TimeDelta> r = stream_->GetBufferedTime();
@@ -89,7 +104,21 @@ class SourceBufferStreamTest : public testing::Test {
ss << "[" << start << "," << end << ") ";
}
ss << "}";
- EXPECT_EQ(ss.str(), expected);
+ EXPECT_EQ(expected, ss.str());
+ }
+
+ void CheckExpectedRangesByTimestamp(const std::string& expected) {
+ Ranges<base::TimeDelta> r = stream_->GetBufferedTime();
+
+ std::stringstream ss;
+ ss << "{ ";
+ for (size_t i = 0; i < r.size(); ++i) {
+ int64 start = r.start(i).InMilliseconds();
+ int64 end = r.end(i).InMilliseconds();
+ ss << "[" << start << "," << end << ") ";
+ }
+ ss << "}";
+ EXPECT_EQ(expected, ss.str());
}
void CheckExpectedBuffers(
@@ -147,6 +176,25 @@ class SourceBufferStreamTest : public testing::Test {
EXPECT_EQ(ending_position + 1, current_position);
}
+ void CheckExpectedBuffers(const std::string& expected) {
+ std::vector<std::string> timestamps;
+ base::SplitString(expected, ' ', &timestamps);
+ for (size_t i = 0; i < timestamps.size(); i++) {
+ scoped_refptr<StreamParserBuffer> buffer;
+ SourceBufferStream::Status status = stream_->GetNextBuffer(&buffer);
+
+ EXPECT_EQ(SourceBufferStream::kSuccess, status);
+ if (status != SourceBufferStream::kSuccess)
+ break;
+
+ std::stringstream ss;
+ ss << buffer->GetDecodeTimestamp().InMilliseconds();
+ if (buffer->IsKeyframe())
+ ss << "K";
+ EXPECT_EQ(timestamps[i], ss.str());
+ }
+ }
+
void CheckNoNextBuffer() {
scoped_refptr<StreamParserBuffer> buffer;
EXPECT_EQ(stream_->GetNextBuffer(&buffer), SourceBufferStream::kNeedBuffer);
@@ -215,6 +263,39 @@ class SourceBufferStreamTest : public testing::Test {
EXPECT_EQ(expect_success, stream_->Append(queue));
}
+ void AppendBuffersOneByOne(const std::string& buffers_to_append,
+ bool start_new_segment) {
+ std::vector<std::string> timestamps;
+ base::SplitString(buffers_to_append, ' ', &timestamps);
+
+ CHECK_GT(timestamps.size(), 0u);
+
+ for (size_t i = 0; i < timestamps.size(); i++) {
+ bool is_keyframe = false;
+ if (EndsWith(timestamps[i], "K", true)) {
+ is_keyframe = true;
+ // Remove the "K" off of the token.
+ timestamps[i] = timestamps[i].substr(0, timestamps[i].length() - 1);
+ }
+ int time_in_ms;
+ CHECK(base::StringToInt(timestamps[i], &time_in_ms));
+
+ // Create buffer.
+ scoped_refptr<StreamParserBuffer> buffer =
+ StreamParserBuffer::CopyFrom(&kDataA, kDataSize, is_keyframe);
+ base::TimeDelta timestamp =
+ base::TimeDelta::FromMilliseconds(time_in_ms);
+ buffer->SetDecodeTimestamp(timestamp);
+
+ if (i == 0u && start_new_segment)
+ stream_->OnNewMediaSegment(timestamp);
+
+ SourceBufferStream::BufferQueue queue;
+ queue.push_back(buffer);
+ EXPECT_TRUE(stream_->Append(queue));
+ }
+ }
+
int frames_per_second_;
int keyframes_per_second_;
base::TimeDelta frame_duration_;
@@ -1084,6 +1165,82 @@ TEST_F(SourceBufferStreamTest, Middle_Overlap_Selected_4) {
CheckExpectedBuffers(10, 14, &kDataA);
}
+TEST_F(SourceBufferStreamTest, Overlap_OneByOne) {
+ // Append 5 buffers starting at 10ms, 30ms apart.
+ NewSegmentAppendOneByOne("10K 40 70 100 130");
+
+ // The range ends at 160, accounting for the last buffer's duration.
+ CheckExpectedRangesByTimestamp("{ [10,160) }");
+
+ // Overlap with 10 buffers starting at the beginning, appended one at a
+ // time.
+ NewSegmentAppend(0, 1, &kDataB);
+ for (int i = 1; i < 10; i++)
+ AppendBuffers(i, 1, &kDataB);
+
+ // All data should be replaced.
+ Seek(0);
+ CheckExpectedRanges("{ [0,9) }");
+ CheckExpectedBuffers(0, 9, &kDataB);
+}
+
+TEST_F(SourceBufferStreamTest, Overlap_OneByOne_DeleteGroup) {
+ NewSegmentAppendOneByOne("10K 40 70 100 130K");
+ CheckExpectedRangesByTimestamp("{ [10,160) }");
+
+ // Seek to 130ms.
+ SeekToTimestamp(base::TimeDelta::FromMilliseconds(130));
+
+ // Overlap with a new segment from 0 to 120ms.
+ NewSegmentAppendOneByOne("0K 120");
+
+ // Next buffer should still be 130ms.
+ CheckExpectedBuffers("130K");
+
+ // Check the final buffers is correct.
+ SeekToTimestamp(base::TimeDelta::FromMilliseconds(0));
+ CheckExpectedBuffers("0K 120 130K");
+}
+
+TEST_F(SourceBufferStreamTest, Overlap_OneByOne_BetweenMediaSegments) {
+ // Append 5 buffers starting at 110ms, 30ms apart.
+ NewSegmentAppendOneByOne("110K 140 170 200 230");
+ CheckExpectedRangesByTimestamp("{ [110,260) }");
+
+ // Now append 2 media segments from 0ms to 210ms, 30ms apart. Note that the
+ // old keyframe 110ms falls in between these two segments.
+ NewSegmentAppendOneByOne("0K 30 60 90");
+ NewSegmentAppendOneByOne("120K 150 180 210");
+ CheckExpectedRangesByTimestamp("{ [0,240) }");
+
+ // Check the final buffers is correct; the keyframe at 110ms should be
+ // deleted.
+ SeekToTimestamp(base::TimeDelta::FromMilliseconds(0));
+ CheckExpectedBuffers("0K 30 60 90 120K 150 180 210");
+}
+
+TEST_F(SourceBufferStreamTest, Overlap_OneByOne_TrackBuffer) {
+ NewSegmentAppendOneByOne("10K 40 70 100K 125 130K");
+ CheckExpectedRangesByTimestamp("{ [10,160) }");
+
+ // Seek to 70ms.
+ SeekToTimestamp(base::TimeDelta::FromMilliseconds(10));
+ CheckExpectedBuffers("10K 40");
+
+ // Overlap with a new segment from 0 to 120ms.
+ NewSegmentAppendOneByOne("0K 30 60 90 120K");
+ CheckExpectedRangesByTimestamp("{ [0,160) }");
+
+ // Should return frames 70ms and 100ms from the track buffer, then switch
+ // to the new data at 120K, then switch back to the old data at 130K. The
+ // frame at 125ms that depended on keyframe 100ms should have been deleted.
+ CheckExpectedBuffers("70 100K 120K 130K");
+
+ // Check the final result: should not include data from the track buffer.
+ SeekToTimestamp(base::TimeDelta::FromMilliseconds(0));
+ CheckExpectedBuffers("0K 30 60 90 120K 130K");
+}
+
TEST_F(SourceBufferStreamTest, Seek_Keyframe) {
// Append 6 buffers at positions 0 through 5.
NewSegmentAppend(0, 6);
« no previous file with comments | « media/filters/source_buffer_stream.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698