Bug 1320829 - updated WebM demuxer to surface alpha information. r=jya
authorkaro <kkoorts@mozilla.com>
Wed, 23 Nov 2016 11:52:16 +1300
changeset 324631 c599df1589cc18d70b70b93d1bebb81dbe008ca3
parent 324630 4802b32ee10badfa52dce93fbb15691108283d14
child 324632 d268ffed16a3baff393dba05c2c9a2a404e0bd48
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
reviewersjya
bugs1320829
milestone53.0a1
Bug 1320829 - updated WebM demuxer to surface alpha information. r=jya MozReview-Commit-ID: 1jBmc5KUEme
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
@@ -387,32 +387,44 @@ 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
@@ -612,25 +612,32 @@ private:
   explicit MediaRawDataWriter(MediaRawData* aMediaRawData);
   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 aSize);
+  MediaRawData(const uint8_t* aData, size_t aSize,
+               const uint8_t* aAlphaData, size_t aAlphaSize);
 
   // 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 +652,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
@@ -210,16 +210,17 @@ public:
     : 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 +234,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 +315,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 = false;
 };
 
 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);