Bug 1062666 - Add a debug-only dump method to MediaSource for debugging issues with appended data.
☠☠ backed out by b36d31ca6e14 ☠ ☠
authorMatthew Gregan <kinetik@flim.org>
Tue, 09 Sep 2014 17:58:18 +1200
changeset 204730 b3f02eb02208092fd717e126b1dad3592b03ac7b
parent 204729 2097b83ffbab847fa200bb891fc0bd3ac98d3463
child 204731 b36d31ca6e1464f9749713fe62b280bcf5aec274
push id48988
push usermgregan@mozilla.com
push dateThu, 11 Sep 2014 04:21:56 +0000
treeherdermozilla-inbound@b3f02eb02208 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1062666
milestone35.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 1062666 - Add a debug-only dump method to MediaSource for debugging issues with appended data.
content/media/mediasource/MediaSource.cpp
content/media/mediasource/MediaSource.h
content/media/mediasource/ResourceQueue.h
content/media/mediasource/SourceBuffer.cpp
content/media/mediasource/SourceBuffer.h
content/media/mediasource/SourceBufferDecoder.cpp
content/media/mediasource/SourceBufferList.cpp
content/media/mediasource/SourceBufferList.h
content/media/mediasource/SourceBufferResource.h
content/media/mediasource/TrackBuffer.cpp
content/media/mediasource/TrackBuffer.h
--- a/content/media/mediasource/MediaSource.cpp
+++ b/content/media/mediasource/MediaSource.cpp
@@ -23,16 +23,21 @@
 #include "nsError.h"
 #include "nsIEventTarget.h"
 #include "nsIRunnable.h"
 #include "nsPIDOMWindow.h"
 #include "nsString.h"
 #include "nsThreadUtils.h"
 #include "prlog.h"
 
+#if defined(DEBUG)
+#include <sys/stat.h>
+#include <sys/types.h>
+#endif
+
 struct JSContext;
 class JSObject;
 
 #ifdef PR_LOGGING
 PRLogModuleInfo* GetMediaSourceLog()
 {
   static PRLogModuleInfo* sLogModule;
   if (!sLogModule) {
@@ -502,16 +507,30 @@ MediaSource::InitializationEvent()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MSE_DEBUG("MediaSource(%p)::InitializationEvent()", this);
   if (mDecoder) {
     mDecoder->PrepareReaderInitialization();
   }
 }
 
+#if defined(DEBUG)
+void
+MediaSource::Dump(const char* aPath)
+{
+  char buf[255];
+  PR_snprintf(buf, sizeof(buf), "%s/mediasource-%p", aPath, this);
+  mkdir(buf, 0700);
+
+  if (mSourceBuffers) {
+    mSourceBuffers->Dump(buf);
+  }
+}
+#endif
+
 nsPIDOMWindow*
 MediaSource::GetParentObject() const
 {
   return GetOwner();
 }
 
 JSObject*
 MediaSource::WrapObject(JSContext* aCx)
--- a/content/media/mediasource/MediaSource.h
+++ b/content/media/mediasource/MediaSource.h
@@ -93,16 +93,22 @@ public:
   // Queue InitializationEvent to run on the main thread.  Called when a
   // SourceBuffer has an initialization segment appended, but only
   // dispatched the first time (using mFirstSourceBufferInitialization).
   // Demarcates the point in time at which only currently registered
   // TrackBuffers are treated as essential by the MediaSourceReader for
   // initialization.
   void QueueInitializationEvent();
 
+#if defined(DEBUG)
+  // Dump the contents of each SourceBuffer to a series of files under aPath.
+  // aPath must exist.  Debug only, invoke from your favourite debugger.
+  void Dump(const char* aPath);
+#endif
+
 private:
   ~MediaSource();
 
   explicit MediaSource(nsPIDOMWindow* aWindow);
 
   friend class AsyncEventRunner<MediaSource>;
   void DispatchSimpleEvent(const char* aName);
   void QueueAsyncSimpleEvent(const char* aName);
--- a/content/media/mediasource/ResourceQueue.h
+++ b/content/media/mediasource/ResourceQueue.h
@@ -129,16 +129,33 @@ public:
     for (uint32_t i = 0; i < uint32_t(GetSize()); ++i) {
       const ResourceItem* item = ResourceAt(i);
       size += item->SizeOfIncludingThis(aMallocSizeOf);
     }
 
     return size;
   }
 
