summaryrefslogtreecommitdiff
path: root/Source/WebCore/Modules/mediasource/MediaSource.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2016-04-10 09:28:39 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2016-04-10 09:28:39 +0000
commit32761a6cee1d0dee366b885b7b9c777e67885688 (patch)
treed6bec92bebfb216f4126356e55518842c2f476a1 /Source/WebCore/Modules/mediasource/MediaSource.cpp
parenta4e969f4965059196ca948db781e52f7cfebf19e (diff)
downloadWebKitGtk-tarball-32761a6cee1d0dee366b885b7b9c777e67885688.tar.gz
webkitgtk-2.4.11webkitgtk-2.4.11
Diffstat (limited to 'Source/WebCore/Modules/mediasource/MediaSource.cpp')
-rw-r--r--Source/WebCore/Modules/mediasource/MediaSource.cpp391
1 files changed, 116 insertions, 275 deletions
diff --git a/Source/WebCore/Modules/mediasource/MediaSource.cpp b/Source/WebCore/Modules/mediasource/MediaSource.cpp
index c0d14e165..7a3294676 100644
--- a/Source/WebCore/Modules/mediasource/MediaSource.cpp
+++ b/Source/WebCore/Modules/mediasource/MediaSource.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2013 Google Inc. All rights reserved.
- * Copyright (C) 2013-2014 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -59,63 +58,53 @@
namespace WebCore {
-URLRegistry* MediaSource::s_registry = 0;
-
-void MediaSource::setRegistry(URLRegistry* registry)
+PassRefPtr<MediaSource> MediaSource::create(ScriptExecutionContext& context)
{
- ASSERT(!s_registry);
- s_registry = registry;
-}
-
-Ref<MediaSource> MediaSource::create(ScriptExecutionContext& context)
-{
- Ref<MediaSource> mediaSource(adoptRef(*new MediaSource(context)));
+ RefPtr<MediaSource> mediaSource(adoptRef(new MediaSource(context)));
mediaSource->suspendIfNeeded();
- return mediaSource;
+ return mediaSource.release();
}
MediaSource::MediaSource(ScriptExecutionContext& context)
: ActiveDOMObject(&context)
- , m_mediaElement(nullptr)
- , m_duration(MediaTime::invalidTime())
- , m_pendingSeekTime(MediaTime::invalidTime())
+ , m_mediaElement(0)
, m_readyState(closedKeyword())
, m_asyncEventQueue(*this)
{
- LOG(MediaSource, "MediaSource::MediaSource %p", this);
+ LOG(Media, "MediaSource::MediaSource %p", this);
m_sourceBuffers = SourceBufferList::create(scriptExecutionContext());
m_activeSourceBuffers = SourceBufferList::create(scriptExecutionContext());
}
MediaSource::~MediaSource()
{
- LOG(MediaSource, "MediaSource::~MediaSource %p", this);
+ LOG(Media, "MediaSource::~MediaSource %p", this);
ASSERT(isClosed());
}
const AtomicString& MediaSource::openKeyword()
{
- static NeverDestroyed<const AtomicString> open("open", AtomicString::ConstructFromLiteral);
+ DEFINE_STATIC_LOCAL(const AtomicString, open, ("open", AtomicString::ConstructFromLiteral));
return open;
}
const AtomicString& MediaSource::closedKeyword()
{
- static NeverDestroyed<const AtomicString> closed("closed", AtomicString::ConstructFromLiteral);
+ DEFINE_STATIC_LOCAL(const AtomicString, closed, ("closed", AtomicString::ConstructFromLiteral));
return closed;
}
const AtomicString& MediaSource::endedKeyword()
{
- static NeverDestroyed<const AtomicString> ended("ended", AtomicString::ConstructFromLiteral);
+ DEFINE_STATIC_LOCAL(const AtomicString, ended, ("ended", AtomicString::ConstructFromLiteral));
return ended;
}
-void MediaSource::setPrivateAndOpen(Ref<MediaSourcePrivate>&& mediaSourcePrivate)
+void MediaSource::setPrivateAndOpen(PassRef<MediaSourcePrivate> mediaSourcePrivate)
{
ASSERT(!m_private);
ASSERT(m_mediaElement);
- m_private = WTFMove(mediaSourcePrivate);
+ m_private = std::move(mediaSourcePrivate);
setReadyState(openKeyword());
}
@@ -129,137 +118,110 @@ void MediaSource::removedFromRegistry()
unsetPendingActivity(this);
}
-MediaTime MediaSource::duration() const
-{
- return m_duration;
-}
-
-MediaTime MediaSource::currentTime() const
+double MediaSource::duration() const
{
- return m_mediaElement ? m_mediaElement->currentMediaTime() : MediaTime::zeroTime();
+ return isClosed() ? std::numeric_limits<float>::quiet_NaN() : m_private->duration();
}
-std::unique_ptr<PlatformTimeRanges> MediaSource::buffered() const
+PassRefPtr<TimeRanges> MediaSource::buffered() const
{
// Implements MediaSource algorithm for HTMLMediaElement.buffered.
// https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#htmlmediaelement-extensions
- Vector<PlatformTimeRanges> activeRanges = this->activeRanges();
+ Vector<RefPtr<TimeRanges>> ranges = activeRanges();
// 1. If activeSourceBuffers.length equals 0 then return an empty TimeRanges object and abort these steps.
- if (activeRanges.isEmpty())
- return std::make_unique<PlatformTimeRanges>();
+ if (ranges.isEmpty())
+ return TimeRanges::create();
// 2. Let active ranges be the ranges returned by buffered for each SourceBuffer object in activeSourceBuffers.
// 3. Let highest end time be the largest range end time in the active ranges.
- MediaTime highestEndTime = MediaTime::zeroTime();
- for (auto& ranges : activeRanges) {
- unsigned length = ranges.length();
+ double highestEndTime = -1;
+ for (size_t i = 0; i < ranges.size(); ++i) {
+ unsigned length = ranges[i]->length();
if (length)
- highestEndTime = std::max(highestEndTime, ranges.end(length - 1));
+ highestEndTime = std::max(highestEndTime, ranges[i]->end(length - 1, ASSERT_NO_EXCEPTION));
}
// Return an empty range if all ranges are empty.
- if (!highestEndTime)
- return std::make_unique<PlatformTimeRanges>();
+ if (highestEndTime < 0)
+ return TimeRanges::create();
// 4. Let intersection ranges equal a TimeRange object containing a single range from 0 to highest end time.
- PlatformTimeRanges intersectionRanges(MediaTime::zeroTime(), highestEndTime);
+ RefPtr<TimeRanges> intersectionRanges = TimeRanges::create(0, highestEndTime);
// 5. For each SourceBuffer object in activeSourceBuffers run the following steps:
bool ended = readyState() == endedKeyword();
- for (auto& sourceRanges : activeRanges) {
+ for (size_t i = 0; i < ranges.size(); ++i) {
// 5.1 Let source ranges equal the ranges returned by the buffered attribute on the current SourceBuffer.
+ TimeRanges* sourceRanges = ranges[i].get();
+
// 5.2 If readyState is "ended", then set the end time on the last range in source ranges to highest end time.
- if (ended && sourceRanges.length())
- sourceRanges.add(sourceRanges.start(sourceRanges.length() - 1), highestEndTime);
+ if (ended && sourceRanges->length())
+ sourceRanges->add(sourceRanges->start(sourceRanges->length() - 1, ASSERT_NO_EXCEPTION), highestEndTime);
// 5.3 Let new intersection ranges equal the the intersection between the intersection ranges and the source ranges.
// 5.4 Replace the ranges in intersection ranges with the new intersection ranges.
- intersectionRanges.intersectWith(sourceRanges);
+ intersectionRanges->intersectWith(sourceRanges);
}
- return std::make_unique<PlatformTimeRanges>(intersectionRanges);
+ return intersectionRanges.release();
}
-void MediaSource::seekToTime(const MediaTime& time)
-{
- // 2.4.3 Seeking
- // https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#mediasource-seeking
-
- m_pendingSeekTime = time;
-
- // Run the following steps as part of the "Wait until the user agent has established whether or not the
- // media data for the new playback position is available, and, if it is, until it has decoded enough data
- // to play back that position" step of the seek algorithm:
- // 1. The media element looks for media segments containing the new playback position in each SourceBuffer
- // object in activeSourceBuffers.
- for (auto& sourceBuffer : *m_activeSourceBuffers) {
- // ↳ If one or more of the objects in activeSourceBuffers is missing media segments for the new
- // playback position
- if (!sourceBuffer->buffered()->ranges().contain(time)) {
- // 1.1 Set the HTMLMediaElement.readyState attribute to HAVE_METADATA.
- m_private->setReadyState(MediaPlayer::HaveMetadata);
-
- // 1.2 The media element waits until an appendBuffer() or an appendStream() call causes the coded
- // frame processing algorithm to set the HTMLMediaElement.readyState attribute to a value greater
- // than HAVE_METADATA.
- LOG(MediaSource, "MediaSource::seekToTime(%p) - waitForSeekCompleted()", this);
- m_private->waitForSeekCompleted();
- return;
- }
- // ↳ Otherwise
- // Continue
+class SourceBufferBufferedDoesNotContainTime {
+public:
+ SourceBufferBufferedDoesNotContainTime(double time) : m_time(time) { }
+ bool operator()(RefPtr<SourceBuffer> sourceBuffer)
+ {
+ return !sourceBuffer->buffered()->contain(m_time);
}
- completeSeek();
-}
-
-void MediaSource::completeSeek()
-{
- // 2.4.3 Seeking, ctd.
- // https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#mediasource-seeking
+ double m_time;
+};
- ASSERT(m_pendingSeekTime.isValid());
+class SourceBufferBufferedHasEnough {
+public:
+ SourceBufferBufferedHasEnough(double time, double duration) : m_time(time), m_duration(duration) { }
+ bool operator()(RefPtr<SourceBuffer> sourceBuffer)
+ {
+ size_t rangePos = sourceBuffer->buffered()->find(m_time);
+ if (rangePos == notFound)
+ return false;
- // 2. The media element resets all decoders and initializes each one with data from the appropriate
- // initialization segment.
- // 3. The media element feeds coded frames from the active track buffers into the decoders starting
- // with the closest random access point before the new playback position.
- for (auto& sourceBuffer : *m_activeSourceBuffers)
- sourceBuffer->seekToTime(m_pendingSeekTime);
+ double endTime = sourceBuffer->buffered()->end(rangePos, IGNORE_EXCEPTION);
+ return m_duration - endTime < 1;
+ }
- // 4. Resume the seek algorithm at the "Await a stable state" step.
- m_private->seekCompleted();
+ double m_time;
+ double m_duration;
+};
+
+class SourceBufferBufferedHasFuture {
+public:
+ SourceBufferBufferedHasFuture(double time) : m_time(time) { }
+ bool operator()(RefPtr<SourceBuffer> sourceBuffer)
+ {
+ size_t rangePos = sourceBuffer->buffered()->find(m_time);
+ if (rangePos == notFound)
+ return false;
+
+ double endTime = sourceBuffer->buffered()->end(rangePos, IGNORE_EXCEPTION);
+ return endTime - m_time > 1;
+ }
- m_pendingSeekTime = MediaTime::invalidTime();
- monitorSourceBuffers();
-}
+ double m_time;
+};
void MediaSource::monitorSourceBuffers()
{
+ double currentTime = mediaElement()->currentTime();
+
// 2.4.4 SourceBuffer Monitoring
// https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#buffer-monitoring
-
- // Note, the behavior if activeSourceBuffers is empty is undefined.
- if (!m_activeSourceBuffers) {
- m_private->setReadyState(MediaPlayer::HaveNothing);
- return;
- }
-
- // http://w3c.github.io/media-source/#buffer-monitoring, change from 11 December 2014
- // ↳ If the the HTMLMediaElement.readyState attribute equals HAVE_NOTHING:
- if (mediaElement()->readyState() == HTMLMediaElement::HAVE_NOTHING) {
- // 1. Abort these steps.
- return;
- }
-
// ↳ If buffered for all objects in activeSourceBuffers do not contain TimeRanges for the current
// playback position:
auto begin = m_activeSourceBuffers->begin();
auto end = m_activeSourceBuffers->end();
- if (std::all_of(begin, end, [](RefPtr<SourceBuffer>& sourceBuffer) {
- return !sourceBuffer->hasCurrentTime();
- })) {
+ if (std::all_of(begin, end, SourceBufferBufferedDoesNotContainTime(currentTime))) {
// 1. Set the HTMLMediaElement.readyState attribute to HAVE_METADATA.
// 2. If this is the first transition to HAVE_METADATA, then queue a task to fire a simple event
// named loadedmetadata at the media element.
@@ -271,34 +233,24 @@ void MediaSource::monitorSourceBuffers()
// ↳ If buffered for all objects in activeSourceBuffers contain TimeRanges that include the current
// playback position and enough data to ensure uninterrupted playback:
- if (std::all_of(begin, end, [](RefPtr<SourceBuffer>& sourceBuffer) {
- return sourceBuffer->hasFutureTime() && sourceBuffer->canPlayThrough();
- })) {
+ if (std::all_of(begin, end, SourceBufferBufferedHasEnough(currentTime, mediaElement()->duration()))) {
// 1. Set the HTMLMediaElement.readyState attribute to HAVE_ENOUGH_DATA.
// 2. Queue a task to fire a simple event named canplaythrough at the media element.
// 3. Playback may resume at this point if it was previously suspended by a transition to HAVE_CURRENT_DATA.
m_private->setReadyState(MediaPlayer::HaveEnoughData);
- if (m_pendingSeekTime.isValid())
- completeSeek();
-
// 4. Abort these steps.
return;
}
- // ↳ If buffered for all objects in activeSourceBuffers contain a TimeRange that includes
- // the current playback position and some time beyond the current playback position, then run the following steps:
- if (std::all_of(begin, end, [](RefPtr<SourceBuffer>& sourceBuffer) {
- return sourceBuffer->hasFutureTime();
- })) {
+ // ↳ If buffered for at least one object in activeSourceBuffers contains a TimeRange that includes
+ // the current playback position but not enough data to ensure uninterrupted playback:
+ if (std::any_of(begin, end, SourceBufferBufferedHasFuture(currentTime))) {
// 1. Set the HTMLMediaElement.readyState attribute to HAVE_FUTURE_DATA.
// 2. If the previous value of HTMLMediaElement.readyState was less than HAVE_FUTURE_DATA, then queue a task to fire a simple event named canplay at the media element.
// 3. Playback may resume at this point if it was previously suspended by a transition to HAVE_CURRENT_DATA.
m_private->setReadyState(MediaPlayer::HaveFutureData);
- if (m_pendingSeekTime.isValid())
- completeSeek();
-
// 4. Abort these steps.
return;
}
@@ -314,89 +266,34 @@ void MediaSource::monitorSourceBuffers()
// 3. Playback is suspended at this point since the media element doesn't have enough data to
// advance the media timeline.
m_private->setReadyState(MediaPlayer::HaveCurrentData);
-
- if (m_pendingSeekTime.isValid())
- completeSeek();
-
+
// 4. Abort these steps.
}
void MediaSource::setDuration(double duration, ExceptionCode& ec)
{
- // 2.1 Attributes - Duration
- // https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#attributes
-
- // On setting, run the following steps:
- // 1. If the value being set is negative or NaN then throw an INVALID_ACCESS_ERR exception and abort these steps.
if (duration < 0.0 || std::isnan(duration)) {
ec = INVALID_ACCESS_ERR;
return;
}
-
- // 2. If the readyState attribute is not "open" then throw an INVALID_STATE_ERR exception and abort these steps.
if (!isOpen()) {
ec = INVALID_STATE_ERR;
return;
}
-
- // 3. If the updating attribute equals true on any SourceBuffer in sourceBuffers, then throw an INVALID_STATE_ERR
- // exception and abort these steps.
- for (auto& sourceBuffer : *m_sourceBuffers) {
- if (sourceBuffer->updating()) {
- ec = INVALID_STATE_ERR;
- return;
- }
- }
-
- // 4. Run the duration change algorithm with new duration set to the value being assigned to this attribute.
- setDurationInternal(MediaTime::createWithDouble(duration));
+ m_private->setDuration(duration);
}
-void MediaSource::setDurationInternal(const MediaTime& duration)
-{
- // Duration Change Algorithm
- // https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#duration-change-algorithm
-
- // 1. If the current value of duration is equal to new duration, then return.
- if (duration == m_duration)
- return;
-
- // 2. Set old duration to the current value of duration.
- MediaTime oldDuration = m_duration;
-
- // 3. Update duration to new duration.
- m_duration = duration;
-
- // 4. If the new duration is less than old duration, then call remove(new duration, old duration)
- // on all objects in sourceBuffers.
- if (oldDuration.isValid() && duration < oldDuration) {
- for (auto& sourceBuffer : *m_sourceBuffers)
- sourceBuffer->rangeRemoval(duration, oldDuration);
- }
-
- // 5. If a user agent is unable to partially render audio frames or text cues that start before and end after the
- // duration, then run the following steps:
- // 5.1 Update new duration to the highest end time reported by the buffered attribute across all SourceBuffer objects
- // in sourceBuffers.
- // 5.2 Update duration to new duration.
- // NOTE: Assume UA is able to partially render audio frames.
-
- // 6. Update the media controller duration to new duration and run the HTMLMediaElement duration change algorithm.
- LOG(MediaSource, "MediaSource::setDurationInternal(%p) - duration(%g)", this, duration.toDouble());
- m_private->durationChanged();
-}
void MediaSource::setReadyState(const AtomicString& state)
{
ASSERT(state == openKeyword() || state == closedKeyword() || state == endedKeyword());
AtomicString oldState = readyState();
- LOG(MediaSource, "MediaSource::setReadyState(%p) : %s -> %s", this, oldState.string().ascii().data(), state.string().ascii().data());
+ LOG(Media, "MediaSource::setReadyState() %p : %s -> %s", this, oldState.string().ascii().data(), state.string().ascii().data());
if (state == closedKeyword()) {
- m_private = nullptr;
- m_mediaElement = nullptr;
- m_duration = MediaTime::invalidTime();
+ m_private.clear();
+ m_mediaElement = 0;
}
if (oldState == state)
@@ -412,11 +309,6 @@ static bool SourceBufferIsUpdating(RefPtr<SourceBuffer>& sourceBuffer)
return sourceBuffer->updating();
}
-void MediaSource::endOfStream(ExceptionCode& ec)
-{
- endOfStream(emptyAtom, ec);
-}
-
void MediaSource::endOfStream(const AtomicString& error, ExceptionCode& ec)
{
// 2.2 https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#widl-MediaSource-endOfStream-void-EndOfStreamError-error
@@ -440,13 +332,10 @@ void MediaSource::endOfStream(const AtomicString& error, ExceptionCode& ec)
void MediaSource::streamEndedWithError(const AtomicString& error, ExceptionCode& ec)
{
- static NeverDestroyed<const AtomicString> network("network", AtomicString::ConstructFromLiteral);
- static NeverDestroyed<const AtomicString> decode("decode", AtomicString::ConstructFromLiteral);
-
- LOG(MediaSource, "MediaSource::streamEndedWithError(%p) : %s", this, error.string().ascii().data());
+ DEFINE_STATIC_LOCAL(const AtomicString, network, ("network", AtomicString::ConstructFromLiteral));
+ DEFINE_STATIC_LOCAL(const AtomicString, decode, ("decode", AtomicString::ConstructFromLiteral));
// 2.4.7 https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#end-of-stream-algorithm
-
// 1. Change the readyState attribute value to "ended".
// 2. Queue a task to fire a simple event named sourceended at the MediaSource.
setReadyState(endedKeyword());
@@ -454,20 +343,16 @@ void MediaSource::streamEndedWithError(const AtomicString& error, ExceptionCode&
// 3.
if (error.isEmpty()) {
// ↳ If error is not set, is null, or is an empty string
- // 1. Run the duration change algorithm with new duration set to the highest end time reported by
- // the buffered attribute across all SourceBuffer objects in sourceBuffers.
- MediaTime maxEndTime;
- for (auto& sourceBuffer : *m_sourceBuffers) {
- if (auto length = sourceBuffer->buffered()->length())
- maxEndTime = std::max(sourceBuffer->buffered()->ranges().end(length - 1), maxEndTime);
- }
- setDurationInternal(maxEndTime);
+ // 1. Run the duration change algorithm with new duration set to the highest end timestamp
+ // across all SourceBuffer objects in sourceBuffers.
+ MediaTime maxEndTimestamp;
+ for (auto it = m_sourceBuffers->begin(), end = m_sourceBuffers->end(); it != end; ++it)
+ maxEndTimestamp = std::max((*it)->highestPresentationEndTimestamp(), maxEndTimestamp);
+ m_private->setDuration(maxEndTimestamp.toDouble());
// 2. Notify the media element that it now has all of the media data.
m_private->markEndOfStream(MediaSourcePrivate::EosNoError);
- }
-
- if (error == network) {
+ } else if (error == network) {
// ↳ If error is set to "network"
ASSERT(m_mediaElement);
if (m_mediaElement->readyState() == HTMLMediaElement::HAVE_NOTHING) {
@@ -498,7 +383,7 @@ void MediaSource::streamEndedWithError(const AtomicString& error, ExceptionCode&
// NOTE: This step is handled by HTMLMediaElement::mediaLoadingFailedFatally().
m_mediaElement->mediaLoadingFailedFatally(MediaPlayer::DecodeError);
}
- } else if (!error.isEmpty()) {
+ } else {
// ↳ Otherwise
// Throw an INVALID_ACCESS_ERR exception.
ec = INVALID_ACCESS_ERR;
@@ -507,11 +392,9 @@ void MediaSource::streamEndedWithError(const AtomicString& error, ExceptionCode&
SourceBuffer* MediaSource::addSourceBuffer(const String& type, ExceptionCode& ec)
{
- LOG(MediaSource, "MediaSource::addSourceBuffer(%s) %p", type.ascii().data(), this);
-
- // 2.2 http://www.w3.org/TR/media-source/#widl-MediaSource-addSourceBuffer-SourceBuffer-DOMString-type
- // When this method is invoked, the user agent must run the following steps:
+ LOG(Media, "MediaSource::addSourceBuffer(%s) %p", type.ascii().data(), this);
+ // 2.2 https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-MediaSource-addSourceBuffer-SourceBuffer-DOMString-type
// 1. If type is null or an empty then throw an INVALID_ACCESS_ERR exception and
// abort these steps.
if (type.isNull() || type.isEmpty()) {
@@ -545,31 +428,16 @@ SourceBuffer* MediaSource::addSourceBuffer(const String& type, ExceptionCode& ec
}
RefPtr<SourceBuffer> buffer = SourceBuffer::create(sourceBufferPrivate.releaseNonNull(), this);
-
- // 6. Set the generate timestamps flag on the new object to the value in the "Generate Timestamps Flag"
- // column of the byte stream format registry [MSE-REGISTRY] entry that is associated with type.
- // NOTE: In the current byte stream format registry <http://www.w3.org/2013/12/byte-stream-format-registry/>
- // only the "MPEG Audio Byte Stream Format" has the "Generate Timestamps Flag" value set.
- bool shouldGenerateTimestamps = contentType.type() == "audio/aac" || contentType.type() == "audio/mpeg";
- buffer->setShouldGenerateTimestamps(shouldGenerateTimestamps);
-
- // 7. If the generate timestamps flag equals true:
- // ↳ Set the mode attribute on the new object to "sequence".
- // Otherwise:
- // ↳ Set the mode attribute on the new object to "segments".
- buffer->setMode(shouldGenerateTimestamps ? SourceBuffer::sequenceKeyword() : SourceBuffer::segmentsKeyword(), IGNORE_EXCEPTION);
-
- // 8. Add the new object to sourceBuffers and fire a addsourcebuffer on that object.
+ // 6. Add the new object to sourceBuffers and fire a addsourcebuffer on that object.
m_sourceBuffers->add(buffer);
- regenerateActiveSourceBuffers();
-
- // 9. Return the new object to the caller.
+ m_activeSourceBuffers->add(buffer);
+ // 7. Return the new object to the caller.
return buffer.get();
}
void MediaSource::removeSourceBuffer(SourceBuffer* buffer, ExceptionCode& ec)
{
- LOG(MediaSource, "MediaSource::removeSourceBuffer() %p", this);
+ LOG(Media, "MediaSource::removeSourceBuffer() %p", this);
RefPtr<SourceBuffer> protect(buffer);
// 2.2 https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-MediaSource-removeSourceBuffer-void-SourceBuffer-sourceBuffer
@@ -605,7 +473,7 @@ void MediaSource::removeSourceBuffer(SourceBuffer* buffer, ExceptionCode& ec)
AudioTrack* track = audioTracks->lastItem();
// 5.3.1 Set the sourceBuffer attribute on the AudioTrack object to null.
- track->setSourceBuffer(nullptr);
+ track->setSourceBuffer(0);
// 5.3.2 If the enabled attribute on the AudioTrack object is true, then set the removed enabled
// audio track flag to true.
@@ -645,7 +513,7 @@ void MediaSource::removeSourceBuffer(SourceBuffer* buffer, ExceptionCode& ec)
VideoTrack* track = videoTracks->lastItem();
// 7.3.1 Set the sourceBuffer attribute on the VideoTrack object to null.
- track->setSourceBuffer(nullptr);
+ track->setSourceBuffer(0);
// 7.3.2 If the selected attribute on the VideoTrack object is true, then set the removed selected
// video track flag to true.
@@ -685,7 +553,7 @@ void MediaSource::removeSourceBuffer(SourceBuffer* buffer, ExceptionCode& ec)
TextTrack* track = textTracks->lastItem();
// 9.3.1 Set the sourceBuffer attribute on the TextTrack object to null.
- track->setSourceBuffer(nullptr);
+ track->setSourceBuffer(0);
// 9.3.2 If the mode attribute on the TextTrack object is set to "showing" or "hidden", then
// set the removed enabled text track flag to true.
@@ -724,7 +592,7 @@ void MediaSource::removeSourceBuffer(SourceBuffer* buffer, ExceptionCode& ec)
bool MediaSource::isTypeSupported(const String& type)
{
- LOG(MediaSource, "MediaSource::isTypeSupported(%s)", type.ascii().data());
+ LOG(Media, "MediaSource::isTypeSupported(%s)", type.ascii().data());
// Section 2.2 isTypeSupported() method steps.
// https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#widl-MediaSource-isTypeSupported-boolean-DOMString-type
@@ -732,12 +600,11 @@ bool MediaSource::isTypeSupported(const String& type)
if (type.isNull() || type.isEmpty())
return false;
- // FIXME: Why do we convert to lowercase here, but not in MediaSource::addSourceBuffer?
- ContentType contentType(type.convertToASCIILowercase());
+ ContentType contentType(type);
String codecs = contentType.parameter("codecs");
// 2. If type does not contain a valid MIME type string, then return false.
- if (contentType.type().isEmpty())
+ if (contentType.type().isEmpty() || codecs.isEmpty())
return false;
// 3. If type contains a media type or media subtype that the MediaSource does not support, then return false.
@@ -748,12 +615,7 @@ bool MediaSource::isTypeSupported(const String& type)
parameters.type = contentType.type();
parameters.codecs = codecs;
parameters.isMediaSource = true;
- MediaPlayer::SupportsType supported = MediaPlayer::supportsType(parameters, 0);
-
- if (codecs.isEmpty())
- return supported != MediaPlayer::IsNotSupported;
-
- return supported == MediaPlayer::IsSupported;
+ return MediaPlayer::supportsType(parameters, 0) != MediaPlayer::IsNotSupported;
}
bool MediaSource::isOpen() const
@@ -766,19 +628,17 @@ bool MediaSource::isClosed() const
return readyState() == closedKeyword();
}
-bool MediaSource::isEnded() const
-{
- return readyState() == endedKeyword();
-}
-
void MediaSource::close()
{
setReadyState(closedKeyword());
}
-void MediaSource::sourceBufferDidChangeAcitveState(SourceBuffer*, bool)
+void MediaSource::sourceBufferDidChangeAcitveState(SourceBuffer* sourceBuffer, bool active)
{
- regenerateActiveSourceBuffers();
+ if (active && !m_activeSourceBuffers->contains(sourceBuffer))
+ m_activeSourceBuffers->add(sourceBuffer);
+ else if (!active && m_activeSourceBuffers->contains(sourceBuffer))
+ m_activeSourceBuffers->remove(sourceBuffer);
}
bool MediaSource::attachToElement(HTMLMediaElement* element)
@@ -812,17 +672,7 @@ void MediaSource::stop()
m_asyncEventQueue.close();
if (!isClosed())
setReadyState(closedKeyword());
- m_private = nullptr;
-}
-
-bool MediaSource::canSuspendForDocumentSuspension() const
-{
- return isClosed() && !m_asyncEventQueue.hasPendingEvents();
-}
-
-const char* MediaSource::activeDOMObjectName() const
-{
- return "MediaSource";
+ m_private.clear();
}
void MediaSource::onReadyStateChange(const AtomicString& oldState, const AtomicString& newState)
@@ -842,18 +692,19 @@ void MediaSource::onReadyStateChange(const AtomicString& oldState, const AtomicS
m_activeSourceBuffers->clear();
// Clear SourceBuffer references to this object.
- for (auto& buffer : *m_sourceBuffers)
- buffer->removedFromMediaSource();
+ for (unsigned long i = 0, length = m_sourceBuffers->length(); i < length; ++i)
+ m_sourceBuffers->item(i)->removedFromMediaSource();
m_sourceBuffers->clear();
scheduleEvent(eventNames().sourcecloseEvent);
}
-Vector<PlatformTimeRanges> MediaSource::activeRanges() const
+Vector<RefPtr<TimeRanges>> MediaSource::activeRanges() const
{
- Vector<PlatformTimeRanges> activeRanges;
- for (auto& sourceBuffer : *m_activeSourceBuffers)
- activeRanges.append(sourceBuffer->buffered()->ranges());
+ Vector<RefPtr<TimeRanges>> activeRanges(m_activeSourceBuffers->length());
+ for (size_t i = 0, length = m_activeSourceBuffers->length(); i < length; ++i)
+ activeRanges[i] = m_activeSourceBuffers->item(i)->buffered(ASSERT_NO_EXCEPTION);
+
return activeRanges;
}
@@ -906,16 +757,6 @@ URLRegistry& MediaSource::registry() const
return MediaSourceRegistry::registry();
}
-void MediaSource::regenerateActiveSourceBuffers()
-{
- Vector<RefPtr<SourceBuffer>> newList;
- for (auto& sourceBuffer : *m_sourceBuffers) {
- if (sourceBuffer->active())
- newList.append(sourceBuffer);
- }
- m_activeSourceBuffers->swap(newList);
-}
-
}
#endif