tor-browser

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

ReaderProxy.cpp (8375B)


      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 
      7 #include "ReaderProxy.h"
      8 
      9 #include "MediaFormatReader.h"
     10 #include "TimeUnits.h"
     11 #include "mozilla/CDMProxy.h"
     12 #include "mozilla/MozPromise.h"
     13 
     14 namespace mozilla {
     15 
     16 ReaderProxy::ReaderProxy(AbstractThread* aOwnerThread,
     17                         MediaFormatReader* aReader)
     18    : mOwnerThread(aOwnerThread),
     19      mReader(aReader),
     20      mWatchManager(this, aReader->OwnerThread()),
     21      mDuration(aReader->OwnerThread(), media::NullableTimeUnit(),
     22                "ReaderProxy::mDuration (Mirror)") {
     23  // Must support either heuristic buffering or WaitForData().
     24  MOZ_ASSERT(mReader->UseBufferingHeuristics() ||
     25             mReader->IsWaitForDataSupported());
     26 }
     27 
     28 ReaderProxy::~ReaderProxy() = default;
     29 
     30 media::TimeUnit ReaderProxy::StartTime() const {
     31  MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
     32  return mStartTime.ref();
     33 }
     34 
     35 RefPtr<ReaderProxy::MetadataPromise> ReaderProxy::ReadMetadata() {
     36  MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
     37  MOZ_ASSERT(!mShutdown);
     38  return InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__,
     39                     &MediaFormatReader::AsyncReadMetadata)
     40      ->Then(mOwnerThread, __func__, this, &ReaderProxy::OnMetadataRead,
     41             &ReaderProxy::OnMetadataNotRead);
     42 }
     43 
     44 RefPtr<ReaderProxy::AudioDataPromise> ReaderProxy::OnAudioDataRequestCompleted(
     45    RefPtr<AudioData> aAudio) {
     46  MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
     47 
     48  if (aAudio->AdjustForStartTime(StartTime())) {
     49    return AudioDataPromise::CreateAndResolve(aAudio.forget(), __func__);
     50  }
     51  return AudioDataPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_OVERFLOW_ERR,
     52                                           __func__);
     53 }
     54 
     55 RefPtr<ReaderProxy::AudioDataPromise> ReaderProxy::OnAudioDataRequestFailed(
     56    const MediaResult& aError) {
     57  MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
     58  return AudioDataPromise::CreateAndReject(aError, __func__);
     59 }
     60 
     61 RefPtr<ReaderProxy::AudioDataPromise> ReaderProxy::RequestAudioData() {
     62  MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
     63  MOZ_ASSERT(!mShutdown);
     64 
     65  return InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__,
     66                     &MediaFormatReader::RequestAudioData)
     67      ->Then(mOwnerThread, __func__, this,
     68             &ReaderProxy::OnAudioDataRequestCompleted,
     69             &ReaderProxy::OnAudioDataRequestFailed);
     70 }
     71 
     72 RefPtr<ReaderProxy::VideoDataPromise> ReaderProxy::RequestVideoData(
     73    const media::TimeUnit& aTimeThreshold, bool aRequestNextVideoKeyFrame) {
     74  MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
     75  MOZ_ASSERT(!mShutdown);
     76 
     77  const auto threshold = aTimeThreshold > media::TimeUnit::Zero()
     78                             ? aTimeThreshold + StartTime()
     79                             : aTimeThreshold;
     80 
     81  auto startTime = StartTime();
     82  return InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__,
     83                     &MediaFormatReader::RequestVideoData, threshold,
     84                     aRequestNextVideoKeyFrame)
     85      ->Then(
     86          mOwnerThread, __func__,
     87          [startTime](RefPtr<VideoData> aVideo) {
     88            return aVideo->AdjustForStartTime(startTime)
     89                       ? VideoDataPromise::CreateAndResolve(aVideo.forget(),
     90                                                            __func__)
     91                       : VideoDataPromise::CreateAndReject(
     92                             NS_ERROR_DOM_MEDIA_OVERFLOW_ERR, __func__);
     93          },
     94          [](const MediaResult& aError) {
     95            return VideoDataPromise::CreateAndReject(aError, __func__);
     96          });
     97 }
     98 
     99 RefPtr<ReaderProxy::SeekPromise> ReaderProxy::Seek(const SeekTarget& aTarget) {
    100  MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
    101  return SeekInternal(aTarget);
    102 }
    103 
    104 RefPtr<ReaderProxy::SeekPromise> ReaderProxy::SeekInternal(
    105    const SeekTarget& aTarget) {
    106  MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
    107  SeekTarget adjustedTarget = aTarget;
    108  adjustedTarget.SetTime(adjustedTarget.GetTime() + StartTime());
    109  return InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__,
    110                     &MediaFormatReader::Seek, std::move(adjustedTarget));
    111 }
    112 
    113 RefPtr<ReaderProxy::WaitForDataPromise> ReaderProxy::WaitForData(
    114    MediaData::Type aType) {
    115  MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
    116  MOZ_ASSERT(mReader->IsWaitForDataSupported());
    117  return InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__,
    118                     &MediaFormatReader::WaitForData, aType);
    119 }
    120 
    121 void ReaderProxy::ReleaseResources() {
    122  MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
    123  nsCOMPtr<nsIRunnable> r =
    124      NewRunnableMethod("MediaFormatReader::ReleaseResources", mReader,
    125                        &MediaFormatReader::ReleaseResources);
    126  nsresult rv = mReader->OwnerThread()->Dispatch(r.forget());
    127  MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
    128  (void)rv;
    129 }
    130 
    131 void ReaderProxy::ResetDecode(TrackSet aTracks) {
    132  MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
    133  nsCOMPtr<nsIRunnable> r =
    134      NewRunnableMethod<TrackSet>("MediaFormatReader::ResetDecode", mReader,
    135                                  &MediaFormatReader::ResetDecode, aTracks);
    136  nsresult rv = mReader->OwnerThread()->Dispatch(r.forget());
    137  MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
    138  (void)rv;
    139 }
    140 
    141 RefPtr<ShutdownPromise> ReaderProxy::Shutdown() {
    142  MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
    143  mShutdown = true;
    144  RefPtr<ReaderProxy> self = this;
    145  return InvokeAsync(mReader->OwnerThread(), __func__, [self]() {
    146    self->mDuration.DisconnectIfConnected();
    147    self->mWatchManager.Shutdown();
    148    return self->mReader->Shutdown();
    149  });
    150 }
    151 
    152 RefPtr<ReaderProxy::MetadataPromise> ReaderProxy::OnMetadataRead(
    153    MetadataHolder&& aMetadata) {
    154  MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
    155  if (mShutdown) {
    156    return MetadataPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_ABORT_ERR,
    157                                            __func__);
    158  }
    159 
    160  if (mStartTime.isNothing()) {
    161    mStartTime.emplace(aMetadata.mInfo->mStartTime);
    162  }
    163  return MetadataPromise::CreateAndResolve(std::move(aMetadata), __func__);
    164 }
    165 
    166 RefPtr<ReaderProxy::MetadataPromise> ReaderProxy::OnMetadataNotRead(
    167    const MediaResult& aError) {
    168  return MetadataPromise::CreateAndReject(aError, __func__);
    169 }
    170 
    171 void ReaderProxy::SetVideoBlankDecode(bool aIsBlankDecode) {
    172  MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
    173  nsCOMPtr<nsIRunnable> r = NewRunnableMethod<bool>(
    174      "MediaFormatReader::SetVideoNullDecode", mReader,
    175      &MediaFormatReader::SetVideoNullDecode, aIsBlankDecode);
    176  nsresult rv = mReader->OwnerThread()->Dispatch(r.forget());
    177  MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
    178  (void)rv;
    179 }
    180 
    181 void ReaderProxy::UpdateDuration() {
    182  MOZ_ASSERT(mReader->OwnerThread()->IsCurrentThreadIn());
    183  mReader->UpdateDuration(mDuration.Ref().ref());
    184 }
    185 
    186 void ReaderProxy::SetCanonicalDuration(
    187    Canonical<media::NullableTimeUnit>& aCanonical) {
    188  MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
    189  nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
    190      "ReaderProxy::SetCanonicalDuration", [this, self = RefPtr(this)]() {
    191        mWatchManager.Watch(mDuration, &ReaderProxy::UpdateDuration);
    192      });
    193  mReader->OwnerThread()->DispatchStateChange(r.forget());
    194  aCanonical.ConnectMirror(&mDuration);
    195 }
    196 
    197 void ReaderProxy::UpdateMediaEngineId(uint64_t aMediaEngineId) {
    198  MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
    199  nsCOMPtr<nsIRunnable> r = NewRunnableMethod<uint64_t>(
    200      "MediaFormatReader::UpdateMediaEngineId", mReader,
    201      &MediaFormatReader::UpdateMediaEngineId, aMediaEngineId);
    202  nsresult rv = mReader->OwnerThread()->Dispatch(r.forget());
    203  MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
    204  (void)rv;
    205 }
    206 
    207 RefPtr<SetCDMPromise> ReaderProxy::SetCDMProxy(CDMProxy* aProxy) {
    208  return InvokeAsync<RefPtr<CDMProxy>>(mReader->OwnerThread(), mReader.get(),
    209                                       __func__,
    210                                       &MediaFormatReader::SetCDMProxy, aProxy);
    211 }
    212 
    213 void ReaderProxy::SetEncryptedCustomIdent() {
    214  mReader->SetEncryptedCustomIdent();
    215 }
    216 
    217 bool ReaderProxy::IsEncryptedCustomIdent() const {
    218  return mReader->IsEncryptedCustomIdent();
    219 }
    220 
    221 }  // namespace mozilla