2011-05-02 Sheriff Bot <webkit.review.bot@gmail.com>
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 2 May 2011 21:04:42 +0000 (21:04 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 2 May 2011 21:04:42 +0000 (21:04 +0000)
        Unreviewed, rolling out r85483.
        http://trac.webkit.org/changeset/85483
        https://bugs.webkit.org/show_bug.cgi?id=59958

        Causes media test failures. (Requested by eric_carlson on
        #webkit).

        * html/HTMLMediaElement.cpp:
        (WebCore::HTMLMediaElement::HTMLMediaElement):
        (WebCore::HTMLMediaElement::prepareForLoad):
        (WebCore::HTMLMediaElement::seek):
        (WebCore::HTMLMediaElement::updatePlayState):
        * html/HTMLMediaElement.h:
        * platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp:
        (WebCore::MediaPlayerPrivateAVFoundation::MediaPlayerPrivateAVFoundation):
        (WebCore::MediaPlayerPrivateAVFoundation::resumeLoad):
        (WebCore::MediaPlayerPrivateAVFoundation::load):
        (WebCore::MediaPlayerPrivateAVFoundation::prepareToPlay):
        (WebCore::MediaPlayerPrivateAVFoundation::paint):
        (WebCore::MediaPlayerPrivateAVFoundation::duration):
        (WebCore::MediaPlayerPrivateAVFoundation::seeking):
        (WebCore::MediaPlayerPrivateAVFoundation::updateStates):
        (WebCore::MediaPlayerPrivateAVFoundation::hasAvailableVideoFrame):
        (WebCore::MediaPlayerPrivateAVFoundation::metadataLoaded):
        (WebCore::MediaPlayerPrivateAVFoundation::loadedTimeRangesChanged):
        (WebCore::MediaPlayerPrivateAVFoundation::timeChanged):
        (WebCore::MediaPlayerPrivateAVFoundation::seekCompleted):
        (WebCore::MediaPlayerPrivateAVFoundation::repaint):
        (WebCore::MediaPlayerPrivateAVFoundation::setPreload):
        * platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h:
        * platform/graphics/avfoundation/MediaPlayerPrivateAVFoundationObjC.h:
        * platform/graphics/avfoundation/MediaPlayerPrivateAVFoundationObjC.mm:
        (WebCore::MediaPlayerPrivateAVFoundationObjC::MediaPlayerPrivateAVFoundationObjC):
        (WebCore::MediaPlayerPrivateAVFoundationObjC::videoLayerIsReadyToDisplay):
        (WebCore::MediaPlayerPrivateAVFoundationObjC::createAVPlayerForURL):
        (WebCore::MediaPlayerPrivateAVFoundationObjC::createAVPlayerForCacheResource):
        (WebCore::MediaPlayerPrivateAVFoundationObjC::createAVPlayer):
        (WebCore::MediaPlayerPrivateAVFoundationObjC::beginLoadingMetadata):
        (WebCore::MediaPlayerPrivateAVFoundationObjC::playerItemStatus):
        (WebCore::MediaPlayerPrivateAVFoundationObjC::platformDuration):
        (WebCore::MediaPlayerPrivateAVFoundationObjC::assetStatus):
        (WebCore::MediaPlayerPrivateAVFoundationObjC::paint):
        (WebCore::MediaPlayerPrivateAVFoundationObjC::tracksChanged):
        (WebCore::MediaPlayerPrivateAVFoundationObjC::sizeChanged):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@85518 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/html/HTMLMediaElement.cpp
Source/WebCore/html/HTMLMediaElement.h
Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp
Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h
Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundationObjC.h
Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundationObjC.mm

index 8507871..c6abbaa 100644 (file)
@@ -1,3 +1,50 @@
+2011-05-02  Sheriff Bot  <webkit.review.bot@gmail.com>
+
+        Unreviewed, rolling out r85483.
+        http://trac.webkit.org/changeset/85483
+        https://bugs.webkit.org/show_bug.cgi?id=59958
+
+        Causes media test failures. (Requested by eric_carlson on
+        #webkit).
+
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::HTMLMediaElement):
+        (WebCore::HTMLMediaElement::prepareForLoad):
+        (WebCore::HTMLMediaElement::seek):
+        (WebCore::HTMLMediaElement::updatePlayState):
+        * html/HTMLMediaElement.h:
+        * platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp:
+        (WebCore::MediaPlayerPrivateAVFoundation::MediaPlayerPrivateAVFoundation):
+        (WebCore::MediaPlayerPrivateAVFoundation::resumeLoad):
+        (WebCore::MediaPlayerPrivateAVFoundation::load):
+        (WebCore::MediaPlayerPrivateAVFoundation::prepareToPlay):
+        (WebCore::MediaPlayerPrivateAVFoundation::paint):
+        (WebCore::MediaPlayerPrivateAVFoundation::duration):
+        (WebCore::MediaPlayerPrivateAVFoundation::seeking):
+        (WebCore::MediaPlayerPrivateAVFoundation::updateStates):
+        (WebCore::MediaPlayerPrivateAVFoundation::hasAvailableVideoFrame):
+        (WebCore::MediaPlayerPrivateAVFoundation::metadataLoaded):
+        (WebCore::MediaPlayerPrivateAVFoundation::loadedTimeRangesChanged):
+        (WebCore::MediaPlayerPrivateAVFoundation::timeChanged):
+        (WebCore::MediaPlayerPrivateAVFoundation::seekCompleted):
+        (WebCore::MediaPlayerPrivateAVFoundation::repaint):
+        (WebCore::MediaPlayerPrivateAVFoundation::setPreload):
+        * platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h:
+        * platform/graphics/avfoundation/MediaPlayerPrivateAVFoundationObjC.h:
+        * platform/graphics/avfoundation/MediaPlayerPrivateAVFoundationObjC.mm:
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::MediaPlayerPrivateAVFoundationObjC):
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::videoLayerIsReadyToDisplay):
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::createAVPlayerForURL):
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::createAVPlayerForCacheResource):
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::createAVPlayer):
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::beginLoadingMetadata):
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::playerItemStatus):
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::platformDuration):
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::assetStatus):
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::paint):
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::tracksChanged):
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::sizeChanged):
+
 2011-05-02  Adam Barth  <abarth@webkit.org>
 
         Reviewed by David Levin.
