Bug 1150853: Part1. Create MediaRawData object type. r=cpearce
authorJean-Yves Avenard <jyavenard@mozilla.com>
Thu, 09 Apr 2015 21:14:55 +1000
changeset 238323 7f283bb1827ce8e6a426713ceda96cfca0712fd3
parent 238322 b9fcd818c945f1769dfd4d575428936f3c891a62
child 238324 5b615a235096a1158965b87fb46b7b8749436b4e
push idunknown
push userunknown
push dateunknown
reviewerscpearce
bugs1150853
milestone40.0a1
Bug 1150853: Part1. Create MediaRawData object type. r=cpearce This object extends MediaData and will be used to contain demuxed compressed data.
dom/media/MediaData.cpp
dom/media/MediaData.h
dom/media/gmp/GMPAudioHost.cpp
dom/media/gmp/GMPAudioHost.h
dom/media/gmp/GMPDecryptorParent.cpp
dom/media/gmp/GMPDecryptorParent.h
dom/media/gmp/GMPDecryptorProxy.h
dom/media/gmp/GMPEncryptedBufferDataImpl.cpp
dom/media/gmp/GMPEncryptedBufferDataImpl.h
dom/media/gmp/GMPVideoEncodedFrameImpl.cpp
dom/media/gmp/GMPVideoEncodedFrameImpl.h
media/libstagefright/binding/include/mp4_demuxer/DecoderData.h
--- a/dom/media/MediaData.cpp
+++ b/dom/media/MediaData.cpp
@@ -10,16 +10,17 @@
 #include "mozilla/layers/TextureClient.h"
 #endif
 #include "VideoUtils.h"
 #include "ImageContainer.h"
 
 #ifdef MOZ_WIDGET_GONK
 #include <cutils/properties.h>
 #endif
