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