tor-browser

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

RemoteMediaDataDecoder.cpp (8424B)


      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 "RemoteMediaDataDecoder.h"
      7 
      8 #include "RemoteDecoderChild.h"
      9 #include "RemoteMediaManagerChild.h"
     10 
     11 namespace mozilla {
     12 
     13 #ifdef LOG
     14 #  undef LOG
     15 #endif  // LOG
     16 #define LOG(arg, ...)                                                  \
     17  DDMOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, "::%s: " arg, __func__, \
     18            ##__VA_ARGS__)
     19 
     20 RemoteMediaDataDecoder::RemoteMediaDataDecoder(RemoteDecoderChild* aChild)
     21    : mChild(aChild),
     22      mDescription("RemoteMediaDataDecoder"_ns),
     23      mProcessName("unknown"_ns),
     24      mCodecName("unknown"_ns),
     25      mIsHardwareAccelerated(false),
     26      mConversion(ConversionRequired::kNeedNone),
     27      mShouldDecoderAlwaysBeRecycled(false) {
     28  LOG("%p is created", this);
     29 }
     30 
     31 RemoteMediaDataDecoder::~RemoteMediaDataDecoder() {
     32  if (mChild) {
     33    // Shutdown didn't get called. This can happen if the creation of the
     34    // decoder got interrupted while pending.
     35    nsCOMPtr<nsISerialEventTarget> thread =
     36        RemoteMediaManagerChild::GetManagerThread();
     37    MOZ_ASSERT(thread);
     38    thread->Dispatch(NS_NewRunnableFunction(
     39        "RemoteMediaDataDecoderShutdown", [child = std::move(mChild), thread] {
     40          child->Shutdown()->Then(
     41              thread, __func__,
     42              [child](const ShutdownPromise::ResolveOrRejectValue& aValue) {
     43                child->DestroyIPDL();
     44              });
     45        }));
     46  }
     47  LOG("%p is released", this);
     48 }
     49 
     50 RefPtr<MediaDataDecoder::InitPromise> RemoteMediaDataDecoder::Init() {
     51  auto managerThread = RemoteMediaManagerChild::GetManagerThread();
     52  if (!managerThread) {
     53    return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
     54  }
     55  RefPtr<RemoteMediaDataDecoder> self = this;
     56  return InvokeAsync(managerThread, __func__,
     57                     [self]() { return self->mChild->Init(); })
     58      ->Then(
     59          managerThread, __func__,
     60          [self, this](TrackType aTrack) {
     61            MutexAutoLock lock(mMutex);
     62            // If shutdown has started in the meantime shutdown promise may
     63            // be resloved before this task. In this case mChild will be null
     64            // and the init promise has to be canceled.
     65            if (!mChild) {
     66              return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_CANCELED,
     67                                                  __func__);
     68            }
     69            mDescription = mChild->GetDescriptionName();
     70            mProcessName = mChild->GetProcessName();
     71            mCodecName = mChild->GetCodecName();
     72            mIsHardwareAccelerated =
     73                mChild->IsHardwareAccelerated(mHardwareAcceleratedReason);
     74            mConversion = mChild->NeedsConversion();
     75            mDecodeProperties = mChild->GetDecodeProperties();
     76            mShouldDecoderAlwaysBeRecycled =
     77                mChild->ShouldDecoderAlwaysBeRecycled();
     78            LOG("%p RemoteDecoderChild has been initialized - description: %s, "
     79                "process: %s, codec: %s",
     80                this, mDescription.get(), mProcessName.get(), mCodecName.get());
     81            return InitPromise::CreateAndResolve(aTrack, __func__);
     82          },
     83          [self](const MediaResult& aError) {
     84            return InitPromise::CreateAndReject(aError, __func__);
     85          });
     86 }
     87 
     88 RefPtr<MediaDataDecoder::DecodePromise> RemoteMediaDataDecoder::Decode(
     89    MediaRawData* aSample) {
     90  auto managerThread = RemoteMediaManagerChild::GetManagerThread();
     91  if (!managerThread) {
     92    return DecodePromise::CreateAndReject(NS_ERROR_DOM_MEDIA_CANCELED,
     93                                          __func__);
     94  }
     95  RefPtr<RemoteMediaDataDecoder> self = this;
     96  RefPtr<MediaRawData> sample = aSample;
     97  return InvokeAsync(managerThread, __func__, [self, sample]() {
     98    return self->mChild->Decode(nsTArray<RefPtr<MediaRawData>>{sample});
     99  });
    100 }
    101 
    102 RefPtr<MediaDataDecoder::DecodePromise> RemoteMediaDataDecoder::DecodeBatch(
    103    nsTArray<RefPtr<MediaRawData>>&& aSamples) {
    104  auto managerThread = RemoteMediaManagerChild::GetManagerThread();
    105  if (!managerThread) {
    106    return DecodePromise::CreateAndReject(NS_ERROR_DOM_MEDIA_CANCELED,
    107                                          __func__);
    108  }
    109  RefPtr<RemoteMediaDataDecoder> self = this;
    110  return InvokeAsync(managerThread, __func__,
    111                     [self, samples = std::move(aSamples)]() {
    112                       return self->mChild->Decode(samples);
    113                     });
    114 }
    115 
    116 RefPtr<MediaDataDecoder::FlushPromise> RemoteMediaDataDecoder::Flush() {
    117  auto managerThread = RemoteMediaManagerChild::GetManagerThread();
    118  if (!managerThread) {
    119    return FlushPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
    120  }
    121  RefPtr<RemoteMediaDataDecoder> self = this;
    122  return InvokeAsync(managerThread, __func__,
    123                     [self]() { return self->mChild->Flush(); });
    124 }
    125 
    126 RefPtr<MediaDataDecoder::DecodePromise> RemoteMediaDataDecoder::Drain() {
    127  auto managerThread = RemoteMediaManagerChild::GetManagerThread();
    128  if (!managerThread) {
    129    return DecodePromise::CreateAndReject(NS_ERROR_DOM_MEDIA_CANCELED,
    130                                          __func__);
    131  }
    132  RefPtr<RemoteMediaDataDecoder> self = this;
    133  return InvokeAsync(managerThread, __func__,
    134                     [self]() { return self->mChild->Drain(); });
    135 }
    136 
    137 RefPtr<ShutdownPromise> RemoteMediaDataDecoder::Shutdown() {
    138  auto managerThread = RemoteMediaManagerChild::GetManagerThread();
    139  if (!managerThread) {
    140    return ShutdownPromise::CreateAndResolve(true, __func__);
    141  }
    142  RefPtr<RemoteMediaDataDecoder> self = this;
    143  return InvokeAsync(managerThread, __func__, [self]() {
    144    auto managerThread = RemoteMediaManagerChild::GetManagerThread();
    145    if (!managerThread) {
    146      return ShutdownPromise::CreateAndResolve(true, __func__);
    147    }
    148 
    149    RefPtr<ShutdownPromise> p = self->mChild->Shutdown();
    150 
    151    // We're about to be destroyed and drop our ref to
    152    // *DecoderChild. Make sure we put a ref into the
    153    // task queue for the *DecoderChild thread to keep
    154    // it alive until we send the delete message.
    155    p->Then(managerThread, __func__,
    156            [child = std::move(self->mChild)](
    157                const ShutdownPromise::ResolveOrRejectValue& aValue) {
    158              MOZ_ASSERT(aValue.IsResolve());
    159              child->DestroyIPDL();
    160              return ShutdownPromise::CreateAndResolveOrReject(aValue,
    161                                                               __func__);
    162            });
    163    return p;
    164  });
    165 }
    166 
    167 bool RemoteMediaDataDecoder::IsHardwareAccelerated(
    168    nsACString& aFailureReason) const {
    169  MutexAutoLock lock(mMutex);
    170  aFailureReason = mHardwareAcceleratedReason;
    171  return mIsHardwareAccelerated;
    172 }
    173 
    174 void RemoteMediaDataDecoder::SetSeekThreshold(const media::TimeUnit& aTime) {
    175  auto managerThread = RemoteMediaManagerChild::GetManagerThread();
    176  if (!managerThread) {
    177    return;
    178  }
    179  RefPtr<RemoteMediaDataDecoder> self = this;
    180  media::TimeUnit time = aTime;
    181  managerThread->Dispatch(
    182      NS_NewRunnableFunction("dom::RemoteMediaDataDecoder::SetSeekThreshold",
    183                             [=]() {
    184                               MOZ_ASSERT(self->mChild);
    185                               self->mChild->SetSeekThreshold(time);
    186                             }),
    187      NS_DISPATCH_NORMAL);
    188 }
    189 
    190 MediaDataDecoder::ConversionRequired RemoteMediaDataDecoder::NeedsConversion()
    191    const {
    192  MutexAutoLock lock(mMutex);
    193  return mConversion;
    194 }
    195 
    196 Maybe<MediaDataDecoder::PropertyValue>
    197 RemoteMediaDataDecoder::GetDecodeProperty(
    198    MediaDataDecoder::PropertyName aName) const {
    199  MutexAutoLock lock(mMutex);
    200  return mDecodeProperties[aName];
    201 }
    202 
    203 nsCString RemoteMediaDataDecoder::GetDescriptionName() const {
    204  MutexAutoLock lock(mMutex);
    205  return mDescription;
    206 }
    207 
    208 nsCString RemoteMediaDataDecoder::GetProcessName() const {
    209  MutexAutoLock lock(mMutex);
    210  return mProcessName;
    211 }
    212 
    213 nsCString RemoteMediaDataDecoder::GetCodecName() const {
    214  MutexAutoLock lock(mMutex);
    215  return mCodecName;
    216 }
    217 
    218 bool RemoteMediaDataDecoder::ShouldDecoderAlwaysBeRecycled() const {
    219  MutexAutoLock lock(mMutex);
    220  return mShouldDecoderAlwaysBeRecycled;
    221 }
    222 
    223 #undef LOG
    224 
    225 }  // namespace mozilla