+#include <stdint.h>
 
 namespace mozilla {
 
 using namespace mozilla::gfx;
 using layers::ImageContainer;
 using layers::PlanarYCbCrImage;
 using layers::PlanarYCbCrData;
 
@@ -98,38 +99,40 @@ IsInEmulator()
 {
   char propQemu[PROPERTY_VALUE_MAX];
   property_get("ro.kernel.qemu", propQemu, "");
   return !strncmp(propQemu, "1", 1);
 }
 
 #endif
 
-VideoData::VideoData(int64_t aOffset, int64_t aTime, int64_t aDuration, int64_t aTimecode)
-  : MediaData(VIDEO_DATA, aOffset, aTime, aDuration),
-    mTimecode(aTimecode),
-    mDuplicate(true),
-    mKeyframe(false)
+VideoData::VideoData(int64_t aOffset,
+                     int64_t aTime,
+                     int64_t aDuration,
+                     int64_t aTimecode)
+  : MediaData(VIDEO_DATA, aOffset, aTime, aDuration)
+  , mDuplicate(true)
 {
   NS_ASSERTION(mDuration >= 0, "Frame must have non-negative duration.");
+  mTimecode = aTimecode;
 }
 
 VideoData::VideoData(int64_t aOffset,
                      int64_t aTime,
                      int64_t aDuration,
                      bool aKeyframe,
                      int64_t aTimecode,
                      IntSize aDisplay)
-  : MediaData(VIDEO_DATA, aOffset, aTime, aDuration),
-    mDisplay(aDisplay),
-    mTimecode(aTimecode),
-    mDuplicate(false),
-    mKeyframe(aKeyframe)
+  : MediaData(VIDEO_DATA, aOffset, aTime, aDuration)
+  , mDisplay(aDisplay)
+  , mDuplicate(false)
 {
   NS_ASSERTION(mDuration >= 0, "Frame must have non-negative duration.");
+  mKeyframe = aKeyframe;
+  mTimecode = aTimecode;
 }
 
 VideoData::~VideoData()
 {
 }
 
 size_t
 VideoData::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
@@ -470,9 +473,180 @@ VideoData::Create(VideoInfo& aInfo,
   data.mGraphicBuffer = aBuffer;
 
   videoImage->SetData(data);
 
   return v.forget();
 }
 #endif  // MOZ_OMX_DECODER
 
+// Alignment value - 1. 0 means that data isn't aligned.
+// For 32-bytes aligned, use 31U.
+#define RAW_DATA_ALIGNMENT 31U
+
+#define RAW_DATA_DEFAULT_SIZE 4096
+
+MediaRawData::MediaRawData()
+  : MediaData(RAW_DATA)
+  , mData(nullptr)
+  , mSize(0)
+  , mBuffer(new LargeDataBuffer(RAW_DATA_DEFAULT_SIZE))
+  , mPadding(0)
+{
+}
+
+MediaRawData::MediaRawData(const uint8_t* aData, size_t aSize)
+  : MediaData(RAW_DATA)
+  , mData(nullptr)
+  , mSize(0)
+  , mBuffer(new LargeDataBuffer(RAW_DATA_DEFAULT_SIZE))
+  , mPadding(0)
+{
+  if (!EnsureCapacity(aSize)) {
+    return;
+  }
+  mBuffer->AppendElements(aData, aSize);
+  mBuffer->AppendElements(RAW_DATA_ALIGNMENT);
+  mSize = aSize;
+}
+
+already_AddRefed<MediaRawData>
+MediaRawData::Clone() const
+{
+  nsRefPtr<MediaRawData> s = new MediaRawData;
+  s->mTimecode = mTimecode;
+  s->mTime = mTime;
+  s->mDuration = mDuration;
+  s->mOffset = mOffset;
+  s->mKeyframe = mKeyframe;
+  s->mExtraData = mExtraData;
+  if (mSize) {
+    if (!s->EnsureCapacity(mSize)) {
+      return nullptr;
+    }
+    s->mBuffer->AppendElements(mData, mSize);
+    s->mBuffer->AppendElements(RAW_DATA_ALIGNMENT);
+    s->mSize = mSize;
+  }
+  return s.forget();
+}
+
+bool
+MediaRawData::EnsureCapacity(size_t aSize)
+{
+  if (mData && mBuffer->Capacity() >= aSize + RAW_DATA_ALIGNMENT * 2) {
+    return true;
+  }
+  if (!mBuffer->SetCapacity(aSize + RAW_DATA_ALIGNMENT * 2)) {
+    return false;
+  }
+  // Find alignment address.
+  const uintptr_t alignmask = RAW_DATA_ALIGNMENT;
+  mData = reinterpret_cast<uint8_t*>(
+    (reinterpret_cast<uintptr_t>(mBuffer->Elements()) + alignmask) & ~alignmask);
+  MOZ_ASSERT(uintptr_t(mData) % (RAW_DATA_ALIGNMENT+1) == 0);
+
+  // Shift old data according to new padding.
+  uint32_t oldpadding = int32_t(mPadding);
+  mPadding = mData - mBuffer->Elements();
+  int32_t shift = int32_t(mPadding) - int32_t(oldpadding);
+
+  if (shift == 0) {
+    // Nothing to do.
+  } else if (shift > 0) {
+    mBuffer->InsertElementsAt(oldpadding, shift);
+  } else {
+    mBuffer->RemoveElementsAt(mPadding, -shift);
+  }
+  return true;
+}
+
+MediaRawData::~MediaRawData()
+{
+}
+
+size_t
+MediaRawData::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
+{
+  size_t size = aMallocSizeOf(this);
+
+  if (mExtraData) {
+    size += mExtraData->SizeOfIncludingThis(aMallocSizeOf);
+  }
+  size += mBuffer->SizeOfIncludingThis(aMallocSizeOf);
+  return size;
+}
+
+MediaRawDataWriter*
+MediaRawData::CreateWriter()
+{
+  return new MediaRawDataWriter(this);
+}
+
+MediaRawDataWriter::MediaRawDataWriter(MediaRawData* aMediaRawData)
+  : mData(nullptr)
+  , mSize(0)
+  , mTarget(aMediaRawData)
+  , mBuffer(aMediaRawData->mBuffer.get())
+{
+  if (aMediaRawData->mData) {
+    mData = mBuffer->Elements() + mTarget->mPadding;
+    mSize = mTarget->mSize;
+  }
+}
+
+bool
+MediaRawDataWriter::EnsureSize(size_t aSize)
+{
+  if (aSize <= mSize) {
+    return true;
+  }
+  if (!mTarget->EnsureCapacity(aSize)) {
+    return false;
+  }
+  mData = mBuffer->Elements() + mTarget->mPadding;
+  return true;
+}
+
+bool
+MediaRawDataWriter::SetSize(size_t aSize)
+{
+  if (aSize > mTarget->mSize && !EnsureSize(aSize)) {
+    return false;
+  }
+  // Pad our buffer.
+  mBuffer->SetLength(aSize + mTarget->mPadding + RAW_DATA_ALIGNMENT);
+  mTarget->mSize = mSize = aSize;
+  return true;
+}
+
+bool
+MediaRawDataWriter::Prepend(const uint8_t* aData, size_t aSize)
+{
+  if (!EnsureSize(aSize + mTarget->mSize)) {
+    return false;
+  }
+  mBuffer->InsertElementsAt(mTarget->mPadding, aData, aSize);
+  mTarget->mSize += aSize;
+  mSize = mTarget->mSize;
+  return true;
+}
+
+bool
+MediaRawDataWriter::Replace(const uint8_t* aData, size_t aSize)
+{
+  if (!EnsureSize(aSize)) {
+    return false;
+  }
+  mBuffer->ReplaceElementsAt(mTarget->mPadding, mTarget->mSize, aData, aSize);
+  mTarget->mSize = mSize = aSize;
+  return true;
+}
+
+void
+MediaRawDataWriter::Clear()
+{
+  mBuffer->RemoveElementsAt(mTarget->mPadding, mTarget->mSize);
+  mTarget->mSize = mSize = 0;
+  mTarget->mData = mData = nullptr;
+}
+
 } // namespace mozilla