index 2368b65..fe82976 100644 (file)
@@ -171,7 +171,6 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document* docum
     , m_dispatchingCanPlayEvent(false)
     , m_loadInitiatedByUserGesture(false)
     , m_completelyLoaded(false)
-    , m_havePreparedToPlay(false)
 {
     LOG(Media, "HTMLMediaElement::HTMLMediaElement");
     document->registerForDocumentActivationCallbacks(this);
@@ -518,7 +517,6 @@ void HTMLMediaElement::prepareForLoad()
     m_sentStalledEvent = false;
     m_haveFiredLoadedData = false;
     m_completelyLoaded = false;
-    m_havePreparedToPlay = false;
     m_displayMode = Unknown;
 
     // 1 - Abort any already-running instance of the resource selection algorithm for this element.
@@ -1084,15 +1082,7 @@ bool HTMLMediaElement::supportsSave() const
 {
     return m_player ? m_player->supportsSave() : false;
 }
-
-void HTMLMediaElement::prepareToPlay()
-{
-    if (m_havePreparedToPlay)
-        return;
-    m_havePreparedToPlay = true;
-    m_player->prepareToPlay();
-}
-
+    
 void HTMLMediaElement::seek(float time, ExceptionCode& ec)
 {
     LOG(Media, "HTMLMediaElement::seek(%f)", time);
@@ -1105,10 +1095,6 @@ void HTMLMediaElement::seek(float time, ExceptionCode& ec)
         return;
     }
 
-    // If the media engine has been told to postpone loading data, let it go ahead now.
-    if (m_preload < MediaPlayer::Auto && m_readyState < HAVE_FUTURE_DATA)
-        prepareToPlay();
-
     // Get the current time before setting m_seeking, m_lastSeekTime is returned once it is set.
     refreshCachedTime();
     float now = currentTime();
@@ -2210,7 +2196,7 @@ void HTMLMediaElement::updatePlayState()
             addPlayedRange(m_lastSeekTime, time);
 
         if (couldPlayIfEnoughData())
-            prepareToPlay();
+            m_player->prepareToPlay();
 
         if (hasMediaControls())
             mediaControls()->playbackStopped();
index 7d3d887..604cdf8 100644 (file)
@@ -286,7 +286,6 @@ private:
     void mediaEngineError(PassRefPtr<MediaError> err);
     void cancelPendingEventsAndCallbacks();
     void waitForSourceChange();
-    void prepareToPlay();
 
     enum InvalidSourceAction { DoNothing, Complain };
     bool isSafeToLoadURL(const KURL&, InvalidSourceAction);
@@ -418,7 +417,6 @@ private:
     bool m_dispatchingCanPlayEvent : 1;
     bool m_loadInitiatedByUserGesture : 1;
     bool m_completelyLoaded : 1;
-    bool m_havePreparedToPlay : 1;
 };
 
 } //namespace
index c988ad6..096ebb2 100644 (file)
@@ -30,7 +30,6 @@
 #include "MediaPlayerPrivateAVFoundation.h"
 
 #include "ApplicationCacheHost.h"
-#include "ApplicationCacheResource.h"
 #include "DocumentLoader.h"
 #include "FrameView.h"
 #include "GraphicsContext.h"
@@ -46,25 +45,30 @@ using namespace std;
 
 namespace WebCore {
 
+static const float invalidTime = -1.0f;
+
 MediaPlayerPrivateAVFoundation::MediaPlayerPrivateAVFoundation(MediaPlayer* player)
     : m_player(player)
     , m_queuedNotifications()
     , m_queueMutex()
+    , m_mainThreadCallPending(false)
     , m_networkState(MediaPlayer::Empty)
     , m_readyState(MediaPlayer::HaveNothing)
     , m_preload(MediaPlayer::Auto)
     , m_scaleFactor(1, 1)
     , m_cachedMaxTimeLoaded(0)
     , m_cachedMaxTimeSeekable(0)
-    , m_cachedDuration(invalidTime())
-    , m_reportedDuration(invalidTime())
-    , m_seekTo(invalidTime())
+    , m_cachedDuration(invalidTime)
+    , m_reportedDuration(invalidTime)
+    , m_seekTo(invalidTime)
     , m_requestedRate(1)
-    , m_delayCallbacks(0)
-    , m_mainThreadCallPending(false)
+    , m_delayCallbacks(false)
+    , m_havePreparedToPlay(false)
     , m_assetIsPlayable(false)
     , m_visible(false)
+    , m_videoFrameHasDrawn(false)
     , m_loadingMetadata(false)
+    , m_delayingLoad(false)
     , m_isAllowedToRender(false)
     , m_cachedHasAudio(false)
     , m_cachedHasVideo(false)
@@ -163,6 +167,17 @@ bool MediaPlayerPrivateAVFoundation::hasSetUpVideoRendering() const
     return hasLayerRenderer() || hasContextRenderer();
 }
 
