Files
shaka-player/test/offline/offline_utils_unit.js
T
Michelle Zhuo f09999aa80 Add channel count information for HLS audio tracks
Adding the count of channels, as a new field for tracks and streams.
Used for HLS audio tracks.

Resolves #826.

Change-Id: I1448b4a8cfaf6dd798670bb2f0f3981d6c7e40c3
2017-06-22 11:34:36 -07:00

303 lines
9.7 KiB
JavaScript

/**
* @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('OfflineUtils', function() {
var OfflineUtils;
var drmInfos;
var timeline;
beforeAll(function() {
OfflineUtils = shaka.offline.OfflineUtils;
});
beforeEach(function() {
drmInfos = [{
keySystem: 'com.example.drm',
licenseServerUri: 'https://example.com/drm',
distinctiveIdentifierRequired: false,
persistentStateRequired: true,
audioRobustness: 'weak',
videoRobustness: 'awesome',
serverCertificate: null,
initData: [{initData: new Uint8Array([1]), initDataType: 'foo'}],
keyIds: ['key1', 'key2']
}];
timeline = new shaka.media.PresentationTimeline(null, 0);
});
describe('reconstructPeriod', function() {
it('will reconstruct Periods correctly', function() {
/** @type {shakaExtern.PeriodDB} */
var periodDb = {
startTime: 60,
streams: [createVideoStreamDb(1), createAudioStreamDb(2)]
};
var period = OfflineUtils.reconstructPeriod(periodDb, drmInfos, timeline);
expect(period).toBeTruthy();
expect(period.startTime).toBe(periodDb.startTime);
expect(period.textStreams).toEqual([]);
expect(period.variants.length).toBe(1);
var variant = period.variants[0];
expect(variant.id).toEqual(jasmine.any(Number));
expect(variant.language).toBe(periodDb.streams[1].language);
expect(variant.primary).toBe(false);
expect(variant.bandwidth).toEqual(jasmine.any(Number));
expect(variant.drmInfos).toBe(drmInfos);
expect(variant.allowedByApplication).toBe(true);
expect(variant.allowedByKeySystem).toBe(true);
verifyStream(variant.video, periodDb.streams[0]);
verifyStream(variant.audio, periodDb.streams[1]);
});
it('supports video-only content', function() {
/** @type {shakaExtern.PeriodDB} */
var periodDb = {
startTime: 60,
streams: [createVideoStreamDb(1), createVideoStreamDb(2)]
};
var period = OfflineUtils.reconstructPeriod(periodDb, drmInfos, timeline);
expect(period).toBeTruthy();
expect(period.variants.length).toBe(2);
expect(period.variants[0].audio).toBe(null);
expect(period.variants[0].video).toBeTruthy();
});
it('supports audio-only content', function() {
/** @type {shakaExtern.PeriodDB} */
var periodDb = {
startTime: 60,
streams: [createAudioStreamDb(1), createAudioStreamDb(2)]
};
var period = OfflineUtils.reconstructPeriod(periodDb, drmInfos, timeline);
expect(period).toBeTruthy();
expect(period.variants.length).toBe(2);
expect(period.variants[0].audio).toBeTruthy();
expect(period.variants[0].video).toBe(null);
});
it('supports text streams', function() {
/** @type {shakaExtern.PeriodDB} */
var periodDb = {
startTime: 60,
streams: [
createVideoStreamDb(1),
createTextStreamDb(2)
]
};
var period = OfflineUtils.reconstructPeriod(periodDb, drmInfos, timeline);
expect(period).toBeTruthy();
expect(period.variants.length).toBe(1);
expect(period.textStreams.length).toBe(1);
verifyStream(period.textStreams[0], periodDb.streams[1]);
});
it('combines Variants according to variantIds field', function() {
/** @type {shakaExtern.PeriodDB} */
var periodDb = {
startTime: 60,
streams: [
createVideoStreamDb(1, [10]),
createVideoStreamDb(2, [11]),
createVideoStreamDb(3, [12, 13]),
createAudioStreamDb(4, [12]),
createAudioStreamDb(5, [10, 13, 14])
]
};
var period = OfflineUtils.reconstructPeriod(periodDb, drmInfos, timeline);
expect(period).toBeTruthy();
expect(period.variants.length).toBe(3);
verifyContainsVariantWithStreamIds(period, 1, 5); // Variant 10
verifyContainsVariantWithStreamIds(period, 3, 4); // Variant 12
verifyContainsVariantWithStreamIds(period, 3, 5); // Variant 13
});
/**
* @param {number} id
* @param {!Array.<number>=} opt_variantIds
* @return {shakaExtern.StreamDB}
*/
function createVideoStreamDb(id, opt_variantIds) {
var ContentType = shaka.util.ManifestParserUtils.ContentType;
return {
id: id,
primary: false,
presentationTimeOffset: 25,
contentType: ContentType.VIDEO,
mimeType: 'video/mp4',
codecs: 'avc1.42c01e',
frameRate: 22,
kind: undefined,
language: '',
label: null,
width: 250,
height: 100,
initSegmentUri: null,
encrypted: true,
keyId: 'key1',
segments: [
{startTime: 0, endTime: 10, uri: 'offline:1/1/1'},
{startTime: 10, endTime: 20, uri: 'offline:1/1/2'},
{startTime: 20, endTime: 25, uri: 'offline:1/1/3'}
],
variantIds: opt_variantIds || [5]
};
}
/**
* @param {number} id
* @param {!Array.<number>=} opt_variantIds
* @return {shakaExtern.StreamDB}
*/
function createAudioStreamDb(id, opt_variantIds) {
var ContentType = shaka.util.ManifestParserUtils.ContentType;
return {
id: id,
primary: false,
presentationTimeOffset: 10,
contentType: ContentType.AUDIO,
mimeType: 'audio/mp4',
codecs: 'mp4a.40.2',
frameRate: undefined,
kind: undefined,
language: 'en',
label: null,
width: null,
height: null,
initSegmentUri: 'offline:1/' + id + '/0',
encrypted: false,
keyId: null,
segments: [
{startTime: 0, endTime: 10, uri: 'offline:1/' + id + '/1'},
{startTime: 10, endTime: 20, uri: 'offline:1/' + id + '/2'},
{startTime: 20, endTime: 25, uri: 'offline:1/' + id + '/3'}
],
variantIds: opt_variantIds || [5]
};
}
/**
* @param {number} id
* @return {shakaExtern.StreamDB}
*/
function createTextStreamDb(id) {
var ContentType = shaka.util.ManifestParserUtils.ContentType;
return {
id: id,
primary: false,
presentationTimeOffset: 10,
contentType: ContentType.TEXT,
mimeType: 'text/vtt',
codecs: '',
frameRate: undefined,
kind: undefined,
language: 'en',
label: null,
width: null,
height: null,
initSegmentUri: 'offline:1/' + id + '/0',
encrypted: false,
keyId: null,
segments: [
{startTime: 0, endTime: 10, uri: 'offline:1/' + id + '/1'},
{startTime: 10, endTime: 20, uri: 'offline:1/' + id + '/2'},
{startTime: 20, endTime: 25, uri: 'offline:1/' + id + '/3'}
],
variantIds: [5]
};
}
/**
* @param {shakaExtern.Stream} stream
* @param {shakaExtern.StreamDB} streamDb
*/
function verifyStream(stream, streamDb) {
if (!streamDb) {
expect(stream).toBeFalsy();
return;
}
var expectedStream = {
id: jasmine.any(Number),
createSegmentIndex: jasmine.any(Function),
findSegmentPosition: jasmine.any(Function),
getSegmentReference: jasmine.any(Function),
initSegmentReference: streamDb.initSegmentUri ?
jasmine.any(shaka.media.InitSegmentReference) :
null,
presentationTimeOffset: streamDb.presentationTimeOffset,
mimeType: streamDb.mimeType,
codecs: streamDb.codecs,
frameRate: streamDb.frameRate,
width: streamDb.width || undefined,
height: streamDb.height || undefined,
kind: streamDb.kind,
encrypted: streamDb.encrypted,
keyId: streamDb.keyId,
language: streamDb.language,
label: streamDb.label,
type: streamDb.contentType,
primary: streamDb.primary,
trickModeVideo: null,
containsEmsgBoxes: false,
roles: [],
channelsCount: null
};
expect(stream).toEqual(expectedStream);
// Assume that we don't have to call createSegmentIndex.
for (var i = 0; i < streamDb.segments.length; i++) {
var segmentDb = streamDb.segments[i];
expect(stream.findSegmentPosition(segmentDb.startTime)).toBe(i);
expect(stream.findSegmentPosition(segmentDb.endTime - 0.1)).toBe(i);
var segment = stream.getSegmentReference(i);
expect(segment).toBeTruthy();
expect(segment.position).toBe(i);
expect(segment.startTime).toBe(segmentDb.startTime);
expect(segment.endTime).toBe(segmentDb.endTime);
expect(segment.startByte).toBe(0);
expect(segment.endByte).toBe(null);
expect(segment.getUris()).toEqual([segmentDb.uri]);
}
}
/**
* @param {shakaExtern.Period} period
* @param {number} videoId
* @param {number} audioId
*/
function verifyContainsVariantWithStreamIds(period, videoId, audioId) {
var found = period.variants.some(function(variant) {
var audioIdMatches = variant.audio && variant.audio.id === audioId;
var videoIdMatches = variant.video && variant.video.id === videoId;
return audioIdMatches && videoIdMatches;
});
expect(found).toBe(true);
}
});
});