Skip to content

Commit 8e28506

Browse files
aveladjoeyparrish
authored andcommitted
fix(HLS): Fix subtitle timing (#7625)
Simplifies subtitle management for sequence mode and segments mode Runs subtitle tests in segments mode as well (Tizen 3.0) Fixes: #7447
1 parent 12acf0a commit 8e28506

14 files changed

+84
-27
lines changed

karma.conf.js

+2
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,8 @@ module.exports = (config) => {
272272
{pattern: 'test/test/assets/hls-raw-ec3/*', included: false},
273273
{pattern: 'test/test/assets/hls-raw-mp3/*', included: false},
274274
{pattern: 'test/test/assets/hls-sample-aes/*', included: false},
275+
// eslint-disable-next-line max-len
276+
{pattern: 'test/test/assets/hls-text-no-discontinuity/*', included: false},
275277
{pattern: 'test/test/assets/hls-text-offset/*', included: false},
276278
{pattern: 'test/test/assets/hls-ts-aac/*', included: false},
277279
{pattern: 'test/test/assets/hls-ts-ac3/*', included: false},

lib/hls/hls_parser.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -4122,7 +4122,7 @@ shaka.hls.HlsParser = class {
41224122
let aesKey = undefined;
41234123

41244124
let discontinuitySequence = shaka.hls.Utils.getFirstTagWithNameAsNumber(
4125-
playlist.tags, 'EXT-X-DISCONTINUITY-SEQUENCE', 0);
4125+
playlist.tags, 'EXT-X-DISCONTINUITY-SEQUENCE', -1);
41264126
const mediaSequenceNumber = shaka.hls.Utils.getFirstTagWithNameAsNumber(
41274127
playlist.tags, 'EXT-X-MEDIA-SEQUENCE', 0);
41284128
const skipTag = shaka.hls.Utils.getFirstTagWithName(

lib/media/media_source_engine.js

+7-2
Original file line numberDiff line numberDiff line change
@@ -883,7 +883,8 @@ shaka.media.MediaSourceEngine = class {
883883
const ContentType = shaka.util.ManifestParserUtils.ContentType;
884884

885885
if (contentType == ContentType.TEXT) {
886-
if (this.sequenceMode_) {
886+
if (this.manifestType_ == shaka.media.ManifestParser.HLS &&
887+
reference.discontinuitySequence >= 0) {
887888
// This won't be known until the first video segment is appended.
888889
const offset = await this.textSequenceModeOffset_;
889890
this.textEngine_.setTimestampOffset(offset);
@@ -977,7 +978,7 @@ shaka.media.MediaSourceEngine = class {
977978
const isBestSourceBufferForTimestamps =
978979
contentType == ContentType.VIDEO ||
979980
!(ContentType.VIDEO in this.sourceBuffers_);
980-
if (this.sequenceMode_ && isBestSourceBufferForTimestamps) {
981+
if (isBestSourceBufferForTimestamps) {
981982
this.textSequenceModeOffset_.resolve(timestampOffset);
982983
}
983984
}
@@ -1306,6 +1307,10 @@ shaka.media.MediaSourceEngine = class {
13061307
this.textSequenceModeOffset_ = new shaka.util.PublicPromise();
13071308
}
13081309

1310+
if (!this.sequenceMode_) {
1311+
return;
1312+
}
1313+
13091314
// Queue an abort() to help MSE splice together overlapping segments.
13101315
// We set appendWindowEnd when we change periods in DASH content, and the
13111316
// period transition may result in overlap.

lib/media/segment_reference.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ shaka.media.SegmentReference = class {
295295
this.thumbnailSprite = null;
296296

297297
/** @type {number} */
298-
this.discontinuitySequence = 0;
298+
this.discontinuitySequence = -1;
299299

300300
/** @type {boolean} */
301301
this.allPartialSegments = allPartialSegments;

lib/media/streaming_engine.js

+9-11
Original file line numberDiff line numberDiff line change
@@ -2148,17 +2148,15 @@ shaka.media.StreamingEngine = class {
21482148
}
21492149
}
21502150

2151-
if (this.manifest_.sequenceMode) {
2152-
const lastDiscontinuitySequence =
2153-
mediaState.lastSegmentReference ?
2154-
mediaState.lastSegmentReference.discontinuitySequence : null;
2155-
// Across discontinuity bounds, we should resync timestamps for
2156-
// sequence mode playbacks. The next segment appended should
2157-
// land at its theoretical timestamp from the segment index.
2158-
if (reference.discontinuitySequence != lastDiscontinuitySequence) {
2159-
operations.push(this.playerInterface_.mediaSourceEngine.resync(
2160-
mediaState.type, reference.startTime));
2161-
}
2151+
const lastDiscontinuitySequence =
2152+
mediaState.lastSegmentReference ?
2153+
mediaState.lastSegmentReference.discontinuitySequence : null;
2154+
// Across discontinuity bounds, we should resync timestamps. The next
2155+
// segment appended should land at its theoretical timestamp from the
2156+
// segment index.
2157+
if (reference.discontinuitySequence != lastDiscontinuitySequence) {
2158+
operations.push(this.playerInterface_.mediaSourceEngine.resync(
2159+
mediaState.type, reference.startTime));
21622160
}
21632161

21642162
await Promise.all(operations);

lib/text/vtt_text_parser.js

+2-8
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,7 @@ shaka.text.VttTextParser = class {
8686
// Only use 'X-TIMESTAMP-MAP' with HLS. This overrides offset above.
8787
if (blocks[0].includes('X-TIMESTAMP-MAP') &&
8888
this.manifestType_ == shaka.media.ManifestParser.HLS) {
89-
if (this.sequenceMode_) {
90-
// Compute a different, rollover-based offset for sequence mode.
91-
offset = this.computeHlsSequenceModeOffset_(blocks[0], time);
92-
} else {
93-
// Calculate the offset from the segment startTime.
94-
offset = time.segmentStart;
95-
}
89+
offset = this.computeHlsOffset_(blocks[0], time);
9690
}
9791

9892
// Parse VTT regions.
@@ -129,7 +123,7 @@ shaka.text.VttTextParser = class {
129123
* @return {number}
130124
* @private
131125
*/
132-
computeHlsSequenceModeOffset_(headerBlock, time) {
126+
computeHlsOffset_(headerBlock, time) {
133127
// https://bit.ly/2K92l7y
134128
// The 'X-TIMESTAMP-MAP' header is used in HLS to align text with
135129
// the rest of the media.

test/hls/hls_parser_integration.js

+21-4
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,6 @@ describe('HlsParser', () => {
111111
});
112112

113113
it('supports text discontinuity', async () => {
114-
if (!shaka.util.Platform.supportsSequenceMode()) {
115-
pending('Sequence mode is not supported by the platform.');
116-
}
117-
118114
player.setTextTrackVisibility(true);
119115

120116
await player.load('/base/test/test/assets/hls-text-offset/index.m3u8');
@@ -134,4 +130,25 @@ describe('HlsParser', () => {
134130

135131
await player.unload();
136132
});
133+
134+
it('supports text without discontinuity', async () => {
135+
player.setTextTrackVisibility(true);
136+
137+
// eslint-disable-next-line max-len
138+
await player.load('/base/test/test/assets/hls-text-no-discontinuity/index.m3u8');
139+
await video.play();
140+
141+
await waiter.waitUntilPlayheadReachesOrFailOnTimeout(video, 1, 30);
142+
143+
const cues = video.textTracks[0].cues;
144+
expect(cues.length).toBe(3);
145+
expect(cues[0].startTime).toBeCloseTo(0.6, 0);
146+
expect(cues[0].endTime).toBeCloseTo(2.88, 0);
147+
expect(cues[1].startTime).toBeCloseTo(2.88, 0);
148+
expect(cues[1].endTime).toBeCloseTo(6.36, 0);
149+
expect(cues[2].startTime).toBeCloseTo(6.36, 0);
150+
expect(cues[2].endTime).toBeCloseTo(10.68, 0);
151+
152+
await player.unload();
153+
});
137154
});

test/hls/hls_parser_unit.js

+1
Original file line numberDiff line numberDiff line change
@@ -1150,6 +1150,7 @@ describe('HlsParser', () => {
11501150
'#EXT-X-VERSION:3\n',
11511151
'#EXT-X-TARGETDURATION:5\n',
11521152
'#EXT-X-MEDIA-SEQUENCE:0\n',
1153+
'#EXT-X-DISCONTINUITY-SEQUENCE:0\n',
11531154
'#EXTINF:3,\n',
11541155
'clip0-video-0.ts\n',
11551156
'#EXTINF:1,\n',
Binary file not shown.
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#EXTM3U
2+
#EXT-X-VERSION:6
3+
#EXT-X-TARGETDURATION:7
4+
#EXT-X-MEDIA-SEQUENCE:0
5+
#EXT-X-PLAYLIST-TYPE:VOD
6+
#EXT-X-INDEPENDENT-SEGMENTS
7+
#EXTINF:6.000000,
8+
0.ts
9+
#EXTINF:6.000000,
10+
1.ts
11+
#EXT-X-ENDLIST
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#EXTM3U
2+
#EXT-X-VERSION:6
3+
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="de",DEFAULT=NO,AUTOSELECT=NO,LANGUAGE="de",FORCED="NO",URI="text.m3u8"
4+
5+
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1240800,CODECS="avc1.640014,mp4a.40.2",RESOLUTION=256x144,SUBTITLES="subs"
6+
av.m3u8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
WEBVTT
2+
3+
1
4+
00:00:00.600 --> 00:00:02.880
5+
Heute haben wir einen wesentlichen Meilenstein
6+
7+
2
8+
00:00:02.880 --> 00:00:06.360
9+
auf dem Weg zur Science
10+
City Hamburg Bahrenfeld erreicht.
11+
12+
3
13+
00:00:06.360 --> 00:00:10.680
14+
Die Science City ist ein 125 Hektar
15+
großes Areal in Bahrenfeld,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#EXTM3U
2+
#EXT-X-VERSION:3
3+
#EXT-X-PLAYLIST-TYPE:VOD
4+
#EXT-X-MEDIA-SEQUENCE:0
5+
#EXT-X-TARGETDURATION:12
6+
#EXTINF:12.000,
7+
subtitle.vtt
8+
#EXT-X-ENDLIST

0 commit comments

Comments
 (0)