Bug 1000608 - Implement cue-less seeking on WebM Reader - r=kinetik
authorcajbir <cajbir.bugzilla@cd.pn>
Wed, 23 Apr 2014 19:47:00 +1200
changeset 180406 f398aa51c65a
parent 180405 a336e673aaf5
child 180407 d75260ca4ed2
push id26663
push userryanvm@gmail.com
push dateSun, 27 Apr 2014 01:52:51 +0000
treeherdermozilla-central@fcf19894d9f3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskinetik
bugs1000608
milestone31.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1000608 - Implement cue-less seeking on WebM Reader - r=kinetik
content/media/webm/WebMBufferedParser.cpp
content/media/webm/WebMBufferedParser.h
content/media/webm/WebMReader.cpp
--- a/content/media/webm/WebMBufferedParser.cpp
+++ b/content/media/webm/WebMBufferedParser.cpp
@@ -214,16 +214,32 @@ bool WebMBufferedState::CalculateBuffere
   // from the ranges' start and end timestamps, so that those timestamps are
   // normalized in the range [0,duration].
 
   *aStartTime = mTimeMapping[start].mTimecode;
   *aEndTime = mTimeMapping[end].mTimecode;
   return true;
 }
 
+bool WebMBufferedState::GetOffsetForTime(uint64_t aTime, int64_t* aOffset)
+{
+  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+  WebMTimeDataOffset result(0,0);
+
+  for (uint32_t i = 0; i < mTimeMapping.Length(); ++i) {
+    WebMTimeDataOffset o = mTimeMapping[i];
+    if (o.mTimecode < aTime && o.mTimecode > result.mTimecode) {
+      result = o;
+    }
+  }
+
+  *aOffset = result.mOffset;
+  return true;
+}
+
 void WebMBufferedState::NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset)
 {
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
   uint32_t idx = mRangeParsers.IndexOfFirstElementGt(aOffset - 1);
   if (idx == 0 || !(mRangeParsers[idx-1] == aOffset)) {
     // If the incoming data overlaps an already parsed range, adjust the
     // buffer so that we only reparse the new data.  It's also possible to
     // have an overlap where the end of the incoming data is within an
--- a/content/media/webm/WebMBufferedParser.h
+++ b/content/media/webm/WebMBufferedParser.h
@@ -189,16 +189,17 @@ class WebMBufferedState MOZ_FINAL
 public:
   WebMBufferedState() : mReentrantMonitor("WebMBufferedState") {
     MOZ_COUNT_CTOR(WebMBufferedState);
   }
 
   void NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset);
   bool CalculateBufferedForRange(int64_t aStartOffset, int64_t aEndOffset,
                                  uint64_t* aStartTime, uint64_t* aEndTime);
+  bool GetOffsetForTime(uint64_t aTime, int64_t* aOffset);
 
 private:
   // Private destructor, to discourage deletion outside of Release():
   ~WebMBufferedState() {
     MOZ_COUNT_DTOR(WebMBufferedState);
   }
 
   // Synchronizes access to the mTimeMapping array.
--- a/content/media/webm/WebMReader.cpp
+++ b/content/media/webm/WebMReader.cpp
@@ -999,17 +999,27 @@ nsresult WebMReader::Seek(int64_t aTarge
   }
   uint32_t trackToSeek = mHasVideo ? mVideoTrack : mAudioTrack;
   uint64_t target = aTarget * NS_PER_USEC;
   if (mSeekPreroll) {
     target = std::max(static_cast<uint64_t>(aStartTime * NS_PER_USEC), target - mSeekPreroll);
   }
   int r = nestegg_track_seek(mContext, trackToSeek, target);
   if (r != 0) {
-    return NS_ERROR_FAILURE;
+    // Try seeking directly based on cluster information in memory.
+    int64_t offset = 0;
+    bool rv = mBufferedState->GetOffsetForTime((aTarget - aStartTime)/NS_PER_USEC, &offset);
+    if (!rv) {
+      return NS_ERROR_FAILURE;
+    }
+
+    r = nestegg_offset_seek(mContext, offset);
+    if (r != 0) {
+      return NS_ERROR_FAILURE;
+    }
   }
   return NS_OK;
 }
 
 nsresult WebMReader::GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime)
 {
   MediaResource* resource = mDecoder->GetResource();