mirror of
https://github.com/shaka-project/shaka-player.git
synced 2026-06-18 16:36:56 +03:00
bf67d87387
This changes the TTML parser to not allow cue regions to be inherited to the children of the element the region was originally assigned on, except for the purposes of styles (colors, etc). To allow regions on elements "above" the cues in TTML, such as the <body> or <div> elements, this also changes the TTML parser to render the full structure of the TTML file as a tree of cues. The end result will be a single cue representing the <body>, with children representing the <div> elements inside it, and those <divs> will have children that represent the actual cues. Now that our text displayer can intelligently update child cues as they enter or leave the display window, this approach should be possible. Closes #3850 Closes #3741 Change-Id: Ia8d750daa06920610c04e9b26e29d2d304eaf8a9
174 lines
5.0 KiB
JavaScript
174 lines
5.0 KiB
JavaScript
/*! @license
|
|
* Shaka Player
|
|
* Copyright 2016 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
goog.require('shaka.test.TtmlUtils');
|
|
goog.require('shaka.test.Util');
|
|
goog.require('shaka.text.Mp4TtmlParser');
|
|
goog.require('shaka.util.BufferUtils');
|
|
goog.require('shaka.util.Error');
|
|
|
|
describe('Mp4TtmlParser', () => {
|
|
const ttmlInitSegmentUri = '/base/test/test/assets/ttml-init.mp4';
|
|
const ttmlSegmentUri = '/base/test/test/assets/ttml-segment.mp4';
|
|
const ttmlSegmentMultipleMDATUri =
|
|
'/base/test/test/assets/ttml-segment-multiplemdat.mp4';
|
|
const audioInitSegmentUri = '/base/test/test/assets/sintel-audio-init.mp4';
|
|
|
|
/** @type {!Uint8Array} */
|
|
let ttmlInitSegment;
|
|
/** @type {!Uint8Array} */
|
|
let ttmlSegment;
|
|
/** @type {!Uint8Array} */
|
|
let ttmlSegmentMultipleMDAT;
|
|
/** @type {!Uint8Array} */
|
|
let audioInitSegment;
|
|
|
|
beforeAll(async () => {
|
|
const responses = await Promise.all([
|
|
shaka.test.Util.fetch(ttmlInitSegmentUri),
|
|
shaka.test.Util.fetch(ttmlSegmentUri),
|
|
shaka.test.Util.fetch(ttmlSegmentMultipleMDATUri),
|
|
shaka.test.Util.fetch(audioInitSegmentUri),
|
|
]);
|
|
ttmlInitSegment = shaka.util.BufferUtils.toUint8(responses[0]);
|
|
ttmlSegment = shaka.util.BufferUtils.toUint8(responses[1]);
|
|
ttmlSegmentMultipleMDAT = shaka.util.BufferUtils.toUint8(responses[2]);
|
|
audioInitSegment = shaka.util.BufferUtils.toUint8(responses[3]);
|
|
});
|
|
|
|
it('parses init segment', () => {
|
|
new shaka.text.Mp4TtmlParser().parseInit(ttmlInitSegment);
|
|
});
|
|
|
|
|
|
it('handles media segments with multiple mdats', () => {
|
|
const parser = new shaka.text.Mp4TtmlParser();
|
|
parser.parseInit(ttmlInitSegment);
|
|
const time = {periodStart: 0, segmentStart: 0, segmentEnd: 0};
|
|
const ret = parser.parseMedia(ttmlSegmentMultipleMDAT, time);
|
|
// Bodies.
|
|
expect(ret.length).toBe(2);
|
|
// Divs.
|
|
expect(ret[0].nestedCues.length).toBe(1);
|
|
expect(ret[1].nestedCues.length).toBe(1);
|
|
// Cues.
|
|
expect(ret[0].nestedCues[0].nestedCues.length).toBe(10);
|
|
expect(ret[1].nestedCues[0].nestedCues.length).toBe(10);
|
|
});
|
|
|
|
it('accounts for offset', () => {
|
|
const time1 = {periodStart: 0, segmentStart: 0, segmentEnd: 0};
|
|
const time2 = {periodStart: 7, segmentStart: 0, segmentEnd: 0};
|
|
|
|
const parser = new shaka.text.Mp4TtmlParser();
|
|
parser.parseInit(ttmlInitSegment);
|
|
|
|
const ret1 = parser.parseMedia(ttmlSegment, time1);
|
|
expect(ret1.length).toBeGreaterThan(0);
|
|
|
|
const ret2 = parser.parseMedia(ttmlSegment, time2);
|
|
expect(ret2.length).toBeGreaterThan(0);
|
|
|
|
expect(ret2[0].startTime).toBe(ret1[0].startTime + 7);
|
|
expect(ret2[0].endTime).toBe(ret1[0].endTime + 7);
|
|
});
|
|
|
|
it('rejects init segment with no ttml', () => {
|
|
const error = shaka.test.Util.jasmineError(new shaka.util.Error(
|
|
shaka.util.Error.Severity.CRITICAL,
|
|
shaka.util.Error.Category.TEXT,
|
|
shaka.util.Error.Code.INVALID_MP4_TTML));
|
|
|
|
expect(() => new shaka.text.Mp4TtmlParser().parseInit(audioInitSegment))
|
|
.toThrow(error);
|
|
});
|
|
|
|
it('parses media segment', () => {
|
|
const cues = [
|
|
{
|
|
startTime: 23,
|
|
endTime: 24.5,
|
|
payload: 'You\'re a jerk, Thom.',
|
|
},
|
|
{
|
|
startTime: 25,
|
|
endTime: 27,
|
|
payload: 'Look Celia, we have to follow our passions;',
|
|
},
|
|
{
|
|
startTime: 27,
|
|
endTime: 30.5,
|
|
nestedCues: [{
|
|
payload: '...you have your robotics, and I',
|
|
}, {
|
|
lineBreak: true,
|
|
}, {
|
|
payload: 'just want to be awesome in space.',
|
|
}],
|
|
},
|
|
{
|
|
startTime: 30.8,
|
|
endTime: 34,
|
|
nestedCues: [{
|
|
payload: 'Why don\'t you just admit that',
|
|
}, {
|
|
lineBreak: true,
|
|
}, {
|
|
payload: 'you\'re freaked out by my robot hand?',
|
|
}],
|
|
},
|
|
{
|
|
startTime: 34.5,
|
|
endTime: 36,
|
|
payload: 'I\'m not freaked out by- it\'s...',
|
|
},
|
|
{
|
|
startTime: 37,
|
|
endTime: 38,
|
|
payload: '...alright! Fine!',
|
|
},
|
|
{
|
|
startTime: 38,
|
|
endTime: 41,
|
|
nestedCues: [{
|
|
payload: 'I\'m freaked out! I have nightmares',
|
|
}, {
|
|
lineBreak: true,
|
|
}, {
|
|
payload: 'that I\'m being chased...',
|
|
}],
|
|
},
|
|
{
|
|
startTime: 41,
|
|
endTime: 42,
|
|
payload: '...by these giant robotic claws of death...',
|
|
},
|
|
{
|
|
startTime: 42.2,
|
|
endTime: 45,
|
|
nestedCues: [{
|
|
payload: '"Fourty years later"',
|
|
}, {
|
|
lineBreak: true,
|
|
}, {
|
|
payload: 'Whatever, Thom. We\'re done.',
|
|
}],
|
|
},
|
|
{
|
|
startTime: 50,
|
|
endTime: 53.5,
|
|
payload: 'Robot\'s memory synced and locked!',
|
|
},
|
|
];
|
|
const parser = new shaka.text.Mp4TtmlParser();
|
|
parser.parseInit(ttmlInitSegment);
|
|
const time = {periodStart: 0, segmentStart: 0, segmentEnd: 0};
|
|
const result = parser.parseMedia(ttmlSegment, time);
|
|
shaka.test.TtmlUtils.verifyHelper(
|
|
cues, result, {startTime: 23, endTime: 53.5});
|
|
});
|
|
});
|