void InbandDataTextTrack::updateDataCue(InbandTextTrackPrivate*, const MediaTime& start, const MediaTime& inEnd, PassRefPtr<SerializedPlatformRepresentation> prpPlatformValue)
{
    MediaTime end = inEnd;

    RefPtr<SerializedPlatformRepresentation> platformValue = prpPlatformValue;
    auto iter = m_incompleteCueMap.find(platformValue.get());
    if (iter == m_incompleteCueMap.end())
        return;

    RefPtr<DataCue> cue = iter->value;
    if (!cue)
        return;

    cue->willChange();

    if (end.isPositiveInfinite() && mediaElement())
        end = mediaElement()->durationMediaTime();
    else
        m_incompleteCueMap.remove(platformValue.get());

    LOG(Media, "InbandDataTextTrack::updateDataCue: was start=%s, end=%s, will be start=%s, end=%s\n", toString(cue->startTime()).utf8().data(), toString(cue->endTime()).utf8().data(), toString(start).utf8().data(), toString(end).utf8().data());

    cue->setStartTime(start);
    cue->setEndTime(end);

    cue->didChange();
}
Пример #2
0
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();
}
Пример #3
0
MediaTime abs(const MediaTime& rhs)
{
    if (rhs.isInvalid())
        return MediaTime::invalidTime();
    if (rhs.isNegativeInfinite() || rhs.isPositiveInfinite())
        return MediaTime::positiveInfiniteTime();
    MediaTime val = rhs;
    val.m_timeValue *= signum(rhs.m_timeScale) * signum(rhs.m_timeValue);
    return val;
}
MediaTime MediaPlayerPrivateAVFoundation::durationMediaTime() const
{
    if (m_cachedDuration.isValid())
        return m_cachedDuration;

    MediaTime duration = platformDuration();
    if (!duration || duration.isInvalid())
        return MediaTime::zeroTime();

    m_cachedDuration = duration;
    LOG(Media, "MediaPlayerPrivateAVFoundation::duration(%p) - caching %s", this, toString(m_cachedDuration).utf8().data());
    return m_cachedDuration;
}
void InbandMetadataTextTrackPrivateAVF::addDataCue(const MediaTime& start, const MediaTime& end, PassRefPtr<SerializedPlatformRepresentation> prpCueData, const String& type)
{
    ASSERT(cueFormat() == Data);
    if (!client())
        return;

    RefPtr<SerializedPlatformRepresentation> cueData = prpCueData;
    m_currentCueStartTime = start;
    if (end.isPositiveInfinite())
        m_incompleteCues.append(IncompleteMetaDataCue { cueData.get(), start });
    client()->addDataCue(this, start, end, cueData, type);
}
Пример #6
0
MediaTime MediaTime::operator-() const
{
    if (isInvalid())
        return invalidTime();

    if (isIndefinite())
        return indefiniteTime();

    if (isPositiveInfinite())
        return negativeInfiniteTime();

    if (isNegativeInfinite())
        return positiveInfiniteTime();

    MediaTime negativeTime = *this;
    if (negativeTime.hasDoubleValue())
        negativeTime.m_timeValueAsDouble = -negativeTime.m_timeValueAsDouble;
    else
        negativeTime.m_timeValue = -negativeTime.m_timeValue;
    return negativeTime;
}
Пример #7
0
MediaTime MediaTime::operator*(int32_t rhs) const
{
    if (isInvalid())
        return invalidTime();

    if (isIndefinite())
        return indefiniteTime();

    if (!rhs)
        return zeroTime();

    if (isPositiveInfinite()) {
        if (rhs > 0)
            return positiveInfiniteTime();
        return negativeInfiniteTime();
    }

    if (isNegativeInfinite()) {
        if (rhs > 0)
            return negativeInfiniteTime();
        return positiveInfiniteTime();
    }

    MediaTime a = *this;

    if (a.hasDoubleValue()) {
        a.m_timeValueAsDouble *= rhs;
        return a;
    }

    while (!safeMultiply(a.m_timeValue, rhs, a.m_timeValue)) {
        if (a.m_timeScale == 1)
            return signum(a.m_timeValue) == signum(rhs) ? positiveInfiniteTime() : negativeInfiniteTime();
        a.setTimeScale(a.m_timeScale / 2);
    }

    return a;
}
Пример #8
0
MediaTime MediaTime::operator-(const MediaTime& rhs) const
{
    if (rhs.isInvalid() || isInvalid())
        return invalidTime();

    if (rhs.isIndefinite() || isIndefinite())
        return indefiniteTime();

    if (isPositiveInfinite()) {
        if (rhs.isPositiveInfinite())
            return invalidTime();
        return positiveInfiniteTime();
    }

    if (isNegativeInfinite()) {
        if (rhs.isNegativeInfinite())
            return invalidTime();
        return negativeInfiniteTime();
    }

    int32_t commonTimeScale;
    if (!leastCommonMultiple(this->m_timeScale, rhs.m_timeScale, commonTimeScale) || commonTimeScale > MaximumTimeScale)
        commonTimeScale = MaximumTimeScale;
    MediaTime a = *this;
    MediaTime b = rhs;
    a.setTimeScale(commonTimeScale);
    b.setTimeScale(commonTimeScale);
    while (!safeSub(a.m_timeValue, b.m_timeValue, a.m_timeValue)) {
        if (commonTimeScale == 1)
            return a.m_timeValue > 0 ? positiveInfiniteTime() : negativeInfiniteTime();
        commonTimeScale /= 2;
        a.setTimeScale(commonTimeScale);
        b.setTimeScale(commonTimeScale);
    }
    return a;
}
Пример #9
0
MediaTime::ComparisonFlags MediaTime::compare(const MediaTime& rhs) const
{
    if ((isPositiveInfinite() && rhs.isPositiveInfinite())
        || (isNegativeInfinite() && rhs.isNegativeInfinite())
        || (isInvalid() && rhs.isInvalid())
        || (isIndefinite() && rhs.isIndefinite()))
        return EqualTo;

    if (isInvalid())
        return GreaterThan;

    if (rhs.isInvalid())
        return LessThan;

    if (rhs.isNegativeInfinite() || isPositiveInfinite())
        return GreaterThan;

    if (rhs.isPositiveInfinite() || isNegativeInfinite())
        return LessThan;

    if (isIndefinite())
        return GreaterThan;

    if (rhs.isIndefinite())
        return LessThan;

    int64_t rhsWhole = rhs.m_timeValue / rhs.m_timeScale;
    int64_t lhsWhole = m_timeValue / m_timeScale;
    if (lhsWhole > rhsWhole)
        return GreaterThan;
    if (lhsWhole < rhsWhole)
        return LessThan;

    int64_t rhsRemain = rhs.m_timeValue % rhs.m_timeScale;
    int64_t lhsRemain = m_timeValue % m_timeScale;
    int64_t lhsFactor = lhsRemain * rhs.m_timeScale;
    int64_t rhsFactor = rhsRemain * m_timeScale;

    if (lhsFactor == rhsFactor)
        return EqualTo;
    return lhsFactor > rhsFactor ? GreaterThan : LessThan;
}
void InbandDataTextTrack::addDataCue(InbandTextTrackPrivate*, const MediaTime& start, const MediaTime& end, PassRefPtr<SerializedPlatformRepresentation> prpPlatformValue, const String& type)
{
    RefPtr<SerializedPlatformRepresentation> platformValue = prpPlatformValue;
    if (m_incompleteCueMap.find(platformValue.get()) != m_incompleteCueMap.end())
        return;

    auto cue = DataCue::create(*scriptExecutionContext(), start, end, platformValue.copyRef(), type);
    if (hasCue(cue.ptr(), TextTrackCue::IgnoreDuration)) {
        LOG(Media, "InbandDataTextTrack::addDataCue ignoring already added cue: start=%s, end=%s\n", toString(cue->startTime()).utf8().data(), toString(cue->endTime()).utf8().data());
        return;
    }

    if (end.isPositiveInfinite() && mediaElement()) {
        cue->setEndTime(mediaElement()->durationMediaTime());
        m_incompleteCueMap.add(WTFMove(platformValue), cue.copyRef());
    }

    addCue(WTFMove(cue), ASSERT_NO_EXCEPTION);
}
Пример #11
0
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;

    LOG(MediaSource, "MediaSource::seekToTime(%p, %f): %lu active source buffers", this, time.toDouble(), m_activeSourceBuffers->length());
    // 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;
        } else
            LOG(MediaSource, "MediaSource::seekToTime(%p) - seek time buffered already.", this);
        // ↳ Otherwise
        // Continue
    }

    completeSeek();
}
Пример #12
0
MediaTime::ComparisonFlags MediaTime::compare(const MediaTime& rhs, bool fuzzy) const
{
    if ((isPositiveInfinite() && rhs.isPositiveInfinite())
        || (isNegativeInfinite() && rhs.isNegativeInfinite())
        || (isInvalid() && rhs.isInvalid())
        || (isIndefinite() && rhs.isIndefinite()))
        return EqualTo;

    if (isInvalid())
        return GreaterThan;

    if (rhs.isInvalid())
        return LessThan;

    if (rhs.isNegativeInfinite() || isPositiveInfinite())
        return GreaterThan;

    if (rhs.isPositiveInfinite() || isNegativeInfinite())
        return LessThan;

    if (isIndefinite())
        return GreaterThan;

    if (rhs.isIndefinite())
        return LessThan;

    if (hasDoubleValue() && rhs.hasDoubleValue()) {
        if (m_timeValueAsDouble == rhs.m_timeValueAsDouble)
            return EqualTo;
        if (fuzzy && fabs(m_timeValueAsDouble - rhs.m_timeValueAsDouble) <= fuzzinessThreshold().toDouble())
            return EqualTo;

        return m_timeValueAsDouble < rhs.m_timeValueAsDouble ? LessThan : GreaterThan;
    }

    MediaTime a = *this;
    MediaTime b = rhs;

    if (a.hasDoubleValue())
        a.setTimeScale(DefaultTimeScale);

    if (b.hasDoubleValue())
        b.setTimeScale(DefaultTimeScale);

    int64_t rhsWhole = b.m_timeValue / b.m_timeScale;
    int64_t lhsWhole = a.m_timeValue / a.m_timeScale;
    if (lhsWhole > rhsWhole)
        return GreaterThan;
    if (lhsWhole < rhsWhole)
        return LessThan;

    int64_t rhsRemain = b.m_timeValue % b.m_timeScale;
    int64_t lhsRemain = a.m_timeValue % a.m_timeScale;
    int64_t lhsFactor = lhsRemain * b.m_timeScale;
    int64_t rhsFactor = rhsRemain * a.m_timeScale;

    if (lhsFactor == rhsFactor)
        return EqualTo;
    return lhsFactor > rhsFactor ? GreaterThan : LessThan;
}
Пример #13
0
MediaTime MediaTime::operator-(const MediaTime& rhs) const
{
    if (rhs.isInvalid() || isInvalid())
        return invalidTime();

    if (rhs.isIndefinite() || isIndefinite())
        return indefiniteTime();

    if (isPositiveInfinite() && rhs.isPositiveInfinite())
        return invalidTime();

    if (isNegativeInfinite() && rhs.isNegativeInfinite())
        return invalidTime();

    if (isPositiveInfinite() || rhs.isNegativeInfinite())
        return positiveInfiniteTime();

    if (isNegativeInfinite() || rhs.isPositiveInfinite())
        return negativeInfiniteTime();

    if (hasDoubleValue() && rhs.hasDoubleValue())
        return MediaTime::createWithDouble(m_timeValueAsDouble - rhs.m_timeValueAsDouble);

    MediaTime a = *this;
    MediaTime b = rhs;

    if (a.hasDoubleValue())
        a.setTimeScale(DefaultTimeScale);
    else if (b.hasDoubleValue())
        b.setTimeScale(DefaultTimeScale);

    int32_t commonTimeScale;
    if (!leastCommonMultiple(this->m_timeScale, rhs.m_timeScale, commonTimeScale) || commonTimeScale > MaximumTimeScale)
        commonTimeScale = MaximumTimeScale;
    a.setTimeScale(commonTimeScale);
    b.setTimeScale(commonTimeScale);
    while (!safeSub(a.m_timeValue, b.m_timeValue, a.m_timeValue)) {
        if (commonTimeScale == 1)
            return a.m_timeValue > 0 ? positiveInfiniteTime() : negativeInfiniteTime();
        commonTimeScale /= 2;
        a.setTimeScale(commonTimeScale);
        b.setTimeScale(commonTimeScale);
    }
    return a;
}