• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007, 2008, 2009, 2010 Apple Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "config.h"
27 
28 #include "core/rendering/RenderVideo.h"
29 
30 #include "core/HTMLNames.h"
31 #include "core/dom/Document.h"
32 #include "core/frame/FrameView.h"
33 #include "core/frame/LocalFrame.h"
34 #include "core/html/HTMLVideoElement.h"
35 #include "core/paint/VideoPainter.h"
36 #include "core/rendering/PaintInfo.h"
37 #include "core/rendering/RenderFullScreen.h"
38 #include "platform/graphics/media/MediaPlayer.h"
39 #include "public/platform/WebLayer.h"
40 
41 namespace blink {
42 
43 using namespace HTMLNames;
44 
RenderVideo(HTMLVideoElement * video)45 RenderVideo::RenderVideo(HTMLVideoElement* video)
46     : RenderMedia(video)
47 {
48     setIntrinsicSize(calculateIntrinsicSize());
49 }
50 
~RenderVideo()51 RenderVideo::~RenderVideo()
52 {
53 }
54 
defaultSize()55 IntSize RenderVideo::defaultSize()
56 {
57     return IntSize(defaultWidth, defaultHeight);
58 }
59 
intrinsicSizeChanged()60 void RenderVideo::intrinsicSizeChanged()
61 {
62     if (videoElement()->shouldDisplayPosterImage())
63         RenderMedia::intrinsicSizeChanged();
64     updateIntrinsicSize();
65 }
66 
updateIntrinsicSize()67 void RenderVideo::updateIntrinsicSize()
68 {
69     LayoutSize size = calculateIntrinsicSize();
70     size.scale(style()->effectiveZoom());
71 
72     // Never set the element size to zero when in a media document.
73     if (size.isEmpty() && node()->ownerDocument() && node()->ownerDocument()->isMediaDocument())
74         return;
75 
76     if (size == intrinsicSize())
77         return;
78 
79     setIntrinsicSize(size);
80     setPreferredLogicalWidthsDirty();
81     setNeedsLayoutAndFullPaintInvalidation();
82 }
83 
calculateIntrinsicSize()84 LayoutSize RenderVideo::calculateIntrinsicSize()
85 {
86     HTMLVideoElement* video = videoElement();
87 
88     // Spec text from 4.8.6
89     //
90     // The intrinsic width of a video element's playback area is the intrinsic width
91     // of the video resource, if that is available; otherwise it is the intrinsic
92     // width of the poster frame, if that is available; otherwise it is 300 CSS pixels.
93     //
94     // The intrinsic height of a video element's playback area is the intrinsic height
95     // of the video resource, if that is available; otherwise it is the intrinsic
96     // height of the poster frame, if that is available; otherwise it is 150 CSS pixels.
97     WebMediaPlayer* webMediaPlayer = mediaElement()->webMediaPlayer();
98     if (webMediaPlayer && video->readyState() >= HTMLVideoElement::HAVE_METADATA) {
99         IntSize size = webMediaPlayer->naturalSize();
100         if (!size.isEmpty())
101             return size;
102     }
103 
104     if (video->shouldDisplayPosterImage() && !m_cachedImageSize.isEmpty() && !imageResource()->errorOccurred())
105         return m_cachedImageSize;
106 
107     // <video> in standalone media documents should not use the default 300x150
108     // size since they also have audio-only files. By setting the intrinsic
109     // size to 300x1 the video will resize itself in these cases, and audio will
110     // have the correct height (it needs to be > 0 for controls to render properly).
111     if (video->ownerDocument() && video->ownerDocument()->isMediaDocument())
112         return LayoutSize(defaultSize().width(), 1);
113 
114     return defaultSize();
115 }
116 
imageChanged(WrappedImagePtr newImage,const IntRect * rect)117 void RenderVideo::imageChanged(WrappedImagePtr newImage, const IntRect* rect)
118 {
119     RenderMedia::imageChanged(newImage, rect);
120 
121     // Cache the image intrinsic size so we can continue to use it to draw the image correctly
122     // even if we know the video intrinsic size but aren't able to draw video frames yet
123     // (we don't want to scale the poster to the video size without keeping aspect ratio).
124     if (videoElement()->shouldDisplayPosterImage())
125         m_cachedImageSize = intrinsicSize();
126 
127     // The intrinsic size is now that of the image, but in case we already had the
128     // intrinsic size of the video we call this here to restore the video size.
129     updateIntrinsicSize();
130 }
131 
videoBox() const132 IntRect RenderVideo::videoBox() const
133 {
134     const LayoutSize* overriddenIntrinsicSize = 0;
135     if (videoElement()->shouldDisplayPosterImage())
136         overriddenIntrinsicSize = &m_cachedImageSize;
137 
138     return pixelSnappedIntRect(replacedContentRect(overriddenIntrinsicSize));
139 }
140 
shouldDisplayVideo() const141 bool RenderVideo::shouldDisplayVideo() const
142 {
143     return !videoElement()->shouldDisplayPosterImage();
144 }
145 
paintReplaced(PaintInfo & paintInfo,const LayoutPoint & paintOffset)146 void RenderVideo::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
147 {
148     VideoPainter(*this).paintReplaced(paintInfo, paintOffset);
149 }
150 
acceleratedRenderingInUse()151 bool RenderVideo::acceleratedRenderingInUse()
152 {
153     WebLayer* webLayer = mediaElement()->platformLayer();
154     return webLayer && !webLayer->isOrphan();
155 }
156 
layout()157 void RenderVideo::layout()
158 {
159     updatePlayer();
160     RenderMedia::layout();
161 }
162 
videoElement() const163 HTMLVideoElement* RenderVideo::videoElement() const
164 {
165     return toHTMLVideoElement(node());
166 }
167 
updateFromElement()168 void RenderVideo::updateFromElement()
169 {
170     RenderMedia::updateFromElement();
171     updatePlayer();
172 }
173 
updatePlayer()174 void RenderVideo::updatePlayer()
175 {
176     updateIntrinsicSize();
177 
178     WebMediaPlayer* mediaPlayer = mediaElement()->webMediaPlayer();
179     if (!mediaPlayer)
180         return;
181 
182     if (!videoElement()->isActive())
183         return;
184 
185     videoElement()->setNeedsCompositingUpdate();
186 }
187 
computeReplacedLogicalWidth(ShouldComputePreferred shouldComputePreferred) const188 LayoutUnit RenderVideo::computeReplacedLogicalWidth(ShouldComputePreferred shouldComputePreferred) const
189 {
190     return RenderReplaced::computeReplacedLogicalWidth(shouldComputePreferred);
191 }
192 
computeReplacedLogicalHeight() const193 LayoutUnit RenderVideo::computeReplacedLogicalHeight() const
194 {
195     return RenderReplaced::computeReplacedLogicalHeight();
196 }
197 
minimumReplacedHeight() const198 LayoutUnit RenderVideo::minimumReplacedHeight() const
199 {
200     return RenderReplaced::minimumReplacedHeight();
201 }
202 
supportsAcceleratedRendering() const203 bool RenderVideo::supportsAcceleratedRendering() const
204 {
205     return !!mediaElement()->platformLayer();
206 }
207 
rendererPlaceholder(const RenderObject * renderer)208 static const RenderBlock* rendererPlaceholder(const RenderObject* renderer)
209 {
210     RenderObject* parent = renderer->parent();
211     if (!parent)
212         return 0;
213 
214     RenderFullScreen* fullScreen = parent->isRenderFullScreen() ? toRenderFullScreen(parent) : 0;
215     if (!fullScreen)
216         return 0;
217 
218     return fullScreen->placeholder();
219 }
220 
offsetLeft() const221 LayoutUnit RenderVideo::offsetLeft() const
222 {
223     if (const RenderBlock* block = rendererPlaceholder(this))
224         return block->offsetLeft();
225     return RenderMedia::offsetLeft();
226 }
227 
offsetTop() const228 LayoutUnit RenderVideo::offsetTop() const
229 {
230     if (const RenderBlock* block = rendererPlaceholder(this))
231         return block->offsetTop();
232     return RenderMedia::offsetTop();
233 }
234 
offsetWidth() const235 LayoutUnit RenderVideo::offsetWidth() const
236 {
237     if (const RenderBlock* block = rendererPlaceholder(this))
238         return block->offsetWidth();
239     return RenderMedia::offsetWidth();
240 }
241 
offsetHeight() const242 LayoutUnit RenderVideo::offsetHeight() const
243 {
244     if (const RenderBlock* block = rendererPlaceholder(this))
245         return block->offsetHeight();
246     return RenderMedia::offsetHeight();
247 }
248 
additionalCompositingReasons() const249 CompositingReasons RenderVideo::additionalCompositingReasons() const
250 {
251     if (RuntimeEnabledFeatures::overlayFullscreenVideoEnabled()) {
252         HTMLMediaElement* media = toHTMLMediaElement(node());
253         if (media->isFullscreen())
254             return CompositingReasonVideo;
255     }
256 
257     if (shouldDisplayVideo() && supportsAcceleratedRendering())
258         return CompositingReasonVideo;
259 
260     return CompositingReasonNone;
261 }
262 
263 } // namespace blink
264