Bug 811730 - Take skip into account when copying video frames into shared memory. r=cpeterson, a=akeybl
authorNicolas Silva <nical.bugzilla@gmail.com>
Tue, 04 Dec 2012 11:36:33 +0100
changeset 119043 e511f4bbab30313448a23859ee39023811a7b877
parent 119042 45d2b0f59abb79fead1bf0378285d7ab2bf96279
child 119044 47d8fc2c65f7a12717e06d3e95edb2a47cf4c2b8
push id3049
push userryanvm@gmail.com
push dateSun, 23 Dec 2012 19:42:50 +0000
treeherdermozilla-aurora@8e0337f05bbf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpeterson, akeybl
bugs811730
milestone19.0a2
Bug 811730 - Take skip into account when copying video frames into shared memory. r=cpeterson, a=akeybl
gfx/layers/ipc/ImageContainerChild.cpp
gfx/layers/ipc/ShmemYCbCrImage.cpp
gfx/layers/ipc/ShmemYCbCrImage.h
--- a/gfx/layers/ipc/ImageContainerChild.cpp
+++ b/gfx/layers/ipc/ImageContainerChild.cpp
@@ -130,19 +130,21 @@ bool ImageContainerChild::CopyDataIntoSh
       (dest->type() == SharedImage::TYCbCrImage)) {
     PlanarYCbCrImage *planarYCbCrImage = static_cast<PlanarYCbCrImage*>(src);
     const PlanarYCbCrImage::Data *data = planarYCbCrImage->GetData();
     NS_ASSERTION(data, "Must be able to retrieve yuv data from image!");
     YCbCrImage& yuv = dest->get_YCbCrImage();
 
     ShmemYCbCrImage shmemImage(yuv.data(), yuv.offset());
 
+    MOZ_ASSERT(data->mCbSkip == data->mCrSkip);
     if (!shmemImage.CopyData(data->mYChannel, data->mCbChannel, data->mCrChannel,
                              data->mYSize, data->mYStride,
-                             data->mCbCrSize, data->mCbCrStride)) {
+                             data->mCbCrSize, data->mCbCrStride,
+                             data->mYSkip, data->mCbSkip)) {
       NS_WARNING("Failed to copy image data!");
       return false;
     }
     return true;
   }
   return false; // TODO: support more image formats
 }
 
@@ -510,20 +512,21 @@ public:
     // do not set mBuffer like in PlanarYCbCrImage because the later
     // will try to manage this memory without knowing it belongs to a
     // shmem.
     mBufferSize = ShmemYCbCrImage::ComputeMinBufferSize(mData.mYSize,
                                                         mData.mCbCrSize);
     mSize = mData.mPicSize;
 
     ShmemYCbCrImage shmImg(mShmem);
-
+    MOZ_ASSERT(aData.mCbSkip == aData.mCrSkip);
     if (!shmImg.CopyData(aData.mYChannel, aData.mCbChannel, aData.mCrChannel,
                          aData.mYSize, aData.mYStride,
-                         aData.mCbCrSize, aData.mCbCrStride)) {
+                         aData.mCbCrSize, aData.mCbCrStride,
+                         aData.mYSkip, aData.mCbSkip)) {
       NS_WARNING("Failed to copy image data!");
     }
     mData.mYChannel = shmImg.GetYData();
     mData.mCbChannel = shmImg.GetCbData();
     mData.mCrChannel = shmImg.GetCrData();
   }
 
   virtual bool Allocate(PlanarYCbCrImage::Data& aData)
--- a/gfx/layers/ipc/ShmemYCbCrImage.cpp
+++ b/gfx/layers/ipc/ShmemYCbCrImage.cpp
@@ -145,34 +145,63 @@ bool ShmemYCbCrImage::IsValid()
   if (mShmem.Size<uint8_t>() < bufferInfoSize ||
       GetYCbCrBufferInfo(mShmem, mOffset)->mYOffset != bufferInfoSize ||
       mShmem.Size<uint8_t>() < mOffset + ComputeMinBufferSize(GetYSize(),GetCbCrSize())) {
     return false;
   }
   return true;
 }
 
