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::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(); }