From bd75032d63755044d2d78ca109e2e9f132e36a00 Mon Sep 17 00:00:00 2001 From: Joey Parrish Date: Thu, 8 Dec 2022 00:05:08 -0800 Subject: [PATCH] fix(TTML): Fix duplicate cues overlapping segment boundaries (#4798) Closes #4631 --- lib/text/ttml_text_parser.js | 17 ++- test/text/mp4_ttml_parser_unit.js | 10 +- test/text/ttml_text_parser_unit.js | 205 +++++++++++++++++------------ 3 files changed, 136 insertions(+), 96 deletions(-) diff --git a/lib/text/ttml_text_parser.js b/lib/text/ttml_text_parser.js index f8eefb1d02..7bb70fe92c 100644 --- a/lib/text/ttml_text_parser.js +++ b/lib/text/ttml_text_parser.js @@ -136,7 +136,7 @@ shaka.text.TtmlTextParser = class { } const cue = TtmlTextParser.parseCue_( - body, time.periodStart, rateInfo, metadataElements, styles, + body, time, rateInfo, metadataElements, styles, regionElements, cueRegions, whitespaceTrim, cellResolutionInfo, /* parentCueElement= */ null, /* isContent= */ false); @@ -157,7 +157,7 @@ shaka.text.TtmlTextParser = class { * Parses a TTML node into a Cue. * * @param {!Node} cueNode - * @param {number} offset + * @param {shaka.extern.TextParser.TimeContext} timeContext * @param {!shaka.text.TtmlTextParser.RateInfo_} rateInfo * @param {!Array.} metadataElements * @param {!Array.} styles @@ -171,7 +171,7 @@ shaka.text.TtmlTextParser = class { * @private */ static parseCue_( - cueNode, offset, rateInfo, metadataElements, styles, regionElements, + cueNode, timeContext, rateInfo, metadataElements, styles, regionElements, cueRegions, whitespaceTrim, cellResolution, parentCueElement, isContent) { /** @type {Element} */ let cueElement; @@ -236,7 +236,7 @@ shaka.text.TtmlTextParser = class { for (const childNode of cueElement.childNodes) { const nestedCue = shaka.text.TtmlTextParser.parseCue_( childNode, - offset, + timeContext, rateInfo, metadataElements, styles, @@ -293,15 +293,20 @@ shaka.text.TtmlTextParser = class { if (start == null) { start = 0; } - start += offset; + start += timeContext.periodStart; // If end is null, that means the duration is effectively infinite. if (end == null) { end = Infinity; } else { - end += offset; + end += timeContext.periodStart; } + // Clip times to segment boundaries. + // https://github.com/shaka-project/shaka-player/issues/4631 + start = Math.max(start, timeContext.segmentStart); + end = Math.min(end, timeContext.segmentEnd); + if (!hasTimeAttributes && nestedCues.length > 0) { // If no time is defined for this cue, base the timing information on // the time of the nested cues. In the case of multiple nested cues with diff --git a/test/text/mp4_ttml_parser_unit.js b/test/text/mp4_ttml_parser_unit.js index 3db52df745..a6160617b4 100644 --- a/test/text/mp4_ttml_parser_unit.js +++ b/test/text/mp4_ttml_parser_unit.js @@ -41,7 +41,8 @@ describe('Mp4TtmlParser', () => { it('handles media segments with multiple mdats', () => { const parser = new shaka.text.Mp4TtmlParser(); parser.parseInit(ttmlInitSegment); - const time = {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}; + const time = + {periodStart: 0, segmentStart: 0, segmentEnd: 60, vttOffset: 0}; const ret = parser.parseMedia(ttmlSegmentMultipleMDAT, time); // Bodies. expect(ret.length).toBe(2); @@ -55,9 +56,9 @@ describe('Mp4TtmlParser', () => { it('accounts for offset', () => { const time1 = - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}; + {periodStart: 0, segmentStart: 0, segmentEnd: 70, vttOffset: 0}; const time2 = - {periodStart: 7, segmentStart: 0, segmentEnd: 0, vttOffset: 7}; + {periodStart: 7, segmentStart: 0, segmentEnd: 70, vttOffset: 7}; const parser = new shaka.text.Mp4TtmlParser(); parser.parseInit(ttmlInitSegment); @@ -161,7 +162,8 @@ describe('Mp4TtmlParser', () => { ]; const parser = new shaka.text.Mp4TtmlParser(); parser.parseInit(ttmlInitSegment); - const time = {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}; + const time = + {periodStart: 0, segmentStart: 0, segmentEnd: 60, vttOffset: 0}; const result = parser.parseMedia(ttmlSegment, time); shaka.test.TtmlUtils.verifyHelper( cues, result, {startTime: 23, endTime: 53.5}); diff --git a/test/text/ttml_text_parser_unit.js b/test/text/ttml_text_parser_unit.js index a0b09bb0fb..9e95bf9204 100644 --- a/test/text/ttml_text_parser_unit.js +++ b/test/text/ttml_text_parser_unit.js @@ -13,14 +13,14 @@ describe('TtmlTextParser', () => { it('supports no cues', () => { verifyHelper([], '', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 0, segmentEnd: 10, vttOffset: 0}, {}); }); it('supports empty text string', () => { verifyHelper([], '', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 0, segmentEnd: 10, vttOffset: 0}, {}); }); @@ -28,7 +28,7 @@ describe('TtmlTextParser', () => { verifyHelper( [], '
\r\n
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 0, segmentEnd: 10, vttOffset: 0}, {}); }); @@ -55,7 +55,7 @@ describe('TtmlTextParser', () => { }, ], '' + ttBody + '', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 70, vttOffset: 0}, {startTime: 62.03, endTime: 62.05}); // When xml:space="preserve", take them into account. verifyHelper( @@ -81,7 +81,7 @@ describe('TtmlTextParser', () => { }, ], '' + ttBody + '', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 70, vttOffset: 0}, {startTime: 62.03, endTime: 62.05}); // The default value for xml:space is "default". verifyHelper( @@ -97,7 +97,7 @@ describe('TtmlTextParser', () => { }, ], '' + ttBody + '', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 70, vttOffset: 0}, {startTime: 62.03, endTime: 62.05}); // Any other value is rejected as an error. @@ -128,7 +128,7 @@ describe('TtmlTextParser', () => { }, ], '' + ttBody + '', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 70, vttOffset: 0}, {startTime: 62.03, endTime: 62.05}); }); @@ -198,7 +198,7 @@ describe('TtmlTextParser', () => { 'First cue
Second cue' + '

