|
|
@ -1,3 +1,10 @@ |
|
|
|
/** |
|
|
|
* Utilities for parsing M3U8 files. If the entire manifest is available, |
|
|
|
* `Parser` will create a object representation with enough detail for managing |
|
|
|
* playback. `ParseStream` and `LineStream` are lower-level parsing primitives |
|
|
|
* that do not assume the entirety of the manifest is ready and expose a |
|
|
|
* ReadableStream-like interface. |
|
|
|
*/ |
|
|
|
(function(videojs, parseInt, isFinite, mergeOptions, undefined) { |
|
|
|
var |
|
|
|
noop = function() {}, |
|
|
@ -18,10 +25,18 @@ |
|
|
|
ParseStream, |
|
|
|
Parser; |
|
|
|
|
|
|
|
/** |
|
|
|
* A stream that buffers string input and generates a `data` event for each |
|
|
|
* line. |
|
|
|
*/ |
|
|
|
LineStream = function() { |
|
|
|
var buffer = ''; |
|
|
|
LineStream.prototype.init.call(this); |
|
|
|
|
|
|
|
/** |
|
|
|
* Add new data to be parsed. |
|
|
|
* @param data {string} the text to process |
|
|
|
*/ |
|
|
|
this.push = function(data) { |
|
|
|
var nextNewline; |
|
|
|
|
|
|
@ -36,10 +51,35 @@ |
|
|
|
}; |
|
|
|
LineStream.prototype = new Stream(); |
|
|
|
|
|
|
|
/** |
|
|
|
* A line-level M3U8 parser event stream. It expects to receive input one |
|
|
|
* line at a time and performs a context-free parse of its contents. A stream |
|
|
|
* interpretation of a manifest can be useful if the manifest is expected to |
|
|
|
* be too large to fit comfortably into memory or the entirety of the input |
|
|
|
* is not immediately available. Otherwise, it's probably much easier to work |
|
|
|
* with a regular `Parser` object. |
|
|
|
* |
|
|
|
* Produces `data` events with an object that captures the parser's |
|
|
|
* interpretation of the input. That object has a property `tag` that is one |
|
|
|
* of `uri`, `comment`, or `tag`. URIs only have a single additional |
|
|
|
* property, `line`, which captures the entirety of the input without |
|
|
|
* interpretation. Comments similarly have a single additional property |
|
|
|
* `text` which is the input without the leading `#`. |
|
|
|
* |
|
|
|
* Tags always have a property `tagType` which is the lower-cased version of |
|
|
|
* the M3U8 directive without the `#EXT` or `#EXT-X-` prefix. For instance, |
|
|
|
* `#EXT-X-MEDIA-SEQUENCE` becomes `media-sequence` when parsed. Unrecognized |
|
|
|
* tags are given the tag type `unknown` and a single additional property |
|
|
|
* `data` with the remainder of the input. |
|
|
|
*/ |
|
|
|
ParseStream = function() { |
|
|
|
ParseStream.prototype.init.call(this); |
|
|
|
}; |
|
|
|
ParseStream.prototype = new Stream(); |
|
|
|
/** |
|
|
|
* Parses an additional line of input. |
|
|
|
* @param line {string} a single line of an M3U8 file to parse |
|
|
|
*/ |
|
|
|
ParseStream.prototype.push = function(line) { |
|
|
|
var match, event; |
|
|
|
if (line.length === 0) { |
|
|
@ -213,6 +253,24 @@ |
|
|
|
}); |
|
|
|
}; |
|
|
|
|
|
|
|
/** |
|
|
|
* A parser for M3U8 files. The current interpretation of the input is |
|
|
|
* exposed as a property `manifest` on parser objects. It's just two lines to |
|
|
|
* create and parse a manifest once you have the contents available as a string: |
|
|
|
* |
|
|
|
* ```js
|
|
|
|
* var parser = new videojs.m3u8.Parser(); |
|
|
|
* parser.push(xhr.responseText); |
|
|
|
* ```
|
|
|
|
* |
|
|
|
* New input can later be applied to update the manifest object by calling |
|
|
|
* `push` again. |
|
|
|
* |
|
|
|
* The parser attempts to create a usable manifest object even if the |
|
|
|
* underlying input is somewhat nonsensical. It emits `info` and `warning` |
|
|
|
* events during the parse if it encounters input that seems invalid or |
|
|
|
* requires some property of the manifest object to be defaulted. |
|
|
|
*/ |
|
|
|
Parser = function() { |
|
|
|
var |
|
|
|
self = this, |
|
|
@ -331,9 +389,18 @@ |
|
|
|
}); |
|
|
|
}; |
|
|
|
Parser.prototype = new Stream(); |
|
|
|
/** |
|
|
|
* Parse the input string and update the manifest object. |
|
|
|
* @param chunk {string} a potentially incomplete portion of the manifest |
|
|
|
*/ |
|
|
|
Parser.prototype.push = function(chunk) { |
|
|
|
this.lineStream.push(chunk); |
|
|
|
}; |
|
|
|
/** |
|
|
|
* Flush any remaining input. This can be handy if the last line of an M3U8 |
|
|
|
* manifest did not contain a trailing newline but the file has been |
|
|
|
* completely received. |
|
|
|
*/ |
|
|
|
Parser.prototype.end = function() { |
|
|
|
// flush any buffered input
|
|
|
|
this.lineStream.push('\n'); |
|
|
|