Bug 1648309 - P3. Use ArrayOfRemoteMediaRawData inplace of an actual array. r=padenot,mjf

The reduce the amount of shmem allocations to 1 instead of 100 when used with webaudio.

We also fix the AudioTrimmer for remote decoders as the trimming information was lost over the IPC serialization.
Another issue corrected is that we no longer crash if the first MediaRawData decoded had an empty size.

Differential Revision: https://phabricator.services.mozilla.com/D91538
This commit is contained in:
Jean-Yves Avenard 2020-09-29 04:39:21 +00:00
Родитель 2c63e2e5b0
Коммит 8f76bc3fd0
5 изменённых файлов: 57 добавлений и 99 удалений

Просмотреть файл

@ -18,16 +18,4 @@ struct MediaDataIPDL
bool keyframe;
};
// used for SendInput/RecvInput
struct MediaRawDataIPDL
{
MediaDataIPDL base;
bool eos;
uint32_t discardPadding;
// Pass along buffer size since we're using ShmemPool
// and we can receive buffers larger than requested size.
int64_t bufferSize;
Shmem buffer;
};
} // namespace mozilla

Просмотреть файл

@ -11,6 +11,7 @@ using mozilla::MediaDataDecoder::ConversionRequired from "PlatformDecoderModule.
using mozilla::TrackInfo::TrackType from "MediaInfo.h";
using mozilla::layers::LayersBackend from "mozilla/layers/LayersTypes.h";
using mozilla::MediaResult from "MediaResult.h";
using refcounted class mozilla::ArrayOfRemoteMediaRawData from "mozilla/RemoteMediaData.h";
using refcounted class mozilla::ArrayOfRemoteVideoData from "mozilla/RemoteMediaData.h";
include PMediaDecoderParams;
include LayersSurfaces;
@ -72,7 +73,7 @@ parent:
// frame. This SurfaceDescriptor can be used on the Layers IPDL protocol, but
// must be released explicitly using DeallocateSurfaceDescriptorGPUVideo
// on the manager protocol.
async Decode(MediaRawDataIPDL[] data) returns (DecodeResultIPDL result);
async Decode(ArrayOfRemoteMediaRawData data) returns (DecodeResultIPDL result);
async Flush() returns (MediaResult error);
async Drain() returns (DecodeResultIPDL result);
async Shutdown() returns (bool unused);

Просмотреть файл

