gecko-dev/dom/media/ipc/RemoteAudioDecoder.cpp

155 строки
5.6 KiB
C++

/* -*- 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 "RemoteAudioDecoder.h"
#include "RemoteDecoderManagerChild.h"
#include "OpusDecoder.h"
#include "VorbisDecoder.h"
#include "WAVDecoder.h"
#include "mozilla/PodOperations.h"
namespace mozilla {
RemoteAudioDecoderChild::RemoteAudioDecoderChild() : RemoteDecoderChild() {}
MediaResult RemoteAudioDecoderChild::ProcessOutput(
const DecodedOutputIPDL& aDecodedData) {
AssertOnManagerThread();
MOZ_ASSERT(aDecodedData.type() ==
DecodedOutputIPDL::TArrayOfRemoteAudioDataIPDL);
const nsTArray<RemoteAudioDataIPDL>& arrayData =
aDecodedData.get_ArrayOfRemoteAudioDataIPDL();
for (auto&& data : arrayData) {
AlignedAudioBuffer alignedAudioBuffer;
// Use std::min to make sure we can't overrun our buffer in case someone is
// fibbing about buffer sizes.
if (!alignedAudioBuffer.SetLength(
std::min((unsigned long)data.audioDataBufferSize(),
(unsigned long)data.buffer().Size<AudioDataValue>()))) {
// OOM
return MediaResult(NS_ERROR_OUT_OF_MEMORY, __func__);
}
PodCopy(alignedAudioBuffer.Data(), data.buffer().get<AudioDataValue>(),
alignedAudioBuffer.Length());
RefPtr<AudioData> audio = new AudioData(
data.base().offset(), data.base().time(), std::move(alignedAudioBuffer),
data.channels(), data.rate(), data.channelMap());
mDecodedData.AppendElement(std::move(audio));
}
return NS_OK;
}
MediaResult RemoteAudioDecoderChild::InitIPDL(
const AudioInfo& aAudioInfo,
const CreateDecoderParams::OptionSet& aOptions) {
RefPtr<RemoteDecoderManagerChild> manager =
RemoteDecoderManagerChild::GetRDDProcessSingleton();
// The manager isn't available because RemoteDecoderManagerChild has been
// initialized with null end points and we don't want to decode video on RDD
// process anymore. Return false here so that we can fallback to other PDMs.
if (!manager) {
return MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
RESULT_DETAIL("RemoteDecoderManager is not available."));
}
if (!manager->CanSend()) {
return MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
RESULT_DETAIL("RemoteDecoderManager unable to send."));
}
mIPDLSelfRef = this;
bool success = false;
nsCString errorDescription;
Unused << manager->SendPRemoteDecoderConstructor(
this, aAudioInfo, aOptions, Nothing(), &success, &errorDescription);
return success ? MediaResult(NS_OK)
: MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, errorDescription);
}
RemoteAudioDecoderParent::RemoteAudioDecoderParent(
RemoteDecoderManagerParent* aParent, const AudioInfo& aAudioInfo,
const CreateDecoderParams::OptionSet& aOptions,
TaskQueue* aManagerTaskQueue, TaskQueue* aDecodeTaskQueue, bool* aSuccess,
nsCString* aErrorDescription)
: RemoteDecoderParent(aParent, aManagerTaskQueue, aDecodeTaskQueue),
mAudioInfo(aAudioInfo) {
CreateDecoderParams params(mAudioInfo);
params.mTaskQueue = mDecodeTaskQueue;
params.mOptions = aOptions;
MediaResult error(NS_OK);
params.mError = &error;
if (VorbisDataDecoder::IsVorbis(params.mConfig.mMimeType)) {
mDecoder = new VorbisDataDecoder(params);
} else if (OpusDataDecoder::IsOpus(params.mConfig.mMimeType)) {
mDecoder = new OpusDataDecoder(params);
} else if (WaveDataDecoder::IsWave(params.mConfig.mMimeType)) {
mDecoder = new WaveDataDecoder(params);
}
if (NS_FAILED(error)) {
MOZ_ASSERT(aErrorDescription);
*aErrorDescription = error.Description();
}
*aSuccess = !!mDecoder;
}
MediaResult RemoteAudioDecoderParent::ProcessDecodedData(
const MediaDataDecoder::DecodedData& aData,
DecodedOutputIPDL& aDecodedData) {
MOZ_ASSERT(OnManagerThread());
nsTArray<RemoteAudioDataIPDL> array;
for (const auto& data : aData) {
MOZ_ASSERT(data->mType == MediaData::Type::AUDIO_DATA,
"Can only decode audio using RemoteAudioDecoderParent!");
AudioData* audio = static_cast<AudioData*>(data.get());
MOZ_ASSERT(audio->Data().Elements(),
"Decoded audio must output an AlignedAudioBuffer "
"to be used with RemoteAudioDecoderParent");
ShmemBuffer buffer =
AllocateBuffer(audio->Data().Length() * sizeof(AudioDataValue));
if (!buffer.Valid()) {
return MediaResult(NS_ERROR_OUT_OF_MEMORY,
"ShmemBuffer::Get failed in "
"RemoteAudioDecoderParent::ProcessDecodedData");
}
PodCopy(buffer.Get().get<AudioDataValue>(), audio->Data().Elements(),
audio->Data().Length());
RemoteAudioDataIPDL output(
MediaDataIPDL(data->mOffset, data->mTime, data->mTimecode,
data->mDuration, data->mKeyframe),
audio->mChannels, audio->mRate, audio->mChannelMap,
audio->Data().Length(), std::move(buffer.Get()));
array.AppendElement(output);
}
// With the new possiblity of batch decodes, we can't always move the
// results directly into DecodedOutputIPDL. If there are already
// elements, we should append the new results.
if (aDecodedData.type() == DecodedOutputIPDL::TArrayOfRemoteAudioDataIPDL) {
aDecodedData.get_ArrayOfRemoteAudioDataIPDL().AppendElements(
std::move(array));
} else {
aDecodedData = std::move(array);
}
return NS_OK;
}
} // namespace mozilla