--- a/dom/media/MediaData.h
+++ b/dom/media/MediaData.h
@@ -17,57 +17,79 @@
 
 namespace mozilla {
 
 namespace layers {
 class Image;
 class ImageContainer;
 }
 
+class LargeDataBuffer;
+class DataBuffer;
+
 // Container that holds media samples.
 class MediaData {
 public:
 
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaData)
 
   enum Type {
     AUDIO_DATA = 0,
-    VIDEO_DATA
+    VIDEO_DATA,
+    RAW_DATA
   };
 
   MediaData(Type aType,
             int64_t aOffset,
             int64_t aTimestamp,
             int64_t aDuration)
     : mType(aType)
     , mOffset(aOffset)
     , mTime(aTimestamp)
+    , mTimecode(aTimestamp)
     , mDuration(aDuration)
+    , mKeyframe(false)
     , mDiscontinuity(false)
   {}
 
   // Type of contained data.
   const Type mType;
 
   // Approximate byte offset where this data was demuxed from its media.
-  const int64_t mOffset;
+  int64_t mOffset;
 
   // Start time of sample, in microseconds.
-  const int64_t mTime;
+  int64_t mTime;
+
+  // Codec specific internal time code. For Ogg based codecs this is the
+  // granulepos.
+  int64_t mTimecode;
 
   // Duration of sample, in microseconds.
-  const int64_t mDuration;
+  int64_t mDuration;
+
+  bool mKeyframe;
 
   // True if this is the first sample after a gap or discontinuity in
   // the stream. This is true for the first sample in a stream after a seek.
   bool mDiscontinuity;
 
   int64_t GetEndTime() const { return mTime + mDuration; }
 
 protected:
+  explicit MediaData(Type aType)
+    : mType(aType)
+    , mOffset(0)
+    , mTime(0)
+    , mTimecode(0)
+    , mDuration(0)
+    , mKeyframe(false)
+    , mDiscontinuity(false)
+  {}
+
   virtual ~MediaData() {}
 
 };
 
 // Holds chunk a decoded audio frames.
 class AudioData : public MediaData {
 public:
 
@@ -250,27 +272,22 @@ public:
 
   size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
 
   // Dimensions at which to display the video frame. The picture region
   // will be scaled to this size. This is should be the picture region's
   // dimensions scaled with respect to its aspect ratio.
   const IntSize mDisplay;
 
-  // Codec specific internal time code. For Ogg based codecs this is the
-  // granulepos.
-  const int64_t mTimecode;
-
   // This frame's image.
   nsRefPtr<Image> mImage;
 
   // When true, denotes that this frame is identical to the frame that
   // came before; it's a duplicate. mBuffer will be empty.
   const bool mDuplicate;
-  const bool mKeyframe;
 
   VideoData(int64_t aOffset,
             int64_t aTime,
             int64_t aDuration,
             int64_t aTimecode);
 
   VideoData(int64_t aOffset,
             int64_t aTime,
@@ -278,20 +295,136 @@ public:
             bool aKeyframe,
             int64_t aTimecode,
             IntSize aDisplay);
 
 protected:
   ~VideoData();
 };
 
