From cffbc80aca49fb6f6373c27c369b3f20d88b22ae Mon Sep 17 00:00:00 2001 From: Jean-Yves Avenard Date: Thu, 22 Oct 2020 12:40:29 +0000 Subject: [PATCH] Bug 1672311 - Implement audio trimming for batch jobs. r=padenot Differential Revision: https://phabricator.services.mozilla.com/D94280 --- dom/media/platforms/wrappers/AudioTrimmer.cpp | 71 +++++++++++++------ dom/media/platforms/wrappers/AudioTrimmer.h | 7 +- 2 files changed, 53 insertions(+), 25 deletions(-) diff --git a/dom/media/platforms/wrappers/AudioTrimmer.cpp b/dom/media/platforms/wrappers/AudioTrimmer.cpp index deed07a28961..46dcb05a5e55 100644 --- a/dom/media/platforms/wrappers/AudioTrimmer.cpp +++ b/dom/media/platforms/wrappers/AudioTrimmer.cpp @@ -24,27 +24,8 @@ RefPtr AudioTrimmer::Decode( MediaRawData* aSample) { MOZ_ASSERT(mThread->IsOnCurrentThread(), "We're not on the thread we were first initialized on"); - // A compress sample indicates that it needs to be trimmed after decoding by - // having its mOriginalPresentationWindow member set; in which case - // mOriginalPresentationWindow contains the original time and duration of the - // frame set by the demuxer and mTime and mDuration set to what it should be - // after trimming. RefPtr sample = aSample; - if (sample->mOriginalPresentationWindow) { - LOG("sample[%" PRId64 ",%" PRId64 "] has trimming info ([%" PRId64 - ",%" PRId64 "]", - sample->mOriginalPresentationWindow->mStart.ToMicroseconds(), - sample->mOriginalPresentationWindow->mEnd.ToMicroseconds(), - sample->mTime.ToMicroseconds(), sample->GetEndTime().ToMicroseconds()); - mTrimmers.AppendElement( - Some(TimeInterval(sample->mTime, sample->GetEndTime()))); - sample->mTime = sample->mOriginalPresentationWindow->mStart; - sample->mDuration = sample->mOriginalPresentationWindow->Length(); - } else { - LOG("sample[%" PRId64 ",%" PRId64 "] no trimming information", - sample->mTime.ToMicroseconds(), sample->GetEndTime().ToMicroseconds()); - mTrimmers.AppendElement(Nothing()); - } + PrepareTrimmers(sample); RefPtr self = this; RefPtr p = mDecoder->Decode(sample)->Then( GetCurrentSerialEventTarget(), __func__, @@ -69,8 +50,7 @@ RefPtr AudioTrimmer::Drain() { RefPtr p = mDecoder->Drain()->Then( GetCurrentSerialEventTarget(), __func__, [self = RefPtr{this}](DecodePromise::ResolveOrRejectValue&& aValue) { - auto p = self->HandleDecodedResult(std::move(aValue), nullptr); - return p; + return self->HandleDecodedResult(std::move(aValue), nullptr); }); return p; } @@ -178,6 +158,53 @@ RefPtr AudioTrimmer::HandleDecodedResult( return DecodePromise::CreateAndResolve(std::move(results), __func__); } +RefPtr AudioTrimmer::DecodeBatch( + nsTArray>&& aSamples) { + MOZ_ASSERT(mThread->IsOnCurrentThread(), + "We're not on the thread we were first initialized on"); + LOG("DecodeBatch"); + + for (auto&& sample : aSamples) { + PrepareTrimmers(sample); + } + RefPtr p = + mDecoder->DecodeBatch(std::move(aSamples)) + ->Then(GetCurrentSerialEventTarget(), __func__, + [self = RefPtr{this}]( + DecodePromise::ResolveOrRejectValue&& aValue) { + // If the decoder returned less samples than what we fed it. + // We can assume that this is due to the decoder encoding + // delay and that all decoded frames have been shifted by n = + // compressedSamples.Length() - decodedSamples.Length() and + // that the first n compressed samples returned nothing. + return self->HandleDecodedResult(std::move(aValue), nullptr); + }); + return p; +} + +void AudioTrimmer::PrepareTrimmers(MediaRawData* aRaw) { + // A compress sample indicates that it needs to be trimmed after decoding by + // having its mOriginalPresentationWindow member set; in which case + // mOriginalPresentationWindow contains the original time and duration of + // the frame set by the demuxer and mTime and mDuration set to what it + // should be after trimming. + if (aRaw->mOriginalPresentationWindow) { + LOG("sample[%" PRId64 ",%" PRId64 "] has trimming info ([%" PRId64 + ",%" PRId64 "]", + aRaw->mOriginalPresentationWindow->mStart.ToMicroseconds(), + aRaw->mOriginalPresentationWindow->mEnd.ToMicroseconds(), + aRaw->mTime.ToMicroseconds(), aRaw->GetEndTime().ToMicroseconds()); + mTrimmers.AppendElement( + Some(TimeInterval(aRaw->mTime, aRaw->GetEndTime()))); + aRaw->mTime = aRaw->mOriginalPresentationWindow->mStart; + aRaw->mDuration = aRaw->mOriginalPresentationWindow->Length(); + } else { + LOG("sample[%" PRId64 ",%" PRId64 "] no trimming information", + aRaw->mTime.ToMicroseconds(), aRaw->GetEndTime().ToMicroseconds()); + mTrimmers.AppendElement(Nothing()); + } +} + } // namespace mozilla #undef LOG diff --git a/dom/media/platforms/wrappers/AudioTrimmer.h b/dom/media/platforms/wrappers/AudioTrimmer.h index 82cf7ae9d277..dd7ac1a57bcb 100644 --- a/dom/media/platforms/wrappers/AudioTrimmer.h +++ b/dom/media/platforms/wrappers/AudioTrimmer.h @@ -24,9 +24,7 @@ class AudioTrimmer : public MediaDataDecoder { RefPtr Decode(MediaRawData* aSample) override; bool CanDecodeBatch() const override { return mDecoder->CanDecodeBatch(); } RefPtr DecodeBatch( - nsTArray>&& aSamples) override { - return mDecoder->DecodeBatch(std::move(aSamples)); - } + nsTArray>&& aSamples) override; RefPtr Drain() override; RefPtr Flush() override; RefPtr Shutdown() override; @@ -37,8 +35,11 @@ class AudioTrimmer : public MediaDataDecoder { ConversionRequired NeedsConversion() const override; private: + // Apply trimming information on decoded data. aRaw can be null as it's only + // used for logging purposes. RefPtr HandleDecodedResult( DecodePromise::ResolveOrRejectValue&& aValue, MediaRawData* aRaw); + void PrepareTrimmers(MediaRawData* aRaw); const RefPtr mDecoder; nsCOMPtr mThread; AutoTArray, 2> mTrimmers;