LCOV - code coverage report
Current view: directory - content/media - nsMediaDecoder.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 98 0 0.0 %
Date: 2012-06-02 Functions: 37 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: MPL 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 Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 2007
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *  Chris Double <chris.double@double.co.nz>
      24                 :  *
      25                 :  * Alternatively, the contents of this file may be used under the terms of
      26                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      27                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      29                 :  * of those above. If you wish to allow use of your version of this file only
      30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      31                 :  * use your version of this file under the terms of the MPL, indicate your
      32                 :  * decision by deleting the provisions above and replace them with the notice
      33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      34                 :  * the provisions above, a recipient may use your version of this file under
      35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      36                 :  *
      37                 :  * ***** END LICENSE BLOCK ***** */
      38                 : 
      39                 : #include "nsMediaDecoder.h"
      40                 : #include "MediaResource.h"
      41                 : 
      42                 : #include "nsHTMLMediaElement.h"
      43                 : #include "nsDOMError.h"
      44                 : 
      45                 : using namespace mozilla;
      46                 : 
      47                 : // Number of milliseconds between progress events as defined by spec
      48                 : static const PRUint32 PROGRESS_MS = 350;
      49                 : 
      50                 : // Number of milliseconds of no data before a stall event is fired as defined by spec
      51                 : static const PRUint32 STALL_MS = 3000;
      52                 : 
      53                 : // Number of estimated seconds worth of data we need to have buffered 
      54                 : // ahead of the current playback position before we allow the media decoder
      55                 : // to report that it can play through the entire media without the decode
      56                 : // catching up with the download. Having this margin make the
      57                 : // nsMediaDecoder::CanPlayThrough() calculation more stable in the case of
      58                 : // fluctuating bitrates.
      59                 : static const PRInt64 CAN_PLAY_THROUGH_MARGIN = 10;
      60                 : 
      61               0 : nsMediaDecoder::nsMediaDecoder() :
      62                 :   mElement(nsnull),
      63                 :   mFrameBufferLength(0),
      64                 :   mPinnedForSeek(false),
      65               0 :   mShuttingDown(false)
      66                 : {
      67               0 :   MOZ_COUNT_CTOR(nsMediaDecoder);
      68               0 :   MediaMemoryReporter::AddMediaDecoder(this);
      69               0 : }
      70                 : 
      71               0 : nsMediaDecoder::~nsMediaDecoder()
      72                 : {
      73               0 :   MOZ_COUNT_DTOR(nsMediaDecoder);
      74               0 :   MediaMemoryReporter::RemoveMediaDecoder(this);
      75               0 : }
      76                 : 
      77               0 : bool nsMediaDecoder::Init(nsHTMLMediaElement* aElement)
      78                 : {
      79               0 :   mElement = aElement;
      80               0 :   mVideoFrameContainer = aElement->GetVideoFrameContainer();
      81               0 :   return true;
      82                 : }
      83                 : 
      84               0 : void nsMediaDecoder::Shutdown()
      85                 : {
      86               0 :   StopProgress();
      87               0 :   mElement = nsnull;
      88               0 : }
      89                 : 
      90               0 : nsHTMLMediaElement* nsMediaDecoder::GetMediaElement()
      91                 : {
      92               0 :   return mElement;
      93                 : }
      94                 : 
      95               0 : nsresult nsMediaDecoder::RequestFrameBufferLength(PRUint32 aLength)
      96                 : {
      97               0 :   if (aLength < FRAMEBUFFER_LENGTH_MIN || aLength > FRAMEBUFFER_LENGTH_MAX) {
      98               0 :     return NS_ERROR_DOM_INDEX_SIZE_ERR;
      99                 :   }
     100                 : 
     101               0 :   mFrameBufferLength = aLength;
     102               0 :   return NS_OK;
     103                 : }
     104                 : 
     105               0 : static void ProgressCallback(nsITimer* aTimer, void* aClosure)
     106                 : {
     107               0 :   nsMediaDecoder* decoder = static_cast<nsMediaDecoder*>(aClosure);
     108               0 :   decoder->Progress(true);
     109               0 : }
     110                 : 
     111               0 : void nsMediaDecoder::Progress(bool aTimer)
     112                 : {
     113               0 :   if (!mElement)
     114               0 :     return;
     115                 : 
     116               0 :   TimeStamp now = TimeStamp::Now();
     117                 : 
     118               0 :   if (!aTimer) {
     119               0 :     mDataTime = now;
     120                 :   }
     121                 : 
     122                 :   // If PROGRESS_MS has passed since the last progress event fired and more
     123                 :   // data has arrived since then, fire another progress event.
     124               0 :   if ((mProgressTime.IsNull() ||
     125               0 :        now - mProgressTime >= TimeDuration::FromMilliseconds(PROGRESS_MS)) &&
     126               0 :       !mDataTime.IsNull() &&
     127               0 :       now - mDataTime <= TimeDuration::FromMilliseconds(PROGRESS_MS)) {
     128               0 :     mElement->DispatchAsyncEvent(NS_LITERAL_STRING("progress"));
     129               0 :     mProgressTime = now;
     130                 :   }
     131                 : 
     132               0 :   if (!mDataTime.IsNull() &&
     133               0 :       now - mDataTime >= TimeDuration::FromMilliseconds(STALL_MS)) {
     134               0 :     mElement->DownloadStalled();
     135                 :     // Null it out
     136               0 :     mDataTime = TimeStamp();
     137                 :   }
     138                 : }
     139                 : 
     140               0 : nsresult nsMediaDecoder::StartProgress()
     141                 : {
     142               0 :   if (mProgressTimer)
     143               0 :     return NS_OK;
     144                 : 
     145               0 :   mProgressTimer = do_CreateInstance("@mozilla.org/timer;1");
     146               0 :   return mProgressTimer->InitWithFuncCallback(ProgressCallback,
     147                 :                                               this,
     148                 :                                               PROGRESS_MS,
     149               0 :                                               nsITimer::TYPE_REPEATING_SLACK);
     150                 : }
     151                 : 
     152               0 : nsresult nsMediaDecoder::StopProgress()
     153                 : {
     154               0 :   if (!mProgressTimer)
     155               0 :     return NS_OK;
     156                 : 
     157               0 :   nsresult rv = mProgressTimer->Cancel();
     158               0 :   mProgressTimer = nsnull;
     159                 : 
     160               0 :   return rv;
     161                 : }
     162                 : 
     163               0 : void nsMediaDecoder::FireTimeUpdate()
     164                 : {
     165               0 :   if (!mElement)
     166               0 :     return;
     167               0 :   mElement->FireTimeUpdate(true);
     168                 : }
     169                 : 
     170               0 : void nsMediaDecoder::PinForSeek()
     171                 : {
     172               0 :   MediaResource* resource = GetResource();
     173               0 :   if (!resource || mPinnedForSeek) {
     174               0 :     return;
     175                 :   }
     176               0 :   mPinnedForSeek = true;
     177               0 :   resource->Pin();
     178                 : }
     179                 : 
     180               0 : void nsMediaDecoder::UnpinForSeek()
     181                 : {
     182               0 :   MediaResource* resource = GetResource();
     183               0 :   if (!resource || !mPinnedForSeek) {
     184               0 :     return;
     185                 :   }
     186               0 :   mPinnedForSeek = false;
     187               0 :   resource->Unpin();
     188                 : }
     189                 : 
     190               0 : bool nsMediaDecoder::CanPlayThrough()
     191                 : {
     192               0 :   Statistics stats = GetStatistics();
     193               0 :   if (!stats.mDownloadRateReliable || !stats.mPlaybackRateReliable) {
     194               0 :     return false;
     195                 :   }
     196               0 :   PRInt64 bytesToDownload = stats.mTotalBytes - stats.mDownloadPosition;
     197               0 :   PRInt64 bytesToPlayback = stats.mTotalBytes - stats.mPlaybackPosition;
     198               0 :   double timeToDownload = bytesToDownload / stats.mDownloadRate;
     199               0 :   double timeToPlay = bytesToPlayback / stats.mPlaybackRate;
     200                 : 
     201               0 :   if (timeToDownload > timeToPlay) {
     202                 :     // Estimated time to download is greater than the estimated time to play.
     203                 :     // We probably can't play through without having to stop to buffer.
     204               0 :     return false;
     205                 :   }
     206                 : 
     207                 :   // Estimated time to download is less than the estimated time to play.
     208                 :   // We can probably play through without having to buffer, but ensure that
     209                 :   // we've got a reasonable amount of data buffered after the current
     210                 :   // playback position, so that if the bitrate of the media fluctuates, or if
     211                 :   // our download rate or decode rate estimation is otherwise inaccurate,
     212                 :   // we don't suddenly discover that we need to buffer. This is particularly
     213                 :   // required near the start of the media, when not much data is downloaded.
     214                 :   PRInt64 readAheadMargin =
     215               0 :     static_cast<PRInt64>(stats.mPlaybackRate * CAN_PLAY_THROUGH_MARGIN);
     216                 :   return stats.mTotalBytes == stats.mDownloadPosition ||
     217               0 :          stats.mDownloadPosition > stats.mPlaybackPosition + readAheadMargin;
     218                 : }
     219                 : 
     220                 : namespace mozilla {
     221                 : 
     222                 : MediaMemoryReporter* MediaMemoryReporter::sUniqueInstance;
     223                 : 
     224               0 : NS_MEMORY_REPORTER_IMPLEMENT(MediaDecodedVideoMemory,
     225                 :                              "explicit/media/decoded-video",
     226                 :                              KIND_HEAP,
     227                 :                              UNITS_BYTES,
     228                 :                              MediaMemoryReporter::GetDecodedVideoMemory,
     229               0 :                              "Memory used by decoded video frames.")
     230                 : 
     231               0 : NS_MEMORY_REPORTER_IMPLEMENT(MediaDecodedAudioMemory,
     232                 :                              "explicit/media/decoded-audio",
     233                 :                              KIND_HEAP,
     234                 :                              UNITS_BYTES,
     235                 :                              MediaMemoryReporter::GetDecodedAudioMemory,
     236               0 :                              "Memory used by decoded audio chunks.")
     237                 : 
     238               0 : MediaMemoryReporter::MediaMemoryReporter()
     239               0 :   : mMediaDecodedVideoMemory(new NS_MEMORY_REPORTER_NAME(MediaDecodedVideoMemory))
     240               0 :   , mMediaDecodedAudioMemory(new NS_MEMORY_REPORTER_NAME(MediaDecodedAudioMemory))
     241                 : {
     242               0 :   NS_RegisterMemoryReporter(mMediaDecodedVideoMemory);
     243               0 :   NS_RegisterMemoryReporter(mMediaDecodedAudioMemory);
     244               0 : }
     245                 : 
     246               0 : MediaMemoryReporter::~MediaMemoryReporter()
     247                 : {
     248               0 :   NS_UnregisterMemoryReporter(mMediaDecodedVideoMemory);
     249               0 :   NS_UnregisterMemoryReporter(mMediaDecodedAudioMemory);
     250               0 : }
     251                 : 
     252                 : } // namespace mozilla

Generated by: LCOV version 1.7