LCOV - code coverage report
Current view: directory - content/media - nsBuiltinDecoderStateMachine.h (source / functions) Found Hit Coverage
Test: app.info Lines: 37 0 0.0 %
Date: 2012-06-02 Functions: 13 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* vim:set ts=2 sw=2 sts=2 et cindent: */
       3                 : /* ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: ML 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is Mozilla code.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is the Mozilla Foundation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 2010
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *  Chris Double <chris.double@double.co.nz>
      24                 :  *  Chris Pearce <chris@pearce.org.nz>
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      28                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 : /*
      40                 : Each video element for a media file has two threads:
      41                 : 
      42                 :   1) The Audio thread writes the decoded audio data to the audio
      43                 :      hardware. This is done in a separate thread to ensure that the
      44                 :      audio hardware gets a constant stream of data without
      45                 :      interruption due to decoding or display. At some point
      46                 :      libsydneyaudio will be refactored to have a callback interface
      47                 :      where it asks for data and an extra thread will no longer be
      48                 :      needed.
      49                 : 
      50                 :   2) The decode thread. This thread reads from the media stream and
      51                 :      decodes the Theora and Vorbis data. It places the decoded data into
      52                 :      queues for the other threads to pull from.
      53                 : 
      54                 : All file reads, seeks, and all decoding must occur on the decode thread.
      55                 : Synchronisation of state between the thread is done via a monitor owned
      56                 : by nsBuiltinDecoder.
      57                 : 
      58                 : The lifetime of the decode and audio threads is controlled by the state
      59                 : machine when it runs on the shared state machine thread. When playback
      60                 : needs to occur they are created and events dispatched to them to run
      61                 : them. These events exit when decoding/audio playback is completed or
      62                 : no longer required.
      63                 : 
      64                 : A/V synchronisation is handled by the state machine. It examines the audio
      65                 : playback time and compares this to the next frame in the queue of video
      66                 : frames. If it is time to play the video frame it is then displayed, otherwise
      67                 : it schedules the state machine to run again at the time of the next frame.
      68                 : 
      69                 : Frame skipping is done in the following ways:
      70                 : 
      71                 :   1) The state machine will skip all frames in the video queue whose
      72                 :      display time is less than the current audio time. This ensures
      73                 :      the correct frame for the current time is always displayed.
      74                 : 
      75                 :   2) The decode thread will stop decoding interframes and read to the
      76                 :      next keyframe if it determines that decoding the remaining
      77                 :      interframes will cause playback issues. It detects this by:
      78                 :        a) If the amount of audio data in the audio queue drops
      79                 :           below a threshold whereby audio may start to skip.
      80                 :        b) If the video queue drops below a threshold where it
      81                 :           will be decoding video data that won't be displayed due
      82                 :           to the decode thread dropping the frame immediately.
      83                 : 
      84                 : When hardware accelerated graphics is not available, YCbCr conversion
      85                 : is done on the decode thread when video frames are decoded.
      86                 : 
      87                 : The decode thread pushes decoded audio and videos frames into two
      88                 : separate queues - one for audio and one for video. These are kept
      89                 : separate to make it easy to constantly feed audio data to the audio
      90                 : hardware while allowing frame skipping of video data. These queues are
      91                 : threadsafe, and neither the decode, audio, or state machine should
      92                 : be able to monopolize them, and cause starvation of the other threads.
      93                 : 
      94                 : Both queues are bounded by a maximum size. When this size is reached
      95                 : the decode thread will no longer decode video or audio depending on the
      96                 : queue that has reached the threshold. If both queues are full, the decode
      97                 : thread will wait on the decoder monitor.
      98                 : 
      99                 : When the decode queues are full (they've reaced their maximum size) and
     100                 : the decoder is not in PLAYING play state, the state machine may opt
     101                 : to shut down the decode thread in order to conserve resources.
     102                 : 
     103                 : During playback the audio thread will be idle (via a Wait() on the
     104                 : monitor) if the audio queue is empty. Otherwise it constantly pops
     105                 : audio data off the queue and plays it with a blocking write to the audio
     106                 : hardware (via nsAudioStream and libsydneyaudio).
     107                 : 
     108                 : */
     109                 : #if !defined(nsBuiltinDecoderStateMachine_h__)
     110                 : #define nsBuiltinDecoderStateMachine_h__
     111                 : 
     112                 : #include "prmem.h"
     113                 : #include "nsThreadUtils.h"
     114                 : #include "nsBuiltinDecoder.h"
     115                 : #include "nsBuiltinDecoderReader.h"
     116                 : #include "nsAudioAvailableEventManager.h"
     117                 : #include "nsHTMLMediaElement.h"
     118                 : #include "mozilla/ReentrantMonitor.h"
     119                 : #include "nsITimer.h"
     120                 : 
     121                 : /*
     122                 :   The state machine class. This manages the decoding and seeking in the
     123                 :   nsBuiltinDecoderReader on the decode thread, and A/V sync on the shared
     124                 :   state machine thread, and controls the audio "push" thread.
     125                 : 
     126                 :   All internal state is synchronised via the decoder monitor. State changes
     127                 :   are either propagated by NotifyAll on the monitor (typically when state
     128                 :   changes need to be propagated to non-state machine threads) or by scheduling
     129                 :   the state machine to run another cycle on the shared state machine thread.
     130                 : 
     131                 :   See nsBuiltinDecoder.h for more details.
     132                 : */
     133                 : class nsBuiltinDecoderStateMachine : public nsDecoderStateMachine
     134                 : {
     135                 : public:
     136                 :   typedef mozilla::ReentrantMonitor ReentrantMonitor;
     137                 :   typedef mozilla::TimeStamp TimeStamp;
     138                 :   typedef mozilla::TimeDuration TimeDuration;
     139                 :   typedef mozilla::VideoFrameContainer VideoFrameContainer;
     140                 : 
     141                 :   nsBuiltinDecoderStateMachine(nsBuiltinDecoder* aDecoder, nsBuiltinDecoderReader* aReader, bool aRealTime = false);
     142                 :   ~nsBuiltinDecoderStateMachine();
     143                 : 
     144                 :   // nsDecoderStateMachine interface
     145                 :   virtual nsresult Init(nsDecoderStateMachine* aCloneDonor);
     146               0 :   State GetState()
     147                 :   { 
     148               0 :     mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
     149               0 :     return mState; 
     150                 :   }
     151                 :   virtual void SetVolume(double aVolume);
     152                 :   virtual void Shutdown();
     153                 :   virtual PRInt64 GetDuration();
     154                 :   virtual void SetDuration(PRInt64 aDuration);
     155                 :   void SetEndTime(PRInt64 aEndTime);
     156               0 :   virtual bool OnDecodeThread() const {
     157               0 :     return IsCurrentThread(mDecodeThread);
     158                 :   }
     159                 : 
     160                 :   virtual nsHTMLMediaElement::NextFrameStatus GetNextFrameStatus();
     161                 :   virtual void Play();
     162                 :   virtual void Seek(double aTime);
     163                 :   virtual double GetCurrentTime() const;
     164                 :   virtual void ClearPositionChangeFlag();
     165                 :   virtual void SetSeekable(bool aSeekable);
     166                 :   virtual void UpdatePlaybackPosition(PRInt64 aTime);
     167                 :   virtual void StartBuffering();
     168                 : 
     169                 :   // State machine thread run function. Defers to RunStateMachine().
     170                 :   NS_IMETHOD Run();
     171                 : 
     172                 :   // This is called on the state machine thread and audio thread.
     173                 :   // The decoder monitor must be obtained before calling this.
     174               0 :   bool HasAudio() const {
     175               0 :     mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
     176               0 :     return mInfo.mHasAudio;
     177                 :   }
     178                 : 
     179                 :   // This is called on the state machine thread and audio thread.
     180                 :   // The decoder monitor must be obtained before calling this.
     181               0 :   bool HasVideo() const {
     182               0 :     mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
     183               0 :     return mInfo.mHasVideo;
     184                 :   }
     185                 : 
     186                 :   // Should be called by main thread.
     187                 :   bool HaveNextFrameData() const;
     188                 : 
     189                 :   // Must be called with the decode monitor held.
     190               0 :   bool IsBuffering() const {
     191               0 :     mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
     192                 : 
     193               0 :     return mState == nsBuiltinDecoderStateMachine::DECODER_STATE_BUFFERING;
     194                 :   }
     195                 : 
     196                 :   // Must be called with the decode monitor held.
     197               0 :   bool IsSeeking() const {
     198               0 :     mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
     199                 : 
     200               0 :     return mState == nsBuiltinDecoderStateMachine::DECODER_STATE_SEEKING;
     201                 :   }
     202                 : 
     203                 :   // Functions used by assertions to ensure we're calling things
     204                 :   // on the appropriate threads.
     205               0 :   bool OnAudioThread() const {
     206               0 :     return IsCurrentThread(mAudioThread);
     207                 :   }
     208                 : 
     209                 :   bool OnStateMachineThread() const;
     210                 :  
     211                 :   nsresult GetBuffered(nsTimeRanges* aBuffered);
     212                 : 
     213               0 :   PRInt64 VideoQueueMemoryInUse() {
     214               0 :     if (mReader) {
     215               0 :       return mReader->VideoQueueMemoryInUse();
     216                 :     }
     217               0 :     return 0;
     218                 :   }
     219                 : 
     220               0 :   PRInt64 AudioQueueMemoryInUse() {
     221               0 :     if (mReader) {
     222               0 :       return mReader->AudioQueueMemoryInUse();
     223                 :     }
     224               0 :     return 0;
     225                 :   }
     226                 : 
     227                 :   void NotifyDataArrived(const char* aBuffer, PRUint32 aLength, PRInt64 aOffset);
     228                 : 
     229                 :   PRInt64 GetEndMediaTime() const {
     230                 :     mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
     231                 :     return mEndTime;
     232                 :   }
     233                 : 
     234               0 :   bool IsSeekable() {
     235               0 :     mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
     236               0 :     return mSeekable;
     237                 :   }
     238                 : 
     239                 :   // Sets the current frame buffer length for the MozAudioAvailable event.
     240                 :   // Accessed on the main and state machine threads.
     241                 :   virtual void SetFrameBufferLength(PRUint32 aLength);
     242                 : 
     243                 :   // Returns the shared state machine thread.
     244                 :   static nsIThread* GetStateMachineThread();
     245                 : 
     246                 :   // Schedules the shared state machine thread to run the state machine.
     247                 :   // If the state machine thread is the currently running the state machine,
     248                 :   // we wait until that has completely finished before running the state
     249                 :   // machine again.
     250                 :   nsresult ScheduleStateMachine();
     251                 : 
     252                 :   // Schedules the shared state machine thread to run the state machine
     253                 :   // in aUsecs microseconds from now, if it's not already scheduled to run
     254                 :   // earlier, in which case the request is discarded.
     255                 :   nsresult ScheduleStateMachine(PRInt64 aUsecs);
     256                 : 
     257                 :   // Creates and starts a new decode thread. Don't call this directly,
     258                 :   // request a new decode thread by calling
     259                 :   // StateMachineTracker::RequestCreateDecodeThread().
     260                 :   // The decoder monitor must not be held. Called on the state machine thread.
     261                 :   nsresult StartDecodeThread();
     262                 : 
     263                 :   // Timer function to implement ScheduleStateMachine(aUsecs).
     264                 :   void TimeoutExpired();
     265                 : 
     266                 :   // Set the media fragment end time. aEndTime is in microseconds.
     267                 :   void SetFragmentEndTime(PRInt64 aEndTime);
     268                 : 
     269                 :   // Drop reference to decoder.  Only called during shutdown dance.
     270               0 :   void ReleaseDecoder() { mDecoder = nsnull; }
     271                 : 
     272                 :    // Called when a "MozAudioAvailable" event listener is added to the media
     273                 :    // element. Called on the main thread.
     274                 :    void NotifyAudioAvailableListener();
     275                 : 
     276                 : protected:
     277                 : 
     278                 :   // Returns true if we've got less than aAudioUsecs microseconds of decoded
     279                 :   // and playable data. The decoder monitor must be held.
     280                 :   bool HasLowDecodedData(PRInt64 aAudioUsecs) const;
     281                 : 
     282                 :   // Returns true if we're running low on data which is not yet decoded.
     283                 :   // The decoder monitor must be held.
     284                 :   bool HasLowUndecodedData() const;
     285                 : 
     286                 :   // Returns the number of microseconds of undecoded data available for
     287                 :   // decoding. The decoder monitor must be held.
     288                 :   PRInt64 GetUndecodedData() const;
     289                 : 
     290                 :   // Returns the number of unplayed usecs of audio we've got decoded and/or
     291                 :   // pushed to the hardware waiting to play. This is how much audio we can
     292                 :   // play without having to run the audio decoder. The decoder monitor
     293                 :   // must be held.
     294                 :   PRInt64 AudioDecodedUsecs() const;
     295                 : 
     296                 :   // Returns true when there's decoded audio waiting to play.
     297                 :   // The decoder monitor must be held.
     298                 :   bool HasFutureAudio() const;
     299                 : 
     300                 :   // Returns true if we recently exited "quick buffering" mode.
     301                 :   bool JustExitedQuickBuffering();
     302                 : 
     303                 :   // Waits on the decoder ReentrantMonitor for aUsecs microseconds. If the decoder
     304                 :   // monitor is awoken by a Notify() call, we'll continue waiting, unless
     305                 :   // we've moved into shutdown state. This enables us to ensure that we
     306                 :   // wait for a specified time, and that the myriad of Notify()s we do on
     307                 :   // the decoder monitor don't cause the audio thread to be starved. aUsecs
     308                 :   // values of less than 1 millisecond are rounded up to 1 millisecond
     309                 :   // (see bug 651023). The decoder monitor must be held. Called only on the
     310                 :   // audio thread.
     311                 :   void Wait(PRInt64 aUsecs);
     312                 : 
     313                 :   // Dispatches an asynchronous event to update the media element's ready state.
     314                 :   void UpdateReadyState();
     315                 : 
     316                 :   // Resets playback timing data. Called when we seek, on the decode thread.
     317                 :   void ResetPlayback();
     318                 : 
     319                 :   // Returns the audio clock, if we have audio, or -1 if we don't.
     320                 :   // Called on the state machine thread.
     321                 :   PRInt64 GetAudioClock();
     322                 : 
     323                 :   // Returns the presentation time of the first audio or video frame in the
     324                 :   // media.  If the media has video, it returns the first video frame. The
     325                 :   // decoder monitor must be held with exactly one lock count. Called on the
     326                 :   // state machine thread.
     327                 :   VideoData* FindStartTime();
     328                 : 
     329                 :   // Update only the state machine's current playback position (and duration,
     330                 :   // if unknown).  Does not update the playback position on the decoder or
     331                 :   // media element -- use UpdatePlaybackPosition for that.  Called on the state
     332                 :   // machine thread, caller must hold the decoder lock.
     333                 :   void UpdatePlaybackPositionInternal(PRInt64 aTime);
     334                 : 
     335                 :   // Pushes the image down the rendering pipeline. Called on the shared state
     336                 :   // machine thread. The decoder monitor must *not* be held when calling this.
     337                 :   void RenderVideoFrame(VideoData* aData, TimeStamp aTarget);
     338                 :  
     339                 :   // If we have video, display a video frame if it's time for display has
     340                 :   // arrived, otherwise sleep until it's time for the next frame. Update the
     341                 :   // current frame time as appropriate, and trigger ready state update.  The
     342                 :   // decoder monitor must be held with exactly one lock count. Called on the
     343                 :   // state machine thread.
     344                 :   void AdvanceFrame();
     345                 : 
     346                 :   // Write aFrames of audio frames of silence to the audio hardware. Returns
     347                 :   // the number of frames actually written. The write size is capped at
     348                 :   // SILENCE_BYTES_CHUNK (32kB), so must be called in a loop to write the
     349                 :   // desired number of frames. This ensures that the playback position
     350                 :   // advances smoothly, and guarantees that we don't try to allocate an
     351                 :   // impossibly large chunk of memory in order to play back silence. Called
     352                 :   // on the audio thread.
     353                 :   PRUint32 PlaySilence(PRUint32 aFrames,
     354                 :                        PRUint32 aChannels,
     355                 :                        PRUint64 aFrameOffset);
     356                 : 
     357                 :   // Pops an audio chunk from the front of the audio queue, and pushes its
     358                 :   // audio data to the audio hardware. MozAudioAvailable data is also queued
     359                 :   // here. Called on the audio thread.
     360                 :   PRUint32 PlayFromAudioQueue(PRUint64 aFrameOffset, PRUint32 aChannels);
     361                 : 
     362                 :   // Stops the decode thread, and if we have a pending request for a new
     363                 :   // decode thread it is canceled. The decoder monitor must be held with exactly
     364                 :   // one lock count. Called on the state machine thread.
     365                 :   void StopDecodeThread();
     366                 : 
     367                 :   // Stops the audio thread. The decoder monitor must be held with exactly
     368                 :   // one lock count. Called on the state machine thread.
     369                 :   void StopAudioThread();
     370                 : 
     371                 :   // Ensures the decode thread is running if it already exists, or requests
     372                 :   // a new decode thread be started if there currently is no decode thread.
     373                 :   // The decoder monitor must be held with exactly one lock count. Called on
     374                 :   // the state machine thread.
     375                 :   nsresult ScheduleDecodeThread();
     376                 : 
     377                 :   // Starts the audio thread. The decoder monitor must be held with exactly
     378                 :   // one lock count. Called on the state machine thread.
     379                 :   nsresult StartAudioThread();
     380                 : 
     381                 :   // The main loop for the audio thread. Sent to the thread as
     382                 :   // an nsRunnableMethod. This continually does blocking writes to
     383                 :   // to audio stream to play audio data.
     384                 :   void AudioLoop();
     385                 : 
     386                 :   // Sets internal state which causes playback of media to pause.
     387                 :   // The decoder monitor must be held. Called on the main, state machine,
     388                 :   // and decode threads.
     389                 :   void StopPlayback();
     390                 : 
     391                 :   // Sets internal state which causes playback of media to begin or resume.
     392                 :   // Must be called with the decode monitor held. Called on the state machine
     393                 :   // and decode threads.
     394                 :   void StartPlayback();
     395                 : 
     396                 :   // Moves the decoder into decoding state. Called on the state machine
     397                 :   // thread. The decoder monitor must be held.
     398                 :   void StartDecoding();
     399                 : 
     400                 :   // Returns true if we're currently playing. The decoder monitor must
     401                 :   // be held.
     402                 :   bool IsPlaying();
     403                 : 
     404                 :   // Returns the "media time". This is the absolute time which the media
     405                 :   // playback has reached. i.e. this returns values in the range
     406                 :   // [mStartTime, mEndTime], and mStartTime will not be 0 if the media does
     407                 :   // not start at 0. Note this is different to the value returned
     408                 :   // by GetCurrentTime(), which is in the range [0,duration].
     409               0 :   PRInt64 GetMediaTime() const {
     410               0 :     mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
     411               0 :     return mStartTime + mCurrentFrameTime;
     412                 :   }
     413                 : 
     414                 :   // Returns an upper bound on the number of microseconds of audio that is
     415                 :   // decoded and playable. This is the sum of the number of usecs of audio which
     416                 :   // is decoded and in the reader's audio queue, and the usecs of unplayed audio
     417                 :   // which has been pushed to the audio hardware for playback. Note that after
     418                 :   // calling this, the audio hardware may play some of the audio pushed to
     419                 :   // hardware, so this can only be used as a upper bound. The decoder monitor
     420                 :   // must be held when calling this. Called on the decode thread.
     421                 :   PRInt64 GetDecodedAudioDuration();
     422                 : 
     423                 :   // Load metadata. Called on the decode thread. The decoder monitor
     424                 :   // must be held with exactly one lock count.
     425                 :   nsresult DecodeMetadata();
     426                 : 
     427                 :   // Seeks to mSeekTarget. Called on the decode thread. The decoder monitor
     428                 :   // must be held with exactly one lock count.
     429                 :   void DecodeSeek();
     430                 : 
     431                 :   // Decode loop, decodes data until EOF or shutdown.
     432                 :   // Called on the decode thread.
     433                 :   void DecodeLoop();
     434                 : 
     435                 :   // Decode thread run function. Determines which of the Decode*() functions
     436                 :   // to call.
     437                 :   void DecodeThreadRun();
     438                 : 
     439                 :   // State machine thread run function. Defers to RunStateMachine().
     440                 :   nsresult CallRunStateMachine();
     441                 : 
     442                 :   // Performs one "cycle" of the state machine. Polls the state, and may send
     443                 :   // a video frame to be displayed, and generally manages the decode. Called
     444                 :   // periodically via timer to ensure the video stays in sync.
     445                 :   nsresult RunStateMachine();
     446                 : 
     447               0 :   bool IsStateMachineScheduled() const {
     448               0 :     mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
     449               0 :     return !mTimeout.IsNull() || mRunAgain;
     450                 :   }
     451                 : 
     452                 :   // Returns true if we're not playing and the decode thread has filled its
     453                 :   // decode buffers and is waiting. We can shut the decode thread down in this
     454                 :   // case as it may not be needed again.
     455                 :   bool IsPausedAndDecoderWaiting();
     456                 : 
     457                 :   // The decoder object that created this state machine. The state machine
     458                 :   // holds a strong reference to the decoder to ensure that the decoder stays
     459                 :   // alive once media element has started the decoder shutdown process, and has
     460                 :   // dropped its reference to the decoder. This enables the state machine to
     461                 :   // keep using the decoder's monitor until the state machine has finished
     462                 :   // shutting down, without fear of the monitor being destroyed. After
     463                 :   // shutting down, the state machine will then release this reference,
     464                 :   // causing the decoder to be destroyed. This is accessed on the decode,
     465                 :   // state machine, audio and main threads.
     466                 :   nsRefPtr<nsBuiltinDecoder> mDecoder;
     467                 : 
     468                 :   // The decoder monitor must be obtained before modifying this state.
     469                 :   // NotifyAll on the monitor must be called when the state is changed so
     470                 :   // that interested threads can wake up and alter behaviour if appropriate
     471                 :   // Accessed on state machine, audio, main, and AV thread.
     472                 :   State mState;
     473                 : 
     474                 :   // The size of the decoded YCbCr frame.
     475                 :   // Accessed on state machine thread.
     476                 :   PRUint32 mCbCrSize;
     477                 : 
     478                 :   // Accessed on state machine thread.
     479                 :   nsAutoArrayPtr<unsigned char> mCbCrBuffer;
     480                 : 
     481                 :   // Thread for pushing audio onto the audio hardware.
     482                 :   // The "audio push thread".
     483                 :   nsCOMPtr<nsIThread> mAudioThread;
     484                 : 
     485                 :   // Thread for decoding video in background. The "decode thread".
     486                 :   nsCOMPtr<nsIThread> mDecodeThread;
     487                 : 
     488                 :   // Timer to call the state machine Run() method. Used by
     489                 :   // ScheduleStateMachine(). Access protected by decoder monitor.
     490                 :   nsCOMPtr<nsITimer> mTimer;
     491                 : 
     492                 :   // Timestamp at which the next state machine Run() method will be called.
     493                 :   // If this is non-null, a call to Run() is scheduled, either by a timer,
     494                 :   // or via an event. Access protected by decoder monitor.
     495                 :   TimeStamp mTimeout;
     496                 : 
     497                 :   // The time that playback started from the system clock. This is used for
     498                 :   // timing the presentation of video frames when there's no audio.
     499                 :   // Accessed only via the state machine thread.
     500                 :   TimeStamp mPlayStartTime;
     501                 : 
     502                 :   // The amount of time we've spent playing already the media. The current
     503                 :   // playback position is therefore |Now() - mPlayStartTime +
     504                 :   // mPlayDuration|, which must be adjusted by mStartTime if used with media
     505                 :   // timestamps.  Accessed only via the state machine thread.
     506                 :   PRInt64 mPlayDuration;
     507                 : 
     508                 :   // Time that buffering started. Used for buffering timeout and only
     509                 :   // accessed on the state machine thread. This is null while we're not
     510                 :   // buffering.
     511                 :   TimeStamp mBufferingStart;
     512                 : 
     513                 :   // Start time of the media, in microseconds. This is the presentation
     514                 :   // time of the first frame decoded from the media, and is used to calculate
     515                 :   // duration and as a bounds for seeking. Accessed on state machine, decode,
     516                 :   // and main threads. Access controlled by decoder monitor.
     517                 :   PRInt64 mStartTime;
     518                 : 
     519                 :   // Time of the last frame in the media, in microseconds. This is the
     520                 :   // end time of the last frame in the media. Accessed on state
     521                 :   // machine, decode, and main threads. Access controlled by decoder monitor.
     522                 :   PRInt64 mEndTime;
     523                 : 
     524                 :   // Position to seek to in microseconds when the seek state transition occurs.
     525                 :   // The decoder monitor lock must be obtained before reading or writing
     526                 :   // this value. Accessed on main and decode thread.
     527                 :   PRInt64 mSeekTime;
     528                 : 
     529                 :   // Media Fragment end time in microseconds. Access controlled by decoder monitor.
     530                 :   PRInt64 mFragmentEndTime;
     531                 : 
     532                 :   // The audio stream resource. Used on the state machine, and audio threads.
     533                 :   // This is created and destroyed on the audio thread, while holding the
     534                 :   // decoder monitor, so if this is used off the audio thread, you must
     535                 :   // first acquire the decoder monitor and check that it is non-null.
     536                 :   nsRefPtr<nsAudioStream> mAudioStream;
     537                 : 
     538                 :   // The reader, don't call its methods with the decoder monitor held.
     539                 :   // This is created in the play state machine's constructor, and destroyed
     540                 :   // in the play state machine's destructor.
     541                 :   nsAutoPtr<nsBuiltinDecoderReader> mReader;
     542                 : 
     543                 :   // The time of the current frame in microseconds. This is referenced from
     544                 :   // 0 which is the initial playback position. Set by the state machine
     545                 :   // thread, and read-only from the main thread to get the current
     546                 :   // time value. Synchronised via decoder monitor.
     547                 :   PRInt64 mCurrentFrameTime;
     548                 : 
     549                 :   // The presentation time of the first audio frame that was played in
     550                 :   // microseconds. We can add this to the audio stream position to determine
     551                 :   // the current audio time. Accessed on audio and state machine thread.
     552                 :   // Synchronized by decoder monitor.
     553                 :   PRInt64 mAudioStartTime;
     554                 : 
     555                 :   // The end time of the last audio frame that's been pushed onto the audio
     556                 :   // hardware in microseconds. This will approximately be the end time of the
     557                 :   // audio stream, unless another frame is pushed to the hardware.
     558                 :   PRInt64 mAudioEndTime;
     559                 : 
     560                 :   // The presentation end time of the last video frame which has been displayed
     561                 :   // in microseconds. Accessed from the state machine thread.
     562                 :   PRInt64 mVideoFrameEndTime;
     563                 :   
     564                 :   // Volume of playback. 0.0 = muted. 1.0 = full volume. Read/Written
     565                 :   // from the state machine and main threads. Synchronised via decoder
     566                 :   // monitor.
     567                 :   double mVolume;
     568                 : 
     569                 :   // Time at which we started decoding. Synchronised via decoder monitor.
     570                 :   TimeStamp mDecodeStartTime;
     571                 : 
     572                 :   // True if the media resource can be seeked. Accessed from the state
     573                 :   // machine and main threads. Synchronised via decoder monitor.
     574                 :   bool mSeekable;
     575                 : 
     576                 :   // True if an event to notify about a change in the playback
     577                 :   // position has been queued, but not yet run. It is set to false when
     578                 :   // the event is run. This allows coalescing of these events as they can be
     579                 :   // produced many times per second. Synchronised via decoder monitor.
     580                 :   // Accessed on main and state machine threads.
     581                 :   bool mPositionChangeQueued;
     582                 : 
     583                 :   // True if the audio playback thread has finished. It is finished
     584                 :   // when either all the audio frames in the Vorbis bitstream have completed
     585                 :   // playing, or we've moved into shutdown state, and the threads are to be
     586                 :   // destroyed. Written by the audio playback thread and read and written by
     587                 :   // the state machine thread. Synchronised via decoder monitor.
     588                 :   bool mAudioCompleted;
     589                 : 
     590                 :   // True if mDuration has a value obtained from an HTTP header, or from
     591                 :   // the media index/metadata. Accessed on the state machine thread.
     592                 :   bool mGotDurationFromMetaData;
     593                 :     
     594                 :   // False while decode thread should be running. Accessed state machine
     595                 :   // and decode threads. Syncrhonised by decoder monitor.
     596                 :   bool mStopDecodeThread;
     597                 : 
     598                 :   // True when the decode thread run function has finished, but the thread
     599                 :   // has not necessarily been shut down yet. This can happen if we switch
     600                 :   // from COMPLETED state to SEEKING before the state machine has a chance
     601                 :   // to run in the COMPLETED state and shutdown the decode thread.
     602                 :   // Synchronised by the decoder monitor.
     603                 :   bool mDecodeThreadIdle;
     604                 : 
     605                 :   // False while audio thread should be running. Accessed state machine
     606                 :   // and audio threads. Syncrhonised by decoder monitor.
     607                 :   bool mStopAudioThread;
     608                 : 
     609                 :   // If this is true while we're in buffering mode, we can exit early,
     610                 :   // as it's likely we may be able to playback. This happens when we enter
     611                 :   // buffering mode soon after the decode starts, because the decode-ahead
     612                 :   // ran fast enough to exhaust all data while the download is starting up.
     613                 :   // Synchronised via decoder monitor.
     614                 :   bool mQuickBuffering;
     615                 : 
     616                 :   // True if the shared state machine thread is currently running this
     617                 :   // state machine.
     618                 :   bool mIsRunning;
     619                 : 
     620                 :   // True if we should run the state machine again once the current
     621                 :   // state machine run has finished.
     622                 :   bool mRunAgain;
     623                 : 
     624                 :   // True if we've dispatched an event to run the state machine. It's
     625                 :   // imperative that we don't dispatch multiple events to run the state
     626                 :   // machine at the same time, as our code assume all events are synchronous.
     627                 :   // If we dispatch multiple events, the second event can run while the
     628                 :   // first is shutting down a thread, causing inconsistent state.
     629                 :   bool mDispatchedRunEvent;
     630                 : 
     631                 :   // True if the decode thread has gone filled its buffers and is now
     632                 :   // waiting to be awakened before it continues decoding. Synchronized
     633                 :   // by the decoder monitor.
     634                 :   bool mDecodeThreadWaiting;
     635                 : 
     636                 :   // True is we are decoding a realtime stream, like a camera stream
     637                 :   bool mRealTime;
     638                 : 
     639                 :   // True if we've requested a new decode thread, but it has not yet been
     640                 :   // created. Synchronized by the decoder monitor.
     641                 :   bool mRequestedNewDecodeThread;
     642                 :   
     643                 :   PRUint32 mBufferingWait;
     644                 :   PRInt64  mLowDataThresholdUsecs;
     645                 : 
     646                 : private:
     647                 :   // Manager for queuing and dispatching MozAudioAvailable events.  The
     648                 :   // event manager is accessed from the state machine and audio threads,
     649                 :   // and takes care of synchronizing access to its internal queue.
     650                 :   nsAudioAvailableEventManager mEventManager;
     651                 : 
     652                 :   // Stores presentation info required for playback. The decoder monitor
     653                 :   // must be held when accessing this.
     654                 :   nsVideoInfo mInfo;
     655                 : };
     656                 : 
     657                 : #endif

Generated by: LCOV version 1.7