LCOV - code coverage report
Current view: top level - dom/html - HTMLVideoElement.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 22 133 16.5 %
Date: 2017-07-14 16:53:18 Functions: 7 28 25.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "nsIDOMHTMLSourceElement.h"
       8             : #include "mozilla/dom/HTMLVideoElement.h"
       9             : #include "mozilla/dom/HTMLVideoElementBinding.h"
      10             : #include "nsGenericHTMLElement.h"
      11             : #include "nsGkAtoms.h"
      12             : #include "nsSize.h"
      13             : #include "nsError.h"
      14             : #include "nsNodeInfoManager.h"
      15             : #include "plbase64.h"
      16             : #include "prlock.h"
      17             : #include "nsThreadUtils.h"
      18             : #include "ImageContainer.h"
      19             : #include "VideoFrameContainer.h"
      20             : 
      21             : #include "nsIScriptSecurityManager.h"
      22             : #include "nsIXPConnect.h"
      23             : 
      24             : #include "nsITimer.h"
      25             : 
      26             : #include "MediaError.h"
      27             : #include "MediaDecoder.h"
      28             : #include "mozilla/Preferences.h"
      29             : #include "mozilla/dom/WakeLock.h"
      30             : #include "mozilla/dom/power/PowerManagerService.h"
      31             : #include "mozilla/dom/Performance.h"
      32             : #include "mozilla/dom/VideoPlaybackQuality.h"
      33             : 
      34             : #include <algorithm>
      35             : #include <limits>
      36             : 
      37           2 : NS_IMPL_NS_NEW_HTML_ELEMENT(Video)
      38             : 
      39             : namespace mozilla {
      40             : namespace dom {
      41             : 
      42             : static bool sVideoStatsEnabled;
      43             : 
      44           0 : NS_IMPL_ELEMENT_CLONE(HTMLVideoElement)
      45             : 
      46           1 : HTMLVideoElement::HTMLVideoElement(already_AddRefed<NodeInfo>& aNodeInfo)
      47             :   : HTMLMediaElement(aNodeInfo)
      48           1 :   , mUseScreenWakeLock(true)
      49             : {
      50           1 : }
      51             : 
      52           0 : HTMLVideoElement::~HTMLVideoElement()
      53             : {
      54           0 : }
      55             : 
      56           0 : nsresult HTMLVideoElement::GetVideoSize(nsIntSize* size)
      57             : {
      58           0 :   if (!mMediaInfo.HasVideo()) {
      59           0 :     return NS_ERROR_FAILURE;
      60             :   }
      61             : 
      62           0 :   if (mDisableVideo) {
      63           0 :     return NS_ERROR_FAILURE;
      64             :   }
      65             : 
      66           0 :   switch (mMediaInfo.mVideo.mRotation) {
      67             :     case VideoInfo::Rotation::kDegree_90:
      68             :     case VideoInfo::Rotation::kDegree_270: {
      69           0 :       size->width = mMediaInfo.mVideo.mDisplay.height;
      70           0 :       size->height = mMediaInfo.mVideo.mDisplay.width;
      71           0 :       break;
      72             :     }
      73             :     case VideoInfo::Rotation::kDegree_0:
      74             :     case VideoInfo::Rotation::kDegree_180:
      75             :     default: {
      76           0 :       size->height = mMediaInfo.mVideo.mDisplay.height;
      77           0 :       size->width = mMediaInfo.mVideo.mDisplay.width;
      78           0 :       break;
      79             :     }
      80             :   }
      81           0 :   return NS_OK;
      82             : }
      83             : 
      84             : bool
      85           1 : HTMLVideoElement::ParseAttribute(int32_t aNamespaceID,
      86             :                                  nsIAtom* aAttribute,
      87             :                                  const nsAString& aValue,
      88             :                                  nsAttrValue& aResult)
      89             : {
      90           1 :    if (aAttribute == nsGkAtoms::width || aAttribute == nsGkAtoms::height) {
      91           0 :      return aResult.ParseSpecialIntValue(aValue);
      92             :    }
      93             : 
      94           1 :    return HTMLMediaElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
      95           1 :                                            aResult);
      96             : }
      97             : 
      98             : void
      99           0 : HTMLVideoElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
     100             :                                         GenericSpecifiedValues* aData)
     101             : {
     102           0 :   nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aData);
     103           0 :   nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
     104           0 : }
     105             : 
     106             : NS_IMETHODIMP_(bool)
     107           1 : HTMLVideoElement::IsAttributeMapped(const nsIAtom* aAttribute) const
     108             : {
     109             :   static const MappedAttributeEntry attributes[] = {
     110             :     { &nsGkAtoms::width },
     111             :     { &nsGkAtoms::height },
     112             :     { nullptr }
     113             :   };
     114             : 
     115             :   static const MappedAttributeEntry* const map[] = {
     116             :     attributes,
     117             :     sCommonAttributeMap
     118             :   };
     119             : 
     120           1 :   return FindAttributeDependence(aAttribute, map);
     121             : }
     122             : 
     123             : nsMapRuleToAttributesFunc
     124           0 : HTMLVideoElement::GetAttributeMappingFunction() const
     125             : {
     126           0 :   return &MapAttributesIntoRule;
     127             : }
     128             : 
     129           0 : nsresult HTMLVideoElement::SetAcceptHeader(nsIHttpChannel* aChannel)
     130             : {
     131             :   nsAutoCString value(
     132             :       "video/webm,"
     133             :       "video/ogg,"
     134             :       "video/*;q=0.9,"
     135             :       "application/ogg;q=0.7,"
     136           0 :       "audio/*;q=0.6,*/*;q=0.5");
     137             : 
     138           0 :   return aChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"),
     139             :                                     value,
     140           0 :                                     false);
     141             : }
     142             : 
     143             : bool
     144           0 : HTMLVideoElement::IsInteractiveHTMLContent(bool aIgnoreTabindex) const
     145             : {
     146           0 :   return HasAttr(kNameSpaceID_None, nsGkAtoms::controls) ||
     147           0 :          HTMLMediaElement::IsInteractiveHTMLContent(aIgnoreTabindex);
     148             : }
     149             : 
     150           0 : uint32_t HTMLVideoElement::MozParsedFrames() const
     151             : {
     152           0 :   MOZ_ASSERT(NS_IsMainThread(), "Should be on main thread.");
     153           0 :   if (!sVideoStatsEnabled) {
     154           0 :     return 0;
     155             :   }
     156           0 :   return mDecoder ? mDecoder->GetFrameStatistics().GetParsedFrames() : 0;
     157             : }
     158             : 
     159           0 : uint32_t HTMLVideoElement::MozDecodedFrames() const
     160             : {
     161           0 :   MOZ_ASSERT(NS_IsMainThread(), "Should be on main thread.");
     162           0 :   if (!sVideoStatsEnabled) {
     163           0 :     return 0;
     164             :   }
     165           0 :   return mDecoder ? mDecoder->GetFrameStatistics().GetDecodedFrames() : 0;
     166             : }
     167             : 
     168           0 : uint32_t HTMLVideoElement::MozPresentedFrames() const
     169             : {
     170           0 :   MOZ_ASSERT(NS_IsMainThread(), "Should be on main thread.");
     171           0 :   if (!sVideoStatsEnabled) {
     172           0 :     return 0;
     173             :   }
     174           0 :   return mDecoder ? mDecoder->GetFrameStatistics().GetPresentedFrames() : 0;
     175             : }
     176             : 
     177           0 : uint32_t HTMLVideoElement::MozPaintedFrames()
     178             : {
     179           0 :   MOZ_ASSERT(NS_IsMainThread(), "Should be on main thread.");
     180           0 :   if (!sVideoStatsEnabled) {
     181           0 :     return 0;
     182             :   }
     183           0 :   layers::ImageContainer* container = GetImageContainer();
     184           0 :   return container ? container->GetPaintCount() : 0;
     185             : }
     186             : 
     187           0 : double HTMLVideoElement::MozFrameDelay()
     188             : {
     189           0 :   MOZ_ASSERT(NS_IsMainThread(), "Should be on main thread.");
     190           0 :   VideoFrameContainer* container = GetVideoFrameContainer();
     191             :   // Hide negative delays. Frame timing tweaks in the compositor (e.g.
     192             :   // adding a bias value to prevent multiple dropped/duped frames when
     193             :   // frame times are aligned with composition times) may produce apparent
     194             :   // negative delay, but we shouldn't report that.
     195           0 :   return container ? std::max(0.0, container->GetFrameDelay()) : 0.0;
     196             : }
     197             : 
     198           0 : bool HTMLVideoElement::MozHasAudio() const
     199             : {
     200           0 :   MOZ_ASSERT(NS_IsMainThread(), "Should be on main thread.");
     201           0 :   return HasAudio();
     202             : }
     203             : 
     204           0 : bool HTMLVideoElement::MozUseScreenWakeLock() const
     205             : {
     206           0 :   MOZ_ASSERT(NS_IsMainThread(), "Should be on main thread.");
     207           0 :   return mUseScreenWakeLock;
     208             : }
     209             : 
     210           0 : void HTMLVideoElement::SetMozUseScreenWakeLock(bool aValue)
     211             : {
     212           0 :   MOZ_ASSERT(NS_IsMainThread(), "Should be on main thread.");
     213           0 :   mUseScreenWakeLock = aValue;
     214           0 :   UpdateScreenWakeLock();
     215           0 : }
     216             : 
     217             : JSObject*
     218           0 : HTMLVideoElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
     219             : {
     220           0 :   return HTMLVideoElementBinding::Wrap(aCx, this, aGivenProto);
     221             : }
     222             : 
     223             : void
     224           1 : HTMLVideoElement::NotifyOwnerDocumentActivityChanged()
     225             : {
     226           1 :   HTMLMediaElement::NotifyOwnerDocumentActivityChanged();
     227           1 :   UpdateScreenWakeLock();
     228           1 : }
     229             : 
     230             : FrameStatistics*
     231           0 : HTMLVideoElement::GetFrameStatistics()
     232             : {
     233           0 :   return mDecoder ? &(mDecoder->GetFrameStatistics()) : nullptr;
     234             : }
     235             : 
     236             : already_AddRefed<VideoPlaybackQuality>
     237           0 : HTMLVideoElement::GetVideoPlaybackQuality()
     238             : {
     239           0 :   DOMHighResTimeStamp creationTime = 0;
     240           0 :   uint32_t totalFrames = 0;
     241           0 :   uint32_t droppedFrames = 0;
     242           0 :   uint32_t corruptedFrames = 0;
     243             : 
     244           0 :   if (sVideoStatsEnabled) {
     245           0 :     if (nsPIDOMWindowInner* window = OwnerDoc()->GetInnerWindow()) {
     246           0 :       Performance* perf = window->GetPerformance();
     247           0 :       if (perf) {
     248           0 :         creationTime = perf->Now();
     249             :       }
     250             :     }
     251             : 
     252           0 :     if (mDecoder) {
     253             :       FrameStatisticsData stats =
     254           0 :         mDecoder->GetFrameStatistics().GetFrameStatisticsData();
     255             :       if (sizeof(totalFrames) >= sizeof(stats.mParsedFrames)) {
     256             :         totalFrames = stats.mPresentedFrames + stats.mDroppedFrames;
     257             :         droppedFrames = stats.mDroppedFrames;
     258             :       } else {
     259           0 :         uint64_t total = stats.mPresentedFrames + stats.mDroppedFrames;
     260           0 :         const auto maxNumber = std::numeric_limits<uint32_t>::max();
     261           0 :         if (total <= maxNumber) {
     262           0 :           totalFrames = uint32_t(total);
     263           0 :           droppedFrames = uint32_t(stats.mDroppedFrames);
     264             :         } else {
     265             :           // Too big number(s) -> Resize everything to fit in 32 bits.
     266           0 :           double ratio = double(maxNumber) / double(total);
     267           0 :           totalFrames = maxNumber; // === total * ratio
     268           0 :           droppedFrames = uint32_t(double(stats.mDroppedFrames) * ratio);
     269             :         }
     270             :       }
     271           0 :       corruptedFrames = 0;
     272             :     }
     273             :   }
     274             : 
     275             :   RefPtr<VideoPlaybackQuality> playbackQuality =
     276             :     new VideoPlaybackQuality(this, creationTime, totalFrames, droppedFrames,
     277           0 :                              corruptedFrames);
     278           0 :   return playbackQuality.forget();
     279             : }
     280             : 
     281             : void
     282           0 : HTMLVideoElement::WakeLockCreate()
     283             : {
     284           0 :   HTMLMediaElement::WakeLockCreate();
     285           0 :   UpdateScreenWakeLock();
     286           0 : }
     287             : 
     288             : void
     289           0 : HTMLVideoElement::WakeLockRelease()
     290             : {
     291           0 :   UpdateScreenWakeLock();
     292           0 :   HTMLMediaElement::WakeLockRelease();
     293           0 : }
     294             : 
     295             : void
     296           1 : HTMLVideoElement::UpdateScreenWakeLock()
     297             : {
     298           1 :   bool hidden = OwnerDoc()->Hidden();
     299             : 
     300           1 :   if (mScreenWakeLock && (mPaused || hidden || !mUseScreenWakeLock)) {
     301           0 :     ErrorResult rv;
     302           0 :     mScreenWakeLock->Unlock(rv);
     303           0 :     rv.SuppressException();
     304           0 :     mScreenWakeLock = nullptr;
     305           0 :     return;
     306             :   }
     307             : 
     308           3 :   if (!mScreenWakeLock && !mPaused && !hidden &&
     309           1 :       mUseScreenWakeLock && HasVideo()) {
     310             :     RefPtr<power::PowerManagerService> pmService =
     311           0 :       power::PowerManagerService::GetInstance();
     312           0 :     NS_ENSURE_TRUE_VOID(pmService);
     313             : 
     314           0 :     ErrorResult rv;
     315           0 :     mScreenWakeLock = pmService->NewWakeLock(NS_LITERAL_STRING("screen"),
     316             :                                              OwnerDoc()->GetInnerWindow(),
     317           0 :                                              rv);
     318             :   }
     319             : }
     320             : 
     321             : void
     322           3 : HTMLVideoElement::Init()
     323             : {
     324           3 :   Preferences::AddBoolVarCache(&sVideoStatsEnabled, "media.video_stats.enabled");
     325           3 : }
     326             : 
     327             : } // namespace dom
     328             : } // namespace mozilla

Generated by: LCOV version 1.13