' + '', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, {startTime: 62.05, endTime: 3723.2}); }); @@ -234,7 +234,7 @@ describe('TtmlTextParser', () => { 'First cue
Second cue' + '

' + '', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, {startTime: 62.05, endTime: 3723.2}); }); @@ -293,7 +293,7 @@ describe('TtmlTextParser', () => { '' + '

' + '', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, {startTime: 62.05, endTime: 3723.2}); }); @@ -312,7 +312,7 @@ describe('TtmlTextParser', () => { '

' + 'Test

' + '', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, {startTime: 62.05, endTime: 3723.2}); }); @@ -342,7 +342,7 @@ describe('TtmlTextParser', () => { '

' + '', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, {startTime: 62.05, endTime: 3723.2}); }); @@ -354,7 +354,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, {startTime: 62.05, endTime: 3723.2}); }); @@ -366,7 +366,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 7, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 7, segmentStart: 60, segmentEnd: 3740, vttOffset: 0}, {startTime: 69.05, endTime: 3730.2}); }); @@ -389,7 +389,7 @@ describe('TtmlTextParser', () => { '
' + '

Nested cue

' + '
', - {periodStart: 7, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 7, segmentStart: 60, segmentEnd: 3740, vttOffset: 0}, {startTime: 69.05, endTime: 3730.2}); }); @@ -401,7 +401,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 3560, segmentEnd: 5410, vttOffset: 0}, {startTime: 3567.03, endTime: 5402.3}); }); @@ -415,7 +415,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 610, segmentEnd: 670, vttOffset: 0}, {startTime: 615.5, endTime: 663}); }); @@ -429,7 +429,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 610, segmentEnd: 670, vttOffset: 0}, {startTime: 615.5, endTime: 663}); }); @@ -447,7 +447,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 610, segmentEnd: 670, vttOffset: 0}, {startTime: Util.closeTo(615.5 + 1 / 60), endTime: 663}); }); @@ -461,7 +461,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 0, segmentEnd: 20, vttOffset: 0}, {startTime: 2.5, endTime: Util.closeTo(10.01)}); }); @@ -475,7 +475,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 0, segmentEnd: 10, vttOffset: 0}, {startTime: 5, endTime: Util.closeTo(6.02)}); }); @@ -487,7 +487,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 70, vttOffset: 0}, {startTime: 62.05, endTime: 67.05}); }); @@ -497,7 +497,7 @@ describe('TtmlTextParser', () => { '
' + '' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 0, segmentEnd: 10, vttOffset: 0}, {}); }); @@ -517,7 +517,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, {startTime: 62.05, endTime: 3723.2, region: {id: 'subtitleArea'}}, {startTime: 62.05, endTime: 3723.2}); }); @@ -539,7 +539,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, {startTime: 62.05, endTime: 3723.2, region: {id: 'subtitleArea'}}, {startTime: 62.05, endTime: 3723.2}); }); @@ -561,7 +561,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, {startTime: 62.05, endTime: 3723.2, region: {id: 'subtitleArea'}}, {startTime: 62.05, endTime: 3723.2}); }); @@ -586,7 +586,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, {startTime: 62.05, endTime: 3723.2, region: {id: 'subtitleArea'}}, {startTime: 62.05, endTime: 3723.2}); }); @@ -611,7 +611,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, {startTime: 62.05, endTime: 3723.2, region: {id: 'subtitleArea'}}, {startTime: 62.05, endTime: 3723.2}); }); @@ -632,7 +632,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, { region: { id: 'subtitleArea', @@ -661,7 +661,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, { region: { viewportAnchorX: 50, @@ -689,7 +689,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, { region: { viewportAnchorX: 50, @@ -718,7 +718,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, { region: { id: 'subtitleArea', @@ -754,7 +754,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, { region: { id: 'subtitleArea', @@ -790,7 +790,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, { region: { id: 'subtitleArea', @@ -827,7 +827,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, { region: { id: 'subtitleArea', @@ -864,7 +864,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, { region: { id: 'subtitleArea', @@ -902,7 +902,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, { region: { id: 'subtitleArea', @@ -939,7 +939,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, { region: { id: 'subtitleArea', @@ -968,7 +968,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, { region: { viewportAnchorX: 50, @@ -996,7 +996,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, { region: { viewportAnchorX: 50, @@ -1026,7 +1026,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, { region: { id: 'subtitleArea', @@ -1058,7 +1058,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, {startTime: 62.05, endTime: 3723.2, region: {id: 'subtitleArea'}}, {startTime: 62.05, endTime: 3723.2}); @@ -1079,7 +1079,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, {startTime: 62.05, endTime: 3723.2, region: {id: 'subtitleArea'}}, {startTime: 62.05, endTime: 3723.2}); @@ -1100,7 +1100,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, {startTime: 62.05, endTime: 3723.2, region: {id: 'subtitleArea'}}, {startTime: 62.05, endTime: 3723.2}); @@ -1121,7 +1121,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, {startTime: 62.05, endTime: 3723.2, region: {id: 'subtitleArea'}}, {startTime: 62.05, endTime: 3723.2}); @@ -1142,7 +1142,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, {startTime: 62.05, endTime: 3723.2, region: {id: 'subtitleArea'}}, {startTime: 62.05, endTime: 3723.2}); }); @@ -1160,7 +1160,7 @@ describe('TtmlTextParser', () => { '
' + '' + '', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, {startTime: 62.05, endTime: 3723.2}); verifyHelper( @@ -1175,7 +1175,7 @@ describe('TtmlTextParser', () => { '' + '' + '', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, {startTime: 62.05, endTime: 3723.2}); verifyHelper( @@ -1188,7 +1188,7 @@ describe('TtmlTextParser', () => { '
' + '' + '', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, {}); }); @@ -1205,7 +1205,7 @@ describe('TtmlTextParser', () => { '' + '' + '', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, {startTime: 62.05, endTime: 3723.2}); }); @@ -1228,7 +1228,7 @@ describe('TtmlTextParser', () => { '
' + '

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, {startTime: 62.05, endTime: 3723.2}, { startTime: 62.05, @@ -1251,7 +1251,7 @@ describe('TtmlTextParser', () => { '
' + '', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 0, segmentEnd: 70, vttOffset: 0}, {startTime: 0, endTime: 62.05}, { startTime: 0, @@ -1282,7 +1282,7 @@ describe('TtmlTextParser', () => { '

' + '', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, {startTime: 62.05, endTime: 3723.2}); }); @@ -1311,7 +1311,7 @@ describe('TtmlTextParser', () => { '

' + '

Line1
Line2

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, {startTime: 62.05, endTime: 3723.2}); verifyHelper( @@ -1345,7 +1345,7 @@ describe('TtmlTextParser', () => { 'Line1
Line2
' + '

' + '', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, {startTime: 62.05, endTime: 3723.2}); }); @@ -1373,7 +1373,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 0, segmentEnd: 10, vttOffset: 0}, {startTime: 1, endTime: 2}); }); @@ -1399,7 +1399,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, {startTime: 62.05, endTime: 3723.2, region: {id: 'subtitleArea'}}, {startTime: 62.05, endTime: 3723.2}); }); @@ -1447,7 +1447,7 @@ describe('TtmlTextParser', () => { '

Test

' + '

Test 2

' + '', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 0, segmentEnd: 10, vttOffset: 0}, {startTime: 1, endTime: 4, region: {id: 'subtitleArea'}}, {startTime: 1, endTime: 4}); }); @@ -1472,7 +1472,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 0, segmentEnd: 10, vttOffset: 0}, {startTime: 1, endTime: 2}); }); @@ -1494,7 +1494,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 0, segmentEnd: 10, vttOffset: 0}, {startTime: 1, endTime: 2}); }); @@ -1531,7 +1531,7 @@ describe('TtmlTextParser', () => { 'Test' + '

' + '', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 0, segmentEnd: 10, vttOffset: 0}, {startTime: 1, endTime: 2}); }); @@ -1551,7 +1551,7 @@ describe('TtmlTextParser', () => { 'Test' + '

' + '', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 0, segmentEnd: 10, vttOffset: 0}, // The body must have these properties: {backgroundColor: 'transparent'}, // The div must have these properties: @@ -1574,7 +1574,7 @@ describe('TtmlTextParser', () => { 'Test' + '

' + '', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 0, segmentEnd: 10, vttOffset: 0}, // The body must have these properties: {backgroundColor: 'black'}, // The div must have these properties: @@ -1601,7 +1601,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, {startTime: 62.05, endTime: 3723.2, region: {id: 'subtitleArea'}}, {startTime: 62.05, endTime: 3723.2}); }); @@ -1629,7 +1629,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, {startTime: 62.05, endTime: 3723.2, region: {id: 'subtitleArea'}}, {startTime: 62.05, endTime: 3723.2}); }); @@ -1654,7 +1654,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 0, segmentEnd: 10, vttOffset: 0}, {startTime: 1, endTime: 2}); }); @@ -1682,7 +1682,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 0, segmentEnd: 10, vttOffset: 0}, {startTime: 1, endTime: 2}); }); @@ -1711,7 +1711,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 0, segmentEnd: 10, vttOffset: 0}, {startTime: 1, endTime: 2}); }); @@ -1736,7 +1736,7 @@ describe('TtmlTextParser', () => { '
' + '

Test

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, {startTime: 62.05, endTime: 3723.2, region: {id: 'subtitleArea'}}, {startTime: 62.05, endTime: 3723.2}); }); @@ -1751,7 +1751,7 @@ describe('TtmlTextParser', () => { '

First cue

' + '

Second cue

' + '', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 0, segmentEnd: 10, vttOffset: 0}, {startTime: 1, endTime: 4}); }); @@ -1775,7 +1775,7 @@ describe('TtmlTextParser', () => { '
' + '

äöü

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0}, {startTime: 62.05, endTime: 3723.2}); }); @@ -1792,9 +1792,10 @@ describe('TtmlTextParser', () => { '

First cue

' + '

Second cue

' + '', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, - {startTime: 1, endTime: Infinity}, - {startTime: 3, endTime: Infinity}); + {periodStart: 0, segmentStart: 0, segmentEnd: 10, vttOffset: 0}, + // Capped to segment end time. + {startTime: 1, endTime: 10}, + {startTime: 3, endTime: 10}); verifyHelper( [{ @@ -1817,9 +1818,10 @@ describe('TtmlTextParser', () => { 'Second cue' + '

' + '', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, - {startTime: 1, endTime: Infinity}, - {startTime: 3, endTime: Infinity}); + {periodStart: 0, segmentStart: 0, segmentEnd: 20, vttOffset: 0}, + // Capped to segment end time. + {startTime: 1, endTime: 20}, + {startTime: 3, endTime: 20}); }); it('gets end time from parent directly if missing', () => { @@ -1833,7 +1835,7 @@ describe('TtmlTextParser', () => { '

First cue

' + '

Second cue

' + '', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 0, segmentEnd: 30, vttOffset: 0}, {startTime: 1, endTime: 30}, {startTime: 3, endTime: 30}); }); @@ -1841,15 +1843,17 @@ describe('TtmlTextParser', () => { it('supports never-ending cues', () => { verifyHelper( [ - {startTime: 1, endTime: Infinity, payload: 'First cue'}, - {startTime: 2, endTime: Infinity, payload: 'Second cue'}, + // Capped to segment end time. + {startTime: 1, endTime: 9000, payload: 'First cue'}, + {startTime: 2, endTime: 9000, payload: 'Second cue'}, ], '
' + '

First cue

' + '

Second cue

' + '
', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, - {startTime: 1, endTime: Infinity}); + {periodStart: 0, segmentStart: 0, segmentEnd: 9000, vttOffset: 0}, + // Capped to segment end time. + {startTime: 1, endTime: 9000}); }); // Regression test for b/159050711 @@ -1920,7 +1924,7 @@ describe('TtmlTextParser', () => { ' Test with spanStyle' + '

' + '', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 0, segmentEnd: 60, vttOffset: 0}, {startTime: 0, endTime: 60}); }); @@ -1952,7 +1956,7 @@ describe('TtmlTextParser', () => { '

' + 'Hello!' + '

', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 0, segmentEnd: 60, vttOffset: 0}, {startTime: 0, endTime: 60}, ); }); @@ -2014,10 +2018,39 @@ describe('TtmlTextParser', () => { ' A
B' + '

' + '', - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}, + {periodStart: 0, segmentStart: 0, segmentEnd: 60, vttOffset: 0}, {startTime: 0, endTime: 60}); }); + // Test for https://github.com/shaka-project/shaka-player/issues/4631 + it('trims cues to segment boundaries', () => { + verifyHelper( + [ + // Capped to segment end time. + {startTime: 168, endTime: 170}, + ], + '
' + + '

' + + ' Emo look.
I mean listen.
' + + '

' + + '
', + {periodStart: 0, segmentStart: 160, segmentEnd: 170, vttOffset: 0}, + {}); + + verifyHelper( + [ + // Capped to segment start time. + {startTime: 170, endTime: Util.closeTo(170.92)}, + ], + '
' + + '

' + + ' Emo look.
I mean listen.
' + + '

' + + '
', + {periodStart: 0, segmentStart: 170, segmentEnd: 180, vttOffset: 0}, + {}); + }); + /** * @param {!Array} cues * @param {string} text @@ -2055,7 +2088,7 @@ describe('TtmlTextParser', () => { expect(() => { new shaka.text.TtmlTextParser().parseMedia( shaka.util.BufferUtils.toUint8(data), - {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0}); + {periodStart: 0, segmentStart: 0, segmentEnd: 10, vttOffset: 0}); }).toThrow(error); } });