DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (c68fe15a81fc)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef MOZILLA_MEDIATRACKLISTENER_h_
#define MOZILLA_MEDIATRACKLISTENER_h_

#include "MediaTrackGraph.h"
#include "PrincipalHandle.h"

namespace mozilla {

class AudioSegment;
class MediaTrackGraph;
class MediaStreamVideoSink;
class VideoSegment;

/**
 * This is a base class for media graph thread listener callbacks locked to
 * specific tracks. Override methods to be notified of audio or video data or
 * changes in track state.
 *
 * All notification methods are called from the media graph thread. Overriders
 * of these methods are responsible for all synchronization. Beware!
 * These methods are called without the media graph monitor held, so
 * reentry into media graph methods is possible, although very much discouraged!
 * You should do something non-blocking and non-reentrant (e.g. dispatch an
 * event to some thread) and return.
 * The listener is not allowed to add/remove any listeners from the parent
 * track.
 *
 * If a listener is attached to a track that has already ended, we guarantee
 * to call NotifyEnded.
 */
class MediaTrackListener {
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaTrackListener)

 public:
  /**
   * When a SourceMediaTrack has pulling enabled, and the MediaTrackGraph
   * control loop is ready to pull, this gets called for each track in the
   * SourceMediaTrack that is lacking data for the current iteration.
   * A NotifyPull implementation is allowed to call the SourceMediaTrack
   * methods that alter track data.
   *
   * It is not allowed to make other MediaTrack API calls, including
   * calls to add or remove MediaTrackListeners. It is not allowed to
   * block for any length of time.
   *
   * aEndOfAppendedData is the duration of the data that has already been
   * appended to this track, in track time.
   *
   * aDesiredTime is the track time we should append data up to. Data
   * beyond this point will not be played until NotifyPull runs again, so
   * there's not much point in providing it. Note that if the track is blocked
   * for some reason, then data before aDesiredTime may not be played
   * immediately.
   */
  virtual void NotifyPull(MediaTrackGraph* aGraph, TrackTime aEndOfAppendedData,
                          TrackTime aDesiredTime) {}

  virtual void NotifyQueuedChanges(MediaTrackGraph* aGraph,
                                   TrackTime aTrackOffset,
                                   const MediaSegment& aQueuedMedia) {}

  virtual void NotifyPrincipalHandleChanged(
      MediaTrackGraph* aGraph, const PrincipalHandle& aNewPrincipalHandle) {}

  /**
   * Notify that the enabled state for the track this listener is attached to
   * has changed.
   *
   * The enabled state here is referring to whether audio should be audible
   * (enabled) or silent (not enabled); or whether video should be displayed as
   * is (enabled), or black (not enabled).
   */
  virtual void NotifyEnabledStateChanged(MediaTrackGraph* aGraph,
                                         bool aEnabled) {}

  /**
   * Notify that the track output is advancing. aCurrentTrackTime is the number
   * of samples that has been played out for this track in track time.
   */
  virtual void NotifyOutput(MediaTrackGraph* aGraph,
                            TrackTime aCurrentTrackTime) {}

  /**
   * Notify that this track has been ended and all data has been played out.
   */
  virtual void NotifyEnded(MediaTrackGraph* aGraph) {}

  /**
   * Notify that this track listener has been removed from the graph, either
   * after shutdown or through MediaTrack::RemoveListener().
   */
  virtual void NotifyRemoved(MediaTrackGraph* aGraph) {}

 protected:
  virtual ~MediaTrackListener() = default;
};

/**
 * This is a base class for media graph thread listener direct callbacks from
 * within AppendToTrack(). It is bound to a certain track and can only be
 * installed on audio tracks. Once added to a track on any track in the graph,
 * the graph will try to install it at that track's source of media data.
 *
 * This works for ForwardedInputTracks, which will forward the listener to the
 * track's input track if it exists, or wait for it to be created before
 * forwarding if it doesn't.
 * Once it reaches a SourceMediaTrack, it can be successfully installed.
 * Other types of tracks will fail installation since they are not supported.
 *
 * Note that this listener and others for the same track will still get
 * NotifyQueuedChanges() callbacks from the MTG tread, so you must be careful
 * to ignore them if this listener was successfully installed.
 */
class DirectMediaTrackListener : public MediaTrackListener {
  friend class SourceMediaTrack;
  friend class ForwardedInputTrack;

 public:
  /*
   * This will be called on any DirectMediaTrackListener added to a
   * SourceMediaTrack when AppendToTrack() is called for the listener's bound
   * track, using the thread of the AppendToTrack() caller. The MediaSegment
   * will be the RawSegment (unresampled) if available in AppendToTrack().
   * If the track is enabled at the source but has been disabled in one of the
   * tracks in between the source and where it was originally added, aMedia
   * will be a disabled version of the one passed to AppendToTrack() as well.
   * Note that NotifyQueuedTrackChanges() calls will also still occur.
   */
  virtual void NotifyRealtimeTrackData(MediaTrackGraph* aGraph,
                                       TrackTime aTrackOffset,
                                       const MediaSegment& aMedia) {}

  /**
   * When a direct listener is processed for installation by the
   * MediaTrackGraph it will be notified with whether the installation was
   * successful or not. The results of this installation are the following:
   * TRACK_NOT_SUPPORTED
   *    While looking for the data source of this track, we found a MediaTrack
   *    that is not a SourceMediaTrack or a ForwardedInputTrack.
   * ALREADY_EXISTS
   *    This DirectMediaTrackListener already exists in the
   *    SourceMediaTrack.
   * SUCCESS
   *    Installation was successful and this listener will start receiving
   *    NotifyRealtimeData on the next AppendData().
   */
  enum class InstallationResult {
    TRACK_NOT_SUPPORTED,
    ALREADY_EXISTS,
    SUCCESS
  };
  virtual void NotifyDirectListenerInstalled(InstallationResult aResult) {}
  virtual void NotifyDirectListenerUninstalled() {}

 protected:
  virtual ~DirectMediaTrackListener() = default;

  void MirrorAndDisableSegment(AudioSegment& aFrom, AudioSegment& aTo);
  void MirrorAndDisableSegment(VideoSegment& aFrom, VideoSegment& aTo,
                               DisabledTrackMode aMode);
  void NotifyRealtimeTrackDataAndApplyTrackDisabling(MediaTrackGraph* aGraph,
                                                     TrackTime aTrackOffset,
                                                     MediaSegment& aMedia);

  void IncreaseDisabled(DisabledTrackMode aMode);
  void DecreaseDisabled(DisabledTrackMode aMode);

  // Matches the number of disabled tracks to which this listener is attached.
  // The number of tracks are those between the track where the listener was
  // added and the SourceMediaTrack that is the source of the data reaching
  // this listener.
  Atomic<int32_t> mDisabledFreezeCount;
  Atomic<int32_t> mDisabledBlackCount;
};

}  // namespace mozilla

#endif  // MOZILLA_MEDIATRACKLISTENER_h_