Bug 1138260 - Add typed Microseconds class and use it for the range removal algorithm. r=jya, r=kinetik, a=sledru
authorMatt Woodrow <mwoodrow@mozilla.com>
Tue, 03 Mar 2015 17:38:45 +1300
changeset 258242 67259acf0c1e
parent 258241 0fce0415d8b4
child 258243 bfe014dd05ef
push id4627
push userryanvm@gmail.com
push date2015-04-03 19:22 +0000
treeherdermozilla-beta@5f5a4c5a7e02 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjya, kinetik, sledru
bugs1138260
milestone38.0
Bug 1138260 - Add typed Microseconds class and use it for the range removal algorithm. r=jya, r=kinetik, a=sledru
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 size=%lld",
                   buffered->GetEndTime(),
                   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',
 ]