tor-browser

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

ForwardedInputTrack.cpp (10245B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #include "ForwardedInputTrack.h"
      6 
      7 #include <algorithm>
      8 
      9 #include "AudioChannelService.h"
     10 #include "AudioNodeEngine.h"
     11 #include "AudioNodeExternalInputTrack.h"
     12 #include "AudioNodeTrack.h"
     13 #include "AudioSegment.h"
     14 #include "DOMMediaStream.h"
     15 #include "GeckoProfiler.h"
     16 #include "ImageContainer.h"
     17 #include "MediaTrackGraph.h"
     18 #include "Tracing.h"
     19 #include "VideoSegment.h"
     20 #include "mozilla/Logging.h"
     21 #include "nsContentUtils.h"
     22 #include "nsPrintfCString.h"
     23 #include "nsServiceManagerUtils.h"
     24 #include "nsWidgetsCID.h"
     25 #include "prerror.h"
     26 #include "webaudio/MediaStreamAudioDestinationNode.h"
     27 
     28 using namespace mozilla::layers;
     29 using namespace mozilla::dom;
     30 using namespace mozilla::gfx;
     31 
     32 namespace mozilla {
     33 
     34 #ifdef TRACK_LOG
     35 #  undef TRACK_LOG
     36 #endif
     37 
     38 LazyLogModule gForwardedInputTrackLog("ForwardedInputTrack");
     39 #define TRACK_LOG(type, msg) MOZ_LOG(gForwardedInputTrackLog, type, msg)
     40 
     41 ForwardedInputTrack::ForwardedInputTrack(TrackRate aSampleRate,
     42                                         MediaSegment::Type aType)
     43    : ProcessedMediaTrack(
     44          aSampleRate, aType,
     45          aType == MediaSegment::AUDIO
     46              ? static_cast<MediaSegment*>(new AudioSegment())
     47              : static_cast<MediaSegment*>(new VideoSegment())) {}
     48 
     49 void ForwardedInputTrack::AddInput(MediaInputPort* aPort) {
     50  SetInput(aPort);
     51  ProcessedMediaTrack::AddInput(aPort);
     52 }
     53 
     54 void ForwardedInputTrack::RemoveInput(MediaInputPort* aPort) {
     55  TRACK_LOG(LogLevel::Debug,
     56            ("ForwardedInputTrack %p removing input %p", this, aPort));
     57  MOZ_ASSERT(aPort == mInputPort);
     58 
     59  for (const auto& listener : mOwnedDirectListeners) {
     60    MediaTrack* source = mInputPort->GetSource();
     61    TRACK_LOG(LogLevel::Debug,
     62              ("ForwardedInputTrack %p removing direct listener "
     63               "%p. Forwarding to input track %p.",
     64               this, listener.get(), aPort->GetSource()));
     65    source->RemoveDirectListenerImpl(listener);
     66  }
     67 
     68  DisabledTrackMode oldMode = CombinedDisabledMode();
     69  mInputDisabledMode = DisabledTrackMode::ENABLED;
     70  NotifyIfDisabledModeChangedFrom(oldMode);
     71 
     72  mInputPort = nullptr;
     73  ProcessedMediaTrack::RemoveInput(aPort);
     74 }
     75 
     76 void ForwardedInputTrack::SetInput(MediaInputPort* aPort) {
     77  MOZ_ASSERT(aPort);
     78  MOZ_ASSERT(aPort->GetSource());
     79  MOZ_ASSERT(aPort->GetSource()->GetData());
     80  MOZ_ASSERT(!mInputPort);
     81  MOZ_ASSERT(mInputDisabledMode == DisabledTrackMode::ENABLED);
     82 
     83  mInputPort = aPort;
     84 
     85  for (const auto& listener : mOwnedDirectListeners) {
     86    MediaTrack* source = mInputPort->GetSource();
     87    TRACK_LOG(LogLevel::Debug, ("ForwardedInputTrack %p adding direct listener "
     88                                "%p. Forwarding to input track %p.",
     89                                this, listener.get(), aPort->GetSource()));
     90    source->AddDirectListenerImpl(do_AddRef(listener));
     91  }
     92 
     93  DisabledTrackMode oldMode = CombinedDisabledMode();
     94  mInputDisabledMode = mInputPort->GetSource()->CombinedDisabledMode();
     95  NotifyIfDisabledModeChangedFrom(oldMode);
     96 }
     97 
     98 void ForwardedInputTrack::ProcessInputImpl(MediaTrack* aSource,
     99                                           MediaSegment* aSegment,
    100                                           GraphTime aFrom, GraphTime aTo,
    101                                           uint32_t aFlags) {
    102  GraphTime next;
    103  for (GraphTime t = aFrom; t < aTo; t = next) {
    104    MediaInputPort::InputInterval interval =
    105        MediaInputPort::GetNextInputInterval(mInputPort, t);
    106    interval.mEnd = std::min(interval.mEnd, aTo);
    107 
    108    const bool inputEnded =
    109        !aSource ||
    110        (aSource->Ended() &&
    111         aSource->GetEnd() <=
    112             aSource->GraphTimeToTrackTimeWithBlocking(interval.mEnd));
    113 
    114    TrackTime ticks = interval.mEnd - interval.mStart;
    115    next = interval.mEnd;
    116 
    117    if (interval.mStart >= interval.mEnd) {
    118      break;
    119    }
    120 
    121    if (inputEnded) {
    122      if (mAutoend && (aFlags & ALLOW_END)) {
    123        mEnded = true;
    124        break;
    125      }
    126      aSegment->AppendNullData(ticks);
    127      TRACK_LOG(LogLevel::Verbose,
    128                ("ForwardedInputTrack %p appending %lld ticks "
    129                 "of null data (ended input)",
    130                 this, (long long)ticks));
    131    } else if (interval.mInputIsBlocked) {
    132      aSegment->AppendNullData(ticks);
    133      TRACK_LOG(LogLevel::Verbose,
    134                ("ForwardedInputTrack %p appending %lld ticks "
    135                 "of null data (blocked input)",
    136                 this, (long long)ticks));
    137    } else if (InMutedCycle()) {
    138      aSegment->AppendNullData(ticks);
    139    } else if (aSource->IsSuspended()) {
    140      aSegment->AppendNullData(ticks);
    141    } else {
    142      MOZ_ASSERT(GetEnd() == GraphTimeToTrackTimeWithBlocking(interval.mStart),
    143                 "Samples missing");
    144      TrackTime inputStart =
    145          aSource->GraphTimeToTrackTimeWithBlocking(interval.mStart);
    146      TrackTime inputEnd =
    147          aSource->GraphTimeToTrackTimeWithBlocking(interval.mEnd);
    148      aSegment->AppendSlice(*aSource->GetData(), inputStart, inputEnd);
    149    }
    150    ApplyTrackDisabling(aSegment);
    151    for (const auto& listener : mTrackListeners) {
    152      listener->NotifyQueuedChanges(Graph(), GetEnd(), *aSegment);
    153    }
    154    mSegment->AppendFrom(aSegment);
    155  }
    156 }
    157 
    158 void ForwardedInputTrack::ProcessInput(GraphTime aFrom, GraphTime aTo,
    159                                       uint32_t aFlags) {
    160  TRACE_COMMENT("ForwardedInputTrack::ProcessInput", "ForwardedInputTrack %p",
    161                this);
    162  if (mEnded) {
    163    return;
    164  }
    165 
    166  MediaInputPort* input = mInputPort;
    167  MediaTrack* source = input ? input->GetSource() : nullptr;
    168  if (mType == MediaSegment::AUDIO) {
    169    AudioSegment audio;
    170    ProcessInputImpl(source, &audio, aFrom, aTo, aFlags);
    171  } else if (mType == MediaSegment::VIDEO) {
    172    VideoSegment video;
    173    ProcessInputImpl(source, &video, aFrom, aTo, aFlags);
    174  } else {
    175    MOZ_CRASH("Unknown segment type");
    176  }
    177 
    178  if (mEnded) {
    179    RemoveAllDirectListenersImpl();
    180  }
    181 }
    182 
    183 DisabledTrackMode ForwardedInputTrack::CombinedDisabledMode() const {
    184  if (mDisabledMode == DisabledTrackMode::SILENCE_BLACK ||
    185      mInputDisabledMode == DisabledTrackMode::SILENCE_BLACK) {
    186    return DisabledTrackMode::SILENCE_BLACK;
    187  }
    188  if (mDisabledMode == DisabledTrackMode::SILENCE_FREEZE ||
    189      mInputDisabledMode == DisabledTrackMode::SILENCE_FREEZE) {
    190    return DisabledTrackMode::SILENCE_FREEZE;
    191  }
    192  return DisabledTrackMode::ENABLED;
    193 }
    194 
    195 void ForwardedInputTrack::SetDisabledTrackModeImpl(DisabledTrackMode aMode) {
    196  bool enabled = aMode == DisabledTrackMode::ENABLED;
    197  TRACK_LOG(LogLevel::Info, ("ForwardedInputTrack %p was explicitly %s", this,
    198                             enabled ? "enabled" : "disabled"));
    199  for (DirectMediaTrackListener* listener : mOwnedDirectListeners) {
    200    DisabledTrackMode oldMode = mDisabledMode;
    201    bool oldEnabled = oldMode == DisabledTrackMode::ENABLED;
    202    if (!oldEnabled && enabled) {
    203      TRACK_LOG(LogLevel::Debug, ("ForwardedInputTrack %p setting "
    204                                  "direct listener enabled",
    205                                  this));
    206      listener->DecreaseDisabled(oldMode);
    207    } else if (oldEnabled && !enabled) {
    208      TRACK_LOG(LogLevel::Debug, ("ForwardedInputTrack %p setting "
    209                                  "direct listener disabled",
    210                                  this));
    211      listener->IncreaseDisabled(aMode);
    212    }
    213  }
    214  MediaTrack::SetDisabledTrackModeImpl(aMode);
    215 }
    216 
    217 void ForwardedInputTrack::OnInputDisabledModeChanged(
    218    DisabledTrackMode aInputMode) {
    219  MOZ_ASSERT(mInputs.Length() == 1);
    220  MOZ_ASSERT(mInputs[0]->GetSource());
    221  DisabledTrackMode oldMode = CombinedDisabledMode();
    222  if (mInputDisabledMode == DisabledTrackMode::SILENCE_BLACK &&
    223      aInputMode == DisabledTrackMode::SILENCE_FREEZE) {
    224    // Don't allow demoting from SILENCE_BLACK to SILENCE_FREEZE. Frames will
    225    // remain black so we shouldn't notify that the track got enabled.
    226    aInputMode = DisabledTrackMode::SILENCE_BLACK;
    227  }
    228  mInputDisabledMode = aInputMode;
    229  NotifyIfDisabledModeChangedFrom(oldMode);
    230 }
    231 
    232 uint32_t ForwardedInputTrack::NumberOfChannels() const {
    233  MOZ_DIAGNOSTIC_ASSERT(mSegment->GetType() == MediaSegment::AUDIO);
    234  if (!mInputPort || !mInputPort->GetSource()) {
    235    return GetData<AudioSegment>()->MaxChannelCount();
    236  }
    237  return mInputPort->GetSource()->NumberOfChannels();
    238 }
    239 
    240 void ForwardedInputTrack::AddDirectListenerImpl(
    241    already_AddRefed<DirectMediaTrackListener> aListener) {
    242  RefPtr<DirectMediaTrackListener> listener = aListener;
    243  mOwnedDirectListeners.AppendElement(listener);
    244 
    245  DisabledTrackMode currentMode = mDisabledMode;
    246  if (currentMode != DisabledTrackMode::ENABLED) {
    247    listener->IncreaseDisabled(currentMode);
    248  }
    249 
    250  if (mInputPort) {
    251    MediaTrack* source = mInputPort->GetSource();
    252    TRACK_LOG(LogLevel::Debug, ("ForwardedInputTrack %p adding direct listener "
    253                                "%p. Forwarding to input track %p.",
    254                                this, listener.get(), source));
    255    source->AddDirectListenerImpl(listener.forget());
    256  }
    257 }
    258 
    259 void ForwardedInputTrack::RemoveDirectListenerImpl(
    260    DirectMediaTrackListener* aListener) {
    261  for (size_t i = 0; i < mOwnedDirectListeners.Length(); ++i) {
    262    if (mOwnedDirectListeners[i] == aListener) {
    263      TRACK_LOG(LogLevel::Debug,
    264                ("ForwardedInputTrack %p removing direct listener %p", this,
    265                 aListener));
    266      DisabledTrackMode currentMode = mDisabledMode;
    267      if (currentMode != DisabledTrackMode::ENABLED) {
    268        // Reset the listener's state.
    269        aListener->DecreaseDisabled(currentMode);
    270      }
    271      mOwnedDirectListeners.RemoveElementAt(i);
    272      break;
    273    }
    274  }
    275  if (mInputPort) {
    276    // Forward to the input
    277    MediaTrack* source = mInputPort->GetSource();
    278    source->RemoveDirectListenerImpl(aListener);
    279  }
    280 }
    281 
    282 void ForwardedInputTrack::RemoveAllDirectListenersImpl() {
    283  for (const auto& listener : mOwnedDirectListeners.Clone()) {
    284    RemoveDirectListenerImpl(listener);
    285  }
    286  MOZ_DIAGNOSTIC_ASSERT(mOwnedDirectListeners.IsEmpty());
    287 }
    288 
    289 }  // namespace mozilla