+class CryptoTrack
+{
+public:
+  CryptoTrack() : valid(false) {}
+  bool valid;
+  int32_t mode;
+  int32_t iv_size;
+  nsTArray<uint8_t> key;
+};
+
+class CryptoSample : public CryptoTrack
+{
+public:
+  nsTArray<uint16_t> plain_sizes;
+  nsTArray<uint32_t> encrypted_sizes;
+  nsTArray<uint8_t> iv;
+  nsTArray<nsCString> session_ids;
+};
+
+
+// MediaRawData is a MediaData container used to store demuxed, still compressed
+// samples.
+// Use MediaRawData::CreateWriter() to obtain a MediaRawDataWriter object that
+// provides methods to modify and manipulate the data.
+// Memory allocations are fallibles. Methods return a boolean indicating if
+// memory allocations were successful. Return values should always be checked.
+// MediaRawData::mData will be nullptr if no memory has been allocated or if
+// an error occurred during construction.
+// Existing data is only ever modified if new memory allocation has succeeded
+// and preserved if not.
+//
+// The memory referenced by mData will always be 32 bytes aligned and the
+// underlying buffer will always have a size such that 32 bytes blocks can be
+// used to read the content, regardless of the mSize value. Buffer is zeroed
+// on creation.
+//
+// Typical usage: create new MediaRawData; create the associated
+// MediaRawDataWriter, call SetSize() to allocate memory, write to mData,
+// up to mSize bytes.
+
+class MediaRawData;
+
+class MediaRawDataWriter
+{
+public:
+  // Pointer to data or null if not-yet allocated
+  uint8_t* mData;
+  // Writeable size of buffer.
+  size_t mSize;
+
+  // Data manipulation methods. mData and mSize may be updated accordingly.
+
+  // Set size of buffer, allocating memory as required.
+  // If size is increased, new buffer area is filled with 0.
+  bool SetSize(size_t aSize);
+  // Add aData at the beginning of buffer.
+  bool Prepend(const uint8_t* aData, size_t aSize);
+  // Replace current content with aData.
+  bool Replace(const uint8_t* aData, size_t aSize);
+  // Clear the memory buffer. Will set mData and mSize to 0.
+  void Clear();
+
+private:
+  friend class MediaRawData;
+  explicit MediaRawDataWriter(MediaRawData* aMediaRawData);
+  bool EnsureSize(size_t aSize);
+  MediaRawData* mTarget;
+  nsRefPtr<LargeDataBuffer> mBuffer;
+};
+
+class MediaRawData : public MediaData {
+public:
+  MediaRawData();
+  MediaRawData(const uint8_t* aData, size_t mSize);
+
+  // Pointer to data or null if not-yet allocated
+  const uint8_t* mData;
+  // Size of buffer.
+  size_t mSize;
+
+  CryptoSample mCrypto;
+  nsRefPtr<DataBuffer> mExtraData;
+
+  // Return a deep copy or nullptr if out of memory.
+  virtual already_AddRefed<MediaRawData> Clone() const;
+  // Create a MediaRawDataWriter for this MediaRawData. The caller must
+  // delete the writer once done. The writer is not thread-safe.
+  virtual MediaRawDataWriter* CreateWriter();
+  virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
+
+protected:
+  ~MediaRawData();
+
+private:
+  friend class MediaRawDataWriter;
+  // Ensure that the backend buffer can hold aSize data. Will update mData.
+  // Will enforce that the start of allocated data is always 32 bytes
+  // aligned and that it has sufficient end padding to allow for 32 bytes block
+  // read as required by some data decoders.
+  // Returns false if memory couldn't be allocated.
+  bool EnsureCapacity(size_t aSize);
+  nsRefPtr<LargeDataBuffer> mBuffer;
+  uint32_t mPadding;
+  MediaRawData(const MediaRawData&); // Not implemented
+};
+
   // LargeDataBuffer is a ref counted fallible TArray.
   // It is designed to share potentially big byte arrays.
 class LargeDataBuffer : public FallibleTArray<uint8_t> {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(LargeDataBuffer);
+  LargeDataBuffer() = default;
+  explicit LargeDataBuffer(size_t aCapacity) : FallibleTArray<uint8_t>(aCapacity) {}
 
 private:
   ~LargeDataBuffer() {}
 };
 
