-
Notifications
You must be signed in to change notification settings - Fork 793
Conversation
src/master-playlist-controller.js
Outdated
} | ||
}; | ||
|
||
this.setupSegmentLoaderListeners_(); | ||
|
||
this.masterPlaylistLoader_.start(); | ||
this.masterPlaylistLoader_.load(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gesinger and I noticed that load
calls start
if start hasn't been called yet and is safe to call multiple times, but start
should only be called once. Since this call is in the MasterPlaylistController
constructor, theres no risk of running into that scenario, but we decided to just change any calls to start
into load
so we didn't have to concern ourselves with it. We can change it back if you think start
makes more sense semantically
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good to me. 👍
* Call load on our SegmentLoaders | ||
*/ | ||
load() { | ||
this.mainSegmentLoader_.load(); | ||
if (this.audioPlaylistLoader_) { | ||
this.audioSegmentLoader_.load(); | ||
} | ||
if (this.subtitlePlaylistLoader_) { | ||
this.subtitleSegmentLoader_.load(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
track.mode = 'disabled'; | ||
} | ||
|
||
this.setupSubtitles(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It shouldn't since just above we set the current active tracks mode
to 'disabled'
. This has the same effect as turning off subtitles through the UI.
src/master-playlist-controller.js
Outdated
} | ||
|
||
// reset the segment loader | ||
this.subtitleSegmentLoader_.resetEverything(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
setupSubtitles
gets called everytime the player's TextTrackList
fires a change
event. When changing subtitle tracks through the player ui, depending on which track was selected and which track you are changing to, this event will fire multiple times. (it also fires a change event if you select the already active track in the UI) Only one of these calls will actually reset the playlist loader and segment loader to start loading from a new track. By only resetting when we are actually changing tracks, we avoid reseting the segment loader after its already started from the previous call, or if the user selected the already active track, then all that happens is the segment loader is paused and unpaused. Also, yes it should be reset even if there is no track, but since we always reset before starting a new track, it will get reset when the user turns subtitles back on.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like a short version of this explanation needs to be in this function somewhere!
src/vtt-segment-loader.js
Outdated
} | ||
|
||
timestampOffset() { | ||
return this.syncController_.timestampOffsetForTimeline(this.currentTimeline_); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, is it? 😆
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the vtt-loader, no it isnt
src/vtt-segment-loader.js
Outdated
|
||
combinedSegment.set(initSegment.bytes); | ||
combinedSegment.set(vttLineTerminators, initSegment.bytes.byteLength); | ||
segment.map.bytes = combinedSegment; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
from #1043
@imbcmdth: Couple of thoughts on this whole block:
- We should pre-calculate the
vttLineTerminators
value because it's a typed array that never changes. - I think we should do the entire append process when we first get the response for the
initSegment
so that we the object stored inthis.initSegments_[initId]
already has the value that would be incombinedSegment
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree with both, good ideas
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do it! 😃
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it will be better to do these changes when we integrate mediaSegmentRequest
since that changes when the maps are stored in initSegments_
this.parseVTTCues_(segmentInfo); | ||
} catch (e) { | ||
this.error({ | ||
message: e.message |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We decided not to do this now as we plan on revisiting how and when we emit errors at some point in the near future.
src/vtt-segment-loader.js
Outdated
const midPoint = (firstStart + lastStart) / 2; | ||
|
||
segment.start = midPoint - (segment.duration / 2); | ||
segment.end = midPoint + (segment.duration / 2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We decided to try not storing segment start and end times and letting the conservative guess make it work since web vtt segments should be much smaller than video or audio segments.
One thing to be careful about is that the "resync" functionality needs to be removed since it will continuously reset the segment loader on poor guess instead of just walking forward.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the resync functionality actually checks for the existence of segment.end
so we are safe leaving it here if we never set it
utils/stats/index.html
Outdated
@@ -56,7 +56,7 @@ | |||
<br> | |||
<label> | |||
Player Options: | |||
<input id="player-options" type="text" value='{}'> | |||
<input id="player-options" type="text" value='{"vtt.js": "PATH/TO/vtt.js"}'> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reminder to self to revert back before releasing
src/vtt-segment-loader.js
Outdated
this.mediaSource_.readyState === 'ended' && | ||
!this.seeking_()) { | ||
this.syncController_.on('timestampoffset', checkTimestampOffset); | ||
this.state = 'WAITING_ON_TIMELINE'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens if we switch subtitles or seek while the state is 'WAITING_ON_TIMELINE'?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While the state is not WAITING
any aborts will just clear pending segment (which at this point there isn't one yet) and does nothing else. The callback will set the state to ready and call monitorBuffer_
to restart the lifecycle. Since it starts back from the beginning, any seeks or subtitle changes that happened in the waiting time shouldn't have adverse effects
src/vtt-segment-loader.js
Outdated
this.handleSegment_(); | ||
}; | ||
|
||
this.state = 'WAITING_ON_VTTJS'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens if we switch subtitles or seek while the state is 'WAITING_ON_VTTJS'?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is basically the same as aborting while waiting in the DECRYPTING
stage, the callback will call handleSegment_
again and if it was aborted while we were waiting, the first if
block will reset the loader to READY
src/vtt-segment-loader.js
Outdated
}; | ||
|
||
this.state = 'WAITING_ON_VTTJS'; | ||
this.subtitlesTrack_.tech_.on('vttjsloaded', loadHandler); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like the perfect case to use this.subtitlesTrack_.tech_.one('vttjsloaded', ...)
src/vtt-segment-loader.js
Outdated
if (segmentInfo.mediaIndex === this.playlist_.segments.length - 1 && | ||
this.mediaSource_.readyState === 'ended' && | ||
!this.seeking_()) { | ||
this.syncController_.on('timestampoffset', checkTimestampOffset); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like the perfect case to use this.syncController_.one('timestampoffset', ...)
@@ -403,7 +403,7 @@ QUnit.test('only appends one segment at a time', function(assert) { | |||
assert.equal(loader.mediaRequests, 1, '1 request'); | |||
}); | |||
|
|||
QUnit.test('adjusts the playlist offset if no buffering progress is made', function(assert) { | |||
QUnit.skip('adjusts the playlist offset if no buffering progress is made', function(assert) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why was this test skipped?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test is actually outdated from before simple-fetcher times when there was the offset correction variable to handle incorrect guesses, (now we just walk forward), it just wasnt skipped/removed previously because it happened to pass after segment loader changes. If you notice the other playlist offset tests are also skipped. I was planning on cleaning up skipped tests when the loaders get refactored
Description
This adds support for in-manifest VTT
Specific Changes proposed
PlaylistLoader
to continuously refresh subtitle playlist in live playbackVTTSegmentLoader
for loading vtt segmentsEXT-X-MAP
tag in the playlistRequirements Checklist