Skip to content

Commit

Permalink
chore: Remove state engine (#5752)
Browse files Browse the repository at this point in the history
The state engine mechanism, designed for the player class, was
over-engineered. The structure of the class makes debugging player
errors unnecessarily annoying, by obfuscating the code-path the error
followed, and in general
has created a significant amount of technical debt.
This changes the player to use an async-await setup for the top-level
operations, laying things out much more cleanly
and linearly.

---------

Co-authored-by: Álvaro Velad Galván <ladvan91@hotmail.com>
  • Loading branch information
theodab and avelad authored Oct 31, 2023
1 parent c457db8 commit 4425dca
Show file tree
Hide file tree
Showing 43 changed files with 913 additions and 2,842 deletions.
5 changes: 1 addition & 4 deletions build/types/core
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,6 @@

+../../lib/polyfill/all.js

+../../lib/routing/node.js
+../../lib/routing/payload.js
+../../lib/routing/walker.js

+../../lib/cea/dummy_cea_parser.js
+../../lib/cea/dummy_caption_decoder.js

Expand Down Expand Up @@ -101,6 +97,7 @@
+../../lib/util/mp4_generator.js
+../../lib/util/mp4_parser.js
+../../lib/util/multi_map.js
+../../lib/util/mutex.js
+../../lib/util/networking.js
+../../lib/util/object_utils.js
+../../lib/util/operation_manager.js
Expand Down
6 changes: 3 additions & 3 deletions demo/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -709,15 +709,15 @@ shakaDemo.Main = class {

// Does the browser support the asset's manifest type?
if (asset.features.includes(shakaAssets.Feature.DASH) &&
!this.support_.manifest['mpd']) {
!this.support_.manifest['application/dash+xml']) {
return 'Your browser does not support MPEG-DASH manifests.';
}
if (asset.features.includes(shakaAssets.Feature.HLS) &&
!this.support_.manifest['m3u8']) {
!this.support_.manifest['application/x-mpegurl']) {
return 'Your browser does not support HLS manifests.';
}
if (asset.features.includes(shakaAssets.Feature.MSS) &&
!this.support_.manifest['ism']) {
!this.support_.manifest['application/vnd.ms-sstr+xml']) {
return 'Your browser does not support MSS manifests.';
}

Expand Down
3 changes: 2 additions & 1 deletion docs/tutorials/basic-usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ function initApp() {
async function initPlayer() {
// Create a Player instance.
const video = document.getElementById('video');
const player = new shaka.Player(video);
const player = new shaka.Player();
async player.attach(video);

// Attach player to the window to make it easy to access in the JS console.
window.player = player;
Expand Down
3 changes: 2 additions & 1 deletion docs/tutorials/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ const handleError = (error) => {
}
};

const player = new shaka.Player(video);
const player = new shaka.Player();
await player.attach(video);

// handle errors that occur after load
player.addEventListener('error', handleError);
Expand Down
18 changes: 10 additions & 8 deletions docs/tutorials/offline.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,14 @@ the end of the tutorial.
```js
// myapp.js

function initApp() {
async function initApp() {
// Install built-in polyfills to patch browser incompatibilities.
shaka.polyfill.installAll();

// Check to see if the browser supports the basic APIs Shaka needs.
if (shaka.Player.isBrowserSupported()) {
// Everything looks good!
initPlayer();
await initPlayer();
} else {
// This browser does not have the minimum set of APIs we need.
console.error('Browser not supported!');
Expand All @@ -99,10 +99,11 @@ function initApp() {
window.addEventListener('offline', updateOnlineStatus);
}

function initPlayer() {
async function initPlayer() {
// Create a Player instance.
const video = document.getElementById('video');
const player = new shaka.Player(video);
const player = new shaka.Player();
await player.attach(video);

// Attach player and storage to the window to make it easy to access
// in the JS console and so we can access it in other methods.
Expand Down Expand Up @@ -437,14 +438,14 @@ That’s it! For your convenience, here is the completed code:
```js
// myapp.js

function initApp() {
async function initApp() {
// Install built-in polyfills to patch browser incompatibilities.
shaka.polyfill.installAll();

// Check to see if the browser supports the basic APIs Shaka needs.
if (shaka.Player.isBrowserSupported()) {
// Everything looks good!
initPlayer();
await initPlayer();
} else {
// This browser does not have the minimum set of APIs we need.
console.error('Browser not supported!');
Expand All @@ -457,10 +458,11 @@ function initApp() {
window.addEventListener('offline', updateOnlineStatus);
}

function initPlayer() {
async function initPlayer() {
// Create a Player instance.
const video = document.getElementById('video');
const player = new shaka.Player(video);
const player = new shaka.Player();
await player.attach(video);

// Attach player and storage to the window to make it easy to access
// in the JS console and so we can access it in other methods.
Expand Down
3 changes: 2 additions & 1 deletion docs/tutorials/ui.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,8 @@ constructor.
```js
// "local" because it is for local playback only, as opposed to the player proxy
// object, which will route your calls to the ChromeCast receiver as necessary.
const localPlayer = new shaka.Player(videoElement);
const localPlayer = new shaka.Player();
await localPlayer.attach(videoElement);
// "Overlay" because the UI will add DOM elements inside the container,
// to visually overlay the video element
const ui = new shaka.ui.Overlay(localPlayer, videoContainerElement,
Expand Down
2 changes: 1 addition & 1 deletion lib/cast/cast_receiver.js
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ shaka.cast.CastReceiver = class extends shaka.util.FakeEventTarget {
} catch (error) {
// Pass any errors through to the app.
goog.asserts.assert(error instanceof shaka.util.Error,
'Wrong error type!');
'Wrong error type! Error: ' + error);
const eventType = shaka.util.FakeEvent.EventName.Error;
const data = (new Map()).set('detail', error);
const event = new shaka.util.FakeEvent(eventType, data);
Expand Down
2 changes: 0 additions & 2 deletions lib/dash/dash_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -2254,8 +2254,6 @@ shaka.dash.DashParser.GenerateSegmentIndexFunction;
shaka.dash.DashParser.StreamInfo;


shaka.media.ManifestParser.registerParserByExtension(
'mpd', () => new shaka.dash.DashParser());
shaka.media.ManifestParser.registerParserByMime(
'application/dash+xml', () => new shaka.dash.DashParser());
shaka.media.ManifestParser.registerParserByMime(
Expand Down
2 changes: 0 additions & 2 deletions lib/hls/hls_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -4003,8 +4003,6 @@ shaka.hls.HlsParser.PresentationType_ = {
LIVE: 'LIVE',
};

shaka.media.ManifestParser.registerParserByExtension(
'm3u8', () => new shaka.hls.HlsParser());
shaka.media.ManifestParser.registerParserByMime(
'application/x-mpegurl', () => new shaka.hls.HlsParser());
shaka.media.ManifestParser.registerParserByMime(
Expand Down
102 changes: 8 additions & 94 deletions lib/media/manifest_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@

goog.provide('shaka.media.ManifestParser');

goog.require('goog.Uri');
goog.require('shaka.Deprecate');
goog.require('shaka.log');
goog.require('shaka.net.NetworkingEngine');
goog.require('shaka.net.NetworkingUtils');
goog.require('shaka.util.Error');
goog.require('shaka.util.Platform');

Expand All @@ -29,7 +27,9 @@ shaka.media.ManifestParser = class {
* @export
*/
static registerParserByExtension(extension, parserFactory) {
shaka.media.ManifestParser.parsersByExtension[extension] = parserFactory;
shaka.Deprecate.deprecateFeature(5,
'ManifestParser',
'Please use an ManifestParser with registerParserByMime function.');
}


Expand Down Expand Up @@ -71,9 +71,6 @@ shaka.media.ManifestParser = class {
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
Expand All @@ -87,14 +84,6 @@ shaka.media.ManifestParser = class {
// 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
Expand All @@ -106,18 +95,6 @@ shaka.media.ManifestParser = class {
}
}

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;
}

Expand All @@ -127,12 +104,10 @@ shaka.media.ManifestParser = class {
* 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>}
* @return {shaka.extern.ManifestParser.Factory}
*/
static async getFactory(uri, netEngine, retryParams, mimeType) {
static getFactory(uri, mimeType) {
const ManifestParser = shaka.media.ManifestParser;

// Try using the MIME type we were given.
Expand All @@ -146,34 +121,6 @@ shaka.media.ManifestParser = class {
'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 shaka.net.NetworkingUtils.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,
Expand All @@ -183,35 +130,15 @@ shaka.media.ManifestParser = class {


/**
* @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
* Determines whether or not the MIME type is 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) {
static isSupported(mimeType) {
// Without MediaSource, our own parsers are useless.
if (!shaka.util.Platform.supportsMediaSource()) {
return false;
Expand All @@ -221,11 +148,6 @@ shaka.media.ManifestParser = class {
return true;
}

const extension = shaka.media.ManifestParser.getExtension(uri);
if (extension in shaka.media.ManifestParser.parsersByExtension) {
return true;
}

return false;
}
};
Expand Down Expand Up @@ -273,11 +195,3 @@ shaka.media.ManifestParser.AccessibilityPurpose = {
shaka.media.ManifestParser.parsersByMime = {};


/**
* Contains the parser factory functions indexed by file extension.
*
* @type {!Object.<string, shaka.extern.ManifestParser.Factory>}
*/
shaka.media.ManifestParser.parsersByExtension = {};


4 changes: 2 additions & 2 deletions lib/media/media_source_engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -514,8 +514,8 @@ shaka.media.MediaSourceEngine = class {
shaka.util.Error.Category.MEDIA,
shaka.util.Error.Code.MEDIA_SOURCE_OPERATION_THREW,
exception,
'The mediaSource_ status was' + this.mediaSource_.readyState +
'expected \'open\'');
'The mediaSource_ status was ' + this.mediaSource_.readyState +
' expected \'open\'');
}

if (this.sequenceMode_) {
Expand Down
2 changes: 0 additions & 2 deletions lib/mss/mss_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -1086,7 +1086,5 @@ shaka.mss.MssParser.Context;
*/
shaka.mss.MssParser.TimeRange;

shaka.media.ManifestParser.registerParserByExtension(
'ism', () => new shaka.mss.MssParser());
shaka.media.ManifestParser.registerParserByMime(
'application/vnd.ms-sstr+xml', () => new shaka.mss.MssParser());
10 changes: 7 additions & 3 deletions lib/offline/storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ goog.require('shaka.log');
goog.require('shaka.media.DrmEngine');
goog.require('shaka.media.ManifestParser');
goog.require('shaka.net.NetworkingEngine');
goog.require('shaka.net.NetworkingUtils');
goog.require('shaka.offline.DownloadInfo');
goog.require('shaka.offline.DownloadManager');
goog.require('shaka.offline.OfflineUri');
Expand Down Expand Up @@ -271,10 +272,13 @@ shaka.offline.Storage = class {
goog.asserts.assert(
this.networkingEngine_, 'Should not call |store| after |destroy|');

const factory = await shaka.media.ManifestParser.getFactory(
if (!mimeType) {
mimeType = await shaka.net.NetworkingUtils.getMimeType(
uri, this.networkingEngine_, config.manifest.retryParameters);
}

const factory = shaka.media.ManifestParser.getFactory(
uri,
this.networkingEngine_,
config.manifest.retryParameters,
mimeType || null);

return factory();
Expand Down
Loading

0 comments on commit 4425dca

Please sign in to comment.