tor-browser

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

AudioStreamTrack.cpp (5284B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      4 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 #include "AudioStreamTrack.h"
      7 
      8 #include "MediaTrackGraph.h"
      9 #include "nsContentUtils.h"
     10 
     11 extern mozilla::LazyLogModule gMediaStreamTrackLog;
     12 #define LOG(type, msg) MOZ_LOG(gMediaStreamTrackLog, type, msg)
     13 
     14 namespace mozilla::dom {
     15 
     16 RefPtr<GenericPromise> AudioStreamTrack::AddAudioOutput(
     17    void* aKey, AudioDeviceInfo* aSink) {
     18  if (Ended()) {
     19    return GenericPromise::CreateAndResolve(true, __func__);
     20  }
     21 
     22  mTrack->AddAudioOutput(aKey, aSink);
     23  return mTrack->Graph()->NotifyWhenDeviceStarted(aSink);
     24 }
     25 
     26 void AudioStreamTrack::RemoveAudioOutput(void* aKey) {
     27  if (Ended()) {
     28    return;
     29  }
     30 
     31  mTrack->RemoveAudioOutput(aKey);
     32 }
     33 
     34 void AudioStreamTrack::SetAudioOutputVolume(void* aKey, float aVolume) {
     35  if (Ended()) {
     36    return;
     37  }
     38 
     39  mTrack->SetAudioOutputVolume(aKey, aVolume);
     40 }
     41 
     42 already_AddRefed<MediaInputPort> AudioStreamTrack::AddConsumerPort(
     43    ProcessedMediaTrack* aTrack) {
     44  MOZ_ASSERT(NS_IsMainThread());
     45  MOZ_ASSERT(!mTrack == Ended());
     46 
     47  if (!mTrack || !aTrack || aTrack->IsDestroyed()) {
     48    LOG(LogLevel::Warning,
     49        ("AudioStreamTrack %p cannot forward contents: track ended or "
     50         "data/destination track ended/destroyed",
     51         this));
     52    return nullptr;
     53  }
     54 
     55  MOZ_ASSERT(!mTrack->IsDestroyed());
     56  if (mTrack->Graph() == aTrack->Graph()) {
     57    return ForwardTrackContentsTo(aTrack);
     58  }
     59 
     60  LOG(LogLevel::Verbose,
     61      ("AudioStreamTrack %p forwarding cross-graph contents from track %p "
     62       "(graph %p) to track %p (graph %p)",
     63       this, mTrack.get(), mTrack->Graph(), aTrack, aTrack->Graph()));
     64 
     65  // Route audio from mTrack through a cross-graph transmitter and receiver to
     66  // aTrack.
     67  MediaTrackGraph* rcvrGraph = aTrack->Graph();
     68 
     69  // Find existing connection for this graph
     70  for (auto& conn : mCrossGraphs) {
     71    if (conn.mPort->mReceiver->Graph() == rcvrGraph) {
     72      conn.mRefCount++;
     73      LOG(LogLevel::Verbose,
     74          ("AudioStreamTrack %p reusing cross-graph port "
     75           "to graph %p (rate %u), refcount now %zu",
     76           this, rcvrGraph, rcvrGraph->GraphRate(), conn.mRefCount));
     77      return aTrack->AllocateInputPort(conn.mPort->mReceiver);
     78    }
     79  }
     80 
     81  // Create new connection if none exists
     82  LOG(LogLevel::Verbose,
     83      ("AudioStreamTrack %p creating cross-graph port to graph %p (rate %u)",
     84       this, rcvrGraph, rcvrGraph->GraphRate()));
     85  CrossGraphConnection* conn = mCrossGraphs.AppendElement(
     86      CrossGraphConnection(CrossGraphPort::Connect(RefPtr{this}, rcvrGraph)));
     87  return aTrack->AllocateInputPort(conn->mPort->mReceiver);
     88 }
     89 
     90 void AudioStreamTrack::RemoveConsumerPort(MediaInputPort* aPort) {
     91  MOZ_ASSERT(NS_IsMainThread());
     92 
     93  if (!aPort) {
     94    return;
     95  }
     96 
     97  MediaTrackGraph* receiverGraph = aPort->Graph();
     98 
     99  // Decrement refcount for this graph's connection and remove if it reaches 0
    100  for (size_t i = 0; i < mCrossGraphs.Length(); ++i) {
    101    auto& conn = mCrossGraphs[i];
    102    if (conn.mPort->mReceiver->Graph() == receiverGraph) {
    103      MOZ_ASSERT(conn.mRefCount > 0);
    104      --conn.mRefCount;
    105      LOG(LogLevel::Verbose,
    106          ("AudioStreamTrack %p decrementing cross-graph port refcount to "
    107           "graph %p (rate %u), refcount now %zu",
    108           this, receiverGraph, receiverGraph->GraphRate(), conn.mRefCount));
    109      if (conn.mRefCount == 0) {
    110        LOG(LogLevel::Verbose,
    111            ("AudioStreamTrack %p removing cross-graph forwarding to graph %p "
    112             "(rate %u)",
    113             this, receiverGraph, receiverGraph->GraphRate()));
    114        mCrossGraphs.UnorderedRemoveElementAt(i);
    115      }
    116      return;
    117    }
    118  }
    119 }
    120 
    121 void AudioStreamTrack::GetLabel(nsAString& aLabel, CallerType aCallerType) {
    122  MediaStreamTrack::GetLabel(aLabel, aCallerType);
    123 }
    124 
    125 already_AddRefed<MediaStreamTrack> AudioStreamTrack::Clone() {
    126  return MediaStreamTrack::CloneInternal<AudioStreamTrack>();
    127 }
    128 
    129 void AudioStreamTrack::SetReadyState(MediaStreamTrackState aState) {
    130  MOZ_ASSERT(NS_IsMainThread());
    131 
    132  // When transitioning from Live to Ended, mTrack will be destroyed. Since
    133  // mTrack is the source for cross-graph data forwarding, keeping cross-graph
    134  // ports is unnecessary. Clearing them here ensures all related connections
    135  // are properly disconnected and prevents an assertion failure in
    136  // CrossGraphTransmitters::ProcessInput due to a missing source.
    137  //
    138  // This state transition may occur in various situations, such as when the
    139  // track is stopped by a user action, or when mTrack is ended during its
    140  // ProcessInput (because its source has ended), which is then detected by
    141  // MediaTrackGraph and ultimately notifies the ended-signal via MTGListener,
    142  // reaching this point.
    143  if (!mCrossGraphs.IsEmpty() && aState == MediaStreamTrackState::Ended) {
    144    MOZ_ASSERT(!Ended());
    145    LOG(LogLevel::Verbose,
    146        ("AudioStreamTrack %p ending, destroying %zu cross-graph ports", this,
    147         mCrossGraphs.Length()));
    148    mCrossGraphs.Clear();
    149  }
    150 
    151  MediaStreamTrack::SetReadyState(aState);
    152 }
    153 
    154 }  // namespace mozilla::dom
    155 
    156 #undef LOG