summaryrefslogtreecommitdiffstats
path: root/dom/media/ipc/RemoteImageHolder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/ipc/RemoteImageHolder.cpp')
-rw-r--r--dom/media/ipc/RemoteImageHolder.cpp172
1 files changed, 172 insertions, 0 deletions
diff --git a/dom/media/ipc/RemoteImageHolder.cpp b/dom/media/ipc/RemoteImageHolder.cpp
new file mode 100644
index 0000000000..553e41fef6
--- /dev/null
+++ b/dom/media/ipc/RemoteImageHolder.cpp
@@ -0,0 +1,172 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "RemoteImageHolder.h"
+
+#include "GPUVideoImage.h"
+#include "mozilla/PRemoteDecoderChild.h"
+#include "mozilla/RemoteDecodeUtils.h"
+#include "mozilla/RemoteDecoderManagerChild.h"
+#include "mozilla/layers/ImageDataSerializer.h"
+#include "mozilla/layers/VideoBridgeUtils.h"
+
+namespace mozilla {
+
+using namespace gfx;
+using namespace layers;
+
+RemoteImageHolder::RemoteImageHolder() = default;
+RemoteImageHolder::RemoteImageHolder(layers::IGPUVideoSurfaceManager* aManager,
+ layers::VideoBridgeSource aSource,
+ const gfx::IntSize& aSize,
+ const gfx::ColorDepth& aColorDepth,
+ const layers::SurfaceDescriptor& aSD)
+ : mSource(aSource),
+ mSize(aSize),
+ mColorDepth(aColorDepth),
+ mSD(Some(aSD)),
+ mManager(aManager) {}
+RemoteImageHolder::RemoteImageHolder(RemoteImageHolder&& aOther)
+ : mSource(aOther.mSource),
+ mSize(aOther.mSize),
+ mColorDepth(aOther.mColorDepth),
+ mSD(std::move(aOther.mSD)),
+ mManager(aOther.mManager) {
+ aOther.mSD = Nothing();
+}
+
+already_AddRefed<Image> RemoteImageHolder::DeserializeImage(
+ layers::BufferRecycleBin* aBufferRecycleBin) {
+ MOZ_ASSERT(mSD && mSD->type() == SurfaceDescriptor::TSurfaceDescriptorBuffer);
+ const SurfaceDescriptorBuffer& sdBuffer = mSD->get_SurfaceDescriptorBuffer();
+ MOZ_ASSERT(sdBuffer.desc().type() == BufferDescriptor::TYCbCrDescriptor);
+ if (sdBuffer.desc().type() != BufferDescriptor::TYCbCrDescriptor ||
+ !aBufferRecycleBin) {
+ return nullptr;
+ }
+ const YCbCrDescriptor& descriptor = sdBuffer.desc().get_YCbCrDescriptor();
+
+ uint8_t* buffer = nullptr;
+ const MemoryOrShmem& memOrShmem = sdBuffer.data();
+ switch (memOrShmem.type()) {
+ case MemoryOrShmem::Tuintptr_t:
+ buffer = reinterpret_cast<uint8_t*>(memOrShmem.get_uintptr_t());
+ break;
+ case MemoryOrShmem::TShmem:
+ buffer = memOrShmem.get_Shmem().get<uint8_t>();
+ break;
+ default:
+ MOZ_ASSERT(false, "Unknown MemoryOrShmem type");
+ }
+ if (!buffer) {
+ return nullptr;
+ }
+
+ PlanarYCbCrData pData;
+ pData.mYStride = descriptor.yStride();
+ pData.mCbCrStride = descriptor.cbCrStride();
+ // default mYSkip, mCbSkip, mCrSkip because not held in YCbCrDescriptor
+ pData.mYSkip = pData.mCbSkip = pData.mCrSkip = 0;
+ pData.mPictureRect = descriptor.display();
+ pData.mStereoMode = descriptor.stereoMode();
+ pData.mColorDepth = descriptor.colorDepth();
+ pData.mYUVColorSpace = descriptor.yUVColorSpace();
+ pData.mColorRange = descriptor.colorRange();
+ pData.mChromaSubsampling = descriptor.chromaSubsampling();
+ pData.mYChannel = ImageDataSerializer::GetYChannel(buffer, descriptor);
+ pData.mCbChannel = ImageDataSerializer::GetCbChannel(buffer, descriptor);
+ pData.mCrChannel = ImageDataSerializer::GetCrChannel(buffer, descriptor);
+
+ // images coming from AOMDecoder are RecyclingPlanarYCbCrImages.
+ RefPtr<RecyclingPlanarYCbCrImage> image =
+ new RecyclingPlanarYCbCrImage(aBufferRecycleBin);
+ bool setData = image->CopyData(pData);
+ MOZ_ASSERT(setData);
+
+ switch (memOrShmem.type()) {
+ case MemoryOrShmem::Tuintptr_t:
+ delete[] reinterpret_cast<uint8_t*>(memOrShmem.get_uintptr_t());
+ break;
+ case MemoryOrShmem::TShmem:
+ // Memory buffer will be recycled by the parent automatically.
+ break;
+ default:
+ MOZ_ASSERT(false, "Unknown MemoryOrShmem type");
+ }
+
+ if (!setData) {
+ return nullptr;
+ }
+
+ return image.forget();
+}
+
+already_AddRefed<layers::Image> RemoteImageHolder::TransferToImage(
+ layers::BufferRecycleBin* aBufferRecycleBin) {
+ if (IsEmpty()) {
+ return nullptr;
+ }
+ RefPtr<Image> image;
+ if (mSD->type() == SurfaceDescriptor::TSurfaceDescriptorBuffer) {
+ image = DeserializeImage(aBufferRecycleBin);
+ } else {
+ // The Image here creates a TextureData object that takes ownership
+ // of the SurfaceDescriptor, and is responsible for making sure that
+ // it gets deallocated.
+ SurfaceDescriptorRemoteDecoder remoteSD =
+ static_cast<const SurfaceDescriptorGPUVideo&>(*mSD);
+ remoteSD.source() = Some(mSource);
+ image = new GPUVideoImage(mManager, remoteSD, mSize, mColorDepth);
+ }
+ mSD = Nothing();
+ mManager = nullptr;
+
+ return image.forget();
+}
+
+RemoteImageHolder::~RemoteImageHolder() {
+ // GPU Images are held by the RemoteDecoderManagerParent, we didn't get to use
+ // this image holder (the decoder could have been flushed). We don't need to
+ // worry about Shmem based image as the Shmem will be automatically re-used
+ // once the decoder is used again.
+ if (!IsEmpty() && mManager &&
+ mSD->type() != SurfaceDescriptor::TSurfaceDescriptorBuffer) {
+ SurfaceDescriptorRemoteDecoder remoteSD =
+ static_cast<const SurfaceDescriptorGPUVideo&>(*mSD);
+ mManager->DeallocateSurfaceDescriptor(remoteSD);
+ }
+}
+
+/* static */ void ipc::IPDLParamTraits<RemoteImageHolder>::Write(
+ IPC::MessageWriter* aWriter, ipc::IProtocol* aActor,
+ RemoteImageHolder&& aParam) {
+ WriteIPDLParam(aWriter, aActor, aParam.mSource);
+ WriteIPDLParam(aWriter, aActor, aParam.mSize);
+ WriteIPDLParam(aWriter, aActor, aParam.mColorDepth);
+ WriteIPDLParam(aWriter, aActor, aParam.mSD);
+ // Empty this holder.
+ aParam.mSD = Nothing();
+ aParam.mManager = nullptr;
+}
+
+/* static */ bool ipc::IPDLParamTraits<RemoteImageHolder>::Read(
+ IPC::MessageReader* aReader, ipc::IProtocol* aActor,
+ RemoteImageHolder* aResult) {
+ if (!ReadIPDLParam(aReader, aActor, &aResult->mSource) ||
+ !ReadIPDLParam(aReader, aActor, &aResult->mSize) ||
+ !ReadIPDLParam(aReader, aActor, &aResult->mColorDepth) ||
+ !ReadIPDLParam(aReader, aActor, &aResult->mSD)) {
+ return false;
+ }
+
+ if (!aResult->IsEmpty()) {
+ aResult->mManager = RemoteDecoderManagerChild::GetSingleton(
+ GetRemoteDecodeInFromVideoBridgeSource(aResult->mSource));
+ }
+ return true;
+}
+
+} // namespace mozilla