rx-player
Version:
Canal+ HTML5 Video Player
197 lines (184 loc) • 7.33 kB
text/typescript
/**
* Copyright 2015 CANAL+ Group
*
* 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.
*/
import noop from "../../../../../../utils/noop";
import type { IMPDAttributes, IMPDChildren } from "../../../node_parser_types";
import type { IAttributeParser, IChildrenParser } from "../parsers_stack";
import type ParsersStack from "../parsers_stack";
import { AttributeName, TagName } from "../types";
import { parseString } from "../utils";
import { generateBaseUrlAttrParser } from "./BaseURL";
import { generateContentProtectionAttrParser } from "./ContentProtection";
import { generatePeriodAttrParser, generatePeriodChildrenParser } from "./Period";
import { generateSchemeAttrParser } from "./Scheme";
/**
* Generate a "children parser" once inside an `MPD` node.
* @param {Object} mpdChildren
* @param {WebAssembly.Memory} linearMemory
* @param {ParsersStack} parsersStack
* @param {ArrayBuffer} fullMpd
* @returns {Function}
*/
export function generateMPDChildrenParser(
mpdChildren: IMPDChildren,
linearMemory: WebAssembly.Memory,
parsersStack: ParsersStack,
fullMpd: ArrayBuffer,
): IChildrenParser {
return function onRootChildren(nodeId: number) {
switch (nodeId) {
case TagName.BaseURL: {
const baseUrl = { value: "", attributes: {} };
mpdChildren.baseURLs.push(baseUrl);
const childrenParser = noop; // BaseURL have no sub-element
const attributeParser = generateBaseUrlAttrParser(baseUrl, linearMemory);
parsersStack.pushParsers(nodeId, childrenParser, attributeParser);
break;
}
case TagName.Period: {
const period = {
children: { adaptations: [], baseURLs: [], eventStreams: [] },
attributes: {},
};
mpdChildren.periods.push(period);
const childrenParser = generatePeriodChildrenParser(
period.children,
linearMemory,
parsersStack,
fullMpd,
);
const attributeParser = generatePeriodAttrParser(period.attributes, linearMemory);
parsersStack.pushParsers(nodeId, childrenParser, attributeParser);
break;
}
case TagName.UtcTiming: {
const utcTiming = {};
mpdChildren.utcTimings.push(utcTiming);
const childrenParser = noop; // UTCTiming have no sub-element
const attributeParser = generateSchemeAttrParser(utcTiming, linearMemory);
parsersStack.pushParsers(nodeId, childrenParser, attributeParser);
break;
}
case TagName.ContentProtection: {
const contentProtection = {
children: { cencPssh: [] },
attributes: {},
};
if (mpdChildren.contentProtections === undefined) {
mpdChildren.contentProtections = [];
}
mpdChildren.contentProtections.push(contentProtection);
const contentProtAttrParser = generateContentProtectionAttrParser(
contentProtection,
linearMemory,
);
parsersStack.pushParsers(nodeId, noop, contentProtAttrParser);
break;
}
default:
// Allows to make sure we're not mistakenly closing a re-opened
// tag.
parsersStack.pushParsers(nodeId, noop, noop);
break;
}
};
}
export function generateMPDAttrParser(
mpdChildren: IMPDChildren,
mpdAttrs: IMPDAttributes,
linearMemory: WebAssembly.Memory,
): IAttributeParser {
let dataView;
const textDecoder = new TextDecoder();
return function onMPDAttribute(attr: number, ptr: number, len: number) {
switch (attr) {
case AttributeName.Id:
mpdAttrs.id = parseString(textDecoder, linearMemory.buffer, ptr, len);
break;
case AttributeName.Profiles:
mpdAttrs.profiles = parseString(textDecoder, linearMemory.buffer, ptr, len);
break;
case AttributeName.Type:
mpdAttrs.type = parseString(textDecoder, linearMemory.buffer, ptr, len);
break;
case AttributeName.AvailabilityStartTime: {
const startTime = parseString(textDecoder, linearMemory.buffer, ptr, len);
mpdAttrs.availabilityStartTime = new Date(startTime).getTime() / 1000;
break;
}
case AttributeName.AvailabilityEndTime: {
const endTime = parseString(textDecoder, linearMemory.buffer, ptr, len);
mpdAttrs.availabilityEndTime = new Date(endTime).getTime() / 1000;
break;
}
case AttributeName.PublishTime: {
const publishTime = parseString(textDecoder, linearMemory.buffer, ptr, len);
mpdAttrs.publishTime = new Date(publishTime).getTime() / 1000;
break;
}
case AttributeName.MediaPresentationDuration:
dataView = new DataView(linearMemory.buffer);
mpdAttrs.duration = dataView.getFloat64(ptr, true);
break;
case AttributeName.MinimumUpdatePeriod:
dataView = new DataView(linearMemory.buffer);
mpdAttrs.minimumUpdatePeriod = dataView.getFloat64(ptr, true);
break;
case AttributeName.MinBufferTime:
dataView = new DataView(linearMemory.buffer);
mpdAttrs.minBufferTime = dataView.getFloat64(ptr, true);
break;
case AttributeName.TimeShiftBufferDepth:
dataView = new DataView(linearMemory.buffer);
mpdAttrs.timeShiftBufferDepth = dataView.getFloat64(ptr, true);
break;
case AttributeName.SuggestedPresentationDelay:
dataView = new DataView(linearMemory.buffer);
mpdAttrs.suggestedPresentationDelay = dataView.getFloat64(ptr, true);
break;
case AttributeName.MaxSegmentDuration:
dataView = new DataView(linearMemory.buffer);
mpdAttrs.maxSegmentDuration = dataView.getFloat64(ptr, true);
break;
case AttributeName.MaxSubsegmentDuration:
dataView = new DataView(linearMemory.buffer);
mpdAttrs.maxSubsegmentDuration = dataView.getFloat64(ptr, true);
break;
case AttributeName.Location: {
const location = parseString(textDecoder, linearMemory.buffer, ptr, len);
mpdChildren.locations.push(location);
break;
}
case AttributeName.Namespace: {
const xmlNs = { key: "", value: "" };
dataView = new DataView(linearMemory.buffer);
let offset = ptr;
const keySize = dataView.getUint32(offset);
offset += 4;
xmlNs.key = parseString(textDecoder, linearMemory.buffer, offset, keySize);
offset += keySize;
const valSize = dataView.getUint32(offset);
offset += 4;
xmlNs.value = parseString(textDecoder, linearMemory.buffer, offset, valSize);
if (mpdAttrs.namespaces === undefined) {
mpdAttrs.namespaces = [xmlNs];
} else {
mpdAttrs.namespaces.push(xmlNs);
}
break;
}
}
};
}