+void MediaPlayerPrivateAVFoundation::resumeLoad()
+{
+    LOG(Media, "MediaPlayerPrivateAVFoundation::resumeLoad(%p)", this);
+
+    ASSERT(m_delayingLoad);
+    m_delayingLoad = false;
+
+    if (m_assetURL.length())
+        prepareToPlay();
+}
+
 void MediaPlayerPrivateAVFoundation::load(const String& url)
 {
     LOG(Media, "MediaPlayerPrivateAVFoundation::load(%p)", this);
@@ -176,13 +191,20 @@ void MediaPlayerPrivateAVFoundation::load(const String& url)
         m_player->readyStateChanged();
     }
 
+    m_videoFrameHasDrawn = false;
     m_assetURL = url;
 
     // Don't do any more work if the url is empty.
     if (!url.length())
         return;
 
-    setPreload(m_preload);
+    if (m_preload == MediaPlayer::None) {
+        LOG(Media, "MediaPlayerPrivateAVFoundation::load(%p) - preload==none so returning", this);
+        m_delayingLoad = true;
+        return;
+    }
+
+    prepareToPlay();
 }
 
 void MediaPlayerPrivateAVFoundation::playabilityKnown()
@@ -210,7 +232,22 @@ void MediaPlayerPrivateAVFoundation::prepareToPlay()
 {
     LOG(Media, "MediaPlayerPrivateAVFoundation::prepareToPlay(%p)", this);
 
-    setPreload(MediaPlayer::Auto);
+    m_preload = MediaPlayer::Auto;
+    if (m_havePreparedToPlay)
+        return;
+    m_havePreparedToPlay = true;
+
+    m_delayingLoad = false;
+#if ENABLE(OFFLINE_WEB_APPLICATIONS)
+    Frame* frame = m_player->frameView() ? m_player->frameView()->frame() : 0;
+    ApplicationCacheHost* cacheHost = frame ? frame->loader()->documentLoader()->applicationCacheHost() : 0;
+    ApplicationCacheResource* resource = 0;
+    if (cacheHost && cacheHost->shouldLoadResourceFromApplicationCache(ResourceRequest(m_assetURL), resource) && resource)
+        createAVPlayerForCacheResource(resource);
+    else
+#endif    
+    createAVPlayerForURL(m_assetURL);
+    checkPlayability();
 }
 
 void MediaPlayerPrivateAVFoundation::play()
@@ -232,20 +269,22 @@ void MediaPlayerPrivateAVFoundation::pause()
     platformPause();
 }
 
-float MediaPlayerPrivateAVFoundation::duration() const
+void MediaPlayerPrivateAVFoundation::paint(GraphicsContext*, const IntRect&)
 {
-    if (m_cachedDuration != invalidTime())
-        return m_cachedDuration;
+    // This is the base class, only need to remember that a frame has been drawn.
+    m_videoFrameHasDrawn = true;
+}
 
+float MediaPlayerPrivateAVFoundation::duration() const
+{
     if (!metaDataAvailable())
         return 0;
 
-    float duration = platformDuration();
-    if (!duration || duration == invalidTime())
-        return 0;
+    if (m_cachedDuration == invalidTime) {
+        m_cachedDuration = platformDuration();
+        LOG(Media, "MediaPlayerPrivateAVFMac::duration(%p) - caching %f", this, m_cachedDuration);
+    }
 
-    m_cachedDuration = duration;
-    LOG(Media, "MediaPlayerPrivateAVFMac::duration(%p) - caching %f", this, m_cachedDuration);
     return m_cachedDuration;
 }
 
@@ -287,7 +326,7 @@ bool MediaPlayerPrivateAVFoundation::seeking() const
     if (!metaDataAvailable())
         return false;
 
-    return m_seekTo != invalidTime();
+    return m_seekTo != invalidTime;
 }
 
 IntSize MediaPlayerPrivateAVFoundation::naturalSize() const
