UNPKG

shaka-player

Version:
309 lines (281 loc) • 9.5 kB
/*! @license * Shaka Player * Copyright 2016 Google LLC * SPDX-License-Identifier: Apache-2.0 */ /** * @fileoverview Externs for the MoQT dialect plugin interface. * * @externs */ /** * A MoQT draft dialect: everything about a draft of the Media over QUIC * Transport specification that differs from the other drafts, gathered behind * one interface. * * A dialect is chosen once, when the session is established, and passed down * from there. Nothing above this layer branches on the draft version, so * supporting a new draft means providing an implementation of this interface * and registering it with shaka.msf.DialectRegistry. * * The interface exists because the differences between drafts run deeper than * message layouts. Draft-17 replaced the variable-length integer encoding * outright, so even reading an integer is draft-specific, and message type IDs * are reassigned between drafts and reused with different meanings, so each * dialect owns its own type constants rather than sharing an enum. * * @interface * @exportDoc */ shaka.extern.MsfDialect = class { /** * The WebTransport subprotocol string that selects this draft, e.g. * 'moqt-18'. * * @return {string} * @exportDoc */ getSubprotocol() {} /** * The draft name, matching the shaka.config.MsfVersion value this dialect is * registered under, e.g. 'draft-18'. * * @return {string} * @exportDoc */ getName() {} /** * The draft number, e.g. 16. Used to order dialects by preference during * negotiation, newest first. * * @return {number} * @exportDoc */ getDraftNumber() {} /** * The primitive codec for this draft, which encodes and decodes the * variable-length integers every other field is built from. * * @return {!shaka.extern.MsfCodec} * @exportDoc */ getCodec() {} /** * Performs this draft's setup handshake over an established WebTransport * connection and returns the resulting session. * * The handshake is part of the dialect because it is not stable across * drafts: draft-16 opens a single bidirectional stream and exchanges * CLIENT_SETUP and SERVER_SETUP over it, while draft-17 collapsed the two * into one SETUP message sent on each of a pair of unidirectional streams. * * @param {!WebTransport} webTransport * @param {!shaka.extern.MsfManifestConfiguration} config * @param {?string=} authorizationToken * @return {!Promise<!shaka.extern.MsfSession>} * @exportDoc */ connect(webTransport, config, authorizationToken) {} }; /** * An established MoQT session. * * This is the boundary between the draft-specific layers and the rest of the * player: it speaks only intent, and hands back objects in the draft-neutral * shaka.extern.MsfObject shape. Nothing above it knows how a request is * addressed, how a response is matched to it, or how object data is framed -- * all of which change between drafts. * * @extends {shaka.util.IReleasable} * @interface * @exportDoc */ shaka.extern.MsfSession = class { /** * Subscribes to a track, delivering its objects to the callback until * unsubscribed. Resolves with the track alias assigned by the publisher. * * @param {Array<string>} namespace * @param {string} trackName * @param {shaka.extern.MsfObjectCallback} callback * @param {?shaka.extern.MsfLocation=} startLocation Where delivery should * begin, for a subscription that is not meant to start at the live edge, * which is what a seek into published-but-not-yet-received content needs. * Every draft carries it, though not alike: draft-18 in the * SUBSCRIPTION_FILTER parameter, draft-20 in LOCATION_FILTER. A publisher * may still refuse it, in which case the subscription fails rather than * silently starting somewhere else. * @param {boolean=} joinCurrentGroup Also deliver the Group the live edge * is in from its first Object, rather than only what comes after the * subscription starts. MSF requires it of the catalog, whose current * state is the first Object of the latest Group plus the ones after it. * Draft-18 does it with a Joining FETCH and draft-20 with FILL_PARAMETERS; * the Objects arrive on the same callback as the subscription's, in * Location order and without repeats. A session that cannot do it, or * whose publisher does not answer in time, delivers only what the * subscription does. * @return {!Promise<bigint>} * @exportDoc */ subscribe(namespace, trackName, callback, startLocation, joinCurrentGroup) {} /** * Stops delivery for a subscription. * * @param {bigint} trackAlias * @return {!Promise} * @exportDoc */ unsubscribe(trackAlias) {} /** * Retrieves a track once rather than subscribing to it. Resolves when the * request has been accepted; objects arrive on the callback. * * @param {Array<string>} namespace * @param {string} trackName * @param {shaka.extern.MsfObjectCallback} callback * @return {!Promise} * @exportDoc */ fetch(namespace, trackName, callback) {} /** * Registers a callback for namespaces the peer announces it can serve. * * @param {function(Array<string>)} callback * @return {function()} Unregisters the callback. * @exportDoc */ onNamespacePublished(callback) {} /** * @param {!shaka.extern.MsfManifestConfiguration} config * @exportDoc */ configure(config) {} /** * Closes the underlying transport. * * @param {number=} code * @param {string=} reason * @return {!Promise} * @exportDoc */ close(code, reason) {} }; /** * An object delivered on a subscription or fetch. * * Defined here rather than borrowed from shaka.msf.Utils because externs are * compiled into every build, including ones that leave the MSF parser out, so * this file cannot depend on lib/msf being present. * * @typedef {{ * trackAlias: bigint, * location: { * group: bigint, * object: bigint, * subgroup: ?(bigint|undefined), * }, * data: !Uint8Array, * extensions: ?(Uint8Array|undefined), * trackProperties: ?(Uint8Array|undefined), * status: ?(bigint|undefined), * payloadReadStartMs: number, * receiveTimestampMs: number, * }} * * @property {?(Uint8Array|undefined)} extensions * The Object Properties block, without its length prefix, or null when the * Object carries none. * @property {?(Uint8Array|undefined)} trackProperties * The Track Properties block of the SUBSCRIBE_OK or FETCH_OK that answered * the request this Object was delivered on, or null when there were none. * Sessions for drafts that have no Track Properties leave it unset. * @exportDoc */ shaka.extern.MsfObject; /** * Where an Object sits in a track: the MoQT Location, a Group ID and an * Object ID within that Group. * * Defined here for the same reason as shaka.extern.MsfObject: it is part of * the dialect plugin contract, and externs are compiled into every build, * including the ones that leave the MSF parser out. * * @typedef {{ * group: bigint, * object: bigint, * subgroup: ?(bigint|undefined), * }} * @exportDoc */ shaka.extern.MsfLocation; /** * @typedef {function(shaka.extern.MsfObject)} * @exportDoc */ shaka.extern.MsfObjectCallback; /** * A factory for creating a MoQT dialect. This function is registered with * shaka.msf.DialectRegistry to create dialect instances. * * @typedef {function():!shaka.extern.MsfDialect} * @exportDoc */ shaka.extern.MsfDialect.Factory; /** * Encodes and decodes the primitive types a MoQT draft is built from. * * This is the lowest layer of the dialect stack. It exists separately because * the variable-length integer encoding is not stable across drafts: draft-16 * and earlier use the QUIC (RFC 9000) encoding, where the two most significant * bits of the first byte give a length of 1, 2, 4 or 8 bytes, while draft-17 * replaced it with a leading-ones-count encoding of 1 to 9 bytes. Every integer * on the wire is affected, so the codec has to be selected per draft rather * than assumed. * * Implementations are stateless and operate on a caller-supplied byte sink or * slice, which keeps them usable from both the buffered stream reader and the * message writers. * * @interface * @exportDoc */ shaka.extern.MsfCodec = class { /** * Returns the total length in bytes of the variable-length integer that * starts with the given byte, so a reader knows how much to buffer before * decoding. * * @param {number} firstByte * @return {number} * @exportDoc */ varIntLength(firstByte) {} /** * Decodes a variable-length integer from a slice holding exactly the bytes * of one encoded value, as reported by varIntLength(). * * @param {!Uint8Array} bytes * @return {bigint} * @exportDoc */ decodeVarInt(bytes) {} /** * Decodes the variable-length integer starting at the given offset within a * larger buffer, reporting how many bytes it consumed so the caller can * continue. * * @param {!Uint8Array} bytes * @param {number} offset * @return {!{value: bigint, bytesRead: number}} * @exportDoc */ decodeVarIntAt(bytes, offset) {} /** * Appends a variable-length integer to the writer. * * @param {!shaka.util.DataViewWriter} writer * @param {bigint} value * @exportDoc */ encodeVarInt(writer, value) {} };