+  // DataBuffer is a ref counted infallible TArray.
+class DataBuffer : public nsTArray<uint8_t> {
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DataBuffer);
+
+private:
+  ~DataBuffer() {}
+};
+
 } // namespace mozilla
 
 #endif // MediaData_h
--- a/dom/media/gmp/GMPAudioHost.cpp
+++ b/dom/media/gmp/GMPAudioHost.cpp
@@ -2,16 +2,17 @@
 /* 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 "GMPAudioHost.h"
 #include "gmp-audio-samples.h"
 #include "gmp-errors.h"
 #include "GMPEncryptedBufferDataImpl.h"
+#include "mp4_demuxer/DecoderData.h"
 
 namespace mozilla {
 namespace gmp {
 
 GMPAudioSamplesImpl::GMPAudioSamplesImpl(GMPAudioFormat aFormat)
   : mFormat(aFormat)
   , mTimeStamp(0)
   , mChannels(0)
@@ -100,17 +101,17 @@ GMPAudioSamplesImpl::Buffer()
 
 const GMPEncryptedBufferMetadata*
 GMPAudioSamplesImpl::GetDecryptionData() const
 {
   return mCrypto;
 }
 
 void
-GMPAudioSamplesImpl::InitCrypto(const mp4_demuxer::CryptoSample& aCrypto)
+GMPAudioSamplesImpl::InitCrypto(const CryptoSample& aCrypto)
 {
   if (!aCrypto.valid) {
     return;
   }
   mCrypto = new GMPEncryptedBufferDataImpl(aCrypto);
 }
 
 void
--- a/dom/media/gmp/GMPAudioHost.h
+++ b/dom/media/gmp/GMPAudioHost.h
@@ -5,22 +5,27 @@
 
 #ifndef GMPAudioHost_h_
 #define GMPAudioHost_h_
 
 #include "gmp-audio-host.h"
 #include "gmp-audio-samples.h"
 #include "nsTArray.h"
 #include "gmp-decryption.h"
-#include "mp4_demuxer/DecoderData.h"
 #include "nsAutoPtr.h"
 #include "GMPEncryptedBufferDataImpl.h"
 #include "mozilla/gmp/GMPTypes.h"
 
+namespace mp4_demuxer {
+class MP4Sample;
+}
+
 namespace mozilla {
+class CryptoSample;
+
 namespace gmp {
 
 class GMPAudioSamplesImpl : public GMPAudioSamples {
 public:
   explicit GMPAudioSamplesImpl(GMPAudioFormat aFormat);
   explicit GMPAudioSamplesImpl(const GMPAudioEncodedSampleData& aData);
   GMPAudioSamplesImpl(mp4_demuxer::MP4Sample* aSample,
                       uint32_t aChannels,
@@ -32,17 +37,17 @@ public:
   virtual GMPErr SetBufferSize(uint32_t aSize) override;
   virtual uint32_t Size() override;
   virtual void SetTimeStamp(uint64_t aTimeStamp) override;
   virtual uint64_t TimeStamp() override;
   virtual const uint8_t* Buffer() const override;
   virtual uint8_t* Buffer() override;
   virtual const GMPEncryptedBufferMetadata* GetDecryptionData() const override;
 
-  void InitCrypto(const mp4_demuxer::CryptoSample& aCrypto);
+  void InitCrypto(const CryptoSample& aCrypto);
 
   void RelinquishData(GMPAudioEncodedSampleData& aData);
 
   virtual uint32_t Channels() const override;
   virtual void SetChannels(uint32_t aChannels) override;
   virtual uint32_t Rate() const override;
   virtual void SetRate(uint32_t aRate) override;
 
--- a/dom/media/gmp/GMPDecryptorParent.cpp
+++ b/dom/media/gmp/GMPDecryptorParent.cpp
@@ -1,16 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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 "GMPDecryptorParent.h"
 #include "GMPContentParent.h"
-#include "mp4_demuxer/DecoderData.h"
+#include "MediaData.h"
 #include "mozilla/unused.h"
 
 namespace mozilla {
 namespace gmp {
 
 GMPDecryptorParent::GMPDecryptorParent(GMPContentParent* aPlugin)
   : mIsOpen(false)
   , mShuttingDown(false)
@@ -128,17 +128,17 @@ GMPDecryptorParent::SetServerCertificate
   }
   // Caller should ensure parameters passed in from JS are valid.
   MOZ_ASSERT(!aServerCert.IsEmpty());
   unused << SendSetServerCertificate(aPromiseId, aServerCert);
 }
 
 void
 GMPDecryptorParent::Decrypt(uint32_t aId,
-                            const mp4_demuxer::CryptoSample& aCrypto,
+                            const CryptoSample& aCrypto,
                             const nsTArray<uint8_t>& aBuffer)
 {
   if (!mIsOpen) {
     NS_WARNING("Trying to use a dead GMP decrypter!");
     return;
   }
 
   // Caller should ensure parameters passed in are valid.
--- a/dom/media/gmp/GMPDecryptorParent.h
+++ b/dom/media/gmp/GMPDecryptorParent.h
@@ -5,21 +5,21 @@
 
 #ifndef GMPDecryptorParent_h_
 #define GMPDecryptorParent_h_
 
 #include "mozilla/gmp/PGMPDecryptorParent.h"
 #include "mozilla/RefPtr.h"
 #include "gmp-decryption.h"
 #include "GMPDecryptorProxy.h"
-namespace mp4_demuxer {
-class CryptoSample;
-}
 
 namespace mozilla {
+
+class CryptoSample;
+
 namespace gmp {
 
 class GMPContentParent;
 
 class GMPDecryptorParent final : public GMPDecryptorProxy
                                , public PGMPDecryptorParent
 {
 public:
@@ -51,17 +51,17 @@ public:
 
   virtual void RemoveSession(uint32_t aPromiseId,
                              const nsCString& aSessionId) override;
 
   virtual void SetServerCertificate(uint32_t aPromiseId,
                                     const nsTArray<uint8_t>& aServerCert) override;
 
   virtual void Decrypt(uint32_t aId,
-                       const mp4_demuxer::CryptoSample& aCrypto,
+                       const CryptoSample& aCrypto,
                        const nsTArray<uint8_t>& aBuffer) override;
 
   virtual void Close() override;
 
   void Shutdown();
 
 private:
   ~GMPDecryptorParent();
--- a/dom/media/gmp/GMPDecryptorProxy.h
+++ b/dom/media/gmp/GMPDecryptorProxy.h
@@ -5,17 +5,17 @@
 
 #ifndef GMPDecryptorProxy_h_
 #define GMPDecryptorProxy_h_
 
 #include "GMPCallbackBase.h"
 #include "gmp-decryption.h"
 #include "nsString.h"
 
-namespace mp4_demuxer {
+namespace mozilla {
 class CryptoSample;
 }
 
 class GMPDecryptorProxyCallback : public GMPCallbackBase {
 public:
   ~GMPDecryptorProxyCallback() {}
 
   virtual void SetSessionId(uint32_t aCreateSessionId,
@@ -81,15 +81,15 @@ public:
 
   virtual void RemoveSession(uint32_t aPromiseId,
                              const nsCString& aSessionId) = 0;
 
   virtual void SetServerCertificate(uint32_t aPromiseId,
                                     const nsTArray<uint8_t>& aServerCert) = 0;
 
   virtual void Decrypt(uint32_t aId,
-                       const mp4_demuxer::CryptoSample& aCrypto,
+                       const mozilla::CryptoSample& aCrypto,
                        const nsTArray<uint8_t>& aBuffer) = 0;
 
   virtual void Close() = 0;
 };
 
 #endif // GMPDecryptorProxy_h_
--- a/dom/media/gmp/GMPEncryptedBufferDataImpl.cpp
+++ b/dom/media/gmp/GMPEncryptedBufferDataImpl.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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 "GMPEncryptedBufferDataImpl.h"
 #include "mozilla/gmp/GMPTypes.h"
+#include "MediaData.h"
 
 namespace mozilla {
 namespace gmp {
 
 GMPEncryptedBufferDataImpl::GMPEncryptedBufferDataImpl(const CryptoSample& aCrypto)
   : mKeyId(aCrypto.key)
   , mIV(aCrypto.iv)
   , mClearBytes(aCrypto.plain_sizes)
--- a/dom/media/gmp/GMPEncryptedBufferDataImpl.h
+++ b/dom/media/gmp/GMPEncryptedBufferDataImpl.h
@@ -2,21 +2,22 @@
 /* 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 GMPEncryptedBufferDataImpl_h_
 #define GMPEncryptedBufferDataImpl_h_
 
 #include "gmp-decryption.h"
-#include "mp4_demuxer/DecoderData.h"
 #include "nsTArray.h"
 #include "mozilla/gmp/GMPTypes.h"
 
 namespace mozilla {
+class CryptoSample;
+
 namespace gmp {
 
 class GMPStringListImpl : public GMPStringList
 {
 public:
   explicit GMPStringListImpl(const nsTArray<nsCString>& aStrings);
   virtual const uint32_t Size() const override;
   virtual void StringAt(uint32_t aIndex,
@@ -24,18 +25,16 @@ public:
   virtual ~GMPStringListImpl() override;
   void RelinquishData(nsTArray<nsCString>& aStrings);
 
 private:
   nsTArray<nsCString> mStrings;
 };
 
 class GMPEncryptedBufferDataImpl : public GMPEncryptedBufferMetadata {
-private:
-  typedef mp4_demuxer::CryptoSample CryptoSample;
 public:
   explicit GMPEncryptedBufferDataImpl(const CryptoSample& aCrypto);
   explicit GMPEncryptedBufferDataImpl(const GMPDecryptionData& aData);
   virtual ~GMPEncryptedBufferDataImpl();
 
   void RelinquishData(GMPDecryptionData& aData);
 
   virtual const uint8_t* KeyId() const override;
--- a/dom/media/gmp/GMPVideoEncodedFrameImpl.cpp
+++ b/dom/media/gmp/GMPVideoEncodedFrameImpl.cpp
@@ -51,17 +51,17 @@ GMPVideoEncodedFrameImpl::~GMPVideoEncod
 {
   DestroyBuffer();
   if (mHost) {
     mHost->EncodedFrameDestroyed(this);
   }
 }
 
 void
-GMPVideoEncodedFrameImpl::InitCrypto(const mp4_demuxer::CryptoSample& aCrypto)
+GMPVideoEncodedFrameImpl::InitCrypto(const CryptoSample& aCrypto)
 {
   mCrypto = new GMPEncryptedBufferDataImpl(aCrypto);
 }
 
 const GMPEncryptedBufferMetadata*
 GMPVideoEncodedFrameImpl::GetDecryptionData() const
 {
   return mCrypto;
--- a/dom/media/gmp/GMPVideoEncodedFrameImpl.h
+++ b/dom/media/gmp/GMPVideoEncodedFrameImpl.h
@@ -31,34 +31,35 @@
 #ifndef GMPVideoEncodedFrameImpl_h_
 #define GMPVideoEncodedFrameImpl_h_
 
 #include "gmp-errors.h"
 #include "gmp-video-frame.h"
 #include "gmp-video-frame-encoded.h"
 #include "gmp-decryption.h"
 #include "mozilla/ipc/Shmem.h"
-#include "mp4_demuxer/DecoderData.h"
 
 namespace mozilla {
+class CryptoSample;
+
 namespace gmp {
 
 class GMPVideoHostImpl;
 class GMPVideoEncodedFrameData;
 class GMPEncryptedBufferDataImpl;
 
 class GMPVideoEncodedFrameImpl: public GMPVideoEncodedFrame
 {
   friend struct IPC::ParamTraits<mozilla::gmp::GMPVideoEncodedFrameImpl>;
 public:
   explicit GMPVideoEncodedFrameImpl(GMPVideoHostImpl* aHost);
   GMPVideoEncodedFrameImpl(const GMPVideoEncodedFrameData& aFrameData, GMPVideoHostImpl* aHost);
   virtual ~GMPVideoEncodedFrameImpl();
 
-  void InitCrypto(const mp4_demuxer::CryptoSample& aCrypto);
+  void InitCrypto(const CryptoSample& aCrypto);
 
   // This is called during a normal destroy sequence, which is
   // when a consumer is finished or during XPCOM shutdown.
   void DoneWithAPI();
   // Does not attempt to release Shmem, as the Shmem has already been released.
   void ActorDestroyed();
 
   bool RelinquishFrameData(GMPVideoEncodedFrameData& aFrameData);
--- a/media/libstagefright/binding/include/mp4_demuxer/DecoderData.h
+++ b/media/libstagefright/binding/include/mp4_demuxer/DecoderData.h
@@ -1,15 +1,16 @@
 /* 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 DECODER_DATA_H_
 #define DECODER_DATA_H_
 
+#include "MediaData.h"
 #include "mozilla/Types.h"
 #include "mozilla/Vector.h"
 #include "nsAutoPtr.h"
 #include "nsRefPtr.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsString.h"
 
@@ -57,35 +58,16 @@ public:
 
   bool valid;
   nsTArray<PsshInfo> pssh;
 
 private:
   bool DoUpdate(const uint8_t* aData, size_t aLength);
 };
 
-class CryptoTrack
-{
-public:
-  CryptoTrack() : valid(false) {}
-  bool valid;
-  int32_t mode;
-  int32_t iv_size;
-  nsTArray<uint8_t> key;
-};
-
-class CryptoSample : public CryptoTrack
-{
-public:
-  nsTArray<uint16_t> plain_sizes;
-  nsTArray<uint32_t> encrypted_sizes;
-  nsTArray<uint8_t> iv;
-  nsTArray<nsCString> session_ids;
-};
-
 class TrackConfig
 {
 public:
   enum TrackType {
     kUndefinedTrack,
     kAudioTrack,
     kVideoTrack,
   };
@@ -96,17 +78,17 @@ public:
     , mType(aType)
   {
   }
 
   nsAutoCString mime_type;
   uint32_t mTrackId;
   int64_t duration;
   int64_t media_time;
-  CryptoTrack crypto;
+  mozilla::CryptoTrack crypto;
   TrackType mType;
 
   bool IsAudioConfig() const
   {
     return mType == kAudioTrack;
   }
   bool IsVideoConfig() const
   {
@@ -189,17 +171,17 @@ public:
   Microseconds composition_timestamp;
   Microseconds duration;
   int64_t byte_offset;
   bool is_sync_point;
 
   uint8_t* data;
   size_t size;
 
-  CryptoSample crypto;
+  mozilla::CryptoSample crypto;
   nsRefPtr<ByteBuffer> extra_data;
 
   bool Prepend(const uint8_t* aData, size_t aSize);
   bool Replace(const uint8_t* aData, size_t aSize);
 
   nsAutoArrayPtr<uint8_t> extra_buffer;
 private:
   MP4Sample(const MP4Sample&); // Not implemented