зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1648309 - P2. Add RemoteArrayOfByteBuffer and ArrayOfRemoteMediaRawData objects. r=padenot,mjf
Those two objects can be used to pack multiple array of objects into a minimal amount of shmem. An ArrayOfRemoteByteBuffer will take at most a single shmem and perform a single memory allocation.. Similarly, an ArrayOfMediaRawData will pack multiple MediaRawData in at most 3 shmems (one for each array of bytes a MediaRawData contains). They are designed to work in combination with a ShmemPool which will own each of the allocated Shmem and so can be re-used over and over. Differential Revision: https://phabricator.services.mozilla.com/D91537
This commit is contained in:
Родитель
da79b617d7
Коммит
2c63e2e5b0
|
@ -452,6 +452,18 @@ MediaRawData::MediaRawData(const uint8_t* aData, size_t aSize,
|
|||
mBuffer(aData, aSize),
|
||||
mAlphaBuffer(aAlphaData, aAlphaSize) {}
|
||||
|
||||
MediaRawData::MediaRawData(AlignedByteBuffer&& aData)
|
||||
: MediaData(Type::RAW_DATA),
|
||||
mCrypto(mCryptoInternal),
|
||||
mBuffer(std::move(aData)) {}
|
||||
|
||||
MediaRawData::MediaRawData(AlignedByteBuffer&& aData,
|
||||
AlignedByteBuffer&& aAlphaData)
|
||||
: MediaData(Type::RAW_DATA),
|
||||
mCrypto(mCryptoInternal),
|
||||
mBuffer(std::move(aData)),
|
||||
mAlphaBuffer(std::move(aAlphaData)) {}
|
||||
|
||||
already_AddRefed<MediaRawData> MediaRawData::Clone() const {
|
||||
RefPtr<MediaRawData> s = new MediaRawData;
|
||||
s->mTimecode = mTimecode;
|
||||
|
|
|
@ -610,6 +610,8 @@ class MediaRawData final : public MediaData {
|
|||
MediaRawData(const uint8_t* aData, size_t aSize);
|
||||
MediaRawData(const uint8_t* aData, size_t aSize, const uint8_t* aAlphaData,
|
||||
size_t aAlphaSize);
|
||||
explicit MediaRawData(AlignedByteBuffer&& aData);
|
||||
MediaRawData(AlignedByteBuffer&& aData, AlignedByteBuffer&& aAlphaData);
|
||||
|
||||
// Pointer to data or null if not-yet allocated
|
||||
const uint8_t* Data() const { return mBuffer.Data(); }
|
||||
|
@ -658,6 +660,7 @@ class MediaRawData final : public MediaData {
|
|||
|
||||
private:
|
||||
friend class MediaRawDataWriter;
|
||||
friend class ArrayOfRemoteMediaRawData;
|
||||
AlignedByteBuffer mBuffer;
|
||||
AlignedByteBuffer mAlphaBuffer;
|
||||
CryptoSample mCryptoInternal;
|
||||
|
|
|
@ -0,0 +1,239 @@
|
|||
/* -*- 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 "RemoteMediaData.h"
|
||||
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/dom/MediaIPCUtils.h"
|
||||
#include "mozilla/ipc/Shmem.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
bool RemoteArrayOfByteBuffer::AllocateShmem(
|
||||
size_t aSize, std::function<ShmemBuffer(size_t)>& aAllocator) {
|
||||
ShmemBuffer buffer = aAllocator(aSize);
|
||||
if (!buffer.Valid()) {
|
||||
return false;
|
||||
}
|
||||
mBuffers.emplace(std::move(buffer.Get()));
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t* RemoteArrayOfByteBuffer::BuffersStartAddress() const {
|
||||
MOZ_ASSERT(mBuffers);
|
||||
return mBuffers->get<uint8_t>();
|
||||
}
|
||||
|
||||
bool RemoteArrayOfByteBuffer::Check(size_t aOffset, size_t aSizeInBytes) const {
|
||||
return mBuffers && detail::IsAddValid(aOffset, aSizeInBytes) &&
|
||||
aOffset + aSizeInBytes <= mBuffers->Size<uint8_t>();
|
||||
}
|
||||
|
||||
void RemoteArrayOfByteBuffer::Write(size_t aOffset, const void* aSourceAddr,
|
||||
size_t aSizeInBytes) {
|
||||
if (!aSizeInBytes) {
|
||||
return;
|
||||
}
|
||||
MOZ_DIAGNOSTIC_ASSERT(Check(aOffset, aSizeInBytes),
|
||||
"Allocated Shmem is too small");
|
||||
memcpy(BuffersStartAddress() + aOffset, aSourceAddr, aSizeInBytes);
|
||||
}
|
||||
|
||||
RemoteArrayOfByteBuffer::RemoteArrayOfByteBuffer() = default;
|
||||
|
||||
RemoteArrayOfByteBuffer::RemoteArrayOfByteBuffer(
|
||||
const nsTArray<RefPtr<MediaByteBuffer>>& aArray,
|
||||
std::function<ShmemBuffer(size_t)>& aAllocator) {
|
||||
// Determine the total size we will need for this object.
|
||||
size_t totalSize = 0;
|
||||
for (const auto& buffer : aArray) {
|
||||
if (buffer) {
|
||||
totalSize += buffer->Length();
|
||||
}
|
||||
}
|
||||
if (totalSize) {
|
||||
if (!AllocateShmem(totalSize, aAllocator)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
size_t offset = 0;
|
||||
for (const auto& buffer : aArray) {
|
||||
size_t sizeBuffer = buffer ? buffer->Length() : 0;
|
||||
if (totalSize && sizeBuffer) {
|
||||
Write(offset, buffer->Elements(), sizeBuffer);
|
||||
}
|
||||
mOffsets.AppendElement(OffsetEntry{offset, sizeBuffer});
|
||||
offset += sizeBuffer;
|
||||
}
|
||||
mIsValid = true;
|
||||
}
|
||||
|
||||
RemoteArrayOfByteBuffer& RemoteArrayOfByteBuffer::operator=(
|
||||
RemoteArrayOfByteBuffer&& aOther) noexcept {
|
||||
mIsValid = aOther.mIsValid;
|
||||
mBuffers = std::move(aOther.mBuffers);
|
||||
mOffsets = std::move(aOther.mOffsets);
|
||||
aOther.mIsValid = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
RemoteArrayOfByteBuffer::~RemoteArrayOfByteBuffer() = default;
|
||||
|
||||
already_AddRefed<MediaByteBuffer> RemoteArrayOfByteBuffer::MediaByteBufferAt(
|
||||
size_t aIndex) const {
|
||||
MOZ_ASSERT(aIndex < Count());
|
||||
const OffsetEntry& entry = mOffsets[aIndex];
|
||||
if (!mBuffers || !Get<1>(entry)) {
|
||||
// It's an empty one.
|
||||
return nullptr;
|
||||
}
|
||||
size_t entrySize = Get<1>(entry);
|
||||
if (!Check(Get<0>(entry), entrySize)) {
|
||||
// This Shmem is corrupted and can't contain the data we are about to
|
||||
// retrieve. We return an empty array instead of asserting to allow for
|
||||
// recovery.
|
||||
return nullptr;
|
||||
}
|
||||
RefPtr<MediaByteBuffer> buffer = new MediaByteBuffer(entrySize);
|
||||
buffer->SetLength(entrySize);
|
||||
memcpy(buffer->Elements(), mBuffers->get<uint8_t>() + Get<0>(entry),
|
||||
entrySize);
|
||||
return buffer.forget();
|
||||
}
|
||||
|
||||
/*static */ void ipc::IPDLParamTraits<RemoteArrayOfByteBuffer>::Write(
|
||||
IPC::Message* aMsg, ipc::IProtocol* aActor,
|
||||
const RemoteArrayOfByteBuffer& aVar) {
|
||||
WriteIPDLParam(aMsg, aActor, aVar.mIsValid);
|
||||
// We need the following gymnastic as the Shmem transfered over IPC will be
|
||||
// revoked. We must create a temporary one instead so that it can be recycled
|
||||
// later back into the original ShmemPool.
|
||||
if (aVar.mBuffers) {
|
||||
WriteIPDLParam(aMsg, aActor, Some(ipc::Shmem(*aVar.mBuffers)));
|
||||
} else {
|
||||
WriteIPDLParam(aMsg, aActor, Maybe<ipc::Shmem>());
|
||||
}
|
||||
WriteIPDLParam(aMsg, aActor, aVar.mOffsets);
|
||||
}
|
||||
|
||||
/* static */ bool ipc::IPDLParamTraits<RemoteArrayOfByteBuffer>::Read(
|
||||
const IPC::Message* aMsg, PickleIterator* aIter,
|
||||
mozilla::ipc::IProtocol* aActor, RemoteArrayOfByteBuffer* aVar) {
|
||||
return ReadIPDLParam(aMsg, aIter, aActor, &aVar->mIsValid) &&
|
||||
ReadIPDLParam(aMsg, aIter, aActor, &aVar->mBuffers) &&
|
||||
ReadIPDLParam(aMsg, aIter, aActor, &aVar->mOffsets);
|
||||
}
|
||||
|
||||
bool ArrayOfRemoteMediaRawData::Fill(
|
||||
const nsTArray<RefPtr<MediaRawData>>& aData,
|
||||
std::function<ShmemBuffer(size_t)>&& aAllocator) {
|
||||
nsTArray<AlignedByteBuffer> dataBuffers(aData.Length());
|
||||
nsTArray<AlignedByteBuffer> alphaBuffers(aData.Length());
|
||||
nsTArray<RefPtr<MediaByteBuffer>> extraDataBuffers(aData.Length());
|
||||
for (auto&& entry : aData) {
|
||||
dataBuffers.AppendElement(std::move(entry->mBuffer));
|
||||
alphaBuffers.AppendElement(std::move(entry->mAlphaBuffer));
|
||||
extraDataBuffers.AppendElement(std::move(entry->mExtraData));
|
||||
mSamples.AppendElement(RemoteMediaRawData{
|
||||
MediaDataIPDL(entry->mOffset, entry->mTime, entry->mTimecode,
|
||||
entry->mDuration, entry->mKeyframe),
|
||||
entry->mEOS, entry->mDiscardPadding,
|
||||
entry->mOriginalPresentationWindow});
|
||||
}
|
||||
mBuffers = RemoteArrayOfByteBuffer(dataBuffers, aAllocator);
|
||||
if (!mBuffers.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
mAlphaBuffers = RemoteArrayOfByteBuffer(alphaBuffers, aAllocator);
|
||||
if (!mAlphaBuffers.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
mExtraDatas = RemoteArrayOfByteBuffer(extraDataBuffers, aAllocator);
|
||||
return mExtraDatas.IsValid();
|
||||
}
|
||||
|
||||
already_AddRefed<MediaRawData> ArrayOfRemoteMediaRawData::ElementAt(
|
||||
size_t aIndex) const {
|
||||
if (!IsValid()) {
|
||||
return nullptr;
|
||||
}
|
||||
MOZ_ASSERT(aIndex < Count());
|
||||
MOZ_DIAGNOSTIC_ASSERT(mBuffers.Count() == Count() &&
|
||||
mAlphaBuffers.Count() == Count() &&
|
||||
mExtraDatas.Count() == Count(),
|
||||
"Something ain't right here");
|
||||
const auto& sample = mSamples[aIndex];
|
||||
AlignedByteBuffer data = mBuffers.AlignedBufferAt<uint8_t>(aIndex);
|
||||
if (mBuffers.SizeAt(aIndex) && !data) {
|
||||
// OOM
|
||||
return nullptr;
|
||||
}
|
||||
AlignedByteBuffer alphaData = mAlphaBuffers.AlignedBufferAt<uint8_t>(aIndex);
|
||||
if (mAlphaBuffers.SizeAt(aIndex) && !alphaData) {
|
||||
// OOM
|
||||
return nullptr;
|
||||
}
|
||||
RefPtr<MediaRawData> rawData;
|
||||
if (mAlphaBuffers.SizeAt(aIndex)) {
|
||||
rawData = new MediaRawData(std::move(data), std::move(alphaData));
|
||||
} else {
|
||||
rawData = new MediaRawData(std::move(data));
|
||||
}
|
||||
rawData->mOffset = sample.mBase.offset();
|
||||
rawData->mTime = sample.mBase.time();
|
||||
rawData->mTimecode = sample.mBase.timecode();
|
||||
rawData->mDuration = sample.mBase.duration();
|
||||
rawData->mKeyframe = sample.mBase.keyframe();
|
||||
rawData->mEOS = sample.mEOS;
|
||||
rawData->mDiscardPadding = sample.mDiscardPadding;
|
||||
rawData->mExtraData = mExtraDatas.MediaByteBufferAt(aIndex);
|
||||
return rawData.forget();
|
||||
}
|
||||
|
||||
/*static */ void ipc::IPDLParamTraits<ArrayOfRemoteMediaRawData*>::Write(
|
||||
IPC::Message* aMsg, ipc::IProtocol* aActor,
|
||||
ArrayOfRemoteMediaRawData* aVar) {
|
||||
WriteIPDLParam(aMsg, aActor, std::move(aVar->mSamples));
|
||||
WriteIPDLParam(aMsg, aActor, std::move(aVar->mBuffers));
|
||||
WriteIPDLParam(aMsg, aActor, std::move(aVar->mAlphaBuffers));
|
||||
WriteIPDLParam(aMsg, aActor, std::move(aVar->mExtraDatas));
|
||||
}
|
||||
|
||||
/* static */ bool ipc::IPDLParamTraits<ArrayOfRemoteMediaRawData*>::Read(
|
||||
const IPC::Message* aMsg, PickleIterator* aIter,
|
||||
mozilla::ipc::IProtocol* aActor, RefPtr<ArrayOfRemoteMediaRawData>* aVar) {
|
||||
auto array = MakeRefPtr<ArrayOfRemoteMediaRawData>();
|
||||
if (!ReadIPDLParam(aMsg, aIter, aActor, &array->mSamples) ||
|
||||
!ReadIPDLParam(aMsg, aIter, aActor, &array->mBuffers) ||
|
||||
!ReadIPDLParam(aMsg, aIter, aActor, &array->mAlphaBuffers) ||
|
||||
!ReadIPDLParam(aMsg, aIter, aActor, &array->mExtraDatas)) {
|
||||
return false;
|
||||
}
|
||||
*aVar = std::move(array);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
ipc::IPDLParamTraits<ArrayOfRemoteMediaRawData::RemoteMediaRawData>::Write(
|
||||
IPC::Message* aMsg, ipc::IProtocol* aActor, const paramType& aVar) {
|
||||
WriteIPDLParam(aMsg, aActor, aVar.mBase);
|
||||
WriteIPDLParam(aMsg, aActor, aVar.mEOS);
|
||||
WriteIPDLParam(aMsg, aActor, aVar.mDiscardPadding);
|
||||
WriteIPDLParam(aMsg, aActor, aVar.mOriginalPresentationWindow);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
ipc::IPDLParamTraits<ArrayOfRemoteMediaRawData::RemoteMediaRawData>::Read(
|
||||
const IPC::Message* aMsg, PickleIterator* aIter, ipc::IProtocol* aActor,
|
||||
paramType* aVar) {
|
||||
MediaDataIPDL mBase;
|
||||
return ReadIPDLParam(aMsg, aIter, aActor, &aVar->mBase) &&
|
||||
ReadIPDLParam(aMsg, aIter, aActor, &aVar->mEOS) &&
|
||||
ReadIPDLParam(aMsg, aIter, aActor, &aVar->mDiscardPadding) &&
|
||||
ReadIPDLParam(aMsg, aIter, aActor, &aVar->mOriginalPresentationWindow);
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
|
@ -7,15 +7,26 @@
|
|||
#ifndef mozilla_dom_media_ipc_RemoteMediaData_h
|
||||
#define mozilla_dom_media_ipc_RemoteMediaData_h
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "MediaData.h"
|
||||
#include "PlatformDecoderModule.h"
|
||||
#include "ipc/IPCMessageUtils.h"
|
||||
#include "mozilla/GfxMessageUtils.h"
|
||||
#include "mozilla/PMediaDecoderParams.h"
|
||||
#include "mozilla/RemoteImageHolder.h"
|
||||
#include "mozilla/ShmemPool.h"
|
||||
#include "mozilla/gfx/Rect.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ShmemPool;
|
||||
|
||||
namespace ipc {
|
||||
class IProtocol;
|
||||
class Shmem;
|
||||
} // namespace ipc
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Declaration of the IPDL type |struct RemoteVideoData|
|
||||
//
|
||||
|
@ -23,9 +34,7 @@ namespace mozilla {
|
|||
// (see bug 1664362)
|
||||
class RemoteVideoData final {
|
||||
private:
|
||||
typedef mozilla::MediaDataIPDL MediaDataIPDL;
|
||||
typedef mozilla::gfx::IntSize IntSize;
|
||||
typedef mozilla::RemoteImageHolder RemoteImageHolder;
|
||||
|
||||
public:
|
||||
RemoteVideoData() = default;
|
||||
|
@ -74,7 +83,7 @@ class ArrayOfRemoteVideoData final {
|
|||
ArrayOfRemoteVideoData(const ArrayOfRemoteVideoData& aOther) {
|
||||
MOZ_CRASH("Should never be used but declared by generated IPDL binding");
|
||||
}
|
||||
ArrayOfRemoteVideoData& operator=(ArrayOfRemoteVideoData&& aOther) {
|
||||
ArrayOfRemoteVideoData& operator=(ArrayOfRemoteVideoData&& aOther) noexcept {
|
||||
if (this != &aOther) {
|
||||
mArray = std::move(aOther.mArray);
|
||||
}
|
||||
|
@ -100,6 +109,143 @@ class ArrayOfRemoteVideoData final {
|
|||
nsTArray<RemoteVideoData> mArray;
|
||||
};
|
||||
|
||||
/* The class will pack either an array of AlignedBuffer or MediaByteBuffer
|
||||
* into a single Shmem objects. */
|
||||
class RemoteArrayOfByteBuffer {
|
||||
public:
|
||||
RemoteArrayOfByteBuffer();
|
||||
template <typename Type>
|
||||
RemoteArrayOfByteBuffer(const nsTArray<AlignedBuffer<Type>>& aArray,
|
||||
std::function<ShmemBuffer(size_t)>& aAllocator) {
|
||||
// Determine the total size we will need for this object.
|
||||
size_t totalSize = 0;
|
||||
for (auto& buffer : aArray) {
|
||||
totalSize += buffer.Size();
|
||||
}
|
||||
if (totalSize) {
|
||||
if (!AllocateShmem(totalSize, aAllocator)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
size_t offset = 0;
|
||||
for (auto& buffer : aArray) {
|
||||
if (totalSize && buffer && buffer.Size()) {
|
||||
Write(offset, buffer.Data(), buffer.Size());
|
||||
}
|
||||
mOffsets.AppendElement(OffsetEntry{offset, buffer.Size()});
|
||||
offset += buffer.Size();
|
||||
}
|
||||
mIsValid = true;
|
||||
}
|
||||
|
||||
RemoteArrayOfByteBuffer(const nsTArray<RefPtr<MediaByteBuffer>>& aArray,
|
||||
std::function<ShmemBuffer(size_t)>& aAllocator);
|
||||
RemoteArrayOfByteBuffer& operator=(RemoteArrayOfByteBuffer&& aOther) noexcept;
|
||||
|
||||
// Return the packed aIndexth buffer as an AlignedByteBuffer.
|
||||
// The operation is fallible should an out of memory be encountered. The
|
||||
// result should be tested accordingly.
|
||||
template <typename Type>
|
||||
AlignedBuffer<Type> AlignedBufferAt(size_t aIndex) const {
|
||||
MOZ_ASSERT(aIndex < Count());
|
||||
const OffsetEntry& entry = mOffsets[aIndex];
|
||||
size_t entrySize = Get<1>(entry);
|
||||
if (!mBuffers || !entrySize) {
|
||||
// It's an empty one.
|
||||
return AlignedBuffer<Type>();
|
||||
}
|
||||
if (!Check(Get<0>(entry), entrySize)) {
|
||||
// This Shmem is corrupted and can't contain the data we are about to
|
||||
// retrieve. We return an empty array instead of asserting to allow for
|
||||
// recovery.
|
||||
return AlignedBuffer<Type>();
|
||||
}
|
||||
if (0 != entrySize % sizeof(Type)) {
|
||||
// There's an error, that entry can't represent this data.
|
||||
return AlignedBuffer<Type>();
|
||||
}
|
||||
return AlignedBuffer<Type>(
|
||||
reinterpret_cast<Type*>(BuffersStartAddress() + Get<0>(entry)),
|
||||
entrySize / sizeof(Type));
|
||||
}
|
||||
|
||||
// Return the packed aIndexth buffer as aMediaByteBuffer.
|
||||
// Will return nullptr if the packed buffer was originally empty.
|
||||
already_AddRefed<MediaByteBuffer> MediaByteBufferAt(size_t aIndex) const;
|
||||
// Return the size of the aIndexth buffer.
|
||||
size_t SizeAt(size_t aIndex) const { return Get<1>(mOffsets[aIndex]); }
|
||||
// Return false if an out of memory error was encountered during construction.
|
||||
bool IsValid() const { return mIsValid; };
|
||||
// Return the number of buffers packed into this entity.
|
||||
size_t Count() const { return mOffsets.Length(); }
|
||||
virtual ~RemoteArrayOfByteBuffer();
|
||||
|
||||
private:
|
||||
friend struct ipc::IPDLParamTraits<RemoteArrayOfByteBuffer>;
|
||||
// Allocate shmem, false if an error occurred.
|
||||
bool AllocateShmem(size_t aSize,
|
||||
std::function<ShmemBuffer(size_t)>& aAllocator);
|
||||
// The starting address of the Shmem
|
||||
uint8_t* BuffersStartAddress() const;
|
||||
// Check that the allocated Shmem can contain such range.
|
||||
bool Check(size_t aOffset, size_t aSizeInBytes) const;
|
||||
void Write(size_t aOffset, const void* aSourceAddr, size_t aSizeInBytes);
|
||||
// Set to false is the buffer isn't initialized yet or a memory error occurred
|
||||
// during construction.
|
||||
bool mIsValid = false;
|
||||
// The packed data. The Maybe will be empty if all buffers packed were
|
||||
// orignally empty.
|
||||
Maybe<ipc::Shmem> mBuffers;
|
||||
// The offset to the start of the individual buffer and its size (all in
|
||||
// bytes)
|
||||
typedef Tuple<size_t, size_t> OffsetEntry;
|
||||
nsTArray<OffsetEntry> mOffsets;
|
||||
};
|
||||
|
||||
/* The class will pack an array of MediaRawData using at most three Shmem
|
||||
* objects. Under the most common scenaria, only two Shmems will be used as
|
||||
* there are few videos with an alpha channel in the wild.
|
||||
* We unfortunately can't populate the array at construction nor present an
|
||||
* interface similar to an actual nsTArray or the ArrayOfRemoteVideoData above
|
||||
* as currently IPC serialization is always non-fallible. So we must create the
|
||||
* object first, fill it to determine if we ran out of memory and then send the
|
||||
* object over IPC.
|
||||
*/
|
||||
class ArrayOfRemoteMediaRawData {
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ArrayOfRemoteMediaRawData)
|
||||
public:
|
||||
// Fill the content, return false if an OOM occurred.
|
||||
bool Fill(const nsTArray<RefPtr<MediaRawData>>& aData,
|
||||
std::function<ShmemBuffer(size_t)>&& aAllocator);
|
||||
|
||||
// Return the aIndexth MediaRawData or nullptr if a memory error occurred.
|
||||
already_AddRefed<MediaRawData> ElementAt(size_t aIndex) const;
|
||||
|
||||
// Return the number of MediaRawData stored in this container.
|
||||
size_t Count() const { return mSamples.Length(); }
|
||||
bool IsEmpty() const { return Count() == 0; }
|
||||
bool IsValid() const {
|
||||
return mBuffers.IsValid() && mAlphaBuffers.IsValid() &&
|
||||
mExtraDatas.IsValid();
|
||||
}
|
||||
|
||||
struct RemoteMediaRawData {
|
||||
MediaDataIPDL mBase;
|
||||
bool mEOS;
|
||||
uint32_t mDiscardPadding;
|
||||
Maybe<media::TimeInterval> mOriginalPresentationWindow;
|
||||
};
|
||||
|
||||
private:
|
||||
friend struct ipc::IPDLParamTraits<ArrayOfRemoteMediaRawData*>;
|
||||
virtual ~ArrayOfRemoteMediaRawData() = default;
|
||||
|
||||
nsTArray<RemoteMediaRawData> mSamples;
|
||||
RemoteArrayOfByteBuffer mBuffers;
|
||||
RemoteArrayOfByteBuffer mAlphaBuffers;
|
||||
RemoteArrayOfByteBuffer mExtraDatas;
|
||||
};
|
||||
|
||||
namespace ipc {
|
||||
|
||||
template <>
|
||||
|
@ -126,15 +272,15 @@ struct IPDLParamTraits<RemoteVideoData> {
|
|||
};
|
||||
|
||||
template <>
|
||||
struct IPDLParamTraits<mozilla::ArrayOfRemoteVideoData*> {
|
||||
typedef mozilla::ArrayOfRemoteVideoData paramType;
|
||||
struct IPDLParamTraits<ArrayOfRemoteVideoData*> {
|
||||
typedef ArrayOfRemoteVideoData paramType;
|
||||
static void Write(IPC::Message* aMsg, mozilla::ipc::IProtocol* aActor,
|
||||
paramType* aVar) {
|
||||
WriteIPDLParam(aMsg, aActor, std::move(aVar->mArray));
|
||||
}
|
||||
|
||||
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
|
||||
mozilla::ipc::IProtocol* aActor, RefPtr<paramType>* aVar) {
|
||||
ipc::IProtocol* aActor, RefPtr<paramType>* aVar) {
|
||||
nsTArray<RemoteVideoData> array;
|
||||
if (!ReadIPDLParam(aMsg, aIter, aActor, &array)) {
|
||||
return false;
|
||||
|
@ -145,8 +291,40 @@ struct IPDLParamTraits<mozilla::ArrayOfRemoteVideoData*> {
|
|||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct IPDLParamTraits<RemoteArrayOfByteBuffer> {
|
||||
typedef RemoteArrayOfByteBuffer paramType;
|
||||
// We do not want to move the RemoteArrayOfByteBuffer as we want to recycle
|
||||
// the shmem it contains for another time.
|
||||
static void Write(IPC::Message* aMsg, ipc::IProtocol* aActor,
|
||||
const paramType& aVar);
|
||||
|
||||
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
|
||||
ipc::IProtocol* aActor, paramType* aVar);
|
||||
};
|
||||
|
||||
template <>
|
||||
struct IPDLParamTraits<ArrayOfRemoteMediaRawData::RemoteMediaRawData> {
|
||||
typedef ArrayOfRemoteMediaRawData::RemoteMediaRawData paramType;
|
||||
static void Write(IPC::Message* aMsg, ipc::IProtocol* aActor,
|
||||
const paramType& aVar);
|
||||
|
||||
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
|
||||
ipc::IProtocol* aActor, paramType* aVar);
|
||||
};
|
||||
|
||||
template <>
|
||||
struct IPDLParamTraits<ArrayOfRemoteMediaRawData*> {
|
||||
typedef ArrayOfRemoteMediaRawData paramType;
|
||||
static void Write(IPC::Message* aMsg, ipc::IProtocol* aActor,
|
||||
paramType* aVar);
|
||||
|
||||
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
|
||||
ipc::IProtocol* aActor, RefPtr<paramType>* aVar);
|
||||
};
|
||||
|
||||
} // namespace ipc
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_media_ipc_RemoteMediaData_h
|
||||
#endif // mozilla_dom_media_ipc_RemoteMediaData_h
|
||||
|
|
|
@ -49,6 +49,7 @@ SOURCES += [
|
|||
'RemoteDecoderModule.cpp',
|
||||
'RemoteDecoderParent.cpp',
|
||||
'RemoteImageHolder.cpp',
|
||||
'RemoteMediaData.cpp',
|
||||
'RemoteMediaDataDecoder.cpp',
|
||||
'RemoteVideoDecoder.cpp',
|
||||
]
|
||||
|
|
Загрузка…
Ссылка в новой задаче