Bug 944117 - updated WebM demuxer to surface alpha information. f?jya draft
authorkaro <kkoorts@mozilla.com>
Wed, 23 Nov 2016 11:52:16 +1300
changeset 443119 0416630ecee2d77586f7268edcc4565db3771821
parent 438112 47e0584afe0ab0b867412189c610b302b6ba0ea7
child 537972 fd24340bfbe4f49009c702f0bdbc89efde66b50f
push id36907
push userbmo:kkoorts@mozilla.com
push dateWed, 23 Nov 2016 22:17:49 +0000
bugs944117
milestone52.0a1
Bug 944117 - updated WebM demuxer to surface alpha information. f?jya MozReview-Commit-ID: 8XQyUs0KXl0
dom/media/MediaData.cpp
dom/media/MediaData.h
dom/media/MediaInfo.h
dom/media/webm/WebMDemuxer.cpp
--- a/dom/media/MediaData.cpp
+++ b/dom/media/MediaData.cpp
@@ -388,32 +388,46 @@ MediaRawData::MediaRawData()
 
 MediaRawData::MediaRawData(const uint8_t* aData, size_t aSize)
   : MediaData(RAW_DATA, 0)
   , mCrypto(mCryptoInternal)
   , mBuffer(aData, aSize)
 {
 }
 
+MediaRawData::MediaRawData(const uint8_t* aData,
+                           size_t aSize,
+                           const uint8_t* aAlphaData,
+                           size_t aAlphaSize)
+  : MediaData(RAW_DATA, 0)
+  , mCrypto(mCryptoInternal)
+  , mBuffer(aData, aSize)
+  , mAlphaBuffer(aAlphaData, aAlphaSize)
+{
+}
+
 already_AddRefed<MediaRawData>
 MediaRawData::Clone() const
 {
   RefPtr<MediaRawData> s = new MediaRawData;
   s->mTimecode = mTimecode;
   s->mTime = mTime;
   s->mDuration = mDuration;
   s->mOffset = mOffset;
   s->mKeyframe = mKeyframe;
   s->mExtraData = mExtraData;
   s->mCryptoInternal = mCryptoInternal;
   s->mTrackInfo = mTrackInfo;
   s->mEOS = mEOS;
   if (!s->mBuffer.Append(mBuffer.Data(), mBuffer.Length())) {
     return nullptr;
   }
+  if (!s->mAlphaBuffer.Append(mAlphaBuffer.Data(), mAlphaBuffer.Length())) {
+    return nullptr;
+  }
   return s.forget();
 }
 
 MediaRawData::~MediaRawData()
 {
 }
 
 size_t
--- a/dom/media/MediaData.h
+++ b/dom/media/MediaData.h
@@ -613,24 +613,33 @@ private:
   bool EnsureSize(size_t aSize);
   MediaRawData* mTarget;
 };
 
 class MediaRawData : public MediaData {
 public:
   MediaRawData();
   MediaRawData(const uint8_t* aData, size_t mSize);
+  MediaRawData(const uint8_t* aData,
+               size_t mSize,
+               const uint8_t* aAlphaData,
+               size_t mAlphaSize);
 
   // Pointer to data or null if not-yet allocated
   const uint8_t* Data() const { return mBuffer.Data(); }
+  // Pointer to alpha data or null if not-yet allocated
+  const uint8_t* AlphaData() const { return mAlphaBuffer.Data(); }
   // Size of buffer.
   size_t Size() const { return mBuffer.Length(); }
+  size_t AlphaSize() const { return mAlphaBuffer.Length(); }
   size_t ComputedSizeOfIncludingThis() const
   {
-    return sizeof(*this) + mBuffer.ComputedSizeOfExcludingThis();
+    return sizeof(*this)
+           + mBuffer.ComputedSizeOfExcludingThis()
+           + mAlphaBuffer.ComputedSizeOfExcludingThis();
   }
 
   const CryptoSample& mCrypto;
   RefPtr<MediaByteBuffer> mExtraData;
 
   // Used by the Vorbis decoder and Ogg demuxer.
   // Indicates that this is the last packet of the stream.
   bool mEOS = false;
@@ -645,16 +654,17 @@ public:
   virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
 
 protected:
   ~MediaRawData();
 
 private:
   friend class MediaRawDataWriter;
   AlignedByteBuffer mBuffer;
+  AlignedByteBuffer mAlphaBuffer;
   CryptoSample mCryptoInternal;
   MediaRawData(const MediaRawData&); // Not implemented
 };
 
   // MediaByteBuffer is a ref counted infallible TArray.
 class MediaByteBuffer : public nsTArray<uint8_t> {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaByteBuffer);
   MediaByteBuffer() = default;
--- a/dom/media/MediaInfo.h
+++ b/dom/media/MediaInfo.h
@@ -198,28 +198,30 @@ public:
                 EmptyString(), EmptyString(), true, 2)
     , mDisplay(aSize)
     , mStereoMode(StereoMode::MONO)
     , mImage(aSize)
     , mCodecSpecificConfig(new MediaByteBuffer)
     , mExtraData(new MediaByteBuffer)
     , mRotation(kDegree_0)
     , mImageRect(nsIntRect(nsIntPoint(), aSize))
