Skip to content

Commit ea4ed1a

Browse files
committed
fix(ttml): use endTimeSegment as fallback for last cue end time
When a TTML cue has no explicit end attribute, mediaTimeEvents[i+1] is undefined on the last iteration. undefined + offsetTime = NaN, and startTime < NaN is always false, so the cue is silently dropped. Use endTimeSegment (already declared, documented in JSDoc, and passed by TextSourceBuffer) as the fallback end time for the last cue. Fixes Dash-Industry-Forum#4985
1 parent 00a296a commit ea4ed1a

3 files changed

Lines changed: 36 additions & 1 deletion

File tree

src/streaming/utils/TTMLParser.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,9 @@ function TTMLParser() {
144144
if (isd.contents.some(topLevelContents => topLevelContents.contents.length)) {
145145
//be sure that mediaTimeEvents values are in the mp4 segment time ranges.
146146
startTime = mediaTimeEvents[i] + offsetTime;
147-
endTime = mediaTimeEvents[i + 1] + offsetTime;
147+
endTime = (i + 1 < mediaTimeEvents.length)
148+
? mediaTimeEvents[i + 1] + offsetTime
149+
: endTimeSegment;
148150

149151
if (startTime < endTime) {
150152
captionArray.push({
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<tt xmlns="http://www.w3.org/ns/ttml"
3+
xmlns:ttp="http://www.w3.org/ns/ttml#parameter"
4+
xmlns:tts="http://www.w3.org/ns/ttml#styling"
5+
xml:lang="en" xml:space="default"
6+
ttp:timeBase="media" ttp:cellResolution="40 24">
7+
8+
<head>
9+
<styling>
10+
<style xml:id="S0" tts:wrapOption="wrap" tts:fontFamily="UnitTestFont,Arial,Roboto,proportionalSansSerif, default" tts:textAlign="center" tts:fontSize="80%" />
11+
</styling>
12+
<layout>
13+
<region xml:id="R1" tts:origin="12.5% 75%" tts:extent="75% 20%" tts:overflow="hidden" tts:displayAlign="before"/>
14+
</layout>
15+
</head>
16+
<body style="S0">
17+
<div region="R1">
18+
<p xml:id="p1" begin="00:00:00">
19+
Last cue without explicit end
20+
</p>
21+
</div>
22+
</body>
23+
</tt>

test/unit/test/streaming/streaming.utils.TTMLParser.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@ import {expect} from 'chai';
55
const context = {};
66
const ttmlParser = TTMLParser(context).getInstance();
77
let ttml_file;
8+
let ttml_last_cue_file;
89

910
describe('TTMLParser', function () {
1011

1112
describe('parse', async () => {
1213

1314
before(async function () {
1415
ttml_file = await FileLoader.loadTextFile('/data/subtitles/ttmlSample.ttml');
16+
ttml_last_cue_file = await FileLoader.loadTextFile('/data/subtitles/ttmlLastCue.ttml');
1517
});
1618

1719
it('should return an empty array when parse is called and parameters are undefined', () => {
@@ -25,5 +27,13 @@ describe('TTMLParser', function () {
2527
expect(captionsArray[0].start).to.equal(0);
2628
expect(captionsArray[0].end).to.equal(5);
2729
});
30+
31+
it('should use endTimeSegment as fallback for the last cue end time', () => {
32+
const endTimeSegment = 10;
33+
const captionsArray = ttmlParser.parse(ttml_last_cue_file, 0, 0, endTimeSegment, []);
34+
expect(captionsArray).to.have.lengthOf(1);
35+
expect(captionsArray[0].start).to.equal(0);
36+
expect(captionsArray[0].end).to.equal(endTimeSegment);
37+
});
2838
});
2939
});

0 commit comments

Comments
 (0)