mirror of
https://github.com/videojs/video.js.git
synced 2024-12-10 11:10:19 +02:00
fix: Use timeupdate as well as rvfc/raf for cues (#7918)
Use the timeupdate event as well as the rvfc and raf callbacks to check cues. This is a bit overkill for "usual" playback but avoids edge cases. If the more preceise callback trigger first the cue will update but the timeupdate event should catch any that were missed, notwithstanding that timeupdate was always somewhat unpredictable. Fixes #7910 (audio in video els and Samsung being weird) and fixes #7902 (no updates off screen).
This commit is contained in:
parent
28105071d3
commit
9b81afee80
@ -184,13 +184,15 @@ class TextTrack extends Track {
|
||||
const activeCues = new TextTrackCueList(this.activeCues_);
|
||||
let changed = false;
|
||||
|
||||
this.timeupdateHandler = Fn.bind(this, function() {
|
||||
this.timeupdateHandler = Fn.bind(this, function(event = {}) {
|
||||
if (this.tech_.isDisposed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.tech_.isReady_) {
|
||||
this.rvf_ = this.tech_.requestVideoFrameCallback(this.timeupdateHandler);
|
||||
if (event.type !== 'timeupdate') {
|
||||
this.rvf_ = this.tech_.requestVideoFrameCallback(this.timeupdateHandler);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@ -205,7 +207,9 @@ class TextTrack extends Track {
|
||||
changed = false;
|
||||
}
|
||||
|
||||
this.rvf_ = this.tech_.requestVideoFrameCallback(this.timeupdateHandler);
|
||||
if (event.type !== 'timeupdate') {
|
||||
this.rvf_ = this.tech_.requestVideoFrameCallback(this.timeupdateHandler);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
@ -368,7 +372,10 @@ class TextTrack extends Track {
|
||||
}
|
||||
|
||||
startTracking() {
|
||||
// More precise cues based on requestVideoFrameCallback with a requestAnimationFram fallback
|
||||
this.rvf_ = this.tech_.requestVideoFrameCallback(this.timeupdateHandler);
|
||||
// Also listen to timeupdate in case rVFC/rAF stops (window in background, audio in video el)
|
||||
this.tech_.on('timeupdate', this.timeupdateHandler);
|
||||
}
|
||||
|
||||
stopTracking() {
|
||||
@ -376,6 +383,7 @@ class TextTrack extends Track {
|
||||
this.tech_.cancelVideoFrameCallback(this.rvf_);
|
||||
this.rvf_ = undefined;
|
||||
}
|
||||
this.tech_.off('timeupdate', this.timeupdateHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -279,7 +279,9 @@ QUnit.test('does not fire cuechange before Tech is ready', function(assert) {
|
||||
return 0;
|
||||
};
|
||||
|
||||
// `playing` would trigger rvfc or raf, `timeupdate` for fallback
|
||||
player.tech_.trigger('playing');
|
||||
player.tech_.trigger('timeupdate');
|
||||
assert.equal(changes, 0, 'a cuechange event is not triggered');
|
||||
|
||||
player.tech_.on('ready', function() {
|
||||
@ -292,6 +294,11 @@ QUnit.test('does not fire cuechange before Tech is ready', function(assert) {
|
||||
|
||||
assert.equal(changes, 2, 'a cuechange event trigger addEventListener and oncuechange');
|
||||
|
||||
player.tech_.trigger('timeupdate');
|
||||
clock.tick(1);
|
||||
|
||||
assert.equal(changes, 2, 'a cuechange event trigger not duplicated by timeupdate');
|
||||
|
||||
tt.off();
|
||||
player.dispose();
|
||||
clock.restore();
|
||||
@ -311,31 +318,45 @@ QUnit.test('fires cuechange when cues become active and inactive', function(asse
|
||||
const cuechangeHandler = function() {
|
||||
changes++;
|
||||
};
|
||||
let fakeCurrentTime = 0;
|
||||
|
||||
player.tech_.currentTime = function() {
|
||||
return fakeCurrentTime;
|
||||
};
|
||||
|
||||
tt.addCue({
|
||||
id: '1',
|
||||
startTime: 1,
|
||||
endTime: 5
|
||||
});
|
||||
tt.addCue({
|
||||
id: '2',
|
||||
startTime: 11,
|
||||
endTime: 14
|
||||
});
|
||||
|
||||
tt.oncuechange = cuechangeHandler;
|
||||
tt.addEventListener('cuechange', cuechangeHandler);
|
||||
|
||||
player.tech_.currentTime = function() {
|
||||
return 2;
|
||||
};
|
||||
|
||||
fakeCurrentTime = 2;
|
||||
player.tech_.trigger('playing');
|
||||
|
||||
assert.equal(changes, 2, 'a cuechange event trigger addEventListener and oncuechange');
|
||||
|
||||
player.tech_.currentTime = function() {
|
||||
return 7;
|
||||
};
|
||||
assert.equal(changes, 2, 'a cuechange event trigger addEventListener and oncuechange (rvfc/raf)');
|
||||
|
||||
fakeCurrentTime = 7;
|
||||
player.tech_.trigger('playing');
|
||||
|
||||
assert.equal(changes, 4, 'a cuechange event trigger addEventListener and oncuechange');
|
||||
assert.equal(changes, 4, 'a cuechange event trigger addEventListener and oncuechange (rvfc/raf)');
|
||||
|
||||
fakeCurrentTime = 12;
|
||||
player.tech_.trigger('timeupdate');
|
||||
|
||||
assert.equal(changes, 6, 'a cuechange event trigger addEventListener and oncuechange (timeupdate)');
|
||||
|
||||
fakeCurrentTime = 17;
|
||||
player.tech_.trigger('timeupdate');
|
||||
|
||||
assert.equal(changes, 8, 'a cuechange event trigger addEventListener and oncuechange (timeupdate)');
|
||||
|
||||
tt.off();
|
||||
player.dispose();
|
||||
@ -365,6 +386,7 @@ QUnit.test('enabled and disabled cuechange handler when changing mode to hidden'
|
||||
return 2;
|
||||
};
|
||||
player.tech_.trigger('playing');
|
||||
player.tech_.trigger('timeupdate');
|
||||
|
||||
assert.equal(changes, 1, 'a cuechange event trigger');
|
||||
|
||||
@ -376,6 +398,7 @@ QUnit.test('enabled and disabled cuechange handler when changing mode to hidden'
|
||||
return 7;
|
||||
};
|
||||
player.tech_.trigger('playing');
|
||||
player.tech_.trigger('timeupdate');
|
||||
|
||||
assert.equal(changes, 0, 'NO cuechange event trigger');
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user