+    , mAlphaPresent(false)
   {
   }
 
   VideoInfo(const VideoInfo& aOther)
     : TrackInfo(aOther)
     , mDisplay(aOther.mDisplay)
     , mStereoMode(aOther.mStereoMode)
     , mImage(aOther.mImage)
     , mCodecSpecificConfig(aOther.mCodecSpecificConfig)
     , mExtraData(aOther.mExtraData)
     , mRotation(aOther.mRotation)
     , mImageRect(aOther.mImageRect)
+    , mAlphaPresent(aOther.mAlphaPresent)
   {
   }
 
   bool IsValid() const override
   {
     return mDisplay.width > 0 && mDisplay.height > 0;
   }
 
@@ -233,16 +235,26 @@ public:
     return this;
   }
 
   UniquePtr<TrackInfo> Clone() const override
   {
     return MakeUnique<VideoInfo>(*this);
   }
 
+  void SetAlpha(bool aAlphaPresent)
+  {
+    mAlphaPresent = aAlphaPresent;
+  }
+
+  bool HasAlpha() const
+  {
+    return mAlphaPresent;
+  }
+
   nsIntRect ImageRect() const
   {
     if (mImageRect.width < 0 || mImageRect.height < 0) {
       return nsIntRect(0, 0, mImage.width, mImage.height);
     }
     return mImageRect;
   }
 
@@ -304,16 +316,19 @@ public:
   // Describing how many degrees video frames should be rotated in clock-wise to
   // get correct view.
   Rotation mRotation;
 
 private:
   // mImage may be cropped; currently only used with the WebM container.
   // A negative width or height indicate that no cropping is to occur.
   nsIntRect mImageRect;
+
+  // Indicates whether or not frames may contain alpha information.
+  bool mAlphaPresent;
 };
 
 class AudioInfo : public TrackInfo {
 public:
   AudioInfo()
     : TrackInfo(kAudioTrack, NS_LITERAL_STRING("1"), NS_LITERAL_STRING("main"),
                 EmptyString(), EmptyString(), true, 1)
     , mRate(0)
--- a/dom/media/webm/WebMDemuxer.cpp
+++ b/dom/media/webm/WebMDemuxer.cpp
@@ -356,16 +356,17 @@ WebMDemuxer::ReadMetadata()
       }
 
       mVideoTrack = track;
       mHasVideo = true;
 
       mInfo.mVideo.mDisplay = displaySize;
       mInfo.mVideo.mImage = frameSize;
       mInfo.mVideo.SetImageRect(pictureRect);
+      mInfo.mVideo.SetAlpha(params.alpha_mode);
 
       switch (params.stereo_mode) {
         case NESTEGG_VIDEO_MONO:
           mInfo.mVideo.mStereoMode = StereoMode::MONO;
           break;
         case NESTEGG_VIDEO_STEREO_LEFT_RIGHT:
           mInfo.mVideo.mStereoMode = StereoMode::LEFT_RIGHT;
           break;
@@ -621,16 +622,31 @@ WebMDemuxer::GetNextPacket(TrackInfo::Tr
   for (uint32_t i = 0; i < count; ++i) {
     unsigned char* data;
     size_t length;
     r = nestegg_packet_data(holder->Packet(), i, &data, &length);
     if (r == -1) {
       WEBM_DEBUG("nestegg_packet_data failed r=%d", r);
       return false;
     }
+    unsigned char* alphaData;
+    size_t alphaLength = 0;
+    // Check packets for alpha information if file has declared alpha frames
+    // may be present.
+    if (mInfo.mVideo.HasAlpha()) {
+      r = nestegg_packet_additional_data(holder->Packet(),
+                                     1,
+                                     &alphaData,
+                                     &alphaLength);
+      if (r == -1) {
+        WEBM_DEBUG(
+          "nestegg_packet_additional_data failed to retrieve alpha data r=%d",
+          r);
+      }
+    }
     bool isKeyframe = false;
     if (aType == TrackInfo::kAudioTrack) {
       isKeyframe = true;
     } else if (aType == TrackInfo::kVideoTrack) {
       if (packetEncryption == NESTEGG_PACKET_HAS_SIGNAL_BYTE_ENCRYPTED) {
         // Packet is encrypted, can't peek, use packet info
         isKeyframe = nestegg_packet_has_keyframe(holder->Packet()) == NESTEGG_PACKET_HAS_KEYFRAME_TRUE;
       } else {
@@ -658,17 +674,22 @@ WebMDemuxer::GetNextPacket(TrackInfo::Tr
           mLastSeenFrameWidth = Some(si.w);
           mLastSeenFrameHeight = Some(si.h);
         }
       }
     }
 
     WEBM_DEBUG("push sample tstamp: %ld next_tstamp: %ld length: %ld kf: %d",
                tstamp, next_tstamp, length, isKeyframe);
-    RefPtr<MediaRawData> sample = new MediaRawData(data, length);
+    RefPtr<MediaRawData> sample;
+    if (mInfo.mVideo.HasAlpha() && alphaLength != 0) {
+      sample = new MediaRawData(data, length, alphaData, alphaLength);
+    } else {
+      sample = new MediaRawData(data, length);
+    }
     sample->mTimecode = tstamp;
     sample->mTime = tstamp;
     sample->mDuration = next_tstamp - tstamp;
     sample->mOffset = holder->Offset();
     sample->mKeyframe = isKeyframe;
     if (discardPadding && i == count - 1) {
       uint8_t c[8];
       BigEndian::writeInt64(&c[0], discardPadding);