tor-browser

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

RemoteImageHolder.cpp (8876B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=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 "RemoteImageHolder.h"
      8 
      9 #include "GPUVideoImage.h"
     10 #include "mozilla/PRemoteDecoderChild.h"
     11 #include "mozilla/RemoteDecodeUtils.h"
     12 #include "mozilla/RemoteMediaManagerChild.h"
     13 #include "mozilla/RemoteMediaManagerParent.h"
     14 #include "mozilla/gfx/SourceSurfaceRawData.h"
     15 #include "mozilla/gfx/Swizzle.h"
     16 #include "mozilla/layers/ImageDataSerializer.h"
     17 #include "mozilla/layers/VideoBridgeUtils.h"
     18 
     19 namespace mozilla {
     20 
     21 using namespace gfx;
     22 using namespace layers;
     23 
     24 RemoteImageHolder::RemoteImageHolder() = default;
     25 RemoteImageHolder::RemoteImageHolder(layers::SurfaceDescriptor&& aSD)
     26    : mSD(Some(std::move(aSD))) {}
     27 RemoteImageHolder::RemoteImageHolder(
     28    layers::IGPUVideoSurfaceManager* aManager,
     29    layers::VideoBridgeSource aSource, const gfx::IntSize& aSize,
     30    const gfx::ColorDepth& aColorDepth, const layers::SurfaceDescriptor& aSD,
     31    gfx::YUVColorSpace aYUVColorSpace, gfx::ColorSpace2 aColorPrimaries,
     32    gfx::TransferFunction aTransferFunction, gfx::ColorRange aColorRange)
     33    : mSource(aSource),
     34      mSize(aSize),
     35      mColorDepth(aColorDepth),
     36      mSD(Some(aSD)),
     37      mManager(aManager),
     38      mYUVColorSpace(aYUVColorSpace),
     39      mColorPrimaries(aColorPrimaries),
     40      mTransferFunction(aTransferFunction),
     41      mColorRange(aColorRange) {}
     42 
     43 RemoteImageHolder::RemoteImageHolder(RemoteImageHolder&& aOther)
     44    : mSource(aOther.mSource),
     45      mSize(aOther.mSize),
     46      mColorDepth(aOther.mColorDepth),
     47      mSD(std::move(aOther.mSD)),
     48      mManager(aOther.mManager),
     49      mYUVColorSpace(aOther.mYUVColorSpace),
     50      mColorPrimaries(aOther.mColorPrimaries),
     51      mTransferFunction(aOther.mTransferFunction),
     52      mColorRange(aOther.mColorRange) {
     53  aOther.mSD = Nothing();
     54 }
     55 
     56 already_AddRefed<Image> RemoteImageHolder::DeserializeImage(
     57    layers::BufferRecycleBin* aBufferRecycleBin) {
     58  MOZ_ASSERT(mSD && mSD->type() == SurfaceDescriptor::TSurfaceDescriptorBuffer);
     59  if (!aBufferRecycleBin) {
     60    return nullptr;
     61  }
     62 
     63  const SurfaceDescriptorBuffer& sdBuffer = mSD->get_SurfaceDescriptorBuffer();
     64  const MemoryOrShmem& memOrShmem = sdBuffer.data();
     65  if (memOrShmem.type() != MemoryOrShmem::TShmem) {
     66    MOZ_ASSERT_UNREACHABLE("Unexpected MemoryOrShmem type");
     67    return nullptr;
     68  }
     69 
     70  // Note that the shmem will be recycled by the parent automatically.
     71  uint8_t* buffer = memOrShmem.get_Shmem().get<uint8_t>();
     72  if (!buffer) {
     73    return nullptr;
     74  }
     75 
     76  size_t bufferSize = memOrShmem.get_Shmem().Size<uint8_t>();
     77 
     78  if (sdBuffer.desc().type() == BufferDescriptor::TYCbCrDescriptor) {
     79    const YCbCrDescriptor& descriptor = sdBuffer.desc().get_YCbCrDescriptor();
     80 
     81    size_t descriptorSize = ImageDataSerializer::ComputeYCbCrBufferSize(
     82        descriptor.ySize(), descriptor.yStride(), descriptor.cbCrSize(),
     83        descriptor.cbCrStride(), descriptor.yOffset(), descriptor.cbOffset(),
     84        descriptor.crOffset());
     85    if (NS_WARN_IF(descriptorSize > bufferSize)) {
     86      MOZ_ASSERT_UNREACHABLE("Buffer too small to fit descriptor!");
     87      return nullptr;
     88    }
     89 
     90    PlanarYCbCrData pData;
     91    pData.mYStride = descriptor.yStride();
     92    pData.mCbCrStride = descriptor.cbCrStride();
     93    // default mYSkip, mCbSkip, mCrSkip because not held in YCbCrDescriptor
     94    pData.mYSkip = pData.mCbSkip = pData.mCrSkip = 0;
     95    pData.mPictureRect = descriptor.display();
     96    pData.mStereoMode = descriptor.stereoMode();
     97    pData.mColorDepth = descriptor.colorDepth();
     98    pData.mYUVColorSpace = descriptor.yUVColorSpace();
     99    pData.mColorRange = descriptor.colorRange();
    100    pData.mChromaSubsampling = descriptor.chromaSubsampling();
    101    pData.mYChannel = ImageDataSerializer::GetYChannel(buffer, descriptor);
    102    pData.mCbChannel = ImageDataSerializer::GetCbChannel(buffer, descriptor);
    103    pData.mCrChannel = ImageDataSerializer::GetCrChannel(buffer, descriptor);
    104 
    105    // images coming from AOMDecoder are RecyclingPlanarYCbCrImages.
    106    RefPtr<RecyclingPlanarYCbCrImage> image =
    107        new RecyclingPlanarYCbCrImage(aBufferRecycleBin);
    108    if (NS_WARN_IF(NS_FAILED(image->CopyData(pData)))) {
    109      return nullptr;
    110    }
    111 
    112    return image.forget();
    113  }
    114 
    115  if (sdBuffer.desc().type() == BufferDescriptor::TRGBDescriptor) {
    116    const RGBDescriptor& descriptor = sdBuffer.desc().get_RGBDescriptor();
    117 
    118    size_t descriptorSize = ImageDataSerializer::ComputeRGBBufferSize(
    119        descriptor.size(), descriptor.format());
    120    if (NS_WARN_IF(descriptorSize > bufferSize)) {
    121      MOZ_ASSERT_UNREACHABLE("Buffer too small to fit descriptor!");
    122      return nullptr;
    123    }
    124 
    125    auto stride = ImageDataSerializer::ComputeRGBStride(
    126        descriptor.format(), descriptor.size().width);
    127    auto surface = MakeRefPtr<SourceSurfaceAlignedRawData>();
    128    if (NS_WARN_IF(!surface->Init(descriptor.size(), descriptor.format(),
    129                                  /* aClearMem */ false, /* aClearValue */ 0,
    130                                  stride))) {
    131      return nullptr;
    132    }
    133 
    134    DataSourceSurface::ScopedMap map(surface, DataSourceSurface::WRITE);
    135    if (NS_WARN_IF(!map.IsMapped())) {
    136      return nullptr;
    137    }
    138 
    139    if (NS_WARN_IF(!SwizzleData(buffer, stride, descriptor.format(),
    140                                map.GetData(), map.GetStride(),
    141                                descriptor.format(), descriptor.size()))) {
    142      return nullptr;
    143    }
    144 
    145    return MakeAndAddRef<SourceSurfaceImage>(descriptor.size(), surface);
    146  }
    147 
    148  MOZ_ASSERT_UNREACHABLE("Unexpected buffer descriptor type!");
    149  return nullptr;
    150 }
    151 
    152 already_AddRefed<layers::Image> RemoteImageHolder::TransferToImage(
    153    layers::BufferRecycleBin* aBufferRecycleBin) {
    154  if (IsEmpty()) {
    155    return nullptr;
    156  }
    157  RefPtr<Image> image;
    158  if (mSD->type() == SurfaceDescriptor::TSurfaceDescriptorBuffer) {
    159    image = DeserializeImage(aBufferRecycleBin);
    160  } else if (mManager) {
    161    image = mManager->TransferToImage(*mSD, mSize, mColorDepth, mYUVColorSpace,
    162                                      mColorPrimaries, mTransferFunction,
    163                                      mColorRange);
    164  }
    165  mSD = Nothing();
    166  mManager = nullptr;
    167 
    168  return image.forget();
    169 }
    170 
    171 RemoteImageHolder::~RemoteImageHolder() {
    172  // GPU Images are held by the RemoteMediaManagerParent, we didn't get to use
    173  // this image holder (the decoder could have been flushed). We don't need to
    174  // worry about Shmem based image as the Shmem will be automatically re-used
    175  // once the decoder is used again.
    176  if (!IsEmpty() && mManager &&
    177      mSD->type() != SurfaceDescriptor::TSurfaceDescriptorBuffer) {
    178    SurfaceDescriptorRemoteDecoder remoteSD =
    179        static_cast<const SurfaceDescriptorGPUVideo&>(*mSD);
    180    mManager->DeallocateSurfaceDescriptor(remoteSD);
    181  }
    182 }
    183 
    184 }  // namespace mozilla
    185 
    186 /* static */ void IPC::ParamTraits<mozilla::RemoteImageHolder>::Write(
    187    MessageWriter* aWriter, mozilla::RemoteImageHolder&& aParam) {
    188  WriteParam(aWriter, aParam.mSource);
    189  WriteParam(aWriter, aParam.mSize);
    190  WriteParam(aWriter, aParam.mColorDepth);
    191  WriteParam(aWriter, aParam.mSD);
    192  WriteParam(aWriter, aParam.mYUVColorSpace);
    193  WriteParam(aWriter, aParam.mColorPrimaries);
    194  WriteParam(aWriter, aParam.mTransferFunction);
    195  WriteParam(aWriter, aParam.mColorRange);
    196  // Empty this holder.
    197  aParam.mSD = mozilla::Nothing();
    198  aParam.mManager = nullptr;
    199 }
    200 
    201 /* static */ bool IPC::ParamTraits<mozilla::RemoteImageHolder>::Read(
    202    MessageReader* aReader, mozilla::RemoteImageHolder* aResult) {
    203  if (!ReadParam(aReader, &aResult->mSource) ||
    204      !ReadParam(aReader, &aResult->mSize) ||
    205      !ReadParam(aReader, &aResult->mColorDepth) ||
    206      !ReadParam(aReader, &aResult->mSD) ||
    207      !ReadParam(aReader, &aResult->mYUVColorSpace) ||
    208      !ReadParam(aReader, &aResult->mColorPrimaries) ||
    209      !ReadParam(aReader, &aResult->mTransferFunction) ||
    210      !ReadParam(aReader, &aResult->mColorRange)) {
    211    return false;
    212  }
    213 
    214  if (aResult->IsEmpty()) {
    215    return true;
    216  }
    217 
    218  if (auto* actor = aReader->GetActor()) {
    219    if (auto* manager = actor->Manager()) {
    220      if (manager->GetProtocolId() ==
    221          mozilla::ipc::ProtocolId::PRemoteMediaManagerMsgStart) {
    222        aResult->mManager =
    223            XRE_IsContentProcess()
    224                ? static_cast<mozilla::IGPUVideoSurfaceManager*>(
    225                      static_cast<mozilla::RemoteMediaManagerChild*>(manager))
    226                : static_cast<mozilla::IGPUVideoSurfaceManager*>(
    227                      static_cast<mozilla::RemoteMediaManagerParent*>(manager));
    228        return true;
    229      }
    230    }
    231  }
    232 
    233  MOZ_ASSERT_UNREACHABLE("Unexpected or missing protocol manager!");
    234  return false;
    235 }