Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/dom/media/ipc/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 11 kB image not shown  

Quelle  RemoteDecoderChild.cpp   Sprache: 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 "RemoteDecoderChild.h"

#include "RemoteDecoderManagerChild.h"

#include "mozilla/RemoteDecodeUtils.h"

namespace mozilla {

RemoteDecoderChild::RemoteDecoderChild(RemoteDecodeIn aLocation)
    : ShmemRecycleAllocator(this),
      mLocation(aLocation),
      mThread(GetCurrentSerialEventTarget()) {
  MOZ_DIAGNOSTIC_ASSERT(
      RemoteDecoderManagerChild::GetManagerThread() &&
          RemoteDecoderManagerChild::GetManagerThread()->IsOnCurrentThread(),
      "Must be created on the manager thread");
}

RemoteDecoderChild::~RemoteDecoderChild() = default;

void RemoteDecoderChild::HandleRejectionError(
    const ipc::ResponseRejectReason& aReason,
    std::function<void(const MediaResult&)>&& aCallback) {
  // If the channel goes down and CanSend() returns false, the IPDL promise will
  // be rejected with SendError rather than ActorDestroyed. Both means the same
  // thing and we can consider that the parent has crashed. The child can no
  // longer be used.
  //

  // The GPU/RDD process crashed.
  if (mLocation == RemoteDecodeIn::GpuProcess) {
    // The GPU process will get automatically restarted by the parent process.
    // Once it has been restarted the ContentChild will receive the message and
    // will call GetManager()->InitForGPUProcess.
    // We defer reporting an error until we've recreated the RemoteDecoder
    // manager so that it'll be safe for MediaFormatReader to recreate decoders
    RefPtr<RemoteDecoderChild> self = this;
    GetManager()->RunWhenGPUProcessRecreated(NS_NewRunnableFunction(
        "RemoteDecoderChild::HandleRejectionError",
        [self, callback = std::move(aCallback)]() {
          MediaResult error(
              NS_ERROR_DOM_MEDIA_REMOTE_DECODER_CRASHED_RDD_OR_GPU_ERR,
              __func__);
          callback(error);
        }));
    return;
  }

  nsresult err = NS_ERROR_DOM_MEDIA_REMOTE_DECODER_CRASHED_UTILITY_ERR;
  if (mLocation == RemoteDecodeIn::GpuProcess ||
      mLocation == RemoteDecodeIn::RddProcess) {
    err = NS_ERROR_DOM_MEDIA_REMOTE_DECODER_CRASHED_RDD_OR_GPU_ERR;
  } else if (mLocation == RemoteDecodeIn::UtilityProcess_MFMediaEngineCDM) {
    err = NS_ERROR_DOM_MEDIA_REMOTE_DECODER_CRASHED_MF_CDM_ERR;
  }
  // The RDD process is restarted on demand and asynchronously, we can
  // immediately inform the caller that a new decoder is needed. The RDD will
  // then be restarted during the new decoder creation by
  aCallback(MediaResult(err, __func__));
}

// ActorDestroy is called if the channel goes down while waiting for a response.
void RemoteDecoderChild::ActorDestroy(ActorDestroyReason aWhy) {
  mRemoteDecoderCrashed = (aWhy == AbnormalShutdown);
  mDecodedData.Clear();
  CleanupShmemRecycleAllocator();
  RecordShutdownTelemetry(mRemoteDecoderCrashed);
}

void RemoteDecoderChild::DestroyIPDL() {
  AssertOnManagerThread();
  MOZ_DIAGNOSTIC_ASSERT(mInitPromise.IsEmpty() && mDecodePromise.IsEmpty() &&
                            mDrainPromise.IsEmpty() &&
                            mFlushPromise.IsEmpty() &&
                            mShutdownPromise.IsEmpty(),
                        "All promises should have been rejected");
  if (CanSend()) {
    PRemoteDecoderChild::Send__delete__(this);
  }
}

void RemoteDecoderChild::IPDLActorDestroyed() { mIPDLSelfRef = nullptr; }

// MediaDataDecoder methods

RefPtr<MediaDataDecoder::InitPromise> RemoteDecoderChild::Init() {
  AssertOnManagerThread();

  mRemoteDecoderCrashed = false;

  RefPtr<RemoteDecoderChild> self = this;
  SendInit()
      ->Then(
          mThread, __func__,
          [self, this](InitResultIPDL&& aResponse) {
            mInitPromiseRequest.Complete();
            if (aResponse.type() == InitResultIPDL::TMediaResult) {
              mInitPromise.Reject(aResponse.get_MediaResult(), __func__);
              return;
            }
            const auto& initResponse = aResponse.get_InitCompletionIPDL();
            mDescription = initResponse.decoderDescription();
            mDescription.Append(" (");
            mDescription.Append(RemoteDecodeInToStr(GetManager()->Location()));
            mDescription.Append(" remote)");

            mProcessName = initResponse.decoderProcessName();
            mCodecName = initResponse.decoderCodecName();

            mIsHardwareAccelerated = initResponse.hardware();
            mHardwareAcceleratedReason = initResponse.hardwareReason();
            mConversion = initResponse.conversion();
            mShouldDecoderAlwaysBeRecycled =
                initResponse.shouldDecoderAlwaysBeRecycled();
            // Either the promise has not yet been resolved or the handler has
            // been disconnected and we can't get here.
            mInitPromise.Resolve(initResponse.type(), __func__);
          },
          [self](const mozilla::ipc::ResponseRejectReason& aReason) {
            self->mInitPromiseRequest.Complete();
            self->HandleRejectionError(
                aReason, [self](const MediaResult& aError) {
                  self->mInitPromise.RejectIfExists(aError, __func__);
                });
          })
      ->Track(mInitPromiseRequest);

  return mInitPromise.Ensure(__func__);
}

RefPtr<MediaDataDecoder::DecodePromise> RemoteDecoderChild::Decode(
    const nsTArray<RefPtr<MediaRawData>>& aSamples) {
  AssertOnManagerThread();

  if (mRemoteDecoderCrashed) {
    nsresult err = NS_ERROR_DOM_MEDIA_REMOTE_DECODER_CRASHED_UTILITY_ERR;
    if (mLocation == RemoteDecodeIn::GpuProcess ||
        mLocation == RemoteDecodeIn::RddProcess) {
      err = NS_ERROR_DOM_MEDIA_REMOTE_DECODER_CRASHED_RDD_OR_GPU_ERR;
    } else if (mLocation == RemoteDecodeIn::UtilityProcess_MFMediaEngineCDM) {
      err = NS_ERROR_DOM_MEDIA_REMOTE_DECODER_CRASHED_MF_CDM_ERR;
    }
    return MediaDataDecoder::DecodePromise::CreateAndReject(err, __func__);
  }

  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();

        if (aValue.IsReject()) {
          HandleRejectionError(
              aValue.RejectValue(), [self](const MediaResult& aError) {
                self->mDecodePromise.RejectIfExists(aError, __func__);
              });
          return;
        }
        MOZ_DIAGNOSTIC_ASSERT(CanSend(),
                              "The parent unexpectedly died, promise should "
                              "have been rejected first");
        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__);
}

