summaryrefslogtreecommitdiff
path: root/Source/WebCore/html/HTMLMediaElement.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/html/HTMLMediaElement.cpp')
-rw-r--r--Source/WebCore/html/HTMLMediaElement.cpp267
1 files changed, 49 insertions, 218 deletions
diff --git a/Source/WebCore/html/HTMLMediaElement.cpp b/Source/WebCore/html/HTMLMediaElement.cpp
index cc025c12b..fadcfe7c6 100644
--- a/Source/WebCore/html/HTMLMediaElement.cpp
+++ b/Source/WebCore/html/HTMLMediaElement.cpp
@@ -111,6 +111,11 @@
#include "DisplaySleepDisabler.h"
#endif
+#if ENABLE(MEDIA_SOURCE)
+#include "MediaSource.h"
+#include "MediaSourceRegistry.h"
+#endif
+
using namespace std;
namespace WebCore {
@@ -145,7 +150,7 @@ static const char* boolString(bool val)
#if ENABLE(MEDIA_SOURCE)
// URL protocol used to signal that the media source API is being used.
-static const char* mediaSourceURLProtocol = "x-media-source";
+static const char* mediaSourceBlobProtocol = "blob";
#endif
using namespace HTMLNames;
@@ -219,9 +224,6 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document* docum
, m_preload(MediaPlayer::Auto)
, m_displayMode(Unknown)
, m_processingMediaPlayerCallback(0)
-#if ENABLE(MEDIA_SOURCE)
- , m_sourceState(SOURCE_CLOSED)
-#endif
, m_cachedTime(MediaPlayer::invalidTime())
, m_cachedTimeWallClockUpdateTime(0)
, m_minimumWallClockTimeToCacheMediaTime(0)
@@ -272,7 +274,7 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document* docum
}
#if ENABLE(MEDIA_SOURCE)
- m_mediaSourceURL.setProtocol(mediaSourceURLProtocol);
+ m_mediaSourceURL.setProtocol(mediaSourceBlobProtocol);
m_mediaSourceURL.setPath(createCanonicalUUIDString());
#endif
@@ -421,14 +423,6 @@ void HTMLMediaElement::parseAttribute(const Attribute& attribute)
setAttributeEventListener(eventNames().webkitbeginfullscreenEvent, createAttributeEventListener(this, attribute));
else if (attribute.name() == onwebkitendfullscreenAttr)
setAttributeEventListener(eventNames().webkitendfullscreenEvent, createAttributeEventListener(this, attribute));
-#if ENABLE(MEDIA_SOURCE)
- else if (attribute.name() == onwebkitsourcecloseAttr)
- setAttributeEventListener(eventNames().webkitsourcecloseEvent, createAttributeEventListener(this, attribute));
- else if (attribute.name() == onwebkitsourceendedAttr)
- setAttributeEventListener(eventNames().webkitsourceendedEvent, createAttributeEventListener(this, attribute));
- else if (attribute.name() == onwebkitsourceopenAttr)
- setAttributeEventListener(eventNames().webkitsourceopenEvent, createAttributeEventListener(this, attribute));
-#endif
else
HTMLElement::parseAttribute(attribute);
}
@@ -693,6 +687,10 @@ void HTMLMediaElement::prepareForLoad()
if (m_networkState == NETWORK_LOADING || m_networkState == NETWORK_IDLE)
scheduleEvent(eventNames().abortEvent);
+#if ENABLE(MEDIA_SOURCE)
+ setSourceState(MediaSource::closedKeyword());
+#endif
+
#if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
createMediaPlayer();
#else
@@ -702,11 +700,6 @@ void HTMLMediaElement::prepareForLoad()
createMediaPlayerProxy();
#endif
-#if ENABLE(MEDIA_SOURCE)
- if (m_sourceState != SOURCE_CLOSED)
- setSourceState(SOURCE_CLOSED);
-#endif
-
// 4 - If the media element's networkState is not set to NETWORK_EMPTY, then run these substeps
if (m_networkState != NETWORK_EMPTY) {
m_networkState = NETWORK_EMPTY;
@@ -927,10 +920,16 @@ void HTMLMediaElement::loadResource(const KURL& initialURL, ContentType& content
}
#if ENABLE(MEDIA_SOURCE)
- // If this is a media source URL, make sure it is the one for this media element.
- if (url.protocolIs(mediaSourceURLProtocol) && url != m_mediaSourceURL) {
- mediaLoadingFailed(MediaPlayer::FormatError);
- return;
+ if (url.protocolIs(mediaSourceBlobProtocol)) {
+ if (m_mediaSource)
+ m_mediaSource->setReadyState(MediaSource::closedKeyword());
+
+ m_mediaSource = MediaSourceRegistry::registry().lookupMediaSource(url.string());
+
+ if (m_mediaSource) {
+ m_mediaSource->setMediaPlayer(m_player.get());
+ m_mediaSourceURL = url;
+ }
}
#endif
@@ -1432,8 +1431,7 @@ void HTMLMediaElement::noneSupported()
scheduleEvent(eventNames().errorEvent);
#if ENABLE(MEDIA_SOURCE)
- if (m_sourceState != SOURCE_CLOSED)
- setSourceState(SOURCE_CLOSED);
+ setSourceState(MediaSource::closedKeyword());
#endif
// 8 - Set the element's delaying-the-load-event flag to false. This stops delaying the load event.
@@ -1464,8 +1462,7 @@ void HTMLMediaElement::mediaEngineError(PassRefPtr<MediaError> err)
scheduleEvent(eventNames().errorEvent);
#if ENABLE(MEDIA_SOURCE)
- if (m_sourceState != SOURCE_CLOSED)
- setSourceState(SOURCE_CLOSED);
+ setSourceState(MediaSource::closedKeyword());
#endif
// 4 - Set the element's networkState attribute to the NETWORK_EMPTY value and queue a
@@ -1581,7 +1578,6 @@ void HTMLMediaElement::setNetworkState(MediaPlayer::NetworkState state)
if (state == MediaPlayer::Idle) {
if (m_networkState > NETWORK_IDLE) {
changeNetworkStateFromLoadingToIdle();
- scheduleEvent(eventNames().suspendEvent);
setShouldDelayLoadEvent(false);
} else {
m_networkState = NETWORK_IDLE;
@@ -1613,6 +1609,7 @@ void HTMLMediaElement::changeNetworkStateFromLoadingToIdle()
// Schedule one last progress event so we guarantee that at least one is fired
// for files that load very quickly.
scheduleEvent(eventNames().progressEvent);
+ scheduleEvent(eventNames().suspendEvent);
m_networkState = NETWORK_IDLE;
}
@@ -1750,7 +1747,7 @@ void HTMLMediaElement::mediaPlayerSourceOpened()
{
beginProcessingMediaPlayerCallback();
- setSourceState(SOURCE_OPEN);
+ setSourceState(MediaSource::openKeyword());
endProcessingMediaPlayerCallback();
}
@@ -1759,22 +1756,6 @@ String HTMLMediaElement::mediaPlayerSourceURL() const
{
return m_mediaSourceURL.string();
}
-
-bool HTMLMediaElement::isValidSourceId(const String& id, ExceptionCode& ec) const
-{
- if (id.isNull() || id.isEmpty()) {
- ec = INVALID_ACCESS_ERR;
- return false;
- }
-
- if (!m_sourceIDs.contains(id)) {
- ec = SYNTAX_ERR;
- return false;
- }
-
- return true;
-}
-
#endif
#if ENABLE(ENCRYPTED_MEDIA)
@@ -1998,8 +1979,8 @@ void HTMLMediaElement::seek(float time, ExceptionCode& ec)
#if ENABLE(MEDIA_SOURCE)
// Always notify the media engine of a seek if the source is not closed. This ensures that the source is
// always in a flushed state when the 'seeking' event fires.
- if (m_sourceState != SOURCE_CLOSED)
- noSeekRequired = false;
+ if (m_mediaSource && m_mediaSource->readyState() != MediaSource::closedKeyword())
+ noSeekRequired = false;
#endif
if (noSeekRequired) {
@@ -2021,8 +2002,8 @@ void HTMLMediaElement::seek(float time, ExceptionCode& ec)
m_sentEndEvent = false;
#if ENABLE(MEDIA_SOURCE)
- if (m_sourceState == SOURCE_ENDED)
- setSourceState(SOURCE_OPEN);
+ if (m_mediaSource && m_mediaSource->readyState() == MediaSource::endedKeyword())
+ setSourceState(MediaSource::openKeyword());
#endif
// 8 - Set the current playback position to the given new playback position
@@ -2370,175 +2351,12 @@ void HTMLMediaElement::pauseInternal()
}
#if ENABLE(MEDIA_SOURCE)
-
-void HTMLMediaElement::webkitSourceAddId(const String& id, const String& type, ExceptionCode& ec)
-{
- if (id.isNull() || id.isEmpty()) {
- ec = INVALID_ACCESS_ERR;
- return;
- }
-
- if (m_sourceIDs.contains(id)) {
- ec = INVALID_STATE_ERR;
- return;
- }
-
- if (type.isNull() || type.isEmpty()) {
- ec = INVALID_ACCESS_ERR;
- return;
- }
-
- if (!m_player || m_currentSrc != m_mediaSourceURL || m_sourceState != SOURCE_OPEN) {
- ec = INVALID_STATE_ERR;
- return;
- }
-
- ContentType contentType(type);
- Vector<String> codecs = contentType.codecs();
-
- if (!codecs.size()) {
- ec = NOT_SUPPORTED_ERR;
- return;
- }
-
- switch (m_player->sourceAddId(id, contentType.type(), codecs)) {
- case MediaPlayer::Ok:
- m_sourceIDs.add(id);
- return;
- case MediaPlayer::NotSupported:
- ec = NOT_SUPPORTED_ERR;
- return;
- case MediaPlayer::ReachedIdLimit:
- ec = QUOTA_EXCEEDED_ERR;
- return;
- }
-
- ASSERT_NOT_REACHED();
-}
-
-void HTMLMediaElement::webkitSourceRemoveId(const String& id, ExceptionCode& ec)
-{
- if (!isValidSourceId(id, ec))
- return;
-
- if (!m_player || m_currentSrc != m_mediaSourceURL || m_sourceState == SOURCE_CLOSED) {
- ec = INVALID_STATE_ERR;
- return;
- }
-
- if (!m_player->sourceRemoveId(id))
- ASSERT_NOT_REACHED();
-
- m_sourceIDs.remove(id);
-}
-
-PassRefPtr<TimeRanges> HTMLMediaElement::webkitSourceBuffered(const String& id, ExceptionCode& ec)
-{
- if (!isValidSourceId(id, ec))
- return 0;
-
- if (!m_player || m_currentSrc != m_mediaSourceURL || m_sourceState == SOURCE_CLOSED) {
- ec = INVALID_STATE_ERR;
- return 0;
- }
-
- return m_player->sourceBuffered(id);
-}
-
-void HTMLMediaElement::webkitSourceAppend(const String& id, PassRefPtr<Uint8Array> data, ExceptionCode& ec)
-{
- if (!isValidSourceId(id, ec))
- return;
-
- if (!m_player || m_currentSrc != m_mediaSourceURL || m_sourceState != SOURCE_OPEN) {
- ec = INVALID_STATE_ERR;
- return;
- }
-
- if (!data.get()) {
- ec = INVALID_ACCESS_ERR;
- return;
- }
-
- if (!data->length())
- return;
-
- if (!m_player->sourceAppend(id, data->data(), data->length())) {
- ec = SYNTAX_ERR;
- return;
- }
-}
-
-void HTMLMediaElement::webkitSourceAbort(const String& id, ExceptionCode& ec)
-{
- if (!isValidSourceId(id, ec))
- return;
-
- if (!m_player || m_currentSrc != m_mediaSourceURL || m_sourceState != SOURCE_OPEN) {
- ec = INVALID_STATE_ERR;
- return;
- }
-
- if (!m_player->sourceAbort(id))
- ASSERT_NOT_REACHED();
-}
-
-void HTMLMediaElement::webkitSourceEndOfStream(unsigned short status, ExceptionCode& ec)
-{
- if (!m_player || m_currentSrc != m_mediaSourceURL || m_sourceState != SOURCE_OPEN) {
- ec = INVALID_STATE_ERR;
- return;
- }
-
- MediaPlayer::EndOfStreamStatus eosStatus = MediaPlayer::EosNoError;
-
- switch (status) {
- case EOS_NO_ERROR:
- eosStatus = MediaPlayer::EosNoError;
- break;
- case EOS_NETWORK_ERR:
- eosStatus = MediaPlayer::EosNetworkError;
- break;
- case EOS_DECODE_ERR:
- eosStatus = MediaPlayer::EosDecodeError;
- break;
- default:
- ec = SYNTAX_ERR;
- return;
- }
-
- setSourceState(SOURCE_ENDED);
- m_player->sourceEndOfStream(eosStatus);
-}
-
-HTMLMediaElement::SourceState HTMLMediaElement::webkitSourceState() const
+void HTMLMediaElement::setSourceState(const String& state)
{
- return m_sourceState;
-}
+ if (!m_mediaSource)
+ return;
-void HTMLMediaElement::setSourceState(SourceState state)
-{
- SourceState oldState = m_sourceState;
- m_sourceState = static_cast<SourceState>(state);
-
- if (m_sourceState == oldState)
- return;
-
- if (m_sourceState == SOURCE_CLOSED) {
- m_sourceIDs.clear();
- scheduleEvent(eventNames().webkitsourcecloseEvent);
- return;
- }
-
- if (oldState == SOURCE_OPEN && m_sourceState == SOURCE_ENDED) {
- scheduleEvent(eventNames().webkitsourceendedEvent);
- return;
- }
-
- if (m_sourceState == SOURCE_OPEN) {
- scheduleEvent(eventNames().webkitsourceopenEvent);
- return;
- }
+ m_mediaSource->setReadyState(state);
}
#endif
@@ -3351,7 +3169,7 @@ void HTMLMediaElement::mediaPlayerTimeChanged(MediaPlayer*)
invalidateCachedTime();
// 4.8.10.9 step 14 & 15. Needed if no ReadyState change is associated with the seek.
- if (m_seeking && m_readyState >= HAVE_CURRENT_DATA)
+ if (m_seeking && m_readyState >= HAVE_CURRENT_DATA && !m_player->seeking())
finishSeek();
// Always call scheduleTimeupdateEvent when the media engine reports a time discontinuity,
@@ -3793,8 +3611,7 @@ void HTMLMediaElement::userCancelledLoad()
scheduleEvent(eventNames().abortEvent);
#if ENABLE(MEDIA_SOURCE)
- if (m_sourceState != SOURCE_CLOSED)
- setSourceState(SOURCE_CLOSED);
+ setSourceState(MediaSource::closedKeyword());
#endif
// 4 - If the media element's readyState attribute has a value equal to HAVE_NOTHING, set the
@@ -3910,6 +3727,15 @@ void HTMLMediaElement::defaultEventHandler(Event* event)
#endif
}
+bool HTMLMediaElement::willRespondToMouseClickEvents()
+{
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+ return true;
+#else
+ return HTMLElement::willRespondToMouseClickEvents();
+#endif
+}
+
#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
void HTMLMediaElement::ensureMediaPlayer()
@@ -4298,6 +4124,11 @@ void HTMLMediaElement::createMediaPlayer()
m_player = MediaPlayer::create(this);
+#if ENABLE(MEDIA_SOURCE)
+ if (m_mediaSource)
+ m_mediaSource->setMediaPlayer(m_player.get());
+#endif
+
#if ENABLE(WEB_AUDIO)
if (m_audioSourceNode) {
// When creating the player, make sure its AudioSourceProvider knows about the MediaElementAudioSourceNode.