Bug 1138260 - Add typed Microseconds class and use it for the range removal algorithm. r=jya,kinetik
authorMatt Woodrow <mwoodrow@mozilla.com>
Tue, 03 Mar 2015 17:38:45 +1300
changeset 231526 d08d7a1a55ba
parent 231525 78b34d0e414a
child 231527 743bc389a2ce
push id28353
push usercbook@mozilla.com
push dateTue, 03 Mar 2015 12:54:59 +0000
treeherdermozilla-central@985070813323 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjya, kinetik
bugs1138260
milestone39.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 1138260 - Add typed Microseconds class and use it for the range removal algorithm. r=jya,kinetik
dom/media/TimeUnits.h
dom/media/mediasource/SourceBuffer.cpp
dom/media/mediasource/TrackBuffer.cpp
dom/media/mediasource/TrackBuffer.h
dom/media/moz.build
new file mode 100644
--- /dev/null
+++ b/dom/media/TimeUnits.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef TIME_UNITS_H
+#define TIME_UNITS_H
+
+#include "VideoUtils.h"
+#include "mozilla/FloatingPoint.h"
+
+namespace mozilla {
+namespace media {
+
+struct Microseconds {
+  Microseconds()
+    : mValue(0)
+  {}
+
+  explicit Microseconds(int64_t aValue)
+    : mValue(aValue)
+  {}
+
+  double ToSeconds() {
+    return double(mValue) / USECS_PER_S;
+  }
+
+  static Microseconds FromSeconds(double aValue) {
+    MOZ_ASSERT(!IsNaN(aValue));
+
+    double val = aValue * USECS_PER_S;
+    if (val >= double(INT64_MAX)) {
+      return Microseconds(INT64_MAX);
+    } else if (val <= double(INT64_MIN)) {
+      return Microseconds(INT64_MIN);
+    } else {
+      return Microseconds(int64_t(val));
+    }
+  }
+
+  bool operator > (const Microseconds& aOther) const {
+    return mValue > aOther.mValue;
+  }
+  bool operator >= (const Microseconds& aOther) const {
+    return mValue >= aOther.mValue;
+  }
+  bool operator < (const Microseconds& aOther) const {
+    return mValue < aOther.mValue;
+  }
+  bool operator <= (const Microseconds& aOther) const {
+    return mValue <= aOther.mValue;
+  }
+
+  int64_t mValue;
+};
+
+
+}
+}
+
+#endif // TIME_UNITS_H
--- a/dom/media/mediasource/SourceBuffer.cpp
+++ b/dom/media/mediasource/SourceBuffer.cpp
@@ -16,16 +16,17 @@
 #include "mozilla/dom/MediaSourceBinding.h"
 #include "mozilla/dom/TimeRanges.h"
 #include "nsError.h"
 #include "nsIEventTarget.h"
 #include "nsIRunnable.h"
 #include "nsThreadUtils.h"
 #include "prlog.h"
 #include <time.h>
+#include "TimeUnits.h"
 
 struct JSContext;
 class JSObject;
 
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* GetMediaSourceLog();
 extern PRLogModuleInfo* GetMediaSourceAPILog();
 
@@ -281,19 +282,18 @@ SourceBuffer::RangeRemoval(double aStart
   NS_DispatchToMainThread(task);
 }
 
 void
 SourceBuffer::DoRangeRemoval(double aStart, double aEnd)
 {
   MSE_DEBUG("DoRangeRemoval(%f, %f)", aStart, aEnd);
   if (mTrackBuffer && !IsInfinite(aStart)) {
-    int64_t start = aStart * USECS_PER_S;
-    int64_t end = IsInfinite(aEnd) ? INT64_MAX : (int64_t)(aEnd * USECS_PER_S);
-    mTrackBuffer->RangeRemoval(start, end);
+    mTrackBuffer->RangeRemoval(media::Microseconds::FromSeconds(aStart),
+                               media::Microseconds::FromSeconds(aEnd));
   }
 }
 
 void
 SourceBuffer::Detach()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MSE_DEBUG("Detach");
--- a/dom/media/mediasource/TrackBuffer.cpp
+++ b/dom/media/mediasource/TrackBuffer.cpp
@@ -966,26 +966,27 @@ TrackBuffer::RemoveDecoder(SourceBufferD
     MOZ_ASSERT(!mParentDecoder->IsActiveReader(aDecoder->GetReader()));
     mInitializedDecoders.RemoveElement(aDecoder);
     mDecoders.RemoveElement(aDecoder);
   }
   aDecoder->GetReader()->GetTaskQueue()->Dispatch(task);
 }
 
 bool