RefPtr<MediaDataDecoder::FlushPromise> RemoteDecoderChild::Flush() {
  AssertOnManagerThread();
  mDecodePromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
  mDrainPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);

  RefPtr<RemoteDecoderChild> self = this;
  SendFlush()->Then(
      mThread, __func__,
      [self](const MediaResult& aResult) {
        if (NS_SUCCEEDED(aResult)) {
          self->mFlushPromise.ResolveIfExists(true, __func__);
        } else {
          self->mFlushPromise.RejectIfExists(aResult, __func__);
        }
      },
      [self](const mozilla::ipc::ResponseRejectReason& aReason) {
        self->HandleRejectionError(aReason, [self](const MediaResult& aError) {
          self->mFlushPromise.RejectIfExists(aError, __func__);
        });
      });
  return mFlushPromise.Ensure(__func__);
}

RefPtr<MediaDataDecoder::DecodePromise> RemoteDecoderChild::Drain() {
  AssertOnManagerThread();

  RefPtr<RemoteDecoderChild> self = this;
  SendDrain()->Then(
      mThread, __func__,
      [self, this](DecodeResultIPDL&& aResponse) {
        if (mDrainPromise.IsEmpty()) {
          // We got flushed.
          return;
        }
        if (aResponse.type() == DecodeResultIPDL::TMediaResult &&
            NS_FAILED(aResponse.get_MediaResult())) {
          mDrainPromise.Reject(aResponse.get_MediaResult(), __func__);
          return;
        }
        MOZ_DIAGNOSTIC_ASSERT(CanSend(),
                              "The parent unexpectedly died, promise should "
                              "have been rejected first");
        if (aResponse.type() == DecodeResultIPDL::TDecodedOutputIPDL) {
          ProcessOutput(std::move(aResponse.get_DecodedOutputIPDL()));
        }
        mDrainPromise.Resolve(std::move(mDecodedData), __func__);
        mDecodedData = MediaDataDecoder::DecodedData();
      },
      [self](const mozilla::ipc::ResponseRejectReason& aReason) {
        self->HandleRejectionError(aReason, [self](const MediaResult& aError) {
          self->mDrainPromise.RejectIfExists(aError, __func__);
        });
      });
  return mDrainPromise.Ensure(__func__);
}