-bool ShmemYCbCrImage::CopyData(uint8_t* aYData, uint8_t* aCbData, uint8_t* aCrData,
+static void CopyLineWithSkip(const uint8_t* src, uint8_t* dst, uint32_t len, uint32_t skip) {
+  for (uint32_t i = 0; i < len; ++i) {
+    *dst = *src;
+    src += 1 + skip;
+    ++dst;
+  }
+}
+
+bool ShmemYCbCrImage::CopyData(const uint8_t* aYData,
+                               const uint8_t* aCbData, const uint8_t* aCrData,
                                gfxIntSize aYSize, uint32_t aYStride,
-                               gfxIntSize aCbCrSize, uint32_t aCbCrStride)
+                               gfxIntSize aCbCrSize, uint32_t aCbCrStride,
+                               uint32_t aYSkip, uint32_t aCbCrSkip)
 {
   if (!IsValid() || GetYSize() != aYSize || GetCbCrSize() != aCbCrSize) {
     return false;
   }
-  for (int i = 0; i < aYSize.height; i++) {
-    memcpy(GetYData() + i * GetYStride(),
-           aYData + i * aYStride,
-           aYSize.width);
+  for (int i = 0; i < aYSize.height; ++i) {
+    if (aYSkip == 0) {
+      // fast path
+      memcpy(GetYData() + i * GetYStride(),
+             aYData + i * aYStride,
+             aYSize.width);
+    } else {
+      // slower path
+      CopyLineWithSkip(aYData + i * aYStride,
+                       GetYData() + i * GetYStride(),
+                       aYSize.width, aYSkip);
+    }
   }
-  for (int i = 0; i < aCbCrSize.height; i++) {
-    memcpy(GetCbData() + i * GetCbCrStride(),
-           aCbData + i * aCbCrStride,
-           aCbCrSize.width);
-    memcpy(GetCrData() + i * GetCbCrStride(),
-           aCrData + i * aCbCrStride,
-           aCbCrSize.width);
+  for (int i = 0; i < aCbCrSize.height; ++i) {
+    if (aCbCrSkip == 0) {
+      // fast path
+      memcpy(GetCbData() + i * GetCbCrStride(),
+             aCbData + i * aCbCrStride,
+             aCbCrSize.width);
+      memcpy(GetCrData() + i * GetCbCrStride(),
+             aCrData + i * aCbCrStride,
+             aCbCrSize.width);
+    } else {
+      // slower path
+      CopyLineWithSkip(aCbData + i * aCbCrStride,
+                       GetCbData() + i * GetCbCrStride(),
+                       aCbCrSize.width, aCbCrSkip);
+      CopyLineWithSkip(aCrData + i * aCbCrStride,
+                       GetCrData() + i * GetCbCrStride(),
+                       aCbCrSize.width, aCbCrSkip);
+    }
   }
   return true;
 }
 
 
 } // namespace
 } // namespace
--- a/gfx/layers/ipc/ShmemYCbCrImage.h
+++ b/gfx/layers/ipc/ShmemYCbCrImage.h
@@ -91,19 +91,21 @@ public:
   /**
    * Returns the dimensions of the Cb and Cr Channel.
    */
   gfxIntSize GetCbCrSize();
 
   /**
    * Copies the data passed in parameter into the shmem.
    */
-  bool CopyData(uint8_t* aYData, uint8_t* aCbData, uint8_t* aCrData,
+  bool CopyData(const uint8_t* aYData,
+                const uint8_t* aCbData, const uint8_t* aCrData,
                 gfxIntSize aYSize, uint32_t aYStride,
-                gfxIntSize aCbCrSize, uint32_t aCbCrStride);
+                gfxIntSize aCbCrSize, uint32_t aCbCrStride,
+                uint32_t aYSkip, uint32_t aCbCrSkip);
 
 private:
   bool Open(Shmem& aShmem, size_t aOffset = 0);
 
   ipc::Shmem mShmem;
   size_t mOffset;
 };