@ -100,62 +100,46 @@ RefPtr<MediaDataDecoder::DecodePromise> RemoteDecoderChild::Decode(
const nsTArray<RefPtr<MediaRawData>>& aSamples) {
AssertOnManagerThread();
nsTArray<MediaRawDataIPDL> samples;
for (auto&& sample : aSamples) {
// TODO: It would be nice to add an allocator method to
// MediaDataDecoder so that the demuxer could write directly
// into shmem rather than requiring a copy here.
ShmemBuffer buffer = AllocateBuffer(sample->Size());
if (!buffer.Valid()) {
return MediaDataDecoder::DecodePromise::CreateAndReject(
NS_ERROR_DOM_MEDIA_DECODE_ERR, __func__);
}
memcpy(buffer.Get().get<uint8_t>(), sample->Data(), sample->Size());
MediaRawDataIPDL rawSample(
MediaDataIPDL(sample->mOffset, sample->mTime, sample->mTimecode,
sample->mDuration, sample->mKeyframe),
sample->mEOS, sample->mDiscardPadding, sample->Size(),
std::move(buffer.Get()));
samples.AppendElement(std::move(rawSample));
auto samples = MakeRefPtr<ArrayOfRemoteMediaRawData>();
if (!samples->Fill(aSamples,
[&](size_t aSize) { return AllocateBuffer(aSize); })) {
return MediaDataDecoder::DecodePromise::CreateAndReject(
NS_ERROR_OUT_OF_MEMORY, __func__);
}
SendDecode(samples)->Then(
mThread, __func__,
[self = RefPtr{this}, this](
PRemoteDecoderChild::DecodePromise::ResolveOrRejectValue&& aValue) {
// We no longer need the samples as the data has been
// processed by the parent.
// If the parent died, the error being fatal will cause the
// decoder to be torn down and all shmem in the pool will be
// deallocated.
ReleaseAllBuffers();
RefPtr<RemoteDecoderChild> self = this;
SendDecode(std::move(samples))
->Then(mThread, __func__,
[self,
this](PRemoteDecoderChild::DecodePromise::ResolveOrRejectValue&&
aValue) {
// We no longer need the samples as the data has been
// processed by the parent.
// If the parent died, the error being fatal will cause the
// decoder to be torn down and all shmem in the pool will be
// deallocated.
ReleaseAllBuffers();
if (aValue.IsReject()) {
HandleRejectionError(
aValue.RejectValue(), [self](const MediaResult& aError) {
self->mDecodePromise.RejectIfExists(aError, __func__);
});
return;
}
if (mDecodePromise.IsEmpty()) {
// We got flushed.
return;
}
auto response = std::move(aValue.ResolveValue());
if (response.type() == DecodeResultIPDL::TMediaResult &&
NS_FAILED(response.get_MediaResult())) {
mDecodePromise.Reject(response.get_MediaResult(), __func__);
return;
}
if (response.type() == DecodeResultIPDL::TDecodedOutputIPDL) {
ProcessOutput(std::move(response.get_DecodedOutputIPDL()));
}
mDecodePromise.Resolve(std::move(mDecodedData), __func__);
mDecodedData = MediaDataDecoder::DecodedData();
});
if (aValue.IsReject()) {
HandleRejectionError(
aValue.RejectValue(), [self](const MediaResult& aError) {
self->mDecodePromise.RejectIfExists(aError, __func__);
});
return;
}
if (mDecodePromise.IsEmpty()) {
// We got flushed.
return;
}
auto response = std::move(aValue.ResolveValue());
if (response.type() == DecodeResultIPDL::TMediaResult &&
NS_FAILED(response.get_MediaResult())) {
mDecodePromise.Reject(response.get_MediaResult(), __func__);
return;
}
if (response.type() == DecodeResultIPDL::TDecodedOutputIPDL) {
ProcessOutput(std::move(response.get_DecodedOutputIPDL()));
}
mDecodePromise.Resolve(std::move(mDecodedData), __func__);
mDecodedData = MediaDataDecoder::DecodedData();
});
return mDecodePromise.Ensure(__func__);
}

Просмотреть файл

@ -5,9 +5,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "RemoteDecoderParent.h"
#include "mozilla/Unused.h"
#include "RemoteDecoderManagerParent.h"
#include "mozilla/Unused.h"
namespace mozilla {
@ -67,41 +66,27 @@ mozilla::ipc::IPCResult RemoteDecoderParent::RecvInit(
return IPC_OK();
}
void RemoteDecoderParent::DecodeNextSample(nsTArray<MediaRawDataIPDL>&& aData,
DecodedOutputIPDL&& aOutput,
DecodeResolver&& aResolver) {
if (aData.IsEmpty()) {
void RemoteDecoderParent::DecodeNextSample(
const RefPtr<ArrayOfRemoteMediaRawData>& aData, size_t aIndex,
DecodedOutputIPDL&& aOutput, DecodeResolver&& aResolver) {
MOZ_ASSERT(OnManagerThread());
if (aData->Count() == aIndex) {
aResolver(std::move(aOutput));
return;
}
const MediaRawDataIPDL& rawData = aData[0];
RefPtr<MediaRawData> data = new MediaRawData(
rawData.buffer().get<uint8_t>(),
std::min((unsigned long)rawData.bufferSize(),
(unsigned long)rawData.buffer().Size<uint8_t>()));
// if MediaRawData's size is less than the actual buffer size recorded
// in MediaRawDataIPDL, consider it an OOM situation.
if ((int64_t)data->Size() < rawData.bufferSize()) {
RefPtr<MediaRawData> rawData = aData->ElementAt(aIndex);
if (!rawData) {
// OOM
ReleaseAllBuffers();
aResolver(MediaResult(NS_ERROR_OUT_OF_MEMORY, __func__));
return;
}
data->mOffset = rawData.base().offset();
data->mTime = rawData.base().time();
data->mTimecode = rawData.base().timecode();
data->mDuration = rawData.base().duration();
data->mKeyframe = rawData.base().keyframe();
data->mEOS = rawData.eos();
data->mDiscardPadding = rawData.discardPadding();
aData.RemoveElementAt(0);
RefPtr<RemoteDecoderParent> self = this;
mDecoder->Decode(data)->Then(
mDecoder->Decode(rawData)->Then(
mManagerThread, __func__,
[self, this, aData = std::move(aData), output = std::move(aOutput),
[self = RefPtr{this}, this, aData, aIndex, output = std::move(aOutput),
resolver = std::move(aResolver)](
MediaDataDecoder::DecodePromise::ResolveOrRejectValue&&
aValue) mutable {
@ -121,14 +106,14 @@ void RemoteDecoderParent::DecodeNextSample(nsTArray<MediaRawDataIPDL>&& aData,
resolver(rv);
} else {
// Call again in case we have more data to decode.
DecodeNextSample(std::move(aData), std::move(output),
DecodeNextSample(aData, aIndex + 1, std::move(output),
std::move(resolver));
}
});
}
mozilla::ipc::IPCResult RemoteDecoderParent::RecvDecode(
nsTArray<MediaRawDataIPDL>&& aData, DecodeResolver&& aResolver) {
ArrayOfRemoteMediaRawData* aData, DecodeResolver&& aResolver) {
MOZ_ASSERT(OnManagerThread());
// XXX: This copies the data into a buffer owned by the MediaRawData. Ideally
// we'd just take ownership of the shmem.
@ -140,7 +125,7 @@ mozilla::ipc::IPCResult RemoteDecoderParent::RecvDecode(
// available again.
ReleaseAllBuffers();
DecodedOutputIPDL output;
DecodeNextSample(std::move(aData), std::move(output), std::move(aResolver));
DecodeNextSample(aData, 0, std::move(output), std::move(aResolver));
return IPC_OK();
}

Просмотреть файл

@ -31,7 +31,7 @@ class RemoteDecoderParent : public ShmemRecycleAllocator<RemoteDecoderParent>,
// PRemoteDecoderParent
IPCResult RecvInit(InitResolver&& aResolver);
IPCResult RecvDecode(nsTArray<MediaRawDataIPDL>&& aData,
IPCResult RecvDecode(ArrayOfRemoteMediaRawData* aData,
DecodeResolver&& aResolver);
IPCResult RecvFlush(FlushResolver&& aResolver);
IPCResult RecvDrain(DrainResolver&& aResolver);
@ -54,8 +54,8 @@ class RemoteDecoderParent : public ShmemRecycleAllocator<RemoteDecoderParent>,
RefPtr<MediaDataDecoder> mDecoder;
private:
void DecodeNextSample(nsTArray<MediaRawDataIPDL>&& aData,
DecodedOutputIPDL&& aOutput,
void DecodeNextSample(const RefPtr<ArrayOfRemoteMediaRawData>& aData,
size_t aIndex, DecodedOutputIPDL&& aOutput,
DecodeResolver&& aResolver);
RefPtr<RemoteDecoderParent> mIPDLSelfRef;
const RefPtr<nsISerialEventTarget> mManagerThread;