RefPtr<mozilla::ShutdownPromise> RemoteDecoderChild::Shutdown() {
  AssertOnManagerThread();
  // Shutdown() can be called while an InitPromise is pending.
  mInitPromiseRequest.DisconnectIfExists();
  mInitPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
  mDecodePromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
  mDrainPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
  mFlushPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);

  RefPtr<RemoteDecoderChild> self = this;
  SendShutdown()->Then(
      mThread, __func__,
      [self](
          PRemoteDecoderChild::ShutdownPromise::ResolveOrRejectValue&& aValue) {
        self->mShutdownPromise.Resolve(aValue.IsResolve(), __func__);
      });
  return mShutdownPromise.Ensure(__func__);
}

bool RemoteDecoderChild::IsHardwareAccelerated(
    nsACString& aFailureReason) const {
  AssertOnManagerThread();
  aFailureReason = mHardwareAcceleratedReason;
  return mIsHardwareAccelerated;
}

nsCString RemoteDecoderChild::GetDescriptionName() const {
  AssertOnManagerThread();
  return mDescription;
}

nsCString RemoteDecoderChild::GetProcessName() const {
  AssertOnManagerThread();
  return mProcessName;
}

nsCString RemoteDecoderChild::GetCodecName() const {
  AssertOnManagerThread();
  return mCodecName;
}

void RemoteDecoderChild::SetSeekThreshold(const media::TimeUnit& aTime) {
  AssertOnManagerThread();
  Unused << SendSetSeekThreshold(aTime);
}

MediaDataDecoder::ConversionRequired RemoteDecoderChild::NeedsConversion()
    const {
  AssertOnManagerThread();
  return mConversion;
}

bool RemoteDecoderChild::ShouldDecoderAlwaysBeRecycled() const {
  AssertOnManagerThread();
  return mShouldDecoderAlwaysBeRecycled;
}

void RemoteDecoderChild::AssertOnManagerThread() const {
  MOZ_ASSERT(mThread->IsOnCurrentThread());
}

RemoteDecoderManagerChild* RemoteDecoderChild::GetManager() {
  if (!CanSend()) {
    return nullptr;
  }
  return static_cast<RemoteDecoderManagerChild*>(Manager());
}

}  // namespace mozilla

Messung V0.5
C=89 H=95 G=91

¤ Dauer der Verarbeitung: 0.27 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.