+#if defined(DEBUG)
+  void Dump(const char* aPath) {
+    for (uint32_t i = 0; i < uint32_t(GetSize()); ++i) {
+      ResourceItem* item = ResourceAt(i);
+
+      char buf[255];
+      PR_snprintf(buf, sizeof(buf), "%s/%08u.bin", aPath, i);
+      FILE* fp = fopen(buf, "wb");
+      if (!fp) {
+        return;
+      }
+      fwrite(item->mData.Elements(), item->mData.Length(), 1, fp);
+      fclose(fp);
+    }
+  }
+#endif
+
 private:
   ResourceItem* ResourceAt(uint32_t aIndex) const {
     return static_cast<ResourceItem*>(ObjectAt(aIndex));
   }
 
   // Returns the index of the resource that contains the given
   // logical offset. aResourceOffset will contain the offset into
   // the resource at the given index returned if it is not null.  If
@@ -168,11 +185,10 @@ private:
 
   // Logical length of the resource.
   uint64_t mLogicalLength;
 
   // Logical offset into the resource of the first element in the queue.
   uint64_t mOffset;
 };
 
-
 } // namespace mozilla
 #endif /* MOZILLA_RESOURCEQUEUE_H_ */
--- a/content/media/mediasource/SourceBuffer.cpp
+++ b/content/media/mediasource/SourceBuffer.cpp
@@ -1,8 +1,9 @@
+/* -*- 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/. */
 
 #include "SourceBuffer.h"
 
 #include "AsyncEventRunner.h"
@@ -682,16 +683,26 @@ SourceBuffer::Evict(double aStart, doubl
   double evictTime = aEnd;
   const double safety_threshold = 5;
   if (currentTime + safety_threshold >= evictTime) {
     evictTime -= safety_threshold;
   }
   mTrackBuffer->EvictBefore(evictTime);
 }
 
