diff --git a/gfx/layers/ipc/ImageContainerChild.cpp b/gfx/layers/ipc/ImageContainerChild.cpp index 7084f7876f2f7..b2ce2b2968078 100644 --- a/gfx/layers/ipc/ImageContainerChild.cpp +++ b/gfx/layers/ipc/ImageContainerChild.cpp @@ -135,9 +135,11 @@ bool ImageContainerChild::CopyDataIntoSharedImage(Image* src, SharedImage* dest) 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; } @@ -515,10 +517,11 @@ class SharedPlanarYCbCrImage : public PlanarYCbCrImage 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(); diff --git a/gfx/layers/ipc/ShmemYCbCrImage.cpp b/gfx/layers/ipc/ShmemYCbCrImage.cpp index 4dbdff47f7f59..ed6f2707ded6f 100644 --- a/gfx/layers/ipc/ShmemYCbCrImage.cpp +++ b/gfx/layers/ipc/ShmemYCbCrImage.cpp @@ -150,25 +150,54 @@ bool ShmemYCbCrImage::IsValid() 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; } diff --git a/gfx/layers/ipc/ShmemYCbCrImage.h b/gfx/layers/ipc/ShmemYCbCrImage.h index 634cb4099d063..74167e9de3c56 100644 --- a/gfx/layers/ipc/ShmemYCbCrImage.h +++ b/gfx/layers/ipc/ShmemYCbCrImage.h @@ -96,9 +96,11 @@ class ShmemYCbCrImage /** * 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);