Bug 599217 - WebM buffered: should use duration for end time of last buffered range. r=kinetik
authorPaul Adenot <paul@paul.cx>
Fri, 24 Sep 2010 13:57:30 +1200
changeset 93982 7da36f8c159a1c7eab74063c0c620863c4ed9580
parent 93981 b15a3c5dd0e6abab3098e1134f827aaae2a6a74b
child 93983 09da30d622c013332a84261a3b7b2819c09dc8fe
push id9404
push userryanvm@gmail.com
push dateTue, 15 May 2012 13:02:31 +0000
treeherdermozilla-inbound@e1fcace4621d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskinetik
bugs599217
milestone15.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 599217 - WebM buffered: should use duration for end time of last buffered range. r=kinetik
content/media/webm/nsWebMBufferedParser.cpp
content/media/webm/nsWebMBufferedParser.h
content/media/webm/nsWebMReader.cpp
--- a/content/media/webm/nsWebMBufferedParser.cpp
+++ b/content/media/webm/nsWebMBufferedParser.cpp
@@ -204,41 +204,39 @@ void nsWebMBufferedParser::Append(const 
       break;
     }
   }
 
   NS_ASSERTION(p == aBuffer + aLength, "Must have parsed to end of data.");
   mCurrentOffset += aLength;
 }
 