+#if defined(DEBUG)
+void
+SourceBuffer::Dump(const char* aPath)
+{
+  if (mTrackBuffer) {
+    mTrackBuffer->Dump(aPath);
+  }
+}
+#endif
+
 NS_IMPL_CYCLE_COLLECTION_INHERITED(SourceBuffer, DOMEventTargetHelper,
                                    mMediaSource)
 
 NS_IMPL_ADDREF_INHERITED(SourceBuffer, DOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(SourceBuffer, DOMEventTargetHelper)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(SourceBuffer)
 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
--- a/content/media/mediasource/SourceBuffer.h
+++ b/content/media/mediasource/SourceBuffer.h
@@ -104,16 +104,20 @@ public:
   void Ended();
 
   // Evict data in the source buffer in the given time range.
   void Evict(double aStart, double aEnd);
 
   double GetBufferedStart();
   double GetBufferedEnd();
 
+#if defined(DEBUG)
+  void Dump(const char* aPath);
+#endif
+
 private:
   ~SourceBuffer();
 
   friend class AsyncEventRunner<SourceBuffer>;
   void DispatchSimpleEvent(const char* aName);
   void QueueAsyncSimpleEvent(const char* aName);
 
   // Create a new decoder for mType, and store the result in mDecoder.
--- a/content/media/mediasource/SourceBufferDecoder.cpp
+++ b/content/media/mediasource/SourceBufferDecoder.cpp
@@ -1,8 +1,9 @@
+/* -*- 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/. */
 
 #include "SourceBufferDecoder.h"
 #include "prlog.h"
 #include "AbstractMediaDecoder.h"
--- a/content/media/mediasource/SourceBufferList.cpp
+++ b/content/media/mediasource/SourceBufferList.cpp
@@ -162,16 +162,26 @@ SourceBufferList::DispatchSimpleEvent(co
 void
 SourceBufferList::QueueAsyncSimpleEvent(const char* aName)
 {
   MSE_DEBUG("SourceBufferList(%p) Queuing event '%s'", this, aName);
   nsCOMPtr<nsIRunnable> event = new AsyncEventRunner<SourceBufferList>(this, aName);
   NS_DispatchToMainThread(event);
 }
 
+#if defined(DEBUG)
+void
+SourceBufferList::Dump(const char* aPath)
+{
+  for (uint32_t i = 0; i < mSourceBuffers.Length(); ++i) {
+    mSourceBuffers[i]->Dump(aPath);
+  }
+}
+#endif
+
 SourceBufferList::SourceBufferList(MediaSource* aMediaSource)
   : DOMEventTargetHelper(aMediaSource->GetParentObject())
   , mMediaSource(aMediaSource)
 {
   MOZ_ASSERT(aMediaSource);
 }
 
 MediaSource*
--- a/content/media/mediasource/SourceBufferList.h
+++ b/content/media/mediasource/SourceBufferList.h
@@ -74,16 +74,20 @@ public:
   void Ended();
 
   // Evicts data for the given time range from each SourceBuffer in the list.
   void Evict(double aStart, double aEnd);
 
   // Returns the highest end time of any of the Sourcebuffers.
   double GetHighestBufferedEndTime();
 
+#if defined(DEBUG)
+  void Dump(const char* aPath);
+#endif
+
 private:
   ~SourceBufferList();
 
   friend class AsyncEventRunner<SourceBufferList>;
   void DispatchSimpleEvent(const char* aName);
   void QueueAsyncSimpleEvent(const char* aName);
 
   nsRefPtr<MediaSource> mMediaSource;
--- a/content/media/mediasource/SourceBufferResource.h
+++ b/content/media/mediasource/SourceBufferResource.h
@@ -115,16 +115,22 @@ public:
   void Ended();
   // Remove data from resource if it holds more than the threshold
   // number of bytes. Returns true if some data was evicted.
   bool EvictData(uint32_t aThreshold);
 
   // Remove data from resource before the given offset.
   void EvictBefore(uint64_t aOffset);
 
+#if defined(DEBUG)
+  void Dump(const char* aPath) {
+    mInputBuffer.Dump(aPath);
+  }
+#endif
+
 private:
   ~SourceBufferResource();
   nsresult SeekInternal(int64_t aOffset);
 
   const nsCString mType;
 
   // Provides synchronization between SourceBuffers and InputAdapters.
   // Protects all of the member variables below.  Read() will await a
--- a/content/media/mediasource/TrackBuffer.cpp
+++ b/content/media/mediasource/TrackBuffer.cpp
@@ -1,8 +1,9 @@
+/* -*- 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/. */
 
 #include "TrackBuffer.h"
 
 #include "MediaSourceDecoder.h"
@@ -344,9 +345,27 @@ TrackBuffer::ResetDecode()
 
 const nsTArray<nsRefPtr<SourceBufferDecoder>>&
 TrackBuffer::Decoders()
 {
   // XXX assert OnDecodeThread
   return mInitializedDecoders;
 }
 
+#if defined(DEBUG)
+void
+TrackBuffer::Dump(const char* aPath)
+{
+  char path[255];
+  PR_snprintf(path, sizeof(path), "%s/trackbuffer-%p", aPath, this);
+  mkdir(path, 0700);
+
+  for (uint32_t i = 0; i < mDecoders.Length(); ++i) {
+    char buf[255];
+    PR_snprintf(buf, sizeof(buf), "%s/reader-%p", path, mDecoders[i]->GetReader());
+    mkdir(buf, 0700);
+
+    mDecoders[i]->GetResource()->Dump(buf);
+  }
+}
+#endif
+
 } // namespace mozilla
--- a/content/media/mediasource/TrackBuffer.h
+++ b/content/media/mediasource/TrackBuffer.h
@@ -77,16 +77,20 @@ public:
   // Call ResetDecode() on each decoder in mDecoders.
   void ResetDecode();
 
   // Returns a reference to mInitializedDecoders, used by MediaSourceReader
   // to select decoders.
   // TODO: Refactor to a cleaner interface between TrackBuffer and MediaSourceReader.
   const nsTArray<nsRefPtr<SourceBufferDecoder>>& Decoders();
 
+#if defined(DEBUG)
+  void Dump(const char* aPath);
+#endif
+
 private:
   ~TrackBuffer();
 
   // Queue execution of InitializeDecoder on mTaskQueue.
   bool QueueInitializeDecoder(nsRefPtr<SourceBufferDecoder> aDecoder);
 
   // Runs decoder initialization including calling ReadMetadata.  Runs as an
   // event on the decode thread pool.