Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(720)

Side by Side Diff: Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp

Issue 13642009: WebCore: Remove PLATFORM(WIN) files we do not use. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2007, 2008, 2009, 2010, 2011 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 #if ENABLE(VIDEO)
29 #include "MediaPlayerPrivateQuickTimeVisualContext.h"
30
31 #include "Cookie.h"
32 #include "CookieJar.h"
33 #include "DocumentLoader.h"
34 #include "Frame.h"
35 #include "FrameView.h"
36 #include "GraphicsContext.h"
37 #include "KURL.h"
38 #include "MediaPlayerPrivateTaskTimer.h"
39 #include "Page.h"
40 #include "QTCFDictionary.h"
41 #include "QTDecompressionSession.h"
42 #include "QTMovie.h"
43 #include "QTMovieTask.h"
44 #include "QTMovieVisualContext.h"
45 #include "ScrollView.h"
46 #include "Settings.h"
47 #include "SoftLinking.h"
48 #include "TimeRanges.h"
49 #include "Timer.h"
50 #include <AssertMacros.h>
51 #include <CoreGraphics/CGAffineTransform.h>
52 #include <CoreGraphics/CGContext.h>
53 #include <QuartzCore/CATransform3D.h>
54 #include <Wininet.h>
55 #include <wtf/CurrentTime.h>
56 #include <wtf/HashSet.h>
57 #include <wtf/MainThread.h>
58 #include <wtf/MathExtras.h>
59 #include <wtf/StdLibExtras.h>
60 #include <wtf/text/StringBuilder.h>
61 #include <wtf/text/StringHash.h>
62
63 #if USE(ACCELERATED_COMPOSITING)
64 #include "PlatformCALayer.h"
65 #include "WKCAImageQueue.h"
66 #endif
67
68 using namespace std;
69
70 namespace WebCore {
71
72 static CGImageRef CreateCGImageFromPixelBuffer(QTPixelBuffer buffer);
73 static bool requiredDllsAvailable();
74
75 SOFT_LINK_LIBRARY(Wininet)
76 SOFT_LINK(Wininet, InternetSetCookieExW, DWORD, WINAPI, (LPCWSTR lpszUrl, LPCWST R lpszCookieName, LPCWSTR lpszCookieData, DWORD dwFlags, DWORD_PTR dwReserved), (lpszUrl, lpszCookieName, lpszCookieData, dwFlags, dwReserved))
77
78 // Interface declaration for MediaPlayerPrivateQuickTimeVisualContext's QTMovieC lient aggregate
79 class MediaPlayerPrivateQuickTimeVisualContext::MovieClient : public QTMovieClie nt {
80 public:
81 MovieClient(MediaPlayerPrivateQuickTimeVisualContext* parent) : m_parent(par ent) {}
82 virtual ~MovieClient() { m_parent = 0; }
83 virtual void movieEnded(QTMovie*);
84 virtual void movieLoadStateChanged(QTMovie*);
85 virtual void movieTimeChanged(QTMovie*);
86 private:
87 MediaPlayerPrivateQuickTimeVisualContext* m_parent;
88 };
89
90 #if USE(ACCELERATED_COMPOSITING)
91 class MediaPlayerPrivateQuickTimeVisualContext::LayerClient : public PlatformCAL ayerClient {
92 public:
93 LayerClient(MediaPlayerPrivateQuickTimeVisualContext* parent) : m_parent(par ent) {}
94 virtual ~LayerClient() { m_parent = 0; }
95
96 private:
97 virtual void platformCALayerLayoutSublayersOfLayer(PlatformCALayer*);
98 virtual bool platformCALayerRespondsToLayoutChanges() const { return true; }
99
100 virtual void platformCALayerAnimationStarted(CFTimeInterval beginTime) { }
101 virtual GraphicsLayer::CompositingCoordinatesOrientation platformCALayerCont entsOrientation() const { return GraphicsLayer::CompositingCoordinatesBottomUp; }
102 virtual void platformCALayerPaintContents(GraphicsContext&, const IntRect& i nClip) { }
103 virtual bool platformCALayerShowDebugBorders() const { return false; }
104 virtual bool platformCALayerShowRepaintCounter(PlatformCALayer*) const { ret urn false; }
105 virtual int platformCALayerIncrementRepaintCount() { return 0; }
106
107 virtual bool platformCALayerContentsOpaque() const { return false; }
108 virtual bool platformCALayerDrawsContent() const { return false; }
109 virtual void platformCALayerLayerDidDisplay(PlatformLayer*) { }
110 virtual void platformCALayerDidCreateTiles(const Vector<FloatRect>&) { }
111 virtual float platformCALayerDeviceScaleFactor() { return 1; }
112
113 MediaPlayerPrivateQuickTimeVisualContext* m_parent;
114 };
115
116 void MediaPlayerPrivateQuickTimeVisualContext::LayerClient::platformCALayerLayou tSublayersOfLayer(PlatformCALayer* layer)
117 {
118 ASSERT(m_parent);
119 ASSERT(m_parent->m_transformLayer == layer);
120
121 FloatSize parentSize = layer->bounds().size();
122 FloatSize naturalSize = m_parent->naturalSize();
123
124 // Calculate the ratio of these two sizes and use that ratio to scale the qt VideoLayer:
125 FloatSize ratio(parentSize.width() / naturalSize.width(), parentSize.height( ) / naturalSize.height());
126
127 int videoWidth = 0;
128 int videoHeight = 0;
129 m_parent->m_movie->getNaturalSize(videoWidth, videoHeight);
130 FloatRect videoBounds(0, 0, videoWidth * ratio.width(), videoHeight * ratio. height());
131 FloatPoint3D videoAnchor = m_parent->m_qtVideoLayer->anchorPoint();
132
133 // Calculate the new position based on the parent's size:
134 FloatPoint position(parentSize.width() * 0.5 - videoBounds.width() * (0.5 - videoAnchor.x()),
135 parentSize.height() * 0.5 - videoBounds.height() * (0.5 - videoAnchor.y( )));
136
137 m_parent->m_qtVideoLayer->setBounds(videoBounds);
138 m_parent->m_qtVideoLayer->setPosition(position);
139 }
140 #endif
141
142 class MediaPlayerPrivateQuickTimeVisualContext::VisualContextClient : public QTM ovieVisualContextClient {
143 public:
144 VisualContextClient(MediaPlayerPrivateQuickTimeVisualContext* parent) : m_pa rent(parent) {}
145 virtual ~VisualContextClient() { m_parent = 0; }
146 void imageAvailableForTime(const QTCVTimeStamp*);
147 static void retrieveCurrentImageProc(void*);
148 private:
149 MediaPlayerPrivateQuickTimeVisualContext* m_parent;
150 };
151
152 PassOwnPtr<MediaPlayerPrivateInterface> MediaPlayerPrivateQuickTimeVisualContext ::create(MediaPlayer* player)
153 {
154 return adoptPtr(new MediaPlayerPrivateQuickTimeVisualContext(player));
155 }
156
157 void MediaPlayerPrivateQuickTimeVisualContext::registerMediaEngine(MediaEngineRe gistrar registrar)
158 {
159 if (isAvailable())
160 registrar(create, getSupportedTypes, supportsType, 0, 0, 0);
161 }
162
163 MediaPlayerPrivateQuickTimeVisualContext::MediaPlayerPrivateQuickTimeVisualConte xt(MediaPlayer* player)
164 : m_player(player)
165 , m_seekTo(-1)
166 , m_seekTimer(this, &MediaPlayerPrivateQuickTimeVisualContext::seekTimerFire d)
167 , m_visualContextTimer(this, &MediaPlayerPrivateQuickTimeVisualContext::visu alContextTimerFired)
168 , m_networkState(MediaPlayer::Empty)
169 , m_readyState(MediaPlayer::HaveNothing)
170 , m_enabledTrackCount(0)
171 , m_totalTrackCount(0)
172 , m_hasUnsupportedTracks(false)
173 , m_startedPlaying(false)
174 , m_isStreaming(false)
175 , m_visible(false)
176 , m_newFrameAvailable(false)
177 , m_movieClient(adoptPtr(new MediaPlayerPrivateQuickTimeVisualContext::Movie Client(this)))
178 #if USE(ACCELERATED_COMPOSITING)
179 , m_layerClient(adoptPtr(new MediaPlayerPrivateQuickTimeVisualContext::Layer Client(this)))
180 , m_movieTransform(CGAffineTransformIdentity)
181 #endif
182 , m_visualContextClient(adoptPtr(new MediaPlayerPrivateQuickTimeVisualContex t::VisualContextClient(this)))
183 , m_delayingLoad(false)
184 , m_privateBrowsing(false)
185 , m_preload(MediaPlayer::Auto)
186 , m_maxTimeLoadedAtLastDidLoadingProgress(0)
187 {
188 }
189
190 MediaPlayerPrivateQuickTimeVisualContext::~MediaPlayerPrivateQuickTimeVisualCont ext()
191 {
192 tearDownVideoRendering();
193 cancelCallOnMainThread(&VisualContextClient::retrieveCurrentImageProc, this) ;
194 }
195
196 bool MediaPlayerPrivateQuickTimeVisualContext::supportsFullscreen() const
197 {
198 #if USE(ACCELERATED_COMPOSITING)
199 Document* document = m_player->mediaPlayerClient()->mediaPlayerOwningDocumen t();
200 if (document && document->settings())
201 return document->settings()->acceleratedCompositingEnabled();
202 #endif
203 return false;
204 }
205
206 PlatformMedia MediaPlayerPrivateQuickTimeVisualContext::platformMedia() const
207 {
208 PlatformMedia p;
209 p.type = PlatformMedia::QTMovieVisualContextType;
210 p.media.qtMovieVisualContext = m_visualContext.get();
211 return p;
212 }
213 #if USE(ACCELERATED_COMPOSITING)
214
215 PlatformLayer* MediaPlayerPrivateQuickTimeVisualContext::platformLayer() const
216 {
217 return m_transformLayer ? m_transformLayer->platformLayer() : 0;
218 }
219 #endif
220
221 String MediaPlayerPrivateQuickTimeVisualContext::rfc2616DateStringFromTime(CFAbs oluteTime time)
222 {
223 static const char* const dayStrings[] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
224 static const char* const monthStrings[] = { "Jan", "Feb", "Mar", "Apr", "May ", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
225 static const CFStringRef dateFormatString = CFSTR("%s, %02d %s %04d %02d:%02 d:%02d GMT");
226 static CFTimeZoneRef gmtTimeZone;
227 if (!gmtTimeZone)
228 gmtTimeZone = CFTimeZoneCopyDefault();
229
230 CFGregorianDate dateValue = CFAbsoluteTimeGetGregorianDate(time, gmtTimeZone );
231 if (!CFGregorianDateIsValid(dateValue, kCFGregorianAllUnits))
232 return String();
233
234 time = CFGregorianDateGetAbsoluteTime(dateValue, gmtTimeZone);
235 SInt32 day = CFAbsoluteTimeGetDayOfWeek(time, 0);
236
237 RetainPtr<CFStringRef> dateCFString(AdoptCF, CFStringCreateWithFormat(0, 0, dateFormatString, dayStrings[day - 1], dateValue.day,
238 monthStrings[dateValue.month - 1], dateValue.year, dateValue.hour, dateV alue.minute, (int)dateValue.second));
239 return dateCFString.get();
240 }
241
242 static void addCookieParam(StringBuilder& cookieBuilder, const String& name, con st String& value)
243 {
244 if (name.isEmpty())
245 return;
246
247 // If this isn't the first parameter added, terminate the previous one.
248 if (cookieBuilder.length())
249 cookieBuilder.append("; ");
250
251 // Add parameter name, and value if there is one.
252 cookieBuilder.append(name);
253 if (!value.isEmpty()) {
254 cookieBuilder.append('=');
255 cookieBuilder.append(value);
256 }
257 }
258
259 void MediaPlayerPrivateQuickTimeVisualContext::setUpCookiesForQuickTime(const St ring& url)
260 {
261 // WebCore loaded the page with the movie URL with CFNetwork but QuickTime w ill
262 // use WinINet to download the movie, so we need to copy any cookies needed to
263 // download the movie into WinInet before asking QuickTime to open it.
264 Document* document = m_player->mediaPlayerClient()->mediaPlayerOwningDocumen t();
265 Frame* frame = document ? document->frame() : 0;
266 if (!frame || !frame->page() || !frame->page()->settings()->cookieEnabled())
267 return;
268
269 KURL movieURL = KURL(KURL(), url);
270 Vector<Cookie> documentCookies;
271 if (!getRawCookies(frame->document(), movieURL, documentCookies))
272 return;
273
274 for (size_t ndx = 0; ndx < documentCookies.size(); ndx++) {
275 const Cookie& cookie = documentCookies[ndx];
276
277 if (cookie.name.isEmpty())
278 continue;
279
280 // Build up the cookie string with as much information as we can get so WinINet
281 // knows what to do with it.
282 StringBuilder cookieBuilder;
283 addCookieParam(cookieBuilder, cookie.name, cookie.value);
284 addCookieParam(cookieBuilder, "path", cookie.path);
285 if (cookie.expires)
286 addCookieParam(cookieBuilder, "expires", rfc2616DateStringFromTime(c ookie.expires));
287 if (cookie.httpOnly)
288 addCookieParam(cookieBuilder, "httpOnly", String());
289 cookieBuilder.append(';');
290
291 String cookieURL;
292 if (!cookie.domain.isEmpty()) {
293 StringBuilder urlBuilder;
294
295 urlBuilder.append(movieURL.protocol());
296 urlBuilder.append("://");
297 if (cookie.domain[0] == '.')
298 urlBuilder.append(cookie.domain.substring(1));
299 else
300 urlBuilder.append(cookie.domain);
301 if (cookie.path.length() > 1)
302 urlBuilder.append(cookie.path);
303
304 cookieURL = urlBuilder.toString();
305 } else
306 cookieURL = movieURL;
307
308 String string = cookieBuilder.toString();
309 InternetSetCookieExW(cookieURL.charactersWithNullTermination(), 0, strin g.charactersWithNullTermination(), 0, 0);
310 }
311 }
312
313 static void disableComponentsOnce()
314 {
315 static bool sComponentsDisabled = false;
316 if (sComponentsDisabled)
317 return;
318 sComponentsDisabled = true;
319
320 uint32_t componentsToDisable[][5] = {
321 {'eat ', 'TEXT', 'text', 0, 0},
322 {'eat ', 'TXT ', 'text', 0, 0},
323 {'eat ', 'utxt', 'text', 0, 0},
324 {'eat ', 'TEXT', 'tx3g', 0, 0},
325 };
326
327 for (size_t i = 0; i < WTF_ARRAY_LENGTH(componentsToDisable); ++i)
328 QTMovie::disableComponent(componentsToDisable[i]);
329 }
330
331 void MediaPlayerPrivateQuickTimeVisualContext::resumeLoad()
332 {
333 m_delayingLoad = false;
334
335 if (!m_movieURL.isEmpty())
336 loadInternal(m_movieURL);
337 }
338
339 void MediaPlayerPrivateQuickTimeVisualContext::load(const String& url)
340 {
341 m_movieURL = url;
342
343 if (m_preload == MediaPlayer::None) {
344 m_delayingLoad = true;
345 return;
346 }
347
348 loadInternal(url);
349 }
350
351 void MediaPlayerPrivateQuickTimeVisualContext::loadInternal(const String& url)
352 {
353 if (!QTMovie::initializeQuickTime()) {
354 // FIXME: is this the right error to return?
355 m_networkState = MediaPlayer::DecodeError;
356 m_player->networkStateChanged();
357 return;
358 }
359
360 disableComponentsOnce();
361
362 // Initialize the task timer.
363 MediaPlayerPrivateTaskTimer::initialize();
364
365 if (m_networkState != MediaPlayer::Loading) {
366 m_networkState = MediaPlayer::Loading;
367 m_player->networkStateChanged();
368 }
369 if (m_readyState != MediaPlayer::HaveNothing) {
370 m_readyState = MediaPlayer::HaveNothing;
371 m_player->readyStateChanged();
372 }
373 cancelSeek();
374
375 setUpCookiesForQuickTime(url);
376
377 m_movie = adoptRef(new QTMovie(m_movieClient.get()));
378
379 m_movie->load(url.characters(), url.length(), m_player->preservesPitch());
380 m_movie->setVolume(m_player->volume());
381 }
382
383 void MediaPlayerPrivateQuickTimeVisualContext::prepareToPlay()
384 {
385 if (!m_movie || m_delayingLoad)
386 resumeLoad();
387 }
388
389 void MediaPlayerPrivateQuickTimeVisualContext::play()
390 {
391 if (!m_movie)
392 return;
393 m_startedPlaying = true;
394
395 m_movie->play();
396 m_visualContextTimer.startRepeating(1.0 / 30);
397 }
398
399 void MediaPlayerPrivateQuickTimeVisualContext::pause()
400 {
401 if (!m_movie)
402 return;
403 m_startedPlaying = false;
404
405 m_movie->pause();
406 m_visualContextTimer.stop();
407 }
408
409 float MediaPlayerPrivateQuickTimeVisualContext::duration() const
410 {
411 if (!m_movie)
412 return 0;
413 return m_movie->duration();
414 }
415
416 float MediaPlayerPrivateQuickTimeVisualContext::currentTime() const
417 {
418 if (!m_movie)
419 return 0;
420 return m_movie->currentTime();
421 }
422
423 void MediaPlayerPrivateQuickTimeVisualContext::seek(float time)
424 {
425 cancelSeek();
426
427 if (!m_movie)
428 return;
429
430 if (time > duration())
431 time = duration();
432
433 m_seekTo = time;
434 if (maxTimeLoaded() >= m_seekTo)
435 doSeek();
436 else
437 m_seekTimer.start(0, 0.5f);
438 }
439
440 void MediaPlayerPrivateQuickTimeVisualContext::doSeek()
441 {
442 float oldRate = m_movie->rate();
443 if (oldRate)
444 m_movie->setRate(0);
445 m_movie->setCurrentTime(m_seekTo);
446 float timeAfterSeek = currentTime();
447 // restore playback only if not at end, othewise QTMovie will loop
448 if (oldRate && timeAfterSeek < duration())
449 m_movie->setRate(oldRate);
450 cancelSeek();
451 }
452
453 void MediaPlayerPrivateQuickTimeVisualContext::cancelSeek()
454 {
455 m_seekTo = -1;
456 m_seekTimer.stop();
457 }
458
459 void MediaPlayerPrivateQuickTimeVisualContext::seekTimerFired(Timer<MediaPlayerP rivateQuickTimeVisualContext>*)
460 {
461 if (!m_movie || !seeking() || currentTime() == m_seekTo) {
462 cancelSeek();
463 updateStates();
464 m_player->timeChanged();
465 return;
466 }
467
468 if (maxTimeLoaded() >= m_seekTo)
469 doSeek();
470 else {
471 MediaPlayer::NetworkState state = networkState();
472 if (state == MediaPlayer::Empty || state == MediaPlayer::Loaded) {
473 cancelSeek();
474 updateStates();
475 m_player->timeChanged();
476 }
477 }
478 }
479
480 bool MediaPlayerPrivateQuickTimeVisualContext::paused() const
481 {
482 if (!m_movie)
483 return true;
484 return (!m_movie->rate());
485 }
486
487 bool MediaPlayerPrivateQuickTimeVisualContext::seeking() const
488 {
489 if (!m_movie)
490 return false;
491 return m_seekTo >= 0;
492 }
493
494 IntSize MediaPlayerPrivateQuickTimeVisualContext::naturalSize() const
495 {
496 if (!m_movie)
497 return IntSize();
498 int width;
499 int height;
500 m_movie->getNaturalSize(width, height);
501 #if USE(ACCELERATED_COMPOSITING)
502 CGSize originalSize = {width, height};
503 CGSize transformedSize = CGSizeApplyAffineTransform(originalSize, m_movieTra nsform);
504 return IntSize(abs(transformedSize.width), abs(transformedSize.height));
505 #else
506 return IntSize(width, height);
507 #endif
508 }
509
510 bool MediaPlayerPrivateQuickTimeVisualContext::hasVideo() const
511 {
512 if (!m_movie)
513 return false;
514 return m_movie->hasVideo();
515 }
516
517 bool MediaPlayerPrivateQuickTimeVisualContext::hasAudio() const
518 {
519 if (!m_movie)
520 return false;
521 return m_movie->hasAudio();
522 }
523
524 void MediaPlayerPrivateQuickTimeVisualContext::setVolume(float volume)
525 {
526 if (!m_movie)
527 return;
528 m_movie->setVolume(volume);
529 }
530
531 void MediaPlayerPrivateQuickTimeVisualContext::setRate(float rate)
532 {
533 if (!m_movie)
534 return;
535
536 // Do not call setRate(...) unless we have started playing; otherwise
537 // QuickTime's VisualContext can get wedged waiting for a rate change
538 // call which will never come.
539 if (m_startedPlaying)
540 m_movie->setRate(rate);
541 }
542
543 void MediaPlayerPrivateQuickTimeVisualContext::setPreservesPitch(bool preservesP itch)
544 {
545 if (!m_movie)
546 return;
547 m_movie->setPreservesPitch(preservesPitch);
548 }
549
550 bool MediaPlayerPrivateQuickTimeVisualContext::hasClosedCaptions() const
551 {
552 if (!m_movie)
553 return false;
554 return m_movie->hasClosedCaptions();
555 }
556
557 void MediaPlayerPrivateQuickTimeVisualContext::setClosedCaptionsVisible(bool vis ible)
558 {
559 if (!m_movie)
560 return;
561 m_movie->setClosedCaptionsVisible(visible);
562 }
563
564 PassRefPtr<TimeRanges> MediaPlayerPrivateQuickTimeVisualContext::buffered() cons t
565 {
566 RefPtr<TimeRanges> timeRanges = TimeRanges::create();
567 float loaded = maxTimeLoaded();
568 // rtsp streams are not buffered
569 if (!m_isStreaming && loaded > 0)
570 timeRanges->add(0, loaded);
571 return timeRanges.release();
572 }
573
574 float MediaPlayerPrivateQuickTimeVisualContext::maxTimeSeekable() const
575 {
576 // infinite duration means live stream
577 return !std::isfinite(duration()) ? 0 : maxTimeLoaded();
578 }
579
580 float MediaPlayerPrivateQuickTimeVisualContext::maxTimeLoaded() const
581 {
582 if (!m_movie)
583 return 0;
584 return m_movie->maxTimeLoaded();
585 }
586
587 bool MediaPlayerPrivateQuickTimeVisualContext::didLoadingProgress() const
588 {
589 if (!m_movie || !duration())
590 return false;
591 float currentMaxTimeLoaded = maxTimeLoaded();
592 bool didLoadingProgress = currentMaxTimeLoaded != m_maxTimeLoadedAtLastDidLo adingProgress;
593 m_maxTimeLoadedAtLastDidLoadingProgress = currentMaxTimeLoaded;
594 return didLoadingProgress;
595 }
596
597 unsigned MediaPlayerPrivateQuickTimeVisualContext::totalBytes() const
598 {
599 if (!m_movie)
600 return 0;
601 return m_movie->dataSize();
602 }
603
604 void MediaPlayerPrivateQuickTimeVisualContext::cancelLoad()
605 {
606 if (m_networkState < MediaPlayer::Loading || m_networkState == MediaPlayer:: Loaded)
607 return;
608
609 tearDownVideoRendering();
610
611 // Cancel the load by destroying the movie.
612 m_movie.clear();
613
614 updateStates();
615 }
616
617 void MediaPlayerPrivateQuickTimeVisualContext::updateStates()
618 {
619 MediaPlayer::NetworkState oldNetworkState = m_networkState;
620 MediaPlayer::ReadyState oldReadyState = m_readyState;
621
622 long loadState = m_movie ? m_movie->loadState() : QTMovieLoadStateError;
623
624 if (loadState >= QTMovieLoadStateLoaded && m_readyState < MediaPlayer::HaveM etadata) {
625 m_movie->disableUnsupportedTracks(m_enabledTrackCount, m_totalTrackCount );
626 if (m_player->inMediaDocument()) {
627 if (!m_enabledTrackCount || m_enabledTrackCount != m_totalTrackCount ) {
628 // This is a type of media that we do not handle directly with a <video>
629 // element, eg. QuickTime VR, a movie with a sprite track, etc. Tell the
630 // MediaPlayerClient that we won't support it.
631 sawUnsupportedTracks();
632 return;
633 }
634 } else if (!m_enabledTrackCount)
635 loadState = QTMovieLoadStateError;
636 }
637
638 // "Loaded" is reserved for fully buffered movies, never the case when strea ming
639 if (loadState >= QTMovieLoadStateComplete && !m_isStreaming) {
640 m_networkState = MediaPlayer::Loaded;
641 m_readyState = MediaPlayer::HaveEnoughData;
642 } else if (loadState >= QTMovieLoadStatePlaythroughOK) {
643 m_readyState = MediaPlayer::HaveEnoughData;
644 } else if (loadState >= QTMovieLoadStatePlayable) {
645 // FIXME: This might not work correctly in streaming case, <rdar://probl em/5693967>
646 m_readyState = currentTime() < maxTimeLoaded() ? MediaPlayer::HaveFuture Data : MediaPlayer::HaveCurrentData;
647 } else if (loadState >= QTMovieLoadStateLoaded) {
648 m_readyState = MediaPlayer::HaveMetadata;
649 } else if (loadState > QTMovieLoadStateError) {
650 m_networkState = MediaPlayer::Loading;
651 m_readyState = MediaPlayer::HaveNothing;
652 } else {
653 if (m_player->inMediaDocument()) {
654 // Something went wrong in the loading of media within a standalone file.
655 // This can occur with chained ref movies that eventually resolve to a
656 // file we don't support.
657 sawUnsupportedTracks();
658 return;
659 }
660
661 float loaded = maxTimeLoaded();
662 if (!loaded)
663 m_readyState = MediaPlayer::HaveNothing;
664
665 if (!m_enabledTrackCount)
666 m_networkState = MediaPlayer::FormatError;
667 else {
668 // FIXME: We should differentiate between load/network errors and de code errors <rdar://problem/5605692>
669 if (loaded > 0)
670 m_networkState = MediaPlayer::DecodeError;
671 else
672 m_readyState = MediaPlayer::HaveNothing;
673 }
674 }
675
676 if (isReadyForRendering() && !hasSetUpVideoRendering())
677 setUpVideoRendering();
678
679 if (seeking())
680 m_readyState = MediaPlayer::HaveNothing;
681
682 if (m_networkState != oldNetworkState)
683 m_player->networkStateChanged();
684 if (m_readyState != oldReadyState)
685 m_player->readyStateChanged();
686 }
687
688 bool MediaPlayerPrivateQuickTimeVisualContext::isReadyForRendering() const
689 {
690 return m_readyState >= MediaPlayer::HaveMetadata && m_player->visible();
691 }
692
693 void MediaPlayerPrivateQuickTimeVisualContext::sawUnsupportedTracks()
694 {
695 m_movie->setDisabled(true);
696 m_hasUnsupportedTracks = true;
697 m_player->mediaPlayerClient()->mediaPlayerSawUnsupportedTracks(m_player);
698 }
699
700 void MediaPlayerPrivateQuickTimeVisualContext::didEnd()
701 {
702 if (m_hasUnsupportedTracks)
703 return;
704
705 m_startedPlaying = false;
706
707 updateStates();
708 m_player->timeChanged();
709 }
710
711 void MediaPlayerPrivateQuickTimeVisualContext::setSize(const IntSize& size)
712 {
713 if (m_hasUnsupportedTracks || !m_movie || m_size == size)
714 return;
715 m_size = size;
716 }
717
718 void MediaPlayerPrivateQuickTimeVisualContext::setVisible(bool visible)
719 {
720 if (m_hasUnsupportedTracks || !m_movie || m_visible == visible)
721 return;
722
723 m_visible = visible;
724 if (m_visible) {
725 if (isReadyForRendering())
726 setUpVideoRendering();
727 } else
728 tearDownVideoRendering();
729 }
730
731 void MediaPlayerPrivateQuickTimeVisualContext::paint(GraphicsContext* p, const I ntRect& r)
732 {
733 MediaRenderingMode currentMode = currentRenderingMode();
734
735 if (currentMode == MediaRenderingNone)
736 return;
737
738 if (currentMode == MediaRenderingSoftwareRenderer && !m_visualContext)
739 return;
740
741 QTPixelBuffer buffer = m_visualContext->imageForTime(0);
742 if (buffer.pixelBufferRef()) {
743 #if USE(ACCELERATED_COMPOSITING)
744 if (m_qtVideoLayer) {
745 // We are probably being asked to render the video into a canvas, bu t
746 // there's a good chance the QTPixelBuffer is not ARGB and thus can' t be
747 // drawn using CG. If so, fire up an ICMDecompressionSession and co nvert
748 // the current frame into something which can be rendered by CG.
749 if (!buffer.pixelFormatIs32ARGB() && !buffer.pixelFormatIs32BGRA()) {
750 // The decompression session will only decompress a specific pix elFormat
751 // at a specific width and height; if these differ, the session must be
752 // recreated with the new parameters.
753 if (!m_decompressionSession || !m_decompressionSession->canDecom press(buffer))
754 m_decompressionSession = QTDecompressionSession::create(buff er.pixelFormatType(), buffer.width(), buffer.height());
755 buffer = m_decompressionSession->decompress(buffer);
756 }
757 }
758 #endif
759 CGImageRef image = CreateCGImageFromPixelBuffer(buffer);
760
761 CGContextRef context = p->platformContext();
762 CGContextSaveGState(context);
763 CGContextTranslateCTM(context, r.x(), r.y());
764 CGContextTranslateCTM(context, 0, r.height());
765 CGContextScaleCTM(context, 1, -1);
766 CGContextDrawImage(context, CGRectMake(0, 0, r.width(), r.height()), ima ge);
767 CGContextRestoreGState(context);
768
769 CGImageRelease(image);
770 }
771 paintCompleted(*p, r);
772 }
773
774 void MediaPlayerPrivateQuickTimeVisualContext::paintCompleted(GraphicsContext& c ontext, const IntRect& rect)
775 {
776 m_newFrameAvailable = false;
777 }
778
779 void MediaPlayerPrivateQuickTimeVisualContext::VisualContextClient::retrieveCurr entImageProc(void* refcon)
780 {
781 static_cast<MediaPlayerPrivateQuickTimeVisualContext*>(refcon)->retrieveCurr entImage();
782 }
783
784 void MediaPlayerPrivateQuickTimeVisualContext::VisualContextClient::imageAvailab leForTime(const QTCVTimeStamp* timeStamp)
785 {
786 // This call may come in on another thread, so marshall to the main thread f irst:
787 callOnMainThread(&retrieveCurrentImageProc, m_parent);
788
789 // callOnMainThread must be paired with cancelCallOnMainThread in the destru ctor,
790 // in case this object is deleted before the main thread request is handled.
791 }
792
793 void MediaPlayerPrivateQuickTimeVisualContext::visualContextTimerFired(Timer<Med iaPlayerPrivateQuickTimeVisualContext>*)
794 {
795 if (m_visualContext && m_visualContext->isImageAvailableForTime(0))
796 retrieveCurrentImage();
797 }
798
799 static CFDictionaryRef QTCFDictionaryCreateWithDataCallback(CFAllocatorRef alloc ator, const UInt8* bytes, CFIndex length)
800 {
801 RetainPtr<CFDataRef> data(AdoptCF, CFDataCreateWithBytesNoCopy(allocator, by tes, length, kCFAllocatorNull));
802 if (!data)
803 return 0;
804
805 return reinterpret_cast<CFDictionaryRef>(CFPropertyListCreateFromXMLData(all ocator, data.get(), kCFPropertyListImmutable, 0));
806 }
807
808 static CGImageRef CreateCGImageFromPixelBuffer(QTPixelBuffer buffer)
809 {
810 #if USE(ACCELERATED_COMPOSITING)
811 CGDataProviderRef provider = 0;
812 CGColorSpaceRef colorSpace = 0;
813 CGImageRef image = 0;
814
815 size_t bitsPerComponent = 0;
816 size_t bitsPerPixel = 0;
817 CGImageAlphaInfo alphaInfo = kCGImageAlphaNone;
818
819 if (buffer.pixelFormatIs32BGRA()) {
820 bitsPerComponent = 8;
821 bitsPerPixel = 32;
822 alphaInfo = (CGImageAlphaInfo)(kCGImageAlphaNoneSkipFirst | kCGBitmapByt eOrder32Little);
823 } else if (buffer.pixelFormatIs32ARGB()) {
824 bitsPerComponent = 8;
825 bitsPerPixel = 32;
826 alphaInfo = (CGImageAlphaInfo)(kCGImageAlphaNoneSkipLast | kCGBitmapByte Order32Big);
827 } else {
828 // All other pixel formats are currently unsupported:
829 ASSERT_NOT_REACHED();
830 }
831
832 CGDataProviderDirectAccessCallbacks callbacks = {
833 &QTPixelBuffer::dataProviderGetBytePointerCallback,
834 &QTPixelBuffer::dataProviderReleaseBytePointerCallback,
835 &QTPixelBuffer::dataProviderGetBytesAtPositionCallback,
836 &QTPixelBuffer::dataProviderReleaseInfoCallback,
837 };
838
839 // Colorspace should be device, so that Quartz does not have to do an extra render.
840 colorSpace = CGColorSpaceCreateDeviceRGB();
841 require(colorSpace, Bail);
842
843 provider = CGDataProviderCreateDirectAccess(buffer.pixelBufferRef(), buffer. dataSize(), &callbacks);
844 require(provider, Bail);
845
846 // CGDataProvider does not retain the buffer, but it will release it later, so do an extra retain here:
847 QTPixelBuffer::retainCallback(buffer.pixelBufferRef());
848
849 image = CGImageCreate(buffer.width(), buffer.height(), bitsPerComponent, bit sPerPixel, buffer.bytesPerRow(), colorSpace, alphaInfo, provider, 0, false, kCGR enderingIntentDefault);
850
851 Bail:
852 // Once the image is created we can release our reference to the provider an d the colorspace, they are retained by the image
853 if (provider)
854 CGDataProviderRelease(provider);
855 if (colorSpace)
856 CGColorSpaceRelease(colorSpace);
857
858 return image;
859 #else
860 return 0;
861 #endif
862 }
863
864
865 void MediaPlayerPrivateQuickTimeVisualContext::retrieveCurrentImage()
866 {
867 if (!m_visualContext)
868 return;
869
870 #if USE(ACCELERATED_COMPOSITING)
871 if (m_qtVideoLayer) {
872
873 QTPixelBuffer buffer = m_visualContext->imageForTime(0);
874 if (!buffer.pixelBufferRef())
875 return;
876
877 PlatformCALayer* layer = m_qtVideoLayer.get();
878
879 if (!buffer.lockBaseAddress()) {
880 if (requiredDllsAvailable()) {
881 if (!m_imageQueue) {
882 m_imageQueue = adoptPtr(new WKCAImageQueue(buffer.width(), b uffer.height(), 30));
883 m_imageQueue->setFlags(WKCAImageQueue::Fill, WKCAImageQueue: :Fill);
884 layer->setContents(m_imageQueue->get());
885 }
886
887 // Debug QuickTime links against a non-Debug version of CoreFoun dation, so the
888 // CFDictionary attached to the CVPixelBuffer cannot be directly passed on into the
889 // CAImageQueue without being converted to a non-Debug CFDiction ary. Additionally,
890 // old versions of QuickTime used a non-AAS CoreFoundation, so t he types are not
891 // interchangable even in the release case.
892 RetainPtr<CFDictionaryRef> attachments(AdoptCF, QTCFDictionaryCr eateCopyWithDataCallback(kCFAllocatorDefault, buffer.attachments(), &QTCFDiction aryCreateWithDataCallback));
893 CFTimeInterval imageTime = QTMovieVisualContext::currentHostTime ();
894
895 m_imageQueue->collect();
896
897 uint64_t imageId = m_imageQueue->registerPixelBuffer(buffer.base Address(), buffer.dataSize(), buffer.bytesPerRow(), buffer.width(), buffer.heigh t(), buffer.pixelFormatType(), attachments.get(), 0);
898
899 if (m_imageQueue->insertImage(imageTime, WKCAImageQueue::Buffer, imageId, WKCAImageQueue::Opaque | WKCAImageQueue::Flush, &QTPixelBuffer::imageQ ueueReleaseCallback, buffer.pixelBufferRef())) {
900 // Retain the buffer one extra time so it doesn't dissappear before CAImageQueue decides to release it:
901 QTPixelBuffer::retainCallback(buffer.pixelBufferRef());
902 }
903
904 } else {
905 CGImageRef image = CreateCGImageFromPixelBuffer(buffer);
906 layer->setContents(image);
907 CGImageRelease(image);
908 }
909
910 buffer.unlockBaseAddress();
911 layer->setNeedsCommit();
912 }
913 } else
914 #endif
915 m_player->repaint();
916
917 m_visualContext->task();
918 }
919
920 static HashSet<String> mimeTypeCache()
921 {
922 DEFINE_STATIC_LOCAL(HashSet<String>, typeCache, ());
923 static bool typeListInitialized = false;
924
925 if (!typeListInitialized) {
926 unsigned count = QTMovie::countSupportedTypes();
927 for (unsigned n = 0; n < count; n++) {
928 const UChar* character;
929 unsigned len;
930 QTMovie::getSupportedType(n, character, len);
931 if (len)
932 typeCache.add(String(character, len));
933 }
934
935 typeListInitialized = true;
936 }
937
938 return typeCache;
939 }
940
941 static CFStringRef createVersionStringFromModuleName(LPCWSTR moduleName)
942 {
943 HMODULE module = GetModuleHandleW(moduleName);
944 if (!module)
945 return 0;
946
947 wchar_t filePath[MAX_PATH] = {0};
948 if (!GetModuleFileNameW(module, filePath, MAX_PATH))
949 return 0;
950
951 DWORD versionInfoSize = GetFileVersionInfoSizeW(filePath, 0);
952 if (!versionInfoSize)
953 return 0;
954
955 CFStringRef versionString = 0;
956 void* versionInfo = calloc(versionInfoSize, sizeof(char));
957 if (GetFileVersionInfo(filePath, 0, versionInfoSize, versionInfo)) {
958 VS_FIXEDFILEINFO* fileInfo = 0;
959 UINT fileInfoLength = 0;
960
961 if (VerQueryValueW(versionInfo, L"\\", reinterpret_cast<LPVOID*>(&fileIn fo), &fileInfoLength)) {
962 versionString = CFStringCreateWithFormat(kCFAllocatorDefault, 0, CFS TR("%d.%d.%d.%d"),
963 HIWORD(fileInfo->dwFileVersionMS), LOWORD(fileInfo->dwFileVersio nMS),
964 HIWORD(fileInfo->dwFileVersionLS), LOWORD(fileInfo->dwFileVersio nLS));
965 }
966 }
967 free(versionInfo);
968
969 return versionString;
970 }
971
972 static bool requiredDllsAvailable()
973 {
974 static bool s_prerequisitesChecked = false;
975 static bool s_prerequisitesSatisfied;
976 static const CFStringRef kMinQuartzCoreVersion = CFSTR("1.0.42.0");
977 static const CFStringRef kMinCoreVideoVersion = CFSTR("1.0.1.0");
978
979 if (s_prerequisitesChecked)
980 return s_prerequisitesSatisfied;
981 s_prerequisitesChecked = true;
982 s_prerequisitesSatisfied = false;
983
984 CFStringRef quartzCoreString = createVersionStringFromModuleName(L"QuartzCor e");
985 if (!quartzCoreString)
986 quartzCoreString = createVersionStringFromModuleName(L"QuartzCore_debug" );
987
988 CFStringRef coreVideoString = createVersionStringFromModuleName(L"CoreVideo" );
989 if (!coreVideoString)
990 coreVideoString = createVersionStringFromModuleName(L"CoreVideo_debug");
991
992 s_prerequisitesSatisfied = (quartzCoreString && coreVideoString
993 && CFStringCompare(quartzCoreString, kMinQuartzCoreVersion, kCFCompareNu merically) != kCFCompareLessThan
994 && CFStringCompare(coreVideoString, kMinCoreVideoVersion, kCFCompareNume rically) != kCFCompareLessThan);
995
996 if (quartzCoreString)
997 CFRelease(quartzCoreString);
998 if (coreVideoString)
999 CFRelease(coreVideoString);
1000
1001 return s_prerequisitesSatisfied;
1002 }
1003
1004 void MediaPlayerPrivateQuickTimeVisualContext::getSupportedTypes(HashSet<String> & types)
1005 {
1006 types = mimeTypeCache();
1007 }
1008
1009 bool MediaPlayerPrivateQuickTimeVisualContext::isAvailable()
1010 {
1011 return QTMovie::initializeQuickTime();
1012 }
1013
1014 MediaPlayer::SupportsType MediaPlayerPrivateQuickTimeVisualContext::supportsType (const String& type, const String& codecs, const KURL&)
1015 {
1016 // only return "IsSupported" if there is no codecs parameter for now as ther e is no way to ask QT if it supports an
1017 // extended MIME type
1018 return mimeTypeCache().contains(type) ? (codecs.isEmpty() ? MediaPlayer::May BeSupported : MediaPlayer::IsSupported) : MediaPlayer::IsNotSupported;
1019 }
1020
1021 void MediaPlayerPrivateQuickTimeVisualContext::MovieClient::movieEnded(QTMovie* movie)
1022 {
1023 if (m_parent->m_hasUnsupportedTracks)
1024 return;
1025
1026 m_parent->m_visualContextTimer.stop();
1027
1028 ASSERT(m_parent->m_movie.get() == movie);
1029 m_parent->didEnd();
1030 }
1031
1032 void MediaPlayerPrivateQuickTimeVisualContext::MovieClient::movieLoadStateChange d(QTMovie* movie)
1033 {
1034 if (m_parent->m_hasUnsupportedTracks)
1035 return;
1036
1037 ASSERT(m_parent->m_movie.get() == movie);
1038 m_parent->updateStates();
1039 }
1040
1041 void MediaPlayerPrivateQuickTimeVisualContext::MovieClient::movieTimeChanged(QTM ovie* movie)
1042 {
1043 if (m_parent->m_hasUnsupportedTracks)
1044 return;
1045
1046 ASSERT(m_parent->m_movie.get() == movie);
1047 m_parent->updateStates();
1048 m_parent->m_player->timeChanged();
1049 }
1050
1051 bool MediaPlayerPrivateQuickTimeVisualContext::hasSingleSecurityOrigin() const
1052 {
1053 // We tell quicktime to disallow resources that come from different origins
1054 // so we all media is single origin.
1055 return true;
1056 }
1057
1058 void MediaPlayerPrivateQuickTimeVisualContext::setPreload(MediaPlayer::Preload p reload)
1059 {
1060 m_preload = preload;
1061 if (m_delayingLoad && m_preload != MediaPlayer::None)
1062 resumeLoad();
1063 }
1064
1065 float MediaPlayerPrivateQuickTimeVisualContext::mediaTimeForTimeValue(float time Value) const
1066 {
1067 long timeScale;
1068 if (m_readyState < MediaPlayer::HaveMetadata || !(timeScale = m_movie->timeS cale()))
1069 return timeValue;
1070
1071 long mediaTimeValue = lroundf(timeValue * timeScale);
1072 return static_cast<float>(mediaTimeValue) / timeScale;
1073 }
1074
1075 MediaPlayerPrivateQuickTimeVisualContext::MediaRenderingMode MediaPlayerPrivateQ uickTimeVisualContext::currentRenderingMode() const
1076 {
1077 if (!m_movie)
1078 return MediaRenderingNone;
1079
1080 #if USE(ACCELERATED_COMPOSITING)
1081 if (m_qtVideoLayer)
1082 return MediaRenderingMovieLayer;
1083 #endif
1084
1085 return m_visualContext ? MediaRenderingSoftwareRenderer : MediaRenderingNone ;
1086 }
1087
1088 MediaPlayerPrivateQuickTimeVisualContext::MediaRenderingMode MediaPlayerPrivateQ uickTimeVisualContext::preferredRenderingMode() const
1089 {
1090 if (!m_player->frameView() || !m_movie)
1091 return MediaRenderingNone;
1092
1093 #if USE(ACCELERATED_COMPOSITING)
1094 if (supportsAcceleratedRendering() && m_player->mediaPlayerClient()->mediaPl ayerRenderingCanBeAccelerated(m_player))
1095 return MediaRenderingMovieLayer;
1096 #endif
1097
1098 return MediaRenderingSoftwareRenderer;
1099 }
1100
1101 void MediaPlayerPrivateQuickTimeVisualContext::setUpVideoRendering()
1102 {
1103 MediaRenderingMode currentMode = currentRenderingMode();
1104 MediaRenderingMode preferredMode = preferredRenderingMode();
1105
1106 #if !USE(ACCELERATED_COMPOSITING)
1107 ASSERT(preferredMode != MediaRenderingMovieLayer);
1108 #endif
1109
1110 if (currentMode == preferredMode && currentMode != MediaRenderingNone)
1111 return;
1112
1113 if (currentMode != MediaRenderingNone)
1114 tearDownVideoRendering();
1115
1116 if (preferredMode == MediaRenderingMovieLayer)
1117 createLayerForMovie();
1118
1119 #if USE(ACCELERATED_COMPOSITING)
1120 if (currentMode == MediaRenderingMovieLayer || preferredMode == MediaRenderi ngMovieLayer)
1121 m_player->mediaPlayerClient()->mediaPlayerRenderingModeChanged(m_player) ;
1122 #endif
1123
1124 QTPixelBuffer::Type contextType = requiredDllsAvailable() && preferredMode = = MediaRenderingMovieLayer ? QTPixelBuffer::ConfigureForCAImageQueue : QTPixelBu ffer::ConfigureForCGImage;
1125 m_visualContext = QTMovieVisualContext::create(m_visualContextClient.get(), contextType);
1126 m_visualContext->setMovie(m_movie.get());
1127 }
1128
1129 void MediaPlayerPrivateQuickTimeVisualContext::tearDownVideoRendering()
1130 {
1131 #if USE(ACCELERATED_COMPOSITING)
1132 if (m_qtVideoLayer)
1133 destroyLayerForMovie();
1134 #endif
1135
1136 m_visualContext = 0;
1137 }
1138
1139 bool MediaPlayerPrivateQuickTimeVisualContext::hasSetUpVideoRendering() const
1140 {
1141 #if USE(ACCELERATED_COMPOSITING)
1142 return m_qtVideoLayer || (currentRenderingMode() != MediaRenderingMovieLayer && m_visualContext);
1143 #else
1144 return true;
1145 #endif
1146 }
1147
1148 void MediaPlayerPrivateQuickTimeVisualContext::retrieveAndResetMovieTransform()
1149 {
1150 #if USE(ACCELERATED_COMPOSITING)
1151 // First things first, reset the total movie transform so that
1152 // we can bail out early:
1153 m_movieTransform = CGAffineTransformIdentity;
1154
1155 if (!m_movie || !m_movie->hasVideo())
1156 return;
1157
1158 // This trick will only work on movies with a single video track,
1159 // so bail out early if the video contains more than one (or zero)
1160 // video tracks.
1161 QTTrackArray videoTracks = m_movie->videoTracks();
1162 if (videoTracks.size() != 1)
1163 return;
1164
1165 QTTrack* track = videoTracks[0].get();
1166 ASSERT(track);
1167
1168 CGAffineTransform movieTransform = m_movie->getTransform();
1169 if (!CGAffineTransformEqualToTransform(movieTransform, CGAffineTransformIden tity))
1170 m_movie->resetTransform();
1171
1172 CGAffineTransform trackTransform = track->getTransform();
1173 if (!CGAffineTransformEqualToTransform(trackTransform, CGAffineTransformIden tity))
1174 track->resetTransform();
1175
1176 // Multiply the two transforms together, taking care to
1177 // do so in the correct order, track * movie = final:
1178 m_movieTransform = CGAffineTransformConcat(trackTransform, movieTransform);
1179 #endif
1180 }
1181
1182 void MediaPlayerPrivateQuickTimeVisualContext::createLayerForMovie()
1183 {
1184 #if USE(ACCELERATED_COMPOSITING)
1185 ASSERT(supportsAcceleratedRendering());
1186
1187 if (!m_movie || m_qtVideoLayer)
1188 return;
1189
1190 // Create a PlatformCALayer which will transform the contents of the video l ayer
1191 // which is in m_qtVideoLayer.
1192 m_transformLayer = PlatformCALayer::create(PlatformCALayer::LayerTypeLayer, m_layerClient.get());
1193 if (!m_transformLayer)
1194 return;
1195
1196 // Mark the layer as anchored in the top left.
1197 m_transformLayer->setAnchorPoint(FloatPoint3D());
1198
1199 m_qtVideoLayer = PlatformCALayer::create(PlatformCALayer::LayerTypeLayer, 0) ;
1200 if (!m_qtVideoLayer)
1201 return;
1202
1203 if (CGAffineTransformEqualToTransform(m_movieTransform, CGAffineTransformIde ntity))
1204 retrieveAndResetMovieTransform();
1205 CGAffineTransform t = m_movieTransform;
1206
1207 // Remove the translation portion of the transform, since we will always rot ate about
1208 // the layer's center point. In our limited use-case (a single video track) , this is
1209 // safe:
1210 t.tx = t.ty = 0;
1211 m_qtVideoLayer->setTransform(CATransform3DMakeAffineTransform(t));
1212
1213 #ifndef NDEBUG
1214 m_qtVideoLayer->setName("Video layer");
1215 #endif
1216 m_transformLayer->appendSublayer(m_qtVideoLayer.get());
1217 m_transformLayer->setNeedsLayout();
1218 // The layer will get hooked up via RenderLayerBacking::updateGraphicsLayerC onfiguration().
1219 #endif
1220
1221 // Fill the newly created layer with image data, so we're not looking at
1222 // an empty layer until the next time a new image is available, which could
1223 // be a long time if we're paused.
1224 if (m_visualContext)
1225 retrieveCurrentImage();
1226 }
1227
1228 void MediaPlayerPrivateQuickTimeVisualContext::destroyLayerForMovie()
1229 {
1230 #if USE(ACCELERATED_COMPOSITING)
1231 if (m_qtVideoLayer) {
1232 m_qtVideoLayer->removeFromSuperlayer();
1233 m_qtVideoLayer = 0;
1234 }
1235
1236 if (m_transformLayer)
1237 m_transformLayer = 0;
1238
1239 if (m_imageQueue)
1240 m_imageQueue = nullptr;
1241 #endif
1242 }
1243
1244 #if USE(ACCELERATED_COMPOSITING)
1245 bool MediaPlayerPrivateQuickTimeVisualContext::supportsAcceleratedRendering() co nst
1246 {
1247 return isReadyForRendering();
1248 }
1249
1250 void MediaPlayerPrivateQuickTimeVisualContext::acceleratedRenderingStateChanged( )
1251 {
1252 // Set up or change the rendering path if necessary.
1253 setUpVideoRendering();
1254 }
1255
1256 void MediaPlayerPrivateQuickTimeVisualContext::setPrivateBrowsingMode(bool priva teBrowsing)
1257 {
1258 m_privateBrowsing = privateBrowsing;
1259 if (m_movie)
1260 m_movie->setPrivateBrowsingMode(m_privateBrowsing);
1261 }
1262
1263 #endif
1264
1265
1266 }
1267
1268 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698