LCOV - code coverage report
Current view: top level - dom/canvas - ImageUtils.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 117 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 21 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim:set ts=2 sw=2 sts=2 et cindent: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "ImageUtils.h"
       8             : #include "ImageBitmapUtils.h"
       9             : #include "ImageContainer.h"
      10             : #include "mozilla/AlreadyAddRefed.h"
      11             : #include "mozilla/dom/ImageBitmapBinding.h"
      12             : #include "mozilla/ErrorResult.h"
      13             : 
      14             : using namespace mozilla::layers;
      15             : using namespace mozilla::gfx;
      16             : 
      17             : namespace mozilla {
      18             : namespace dom {
      19             : 
      20             : static ImageBitmapFormat
      21           0 : GetImageBitmapFormatFromSurfaceFromat(SurfaceFormat aSurfaceFormat)
      22             : {
      23           0 :   switch (aSurfaceFormat) {
      24             :   case SurfaceFormat::B8G8R8A8:
      25             :   case SurfaceFormat::B8G8R8X8:
      26           0 :     return ImageBitmapFormat::BGRA32;
      27             :   case SurfaceFormat::R8G8B8A8:
      28             :   case SurfaceFormat::R8G8B8X8:
      29           0 :     return ImageBitmapFormat::RGBA32;
      30             :   case SurfaceFormat::R8G8B8:
      31           0 :     return ImageBitmapFormat::RGB24;
      32             :   case SurfaceFormat::B8G8R8:
      33           0 :     return ImageBitmapFormat::BGR24;
      34             :   case SurfaceFormat::HSV:
      35           0 :     return ImageBitmapFormat::HSV;
      36             :   case SurfaceFormat::Lab:
      37           0 :     return ImageBitmapFormat::Lab;
      38             :   case SurfaceFormat::Depth:
      39           0 :     return ImageBitmapFormat::DEPTH;
      40             :   case SurfaceFormat::A8:
      41           0 :     return ImageBitmapFormat::GRAY8;
      42             :   case SurfaceFormat::R5G6B5_UINT16:
      43             :   case SurfaceFormat::YUV:
      44             :   case SurfaceFormat::NV12:
      45             :   case SurfaceFormat::UNKNOWN:
      46             :   default:
      47           0 :     return ImageBitmapFormat::EndGuard_;
      48             :   }
      49             : }
      50             : 
      51             : static ImageBitmapFormat
      52           0 : GetImageBitmapFormatFromPlanarYCbCrData(layers::PlanarYCbCrData const *aData)
      53             : {
      54           0 :   MOZ_ASSERT(aData);
      55             : 
      56           0 :   if (aData->mYSkip == 0 && aData->mCbSkip == 0 &&
      57           0 :       aData->mCrSkip == 0) { // Possibly three planes.
      58           0 :     if (aData->mCbChannel >=
      59           0 :           aData->mYChannel + aData->mYSize.height * aData->mYStride &&
      60           0 :         aData->mCrChannel >=
      61           0 :           aData->mCbChannel +
      62           0 :             aData->mCbCrSize.height * aData->mCbCrStride) { // Three planes.
      63           0 :       if (aData->mYSize.height == aData->mCbCrSize.height) {
      64           0 :         if (aData->mYSize.width == aData->mCbCrSize.width) {
      65           0 :           return ImageBitmapFormat::YUV444P;
      66             :         }
      67           0 :         if (((aData->mYSize.width + 1) / 2) == aData->mCbCrSize.width) {
      68           0 :           return ImageBitmapFormat::YUV422P;
      69             :         }
      70           0 :       } else if (((aData->mYSize.height + 1) / 2) == aData->mCbCrSize.height) {
      71           0 :         if (((aData->mYSize.width + 1) / 2) == aData->mCbCrSize.width) {
      72           0 :           return ImageBitmapFormat::YUV420P;
      73             :         }
      74             :       }
      75             :     }
      76           0 :   } else if (aData->mYSkip == 0 && aData->mCbSkip == 1 && aData->mCrSkip == 1) { // Possibly two planes.
      77           0 :     if (aData->mCbChannel >= aData->mYChannel + aData->mYSize.height * aData->mYStride &&
      78           0 :         aData->mCbChannel == aData->mCrChannel - 1) { // Two planes.
      79           0 :       if (((aData->mYSize.height + 1) / 2) == aData->mCbCrSize.height &&
      80           0 :           ((aData->mYSize.width + 1) / 2) == aData->mCbCrSize.width) {
      81           0 :         return ImageBitmapFormat::YUV420SP_NV12;  // Y-Cb-Cr
      82             :       }
      83           0 :     } else if (aData->mCrChannel >= aData->mYChannel + aData->mYSize.height * aData->mYStride &&
      84           0 :                aData->mCrChannel == aData->mCbChannel - 1) { // Two planes.
      85           0 :       if (((aData->mYSize.height + 1) / 2) == aData->mCbCrSize.height &&
      86           0 :           ((aData->mYSize.width + 1) / 2) == aData->mCbCrSize.width) {
      87           0 :         return ImageBitmapFormat::YUV420SP_NV21;  // Y-Cr-Cb
      88             :       }
      89             :     }
      90             :   }
      91             : 
      92           0 :   return ImageBitmapFormat::EndGuard_;
      93             : }
      94             : 
      95             : // ImageUtils::Impl implements the _generic_ algorithm which always readback
      96             : // data in RGBA format into CPU memory.
      97             : // Since layers::CairoImage is just a warpper to a DataSourceSurface, the
      98             : // implementation of CairoSurfaceImpl is nothing different to the generic
      99             : // version.
     100             : class ImageUtils::Impl
     101             : {
     102             : public:
     103           0 :   explicit Impl(layers::Image* aImage)
     104           0 :   : mImage(aImage)
     105           0 :   , mSurface(nullptr)
     106             :   {
     107           0 :   }
     108             : 
     109           0 :   virtual ~Impl() = default;
     110             : 
     111             :   virtual ImageBitmapFormat
     112           0 :   GetFormat() const
     113             :   {
     114           0 :     return GetImageBitmapFormatFromSurfaceFromat(Surface()->GetFormat());
     115             :   }
     116             : 
     117             :   virtual uint32_t
     118           0 :   GetBufferLength() const
     119             :   {
     120           0 :     const uint32_t stride = Surface()->Stride();
     121           0 :     const IntSize size = Surface()->GetSize();
     122           0 :     return (uint32_t)(size.height * stride);
     123             :   }
     124             : 
     125             :   virtual UniquePtr<ImagePixelLayout>
     126           0 :   MapDataInto(uint8_t* aBuffer,
     127             :               uint32_t aOffset,
     128             :               uint32_t aBufferLength,
     129             :               ImageBitmapFormat aFormat,
     130             :               ErrorResult& aRv) const
     131             :   {
     132           0 :     DataSourceSurface::ScopedMap map(Surface(), DataSourceSurface::READ);
     133           0 :     if (!map.IsMapped()) {
     134           0 :       aRv.Throw(NS_ERROR_ILLEGAL_VALUE);
     135           0 :       return nullptr;
     136             :     }
     137             : 
     138             :     // Copy or convert data.
     139             :     UniquePtr<ImagePixelLayout> srcLayout =
     140           0 :       CreateDefaultPixelLayout(GetFormat(), Surface()->GetSize().width,
     141           0 :                                Surface()->GetSize().height, map.GetStride());
     142             : 
     143             :     // Prepare destination buffer.
     144           0 :     uint8_t* dstBuffer = aBuffer + aOffset;
     145             :     UniquePtr<ImagePixelLayout> dstLayout =
     146           0 :       CopyAndConvertImageData(GetFormat(), map.GetData(), srcLayout.get(),
     147           0 :                               aFormat, dstBuffer);
     148             : 
     149           0 :     if (!dstLayout) {
     150           0 :       aRv.Throw(NS_ERROR_NOT_AVAILABLE);
     151           0 :       return nullptr;
     152             :     }
     153             : 
     154           0 :     return dstLayout;
     155             :   }
     156             : 
     157             : protected:
     158             :   Impl() {}
     159             : 
     160           0 :   DataSourceSurface* Surface() const
     161             :   {
     162           0 :     if (!mSurface) {
     163           0 :       RefPtr<SourceSurface> surface = mImage->GetAsSourceSurface();
     164           0 :       MOZ_ASSERT(surface);
     165             : 
     166           0 :       mSurface = surface->GetDataSurface();
     167           0 :       MOZ_ASSERT(mSurface);
     168             :     }
     169             : 
     170           0 :     return mSurface.get();
     171             :   }
     172             : 
     173             :   RefPtr<layers::Image> mImage;
     174             :   mutable RefPtr<DataSourceSurface> mSurface;
     175             : };
     176             : 
     177             : // YUVImpl is optimized for the layers::PlanarYCbCrImage and layers::NVImage.
     178             : // This implementation does not readback data in RGBA format but keep it in YUV
     179             : // format family.
     180           0 : class YUVImpl final : public ImageUtils::Impl
     181             : {
     182             : public:
     183           0 :   explicit YUVImpl(layers::Image* aImage)
     184           0 :   : Impl(aImage)
     185             :   {
     186           0 :     MOZ_ASSERT(aImage->GetFormat() == ImageFormat::PLANAR_YCBCR ||
     187             :                aImage->GetFormat() == ImageFormat::NV_IMAGE);
     188           0 :   }
     189             : 
     190           0 :   ImageBitmapFormat GetFormat() const override
     191             :   {
     192           0 :     return GetImageBitmapFormatFromPlanarYCbCrData(GetPlanarYCbCrData());
     193             :   }
     194             : 
     195           0 :   uint32_t GetBufferLength() const override
     196             :   {
     197           0 :     if (mImage->GetFormat() == ImageFormat::PLANAR_YCBCR) {
     198           0 :       return mImage->AsPlanarYCbCrImage()->GetDataSize();
     199             :     }
     200           0 :     return mImage->AsNVImage()->GetBufferSize();
     201             :   }
     202             : 
     203           0 :   UniquePtr<ImagePixelLayout> MapDataInto(uint8_t* aBuffer,
     204             :                                           uint32_t aOffset,
     205             :                                           uint32_t aBufferLength,
     206             :                                           ImageBitmapFormat aFormat,
     207             :                                           ErrorResult& aRv) const override
     208             :   {
     209             :     // Prepare source buffer and pixel layout.
     210           0 :     const PlanarYCbCrData* data = GetPlanarYCbCrData();
     211             : 
     212             :     UniquePtr<ImagePixelLayout> srcLayout =
     213           0 :       CreatePixelLayoutFromPlanarYCbCrData(data);
     214             : 
     215             :     // Do conversion.
     216             :     UniquePtr<ImagePixelLayout> dstLayout =
     217           0 :       CopyAndConvertImageData(GetFormat(), data->mYChannel, srcLayout.get(),
     218           0 :                               aFormat, aBuffer+aOffset);
     219             : 
     220           0 :     if (!dstLayout) {
     221           0 :       aRv.Throw(NS_ERROR_NOT_AVAILABLE);
     222           0 :       return nullptr;
     223             :     }
     224             : 
     225           0 :     return dstLayout;
     226             :   }
     227             : 
     228             : private:
     229           0 :   const PlanarYCbCrData* GetPlanarYCbCrData() const
     230             :   {
     231           0 :     if (mImage->GetFormat() == ImageFormat::PLANAR_YCBCR) {
     232           0 :       return mImage->AsPlanarYCbCrImage()->GetData();
     233             :     }
     234           0 :     return mImage->AsNVImage()->GetData();
     235             :   }
     236             : };
     237             : 
     238             : // TODO: optimize for other platforms.
     239             : // For GONK: implement GrallocImageImpl, GrallocPlanarYCbCrImpl and GonkCameraImpl.
     240             : // For Windows: implement D3D9RGB32TextureImpl and D3D11ShareHandleTextureImpl.
     241             : // Others: SharedBGRImpl, MACIOSrufaceImpl, GLImageImpl, SurfaceTextureImpl
     242             : //         EGLImageImpl and OverlayImegImpl.
     243             : 
     244           0 : ImageUtils::ImageUtils(layers::Image* aImage)
     245           0 : : mImpl(nullptr)
     246             : {
     247           0 :   MOZ_ASSERT(aImage, "Create ImageUtils with nullptr.");
     248           0 :   switch(aImage->GetFormat()) {
     249             :   case mozilla::ImageFormat::PLANAR_YCBCR:
     250             :   case mozilla::ImageFormat::NV_IMAGE:
     251           0 :     mImpl = new YUVImpl(aImage);
     252           0 :     break;
     253             :   case mozilla::ImageFormat::CAIRO_SURFACE:
     254             :   default:
     255           0 :     mImpl = new Impl(aImage);
     256             :   }
     257           0 : }
     258             : 
     259           0 : ImageUtils::~ImageUtils()
     260             : {
     261           0 :   if (mImpl) { delete mImpl; mImpl = nullptr; }
     262           0 : }
     263             : 
     264             : ImageBitmapFormat
     265           0 : ImageUtils::GetFormat() const
     266             : {
     267           0 :   MOZ_ASSERT(mImpl);
     268           0 :   return mImpl->GetFormat();
     269             : }
     270             : 
     271             : uint32_t
     272           0 : ImageUtils::GetBufferLength() const
     273             : {
     274           0 :   MOZ_ASSERT(mImpl);
     275           0 :   return mImpl->GetBufferLength();
     276             : }
     277             : 
     278             : UniquePtr<ImagePixelLayout>
     279           0 : ImageUtils::MapDataInto(uint8_t* aBuffer,
     280             :                         uint32_t aOffset,
     281             :                         uint32_t aBufferLength,
     282             :                         ImageBitmapFormat aFormat,
     283             :                         ErrorResult& aRv) const
     284             : {
     285           0 :   MOZ_ASSERT(mImpl);
     286           0 :   MOZ_ASSERT(aBuffer, "Map data into a null buffer.");
     287           0 :   return mImpl->MapDataInto(aBuffer, aOffset, aBufferLength, aFormat, aRv);
     288             : }
     289             : 
     290             : } // namespace dom
     291             : } // namespace mozilla

Generated by: LCOV version 1.13