LCOV - code coverage report
Current view: directory - layout/generic - nsVideoFrame.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 242 0 0.0 %
Date: 2012-06-02 Functions: 36 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                 : /* rendering object for the HTML <video> element */
      40                 : 
      41                 : #include "nsHTMLParts.h"
      42                 : #include "nsCOMPtr.h"
      43                 : #include "nsIServiceManager.h"
      44                 : #include "nsGkAtoms.h"
      45                 : 
      46                 : #include "nsVideoFrame.h"
      47                 : #include "nsHTMLVideoElement.h"
      48                 : #include "nsIDOMHTMLVideoElement.h"
      49                 : #include "nsDisplayList.h"
      50                 : #include "gfxContext.h"
      51                 : #include "gfxImageSurface.h"
      52                 : #include "nsPresContext.h"
      53                 : #include "nsTransform2D.h"
      54                 : #include "nsContentCreatorFunctions.h"
      55                 : #include "nsBoxLayoutState.h"
      56                 : #include "nsBoxFrame.h"
      57                 : #include "nsImageFrame.h"
      58                 : #include "nsIImageLoadingContent.h"
      59                 : #include "nsCSSRendering.h"
      60                 : #include "nsContentUtils.h"
      61                 : 
      62                 : #ifdef ACCESSIBILITY
      63                 : #include "nsAccessibilityService.h"
      64                 : #endif
      65                 : 
      66                 : using namespace mozilla;
      67                 : using namespace mozilla::layers;
      68                 : using namespace mozilla::dom;
      69                 : 
      70                 : nsIFrame*
      71               0 : NS_NewHTMLVideoFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
      72                 : {
      73               0 :   return new (aPresShell) nsVideoFrame(aContext);
      74                 : }
      75                 : 
      76               0 : NS_IMPL_FRAMEARENA_HELPERS(nsVideoFrame)
      77                 : 
      78               0 : nsVideoFrame::nsVideoFrame(nsStyleContext* aContext) :
      79               0 :   nsContainerFrame(aContext)
      80                 : {
      81               0 : }
      82                 : 
      83               0 : nsVideoFrame::~nsVideoFrame()
      84                 : {
      85               0 : }
      86                 : 
      87               0 : NS_QUERYFRAME_HEAD(nsVideoFrame)
      88               0 :   NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
      89               0 : NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
      90                 : 
      91                 : nsresult
      92               0 : nsVideoFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
      93                 : {
      94               0 :   nsNodeInfoManager *nodeInfoManager = GetContent()->GetCurrentDoc()->NodeInfoManager();
      95               0 :   nsCOMPtr<nsINodeInfo> nodeInfo;
      96               0 :   if (HasVideoElement()) {
      97                 :     // Create an anonymous image element as a child to hold the poster
      98                 :     // image. We may not have a poster image now, but one could be added
      99                 :     // before we load, or on a subsequent load.
     100                 :     nodeInfo = nodeInfoManager->GetNodeInfo(nsGkAtoms::img,
     101                 :                                             nsnull,
     102                 :                                             kNameSpaceID_XHTML,
     103               0 :                                             nsIDOMNode::ELEMENT_NODE);
     104               0 :     NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY);
     105               0 :     Element* element = NS_NewHTMLImageElement(nodeInfo.forget());
     106               0 :     mPosterImage = element;
     107               0 :     NS_ENSURE_TRUE(mPosterImage, NS_ERROR_OUT_OF_MEMORY);
     108                 : 
     109                 :     // Push a null JSContext on the stack so that code that runs
     110                 :     // within the below code doesn't think it's being called by
     111                 :     // JS. See bug 604262.
     112               0 :     nsCxPusher pusher;
     113               0 :     pusher.PushNull();
     114                 : 
     115                 :     // Set the nsImageLoadingContent::ImageState() to 0. This means that the
     116                 :     // image will always report its state as 0, so it will never be reframed
     117                 :     // to show frames for loading or the broken image icon. This is important,
     118                 :     // as the image is native anonymous, and so can't be reframed (currently).
     119               0 :     nsCOMPtr<nsIImageLoadingContent> imgContent = do_QueryInterface(mPosterImage);
     120               0 :     NS_ENSURE_TRUE(imgContent, NS_ERROR_FAILURE);
     121                 : 
     122               0 :     imgContent->ForceImageState(true, 0);
     123                 :     // And now have it update its internal state
     124               0 :     element->UpdateState(false);
     125                 : 
     126               0 :     nsresult res = UpdatePosterSource(false);
     127               0 :     NS_ENSURE_SUCCESS(res,res);
     128                 : 
     129               0 :     if (!aElements.AppendElement(mPosterImage))
     130               0 :       return NS_ERROR_OUT_OF_MEMORY;
     131                 :   }
     132                 : 
     133                 :   // Set up "videocontrols" XUL element which will be XBL-bound to the
     134                 :   // actual controls.
     135                 :   nodeInfo = nodeInfoManager->GetNodeInfo(nsGkAtoms::videocontrols,
     136                 :                                           nsnull,
     137                 :                                           kNameSpaceID_XUL,
     138               0 :                                           nsIDOMNode::ELEMENT_NODE);
     139               0 :   NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY);
     140                 : 
     141               0 :   NS_TrustedNewXULElement(getter_AddRefs(mVideoControls), nodeInfo.forget());
     142               0 :   if (!aElements.AppendElement(mVideoControls))
     143               0 :     return NS_ERROR_OUT_OF_MEMORY;
     144                 : 
     145               0 :   return NS_OK;
     146                 : }
     147                 : 
     148                 : void
     149               0 : nsVideoFrame::AppendAnonymousContentTo(nsBaseContentList& aElements,
     150                 :                                        PRUint32 aFliter)
     151                 : {
     152               0 :   aElements.MaybeAppendElement(mPosterImage);
     153               0 :   aElements.MaybeAppendElement(mVideoControls);
     154               0 : }
     155                 : 
     156                 : void
     157               0 : nsVideoFrame::DestroyFrom(nsIFrame* aDestructRoot)
     158                 : {
     159               0 :   nsContentUtils::DestroyAnonymousContent(&mVideoControls);
     160               0 :   nsContentUtils::DestroyAnonymousContent(&mPosterImage);
     161               0 :   nsContainerFrame::DestroyFrom(aDestructRoot);
     162               0 : }
     163                 : 
     164                 : bool
     165               0 : nsVideoFrame::IsLeaf() const
     166                 : {
     167               0 :   return true;
     168                 : }
     169                 : 
     170                 : // Return the largest rectangle that fits in aRect and has the
     171                 : // same aspect ratio as aRatio, centered at the center of aRect
     172                 : static gfxRect
     173               0 : CorrectForAspectRatio(const gfxRect& aRect, const nsIntSize& aRatio)
     174                 : {
     175               0 :   NS_ASSERTION(aRatio.width > 0 && aRatio.height > 0 && !aRect.IsEmpty(),
     176                 :                "Nothing to draw");
     177                 :   // Choose scale factor that scales aRatio to just fit into aRect
     178                 :   gfxFloat scale =
     179               0 :     NS_MIN(aRect.Width()/aRatio.width, aRect.Height()/aRatio.height);
     180               0 :   gfxSize scaledRatio(scale*aRatio.width, scale*aRatio.height);
     181               0 :   gfxPoint topLeft((aRect.Width() - scaledRatio.width)/2,
     182               0 :                    (aRect.Height() - scaledRatio.height)/2);
     183               0 :   return gfxRect(aRect.TopLeft() + topLeft, scaledRatio);
     184                 : }
     185                 : 
     186                 : already_AddRefed<Layer>
     187               0 : nsVideoFrame::BuildLayer(nsDisplayListBuilder* aBuilder,
     188                 :                          LayerManager* aManager,
     189                 :                          nsDisplayItem* aItem)
     190                 : {
     191               0 :   nsRect area = GetContentRect() - GetPosition() + aItem->ToReferenceFrame();
     192               0 :   nsHTMLVideoElement* element = static_cast<nsHTMLVideoElement*>(GetContent());
     193               0 :   nsIntSize videoSize = element->GetVideoSize(nsIntSize(0, 0));
     194               0 :   if (videoSize.width <= 0 || videoSize.height <= 0 || area.IsEmpty())
     195               0 :     return nsnull;
     196                 : 
     197               0 :   nsRefPtr<ImageContainer> container = element->GetImageContainer();
     198                 :   
     199                 :   // Retrieve the size of the decoded video frame, before being scaled
     200                 :   // by pixel aspect ratio.
     201               0 :   gfxIntSize frameSize = container->GetCurrentSize();
     202               0 :   if (frameSize.width == 0 || frameSize.height == 0) {
     203                 :     // No image, or zero-sized image. No point creating a layer.
     204               0 :     return nsnull;
     205                 :   }
     206                 : 
     207                 :   // Compute the rectangle in which to paint the video. We need to use
     208                 :   // the largest rectangle that fills our content-box and has the
     209                 :   // correct aspect ratio.
     210               0 :   nsPresContext* presContext = PresContext();
     211                 :   gfxRect r = gfxRect(presContext->AppUnitsToGfxUnits(area.x),
     212                 :                       presContext->AppUnitsToGfxUnits(area.y),
     213                 :                       presContext->AppUnitsToGfxUnits(area.width),
     214               0 :                       presContext->AppUnitsToGfxUnits(area.height));
     215               0 :   r = CorrectForAspectRatio(r, videoSize);
     216               0 :   r.Round();
     217               0 :   gfxIntSize scaleHint(static_cast<PRInt32>(r.Width()),
     218               0 :                        static_cast<PRInt32>(r.Height()));
     219               0 :   container->SetScaleHint(scaleHint);
     220                 : 
     221                 :   nsRefPtr<ImageLayer> layer = static_cast<ImageLayer*>
     222               0 :     (aBuilder->LayerBuilder()->GetLeafLayerFor(aBuilder, aManager, aItem));
     223               0 :   if (!layer) {
     224               0 :     layer = aManager->CreateImageLayer();
     225               0 :     if (!layer)
     226               0 :       return nsnull;
     227                 :   }
     228                 : 
     229               0 :   layer->SetContainer(container);
     230               0 :   layer->SetFilter(nsLayoutUtils::GetGraphicsFilterForFrame(this));
     231               0 :   layer->SetContentFlags(Layer::CONTENT_OPAQUE);
     232                 :   // Set a transform on the layer to draw the video in the right place
     233               0 :   gfxMatrix transform;
     234               0 :   transform.Translate(r.TopLeft());
     235               0 :   transform.Scale(r.Width()/frameSize.width, r.Height()/frameSize.height);
     236               0 :   layer->SetTransform(gfx3DMatrix::From2D(transform));
     237               0 :   layer->SetVisibleRegion(nsIntRect(0, 0, frameSize.width, frameSize.height));
     238               0 :   nsRefPtr<Layer> result = layer.forget();
     239               0 :   return result.forget();
     240                 : }
     241                 : 
     242                 : NS_IMETHODIMP
     243               0 : nsVideoFrame::Reflow(nsPresContext*           aPresContext,
     244                 :                      nsHTMLReflowMetrics&     aMetrics,
     245                 :                      const nsHTMLReflowState& aReflowState,
     246                 :                      nsReflowStatus&          aStatus)
     247                 : {
     248               0 :   DO_GLOBAL_REFLOW_COUNT("nsVideoFrame");
     249               0 :   DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus);
     250               0 :   NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
     251                 :                   ("enter nsVideoFrame::Reflow: availSize=%d,%d",
     252                 :                   aReflowState.availableWidth, aReflowState.availableHeight));
     253                 : 
     254               0 :   NS_PRECONDITION(mState & NS_FRAME_IN_REFLOW, "frame is not in reflow");
     255                 : 
     256               0 :   aStatus = NS_FRAME_COMPLETE;
     257                 : 
     258               0 :   aMetrics.width = aReflowState.ComputedWidth();
     259               0 :   aMetrics.height = aReflowState.ComputedHeight();
     260                 : 
     261                 :   // stash this away so we can compute our inner area later
     262               0 :   mBorderPadding   = aReflowState.mComputedBorderPadding;
     263                 : 
     264               0 :   aMetrics.width += mBorderPadding.left + mBorderPadding.right;
     265               0 :   aMetrics.height += mBorderPadding.top + mBorderPadding.bottom;
     266                 : 
     267                 :   // Reflow the child frames. We may have up to two, an image frame
     268                 :   // which is the poster, and a box frame, which is the video controls.
     269               0 :   for (nsIFrame *child = mFrames.FirstChild();
     270                 :        child;
     271                 :        child = child->GetNextSibling()) {
     272               0 :     if (child->GetType() == nsGkAtoms::imageFrame) {
     273                 :       // Reflow the poster frame.
     274               0 :       nsImageFrame* imageFrame = static_cast<nsImageFrame*>(child);
     275               0 :       nsHTMLReflowMetrics kidDesiredSize;
     276                 :       nsSize availableSize = nsSize(aReflowState.availableWidth,
     277               0 :                                     aReflowState.availableHeight);
     278                 :       nsHTMLReflowState kidReflowState(aPresContext,
     279                 :                                        aReflowState,
     280                 :                                        imageFrame,
     281                 :                                        availableSize,
     282                 :                                        aMetrics.width,
     283               0 :                                        aMetrics.height);
     284               0 :       if (ShouldDisplayPoster()) {
     285               0 :         kidReflowState.SetComputedWidth(aReflowState.ComputedWidth());
     286               0 :         kidReflowState.SetComputedHeight(aReflowState.ComputedHeight());
     287                 :       } else {
     288               0 :         kidReflowState.SetComputedWidth(0);
     289               0 :         kidReflowState.SetComputedHeight(0);
     290                 :       }
     291                 :       ReflowChild(imageFrame, aPresContext, kidDesiredSize, kidReflowState,
     292               0 :                   mBorderPadding.left, mBorderPadding.top, 0, aStatus);
     293                 :       FinishReflowChild(imageFrame, aPresContext,
     294                 :                         &kidReflowState, kidDesiredSize,
     295               0 :                         mBorderPadding.left, mBorderPadding.top, 0);
     296               0 :     } else if (child->GetType() == nsGkAtoms::boxFrame) {
     297                 :       // Reflow the video controls frame.
     298               0 :       nsBoxLayoutState boxState(PresContext(), aReflowState.rendContext);
     299                 :       nsBoxFrame::LayoutChildAt(boxState,
     300                 :                                 child,
     301                 :                                 nsRect(mBorderPadding.left,
     302                 :                                        mBorderPadding.top,
     303                 :                                        aReflowState.ComputedWidth(),
     304               0 :                                        aReflowState.ComputedHeight()));
     305                 :     }
     306                 :   }
     307               0 :   aMetrics.SetOverflowAreasToDesiredBounds();
     308                 : 
     309               0 :   FinishAndStoreOverflow(&aMetrics);
     310                 : 
     311               0 :   if (mRect.width != aMetrics.width || mRect.height != aMetrics.height) {
     312               0 :     Invalidate(nsRect(0, 0, mRect.width, mRect.height));
     313                 :   }
     314                 : 
     315               0 :   NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
     316                 :                   ("exit nsVideoFrame::Reflow: size=%d,%d",
     317                 :                   aMetrics.width, aMetrics.height));
     318               0 :   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
     319                 : 
     320               0 :   return NS_OK;
     321                 : }
     322                 : 
     323                 : class nsDisplayVideo : public nsDisplayItem {
     324                 : public:
     325               0 :   nsDisplayVideo(nsDisplayListBuilder* aBuilder, nsVideoFrame* aFrame)
     326               0 :     : nsDisplayItem(aBuilder, aFrame)
     327                 :   {
     328               0 :     MOZ_COUNT_CTOR(nsDisplayVideo);
     329               0 :   }
     330                 : #ifdef NS_BUILD_REFCNT_LOGGING
     331               0 :   virtual ~nsDisplayVideo() {
     332               0 :     MOZ_COUNT_DTOR(nsDisplayVideo);
     333               0 :   }
     334                 : #endif
     335                 :   
     336               0 :   NS_DISPLAY_DECL_NAME("Video", TYPE_VIDEO)
     337                 : 
     338                 :   // It would be great if we could override GetOpaqueRegion to return nonempty here,
     339                 :   // but it's probably not safe to do so in general. Video frames are
     340                 :   // updated asynchronously from decoder threads, and it's possible that
     341                 :   // we might have an opaque video frame when GetOpaqueRegion is called, but
     342                 :   // when we come to paint, the video frame is transparent or has gone
     343                 :   // away completely (e.g. because of a decoder error). The problem would
     344                 :   // be especially acute if we have off-main-thread rendering.
     345                 : 
     346               0 :   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder)
     347                 :   {
     348               0 :     nsIFrame* f = GetUnderlyingFrame();
     349               0 :     return f->GetContentRect() - f->GetPosition() + ToReferenceFrame();
     350                 :   }
     351                 : 
     352               0 :   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
     353                 :                                              LayerManager* aManager,
     354                 :                                              const ContainerParameters& aContainerParameters)
     355                 :   {
     356               0 :     return static_cast<nsVideoFrame*>(mFrame)->BuildLayer(aBuilder, aManager, this);
     357                 :   }
     358                 : 
     359               0 :   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
     360                 :                                    LayerManager* aManager)
     361                 :   {
     362               0 :     if (aManager->GetBackendType() != LayerManager::LAYERS_BASIC) {
     363                 :       // For non-basic layer managers we can assume that compositing
     364                 :       // layers is very cheap, and since ImageLayers don't require
     365                 :       // additional memory of the video frames we have to have anyway,
     366                 :       // we can't save much by making layers inactive. Also, for many
     367                 :       // accelerated layer managers calling
     368                 :       // imageContainer->GetCurrentAsSurface can be very expensive. So
     369                 :       // just always be active for these managers.
     370               0 :       return LAYER_ACTIVE;
     371                 :     }
     372                 :     nsHTMLMediaElement* elem =
     373               0 :       static_cast<nsHTMLMediaElement*>(mFrame->GetContent());
     374               0 :     return elem->IsPotentiallyPlaying() ? LAYER_ACTIVE : LAYER_INACTIVE;
     375                 :   }
     376                 : };
     377                 : 
     378                 : NS_IMETHODIMP
     379               0 : nsVideoFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
     380                 :                                const nsRect&           aDirtyRect,
     381                 :                                const nsDisplayListSet& aLists)
     382                 : {
     383               0 :   if (!IsVisibleForPainting(aBuilder))
     384               0 :     return NS_OK;
     385                 : 
     386               0 :   DO_GLOBAL_REFLOW_COUNT_DSP("nsVideoFrame");
     387                 : 
     388               0 :   nsresult rv = DisplayBorderBackgroundOutline(aBuilder, aLists);
     389               0 :   NS_ENSURE_SUCCESS(rv, rv);
     390                 : 
     391               0 :   nsDisplayList replacedContent;
     392                 : 
     393               0 :   if (HasVideoElement() && !ShouldDisplayPoster()) {
     394                 :     rv = replacedContent.AppendNewToTop(
     395               0 :       new (aBuilder) nsDisplayVideo(aBuilder, this));
     396               0 :     NS_ENSURE_SUCCESS(rv, rv);
     397                 :   }
     398                 : 
     399                 :   // Add child frames to display list. We expect up to two children, an image
     400                 :   // frame for the poster, and the box frame for the video controls.
     401               0 :   for (nsIFrame *child = mFrames.FirstChild();
     402                 :        child;
     403                 :        child = child->GetNextSibling()) {
     404               0 :     if (child->GetType() == nsGkAtoms::imageFrame && ShouldDisplayPoster()) {
     405                 :       rv = child->BuildDisplayListForStackingContext(aBuilder,
     406               0 :                                                      aDirtyRect - child->GetOffsetTo(this),
     407               0 :                                                      &replacedContent);
     408               0 :       NS_ENSURE_SUCCESS(rv,rv);
     409               0 :     } else if (child->GetType() == nsGkAtoms::boxFrame) {
     410                 :       rv = child->BuildDisplayListForStackingContext(aBuilder,
     411               0 :                                                      aDirtyRect - child->GetOffsetTo(this),
     412               0 :                                                      &replacedContent);
     413               0 :       NS_ENSURE_SUCCESS(rv,rv);
     414                 :     }
     415                 :   }
     416                 : 
     417               0 :   WrapReplacedContentForBorderRadius(aBuilder, &replacedContent, aLists);
     418                 : 
     419               0 :   return NS_OK;
     420                 : }
     421                 : 
     422                 : nsIAtom*
     423               0 : nsVideoFrame::GetType() const
     424                 : {
     425               0 :   return nsGkAtoms::HTMLVideoFrame;
     426                 : }
     427                 : 
     428                 : #ifdef ACCESSIBILITY
     429                 : already_AddRefed<nsAccessible>
     430               0 : nsVideoFrame::CreateAccessible()
     431                 : {
     432               0 :   nsAccessibilityService* accService = nsIPresShell::AccService();
     433                 :   return accService ?
     434               0 :     accService->CreateHTMLMediaAccessible(mContent, PresContext()->PresShell()) :
     435               0 :     nsnull;
     436                 : }
     437                 : #endif
     438                 : 
     439                 : #ifdef DEBUG
     440                 : NS_IMETHODIMP
     441               0 : nsVideoFrame::GetFrameName(nsAString& aResult) const
     442                 : {
     443               0 :   return MakeFrameName(NS_LITERAL_STRING("HTMLVideo"), aResult);
     444                 : }
     445                 : #endif
     446                 : 
     447               0 : nsSize nsVideoFrame::ComputeSize(nsRenderingContext *aRenderingContext,
     448                 :                                      nsSize aCBSize,
     449                 :                                      nscoord aAvailableWidth,
     450                 :                                      nsSize aMargin,
     451                 :                                      nsSize aBorder,
     452                 :                                      nsSize aPadding,
     453                 :                                      bool aShrinkWrap)
     454                 : {
     455               0 :   nsSize size = GetVideoIntrinsicSize(aRenderingContext);
     456                 : 
     457               0 :   IntrinsicSize intrinsicSize;
     458               0 :   intrinsicSize.width.SetCoordValue(size.width);
     459               0 :   intrinsicSize.height.SetCoordValue(size.height);
     460                 : 
     461               0 :   nsSize& intrinsicRatio = size; // won't actually be used
     462                 : 
     463                 :   return nsLayoutUtils::ComputeSizeWithIntrinsicDimensions(aRenderingContext,
     464                 :                                                            this,
     465                 :                                                            intrinsicSize,
     466                 :                                                            intrinsicRatio,
     467                 :                                                            aCBSize,
     468                 :                                                            aMargin,
     469                 :                                                            aBorder,
     470               0 :                                                            aPadding);
     471                 : }
     472                 : 
     473               0 : nscoord nsVideoFrame::GetMinWidth(nsRenderingContext *aRenderingContext)
     474                 : {
     475               0 :   nscoord result = GetVideoIntrinsicSize(aRenderingContext).width;
     476               0 :   DISPLAY_MIN_WIDTH(this, result);
     477               0 :   return result;
     478                 : }
     479                 : 
     480               0 : nscoord nsVideoFrame::GetPrefWidth(nsRenderingContext *aRenderingContext)
     481                 : {
     482               0 :   nscoord result = GetVideoIntrinsicSize(aRenderingContext).width;
     483               0 :   DISPLAY_PREF_WIDTH(this, result);
     484               0 :   return result;
     485                 : }
     486                 : 
     487               0 : nsSize nsVideoFrame::GetIntrinsicRatio()
     488                 : {
     489               0 :   return GetVideoIntrinsicSize(nsnull);
     490                 : }
     491                 : 
     492               0 : bool nsVideoFrame::ShouldDisplayPoster()
     493                 : {
     494               0 :   if (!HasVideoElement())
     495               0 :     return false;
     496                 : 
     497               0 :   nsHTMLVideoElement* element = static_cast<nsHTMLVideoElement*>(GetContent());
     498               0 :   if (element->GetPlayedOrSeeked() && HasVideoData())
     499               0 :     return false;
     500                 : 
     501               0 :   nsCOMPtr<nsIImageLoadingContent> imgContent = do_QueryInterface(mPosterImage);
     502               0 :   NS_ENSURE_TRUE(imgContent, false);
     503                 : 
     504               0 :   nsCOMPtr<imgIRequest> request;
     505               0 :   nsresult res = imgContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
     506               0 :                                         getter_AddRefs(request));
     507               0 :   if (NS_FAILED(res) || !request) {
     508               0 :     return false;
     509                 :   }
     510                 : 
     511               0 :   PRUint32 status = 0;
     512               0 :   res = request->GetImageStatus(&status);
     513               0 :   if (NS_FAILED(res) || (status & imgIRequest::STATUS_ERROR))
     514               0 :     return false;
     515                 : 
     516               0 :   return true;
     517                 : }
     518                 : 
     519                 : nsSize
     520               0 : nsVideoFrame::GetVideoIntrinsicSize(nsRenderingContext *aRenderingContext)
     521                 : {
     522                 :   // Defaulting size to 300x150 if no size given.
     523               0 :   nsIntSize size(300, 150);
     524                 : 
     525               0 :   if (ShouldDisplayPoster()) {
     526                 :     // Use the poster image frame's size.
     527               0 :     nsIFrame *child = mFrames.FirstChild();
     528               0 :     if (child && child->GetType() == nsGkAtoms::imageFrame) {
     529               0 :       nsImageFrame* imageFrame = static_cast<nsImageFrame*>(child);
     530               0 :       nsSize imgsize;
     531               0 :       if (NS_SUCCEEDED(imageFrame->GetIntrinsicImageSize(imgsize))) {
     532               0 :         return imgsize;
     533                 :       }
     534                 :     }
     535                 :   }
     536                 : 
     537               0 :   if (!HasVideoElement()) {
     538               0 :     if (!aRenderingContext || !mFrames.FirstChild()) {
     539                 :       // We just want our intrinsic ratio, but audio elements need no
     540                 :       // intrinsic ratio, so just return "no ratio". Also, if there's
     541                 :       // no controls frame, we prefer to be zero-sized.
     542               0 :       return nsSize(0, 0);
     543                 :     }
     544                 : 
     545                 :     // Ask the controls frame what its preferred height is
     546               0 :     nsBoxLayoutState boxState(PresContext(), aRenderingContext, 0);
     547               0 :     nscoord prefHeight = mFrames.LastChild()->GetPrefSize(boxState).height;
     548               0 :     return nsSize(nsPresContext::CSSPixelsToAppUnits(size.width), prefHeight);
     549                 :   }
     550                 : 
     551               0 :   nsHTMLVideoElement* element = static_cast<nsHTMLVideoElement*>(GetContent());
     552               0 :   size = element->GetVideoSize(size);
     553                 : 
     554                 :   return nsSize(nsPresContext::CSSPixelsToAppUnits(size.width),
     555               0 :                 nsPresContext::CSSPixelsToAppUnits(size.height));
     556                 : }
     557                 : 
     558                 : nsresult
     559               0 : nsVideoFrame::UpdatePosterSource(bool aNotify)
     560                 : {
     561               0 :   NS_ASSERTION(HasVideoElement(), "Only call this on <video> elements.");
     562               0 :   nsHTMLVideoElement* element = static_cast<nsHTMLVideoElement*>(GetContent());
     563                 : 
     564               0 :   nsAutoString posterStr;
     565               0 :   element->GetPoster(posterStr);
     566                 :   nsresult res = mPosterImage->SetAttr(kNameSpaceID_None,
     567                 :                                        nsGkAtoms::src,
     568                 :                                        posterStr,
     569               0 :                                        aNotify);
     570               0 :   NS_ENSURE_SUCCESS(res,res);
     571               0 :   return NS_OK;
     572                 : }
     573                 : 
     574                 : NS_IMETHODIMP
     575               0 : nsVideoFrame::AttributeChanged(PRInt32 aNameSpaceID,
     576                 :                                nsIAtom* aAttribute,
     577                 :                                PRInt32 aModType)
     578                 : {
     579               0 :   if (aAttribute == nsGkAtoms::poster && HasVideoElement()) {
     580               0 :     nsresult res = UpdatePosterSource(true);
     581               0 :     NS_ENSURE_SUCCESS(res,res);
     582                 :   }
     583                 :   return nsContainerFrame::AttributeChanged(aNameSpaceID,
     584                 :                                             aAttribute,
     585               0 :                                             aModType);
     586                 : }
     587                 : 
     588               0 : bool nsVideoFrame::HasVideoElement() {
     589               0 :   nsCOMPtr<nsIDOMHTMLVideoElement> videoDomElement = do_QueryInterface(mContent);
     590               0 :   return videoDomElement != nsnull;
     591                 : }
     592                 : 
     593               0 : bool nsVideoFrame::HasVideoData()
     594                 : {
     595               0 :   if (!HasVideoElement())
     596               0 :     return false;
     597               0 :   nsHTMLVideoElement* element = static_cast<nsHTMLVideoElement*>(GetContent());
     598               0 :   nsIntSize size = element->GetVideoSize(nsIntSize(0,0));
     599               0 :   return size != nsIntSize(0,0);
     600                 : }

Generated by: LCOV version 1.7