mirror of
https://github.com/shaka-project/shaka-player.git
synced 2026-06-17 16:26:39 +03:00
f539147d48
This fixes all the license headers in the main library, which corrects the appearance of the main license in the compiled output. It seems that the `!` in the header forces the compiler to keep it in the output. I believe older compiler releases did this purely based on `@license`. Issue #2638 Change-Id: I7f0e918caad10c9af689c9d07672b7fe9be7b2f3
269 lines
7.6 KiB
JavaScript
269 lines
7.6 KiB
JavaScript
/*! @license
|
|
* Shaka Player
|
|
* Copyright 2016 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
goog.provide('shaka.media.ManifestParser');
|
|
|
|
goog.require('goog.Uri');
|
|
goog.require('shaka.log');
|
|
goog.require('shaka.net.NetworkingEngine');
|
|
goog.require('shaka.util.Error');
|
|
goog.require('shaka.util.Platform');
|
|
|
|
|
|
// TODO: revisit this when Closure Compiler supports partially-exported classes.
|
|
/**
|
|
* @summary An interface to register manifest parsers.
|
|
* @export
|
|
*/
|
|
shaka.media.ManifestParser = class {
|
|
/**
|
|
* Registers a manifest parser by file extension.
|
|
*
|
|
* @param {string} extension The file extension of the manifest.
|
|
* @param {shaka.extern.ManifestParser.Factory} parserFactory The factory
|
|
* used to create parser instances.
|
|
* @export
|
|
*/
|
|
static registerParserByExtension(extension, parserFactory) {
|
|
shaka.media.ManifestParser.parsersByExtension[extension] = parserFactory;
|
|
}
|
|
|
|
|
|
/**
|
|
* Registers a manifest parser by MIME type.
|
|
*
|
|
* @param {string} mimeType The MIME type of the manifest.
|
|
* @param {shaka.extern.ManifestParser.Factory} parserFactory The factory
|
|
* used to create parser instances.
|
|
* @export
|
|
*/
|
|
static registerParserByMime(mimeType, parserFactory) {
|
|
shaka.media.ManifestParser.parsersByMime[mimeType] = parserFactory;
|
|
}
|
|
|
|
/**
|
|
* Unregisters a manifest parser by MIME type.
|
|
*
|
|
* @param {string} mimeType The MIME type of the manifest.
|
|
* @export
|
|
*/
|
|
static unregisterParserByMime(mimeType) {
|
|
delete shaka.media.ManifestParser.parsersByMime[mimeType];
|
|
}
|
|
|
|
|
|
/**
|
|
* Returns a map of manifest support for well-known types.
|
|
*
|
|
* @return {!Object.<string, boolean>}
|
|
*/
|
|
static probeSupport() {
|
|
const ManifestParser = shaka.media.ManifestParser;
|
|
const support = {};
|
|
|
|
// Make sure all registered parsers are shown, but only for MSE-enabled
|
|
// platforms where our parsers matter.
|
|
if (shaka.util.Platform.supportsMediaSource()) {
|
|
for (const type in ManifestParser.parsersByMime) {
|
|
support[type] = true;
|
|
}
|
|
for (const type in ManifestParser.parsersByExtension) {
|
|
support[type] = true;
|
|
}
|
|
}
|
|
|
|
// Make sure all well-known types are tested as well, just to show an
|
|
// explicit false for things people might be expecting.
|
|
const testMimeTypes = [
|
|
// DASH
|
|
'application/dash+xml',
|
|
// HLS
|
|
'application/x-mpegurl',
|
|
'application/vnd.apple.mpegurl',
|
|
// SmoothStreaming
|
|
'application/vnd.ms-sstr+xml',
|
|
];
|
|
const testExtensions = {
|
|
// DASH
|
|
'mpd': 'application/dash+xml',
|
|
// HLS
|
|
'm3u8': 'application/x-mpegurl',
|
|
// SmoothStreaming
|
|
'ism': 'application/vnd.ms-sstr+xml',
|
|
};
|
|
|
|
for (const type of testMimeTypes) {
|
|
// Only query our parsers for MSE-enabled platforms. Otherwise, query a
|
|
// temporary media element for native support for these types.
|
|
if (shaka.util.Platform.supportsMediaSource()) {
|
|
support[type] = !!ManifestParser.parsersByMime[type];
|
|
} else {
|
|
support[type] = shaka.util.Platform.supportsMediaType(type);
|
|
}
|
|
}
|
|
|
|
for (const extension in testExtensions) {
|
|
// Only query our parsers for MSE-enabled platforms. Otherwise, query a
|
|
// temporary media element for native support for these MIME type for the
|
|
// extension.
|
|
if (shaka.util.Platform.supportsMediaSource()) {
|
|
support[extension] = !!ManifestParser.parsersByExtension[extension];
|
|
} else {
|
|
const type = testExtensions[extension];
|
|
support[extension] = shaka.util.Platform.supportsMediaType(type);
|
|
}
|
|
}
|
|
|
|
return support;
|
|
}
|
|
|
|
|
|
/**
|
|
* Get a factory that can create a manifest parser that should be able to
|
|
* parse the manifest at |uri|.
|
|
*
|
|
* @param {string} uri
|
|
* @param {!shaka.net.NetworkingEngine} netEngine
|
|
* @param {shaka.extern.RetryParameters} retryParams
|
|
* @param {?string} mimeType
|
|
* @return {!Promise.<shaka.extern.ManifestParser.Factory>}
|
|
*/
|
|
static async getFactory(uri, netEngine, retryParams, mimeType) {
|
|
const ManifestParser = shaka.media.ManifestParser;
|
|
|
|
// Try using the MIME type we were given.
|
|
if (mimeType) {
|
|
const factory = ManifestParser.parsersByMime[mimeType.toLowerCase()];
|
|
if (factory) {
|
|
return factory;
|
|
}
|
|
|
|
shaka.log.warning(
|
|
'Could not determine manifest type using MIME type ', mimeType);
|
|
}
|
|
|
|
const extension = ManifestParser.getExtension(uri);
|
|
if (extension) {
|
|
const factory = ManifestParser.parsersByExtension[extension];
|
|
if (factory) {
|
|
return factory;
|
|
}
|
|
|
|
shaka.log.warning(
|
|
'Could not determine manifest type for extension ', extension);
|
|
} else {
|
|
shaka.log.warning('Could not find extension for ', uri);
|
|
}
|
|
|
|
if (!mimeType) {
|
|
mimeType = await ManifestParser.getMimeType(uri, netEngine, retryParams);
|
|
|
|
if (mimeType) {
|
|
const factory = shaka.media.ManifestParser.parsersByMime[mimeType];
|
|
if (factory) {
|
|
return factory;
|
|
}
|
|
|
|
shaka.log.warning('Could not determine manifest type using MIME type',
|
|
mimeType);
|
|
}
|
|
}
|
|
|
|
throw new shaka.util.Error(
|
|
shaka.util.Error.Severity.CRITICAL,
|
|
shaka.util.Error.Category.MANIFEST,
|
|
shaka.util.Error.Code.UNABLE_TO_GUESS_MANIFEST_TYPE,
|
|
uri);
|
|
}
|
|
|
|
|
|
/**
|
|
* @param {string} uri
|
|
* @param {!shaka.net.NetworkingEngine} netEngine
|
|
* @param {shaka.extern.RetryParameters} retryParams
|
|
* @return {!Promise.<string>}
|
|
*/
|
|
static async getMimeType(uri, netEngine, retryParams) {
|
|
const type = shaka.net.NetworkingEngine.RequestType.MANIFEST;
|
|
|
|
const request = shaka.net.NetworkingEngine.makeRequest([uri], retryParams);
|
|
request.method = 'HEAD';
|
|
|
|
const response = await netEngine.request(type, request).promise;
|
|
|
|
// https://bit.ly/2K9s9kf says this header should always be available,
|
|
// but just to be safe:
|
|
const mimeType = response.headers['content-type'];
|
|
return mimeType ? mimeType.toLowerCase().split(';').shift() : '';
|
|
}
|
|
|
|
|
|
/**
|
|
* @param {string} uri
|
|
* @return {string}
|
|
*/
|
|
static getExtension(uri) {
|
|
const uriObj = new goog.Uri(uri);
|
|
const uriPieces = uriObj.getPath().split('/');
|
|
const uriFilename = uriPieces.pop();
|
|
const filenamePieces = uriFilename.split('.');
|
|
|
|
// Only one piece means there is no extension.
|
|
if (filenamePieces.length == 1) {
|
|
return '';
|
|
}
|
|
|
|
return filenamePieces.pop().toLowerCase();
|
|
}
|
|
|
|
|
|
/**
|
|
* Determines whether or not this URI and MIME type are supported by our own
|
|
* manifest parsers on this platform. This takes into account whether or not
|
|
* MediaSource is available, as well as which parsers are registered to the
|
|
* system.
|
|
*
|
|
* @param {string} uri
|
|
* @param {string} mimeType
|
|
* @return {boolean}
|
|
*/
|
|
static isSupported(uri, mimeType) {
|
|
// Without MediaSource, our own parsers are useless.
|
|
if (!shaka.util.Platform.supportsMediaSource()) {
|
|
return false;
|
|
}
|
|
|
|
if (mimeType in shaka.media.ManifestParser.parsersByMime) {
|
|
return true;
|
|
}
|
|
|
|
const extension = shaka.media.ManifestParser.getExtension(uri);
|
|
if (extension in shaka.media.ManifestParser.parsersByExtension) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* Contains the parser factory functions indexed by MIME type.
|
|
*
|
|
* @type {!Object.<string, shaka.extern.ManifestParser.Factory>}
|
|
*/
|
|
shaka.media.ManifestParser.parsersByMime = {};
|
|
|
|
|
|
/**
|
|
* Contains the parser factory functions indexed by file extension.
|
|
*
|
|
* @type {!Object.<string, shaka.extern.ManifestParser.Factory>}
|
|
*/
|
|
shaka.media.ManifestParser.parsersByExtension = {};
|
|
|
|
|