@@ -393,28 +432,24 @@ void MediaPlayerPrivateAVFoundation::updateStates()
         m_networkState = MediaPlayer::Loading;
     else {
         // -loadValuesAsynchronouslyForKeys:completionHandler: has invoked its handler; test status of keys and determine state.
-        AssetStatus avAssetStatus = assetStatus();
+        AVAssetStatus avAssetStatus = assetStatus();
         ItemStatus itemStatus = playerItemStatus();
         
         m_assetIsPlayable = (avAssetStatus == MediaPlayerAVAssetStatusPlayable);
         if (m_readyState < MediaPlayer::HaveMetadata && avAssetStatus > MediaPlayerAVAssetStatusLoading) {
             if (m_assetIsPlayable) {
-                if (itemStatus <= MediaPlayerAVPlayerItemStatusUnknown) {
+                if (itemStatus == MediaPlayerAVPlayerItemStatusUnknown) {
                     if (avAssetStatus == MediaPlayerAVAssetStatusFailed || m_preload > MediaPlayer::MetaData) {
                         // We may have a playable asset that doesn't support inspection prior to playback; go ahead 
                         // and create the AVPlayerItem now. When the AVPlayerItem becomes ready to play, we will 
                         // have access to its metadata. Or we may have been asked to become ready to play immediately.
                         m_networkState = MediaPlayer::Loading;
                         prepareToPlay();
-                    } else {
-                        // The asset is playable, but we don't want to load media data yet so don't allocate
-                        // the player item. Even though we don't want to play yet, allocate a player so
-                        // we can create a layer as soon as possible.
-                        createAVPlayer();
+                    } else
                         m_networkState = MediaPlayer::Idle;
-                    }
                 }
-                m_readyState = MediaPlayer::HaveMetadata;
+                if (avAssetStatus == MediaPlayerAVAssetStatusLoaded)
+                    m_readyState = MediaPlayer::HaveMetadata;
             } else {
                 // FIX ME: fetch the error associated with the @"playable" key to distinguish between format 
                 // and network errors.
@@ -428,7 +463,6 @@ void MediaPlayerPrivateAVFoundation::updateStates()
             else {
                 float maxLoaded = maxTimeLoaded();
                 switch (itemStatus) {
-                case MediaPlayerAVPlayerItemStatusDoesNotExist:
                 case MediaPlayerAVPlayerItemStatusUnknown:
                     break;
                 case MediaPlayerAVPlayerItemStatusFailed:
@@ -437,11 +471,8 @@ void MediaPlayerPrivateAVFoundation::updateStates()
                 case MediaPlayerAVPlayerItemStatusPlaybackLikelyToKeepUp:
                     m_readyState = MediaPlayer::HaveEnoughData;
                     break;
-
-                case MediaPlayerAVPlayerItemStatusPlaybackBufferFull:
-                    m_networkState = MediaPlayer::Idle;
-
                 case MediaPlayerAVPlayerItemStatusReadyToPlay:
+                case MediaPlayerAVPlayerItemStatusPlaybackBufferFull:
                     // If the readyState is already HaveEnoughData, don't go lower because of this state change.
                     if (m_readyState == MediaPlayer::HaveEnoughData)
                         break;
@@ -454,7 +485,7 @@ void MediaPlayerPrivateAVFoundation::updateStates()
                     break;
                 }
 
-                if (itemStatus != MediaPlayerAVPlayerItemStatusPlaybackBufferFull && itemStatus >= MediaPlayerAVPlayerItemStatusReadyToPlay)
+                if (itemStatus >= MediaPlayerAVPlayerItemStatusReadyToPlay)
                     m_networkState = (maxLoaded == duration()) ? MediaPlayer::Loaded : MediaPlayer::Loading;
             }
         }
@@ -464,8 +495,6 @@ void MediaPlayerPrivateAVFoundation::updateStates()
         setUpVideoRendering();
 
     if (!m_haveReportedFirstVideoFrame && m_cachedHasVideo && hasAvailableVideoFrame()) {
-        if (m_readyState < MediaPlayer::HaveCurrentData)
-            m_readyState = MediaPlayer::HaveCurrentData;
         m_haveReportedFirstVideoFrame = true;
         m_player->firstVideoFrameAvailable();
     }
@@ -501,6 +530,16 @@ void MediaPlayerPrivateAVFoundation::setVisible(bool visible)
     platformSetVisible(visible);
 }
 
+bool MediaPlayerPrivateAVFoundation::hasAvailableVideoFrame() const
+{
+    if (currentRenderingMode() == MediaRenderingToLayer)
+        return videoLayerIsReadyToDisplay();
+
+    // When using the software renderer we hope someone will signal that a frame is available so we might as well
+    // wait until we know that a frame has been drawn.
+    return m_videoFrameHasDrawn;
+}
+
 void MediaPlayerPrivateAVFoundation::acceleratedRenderingStateChanged()
 {
     // Set up or change the rendering path if necessary.
@@ -510,7 +549,6 @@ void MediaPlayerPrivateAVFoundation::acceleratedRenderingStateChanged()
 void MediaPlayerPrivateAVFoundation::metadataLoaded()
 {
     m_loadingMetadata = false;
-    tracksChanged();
     updateStates();
 }
 
@@ -537,7 +575,7 @@ void MediaPlayerPrivateAVFoundation::loadedTimeRangesChanged()
     // so report duration changed when the estimate is upated.
     float dur = duration();
     if (dur != m_reportedDuration) {
-        if (m_reportedDuration != invalidTime())
+        if (m_reportedDuration != invalidTime)
             m_player->durationChanged();
         m_reportedDuration = dur;
     }
@@ -552,7 +590,7 @@ void MediaPlayerPrivateAVFoundation::timeChanged(double time)
 {
     LOG(Media, "MediaPlayerPrivateAVFoundation::timeChanged(%p) - time = %f", this, time);
 
-    if (m_seekTo == invalidTime())
+    if (m_seekTo == invalidTime)
         return;
 
     // AVFoundation may call our observer more than once during a seek, and we can't currently tell
@@ -562,7 +600,7 @@ void MediaPlayerPrivateAVFoundation::timeChanged(double time)
 
     float currentRate = rate();
     if ((currentRate > 0 && time >= m_seekTo) || (currentRate < 0 && time <= m_seekTo) || (abs(m_seekTo - time) <= smallSeekDelta)) {
-        m_seekTo = invalidTime();
+        m_seekTo = invalidTime;
         updateStates();
         m_player->timeChanged();
     }
@@ -573,7 +611,7 @@ void MediaPlayerPrivateAVFoundation::seekCompleted(bool finished)
     LOG(Media, "MediaPlayerPrivateAVFoundation::seekCompleted(%p) - finished = %d", this, finished);
     
     if (finished)
-        m_seekTo = invalidTime();
+        m_seekTo = invalidTime;
 }
 
 void MediaPlayerPrivateAVFoundation::didEnd()
@@ -590,6 +628,7 @@ void MediaPlayerPrivateAVFoundation::didEnd()
 
 void MediaPlayerPrivateAVFoundation::repaint()
 {
+    m_videoFrameHasDrawn = true;
     m_player->repaint();
 }
 
@@ -607,30 +646,8 @@ MediaPlayer::MovieLoadType MediaPlayerPrivateAVFoundation::movieLoadType() const
 void MediaPlayerPrivateAVFoundation::setPreload(MediaPlayer::Preload preload)
 {
     m_preload = preload;
-    if (!m_assetURL.length())
-        return;
-
-    if (m_preload >= MediaPlayer::MetaData && assetStatus() == MediaPlayerAVAssetStatusDoesNotExist) {
-#if ENABLE(OFFLINE_WEB_APPLICATIONS)
-        Frame* frame = m_player->frameView() ? m_player->frameView()->frame() : 0;
-        ApplicationCacheHost* cacheHost = frame ? frame->loader()->documentLoader()->applicationCacheHost() : 0;
-        ApplicationCacheResource* resource;
-        if (cacheHost && cacheHost->shouldLoadResourceFromApplicationCache(ResourceRequest(m_assetURL), resource) && resource) {
-            // AVFoundation can't open arbitrary data pointers, so if this ApplicationCacheResource doesn't 
-            // have a valid local path, just open the resource's original URL.
-            if (resource->path().isEmpty())
-                createAVAssetForURL(resource->url());
-            else
-                createAVAssetForCacheResource(resource);
-        } else
-#endif    
-            createAVAssetForURL(m_assetURL);
-
-        checkPlayability();
-    }
-
-    if (m_preload == MediaPlayer::Auto && playerItemStatus() == MediaPlayerAVPlayerItemStatusDoesNotExist)
-        createAVPlayerItem();
+    if (m_delayingLoad && m_preload != MediaPlayer::None)
+        resumeLoad();
 }
 
 void MediaPlayerPrivateAVFoundation::setDelayCallbacks(bool delay)
index 4a587b2..225f6cf 100644 (file)
@@ -142,9 +142,10 @@ protected:
     virtual PassRefPtr<TimeRanges> buffered() const;
     virtual unsigned bytesLoaded() const;
     virtual void setSize(const IntSize&);
-    virtual void paint(GraphicsContext*, const IntRect&) = 0;
+    virtual void paint(GraphicsContext*, const IntRect&);
     virtual void paintCurrentFrameInContext(GraphicsContext*, const IntRect&) = 0;
     virtual void setPreload(MediaPlayer::Preload);
+    virtual bool hasAvailableVideoFrame() const;
 #if USE(ACCELERATED_COMPOSITING)
     virtual PlatformLayer* platformLayer() const { return 0; }
     virtual bool supportsAcceleratedRendering() const = 0;
@@ -158,15 +159,12 @@ protected:
     virtual bool supportsFullscreen() const;
 
     // Required interfaces for concrete derived classes.
-    virtual void createAVAssetForURL(const String&) = 0;
-    virtual void createAVPlayer() = 0;
-    virtual void createAVPlayerItem() = 0;
+    virtual void createAVPlayerForURL(const String& url) = 0;
 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
-    virtual void createAVAssetForCacheResource(ApplicationCacheResource*) = 0;
+    virtual void createAVPlayerForCacheResource(ApplicationCacheResource*) = 0;
 #endif
 
     enum ItemStatus {
-        MediaPlayerAVPlayerItemStatusDoesNotExist,
         MediaPlayerAVPlayerItemStatusUnknown,
         MediaPlayerAVPlayerItemStatusFailed,
         MediaPlayerAVPlayerItemStatusReadyToPlay,
@@ -176,8 +174,7 @@ protected:
     };
     virtual ItemStatus playerItemStatus() const = 0;
 
-    enum AssetStatus {
-        MediaPlayerAVAssetStatusDoesNotExist,
+    enum AVAssetStatus {
         MediaPlayerAVAssetStatusUnknown,
         MediaPlayerAVAssetStatusLoading,
         MediaPlayerAVAssetStatusFailed,
@@ -185,7 +182,7 @@ protected:
         MediaPlayerAVAssetStatusLoaded,
         MediaPlayerAVAssetStatusPlayable,
     };
-    virtual AssetStatus assetStatus() const = 0;
+    virtual AVAssetStatus assetStatus() const = 0;
 
     virtual void platformSetVisible(bool) = 0;
     virtual void platformPlay() = 0;
@@ -209,13 +206,13 @@ protected:
 
     virtual void createVideoLayer() = 0;
     virtual void destroyVideoLayer() = 0;
-
-    virtual bool hasAvailableVideoFrame() const = 0;
+    virtual bool videoLayerIsReadyToDisplay() const = 0;
 
     virtual bool hasContextRenderer() const = 0;
     virtual bool hasLayerRenderer() const = 0;
 
 protected:
+    void resumeLoad();
     void updateStates();
 
     void setHasVideo(bool b) { m_cachedHasVideo = b; };
@@ -239,14 +236,14 @@ protected:
     bool hasSetUpVideoRendering() const;
 
     static void mainThreadCallback(void*);
-    
-    float invalidTime() const { return -1.0f; }
 
 private:
+
     MediaPlayer* m_player;
 
     Vector<Notification> m_queuedNotifications;
     Mutex m_queueMutex;
+    bool m_mainThreadCallPending;
 
     mutable RefPtr<TimeRanges> m_cachedLoadedTimeRanges;
 
@@ -266,10 +263,12 @@ private:
     float m_seekTo;
     float m_requestedRate;
     int m_delayCallbacks;
-    bool m_mainThreadCallPending;
+    bool m_havePreparedToPlay;
     bool m_assetIsPlayable;
     bool m_visible;
+    bool m_videoFrameHasDrawn;
     bool m_loadingMetadata;
+    bool m_delayingLoad;
     bool m_isAllowedToRender;
     bool m_cachedHasAudio;
     bool m_cachedHasVideo;
index 78a9bc4..cebe2bc 100644 (file)
@@ -86,13 +86,12 @@ private:
     virtual float mediaTimeForTimeValue(float) const;
 
     virtual void createAVPlayer();
-    virtual void createAVPlayerItem();
-    virtual void createAVAssetForURL(const String& url);
+    virtual void createAVPlayerForURL(const String& url);
 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
-    virtual void createAVAssetForCacheResource(ApplicationCacheResource*);
+    virtual void createAVPlayerForCacheResource(ApplicationCacheResource*);
 #endif
     virtual MediaPlayerPrivateAVFoundation::ItemStatus playerItemStatus() const;
-    virtual MediaPlayerPrivateAVFoundation::AssetStatus assetStatus() const;
+    virtual MediaPlayerPrivateAVFoundation::AVAssetStatus assetStatus() const;
 
     virtual void checkPlayability();
     virtual void updateRate();
@@ -106,13 +105,12 @@ private:
     virtual void beginLoadingMetadata();
     virtual void sizeChanged();
 
-    virtual bool hasAvailableVideoFrame() const;
-
     virtual void createContextVideoRenderer();
     virtual void destroyContextVideoRenderer();
 
     virtual void createVideoLayer();
     virtual void destroyVideoLayer();
+    virtual bool videoLayerIsReadyToDisplay() const;
 
     virtual bool hasContextRenderer() const;
     virtual bool hasLayerRenderer() const;
@@ -127,7 +125,6 @@ private:
     RetainPtr<WebCoreAVFMovieObserver> m_objcObserver;
     RetainPtr<AVAssetImageGenerator> m_imageGenerator;
     id m_timeObserver;
-    bool m_videoFrameHasDrawn;
 };
 
 }
index 60b2948..542560a 100644 (file)
@@ -138,7 +138,6 @@ MediaPlayerPrivateAVFoundationObjC::MediaPlayerPrivateAVFoundationObjC(MediaPlay
     : MediaPlayerPrivateAVFoundation(player)
     , m_objcObserver(AdoptNS, [[WebCoreAVFMovieObserver alloc] initWithCallback:this])
     , m_timeObserver(0)
-    , m_videoFrameHasDrawn(false)
 {
 }
 
@@ -235,77 +234,71 @@ void MediaPlayerPrivateAVFoundationObjC::destroyVideoLayer()
     m_videoLayer = 0;
 }
 
-bool MediaPlayerPrivateAVFoundationObjC::hasAvailableVideoFrame() const
+bool MediaPlayerPrivateAVFoundationObjC::videoLayerIsReadyToDisplay() const
 {
-    return (m_videoFrameHasDrawn || (m_videoLayer && [m_videoLayer.get() isReadyForDisplay]));
+    return (m_videoLayer && [m_videoLayer.get() isReadyForDisplay]);
 }
 
-void MediaPlayerPrivateAVFoundationObjC::createAVAssetForURL(const String& url)
+void MediaPlayerPrivateAVFoundationObjC::createAVPlayerForURL(const String& url)
 {
-    if (m_avAsset)
-        return;
-
     setDelayCallbacks(true);
-    NSURL *cocoaURL = KURL(ParsedURLString, url);
-    m_avAsset.adoptNS([[AVURLAsset alloc] initWithURL:cocoaURL options:nil]);
-    setDelayCallbacks(false);
+
+    if (!m_avAsset) {
+        NSURL *cocoaURL = KURL(ParsedURLString, url);
+        m_avAsset.adoptNS([[AVURLAsset alloc] initWithURL:cocoaURL options:nil]);
+    }
+    
+    createAVPlayer();
 }
 
 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
-void MediaPlayerPrivateAVFoundationObjC::createAVAssetForCacheResource(ApplicationCacheResource* resource)
+void MediaPlayerPrivateAVFoundationObjC::createAVPlayerForCacheResource(ApplicationCacheResource* resource)
 {
-    if (m_avAsset)
+    // AVFoundation can't open arbitrary data pointers, so if this ApplicationCacheResource doesn't 
+    // have a valid local path, just open the resource's original URL.
+    if (resource->path().isEmpty()) {
+        createAVPlayerForURL(resource->url());
         return;
-
-    // AVFoundation can't open arbitrary data pointers.
-    ASSERT(!resource->path().isEmpty());
+    }
     
     setDelayCallbacks(true);
 
-    NSURL* localURL = [NSURL fileURLWithPath:resource->path()];
-    m_avAsset.adoptNS([[AVURLAsset alloc] initWithURL:localURL options:nil]);
+    if (!m_avAsset) {
+        NSURL* localURL = [NSURL fileURLWithPath:resource->path()];
+        m_avAsset.adoptNS([[AVURLAsset alloc] initWithURL:localURL options:nil]);
+    }
 
-    setDelayCallbacks(false);
+    createAVPlayer();
 }
 #endif
 
 void MediaPlayerPrivateAVFoundationObjC::createAVPlayer()
 {
-    if (m_avPlayer)
-        return;
-
-    setDelayCallbacks(true);
-
-    m_avPlayer.adoptNS([[AVPlayer alloc] init]);
-    [m_avPlayer.get() addObserver:m_objcObserver.get() forKeyPath:@"rate" options:nil context:(void *)MediaPlayerAVFoundationObservationContextPlayer];
-    
-    // Add a time observer, ask to be called infrequently because we don't really want periodic callbacks but
-    // our observer will also be called whenever a seek happens.
-    const double veryLongInterval = 60*60*60*24*30;
-    WebCoreAVFMovieObserver *observer = m_objcObserver.get();
-    m_timeObserver = [m_avPlayer.get() addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(veryLongInterval, 10) queue:nil usingBlock:^(CMTime time){
-        [observer timeChanged:CMTimeGetSeconds(time)];
-    }];
-
-    setDelayCallbacks(false);
-}
-
-void MediaPlayerPrivateAVFoundationObjC::createAVPlayerItem()
-{
-    if (m_avPlayerItem)
-        return;
-
-    setDelayCallbacks(true);
+    if (!m_avPlayer) {
+        m_avPlayer.adoptNS([[AVPlayer alloc] init]);
+        
+        [m_avPlayer.get() addObserver:m_objcObserver.get() forKeyPath:@"rate" options:nil context:(void *)MediaPlayerAVFoundationObservationContextPlayer];
+        
+        // Add a time observer, ask to be called infrequently because we don't really want periodic callbacks but
+        // our observer will also be called whenever a seek happens.
+        const double veryLongInterval = 60*60*60*24*30;
+        WebCoreAVFMovieObserver *observer = m_objcObserver.get();
+        m_timeObserver = [m_avPlayer.get() addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(veryLongInterval, 10) queue:nil usingBlock:^(CMTime time){
+            [observer timeChanged:CMTimeGetSeconds(time)];
+        }];
+    }
 
-    // Create the player item so we can media data. 
-    m_avPlayerItem.adoptNS([[AVPlayerItem alloc] initWithAsset:m_avAsset.get()]);
-    
-    [[NSNotificationCenter defaultCenter] addObserver:m_objcObserver.get()selector:@selector(didEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:m_avPlayerItem.get()];
+    if (!m_avPlayerItem) {
+        // Create the player item so we can media data. 
+        m_avPlayerItem.adoptNS([[AVPlayerItem alloc] initWithAsset:m_avAsset.get()]);
+        
+        [[NSNotificationCenter defaultCenter] addObserver:m_objcObserver.get()selector:@selector(didEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:m_avPlayerItem.get()];
 
-    for (NSString *keyName in itemKVOProperties())
-        [m_avPlayerItem.get() addObserver:m_objcObserver.get() forKeyPath:keyName options:nil context:(void *)MediaPlayerAVFoundationObservationContextPlayerItem];
+        for (NSString *keyName in itemKVOProperties())
+            [m_avPlayerItem.get() addObserver:m_objcObserver.get() forKeyPath:keyName options:nil context:(void *)MediaPlayerAVFoundationObservationContextPlayerItem];
 
-    [m_avPlayer.get() replaceCurrentItemWithPlayerItem:m_avPlayerItem.get()];
+        [m_avPlayer.get() replaceCurrentItemWithPlayerItem:m_avPlayerItem.get()];
+    }
 
     setDelayCallbacks(false);
 }
@@ -321,7 +314,7 @@ void MediaPlayerPrivateAVFoundationObjC::checkPlayability()
 
 void MediaPlayerPrivateAVFoundationObjC::beginLoadingMetadata()
 {
-    LOG(Media, "MediaPlayerPrivateAVFoundationObjC::beginLoadingMetadata(%p) - requesting metadata loading", this);
+    LOG(Media, "MediaPlayerPrivateAVFoundationObjC::playabilityKnown(%p) - requesting metadata loading", this);
     [m_avAsset.get() loadValuesAsynchronouslyForKeys:[assetMetadataKeyNames() retain] completionHandler:^{
         [m_objcObserver.get() metadataLoaded];
     }];
@@ -330,7 +323,7 @@ void MediaPlayerPrivateAVFoundationObjC::beginLoadingMetadata()
 MediaPlayerPrivateAVFoundation::ItemStatus MediaPlayerPrivateAVFoundationObjC::playerItemStatus() const
 {
     if (!m_avPlayerItem)
-        return MediaPlayerPrivateAVFoundation::MediaPlayerAVPlayerItemStatusDoesNotExist;
+        return MediaPlayerPrivateAVFoundation::MediaPlayerAVPlayerItemStatusUnknown;
 
     AVPlayerItemStatus status = [m_avPlayerItem.get() status];
     if (status == AVPlayerItemStatusUnknown)
@@ -339,9 +332,9 @@ MediaPlayerPrivateAVFoundation::ItemStatus MediaPlayerPrivateAVFoundationObjC::p
         return MediaPlayerPrivateAVFoundation::MediaPlayerAVPlayerItemStatusFailed;
     if ([m_avPlayerItem.get() isPlaybackLikelyToKeepUp])
         return MediaPlayerPrivateAVFoundation::MediaPlayerAVPlayerItemStatusPlaybackLikelyToKeepUp;
-    if ([m_avPlayerItem.get() isPlaybackBufferFull])
+    if (buffered()->contain(duration()))
         return MediaPlayerPrivateAVFoundation::MediaPlayerAVPlayerItemStatusPlaybackBufferFull;
-    if ([m_avPlayerItem.get() isPlaybackBufferEmpty])
+    if (buffered()->contain(currentTime()))
         return MediaPlayerPrivateAVFoundation::MediaPlayerAVPlayerItemStatusPlaybackBufferEmpty;
 
     return MediaPlayerPrivateAVFoundation::MediaPlayerAVPlayerItemStatusReadyToPlay;
@@ -392,25 +385,21 @@ void MediaPlayerPrivateAVFoundationObjC::platformPause()
 
 float MediaPlayerPrivateAVFoundationObjC::platformDuration() const
 {
-    if (!metaDataAvailable())
-        return invalidTime();
-    
-    CMTime cmDuration;
+    if (!metaDataAvailable() || !m_avPlayerItem)
+        return 0;
     
-    // Check the avitem if we have one, some assets never report duration.
-    if (m_avPlayerItem)
-        cmDuration = [m_avPlayerItem.get() duration];
-    else
-        cmDuration= [m_avAsset.get() duration];
-
+    float duration;
+    CMTime cmDuration = [m_avPlayerItem.get() duration];
     if (CMTIME_IS_NUMERIC(cmDuration))
-        return narrowPrecisionToFloat(CMTimeGetSeconds(cmDuration));
-
-    if (CMTIME_IS_INDEFINITE(cmDuration))
-        return numeric_limits<float>::infinity();
+        duration = narrowPrecisionToFloat(CMTimeGetSeconds(cmDuration));
+    else if (CMTIME_IS_INDEFINITE(cmDuration))
+        duration = numeric_limits<float>::infinity();
+    else {
+        LOG(Media, "MediaPlayerPrivateAVFoundationObjC::duration(%p) - invalid duration, returning 0", this);
+        return 0;
+    }
 
-    LOG(Media, "MediaPlayerPrivateAVFoundationObjC::duration(%p) - invalid duration, returning -1", this);
-    return invalidTime();
+    return duration;
 }
 
 float MediaPlayerPrivateAVFoundationObjC::currentTime() const
@@ -546,10 +535,10 @@ void MediaPlayerPrivateAVFoundationObjC::setAsset(id asset)
     m_avAsset = asset;
 }
 
-MediaPlayerPrivateAVFoundation::AssetStatus MediaPlayerPrivateAVFoundationObjC::assetStatus() const
+MediaPlayerPrivateAVFoundation::AVAssetStatus MediaPlayerPrivateAVFoundationObjC::assetStatus() const
 {
     if (!m_avAsset)
-        return MediaPlayerAVAssetStatusDoesNotExist;
+        return MediaPlayerAVAssetStatusUnknown;
 
     for (NSString *keyName in assetMetadataKeyNames()) {
         AVKeyValueStatus keyStatus = [m_avAsset.get() statusOfValueForKey:keyName error:nil];
@@ -598,7 +587,7 @@ void MediaPlayerPrivateAVFoundationObjC::paint(GraphicsContext* context, const I
     END_BLOCK_OBJC_EXCEPTIONS;
     setDelayCallbacks(false);
 
-    m_videoFrameHasDrawn = true;
+    MediaPlayerPrivateAVFoundation::paint(context, rect);
 }
 
 static HashSet<String> mimeTypeCache()
@@ -673,51 +662,37 @@ float MediaPlayerPrivateAVFoundationObjC::mediaTimeForTimeValue(float timeValue)
 
 void MediaPlayerPrivateAVFoundationObjC::tracksChanged()
 {
-    if (!m_avAsset)
-        return;
-
     // This is called whenever the tracks collection changes so cache hasVideo and hasAudio since we are
     // asked about those fairly fequently.
-    if (!m_avPlayerItem) {
-        // We don't have a player item yet, so check with the asset because some assets support inspection
-        // prior to becoming ready to play.
-        setHasVideo([[m_avAsset.get() tracksWithMediaCharacteristic:AVMediaCharacteristicVisual] count]);
-        setHasAudio([[m_avAsset.get() tracksWithMediaCharacteristic:AVMediaCharacteristicAudible] count]);
-        setHasClosedCaptions([[m_avAsset.get() tracksWithMediaType:AVMediaTypeClosedCaption] count]);
-    } else {
-        bool hasVideo = false;
-        bool hasAudio = false;
-        bool hasCaptions = false;
-        NSArray *tracks = [m_avPlayerItem.get() tracks];
-        for (AVPlayerItemTrack *track in tracks) {
-            if ([track isEnabled]) {
-                AVAssetTrack *assetTrack = [track assetTrack];
-                if ([[assetTrack mediaType] isEqualToString:AVMediaTypeVideo])
-                    hasVideo = true;
-                else if ([[assetTrack mediaType] isEqualToString:AVMediaTypeAudio])
-                    hasAudio = true;
-                else if ([[assetTrack mediaType] isEqualToString:AVMediaTypeClosedCaption])
-                    hasCaptions = true;
-            }
+    bool hasVideo = false;
+    bool hasAudio = false;
+    bool hasCaptions = false;
+    NSArray *tracks = [m_avPlayerItem.get() tracks];
+    for (AVPlayerItemTrack *track in tracks) {
+        if ([track isEnabled]) {
+            AVAssetTrack *assetTrack = [track assetTrack];
+            if ([[assetTrack mediaType] isEqualToString:AVMediaTypeVideo])
+                hasVideo = true;
+            else if ([[assetTrack mediaType] isEqualToString:AVMediaTypeAudio])
+                hasAudio = true;
+            else if ([[assetTrack mediaType] isEqualToString:AVMediaTypeClosedCaption])
+                hasCaptions = true;
         }
-        setHasVideo(hasVideo);
-        setHasAudio(hasAudio);
-        setHasClosedCaptions(hasCaptions);
     }
+    setHasVideo(hasVideo);
+    setHasAudio(hasAudio);
+    setHasClosedCaptions(hasCaptions);
 
     sizeChanged();
 }
 
 void MediaPlayerPrivateAVFoundationObjC::sizeChanged()
 {
-    if (!m_avAsset)
-        return;
-
     NSArray *tracks = [m_avAsset.get() tracks];
 
     // Some assets don't report track properties until they are completely ready to play, but we
     // want to report a size as early as possible so use presentationSize when an asset has no tracks.
-    if (m_avPlayerItem && ![tracks count]) {
+    if (![tracks count]) {
         setNaturalSize(IntSize([m_avPlayerItem.get() presentationSize]));
         return;
     }