content/media/MediaDecoder.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/content/media/MediaDecoder.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1219 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* vim:set ts=2 sw=2 sts=2 et cindent: */
     1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +/*
    1.10 +Each video element based on MediaDecoder has a state machine to manage
    1.11 +its play state and keep the current frame up to date. All state machines
    1.12 +share time in a single shared thread. Each decoder also has one thread
    1.13 +dedicated to decoding audio and video data. This thread is shutdown when
    1.14 +playback is paused. Each decoder also has a thread to push decoded audio
    1.15 +to the hardware. This thread is not created until playback starts, but
    1.16 +currently is not destroyed when paused, only when playback ends.
    1.17 +
    1.18 +The decoder owns the resources for downloading the media file, and the
    1.19 +high level state. It holds an owning reference to the state machine that
    1.20 +owns all the resources related to decoding data, and manages the low level
    1.21 +decoding operations and A/V sync.
    1.22 +
    1.23 +Each state machine runs on the shared state machine thread. Every time some
    1.24 +action is required for a state machine, it is scheduled to run on the shared
    1.25 +the state machine thread. The state machine runs one "cycle" on the state
    1.26 +machine thread, and then returns. If necessary, it will schedule itself to
    1.27 +run again in future. While running this cycle, it must not block the
    1.28 +thread, as other state machines' events may need to run. State shared
    1.29 +between a state machine's threads is synchronised via the monitor owned
    1.30 +by its MediaDecoder object.
    1.31 +
    1.32 +The Main thread controls the decode state machine by setting the value
    1.33 +of a mPlayState variable and notifying on the monitor based on the
    1.34 +high level player actions required (Seek, Pause, Play, etc).
    1.35 +
    1.36 +The player states are the states requested by the client through the
    1.37 +DOM API.  They represent the desired state of the player, while the
    1.38 +decoder's state represents the actual state of the decoder.
    1.39 +
    1.40 +The high level state of the player is maintained via a PlayState value.
    1.41 +It can have the following states:
    1.42 +
    1.43 +START
    1.44 +  The decoder has been initialized but has no resource loaded.
    1.45 +PAUSED
    1.46 +  A request via the API has been received to pause playback.
    1.47 +LOADING
    1.48 +  A request via the API has been received to load a resource.
    1.49 +PLAYING
    1.50 +  A request via the API has been received to start playback.
    1.51 +SEEKING
    1.52 +  A request via the API has been received to start seeking.
    1.53 +COMPLETED
    1.54 +  Playback has completed.
    1.55 +SHUTDOWN
    1.56 +  The decoder is about to be destroyed.
    1.57 +
    1.58 +State transition occurs when the Media Element calls the Play, Seek,
    1.59 +etc methods on the MediaDecoder object. When the transition
    1.60 +occurs MediaDecoder then calls the methods on the decoder state
    1.61 +machine object to cause it to behave as required by the play state.
    1.62 +State transitions will likely schedule the state machine to run to
    1.63 +affect the change.
    1.64 +
    1.65 +An implementation of the MediaDecoderStateMachine class is the event
    1.66 +that gets dispatched to the state machine thread. Each time the event is run,
    1.67 +the state machine must cycle the state machine once, and then return.
    1.68 +
    1.69 +The state machine has the following states:
    1.70 +
    1.71 +DECODING_METADATA
    1.72 +  The media headers are being loaded, and things like framerate, etc are
    1.73 +  being determined, and the first frame of audio/video data is being decoded.
    1.74 +DECODING
    1.75 +  The decode has started. If the PlayState is PLAYING, the decode thread
    1.76 +  should be alive and decoding video and audio frame, the audio thread
    1.77 +  should be playing audio, and the state machine should run periodically
    1.78 +  to update the video frames being displayed.
    1.79 +SEEKING
    1.80 +  A seek operation is in progress. The decode thread should be seeking.
    1.81 +BUFFERING
    1.82 +  Decoding is paused while data is buffered for smooth playback. If playback
    1.83 +  is paused (PlayState transitions to PAUSED) we'll destory the decode thread.
    1.84 +COMPLETED
    1.85 +  The resource has completed decoding, but possibly not finished playback.
    1.86 +  The decode thread will be destroyed. Once playback finished, the audio
    1.87 +  thread will also be destroyed.
    1.88 +SHUTDOWN
    1.89 +  The decoder object and its state machine are about to be destroyed.
    1.90 +  Once the last state machine has been destroyed, the shared state machine
    1.91 +  thread will also be destroyed. It will be recreated later if needed.
    1.92 +
    1.93 +The following result in state transitions.
    1.94 +
    1.95 +Shutdown()
    1.96 +  Clean up any resources the MediaDecoderStateMachine owns.
    1.97 +Play()
    1.98 +  Start decoding and playback of media data.
    1.99 +Buffer
   1.100 +  This is not user initiated. It occurs when the
   1.101 +  available data in the stream drops below a certain point.
   1.102 +Complete
   1.103 +  This is not user initiated. It occurs when the
   1.104 +  stream is completely decoded.
   1.105 +Seek(double)
   1.106 +  Seek to the time position given in the resource.
   1.107 +
   1.108 +A state transition diagram:
   1.109 +
   1.110 +DECODING_METADATA
   1.111 +  |      |
   1.112 +  v      | Shutdown()
   1.113 +  |      |
   1.114 +  v      -->-------------------->--------------------------|
   1.115 +  |---------------->----->------------------------|        v
   1.116 +DECODING             |          |  |              |        |
   1.117 +  ^                  v Seek(t)  |  |              |        |
   1.118 +  |         Play()   |          v  |              |        |
   1.119 +  ^-----------<----SEEKING      |  v Complete     v        v
   1.120 +  |                  |          |  |              |        |
   1.121 +  |                  |          |  COMPLETED    SHUTDOWN-<-|
   1.122 +  ^                  ^          |  |Shutdown()    |
   1.123 +  |                  |          |  >-------->-----^
   1.124 +  |          Play()  |Seek(t)   |Buffer()         |
   1.125 +  -----------<--------<-------BUFFERING           |
   1.126 +                                |                 ^
   1.127 +                                v Shutdown()      |
   1.128 +                                |                 |
   1.129 +                                ------------>-----|
   1.130 +
   1.131 +The following represents the states that the MediaDecoder object
   1.132 +can be in, and the valid states the MediaDecoderStateMachine can be in at that
   1.133 +time:
   1.134 +
   1.135 +player LOADING   decoder DECODING_METADATA
   1.136 +player PLAYING   decoder DECODING, BUFFERING, SEEKING, COMPLETED
   1.137 +player PAUSED    decoder DECODING, BUFFERING, SEEKING, COMPLETED
   1.138 +player SEEKING   decoder SEEKING
   1.139 +player COMPLETED decoder SHUTDOWN
   1.140 +player SHUTDOWN  decoder SHUTDOWN
   1.141 +
   1.142 +The general sequence of events is:
   1.143 +
   1.144 +1) The video element calls Load on MediaDecoder. This creates the
   1.145 +   state machine and starts the channel for downloading the
   1.146 +   file. It instantiates and schedules the MediaDecoderStateMachine. The
   1.147 +   high level LOADING state is entered, which results in the decode
   1.148 +   thread being created and starting to decode metadata. These are
   1.149 +   the headers that give the video size, framerate, etc. Load() returns
   1.150 +   immediately to the calling video element.
   1.151 +
   1.152 +2) When the metadata has been loaded by the decode thread, the state machine
   1.153 +   will call a method on the video element object to inform it that this
   1.154 +   step is done, so it can do the things required by the video specification
   1.155 +   at this stage. The decode thread then continues to decode the first frame
   1.156 +   of data.
   1.157 +
   1.158 +3) When the first frame of data has been successfully decoded the state
   1.159 +   machine calls a method on the video element object to inform it that
   1.160 +   this step has been done, once again so it can do the required things
   1.161 +   by the video specification at this stage.
   1.162 +
   1.163 +   This results in the high level state changing to PLAYING or PAUSED
   1.164 +   depending on any user action that may have occurred.
   1.165 +
   1.166 +   While the play state is PLAYING, the decode thread will decode
   1.167 +   data, and the audio thread will push audio data to the hardware to
   1.168 +   be played. The state machine will run periodically on the shared
   1.169 +   state machine thread to ensure video frames are played at the
   1.170 +   correct time; i.e. the state machine manages A/V sync.
   1.171 +
   1.172 +The Shutdown method on MediaDecoder closes the download channel, and
   1.173 +signals to the state machine that it should shutdown. The state machine
   1.174 +shuts down asynchronously, and will release the owning reference to the
   1.175 +state machine once its threads are shutdown.
   1.176 +
   1.177 +The owning object of a MediaDecoder object *MUST* call Shutdown when
   1.178 +destroying the MediaDecoder object.
   1.179 +
   1.180 +*/
   1.181 +#if !defined(MediaDecoder_h_)
   1.182 +#define MediaDecoder_h_
   1.183 +
   1.184 +#include "nsISupports.h"
   1.185 +#include "nsCOMPtr.h"
   1.186 +#include "nsIObserver.h"
   1.187 +#include "nsAutoPtr.h"
   1.188 +#include "MediaResource.h"
   1.189 +#include "mozilla/dom/AudioChannelBinding.h"
   1.190 +#include "mozilla/gfx/Rect.h"
   1.191 +#include "mozilla/ReentrantMonitor.h"
   1.192 +#include "mozilla/TimeStamp.h"
   1.193 +#include "MediaStreamGraph.h"
   1.194 +#include "AbstractMediaDecoder.h"
   1.195 +#include "necko-config.h"
   1.196 +
   1.197 +class nsIStreamListener;
   1.198 +class nsIPrincipal;
   1.199 +class nsITimer;
   1.200 +
   1.201 +namespace mozilla {
   1.202 +namespace dom {
   1.203 +class TimeRanges;
   1.204 +}
   1.205 +}
   1.206 +
   1.207 +namespace mozilla {
   1.208 +namespace layers {
   1.209 +class Image;
   1.210 +} //namespace layers
   1.211 +
   1.212 +class VideoFrameContainer;
   1.213 +class MediaDecoderStateMachine;
   1.214 +class MediaDecoderOwner;
   1.215 +
   1.216 +// GetCurrentTime is defined in winbase.h as zero argument macro forwarding to
   1.217 +// GetTickCount() and conflicts with MediaDecoder::GetCurrentTime implementation.
   1.218 +#ifdef GetCurrentTime
   1.219 +#undef GetCurrentTime
   1.220 +#endif
   1.221 +
   1.222 +// Stores the seek target; the time to seek to, and whether an Accurate,
   1.223 +// or "Fast" (nearest keyframe) seek was requested.
   1.224 +struct SeekTarget {
   1.225 +  enum Type {
   1.226 +    Invalid,
   1.227 +    PrevSyncPoint,
   1.228 +    Accurate
   1.229 +  };
   1.230 +  SeekTarget()
   1.231 +    : mTime(-1.0)
   1.232 +    , mType(SeekTarget::Invalid)
   1.233 +  {
   1.234 +  }
   1.235 +  SeekTarget(int64_t aTimeUsecs, Type aType)
   1.236 +    : mTime(aTimeUsecs)
   1.237 +    , mType(aType)
   1.238 +  {
   1.239 +  }
   1.240 +  bool IsValid() const {
   1.241 +    return mType != SeekTarget::Invalid;
   1.242 +  }
   1.243 +  void Reset() {
   1.244 +    mTime = -1;
   1.245 +    mType = SeekTarget::Invalid;
   1.246 +  }
   1.247 +  // Seek target time in microseconds.
   1.248 +  int64_t mTime;
   1.249 +  // Whether we should seek "Fast", or "Accurate".
   1.250 +  // "Fast" seeks to the seek point preceeding mTime, whereas
   1.251 +  // "Accurate" seeks as close as possible to mTime.
   1.252 +  Type mType;
   1.253 +};
   1.254 +
   1.255 +class MediaDecoder : public nsIObserver,
   1.256 +                     public AbstractMediaDecoder
   1.257 +{
   1.258 +public:
   1.259 +  class DecodedStreamGraphListener;
   1.260 +
   1.261 +  NS_DECL_THREADSAFE_ISUPPORTS
   1.262 +  NS_DECL_NSIOBSERVER
   1.263 +
   1.264 +  // Enumeration for the valid play states (see mPlayState)
   1.265 +  enum PlayState {
   1.266 +    PLAY_STATE_START,
   1.267 +    PLAY_STATE_LOADING,
   1.268 +    PLAY_STATE_PAUSED,
   1.269 +    PLAY_STATE_PLAYING,
   1.270 +    PLAY_STATE_SEEKING,
   1.271 +    PLAY_STATE_ENDED,
   1.272 +    PLAY_STATE_SHUTDOWN
   1.273 +  };
   1.274 +
   1.275 +  MediaDecoder();
   1.276 +  virtual ~MediaDecoder();
   1.277 +
   1.278 +  // Reset the decoder and notify the media element that
   1.279 +  // server connection is closed.
   1.280 +  virtual void ResetConnectionState();
   1.281 +  // Create a new decoder of the same type as this one.
   1.282 +  // Subclasses must implement this.
   1.283 +  virtual MediaDecoder* Clone() = 0;
   1.284 +  // Create a new state machine to run this decoder.
   1.285 +  // Subclasses must implement this.
   1.286 +  virtual MediaDecoderStateMachine* CreateStateMachine() = 0;
   1.287 +
   1.288 +  // Call on the main thread only.
   1.289 +  // Perform any initialization required for the decoder.
   1.290 +  // Return true on successful initialisation, false
   1.291 +  // on failure.
   1.292 +  virtual bool Init(MediaDecoderOwner* aOwner);
   1.293 +
   1.294 +  // Cleanup internal data structures. Must be called on the main
   1.295 +  // thread by the owning object before that object disposes of this object.
   1.296 +  virtual void Shutdown();
   1.297 +
   1.298 +  // Start downloading the media. Decode the downloaded data up to the
   1.299 +  // point of the first frame of data.
   1.300 +  // This is called at most once per decoder, after Init().
   1.301 +  virtual nsresult Load(nsIStreamListener** aListener,
   1.302 +                        MediaDecoder* aCloneDonor);
   1.303 +
   1.304 +  // Called in |Load| to open mResource.
   1.305 +  nsresult OpenResource(nsIStreamListener** aStreamListener);
   1.306 +
   1.307 +  // Called when the video file has completed downloading.
   1.308 +  virtual void ResourceLoaded();
   1.309 +
   1.310 +  // Called if the media file encounters a network error.
   1.311 +  virtual void NetworkError();
   1.312 +
   1.313 +  // Get the current MediaResource being used. Its URI will be returned
   1.314 +  // by currentSrc. Returns what was passed to Load(), if Load() has been called.
   1.315 +  // Note: The MediaResource is refcounted, but it outlives the MediaDecoder,
   1.316 +  // so it's OK to use the reference returned by this function without
   1.317 +  // refcounting, *unless* you need to store and use the reference after the
   1.318 +  // MediaDecoder has been destroyed. You might need to do this if you're
   1.319 +  // wrapping the MediaResource in some kind of byte stream interface to be
   1.320 +  // passed to a platform decoder.
   1.321 +  MediaResource* GetResource() const MOZ_FINAL MOZ_OVERRIDE
   1.322 +  {
   1.323 +    return mResource;
   1.324 +  }
   1.325 +  void SetResource(MediaResource* aResource)
   1.326 +  {
   1.327 +    NS_ASSERTION(NS_IsMainThread(), "Should only be called on main thread");
   1.328 +    mResource = aResource;
   1.329 +  }
   1.330 +
   1.331 +  // Return the principal of the current URI being played or downloaded.
   1.332 +  virtual already_AddRefed<nsIPrincipal> GetCurrentPrincipal();
   1.333 +
   1.334 +  // Return the time position in the video stream being
   1.335 +  // played measured in seconds.
   1.336 +  virtual double GetCurrentTime();
   1.337 +
   1.338 +  // Seek to the time position in (seconds) from the start of the video.
   1.339 +  // If aDoFastSeek is true, we'll seek to the sync point/keyframe preceeding
   1.340 +  // the seek target.
   1.341 +  virtual nsresult Seek(double aTime, SeekTarget::Type aSeekType);
   1.342 +
   1.343 +  // Enables decoders to supply an enclosing byte range for a seek offset.
   1.344 +  // E.g. used by ChannelMediaResource to download a whole cluster for
   1.345 +  // DASH-WebM.
   1.346 +  virtual nsresult GetByteRangeForSeek(int64_t const aOffset,
   1.347 +                                       MediaByteRange &aByteRange) {
   1.348 +    return NS_ERROR_NOT_AVAILABLE;
   1.349 +  }
   1.350 +
   1.351 +  // Initialize state machine and schedule it.
   1.352 +  nsresult InitializeStateMachine(MediaDecoder* aCloneDonor);
   1.353 +
   1.354 +  // Start playback of a video. 'Load' must have previously been
   1.355 +  // called.
   1.356 +  virtual nsresult Play();
   1.357 +
   1.358 +  // Set/Unset dormant state if necessary.
   1.359 +  // Dormant state is a state to free all scarce media resources
   1.360 +  //  (like hw video codec), did not decoding and stay dormant.
   1.361 +  // It is used to share scarece media resources in system.
   1.362 +  virtual void SetDormantIfNecessary(bool aDormant);
   1.363 +
   1.364 +  // Pause video playback.
   1.365 +  virtual void Pause();
   1.366 +  // Adjust the speed of the playback, optionally with pitch correction,
   1.367 +  virtual void SetVolume(double aVolume);
   1.368 +  // Sets whether audio is being captured. If it is, we won't play any
   1.369 +  // of our audio.
   1.370 +  virtual void SetAudioCaptured(bool aCaptured);
   1.371 +
   1.372 +  virtual void NotifyWaitingForResourcesStatusChanged() MOZ_OVERRIDE;
   1.373 +
   1.374 +  virtual void SetPlaybackRate(double aPlaybackRate);
   1.375 +  void SetPreservesPitch(bool aPreservesPitch);
   1.376 +
   1.377 +  // Directs the decoder to not preroll extra samples until the media is
   1.378 +  // played. This reduces the memory overhead of media elements that may
   1.379 +  // not be played. Note that seeking also doesn't cause us start prerolling.
   1.380 +  void SetMinimizePrerollUntilPlaybackStarts();
   1.381 +
   1.382 +  // All MediaStream-related data is protected by mReentrantMonitor.
   1.383 +  // We have at most one DecodedStreamData per MediaDecoder. Its stream
   1.384 +  // is used as the input for each ProcessedMediaStream created by calls to
   1.385 +  // captureStream(UntilEnded). Seeking creates a new source stream, as does
   1.386 +  // replaying after the input as ended. In the latter case, the new source is
   1.387 +  // not connected to streams created by captureStreamUntilEnded.
   1.388 +
   1.389 +  struct DecodedStreamData {
   1.390 +    typedef gfx::IntSize IntSize;
   1.391 +
   1.392 +    DecodedStreamData(MediaDecoder* aDecoder,
   1.393 +                      int64_t aInitialTime, SourceMediaStream* aStream);
   1.394 +    ~DecodedStreamData();
   1.395 +
   1.396 +    StreamTime GetLastOutputTime() { return mListener->GetLastOutputTime(); }
   1.397 +    bool IsFinished() { return mListener->IsFinishedOnMainThread(); }
   1.398 +
   1.399 +    // The following group of fields are protected by the decoder's monitor
   1.400 +    // and can be read or written on any thread.
   1.401 +    int64_t mLastAudioPacketTime; // microseconds
   1.402 +    int64_t mLastAudioPacketEndTime; // microseconds
   1.403 +    // Count of audio frames written to the stream
   1.404 +    int64_t mAudioFramesWritten;
   1.405 +    // Saved value of aInitialTime. Timestamp of the first audio and/or
   1.406 +    // video packet written.
   1.407 +    int64_t mInitialTime; // microseconds
   1.408 +    // mNextVideoTime is the end timestamp for the last packet sent to the stream.
   1.409 +    // Therefore video packets starting at or after this time need to be copied
   1.410 +    // to the output stream.
   1.411 +    int64_t mNextVideoTime; // microseconds
   1.412 +    MediaDecoder* mDecoder;
   1.413 +    // The last video image sent to the stream. Useful if we need to replicate
   1.414 +    // the image.
   1.415 +    nsRefPtr<layers::Image> mLastVideoImage;
   1.416 +    IntSize mLastVideoImageDisplaySize;
   1.417 +    // This is set to true when the stream is initialized (audio and
   1.418 +    // video tracks added).
   1.419 +    bool mStreamInitialized;
   1.420 +    bool mHaveSentFinish;
   1.421 +    bool mHaveSentFinishAudio;
   1.422 +    bool mHaveSentFinishVideo;
   1.423 +
   1.424 +    // The decoder is responsible for calling Destroy() on this stream.
   1.425 +    // Can be read from any thread.
   1.426 +    const nsRefPtr<SourceMediaStream> mStream;
   1.427 +    // Can be read from any thread.
   1.428 +    nsRefPtr<DecodedStreamGraphListener> mListener;
   1.429 +    // True when we've explicitly blocked this stream because we're
   1.430 +    // not in PLAY_STATE_PLAYING. Used on the main thread only.
   1.431 +    bool mHaveBlockedForPlayState;
   1.432 +    // We also have an explicit blocker on the stream when
   1.433 +    // mDecoderStateMachine is non-null and MediaDecoderStateMachine is false.
   1.434 +    bool mHaveBlockedForStateMachineNotPlaying;
   1.435 +  };
   1.436 +
   1.437 +  class DecodedStreamGraphListener : public MediaStreamListener {
   1.438 +  public:
   1.439 +    DecodedStreamGraphListener(MediaStream* aStream, DecodedStreamData* aData);
   1.440 +    virtual void NotifyOutput(MediaStreamGraph* aGraph, GraphTime aCurrentTime) MOZ_OVERRIDE;
   1.441 +    virtual void NotifyFinished(MediaStreamGraph* aGraph) MOZ_OVERRIDE;
   1.442 +
   1.443 +    void DoNotifyFinished();
   1.444 +
   1.445 +    StreamTime GetLastOutputTime()
   1.446 +    {
   1.447 +      MutexAutoLock lock(mMutex);
   1.448 +      return mLastOutputTime;
   1.449 +    }
   1.450 +    void Forget()
   1.451 +    {
   1.452 +      NS_ASSERTION(NS_IsMainThread(), "Main thread only");
   1.453 +      mData = nullptr;
   1.454 +
   1.455 +      MutexAutoLock lock(mMutex);
   1.456 +      mStream = nullptr;
   1.457 +    }
   1.458 +    bool SetFinishedOnMainThread(bool aFinished)
   1.459 +    {
   1.460 +      MutexAutoLock lock(mMutex);
   1.461 +      bool result = !mStreamFinishedOnMainThread;
   1.462 +      mStreamFinishedOnMainThread = aFinished;
   1.463 +      return result;
   1.464 +    }
   1.465 +    bool IsFinishedOnMainThread()
   1.466 +    {
   1.467 +      MutexAutoLock lock(mMutex);
   1.468 +      return mStreamFinishedOnMainThread;
   1.469 +    }
   1.470 +  private:
   1.471 +    // Main thread only
   1.472 +    DecodedStreamData* mData;
   1.473 +
   1.474 +    Mutex mMutex;
   1.475 +    // Protected by mMutex
   1.476 +    nsRefPtr<MediaStream> mStream;
   1.477 +    // Protected by mMutex
   1.478 +    StreamTime mLastOutputTime;
   1.479 +    // Protected by mMutex
   1.480 +    bool mStreamFinishedOnMainThread;
   1.481 +  };
   1.482 +
   1.483 +  struct OutputStreamData {
   1.484 +    void Init(ProcessedMediaStream* aStream, bool aFinishWhenEnded)
   1.485 +    {
   1.486 +      mStream = aStream;
   1.487 +      mFinishWhenEnded = aFinishWhenEnded;
   1.488 +    }
   1.489 +    nsRefPtr<ProcessedMediaStream> mStream;
   1.490 +    // mPort connects mDecodedStream->mStream to our mStream.
   1.491 +    nsRefPtr<MediaInputPort> mPort;
   1.492 +    bool mFinishWhenEnded;
   1.493 +  };
   1.494 +  /**
   1.495 +   * Connects mDecodedStream->mStream to aStream->mStream.
   1.496 +   */
   1.497 +  void ConnectDecodedStreamToOutputStream(OutputStreamData* aStream);
   1.498 +  /**
   1.499 +   * Disconnects mDecodedStream->mStream from all outputs and clears
   1.500 +   * mDecodedStream.
   1.501 +   */
   1.502 +  void DestroyDecodedStream();
   1.503 +  /**
   1.504 +   * Recreates mDecodedStream. Call this to create mDecodedStream at first,
   1.505 +   * and when seeking, to ensure a new stream is set up with fresh buffers.
   1.506 +   * aStartTimeUSecs is relative to the state machine's mStartTime.
   1.507 +   * Decoder monitor must be held.
   1.508 +   */
   1.509 +  void RecreateDecodedStream(int64_t aStartTimeUSecs);
   1.510 +  /**
   1.511 +   * Call this when mDecoderStateMachine or mDecoderStateMachine->IsPlaying() changes.
   1.512 +   * Decoder monitor must be held.
   1.513 +   */
   1.514 +  void UpdateStreamBlockingForStateMachinePlaying();
   1.515 +  nsTArray<OutputStreamData>& OutputStreams()
   1.516 +  {
   1.517 +    GetReentrantMonitor().AssertCurrentThreadIn();
   1.518 +    return mOutputStreams;
   1.519 +  }
   1.520 +  DecodedStreamData* GetDecodedStream()
   1.521 +  {
   1.522 +    GetReentrantMonitor().AssertCurrentThreadIn();
   1.523 +    return mDecodedStream;
   1.524 +  }
   1.525 +
   1.526 +  // Add an output stream. All decoder output will be sent to the stream.
   1.527 +  // The stream is initially blocked. The decoder is responsible for unblocking
   1.528 +  // it while it is playing back.
   1.529 +  virtual void AddOutputStream(ProcessedMediaStream* aStream, bool aFinishWhenEnded);
   1.530 +
   1.531 +  // Return the duration of the video in seconds.
   1.532 +  virtual double GetDuration();
   1.533 +
   1.534 +  // Return the duration of the video in seconds.
   1.535 +  int64_t GetMediaDuration() MOZ_FINAL MOZ_OVERRIDE;
   1.536 +
   1.537 +  // A media stream is assumed to be infinite if the metadata doesn't
   1.538 +  // contain the duration, and range requests are not supported, and
   1.539 +  // no headers give a hint of a possible duration (Content-Length,
   1.540 +  // Content-Duration, and variants), and we cannot seek in the media
   1.541 +  // stream to determine the duration.
   1.542 +  //
   1.543 +  // When the media stream ends, we can know the duration, thus the stream is
   1.544 +  // no longer considered to be infinite.
   1.545 +  virtual void SetInfinite(bool aInfinite);
   1.546 +
   1.547 +  // Return true if the stream is infinite (see SetInfinite).
   1.548 +  virtual bool IsInfinite();
   1.549 +
   1.550 +  // Called by MediaResource when the "cache suspended" status changes.
   1.551 +  // If MediaResource::IsSuspendedByCache returns true, then the decoder
   1.552 +  // should stop buffering or otherwise waiting for download progress and
   1.553 +  // start consuming data, if possible, because the cache is full.
   1.554 +  virtual void NotifySuspendedStatusChanged();
   1.555 +
   1.556 +  // Called by MediaResource when some data has been received.
   1.557 +  // Call on the main thread only.
   1.558 +  virtual void NotifyBytesDownloaded();
   1.559 +
   1.560 +  // Called by nsChannelToPipeListener or MediaResource when the
   1.561 +  // download has ended. Called on the main thread only. aStatus is
   1.562 +  // the result from OnStopRequest.
   1.563 +  virtual void NotifyDownloadEnded(nsresult aStatus);
   1.564 +
   1.565 +  // Called as data arrives on the stream and is read into the cache.  Called
   1.566 +  // on the main thread only.
   1.567 +  virtual void NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset);
   1.568 +
   1.569 +  // Called by MediaResource when the principal of the resource has
   1.570 +  // changed. Called on main thread only.
   1.571 +  virtual void NotifyPrincipalChanged();
   1.572 +
   1.573 +  // Called by the MediaResource to keep track of the number of bytes read
   1.574 +  // from the resource. Called on the main by an event runner dispatched
   1.575 +  // by the MediaResource read functions.
   1.576 +  void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset) MOZ_FINAL MOZ_OVERRIDE;
   1.577 +
   1.578 +  int64_t GetEndMediaTime() const MOZ_FINAL MOZ_OVERRIDE;
   1.579 +
   1.580 +  // Return true if we are currently seeking in the media resource.
   1.581 +  // Call on the main thread only.
   1.582 +  virtual bool IsSeeking() const;
   1.583 +
   1.584 +  // Return true if the decoder has reached the end of playback.
   1.585 +  // Call on the main thread only.
   1.586 +  virtual bool IsEnded() const;
   1.587 +
   1.588 +  // Set the duration of the media resource in units of seconds.
   1.589 +  // This is called via a channel listener if it can pick up the duration
   1.590 +  // from a content header. Must be called from the main thread only.
   1.591 +  virtual void SetDuration(double aDuration);
   1.592 +
   1.593 +  // Sets the initial duration of the media. Called while the media metadata
   1.594 +  // is being read and the decode is being setup.
   1.595 +  void SetMediaDuration(int64_t aDuration) MOZ_OVERRIDE;
   1.596 +  // Updates the media duration. This is called while the media is being
   1.597 +  // played, calls before the media has reached loaded metadata are ignored.
   1.598 +  // The duration is assumed to be an estimate, and so a degree of
   1.599 +  // instability is expected; if the incoming duration is not significantly
   1.600 +  // different from the existing duration, the change request is ignored.
   1.601 +  // If the incoming duration is significantly different, the duration is
   1.602 +  // changed, this causes a durationchanged event to fire to the media
   1.603 +  // element.
   1.604 +  void UpdateEstimatedMediaDuration(int64_t aDuration) MOZ_OVERRIDE;
   1.605 +
   1.606 +  // Set a flag indicating whether seeking is supported
   1.607 +  virtual void SetMediaSeekable(bool aMediaSeekable) MOZ_OVERRIDE;
   1.608 +  virtual void SetTransportSeekable(bool aTransportSeekable) MOZ_FINAL MOZ_OVERRIDE;
   1.609 +  // Returns true if this media supports seeking. False for example for WebM
   1.610 +  // files without an index and chained ogg files.
   1.611 +  virtual bool IsMediaSeekable() MOZ_FINAL MOZ_OVERRIDE;
   1.612 +  // Returns true if seeking is supported on a transport level (e.g. the server
   1.613 +  // supports range requests, we are playing a file, etc.).
   1.614 +  virtual bool IsTransportSeekable();
   1.615 +
   1.616 +  // Return the time ranges that can be seeked into.
   1.617 +  virtual nsresult GetSeekable(dom::TimeRanges* aSeekable);
   1.618 +
   1.619 +  // Set the end time of the media resource. When playback reaches
   1.620 +  // this point the media pauses. aTime is in seconds.
   1.621 +  virtual void SetFragmentEndTime(double aTime);
   1.622 +
   1.623 +  // Set the end time of the media. aTime is in microseconds.
   1.624 +  void SetMediaEndTime(int64_t aTime) MOZ_FINAL MOZ_OVERRIDE;
   1.625 +
   1.626 +  // Invalidate the frame.
   1.627 +  void Invalidate();
   1.628 +  void InvalidateWithFlags(uint32_t aFlags);
   1.629 +
   1.630 +  // Suspend any media downloads that are in progress. Called by the
   1.631 +  // media element when it is sent to the bfcache, or when we need
   1.632 +  // to throttle the download. Call on the main thread only. This can
   1.633 +  // be called multiple times, there's an internal "suspend count".
   1.634 +  virtual void Suspend();
   1.635 +
   1.636 +  // Resume any media downloads that have been suspended. Called by the
   1.637 +  // media element when it is restored from the bfcache, or when we need
   1.638 +  // to stop throttling the download. Call on the main thread only.
   1.639 +  // The download will only actually resume once as many Resume calls
   1.640 +  // have been made as Suspend calls. When aForceBuffering is true,
   1.641 +  // we force the decoder to go into buffering state before resuming
   1.642 +  // playback.
   1.643 +  virtual void Resume(bool aForceBuffering);
   1.644 +
   1.645 +  // Moves any existing channel loads into the background, so that they don't
   1.646 +  // block the load event. This is called when we stop delaying the load
   1.647 +  // event. Any new loads initiated (for example to seek) will also be in the
   1.648 +  // background. Implementations of this must call MoveLoadsToBackground() on
   1.649 +  // their MediaResource.
   1.650 +  virtual void MoveLoadsToBackground();
   1.651 +
   1.652 +  // Returns a weak reference to the media decoder owner.
   1.653 +  MediaDecoderOwner* GetMediaOwner() const;
   1.654 +
   1.655 +  // Called by the state machine to notify the decoder that the duration
   1.656 +  // has changed.
   1.657 +  void DurationChanged();
   1.658 +
   1.659 +  bool OnStateMachineThread() const MOZ_OVERRIDE;
   1.660 +
   1.661 +  bool OnDecodeThread() const MOZ_OVERRIDE;
   1.662 +
   1.663 +  // Returns the monitor for other threads to synchronise access to
   1.664 +  // state.
   1.665 +  ReentrantMonitor& GetReentrantMonitor() MOZ_OVERRIDE;
   1.666 +
   1.667 +  // Returns true if the decoder is shut down
   1.668 +  bool IsShutdown() const MOZ_FINAL MOZ_OVERRIDE;
   1.669 +
   1.670 +  // Constructs the time ranges representing what segments of the media
   1.671 +  // are buffered and playable.
   1.672 +  virtual nsresult GetBuffered(dom::TimeRanges* aBuffered);
   1.673 +
   1.674 +  // Returns the size, in bytes, of the heap memory used by the currently
   1.675 +  // queued decoded video and audio data.
   1.676 +  size_t SizeOfVideoQueue();
   1.677 +  size_t SizeOfAudioQueue();
   1.678 +
   1.679 +  VideoFrameContainer* GetVideoFrameContainer() MOZ_FINAL MOZ_OVERRIDE
   1.680 +  {
   1.681 +    return mVideoFrameContainer;
   1.682 +  }
   1.683 +  layers::ImageContainer* GetImageContainer() MOZ_OVERRIDE;
   1.684 +
   1.685 +  // Return the current state. Can be called on any thread. If called from
   1.686 +  // a non-main thread, the decoder monitor must be held.
   1.687 +  PlayState GetState() {
   1.688 +    return mPlayState;
   1.689 +  }
   1.690 +
   1.691 +  // Fire progress events if needed according to the time and byte
   1.692 +  // constraints outlined in the specification. aTimer is true
   1.693 +  // if the method is called as a result of the progress timer rather
   1.694 +  // than the result of downloaded data.
   1.695 +  void Progress(bool aTimer);
   1.696 +
   1.697 +  // Fire timeupdate events if needed according to the time constraints
   1.698 +  // outlined in the specification.
   1.699 +  void FireTimeUpdate();
   1.700 +
   1.701 +  // Stop updating the bytes downloaded for progress notifications. Called
   1.702 +  // when seeking to prevent wild changes to the progress notification.
   1.703 +  // Must be called with the decoder monitor held.
   1.704 +  virtual void StopProgressUpdates();
   1.705 +
   1.706 +  // Allow updating the bytes downloaded for progress notifications. Must
   1.707 +  // be called with the decoder monitor held.
   1.708 +  virtual void StartProgressUpdates();
   1.709 +
   1.710 +  // Something has changed that could affect the computed playback rate,
   1.711 +  // so recompute it. The monitor must be held.
   1.712 +  virtual void UpdatePlaybackRate();
   1.713 +
   1.714 +  // Used to estimate rates of data passing through the decoder's channel.
   1.715 +  // Records activity stopping on the channel. The monitor must be held.
   1.716 +  virtual void NotifyPlaybackStarted() {
   1.717 +    GetReentrantMonitor().AssertCurrentThreadIn();
   1.718 +    mPlaybackStatistics.Start();
   1.719 +  }
   1.720 +
   1.721 +  // Used to estimate rates of data passing through the decoder's channel.
   1.722 +  // Records activity stopping on the channel. The monitor must be held.
   1.723 +  virtual void NotifyPlaybackStopped() {
   1.724 +    GetReentrantMonitor().AssertCurrentThreadIn();
   1.725 +    mPlaybackStatistics.Stop();
   1.726 +  }
   1.727 +
   1.728 +  // The actual playback rate computation. The monitor must be held.
   1.729 +  virtual double ComputePlaybackRate(bool* aReliable);
   1.730 +
   1.731 +  // Return true when the media is same-origin with the element. The monitor
   1.732 +  // must be held.
   1.733 +  bool IsSameOriginMedia();
   1.734 +
   1.735 +  // Returns true if we can play the entire media through without stopping
   1.736 +  // to buffer, given the current download and playback rates.
   1.737 +  bool CanPlayThrough();
   1.738 +
   1.739 +  // Make the decoder state machine update the playback position. Called by
   1.740 +  // the reader on the decoder thread (Assertions for this checked by
   1.741 +  // mDecoderStateMachine). This must be called with the decode monitor
   1.742 +  // held.
   1.743 +  void UpdatePlaybackPosition(int64_t aTime) MOZ_FINAL MOZ_OVERRIDE;
   1.744 +
   1.745 +  void SetAudioChannel(dom::AudioChannel aChannel) { mAudioChannel = aChannel; }
   1.746 +  dom::AudioChannel GetAudioChannel() { return mAudioChannel; }
   1.747 +
   1.748 +  // Send a new set of metadata to the state machine, to be dispatched to the
   1.749 +  // main thread to be presented when the |currentTime| of the media is greater
   1.750 +  // or equal to aPublishTime.
   1.751 +  void QueueMetadata(int64_t aPublishTime,
   1.752 +                     int aChannels,
   1.753 +                     int aRate,
   1.754 +                     bool aHasAudio,
   1.755 +                     bool aHasVideo,
   1.756 +                     MetadataTags* aTags);
   1.757 +
   1.758 +  /******
   1.759 +   * The following methods must only be called on the main
   1.760 +   * thread.
   1.761 +   ******/
   1.762 +
   1.763 +  // Change to a new play state. This updates the mState variable and
   1.764 +  // notifies any thread blocking on this object's monitor of the
   1.765 +  // change. Call on the main thread only.
   1.766 +  virtual void ChangeState(PlayState aState);
   1.767 +
   1.768 +  // Called by |ChangeState|, to update the state machine.
   1.769 +  // Call on the main thread only and the lock must be obtained.
   1.770 +  virtual void ApplyStateToStateMachine(PlayState aState);
   1.771 +
   1.772 +  // May be called by the reader to notify this decoder that the metadata from
   1.773 +  // the media file has been read. Call on the decode thread only.
   1.774 +  void OnReadMetadataCompleted() MOZ_OVERRIDE { }
   1.775 +
   1.776 +  // Called when the metadata from the media file has been loaded by the
   1.777 +  // state machine. Call on the main thread only.
   1.778 +  virtual void MetadataLoaded(int aChannels,
   1.779 +                              int aRate,
   1.780 +                              bool aHasAudio,
   1.781 +                              bool aHasVideo,
   1.782 +                              MetadataTags* aTags);
   1.783 +
   1.784 +  // Called when the first frame has been loaded.
   1.785 +  // Call on the main thread only.
   1.786 +  void FirstFrameLoaded();
   1.787 +
   1.788 +  // Returns true if the resource has been loaded. Acquires the monitor.
   1.789 +  // Call from any thread.
   1.790 +  virtual bool IsDataCachedToEndOfResource();
   1.791 +
   1.792 +  // Called when the video has completed playing.
   1.793 +  // Call on the main thread only.
   1.794 +  void PlaybackEnded();
   1.795 +
   1.796 +  // Seeking has stopped. Inform the element on the main
   1.797 +  // thread.
   1.798 +  void SeekingStopped();
   1.799 +
   1.800 +  // Seeking has stopped at the end of the resource. Inform the element on the main
   1.801 +  // thread.
   1.802 +  void SeekingStoppedAtEnd();
   1.803 +
   1.804 +  // Seeking has started. Inform the element on the main
   1.805 +  // thread.
   1.806 +  void SeekingStarted();
   1.807 +
   1.808 +  // Called when the backend has changed the current playback
   1.809 +  // position. It dispatches a timeupdate event and invalidates the frame.
   1.810 +  // This must be called on the main thread only.
   1.811 +  void PlaybackPositionChanged();
   1.812 +
   1.813 +  // Calls mElement->UpdateReadyStateForData, telling it whether we have
   1.814 +  // data for the next frame and if we're buffering. Main thread only.
   1.815 +  virtual void UpdateReadyStateForData();
   1.816 +
   1.817 +  // Find the end of the cached data starting at the current decoder
   1.818 +  // position.
   1.819 +  int64_t GetDownloadPosition();
   1.820 +
   1.821 +  // Updates the approximate byte offset which playback has reached. This is
   1.822 +  // used to calculate the readyState transitions.
   1.823 +  void UpdatePlaybackOffset(int64_t aOffset);
   1.824 +
   1.825 +  // Provide access to the state machine object
   1.826 +  MediaDecoderStateMachine* GetStateMachine() const;
   1.827 +
   1.828 +  // Drop reference to state machine.  Only called during shutdown dance.
   1.829 +  virtual void ReleaseStateMachine();
   1.830 +
   1.831 +  // Notifies the element that decoding has failed.
   1.832 +  virtual void DecodeError();
   1.833 +
   1.834 +  // Indicate whether the media is same-origin with the element.
   1.835 +  void UpdateSameOriginStatus(bool aSameOrigin);
   1.836 +
   1.837 +  MediaDecoderOwner* GetOwner() MOZ_OVERRIDE;
   1.838 +
   1.839 +  // Returns true if we're logically playing, that is, if the Play() has
   1.840 +  // been called and Pause() has not or we have not yet reached the end
   1.841 +  // of media. This is irrespective of the seeking state; if the owner
   1.842 +  // calls Play() and then Seek(), we still count as logically playing.
   1.843 +  // The decoder monitor must be held.
   1.844 +  bool IsLogicallyPlaying();
   1.845 +
   1.846 +#ifdef MOZ_RAW
   1.847 +  static bool IsRawEnabled();
   1.848 +#endif
   1.849 +
   1.850 +  static bool IsOggEnabled();
   1.851 +  static bool IsOpusEnabled();
   1.852 +
   1.853 +#ifdef MOZ_WAVE
   1.854 +  static bool IsWaveEnabled();
   1.855 +#endif
   1.856 +
   1.857 +#ifdef MOZ_WEBM
   1.858 +  static bool IsWebMEnabled();
   1.859 +#endif
   1.860 +#ifdef NECKO_PROTOCOL_rtsp
   1.861 +  static bool IsRtspEnabled();
   1.862 +#endif
   1.863 +
   1.864 +#ifdef MOZ_GSTREAMER
   1.865 +  static bool IsGStreamerEnabled();
   1.866 +#endif
   1.867 +
   1.868 +#ifdef MOZ_OMX_DECODER
   1.869 +  static bool IsOmxEnabled();
   1.870 +#endif
   1.871 +
   1.872 +#ifdef MOZ_MEDIA_PLUGINS
   1.873 +  static bool IsMediaPluginsEnabled();
   1.874 +#endif
   1.875 +
   1.876 +#ifdef MOZ_WMF
   1.877 +  static bool IsWMFEnabled();
   1.878 +#endif
   1.879 +
   1.880 +#ifdef MOZ_APPLEMEDIA
   1.881 +  static bool IsAppleMP3Enabled();
   1.882 +#endif
   1.883 +
   1.884 +  // Schedules the state machine to run one cycle on the shared state
   1.885 +  // machine thread. Main thread only.
   1.886 +  nsresult ScheduleStateMachineThread();
   1.887 +
   1.888 +  struct Statistics {
   1.889 +    // Estimate of the current playback rate (bytes/second).
   1.890 +    double mPlaybackRate;
   1.891 +    // Estimate of the current download rate (bytes/second). This
   1.892 +    // ignores time that the channel was paused by Gecko.
   1.893 +    double mDownloadRate;
   1.894 +    // Total length of media stream in bytes; -1 if not known
   1.895 +    int64_t mTotalBytes;
   1.896 +    // Current position of the download, in bytes. This is the offset of
   1.897 +    // the first uncached byte after the decoder position.
   1.898 +    int64_t mDownloadPosition;
   1.899 +    // Current position of decoding, in bytes (how much of the stream
   1.900 +    // has been consumed)
   1.901 +    int64_t mDecoderPosition;
   1.902 +    // Current position of playback, in bytes
   1.903 +    int64_t mPlaybackPosition;
   1.904 +    // If false, then mDownloadRate cannot be considered a reliable
   1.905 +    // estimate (probably because the download has only been running
   1.906 +    // a short time).
   1.907 +    bool mDownloadRateReliable;
   1.908 +    // If false, then mPlaybackRate cannot be considered a reliable
   1.909 +    // estimate (probably because playback has only been running
   1.910 +    // a short time).
   1.911 +    bool mPlaybackRateReliable;
   1.912 +  };
   1.913 +
   1.914 +  // Return statistics. This is used for progress events and other things.
   1.915 +  // This can be called from any thread. It's only a snapshot of the
   1.916 +  // current state, since other threads might be changing the state
   1.917 +  // at any time.
   1.918 +  virtual Statistics GetStatistics();
   1.919 +
   1.920 +  // Frame decoding/painting related performance counters.
   1.921 +  // Threadsafe.
   1.922 +  class FrameStatistics {
   1.923 +  public:
   1.924 +
   1.925 +    FrameStatistics() :
   1.926 +        mReentrantMonitor("MediaDecoder::FrameStats"),
   1.927 +        mParsedFrames(0),
   1.928 +        mDecodedFrames(0),
   1.929 +        mPresentedFrames(0) {}
   1.930 +
   1.931 +    // Returns number of frames which have been parsed from the media.
   1.932 +    // Can be called on any thread.
   1.933 +    uint32_t GetParsedFrames() {
   1.934 +      ReentrantMonitorAutoEnter mon(mReentrantMonitor);
   1.935 +      return mParsedFrames;
   1.936 +    }
   1.937 +
   1.938 +    // Returns the number of parsed frames which have been decoded.
   1.939 +    // Can be called on any thread.
   1.940 +    uint32_t GetDecodedFrames() {
   1.941 +      ReentrantMonitorAutoEnter mon(mReentrantMonitor);
   1.942 +      return mDecodedFrames;
   1.943 +    }
   1.944 +
   1.945 +    // Returns the number of decoded frames which have been sent to the rendering
   1.946 +    // pipeline for painting ("presented").
   1.947 +    // Can be called on any thread.
   1.948 +    uint32_t GetPresentedFrames() {
   1.949 +      ReentrantMonitorAutoEnter mon(mReentrantMonitor);
   1.950 +      return mPresentedFrames;
   1.951 +    }
   1.952 +
   1.953 +    // Increments the parsed and decoded frame counters by the passed in counts.
   1.954 +    // Can be called on any thread.
   1.955 +    void NotifyDecodedFrames(uint32_t aParsed, uint32_t aDecoded) {
   1.956 +      if (aParsed == 0 && aDecoded == 0)
   1.957 +        return;
   1.958 +      ReentrantMonitorAutoEnter mon(mReentrantMonitor);
   1.959 +      mParsedFrames += aParsed;
   1.960 +      mDecodedFrames += aDecoded;
   1.961 +    }
   1.962 +
   1.963 +    // Increments the presented frame counters.
   1.964 +    // Can be called on any thread.
   1.965 +    void NotifyPresentedFrame() {
   1.966 +      ReentrantMonitorAutoEnter mon(mReentrantMonitor);
   1.967 +      ++mPresentedFrames;
   1.968 +    }
   1.969 +
   1.970 +  private:
   1.971 +
   1.972 +    // ReentrantMonitor to protect access of playback statistics.
   1.973 +    ReentrantMonitor mReentrantMonitor;
   1.974 +
   1.975 +    // Number of frames parsed and demuxed from media.
   1.976 +    // Access protected by mReentrantMonitor.
   1.977 +    uint32_t mParsedFrames;
   1.978 +
   1.979 +    // Number of parsed frames which were actually decoded.
   1.980 +    // Access protected by mReentrantMonitor.
   1.981 +    uint32_t mDecodedFrames;
   1.982 +
   1.983 +    // Number of decoded frames which were actually sent down the rendering
   1.984 +    // pipeline to be painted ("presented"). Access protected by mReentrantMonitor.
   1.985 +    uint32_t mPresentedFrames;
   1.986 +  };
   1.987 +
   1.988 +  // Return the frame decode/paint related statistics.
   1.989 +  FrameStatistics& GetFrameStatistics() { return mFrameStats; }
   1.990 +
   1.991 +  // Increments the parsed and decoded frame counters by the passed in counts.
   1.992 +  // Can be called on any thread.
   1.993 +  virtual void NotifyDecodedFrames(uint32_t aParsed, uint32_t aDecoded) MOZ_OVERRIDE
   1.994 +  {
   1.995 +    GetFrameStatistics().NotifyDecodedFrames(aParsed, aDecoded);
   1.996 +  }
   1.997 +
   1.998 +protected:
   1.999 +  /******
  1.1000 +   * The following members should be accessed with the decoder lock held.
  1.1001 +   ******/
  1.1002 +
  1.1003 +  // Current decoding position in the stream. This is where the decoder
  1.1004 +  // is up to consuming the stream. This is not adjusted during decoder
  1.1005 +  // seek operations, but it's updated at the end when we start playing
  1.1006 +  // back again.
  1.1007 +  int64_t mDecoderPosition;
  1.1008 +  // Current playback position in the stream. This is (approximately)
  1.1009 +  // where we're up to playing back the stream. This is not adjusted
  1.1010 +  // during decoder seek operations, but it's updated at the end when we
  1.1011 +  // start playing back again.
  1.1012 +  int64_t mPlaybackPosition;
  1.1013 +
  1.1014 +  // The current playback position of the media resource in units of
  1.1015 +  // seconds. This is updated approximately at the framerate of the
  1.1016 +  // video (if it is a video) or the callback period of the audio.
  1.1017 +  // It is read and written from the main thread only.
  1.1018 +  double mCurrentTime;
  1.1019 +
  1.1020 +  // Volume that playback should start at.  0.0 = muted. 1.0 = full
  1.1021 +  // volume.  Readable/Writeable from the main thread.
  1.1022 +  double mInitialVolume;
  1.1023 +
  1.1024 +  // PlaybackRate and pitch preservation status we should start at.
  1.1025 +  // Readable/Writeable from the main thread.
  1.1026 +  double mInitialPlaybackRate;
  1.1027 +  bool mInitialPreservesPitch;
  1.1028 +
  1.1029 +  // Duration of the media resource. Set to -1 if unknown.
  1.1030 +  // Set when the metadata is loaded. Accessed on the main thread
  1.1031 +  // only.
  1.1032 +  int64_t mDuration;
  1.1033 +
  1.1034 +  // True when playback should start with audio captured (not playing).
  1.1035 +  bool mInitialAudioCaptured;
  1.1036 +
  1.1037 +  // True if the resource is seekable at a transport level (server supports byte
  1.1038 +  // range requests, local file, etc.).
  1.1039 +  bool mTransportSeekable;
  1.1040 +
  1.1041 +  // True if the media is seekable (i.e. supports random access).
  1.1042 +  bool mMediaSeekable;
  1.1043 +
  1.1044 +  // True if the media is same-origin with the element. Data can only be
  1.1045 +  // passed to MediaStreams when this is true.
  1.1046 +  bool mSameOriginMedia;
  1.1047 +
  1.1048 +  /******
  1.1049 +   * The following member variables can be accessed from any thread.
  1.1050 +   ******/
  1.1051 +
  1.1052 +  // The state machine object for handling the decoding. It is safe to
  1.1053 +  // call methods of this object from other threads. Its internal data
  1.1054 +  // is synchronised on a monitor. The lifetime of this object is
  1.1055 +  // after mPlayState is LOADING and before mPlayState is SHUTDOWN. It
  1.1056 +  // is safe to access it during this period.
  1.1057 +  nsRefPtr<MediaDecoderStateMachine> mDecoderStateMachine;
  1.1058 +
  1.1059 +  // Media data resource.
  1.1060 +  nsRefPtr<MediaResource> mResource;
  1.1061 +
  1.1062 +  // |ReentrantMonitor| for detecting when the video play state changes. A call
  1.1063 +  // to |Wait| on this monitor will block the thread until the next state
  1.1064 +  // change.
  1.1065 +  // Using a wrapper class to restrict direct access to the |ReentrantMonitor|
  1.1066 +  // object. Subclasses may override |MediaDecoder|::|GetReentrantMonitor|
  1.1067 +  // e.g. |DASHRepDecoder|::|GetReentrantMonitor| returns the monitor in the
  1.1068 +  // main |DASHDecoder| object. In this case, directly accessing the
  1.1069 +  // member variable mReentrantMonitor in |DASHRepDecoder| is wrong.
  1.1070 +  // The wrapper |RestrictedAccessMonitor| restricts use to the getter
  1.1071 +  // function rather than the object itself.
  1.1072 +private:
  1.1073 +  class RestrictedAccessMonitor
  1.1074 +  {
  1.1075 +  public:
  1.1076 +    RestrictedAccessMonitor(const char* aName) :
  1.1077 +      mReentrantMonitor(aName)
  1.1078 +    {
  1.1079 +      MOZ_COUNT_CTOR(RestrictedAccessMonitor);
  1.1080 +    }
  1.1081 +    ~RestrictedAccessMonitor()
  1.1082 +    {
  1.1083 +      MOZ_COUNT_DTOR(RestrictedAccessMonitor);
  1.1084 +    }
  1.1085 +
  1.1086 +    // Returns a ref to the reentrant monitor
  1.1087 +    ReentrantMonitor& GetReentrantMonitor() {
  1.1088 +      return mReentrantMonitor;
  1.1089 +    }
  1.1090 +  private:
  1.1091 +    ReentrantMonitor mReentrantMonitor;
  1.1092 +  };
  1.1093 +
  1.1094 +  // The |RestrictedAccessMonitor| member object.
  1.1095 +  RestrictedAccessMonitor mReentrantMonitor;
  1.1096 +
  1.1097 +protected:
  1.1098 +  // Data about MediaStreams that are being fed by this decoder.
  1.1099 +  nsTArray<OutputStreamData> mOutputStreams;
  1.1100 +  // The SourceMediaStream we are using to feed the mOutputStreams. This stream
  1.1101 +  // is never exposed outside the decoder.
  1.1102 +  // Only written on the main thread while holding the monitor. Therefore it
  1.1103 +  // can be read on any thread while holding the monitor, or on the main thread
  1.1104 +  // without holding the monitor.
  1.1105 +  nsAutoPtr<DecodedStreamData> mDecodedStream;
  1.1106 +
  1.1107 +  // True if this decoder is in dormant state.
  1.1108 +  // Should be true only when PlayState is PLAY_STATE_LOADING.
  1.1109 +  bool mIsDormant;
  1.1110 +
  1.1111 +  // True if this decoder is exiting from dormant state.
  1.1112 +  // Should be true only when PlayState is PLAY_STATE_LOADING.
  1.1113 +  bool mIsExitingDormant;
  1.1114 +
  1.1115 +  // Set to one of the valid play states.
  1.1116 +  // This can only be changed on the main thread while holding the decoder
  1.1117 +  // monitor. Thus, it can be safely read while holding the decoder monitor
  1.1118 +  // OR on the main thread.
  1.1119 +  // Any change to the state on the main thread must call NotifyAll on the
  1.1120 +  // monitor so the decode thread can wake up.
  1.1121 +  PlayState mPlayState;
  1.1122 +
  1.1123 +  // The state to change to after a seek or load operation.
  1.1124 +  // This can only be changed on the main thread while holding the decoder
  1.1125 +  // monitor. Thus, it can be safely read while holding the decoder monitor
  1.1126 +  // OR on the main thread.
  1.1127 +  // Any change to the state must call NotifyAll on the monitor.
  1.1128 +  // This can only be PLAY_STATE_PAUSED or PLAY_STATE_PLAYING.
  1.1129 +  PlayState mNextState;
  1.1130 +
  1.1131 +  // Position to seek to when the seek notification is received by the
  1.1132 +  // decode thread.
  1.1133 +  // This can only be changed on the main thread while holding the decoder
  1.1134 +  // monitor. Thus, it can be safely read while holding the decoder monitor
  1.1135 +  // OR on the main thread.
  1.1136 +  // If the SeekTarget's IsValid() accessor returns false, then no seek has
  1.1137 +  // been requested. When a seek is started this is reset to invalid.
  1.1138 +  SeekTarget mRequestedSeekTarget;
  1.1139 +
  1.1140 +  // True when we have fully loaded the resource and reported that
  1.1141 +  // to the element (i.e. reached NETWORK_LOADED state).
  1.1142 +  // Accessed on the main thread only.
  1.1143 +  bool mCalledResourceLoaded;
  1.1144 +
  1.1145 +  // True when seeking or otherwise moving the play position around in
  1.1146 +  // such a manner that progress event data is inaccurate. This is set
  1.1147 +  // during seek and duration operations to prevent the progress indicator
  1.1148 +  // from jumping around. Read/Write from any thread. Must have decode monitor
  1.1149 +  // locked before accessing.
  1.1150 +  bool mIgnoreProgressData;
  1.1151 +
  1.1152 +  // True if the stream is infinite (e.g. a webradio).
  1.1153 +  bool mInfiniteStream;
  1.1154 +
  1.1155 +  // Start timer to update download progress information.
  1.1156 +  nsresult StartProgress();
  1.1157 +
  1.1158 +  // Stop progress information timer.
  1.1159 +  nsresult StopProgress();
  1.1160 +
  1.1161 +  // Ensures our media stream has been pinned.
  1.1162 +  void PinForSeek();
  1.1163 +
  1.1164 +  // Ensures our media stream has been unpinned.
  1.1165 +  void UnpinForSeek();
  1.1166 +
  1.1167 +  // Timer used for updating progress events
  1.1168 +  nsCOMPtr<nsITimer> mProgressTimer;
  1.1169 +
  1.1170 +  // This should only ever be accessed from the main thread.
  1.1171 +  // It is set in Init and cleared in Shutdown when the element goes away.
  1.1172 +  // The decoder does not add a reference the element.
  1.1173 +  MediaDecoderOwner* mOwner;
  1.1174 +
  1.1175 +  // Counters related to decode and presentation of frames.
  1.1176 +  FrameStatistics mFrameStats;
  1.1177 +
  1.1178 +  nsRefPtr<VideoFrameContainer> mVideoFrameContainer;
  1.1179 +
  1.1180 +  // Time that the last progress event was fired. Read/Write from the
  1.1181 +  // main thread only.
  1.1182 +  TimeStamp mProgressTime;
  1.1183 +
  1.1184 +  // Time that data was last read from the media resource. Used for
  1.1185 +  // computing if the download has stalled and to rate limit progress events
  1.1186 +  // when data is arriving slower than PROGRESS_MS. A value of null indicates
  1.1187 +  // that a stall event has already fired and not to fire another one until
  1.1188 +  // more data is received. Read/Write from the main thread only.
  1.1189 +  TimeStamp mDataTime;
  1.1190 +
  1.1191 +  // Data needed to estimate playback data rate. The timeline used for
  1.1192 +  // this estimate is "decode time" (where the "current time" is the
  1.1193 +  // time of the last decoded video frame).
  1.1194 +  MediaChannelStatistics mPlaybackStatistics;
  1.1195 +
  1.1196 +  // True when our media stream has been pinned. We pin the stream
  1.1197 +  // while seeking.
  1.1198 +  bool mPinnedForSeek;
  1.1199 +
  1.1200 +  // True if the decoder is being shutdown. At this point all events that
  1.1201 +  // are currently queued need to return immediately to prevent javascript
  1.1202 +  // being run that operates on the element and decoder during shutdown.
  1.1203 +  // Read/Write from the main thread only.
  1.1204 +  bool mShuttingDown;
  1.1205 +
  1.1206 +  // True if the playback is paused because the playback rate member is 0.0.
  1.1207 +  bool mPausedForPlaybackRateNull;
  1.1208 +
  1.1209 +  // Be assigned from media element during the initialization and pass to
  1.1210 +  // AudioStream Class.
  1.1211 +  dom::AudioChannel mAudioChannel;
  1.1212 +
  1.1213 +  // True if the decoder has been directed to minimize its preroll before
  1.1214 +  // playback starts. After the first time playback starts, we don't attempt
  1.1215 +  // to minimize preroll, as we assume the user is likely to keep playing,
  1.1216 +  // or play the media again.
  1.1217 +  bool mMinimizePreroll;
  1.1218 +};
  1.1219 +
  1.1220 +} // namespace mozilla
  1.1221 +
  1.1222 +#endif

mercurial