Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / media / filters / source_buffer_stream_unittest.cc
index d830b1f..a1df540 100644 (file)
@@ -31,8 +31,7 @@ static const int kDataSize = 1;
 
 class SourceBufferStreamTest : public testing::Test {
  protected:
-  SourceBufferStreamTest()
-      : accurate_durations_(false) {
+  SourceBufferStreamTest() {
     video_config_ = TestVideoConfig::Normal();
     SetStreamInfo(kDefaultFramesPerSecond, kDefaultKeyframesPerSecond);
     stream_.reset(new SourceBufferStream(video_config_, log_cb(), true));
@@ -57,7 +56,6 @@ class SourceBufferStreamTest : public testing::Test {
 
   void SetAudioStream() {
     video_config_ = TestVideoConfig::Invalid();
-    accurate_durations_ = true;
     audio_config_.Initialize(kCodecVorbis,
                              kSampleFormatPlanarF32,
                              CHANNEL_LAYOUT_STEREO,
@@ -159,11 +157,11 @@ class SourceBufferStreamTest : public testing::Test {
 
   int GetRemovalRangeInMs(int start, int end, int bytes_to_free,
                           int* removal_end) {
-    base::TimeDelta removal_end_timestamp =
-        base::TimeDelta::FromMilliseconds(*removal_end);
+    DecodeTimestamp removal_end_timestamp =
+        DecodeTimestamp::FromMilliseconds(*removal_end);
     int bytes_removed = stream_->GetRemovalRange(
-        base::TimeDelta::FromMilliseconds(start),
-        base::TimeDelta::FromMilliseconds(end), bytes_to_free,
+        DecodeTimestamp::FromMilliseconds(start),
+        DecodeTimestamp::FromMilliseconds(end), bytes_to_free,
         &removal_end_timestamp);
     *removal_end = removal_end_timestamp.InMilliseconds();
     return bytes_removed;
@@ -278,8 +276,7 @@ class SourceBufferStreamTest : public testing::Test {
             break;
         }
 
-        if (timestamps[i] == "C")
-          EXPECT_EQ(SourceBufferStream::kConfigChange, status);
+        EXPECT_EQ("C", timestamps[i]);
 
         ss << "C";
         continue;
@@ -289,9 +286,38 @@ class SourceBufferStreamTest : public testing::Test {
       if (status != SourceBufferStream::kSuccess)
         break;
 
-      ss << buffer->GetDecodeTimestamp().InMilliseconds();
-      if (buffer->IsKeyframe())
+      ss << buffer->timestamp().InMilliseconds();
+
+      if (buffer->GetDecodeTimestamp() !=
+          DecodeTimestamp::FromPresentationTime(buffer->timestamp())) {
+        ss << "|" << buffer->GetDecodeTimestamp().InMilliseconds();
+      }
+
+      // Handle preroll buffers.
+      if (EndsWith(timestamps[i], "P", true)) {
+        ASSERT_TRUE(buffer->IsKeyframe());
+        scoped_refptr<StreamParserBuffer> preroll_buffer;
+        preroll_buffer.swap(buffer);
+
+        // When a preroll buffer is encountered we should be able to request one
+        // more buffer.  The first buffer should match the timestamp and config
+        // of the second buffer, except that its discard_padding() should be its
+        // duration.
+        ASSERT_EQ(SourceBufferStream::kSuccess,
+                  stream_->GetNextBuffer(&buffer));
+        ASSERT_EQ(buffer->GetConfigId(), preroll_buffer->GetConfigId());
+        ASSERT_EQ(buffer->track_id(), preroll_buffer->track_id());
+        ASSERT_EQ(buffer->timestamp(), preroll_buffer->timestamp());
+        ASSERT_EQ(buffer->GetDecodeTimestamp(),
+                  preroll_buffer->GetDecodeTimestamp());
+        ASSERT_EQ(kInfiniteDuration(), preroll_buffer->discard_padding().first);
+        ASSERT_EQ(base::TimeDelta(), preroll_buffer->discard_padding().second);
+        ASSERT_TRUE(buffer->IsKeyframe());
+
+        ss << "P";
+      } else if (buffer->IsKeyframe()) {
         ss << "K";
+      }
 
       // Until the last splice frame is seen, indicated by a matching timestamp,
       // all buffers must have the same splice_timestamp().
@@ -351,7 +377,8 @@ class SourceBufferStreamTest : public testing::Test {
                      const uint8* data,
                      int size) {
     if (begin_media_segment)
-      stream_->OnNewMediaSegment(starting_position * frame_duration_);
+      stream_->OnNewMediaSegment(DecodeTimestamp::FromPresentationTime(
+          starting_position * frame_duration_));
 
     int keyframe_interval = frames_per_second_ / keyframes_per_second_;
 
@@ -367,7 +394,8 @@ class SourceBufferStreamTest : public testing::Test {
 
       if (i == 0)
         timestamp += first_buffer_offset;
-      buffer->SetDecodeTimestamp(timestamp);
+      buffer->SetDecodeTimestamp(
+          DecodeTimestamp::FromPresentationTime(timestamp));
 
       // Simulate an IBB...BBP pattern in which all B-frames reference both
       // the I- and P-frames. For a GOP with playback order 12345, this would
@@ -383,8 +411,7 @@ class SourceBufferStreamTest : public testing::Test {
         presentation_timestamp = timestamp - frame_duration_;
       }
       buffer->set_timestamp(presentation_timestamp);
-      if (accurate_durations_)
-        buffer->set_duration(frame_duration_);
+      buffer->set_duration(frame_duration_);
 
       queue.push_back(buffer);
     }
@@ -392,14 +419,40 @@ class SourceBufferStreamTest : public testing::Test {
       EXPECT_EQ(expect_success, stream_->Append(queue));
   }
 
+  void UpdateLastBufferDuration(DecodeTimestamp current_dts,
+                                BufferQueue* buffers) {
+    if (buffers->empty() || buffers->back()->duration() > base::TimeDelta())
+      return;
+
+    DecodeTimestamp last_dts = buffers->back()->GetDecodeTimestamp();
+    DCHECK(current_dts >= last_dts);
+    buffers->back()->set_duration(current_dts - last_dts);
+  }
+
   // StringToBufferQueue() allows for the generation of StreamParserBuffers from
   // coded strings of timestamps separated by spaces.  Supported syntax:
   //
-  // ##:
-  // Generates a StreamParserBuffer with decode timestamp ##.  E.g., "0 1 2 3".
+  // xx:
+  // Generates a StreamParserBuffer with decode and presentation timestamp xx.
+  // E.g., "0 1 2 3".
+  //
+  // pp|dd:
+  // Generates a StreamParserBuffer with presentation timestamp pp and decode
+  // timestamp dd. E.g., "0|0 3|1 1|2 2|3".
+  //
+  // ##Dzz
+  // Specifies the duration for a buffer. ## represents one of the 2 timestamp
+  // formats above. zz specifies the duration of the buffer in milliseconds.
+  // If the duration isn't specified with this syntax then the buffer duration
+  // is determined by the difference between the decode timestamp in ## and
+  // the decode timestamp of the previous buffer in the string. If the string
+  // only contains 1 buffer then the duration must be explicitly specified with
+  // this format.
   //
   // ##K:
-  // Indicates the buffer with timestamp ## reflects a keyframe.  E.g., "0K 1".
+  // Indicates the buffer with timestamp ## reflects a keyframe. ##
+  // can be any of the 3 timestamp formats above.
+  // E.g., "0K 1|2K 2|4D2K".
   //
   // S(a# ... y# z#)
   // Indicates a splice frame buffer should be created with timestamp z#.  The
@@ -419,6 +472,7 @@ class SourceBufferStreamTest : public testing::Test {
     BufferQueue buffers;
     for (size_t i = 0; i < timestamps.size(); i++) {
       bool is_keyframe = false;
+      bool has_preroll = false;
       bool last_splice_frame = false;
       // Handle splice frame starts.
       if (StartsWithASCII(timestamps[i], "S(", true)) {
@@ -446,29 +500,76 @@ class SourceBufferStreamTest : public testing::Test {
         // Remove the "K" off of the token.
         timestamps[i] = timestamps[i].substr(0, timestamps[i].length() - 1);
       }
+      // Handle preroll buffers.
+      if (EndsWith(timestamps[i], "P", true)) {
+        is_keyframe = true;
+        has_preroll = true;
+        // Remove the "P" off of the token.
+        timestamps[i] = timestamps[i].substr(0, timestamps[i].length() - 1);
+      }
+
+      int duration_in_ms = 0;
+      size_t duration_pos = timestamps[i].find('D');
+      if (duration_pos != std::string::npos) {
+        CHECK(base::StringToInt(timestamps[i].substr(duration_pos + 1),
+                                &duration_in_ms));
+        timestamps[i] = timestamps[i].substr(0, duration_pos);
+      }
 
-      int time_in_ms;
-      CHECK(base::StringToInt(timestamps[i], &time_in_ms));
+      std::vector<std::string> buffer_timestamps;
+      base::SplitString(timestamps[i], '|', &buffer_timestamps);
+
+      if (buffer_timestamps.size() == 1)
+        buffer_timestamps.push_back(buffer_timestamps[0]);
+
+      CHECK_EQ(2u, buffer_timestamps.size());
+
+      int pts_in_ms = 0;
+      int dts_in_ms = 0;
+      CHECK(base::StringToInt(buffer_timestamps[0], &pts_in_ms));
+      CHECK(base::StringToInt(buffer_timestamps[1], &dts_in_ms));
 
       // Create buffer. Buffer type and track ID are meaningless to these tests.
       scoped_refptr<StreamParserBuffer> buffer =
           StreamParserBuffer::CopyFrom(&kDataA, kDataSize, is_keyframe,
                                        DemuxerStream::AUDIO, 0);
-      base::TimeDelta timestamp =
-          base::TimeDelta::FromMilliseconds(time_in_ms);
-      buffer->set_timestamp(timestamp);
-      if (accurate_durations_)
-        buffer->set_duration(frame_duration_);
-      buffer->SetDecodeTimestamp(timestamp);
+      buffer->set_timestamp(base::TimeDelta::FromMilliseconds(pts_in_ms));
+
+      if (dts_in_ms != pts_in_ms) {
+        buffer->SetDecodeTimestamp(
+            DecodeTimestamp::FromMilliseconds(dts_in_ms));
+      }
+
+      if (duration_in_ms)
+        buffer->set_duration(base::TimeDelta::FromMilliseconds(duration_in_ms));
+
+      // Simulate preroll buffers by just generating another buffer and sticking
+      // it as the preroll.
+      if (has_preroll) {
+        scoped_refptr<StreamParserBuffer> preroll_buffer =
+            StreamParserBuffer::CopyFrom(
+                &kDataA, kDataSize, is_keyframe, DemuxerStream::AUDIO, 0);
+        preroll_buffer->set_duration(frame_duration_);
+        buffer->SetPrerollBuffer(preroll_buffer);
+      }
 
       if (splice_frame) {
+        // Make sure that splice frames aren't used with content where decode
+        // and presentation timestamps can differ. (i.e., B-frames)
+        CHECK_EQ(buffer->GetDecodeTimestamp().InMicroseconds(),
+                 buffer->timestamp().InMicroseconds());
         if (!pre_splice_buffers.empty()) {
           // Enforce strictly monotonically increasing timestamps.
           CHECK_GT(
-              timestamp.InMicroseconds(),
+              buffer->timestamp().InMicroseconds(),
+              pre_splice_buffers.back()->timestamp().InMicroseconds());
+          CHECK_GT(
+              buffer->GetDecodeTimestamp().InMicroseconds(),
               pre_splice_buffers.back()->GetDecodeTimestamp().InMicroseconds());
         }
         buffer->SetConfigId(splice_config_id);
+        UpdateLastBufferDuration(buffer->GetDecodeTimestamp(),
+                                 &pre_splice_buffers);
         pre_splice_buffers.push_back(buffer);
         continue;
       }
@@ -481,8 +582,18 @@ class SourceBufferStreamTest : public testing::Test {
         pre_splice_buffers.clear();
       }
 
+      UpdateLastBufferDuration(buffer->GetDecodeTimestamp(), &buffers);
       buffers.push_back(buffer);
     }
+
+    // If the last buffer doesn't have a duration, assume it is the
+    // same as the second to last buffer.
+    if (buffers.size() >= 2 &&
+        buffers.back()->duration() <= base::TimeDelta()) {
+      buffers.back()->set_duration(
+          buffers[buffers.size() - 2]->duration());
+    }
+
     return buffers;
   }
 
@@ -496,11 +607,12 @@ class SourceBufferStreamTest : public testing::Test {
     if (start_new_segment) {
       base::TimeDelta start_timestamp = segment_start_timestamp;
       if (start_timestamp == kNoTimestamp())
-        start_timestamp = buffers[0]->GetDecodeTimestamp();
+        start_timestamp = buffers[0]->timestamp();
 
-      ASSERT_TRUE(start_timestamp <= buffers[0]->GetDecodeTimestamp());
+      ASSERT_TRUE(start_timestamp <= buffers[0]->timestamp());
 
-      stream_->OnNewMediaSegment(start_timestamp);
+      stream_->OnNewMediaSegment(
+          DecodeTimestamp::FromPresentationTime(start_timestamp));
     }
 
     if (!one_by_one) {
@@ -523,10 +635,6 @@ class SourceBufferStreamTest : public testing::Test {
   int frames_per_second_;
   int keyframes_per_second_;
   base::TimeDelta frame_duration_;
-  // TODO(dalecurtis): It's silly to have this, all tests should use accurate
-  // durations instead.  However, currently all tests are written with an
-  // expectation of 0 duration, so it's an involved change.
-  bool accurate_durations_;
   DISALLOW_COPY_AND_ASSIGN(SourceBufferStreamTest);
 };
 
@@ -649,7 +757,7 @@ TEST_F(SourceBufferStreamTest,
   // Completely overlap the old buffers, with a segment that starts
   // after the old segment start timestamp, but before the timestamp
   // of the first buffer in the segment.
-  NewSegmentAppend("20K 50K 80K 110K");
+  NewSegmentAppend("20K 50K 80K 110D10K");
 
   // Verify that the buffered ranges are updated properly and we don't crash.
   CheckExpectedRangesByTimestamp("{ [20,150) }");
@@ -737,7 +845,7 @@ TEST_F(SourceBufferStreamTest, End_Overlap_SingleBuffer) {
   NewSegmentAppend("0K 30 60 90 120K 150");
   CheckExpectedRangesByTimestamp("{ [0,180) }");
 
-  NewSegmentAppend("0K");
+  NewSegmentAppend("0D30K");
   CheckExpectedRangesByTimestamp("{ [0,30) [120,180) }");
 
   CheckExpectedBuffers("0K");
@@ -1506,8 +1614,8 @@ TEST_F(SourceBufferStreamTest, Overlap_OneByOne_DeleteGroup) {
   // Seek to 130ms.
   SeekToTimestamp(base::TimeDelta::FromMilliseconds(130));
 
-  // Overlap with a new segment from 0 to 120ms.
-  NewSegmentAppendOneByOne("0K 120");
+  // Overlap with a new segment from 0 to 130ms.
+  NewSegmentAppendOneByOne("0K 120D10");
 
   // Next buffer should still be 130ms.
   CheckExpectedBuffers("130K");
@@ -1538,21 +1646,21 @@ TEST_F(SourceBufferStreamTest, Overlap_OneByOne_BetweenMediaSegments) {
 // new  : 0K   30   60   90   120K
 // after: 0K   30   60   90  *120K*   130K
 TEST_F(SourceBufferStreamTest, Overlap_OneByOne_TrackBuffer) {
-  NewSegmentAppendOneByOne("10K 40 70 100K 125 130K");
+  NewSegmentAppendOneByOne("10K 40 70 100K 125 130D30K");
   CheckExpectedRangesByTimestamp("{ [10,160) }");
 
   // Seek to 70ms.
   SeekToTimestamp(base::TimeDelta::FromMilliseconds(70));
   CheckExpectedBuffers("10K 40");
 
-  // Overlap with a new segment from 0 to 120ms.
-  NewSegmentAppendOneByOne("0K 30 60 90 120K");
+  // Overlap with a new segment from 0 to 130ms.
+  NewSegmentAppendOneByOne("0K 30 60 90 120D10K");
   CheckExpectedRangesByTimestamp("{ [0,160) }");
 
-  // Should return frames 70ms and 100ms from the track buffer, then switch
+  // Should return frame 70ms 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");
+  CheckExpectedBuffers("70 120K 130K");
 
   // Check the final result: should not include data from the track buffer.
   SeekToTimestamp(base::TimeDelta::FromMilliseconds(0));
@@ -1564,11 +1672,11 @@ TEST_F(SourceBufferStreamTest, Overlap_OneByOne_TrackBuffer) {
 // old  :   10K  40  *70*  100K  125  130K
 // new  : 0K   30   60   90   120K
 // after: 0K   30   60   90  *120K*   130K
-// track:             70   100K
+// track:             70
 // new  :                     110K    130
 // after: 0K   30   60   90  *110K*   130
 TEST_F(SourceBufferStreamTest, Overlap_OneByOne_TrackBuffer2) {
-  NewSegmentAppendOneByOne("10K 40 70 100K 125 130K");
+  NewSegmentAppendOneByOne("10K 40 70 100K 125 130D30K");
   CheckExpectedRangesByTimestamp("{ [10,160) }");
 
   // Seek to 70ms.
@@ -1577,15 +1685,15 @@ TEST_F(SourceBufferStreamTest, Overlap_OneByOne_TrackBuffer2) {
 
   // Overlap with a new segment from 0 to 120ms; 70ms and 100ms go in track
   // buffer.
-  NewSegmentAppendOneByOne("0K 30 60 90 120K");
+  NewSegmentAppendOneByOne("0K 30 60 90 120D10K");
   CheckExpectedRangesByTimestamp("{ [0,160) }");
 
   // Now overlap the keyframe at 120ms.
   NewSegmentAppendOneByOne("110K 130");
 
-  // Should expect buffers 70ms and 100ms from the track buffer. Then it should
+  // Should return frame 70ms from the track buffer. Then it should
   // return the keyframe after the track buffer, which is at 110ms.
-  CheckExpectedBuffers("70 100K 110K 130");
+  CheckExpectedBuffers("70 110K 130");
 }
 
 // Overlap the next keyframe after the end of the track buffer without a
@@ -1593,33 +1701,32 @@ TEST_F(SourceBufferStreamTest, Overlap_OneByOne_TrackBuffer2) {
 // old  :   10K  40  *70*  100K  125  130K
 // new  : 0K   30   60   90   120K
 // after: 0K   30   60   90  *120K*   130K
-// track:             70   100K
+// track:             70
 // new  :        50K   80   110          140
 // after: 0K   30   50K   80   110   140 * (waiting for keyframe)
-// track:               70   100K   120K   130K
+// track:             70
 TEST_F(SourceBufferStreamTest, Overlap_OneByOne_TrackBuffer3) {
-  NewSegmentAppendOneByOne("10K 40 70 100K 125 130K");
+  NewSegmentAppendOneByOne("10K 40 70 100K 125 130D30K");
   CheckExpectedRangesByTimestamp("{ [10,160) }");
 
   // Seek to 70ms.
   SeekToTimestamp(base::TimeDelta::FromMilliseconds(70));
   CheckExpectedBuffers("10K 40");
 
-  // Overlap with a new segment from 0 to 120ms; 70ms and 100ms go in track
-  // buffer.
-  NewSegmentAppendOneByOne("0K 30 60 90 120K");
+  // Overlap with a new segment from 0 to 120ms; 70ms goes in track buffer.
+  NewSegmentAppendOneByOne("0K 30 60 90 120D10K");
   CheckExpectedRangesByTimestamp("{ [0,160) }");
 
-  // Now overlap the keyframe at 120ms. There's no keyframe after 70ms, so 120ms
-  // and 130ms go into the track buffer.
+  // Now overlap the keyframe at 120ms and 130ms.
   NewSegmentAppendOneByOne("50K 80 110 140");
+  CheckExpectedRangesByTimestamp("{ [0,170) }");
 
   // Should have all the buffers from the track buffer, then stall.
-  CheckExpectedBuffers("70 100K 120K 130K");
+  CheckExpectedBuffers("70");
   CheckNoNextBuffer();
 
   // Appending a keyframe should fulfill the read.
-  AppendBuffersOneByOne("150K");
+  AppendBuffersOneByOne("150D30K");
   CheckExpectedBuffers("150K");
   CheckNoNextBuffer();
 }
@@ -1629,12 +1736,12 @@ TEST_F(SourceBufferStreamTest, Overlap_OneByOne_TrackBuffer3) {
 // old  :   10K  40  *70*  100K  125  130K
 // new  : 0K   30   60   90   120K
 // after: 0K   30   60   90  *120K*   130K
-// track:             70   100K
+// track:             70
 // new  :              80K  110          140
 // after: 0K   30   60   *80K*  110   140
 // track:               70
 TEST_F(SourceBufferStreamTest, Overlap_OneByOne_TrackBuffer4) {
-  NewSegmentAppendOneByOne("10K 40 70 100K 125 130K");
+  NewSegmentAppendOneByOne("10K 40 70 100K 125 130D30K");
   CheckExpectedRangesByTimestamp("{ [10,160) }");
 
   // Seek to 70ms.
@@ -1643,7 +1750,7 @@ TEST_F(SourceBufferStreamTest, Overlap_OneByOne_TrackBuffer4) {
 
   // Overlap with a new segment from 0 to 120ms; 70ms and 100ms go in track
   // buffer.
-  NewSegmentAppendOneByOne("0K 30 60 90 120K");
+  NewSegmentAppendOneByOne("0K 30 60 90 120D10K");
   CheckExpectedRangesByTimestamp("{ [0,160) }");
 
   // Now append a keyframe at 80ms.
@@ -1659,7 +1766,7 @@ TEST_F(SourceBufferStreamTest, Overlap_OneByOne_TrackBuffer4) {
 // old  :   10K  40  *70*  100K
 // new  : 0K   30   60   90   120
 // after: 0K   30   60   90   120 * (waiting for keyframe)
-// track:             70   100K
+// track:             70
 // new  :              80K  110          140
 // after: 0K   30   60   *80K*  110   140
 // track:               70
@@ -1671,13 +1778,12 @@ TEST_F(SourceBufferStreamTest, Overlap_OneByOne_TrackBuffer5) {
   SeekToTimestamp(base::TimeDelta::FromMilliseconds(70));
   CheckExpectedBuffers("10K 40");
 
-  // Overlap with a new segment from 0 to 120ms; 70ms and 100ms go in track
+  // Overlap with a new segment from 0 to 120ms; 70ms goes in track
   // buffer.
   NewSegmentAppendOneByOne("0K 30 60 90 120");
   CheckExpectedRangesByTimestamp("{ [0,150) }");
 
-  // Now append a keyframe at 80ms. The buffer at 100ms should be deleted from
-  // the track buffer.
+  // Now append a keyframe at 80ms.
   NewSegmentAppendOneByOne("80K 110 140");
 
   CheckExpectedBuffers("70 80K 110 140");
@@ -1689,13 +1795,13 @@ TEST_F(SourceBufferStreamTest, Overlap_OneByOne_TrackBuffer5) {
 // old  :   10K  40  *70*  100K  125  130K ... 200K 230
 // new  : 0K   30   60   90   120K
 // after: 0K   30   60   90  *120K*   130K ... 200K 230
-// track:             70   100K
+// track:             70
 // old  : 0K   30   60   90  *120K*   130K ... 200K 230
 // new  :                                               260K 290
 // after: 0K   30   60   90  *120K*   130K ... 200K 230 260K 290
-// track:             70   100K
+// track:             70
 TEST_F(SourceBufferStreamTest, Overlap_OneByOne_TrackBuffer6) {
-  NewSegmentAppendOneByOne("10K 40 70 100K 125 130K");
+  NewSegmentAppendOneByOne("10K 40 70 100K 125 130D30K");
   NewSegmentAppendOneByOne("200K 230");
   CheckExpectedRangesByTimestamp("{ [10,160) [200,260) }");
 
@@ -1704,7 +1810,7 @@ TEST_F(SourceBufferStreamTest, Overlap_OneByOne_TrackBuffer6) {
   CheckExpectedBuffers("10K 40");
 
   // Overlap with a new segment from 0 to 120ms.
-  NewSegmentAppendOneByOne("0K 30 60 90 120K");
+  NewSegmentAppendOneByOne("0K 30 60 90 120D10K");
   CheckExpectedRangesByTimestamp("{ [0,160) [200,260) }");
 
   // Verify that 70 gets read out of the track buffer.
@@ -1714,7 +1820,7 @@ TEST_F(SourceBufferStreamTest, Overlap_OneByOne_TrackBuffer6) {
   NewSegmentAppendOneByOne("260K 290");
   CheckExpectedRangesByTimestamp("{ [0,160) [200,320) }");
 
-  CheckExpectedBuffers("100K 120K 130K");
+  CheckExpectedBuffers("120K 130K");
   CheckNoNextBuffer();
 
   // Check the final result: should not include data from the track buffer.
@@ -1820,7 +1926,8 @@ TEST_F(SourceBufferStreamTest, Seek_StartOfSegment) {
 
   // GetNextBuffer() should return the next buffer at position (5 + |bump|).
   EXPECT_EQ(stream_->GetNextBuffer(&buffer), SourceBufferStream::kSuccess);
-  EXPECT_EQ(buffer->GetDecodeTimestamp(), 5 * frame_duration() + bump);
+  EXPECT_EQ(buffer->GetDecodeTimestamp(),
+            DecodeTimestamp::FromPresentationTime(5 * frame_duration() + bump));
 
   // Check rest of buffers.
   CheckExpectedBuffers(6, 9);
@@ -1834,7 +1941,8 @@ TEST_F(SourceBufferStreamTest, Seek_StartOfSegment) {
 
   // GetNextBuffer() should return the next buffer at position (15 + |bump|).
   EXPECT_EQ(stream_->GetNextBuffer(&buffer), SourceBufferStream::kSuccess);
-  EXPECT_EQ(buffer->GetDecodeTimestamp(), 15 * frame_duration() + bump);
+  EXPECT_EQ(buffer->GetDecodeTimestamp(), DecodeTimestamp::FromPresentationTime(
+      15 * frame_duration() + bump));
 
   // Check rest of buffers.
   CheckExpectedBuffers(16, 19);
@@ -2080,7 +2188,7 @@ TEST_F(SourceBufferStreamTest, GetNextBuffer_ExhaustThenStartOverlap2) {
   CheckNoNextBuffer();
 
   // Append a keyframe with the same timestamp as the last buffer output.
-  NewSegmentAppend("120K");
+  NewSegmentAppend("120D30K");
   CheckNoNextBuffer();
 
   // Append the rest of the segment and make sure that buffers are returned
@@ -2194,7 +2302,8 @@ TEST_F(SourceBufferStreamTest, PresentationTimestampIndependence) {
     ASSERT_EQ(stream_->GetNextBuffer(&buffer), SourceBufferStream::kSuccess);
 
     if (buffer->IsKeyframe()) {
-      EXPECT_EQ(buffer->timestamp(), buffer->GetDecodeTimestamp());
+      EXPECT_EQ(DecodeTimestamp::FromPresentationTime(buffer->timestamp()),
+                buffer->GetDecodeTimestamp());
       last_keyframe_idx = i;
       last_keyframe_presentation_timestamp = buffer->timestamp();
     } else if (i == last_keyframe_idx + 1) {
@@ -2205,7 +2314,8 @@ TEST_F(SourceBufferStreamTest, PresentationTimestampIndependence) {
     } else {
       EXPECT_GT(buffer->timestamp(), last_keyframe_presentation_timestamp);
       EXPECT_LT(buffer->timestamp(), last_p_frame_presentation_timestamp);
-      EXPECT_LT(buffer->timestamp(), buffer->GetDecodeTimestamp());
+      EXPECT_LT(DecodeTimestamp::FromPresentationTime(buffer->timestamp()),
+                buffer->GetDecodeTimestamp());
     }
   }
 }
@@ -2508,7 +2618,7 @@ TEST_F(SourceBufferStreamTest, GarbageCollection_SaveAppendGOP) {
 
   // Make sure you can continue appending data to this GOP; again, GC should not
   // wipe out anything.
-  AppendBuffers("120");
+  AppendBuffers("120D30");
   CheckExpectedRangesByTimestamp("{ [0,150) }");
 
   // Set memory limit to 100 and append a 2nd range after this without
@@ -2530,7 +2640,7 @@ TEST_F(SourceBufferStreamTest, GarbageCollection_SaveAppendGOP) {
   CheckExpectedRangesByTimestamp("{ [290,380) [500,620) }");
 
   // Continue appending to this GOP after GC.
-  AppendBuffers("620");
+  AppendBuffers("620D30");
   CheckExpectedRangesByTimestamp("{ [290,380) [500,650) }");
 }
 
@@ -2549,7 +2659,7 @@ TEST_F(SourceBufferStreamTest, GarbageCollection_SaveAppendGOP_Middle) {
   // This whole GOP should be saved, and should be able to continue appending
   // data to it.
   CheckExpectedRangesByTimestamp("{ [80,170) }");
-  AppendBuffers("170");
+  AppendBuffers("170D30");
   CheckExpectedRangesByTimestamp("{ [80,200) }");
 
   // Set memory limit to 100 and append a 2nd range after this without
@@ -2572,7 +2682,7 @@ TEST_F(SourceBufferStreamTest, GarbageCollection_SaveAppendGOP_Middle) {
   CheckExpectedRangesByTimestamp("{ [80,200) [500,620) }");
 
   // Continue appending to this GOP after GC.
-  AppendBuffers("620");
+  AppendBuffers("620D30");
   CheckExpectedRangesByTimestamp("{ [80,200) [500,650) }");
 }
 
@@ -3469,6 +3579,33 @@ TEST_F(SourceBufferStreamTest, Remove_GOPBeingAppended) {
   CheckExpectedBuffers("240K 270 300");
 }
 
+TEST_F(SourceBufferStreamTest, Remove_WholeGOPBeingAppended) {
+  Seek(0);
+  NewSegmentAppend("0K 30 60 90");
+  CheckExpectedRangesByTimestamp("{ [0,120) }");
+
+  // Remove the keyframe of the current GOP being appended.
+  RemoveInMs(0, 30, 120);
+  CheckExpectedRangesByTimestamp("{ }");
+
+  // Continue appending the current GOP.
+  AppendBuffers("210 240");
+
+  CheckExpectedRangesByTimestamp("{ }");
+
+  // Append the beginning of the next GOP.
+  AppendBuffers("270K 300");
+
+  // Verify that the new range is started at the
+  // beginning of the next GOP.
+  CheckExpectedRangesByTimestamp("{ [270,330) }");
+
+  // Verify the buffers in the ranges.
+  CheckNoNextBuffer();
+  SeekToTimestamp(base::TimeDelta::FromMilliseconds(270));
+  CheckExpectedBuffers("270K 300");
+}
+
 TEST_F(SourceBufferStreamTest,
        Remove_PreviousAppendDestroyedAndOverwriteExistingRange) {
   SeekToTimestamp(base::TimeDelta::FromMilliseconds(90));
@@ -3493,6 +3630,36 @@ TEST_F(SourceBufferStreamTest,
   CheckExpectedBuffers("90K 121 151");
 }
 
+TEST_F(SourceBufferStreamTest, Remove_GapAtBeginningOfMediaSegment) {
+  Seek(0);
+
+  // Append a media segment that has a gap at the beginning of it.
+  NewSegmentAppend(base::TimeDelta::FromMilliseconds(0),
+                   "30K 60 90 120K 150");
+  CheckExpectedRangesByTimestamp("{ [0,180) }");
+
+  // Remove the gap that doesn't contain any buffers.
+  RemoveInMs(0, 10, 180);
+  CheckExpectedRangesByTimestamp("{ [10,180) }");
+
+  // Verify we still get the first buffer still since only part of
+  // the gap was removed.
+  // TODO(acolwell/wolenetz): Consider not returning a buffer at this
+  // point since the current seek position has been explicitly
+  // removed but didn't happen to remove any buffers.
+  // http://crbug.com/384016
+  CheckExpectedBuffers("30K");
+
+  // Remove a range that includes the first GOP.
+  RemoveInMs(0, 60, 180);
+
+  // Verify that no buffer is returned because the current buffer
+  // position has been removed.
+  CheckNoNextBuffer();
+
+  CheckExpectedRangesByTimestamp("{ [120,180) }");
+}
+
 TEST_F(SourceBufferStreamTest, Text_Append_SingleRange) {
   SetTextStream();
   NewSegmentAppend("0K 500K 1000K");
@@ -3530,7 +3697,7 @@ TEST_F(SourceBufferStreamTest, Text_CompleteOverlap) {
   CheckExpectedRangesByTimestamp("{ [3000,4500) }");
   NewSegmentAppend("0K 501K 1001K 1501K 2001K 2501K "
                    "3001K 3501K 4001K 4501K 5001K");
-  CheckExpectedRangesByTimestamp("{ [0,5502) }");
+  CheckExpectedRangesByTimestamp("{ [0,5501) }");
 
   Seek(0);
   CheckExpectedBuffers("0K 501K 1001K 1501K 2001K 2501K "
@@ -3542,7 +3709,7 @@ TEST_F(SourceBufferStreamTest, Text_OverlapAfter) {
   NewSegmentAppend("0K 500K 1000K 1500K 2000K");
   CheckExpectedRangesByTimestamp("{ [0,2500) }");
   NewSegmentAppend("1499K 2001K 2501K 3001K");
-  CheckExpectedRangesByTimestamp("{ [0,3503) }");
+  CheckExpectedRangesByTimestamp("{ [0,3501) }");
 
   Seek(0);
   CheckExpectedBuffers("0K 500K 1000K 1499K 2001K 2501K 3001K");
@@ -3553,22 +3720,22 @@ TEST_F(SourceBufferStreamTest, Text_OverlapBefore) {
   NewSegmentAppend("1500K 2000K 2500K 3000K 3500K");
   CheckExpectedRangesByTimestamp("{ [1500,4000) }");
   NewSegmentAppend("0K 501K 1001K 1501K 2001K");
-  CheckExpectedRangesByTimestamp("{ [0,4001) }");
+  CheckExpectedRangesByTimestamp("{ [0,4000) }");
 
   Seek(0);
-  CheckExpectedBuffers("0K 501K 1001K 1501K 2001K 2500K 3000K 3500K");
+  CheckExpectedBuffers("0K 501K 1001K 1501K 2001K 3000K 3500K");
 }
 
 TEST_F(SourceBufferStreamTest, SpliceFrame_Basic) {
   Seek(0);
-  NewSegmentAppend("0K S(3K 6 9 10) 15 20 S(25K 30 35) 40");
+  NewSegmentAppend("0K S(3K 6 9D3 10D5) 15 20 S(25K 30D5 35D5) 40");
   CheckExpectedBuffers("0K 3K 6 9 C 10 15 20 25K 30 C 35 40");
   CheckNoNextBuffer();
 }
 
 TEST_F(SourceBufferStreamTest, SpliceFrame_SeekClearsSplice) {
   Seek(0);
-  NewSegmentAppend("0K S(3K 6 9 10) 15K 20");
+  NewSegmentAppend("0K S(3K 6 9D3 10D5) 15K 20");
   CheckExpectedBuffers("0K 3K 6");
 
   SeekToTimestamp(base::TimeDelta::FromMilliseconds(15));
@@ -3578,7 +3745,7 @@ TEST_F(SourceBufferStreamTest, SpliceFrame_SeekClearsSplice) {
 
 TEST_F(SourceBufferStreamTest, SpliceFrame_SeekClearsSpliceFromTrackBuffer) {
   Seek(0);
-  NewSegmentAppend("0K 2K S(3K 6 9 10) 15K 20");
+  NewSegmentAppend("0K 2K S(3K 6 9D3 10D5) 15K 20");
   CheckExpectedBuffers("0K 2K");
 
   // Overlap the existing segment.
@@ -3600,7 +3767,7 @@ TEST_F(SourceBufferStreamTest, SpliceFrame_ConfigChangeWithinSplice) {
 
   Seek(0);
   CheckVideoConfig(video_config_);
-  NewSegmentAppend("0K S(3K 6C 9 10) 15");
+  NewSegmentAppend("0K S(3K 6C 9D3 10D5) 15");
 
   CheckExpectedBuffers("0K 3K C");
   CheckVideoConfig(new_config);
@@ -3613,7 +3780,7 @@ TEST_F(SourceBufferStreamTest, SpliceFrame_ConfigChangeWithinSplice) {
 
 TEST_F(SourceBufferStreamTest, SpliceFrame_BasicFromTrackBuffer) {
   Seek(0);
-  NewSegmentAppend("0K 5K S(8K 9 10) 20");
+  NewSegmentAppend("0K 5K S(8K 9D1 10D10) 20");
   CheckExpectedBuffers("0K 5K");
 
   // Overlap the existing segment.
@@ -3633,7 +3800,7 @@ TEST_F(SourceBufferStreamTest,
 
   Seek(0);
   CheckVideoConfig(video_config_);
-  NewSegmentAppend("0K 5K S(7K 8C 9 10) 20");
+  NewSegmentAppend("0K 5K S(7K 8C 9D1 10D10) 20");
   CheckExpectedBuffers("0K 5K");
 
   // Overlap the existing segment.
@@ -3678,7 +3845,7 @@ TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_NoDoubleSplice) {
   Seek(0);
 
   // Create a splice before the first splice which would include it.
-  NewSegmentAppend("9K");
+  NewSegmentAppend("9D2K");
 
   // A splice on top of a splice should result in a discard of the original
   // splice and no new splice frame being generated.
@@ -3704,7 +3871,7 @@ TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_CorrectMediaSegmentStartTime) {
   CheckExpectedRangesByTimestamp("{ [0,6) }");
   NewSegmentAppend("6K 8K 10K");
   CheckExpectedRangesByTimestamp("{ [0,12) }");
-  NewSegmentAppend("1K 4K");
+  NewSegmentAppend("1K 4D2K");
   CheckExpectedRangesByTimestamp("{ [0,12) }");
   CheckExpectedBuffers("0K 2K 4K C 1K 4K 6K 8K 10K");
   CheckNoNextBuffer();
@@ -3741,14 +3908,39 @@ TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_NoTinySplices) {
   // 2ms this results in an overlap of 1ms between the ranges.  A splice frame
   // should not be generated since it requires at least 2 frames, or 2ms in this
   // case, of data to crossfade.
-  NewSegmentAppend("0K");
+  NewSegmentAppend("0D2K");
   CheckExpectedRangesByTimestamp("{ [0,2) }");
-  NewSegmentAppend("1K");
+  NewSegmentAppend("1D2K");
   CheckExpectedRangesByTimestamp("{ [0,3) }");
   CheckExpectedBuffers("0K 1K");
   CheckNoNextBuffer();
 }
 
+TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_Preroll) {
+  SetAudioStream();
+  Seek(0);
+  NewSegmentAppend("0K 2K 4K 6K 8K 10K 12K");
+  NewSegmentAppend("11P 13K 15K 17K");
+  CheckExpectedBuffers("0K 2K 4K 6K 8K 10K 12K C 11P 13K 15K 17K");
+  CheckNoNextBuffer();
+}
+
+TEST_F(SourceBufferStreamTest, Audio_PrerollFrame) {
+  Seek(0);
+  NewSegmentAppend("0K 3P 6K");
+  CheckExpectedBuffers("0K 3P 6K");
+  CheckNoNextBuffer();
+}
+
+TEST_F(SourceBufferStreamTest, BFrames) {
+  Seek(0);
+  NewSegmentAppend("0K 120|30 30|60 60|90 90|120");
+  CheckExpectedRangesByTimestamp("{ [0,150) }");
+
+  CheckExpectedBuffers("0K 120|30 30|60 60|90 90|120");
+  CheckNoNextBuffer();
+}
+
 // TODO(vrk): Add unit tests where keyframes are unaligned between streams.
 // (crbug.com/133557)