LCOV - app.info - content/media/nsBuiltinDecoderStateMachine.h

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