-void nsWebMBufferedState::CalculateBufferedForRange(nsTimeRanges* aBuffered,
-                                                    PRInt64 aStartOffset, PRInt64 aEndOffset,
-                                                    PRUint64 aTimecodeScale,
-                                                    PRInt64 aStartTimeOffsetNS)
+bool nsWebMBufferedState::CalculateBufferedForRange(PRInt64 aStartOffset, PRInt64 aEndOffset,
+                                                    PRUint64* aStartTime, PRUint64* aEndTime)
 {
   ReentrantMonitorAutoEnter mon(mReentrantMonitor);
 
   // Find the first nsWebMTimeDataOffset at or after aStartOffset.
   PRUint32 start;
   mTimeMapping.GreatestIndexLtEq(aStartOffset, start);
   if (start == mTimeMapping.Length()) {
-    return;
+    return false;
   }
 
   // Find the first nsWebMTimeDataOffset at or before aEndOffset.
   PRUint32 end;
   if (!mTimeMapping.GreatestIndexLtEq(aEndOffset, end) && end > 0) {
     // No exact match, so adjust end to be the first entry before
     // aEndOffset.
     end -= 1;
   }
 
   // Range is empty.
   if (end <= start) {
-    return;
+    return false;
   }
 
   NS_ASSERTION(mTimeMapping[start].mOffset >= aStartOffset &&
                mTimeMapping[end].mOffset <= aEndOffset,
                "Computed time range must lie within data range.");
   if (start > 0) {
     NS_ASSERTION(mTimeMapping[start - 1].mOffset <= aStartOffset,
                  "Must have found least nsWebMTimeDataOffset for start");
@@ -247,19 +245,19 @@ void nsWebMBufferedState::CalculateBuffe
     NS_ASSERTION(mTimeMapping[end + 1].mOffset >= aEndOffset,
                  "Must have found greatest nsWebMTimeDataOffset for end");
   }
 
   // The timestamp of the first media sample, in ns. We must subtract this
   // from the ranges' start and end timestamps, so that those timestamps are
   // normalized in the range [0,duration].
 
-  double startTime = (mTimeMapping[start].mTimecode * aTimecodeScale - aStartTimeOffsetNS) / NS_PER_S;
-  double endTime = (mTimeMapping[end].mTimecode * aTimecodeScale - aStartTimeOffsetNS) / NS_PER_S;
-  aBuffered->Add(startTime, endTime);
+  *aStartTime = mTimeMapping[start].mTimecode;
+  *aEndTime = mTimeMapping[end].mTimecode;
+  return true;
 }
 
 void nsWebMBufferedState::NotifyDataArrived(const char* aBuffer, PRUint32 aLength, PRInt64 aOffset)
 {
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
   PRUint32 idx;
   if (!mRangeParsers.GreatestIndexLtEq(aOffset, idx)) {
     // If the incoming data overlaps an already parsed range, adjust the
--- a/content/media/webm/nsWebMBufferedParser.h
+++ b/content/media/webm/nsWebMBufferedParser.h
@@ -220,20 +220,18 @@ public:
     MOZ_COUNT_CTOR(nsWebMBufferedState);
   }
 
   ~nsWebMBufferedState() {
     MOZ_COUNT_DTOR(nsWebMBufferedState);
   }
 
   void NotifyDataArrived(const char* aBuffer, PRUint32 aLength, PRInt64 aOffset);
-  void CalculateBufferedForRange(nsTimeRanges* aBuffered,
-                                 PRInt64 aStartOffset, PRInt64 aEndOffset,
-                                 PRUint64 aTimecodeScale,
-                                 PRInt64 aStartTimeOffsetNS);
+  bool CalculateBufferedForRange(PRInt64 aStartOffset, PRInt64 aEndOffset,
+                                 PRUint64* aStartTime, PRUint64* aEndTime);
 
 private:
   // Synchronizes access to the mTimeMapping array.
   ReentrantMonitor mReentrantMonitor;
 
   // Sorted (by offset) map of data offsets to timecodes.  Populated
   // on the main thread as data is received and parsed by nsWebMBufferedParsers.
   nsTArray<nsWebMTimeDataOffset> mTimeMapping;
--- a/content/media/webm/nsWebMReader.cpp
+++ b/content/media/webm/nsWebMReader.cpp
@@ -786,34 +786,55 @@ nsresult nsWebMReader::GetBuffered(nsTim
   MediaResource* resource = mDecoder->GetResource();
 
   uint64_t timecodeScale;
   if (!mContext || nestegg_tstamp_scale(mContext, &timecodeScale) == -1) {
     return NS_OK;
   }
 
   // Special case completely cached files.  This also handles local files.
-  if (resource->IsDataCachedToEndOfResource(0)) {
+  bool isFullyCached = resource->IsDataCachedToEndOfResource(0);
+  if (isFullyCached) {
     uint64_t duration = 0;
     if (nestegg_duration(mContext, &duration) == 0) {
       aBuffered->Add(0, duration / NS_PER_S);
     }
-  } else {
+  }
+
+  PRUint32 bufferedLength = 0;
+  aBuffered->GetLength(&bufferedLength);
+
+  // Either we the file is not fully cached, or we couldn't find a duration in
+  // the WebM bitstream.
+  if (!isFullyCached || !bufferedLength) {
     MediaResource* resource = mDecoder->GetResource();
     nsTArray<MediaByteRange> ranges;
     nsresult res = resource->GetCachedRanges(ranges);
     NS_ENSURE_SUCCESS(res, res);
 
-    PRInt64 startTimeOffsetNS = aStartTime * NS_PER_USEC;
     for (PRUint32 index = 0; index < ranges.Length(); index++) {
-      mBufferedState->CalculateBufferedForRange(aBuffered,
-                                                ranges[index].mStart,
-                                                ranges[index].mEnd,
-                                                timecodeScale,
-                                                startTimeOffsetNS);
+      PRUint64 start, end;
+      bool rv = mBufferedState->CalculateBufferedForRange(ranges[index].mStart,
+                                                          ranges[index].mEnd,
+                                                          &start, &end);
+      if (rv) {
+        double startTime = start * timecodeScale / NS_PER_S - aStartTime;
+        double endTime = end * timecodeScale / NS_PER_S - aStartTime;
+
+        // If this range extends to the end of the file, the true end time
+        // is the file's duration.
+        if (resource->IsDataCachedToEndOfResource(ranges[index].mStart)) {
+          uint64_t duration = 0;
+          if (nestegg_duration(mContext, &duration) == 0) {
+            endTime = duration / NS_PER_S;
+          }
+        }
+
+        aBuffered->Add(startTime, endTime);
+      }
     }
   }
 
   return NS_OK;
 }
 
 void nsWebMReader::NotifyDataArrived(const char* aBuffer, PRUint32 aLength, PRInt64 aOffset)
 {