tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TestImageConversion.cpp (7653B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=2 et sw=2 tw=80: */
      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 "ImageContainer.h"
      8 #include "ImageConversion.h"
      9 #include "SourceSurfaceRawData.h"
     10 #include "gtest/gtest.h"
     11 #include "mozilla/RefPtr.h"
     12 #include "mozilla/dom/ImageBitmapBinding.h"
     13 #include "mozilla/dom/ImageUtils.h"
     14 
     15 using mozilla::ConvertToI420;
     16 using mozilla::MakeAndAddRef;
     17 using mozilla::MakeRefPtr;
     18 using mozilla::Maybe;
     19 using mozilla::Nothing;
     20 using mozilla::Some;
     21 using mozilla::dom::ImageBitmapFormat;
     22 using mozilla::gfx::ChromaSubsampling;
     23 using mozilla::gfx::DataSourceSurface;
     24 using mozilla::gfx::IntSize;
     25 using mozilla::gfx::SourceSurfaceAlignedRawData;
     26 using mozilla::gfx::SurfaceFormat;
     27 using mozilla::layers::PlanarYCbCrImage;
     28 using mozilla::layers::SourceSurfaceImage;
     29 
     30 class TestRedPlanarYCbCrImage2x2 final : public PlanarYCbCrImage {
     31 public:
     32  explicit TestRedPlanarYCbCrImage2x2(ImageBitmapFormat aFormat) {
     33    mSize = IntSize(2, 2);
     34    mBufferSize = sizeof(mY) + sizeof(mU) + sizeof(mV);
     35    mData.mPictureRect = mozilla::gfx::IntRect(mozilla::gfx::IntPoint(), mSize);
     36    mData.mYChannel = mY;
     37    mData.mYStride = 2;
     38    switch (aFormat) {
     39      case ImageBitmapFormat::YUV420P:
     40        mData.mChromaSubsampling = ChromaSubsampling::HALF_WIDTH_AND_HEIGHT;
     41        mData.mCbChannel = mU;
     42        mData.mCrChannel = mV;
     43        mData.mCbCrStride = 1;
     44        break;
     45      case ImageBitmapFormat::YUV422P:
     46        mData.mChromaSubsampling = ChromaSubsampling::HALF_WIDTH;
     47        mData.mCbChannel = mU;
     48        mData.mCrChannel = mV;
     49        mData.mCbCrStride = 1;
     50        break;
     51      case ImageBitmapFormat::YUV444P:
     52        mData.mChromaSubsampling = ChromaSubsampling::FULL;
     53        mData.mCbChannel = mU;
     54        mData.mCrChannel = mV;
     55        mData.mCbCrStride = 2;
     56        break;
     57      case ImageBitmapFormat::YUV420SP_NV12:
     58        mData.mChromaSubsampling = ChromaSubsampling::HALF_WIDTH_AND_HEIGHT;
     59        mData.mCbChannel = mU;
     60        mData.mCrChannel = mData.mCbChannel + 1;
     61        mData.mCbCrStride = 1;
     62        mData.mCrSkip = 1;
     63        mData.mCbSkip = 1;
     64        mU[1] = mV[0];
     65        mU[3] = mV[1];
     66        break;
     67      case ImageBitmapFormat::YUV420SP_NV21:
     68        mData.mChromaSubsampling = ChromaSubsampling::HALF_WIDTH_AND_HEIGHT;
     69        mData.mCrChannel = mU;
     70        mData.mCbChannel = mData.mCrChannel + 1;
     71        mData.mCbCrStride = 1;
     72        mData.mCrSkip = 1;
     73        mData.mCbSkip = 1;
     74        mU[0] = mV[0];
     75        mU[2] = mV[1];
     76        break;
     77      default:
     78        MOZ_CRASH("Unsupported ImageBitmapFormat!");
     79        break;
     80    }
     81  }
     82 
     83  nsresult CopyData(const Data& aData) override {
     84    return NS_ERROR_NOT_IMPLEMENTED;
     85  }
     86 
     87  size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
     88    return 0;
     89  }
     90 
     91 private:
     92  uint8_t mY[4] = {0x52, 0x52, 0x52, 0x52};
     93  uint8_t mU[4] = {0x5A, 0x5A, 0x5A, 0x5A};
     94  uint8_t mV[4] = {0xEF, 0xEF, 0xEF, 0xEF};
     95 };
     96 
     97 static already_AddRefed<SourceSurfaceImage> CreateRedSurfaceImage2x2(
     98    SurfaceFormat aFormat) {
     99  uint8_t redPixel[4] = {};
    100 
    101  switch (aFormat) {
    102    case SurfaceFormat::R8G8B8A8:
    103    case SurfaceFormat::R8G8B8X8:
    104      redPixel[0] = 0xFF;
    105      redPixel[3] = 0xFF;
    106      break;
    107    case SurfaceFormat::B8G8R8A8:
    108    case SurfaceFormat::B8G8R8X8:
    109      redPixel[2] = 0xFF;
    110      redPixel[3] = 0xFF;
    111      break;
    112    case SurfaceFormat::R5G6B5_UINT16:
    113      redPixel[1] = 0xF8;
    114      break;
    115    default:
    116      MOZ_ASSERT_UNREACHABLE("Unsupported format!");
    117      return nullptr;
    118  }
    119 
    120  const IntSize size(2, 2);
    121 
    122  auto surface = MakeRefPtr<SourceSurfaceAlignedRawData>();
    123  if (NS_WARN_IF(!surface->Init(size, aFormat, /* aClearMem */ false, 0, 0))) {
    124    return nullptr;
    125  }
    126 
    127  DataSourceSurface::ScopedMap map(surface, DataSourceSurface::WRITE);
    128  if (NS_WARN_IF(!map.IsMapped())) {
    129    return nullptr;
    130  }
    131 
    132  const uint32_t bpp = BytesPerPixel(aFormat);
    133  MOZ_ASSERT(bpp <= sizeof(redPixel));
    134 
    135  uint8_t* rowPtr = map.GetData();
    136  for (int32_t row = 0; row < size.height; ++row) {
    137    for (int32_t col = 0; col < size.width; ++col) {
    138      for (uint32_t i = 0; i < bpp; ++i) {
    139        rowPtr[col * bpp + i] = redPixel[i];
    140      }
    141    }
    142    rowPtr += map.GetStride();
    143  }
    144 
    145  return MakeAndAddRef<SourceSurfaceImage>(size, surface);
    146 }
    147 
    148 TEST(MediaImageConversion, ConvertToI420)
    149 {
    150  uint8_t y[20] = {};
    151  uint8_t u[20] = {};
    152  uint8_t v[20] = {};
    153 
    154  auto checkBuf = [&](const uint8_t* aY, const uint8_t* aU, const uint8_t* aV) {
    155    for (size_t i = 0; i < sizeof(y); ++i) {
    156      EXPECT_EQ(y[i], aY[i]);
    157    }
    158    for (size_t i = 0; i < sizeof(u); ++i) {
    159      EXPECT_EQ(u[i], aU[i]);
    160    }
    161    for (size_t i = 0; i < sizeof(v); ++i) {
    162      EXPECT_EQ(v[i], aV[i]);
    163    }
    164    memset(y, 0, sizeof(y));
    165    memset(u, 0, sizeof(u));
    166    memset(v, 0, sizeof(v));
    167  };
    168 
    169  static constexpr uint8_t yRed1x1[20] = {0x52};
    170  static constexpr uint8_t yRed2x2[20] = {0x52, 0x52, 0x52, 0x52};
    171  static constexpr uint8_t yRed4x4[20] = {0x52, 0x52, 0x52, 0x52, 0x52, 0x52,
    172                                          0x52, 0x52, 0x52, 0x52, 0x52, 0x52,
    173                                          0x52, 0x52, 0x52, 0x52};
    174 
    175  static constexpr uint8_t uRed1x1[20] = {0x5A};
    176  static constexpr uint8_t uRed2x2[20] = {0x5A, 0x5A, 0x5A, 0x5A};
    177 
    178  static constexpr uint8_t vRed1x1[20] = {0xEF};
    179  static constexpr uint8_t vRed2x2[20] = {0xEF, 0xEF, 0xEF, 0xEF};
    180 
    181  auto checkImage = [&](mozilla::layers::Image* aImage,
    182                        const Maybe<ImageBitmapFormat>& aFormat) {
    183    ASSERT_TRUE(!!aImage);
    184 
    185    mozilla::dom::ImageUtils utils(aImage);
    186    Maybe<ImageBitmapFormat> format = utils.GetFormat();
    187    ASSERT_EQ(format.isSome(), aFormat.isSome());
    188    if (format.isSome()) {
    189      ASSERT_EQ(format.value(), aFormat.value());
    190    }
    191 
    192    EXPECT_TRUE(
    193        NS_SUCCEEDED(ConvertToI420(aImage, y, 2, u, 1, v, 1, IntSize(2, 2))));
    194    checkBuf(yRed2x2, uRed1x1, vRed1x1);
    195 
    196    EXPECT_TRUE(
    197        NS_SUCCEEDED(ConvertToI420(aImage, y, 1, u, 1, v, 1, IntSize(1, 1))));
    198    checkBuf(yRed1x1, uRed1x1, vRed1x1);
    199 
    200    EXPECT_TRUE(
    201        NS_SUCCEEDED(ConvertToI420(aImage, y, 4, u, 2, v, 2, IntSize(4, 4))));
    202    checkBuf(yRed4x4, uRed2x2, vRed2x2);
    203  };
    204 
    205  RefPtr<SourceSurfaceImage> imgRgba =
    206      CreateRedSurfaceImage2x2(SurfaceFormat::R8G8B8A8);
    207  checkImage(imgRgba, Some(ImageBitmapFormat::RGBA32));
    208 
    209  RefPtr<SourceSurfaceImage> imgBgra =
    210      CreateRedSurfaceImage2x2(SurfaceFormat::B8G8R8A8);
    211  checkImage(imgBgra, Some(ImageBitmapFormat::BGRA32));
    212 
    213  RefPtr<SourceSurfaceImage> imgRgb565 =
    214      CreateRedSurfaceImage2x2(SurfaceFormat::R5G6B5_UINT16);
    215  checkImage(imgRgb565, Nothing());
    216 
    217  auto imgYuv420p =
    218      MakeRefPtr<TestRedPlanarYCbCrImage2x2>(ImageBitmapFormat::YUV420P);
    219  checkImage(imgYuv420p, Some(ImageBitmapFormat::YUV420P));
    220 
    221  auto imgYuv422p =
    222      MakeRefPtr<TestRedPlanarYCbCrImage2x2>(ImageBitmapFormat::YUV422P);
    223  checkImage(imgYuv422p, Some(ImageBitmapFormat::YUV422P));
    224 
    225  auto imgYuv444p =
    226      MakeRefPtr<TestRedPlanarYCbCrImage2x2>(ImageBitmapFormat::YUV444P);
    227  checkImage(imgYuv444p, Some(ImageBitmapFormat::YUV444P));
    228 
    229  auto imgYuvNv12 =
    230      MakeRefPtr<TestRedPlanarYCbCrImage2x2>(ImageBitmapFormat::YUV420SP_NV12);
    231  checkImage(imgYuvNv12, Some(ImageBitmapFormat::YUV420SP_NV12));
    232 
    233  auto imgYuvNv21 =
    234      MakeRefPtr<TestRedPlanarYCbCrImage2x2>(ImageBitmapFormat::YUV420SP_NV21);
    235  checkImage(imgYuvNv21, Some(ImageBitmapFormat::YUV420SP_NV21));
    236 }