-TrackBuffer::RangeRemoval(int64_t aStart, int64_t aEnd)
+TrackBuffer::RangeRemoval(media::Microseconds aStart,
+                          media::Microseconds aEnd)
 {
   MOZ_ASSERT(NS_IsMainThread());
   ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
 
   nsRefPtr<dom::TimeRanges> buffered = new dom::TimeRanges();
-  int64_t bufferedEnd = Buffered(buffered) * USECS_PER_S;
-  int64_t bufferedStart = buffered->GetStartTime() * USECS_PER_S;
+  media::Microseconds bufferedEnd = media::Microseconds::FromSeconds(Buffered(buffered));
+  media::Microseconds bufferedStart = media::Microseconds::FromSeconds(buffered->GetStartTime());
 
-  if (bufferedStart < 0 || aStart > bufferedEnd || aEnd < bufferedStart) {
+  if (bufferedStart < media::Microseconds(0) || aStart > bufferedEnd || aEnd < bufferedStart) {
     // Nothing to remove.
     return false;
   }
 
   if (aStart > bufferedStart && aEnd < bufferedEnd) {
     // TODO. We only handle trimming and removal from the start.
     NS_WARNING("RangeRemoval unsupported arguments. "
                "Can only handle trimming (trim left or trim right");
@@ -995,40 +996,40 @@ TrackBuffer::RangeRemoval(int64_t aStart
   nsTArray<SourceBufferDecoder*> decoders;
   decoders.AppendElements(mInitializedDecoders);
 
   if (aStart <= bufferedStart && aEnd < bufferedEnd) {
     // Evict data from beginning.
     for (size_t i = 0; i < decoders.Length(); ++i) {
       nsRefPtr<dom::TimeRanges> buffered = new dom::TimeRanges();
       decoders[i]->GetBuffered(buffered);
-      if (int64_t(buffered->GetEndTime() * USECS_PER_S) < aEnd) {
+      if (media::Microseconds::FromSeconds(buffered->GetEndTime()) < aEnd) {
         // Can be fully removed.
         MSE_DEBUG("remove all bufferedEnd=%f time=%f, size=%lld",
                   buffered->GetEndTime(), time,
                   decoders[i]->GetResource()->GetSize());
         decoders[i]->GetResource()->EvictAll();
       } else {
-        int64_t offset = decoders[i]->ConvertToByteOffset(aEnd);
+        int64_t offset = decoders[i]->ConvertToByteOffset(aEnd.ToSeconds());
         MSE_DEBUG("removing some bufferedEnd=%f offset=%lld size=%lld",
                   buffered->GetEndTime(), offset,
                   decoders[i]->GetResource()->GetSize());
         if (offset > 0) {
           decoders[i]->GetResource()->EvictData(offset, offset);
         }
       }
     }
   } else {
     // Only trimming existing buffers.
     for (size_t i = 0; i < decoders.Length(); ++i) {
-      if (aStart <= int64_t(buffered->GetStartTime() * USECS_PER_S)) {
+      if (aStart <= media::Microseconds::FromSeconds(buffered->GetStartTime())) {
         // It will be entirely emptied, can clear all data.
         decoders[i]->GetResource()->EvictAll();
       } else {
-        decoders[i]->Trim(aStart);
+        decoders[i]->Trim(aStart.mValue);
       }
     }
   }
 
   RemoveEmptyDecoders(decoders);
 
   return true;
 }
--- a/dom/media/mediasource/TrackBuffer.h
+++ b/dom/media/mediasource/TrackBuffer.h
@@ -11,16 +11,17 @@
 #include "SourceBufferDecoder.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/mozalloc.h"
 #include "mozilla/Maybe.h"
 #include "nsCOMPtr.h"
 #include "nsString.h"
 #include "nscore.h"
+#include "TimeUnits.h"
 
 namespace mozilla {
 
 class ContainerParser;
 class MediaSourceDecoder;
 class LargeDataBuffer;
 
 namespace dom {
@@ -91,17 +92,18 @@ public:
   // TODO: Refactor to a cleaner interface between TrackBuffer and MediaSourceReader.
   const nsTArray<nsRefPtr<SourceBufferDecoder>>& Decoders();
 
   // Runs MSE range removal algorithm.
   // http://w3c.github.io/media-source/#sourcebuffer-coded-frame-removal
   // Implementation is only partial, we can only trim a buffer.
   // Returns true if data was evicted.
   // Times are in microseconds.
-  bool RangeRemoval(int64_t aStart, int64_t aEnd);
+  bool RangeRemoval(mozilla::media::Microseconds aStart,
+                    mozilla::media::Microseconds aEnd);
 
   // Abort any pending appendBuffer by rejecting any pending promises.
   void AbortAppendData();
 
   // Return the size used by all decoders managed by this TrackBuffer.
   int64_t GetSize();
 
   // Return true if we have a partial media segment being appended that is
--- a/dom/media/moz.build
+++ b/dom/media/moz.build
@@ -117,16 +117,17 @@ EXPORTS += [
     'MP3FrameParser.h',
     'nsIDocumentActivity.h',
     'RtspMediaResource.h',
     'SelfRef.h',
     'SharedBuffer.h',
     'SharedThreadPool.h',
     'StreamBuffer.h',
     'ThreadPoolCOMListener.h',
+    'TimeUnits.h',
     'TimeVarying.h',
     'TrackUnionStream.h',
     'VideoFrameContainer.h',
     'VideoSegment.h',
     'VideoUtils.h',
     'VorbisUtils.h',
 ]