tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

RemoteDecoderParent.cpp (7746B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 #include "RemoteDecoderParent.h"
      7 
      8 #include "RemoteCDMParent.h"
      9 #include "RemoteMediaManagerParent.h"
     10 
     11 namespace mozilla {
     12 
     13 RemoteDecoderParent::RemoteDecoderParent(
     14    RemoteMediaManagerParent* aParent,
     15    const CreateDecoderParams::OptionSet& aOptions,
     16    nsISerialEventTarget* aManagerThread, TaskQueue* aDecodeTaskQueue,
     17    const Maybe<uint64_t>& aMediaEngineId, Maybe<TrackingId> aTrackingId,
     18    RemoteCDMParent* aCDM)
     19    : ShmemRecycleAllocator(this),
     20      mParent(aParent),
     21      mOptions(aOptions),
     22      mDecodeTaskQueue(aDecodeTaskQueue),
     23      mCDM(aCDM),
     24      mTrackingId(aTrackingId),
     25      mMediaEngineId(aMediaEngineId),
     26      mManagerThread(aManagerThread) {
     27  MOZ_COUNT_CTOR(RemoteDecoderParent);
     28  MOZ_ASSERT(OnManagerThread());
     29  // We hold a reference to ourselves to keep us alive until IPDL
     30  // explicitly destroys us. There may still be refs held by
     31  // tasks, but no new ones should be added after we're
     32  // destroyed.
     33  mIPDLSelfRef = this;
     34 }
     35 
     36 RemoteDecoderParent::~RemoteDecoderParent() {
     37  MOZ_COUNT_DTOR(RemoteDecoderParent);
     38 }
     39 
     40 void RemoteDecoderParent::Destroy() {
     41  MOZ_ASSERT(OnManagerThread());
     42  mIPDLSelfRef = nullptr;
     43 }
     44 
     45 mozilla::ipc::IPCResult RemoteDecoderParent::RecvInit(
     46    InitResolver&& aResolver) {
     47  MOZ_ASSERT(OnManagerThread());
     48  RefPtr<RemoteDecoderParent> self = this;
     49  mDecoder->Init()->Then(
     50      mManagerThread, __func__,
     51      [self, resolver = std::move(aResolver)](
     52          MediaDataDecoder::InitPromise::ResolveOrRejectValue&& aValue) {
     53        if (!self->CanRecv()) {
     54          // The promise to the child would have already been rejected.
     55          return;
     56        }
     57        if (aValue.IsReject()) {
     58          resolver(aValue.RejectValue());
     59          return;
     60        }
     61        auto track = aValue.ResolveValue();
     62        MOZ_ASSERT(track == TrackInfo::kAudioTrack ||
     63                   track == TrackInfo::kVideoTrack);
     64        if (self->mDecoder) {
     65          nsCString hardwareReason;
     66          bool hardwareAccelerated =
     67              self->mDecoder->IsHardwareAccelerated(hardwareReason);
     68          nsTArray<DecodePropertyIPDL> properties;
     69          for (size_t i = 0; i < MediaDataDecoder::sPropertyNameCount; i++) {
     70            MediaDataDecoder::PropertyName name =
     71                static_cast<MediaDataDecoder::PropertyName>(i);
     72            if (auto v = self->mDecoder->GetDecodeProperty(name)) {
     73              properties.AppendElement(
     74                  DecodePropertyIPDL(name, std::move(v.ref())));
     75            }
     76          }
     77          resolver(InitCompletionIPDL{
     78              track, self->mDecoder->GetDescriptionName(),
     79              self->mDecoder->GetProcessName(), self->mDecoder->GetCodecName(),
     80              hardwareAccelerated, hardwareReason,
     81              self->mDecoder->NeedsConversion(),
     82              self->mDecoder->ShouldDecoderAlwaysBeRecycled(), properties});
     83        }
     84      });
     85  return IPC_OK();
     86 }
     87 
     88 void RemoteDecoderParent::DecodeNextSample(
     89    const RefPtr<ArrayOfRemoteMediaRawData>& aData, size_t aIndex,
     90    MediaDataDecoder::DecodedData&& aOutput, DecodeResolver&& aResolver) {
     91  MOZ_ASSERT(OnManagerThread());
     92 
     93  if (!CanRecv()) {
     94    // Avoid unnecessarily creating shmem objects later.
     95    return;
     96  }
     97 
     98  if (!mDecoder) {
     99    // We got shutdown or the child got destroyed.
    100    aResolver(MediaResult(NS_ERROR_ABORT, __func__));
    101    return;
    102  }
    103 
    104  if (aData->Count() == aIndex) {
    105    DecodedOutputIPDL result;
    106    MediaResult rv = ProcessDecodedData(std::move(aOutput), result);
    107    if (NS_FAILED(rv)) {
    108      aResolver(std::move(rv));  // Out of Memory.
    109    } else {
    110      aResolver(std::move(result));
    111    }
    112    return;
    113  }
    114 
    115  RefPtr<MediaRawData> rawData = aData->ElementAt(aIndex);
    116  if (!rawData) {
    117    // OOM
    118    aResolver(MediaResult(NS_ERROR_OUT_OF_MEMORY, __func__));
    119    return;
    120  }
    121 
    122  mDecoder->Decode(rawData)->Then(
    123      mManagerThread, __func__,
    124      [self = RefPtr{this}, this, aData, aIndex, output = std::move(aOutput),
    125       resolver = std::move(aResolver)](
    126          MediaDataDecoder::DecodePromise::ResolveOrRejectValue&&
    127              aValue) mutable {
    128        if (aValue.IsReject()) {
    129          resolver(aValue.RejectValue());
    130          return;
    131        }
    132 
    133        output.AppendElements(std::move(aValue.ResolveValue()));
    134 
    135        // Call again in case we have more data to decode.
    136        DecodeNextSample(aData, aIndex + 1, std::move(output),
    137                         std::move(resolver));
    138      });
    139 }
    140 
    141 mozilla::ipc::IPCResult RemoteDecoderParent::RecvDecode(
    142    ArrayOfRemoteMediaRawData* aData, DecodeResolver&& aResolver) {
    143  MOZ_ASSERT(OnManagerThread());
    144  // If we are here, we know all previously returned DecodedOutputIPDL got
    145  // used by the child. We can mark all previously sent ShmemBuffer as
    146  // available again.
    147  ReleaseAllBuffers();
    148  MediaDataDecoder::DecodedData output;
    149  DecodeNextSample(aData, 0, std::move(output), std::move(aResolver));
    150 
    151  return IPC_OK();
    152 }
    153 
    154 mozilla::ipc::IPCResult RemoteDecoderParent::RecvFlush(
    155    FlushResolver&& aResolver) {
    156  MOZ_ASSERT(OnManagerThread());
    157  RefPtr<RemoteDecoderParent> self = this;
    158  mDecoder->Flush()->Then(
    159      mManagerThread, __func__,
    160      [self, resolver = std::move(aResolver)](
    161          MediaDataDecoder::FlushPromise::ResolveOrRejectValue&& aValue) {
    162        self->ReleaseAllBuffers();
    163        if (aValue.IsReject()) {
    164          resolver(aValue.RejectValue());
    165        } else {
    166          resolver(MediaResult(NS_OK));
    167        }
    168      });
    169 
    170  return IPC_OK();
    171 }
    172 
    173 mozilla::ipc::IPCResult RemoteDecoderParent::RecvDrain(
    174    DrainResolver&& aResolver) {
    175  MOZ_ASSERT(OnManagerThread());
    176  RefPtr<RemoteDecoderParent> self = this;
    177  mDecoder->Drain()->Then(
    178      mManagerThread, __func__,
    179      [self, this, resolver = std::move(aResolver)](
    180          MediaDataDecoder::DecodePromise::ResolveOrRejectValue&& aValue) {
    181        ReleaseAllBuffers();
    182        if (!self->CanRecv()) {
    183          // Avoid unnecessarily creating shmem objects later.
    184          return;
    185        }
    186        if (aValue.IsReject()) {
    187          resolver(aValue.RejectValue());
    188          return;
    189        }
    190        DecodedOutputIPDL output;
    191        MediaResult rv =
    192            ProcessDecodedData(std::move(aValue.ResolveValue()), output);
    193        if (NS_FAILED(rv)) {
    194          resolver(rv);
    195        } else {
    196          resolver(std::move(output));
    197        }
    198      });
    199  return IPC_OK();
    200 }
    201 
    202 mozilla::ipc::IPCResult RemoteDecoderParent::RecvShutdown(
    203    ShutdownResolver&& aResolver) {
    204  MOZ_ASSERT(OnManagerThread());
    205  if (mDecoder) {
    206    RefPtr<RemoteDecoderParent> self = this;
    207    mDecoder->Shutdown()->Then(
    208        mManagerThread, __func__,
    209        [self, resolver = std::move(aResolver)](
    210            const ShutdownPromise::ResolveOrRejectValue& aValue) {
    211          MOZ_ASSERT(aValue.IsResolve());
    212          self->ReleaseAllBuffers();
    213          resolver(true);
    214        });
    215  }
    216  mDecoder = nullptr;
    217  return IPC_OK();
    218 }
    219 
    220 mozilla::ipc::IPCResult RemoteDecoderParent::RecvSetSeekThreshold(
    221    const TimeUnit& aTime) {
    222  MOZ_ASSERT(OnManagerThread());
    223  mDecoder->SetSeekThreshold(aTime);
    224  return IPC_OK();
    225 }
    226 
    227 void RemoteDecoderParent::ActorDestroy(ActorDestroyReason aWhy) {
    228  MOZ_ASSERT(OnManagerThread());
    229  if (mDecoder) {
    230    mDecoder->Shutdown();
    231    mDecoder = nullptr;
    232  }
    233  CleanupShmemRecycleAllocator();
    234 }
    235 
    236 bool RemoteDecoderParent::OnManagerThread() {
    237  return mParent->OnManagerThread();
    238 }
    239 
    240 }  // namespace mozilla