/**
* @license
* Copyright 2016 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
describe('DashParser SegmentBase', () => {
const Dash = shaka.test.Dash;
const indexSegmentUri = '/base/test/test/assets/index-segment.mp4';
/** @type {!shaka.test.FakeNetworkingEngine} */
let fakeNetEngine;
/** @type {!shaka.dash.DashParser} */
let parser;
/** @type {shaka.extern.ManifestParser.PlayerInterface} */
let playerInterface;
/** @type {!ArrayBuffer} */
let indexSegment;
beforeAll(async () => {
indexSegment = await shaka.test.Util.fetch(indexSegmentUri);
});
beforeEach(() => {
fakeNetEngine = new shaka.test.FakeNetworkingEngine();
parser = shaka.test.Dash.makeDashParser();
playerInterface = {
networkingEngine: fakeNetEngine,
filterNewPeriod: () => {},
filterAllPeriods: () => {},
onTimelineRegionAdded: fail, // Should not have any EventStream elements.
onEvent: fail,
onError: fail,
};
});
it('requests init data for WebM', async () => {
const source = [
'',
' ',
' ',
' ',
' http://example.com',
' ',
' ',
' ',
' ',
' ',
' ',
'',
].join('\n');
fakeNetEngine
.setResponseText('dummy://foo', source)
.setResponseText('http://example.com', '')
.setResponseText('http://example.com/init.webm', '');
const manifest = await parser.start('dummy://foo', playerInterface);
expect(manifest).toEqual(Dash.makeManifestFromInit('init.webm', 201, 300));
await Dash.callCreateSegmentIndex(manifest);
expect(fakeNetEngine.request).toHaveBeenCalledTimes(3);
fakeNetEngine.expectRangeRequest('http://example.com', 100, 200);
fakeNetEngine.expectRangeRequest('http://example.com/init.webm', 201, 300);
});
it('inherits from Period', async () => {
const source = [
'',
' ',
' http://example.com',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
'',
].join('\n');
fakeNetEngine
.setResponseText('dummy://foo', source)
.setResponseText('http://example.com', '');
const manifest = await parser.start('dummy://foo', playerInterface);
expect(manifest).toEqual(Dash.makeManifestFromInit('init.mp4', 201, 300));
await Dash.callCreateSegmentIndex(manifest);
expect(fakeNetEngine.request).toHaveBeenCalledTimes(2);
fakeNetEngine.expectRangeRequest('http://example.com', 100, 200);
});
it('inherits from AdaptationSet', async () => {
const source = [
'',
' ',
' ',
' http://example.com',
' ',
' ',
' ',
' ',
' ',
' ',
'',
].join('\n');
fakeNetEngine
.setResponseText('dummy://foo', source)
.setResponseText('http://example.com', '');
const manifest = await parser.start('dummy://foo', playerInterface);
expect(manifest).toEqual(Dash.makeManifestFromInit('init.mp4', 201, 300));
await Dash.callCreateSegmentIndex(manifest);
expect(fakeNetEngine.request).toHaveBeenCalledTimes(2);
fakeNetEngine.expectRangeRequest('http://example.com', 100, 200);
});
it('does not require sourceURL in Initialization', async () => {
const source = [
'',
' ',
' ',
' ',
' http://example.com/stream.mp4',
' ',
' ',
' ',
' ',
' ',
' ',
'',
].join('\n');
fakeNetEngine
.setResponseText('dummy://foo', source)
.setResponseText('http://example.com/stream.mp4', '');
const manifest = await parser.start('dummy://foo', playerInterface);
expect(manifest).toEqual(Dash.makeManifestFromInit('stream.mp4', 201, 300));
await Dash.callCreateSegmentIndex(manifest);
expect(fakeNetEngine.request).toHaveBeenCalledTimes(2);
fakeNetEngine.expectRangeRequest('http://example.com/stream.mp4', 100, 200);
});
it('merges across levels', async () => {
const source = [
'',
' ',
' http://example.com',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
'',
].join('\n');
fakeNetEngine
.setResponseText('dummy://foo', source)
.setResponseText('http://example.com/index.mp4', '');
const manifest = await parser.start('dummy://foo', playerInterface);
expect(manifest).toEqual(
Dash.makeManifestFromInit('init.mp4', 201, 300, 10));
await Dash.callCreateSegmentIndex(manifest);
expect(fakeNetEngine.request).toHaveBeenCalledTimes(2);
fakeNetEngine.expectRangeRequest('http://example.com/index.mp4', 5, 2000);
});
it('merges and overrides across levels', async () => {
const source = [
'',
' ',
' http://example.com',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
'',
].join('\n');
fakeNetEngine
.setResponseText('dummy://foo', source)
.setResponseText('http://example.com', '');
const manifest = await parser.start('dummy://foo', playerInterface);
expect(manifest).toEqual(
Dash.makeManifestFromInit('special.mp4', 0, null, 20));
await Dash.callCreateSegmentIndex(manifest);
expect(fakeNetEngine.request).toHaveBeenCalledTimes(2);
fakeNetEngine.expectRangeRequest('http://example.com', 30, 900);
});
it('does not assume the same timescale as media', async () => {
const source = [
'',
' ',
' ',
' ',
' http://example.com/index.mp4',
' ',
' ',
' ',
' ',
'',
].join('\n');
fakeNetEngine
.setResponseText('dummy://foo', source)
.setResponseValue('http://example.com/index.mp4', indexSegment);
const manifest = await parser.start('dummy://foo', playerInterface);
const video = manifest.periods[0].variants[0].video;
await video.createSegmentIndex(); // real data, should succeed
const reference = video.getSegmentReference(0);
expect(reference.startTime).toBe(-2);
expect(reference.endTime).toBe(10); // would be 12 without PTO
});
describe('fails for', () => {
it('unsupported container', async () => {
const source = [
'',
' ',
' http://example.com',
' ',
' ',
' ',
' ',
' ',
' ',
'',
].join('\n');
const error = new shaka.util.Error(
shaka.util.Error.Severity.CRITICAL,
shaka.util.Error.Category.MANIFEST,
shaka.util.Error.Code.DASH_UNSUPPORTED_CONTAINER);
await Dash.testFails(source, error);
});
it('missing init segment for WebM', async () => {
const source = [
'',
' ',
' http://example.com',
' ',
' ',
' ',
' ',
' ',
' ',
'',
].join('\n');
const error = new shaka.util.Error(
shaka.util.Error.Severity.CRITICAL,
shaka.util.Error.Category.MANIFEST,
shaka.util.Error.Code.DASH_WEBM_MISSING_INIT);
await Dash.testFails(source, error);
});
it('no @indexRange nor RepresentationIndex', async () => {
const source = [
'',
' ',
' http://example.com',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
'',
].join('\n');
const error = new shaka.util.Error(
shaka.util.Error.Severity.CRITICAL,
shaka.util.Error.Category.MANIFEST,
shaka.util.Error.Code.DASH_NO_SEGMENT_INFO);
await Dash.testFails(source, error);
});
});
});