mirror of
https://github.com/DanielnetoDotCom/YouPHPTube
synced 2025-10-04 10:19:24 +02:00
This commit is contained in:
parent
746e163d01
commit
1c7ea28b46
808 changed files with 316395 additions and 381162 deletions
15
node_modules/@videojs/http-streaming/docs/README.md
generated
vendored
15
node_modules/@videojs/http-streaming/docs/README.md
generated
vendored
|
@ -1,3 +1,14 @@
|
|||
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
||||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
||||
|
||||
- [Overview](#overview)
|
||||
- [HTTP Live Streaming](#http-live-streaming)
|
||||
- [Dynamic Adaptive Streaming over HTTP](#dynamic-adaptive-streaming-over-http)
|
||||
- [Further Documentation](#further-documentation)
|
||||
- [Helpful Tools](#helpful-tools)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
|
||||
# Overview
|
||||
This project supports both [HLS][hls] and [MPEG-DASH][dash] playback in the video.js player. This document is intended as a primer for anyone interested in contributing or just better understanding how bits from a server get turned into video on their display.
|
||||
|
||||
|
@ -7,11 +18,11 @@ This project supports both [HLS][hls] and [MPEG-DASH][dash] playback in the vide
|
|||
- Delivered over HTTP(S): it uses the standard application protocol of the web to deliver all its data
|
||||
- Segmented: longer videos are broken up into smaller chunks which can be downloaded independently and switched between at runtime
|
||||
|
||||
A standard HLS stream consists of a *Master Playlist* which references one or more *Media Playlists*. Each Media Playlist contains one or more sequential video segments. All these components form a logical hierarchy that informs the player of the different quality levels of the video available and how to address the individual segments of video at each of those levels:
|
||||
A standard HLS stream consists of a *Main Playlist* which references one or more *Media Playlists*. Each Media Playlist contains one or more sequential video segments. All these components form a logical hierarchy that informs the player of the different quality levels of the video available and how to address the individual segments of video at each of those levels:
|
||||
|
||||

|
||||
|
||||
HLS streams can be delivered in two different modes: a "static" mode for videos that can be played back from any point, often referred to as video-on-demand (VOD); or a "live" mode where later portions of the video become available as time goes by. In the static mode, the Master and Media playlists are fixed. The player is guaranteed that the set of video segments referenced by those playlists will not change over time.
|
||||
HLS streams can be delivered in two different modes: a "static" mode for videos that can be played back from any point, often referred to as video-on-demand (VOD); or a "live" mode where later portions of the video become available as time goes by. In the static mode, the Main and Media playlists are fixed. The player is guaranteed that the set of video segments referenced by those playlists will not change over time.
|
||||
|
||||
Live mode can work in one of two ways. For truly live events, the most common configuration is for each individual Media Playlist to only include the latest video segment and a small number of consecutive previous segments. In this mode, the player may be able to seek backwards a short time in the video but probably not all the way back to the beginning. In the other live configuration, new video segments can be appended to the Media Playlists but older segments are never removed. This configuration allows the player to seek back to the beginning of the stream at any time during the broadcast and transitions seamlessly to the static stream type when the event finishes.
|
||||
|
||||
|
|
84
node_modules/@videojs/http-streaming/docs/a-walk-through-vhs.md
generated
vendored
84
node_modules/@videojs/http-streaming/docs/a-walk-through-vhs.md
generated
vendored
|
@ -58,25 +58,23 @@ flowchart TD
|
|||
> * most EME handling for DRM and setup of the [videojs-contrib-eme plugin](https://github.com/videojs/videojs-contrib-eme)
|
||||
> * mapping/handling of options passed down via Video.js
|
||||
|
||||
## MasterPlaylistController
|
||||
## PlaylistController
|
||||
|
||||
One critical object that `VhsHandler`'s constructor creates is a new `MasterPlaylistController`.
|
||||
One critical object that `VhsHandler`'s constructor creates is a new `PlaylistController`.
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
VhsSourceHandler --> VhsHandler
|
||||
VhsHandler --> MasterPlaylistController
|
||||
VhsHandler --> PlaylistController
|
||||
```
|
||||
|
||||
`MasterPlaylistController` is not a great name, and has grown in size to be a bit unwieldy, but it's the hub of VHS. Eventually, it should be broken into smaller pieces, but for now, it handles the creation and management of most of the other VHS modules. Its code can be found in [src/master-playlist-controller.js](https://github.com/videojs/http-streaming/blob/0964cb4827d9e80aa36f2fa29e35dad92ca84111/src/master-playlist-controller.js).
|
||||
`PlaylistController` is not a great name, and has grown in size to be a bit unwieldy, but it's the hub of VHS. Eventually, it should be broken into smaller pieces, but for now, it handles the creation and management of most of the other VHS modules. Its code can be found in [src/playlist-controller.js](/src/playlist-controller.js).
|
||||
|
||||
The best way to think of `MasterPlaylistController` is as Tron's Master Control Program, though hopefully it isn't as evil.
|
||||
`PlaylistController` is a lot to say. So we often refer to it as PC.
|
||||
|
||||
`MasterPlaylistController` is a lot to say. So we often refer to it as MPC.
|
||||
If you need to find a place where different modules communicate, you will probably end up in PC. Just about all of `VhsHandler` that doesn't interface with Video.js or other plugins, interfaces with PC.
|
||||
|
||||
If you need to find a place where different modules communicate, you will probably end up in MPC. Just about all of `VhsHandler` that doesn't interface with Video.js or other plugins, interfaces with MPC.
|
||||
|
||||
MPC's [constructor](https://github.com/videojs/http-streaming/blob/0964cb4827d9e80aa36f2fa29e35dad92ca84111/src/master-playlist-controller.js#L148) does a lot. Instead of listing all of the things it does, let's go step-by-step through the main ones, passing the source we had above.
|
||||
PC's [constructor](/src/playlist-controller.js#L148) does a lot. Instead of listing all of the things it does, let's go step-by-step through the main ones, passing the source we had above.
|
||||
|
||||
```html
|
||||
<video-js id="myPlayer" class="video-js" data-setup='{}'>
|
||||
|
@ -84,18 +82,18 @@ MPC's [constructor](https://github.com/videojs/http-streaming/blob/0964cb4827d9e
|
|||
</video-js>
|
||||
```
|
||||
|
||||
Looking at the `<source>` tag, `VhsSourceHandler` already used the "type" to tell Video.js that it could handle the source. `VhsHandler` took the manifest URL, in this case "manifest.m3u8" and provided it to the constructor of MPC.
|
||||
Looking at the `<source>` tag, `VhsSourceHandler` already used the "type" to tell Video.js that it could handle the source. `VhsHandler` took the manifest URL, in this case "manifest.m3u8" and provided it to the constructor of PC.
|
||||
|
||||
The first thing that MPC must do is download that source, but it doesn't make the request itself. Instead, it creates [this.masterPlaylistLoader_](https://github.com/videojs/http-streaming/blob/0964cb4827d9e80aa36f2fa29e35dad92ca84111/src/master-playlist-controller.js#L264-L266).
|
||||
The first thing that PC must do is download that source, but it doesn't make the request itself. Instead, it creates [this.mainPlaylistLoader_](/src/laylist-controller.js#L263-L265).
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
VhsSourceHandler --> VhsHandler
|
||||
VhsHandler --> MasterPlaylistController
|
||||
MasterPlaylistController --> PlaylistLoader
|
||||
VhsHandler --> PlaylistController
|
||||
PlaylistController --> PlaylistLoader
|
||||
```
|
||||
|
||||
`masterPlaylistLoader_` is an instance of either the [HLS PlaylistLoader](https://github.com/videojs/http-streaming/blob/0964cb4827d9e80aa36f2fa29e35dad92ca84111/src/playlist-loader.js#L379) or the [DashPlaylistLoader](https://github.com/videojs/http-streaming/blob/0964cb4827d9e80aa36f2fa29e35dad92ca84111/src/dash-playlist-loader.js#L259).
|
||||
`mainPlaylistLoader_` is an instance of either the [HLS PlaylistLoader](/src/playlist-loader.js#L379) or the [DashPlaylistLoader](/src/dash-playlist-loader.js#L259).
|
||||
|
||||
The names betray their use. They load the playlist. The URL ("manifest.m3u8" here) is given, and the manifest/playlist is downloaded and parsed. If the content is live, the playlist loader also handles refreshing the manifest. For HLS, where manifests point to other manifests, the playlist loader requests those as well.
|
||||
|
||||
|
@ -117,9 +115,9 @@ Manifest {
|
|||
}
|
||||
```
|
||||
|
||||
Many properties are removed for simplicity. This is a top level manifest (often referred to as a master or main manifest), and within it there are playlists, each playlist being a Manifest itself. Since the JSON "schema" for main and media playlists is the same, you will see irrelevant properties within any given manifest object. For instance, you might see a `targetDuration` property on the main manifest object, though a main manifest doesn't have a target duration. You can ignore irrelevant properties. Eventually they should be cleaned up, and a proper schema defined for manifest objects.
|
||||
Many properties are removed for simplicity. This is a top level manifest (often referred to as a main manifest or a multivariant manifest [from the HLS spec]), and within it there are playlists, each playlist being a Manifest itself. Since the JSON "schema" for main and media playlists is the same, you will see irrelevant properties within any given manifest object. For instance, you might see a `targetDuration` property on the main manifest object, though a main manifest doesn't have a target duration. You can ignore irrelevant properties. Eventually they should be cleaned up, and a proper schema defined for manifest objects.
|
||||
|
||||
MPC will also use `masterPlaylistLoader_` to select which media playlist is active (e.g., the 720p rendition or the 480p rendition), so that `masterPlaylistLoader_` will only need to refresh that individual playlist if the stream is live.
|
||||
PC will also use `mainPlaylistLoader_` to select which media playlist is active (e.g., the 720p rendition or the 480p rendition), so that `mainPlaylistLoader_` will only need to refresh that individual playlist if the stream is live.
|
||||
|
||||
> :information_source: **Future Work**
|
||||
>
|
||||
|
@ -129,26 +127,26 @@ MPC will also use `masterPlaylistLoader_` to select which media playlist is acti
|
|||
|
||||
### Media Source Extensions
|
||||
|
||||
The next thing MPC needs to do is set up a media source for [Media Source Extensions](https://www.w3.org/TR/media-source/). Specifically, it needs to create [this.mediaSource](https://github.com/videojs/http-streaming/blob/0964cb4827d9e80aa36f2fa29e35dad92ca84111/src/master-playlist-controller.js#L210) and its associated [source buffers](https://github.com/videojs/http-streaming/blob/main/src/master-playlist-controller.js#L1818). These are where audio and video data will be appended, so that the browser has content to play. But those aren't used directly. Because source buffers can only handle one operation at a time, [this.sourceUpdater_](https://github.com/videojs/http-streaming/blob/0964cb4827d9e80aa36f2fa29e35dad92ca84111/src/master-playlist-controller.js#L234) is created. `sourceUpdater_` is a queue for operations performed on the source buffers. That's pretty much it. So all of the MSE pieces for appending get wrapped up in `sourceUpdater_`.
|
||||
The next thing PC needs to do is set up a media source for [Media Source Extensions](https://www.w3.org/TR/media-source/). Specifically, it needs to create [this.mediaSource](/src/playlist-controller.js#L208) and its associated [source buffers](/src/playlist-controller.js#L1814). These are where audio and video data will be appended, so that the browser has content to play. But those aren't used directly. Because source buffers can only handle one operation at a time, [this.sourceUpdater_](/src/playlist-controller.js#L232) is created. `sourceUpdater_` is a queue for operations performed on the source buffers. That's pretty much it. So all of the MSE pieces for appending get wrapped up in `sourceUpdater_`.
|
||||
|
||||
## Segment Loaders
|
||||
|
||||
The SourceUpdater created for MSE above is passed to the segment loaders.
|
||||
|
||||
[this.mainSegmentLoader_](https://github.com/videojs/http-streaming/blob/0964cb4827d9e80aa36f2fa29e35dad92ca84111/src/master-playlist-controller.js#L271-L275) is used for muxed content (audio and video in one segment) and for audio or video only streams.
|
||||
[this.mainSegmentLoader_](/src/playlist-controller.js#L270-L274) is used for muxed content (audio and video in one segment) and for audio or video only streams.
|
||||
|
||||
[this.audioSegmentLoader_](https://github.com/videojs/http-streaming/blob/0964cb4827d9e80aa36f2fa29e35dad92ca84111/src/master-playlist-controller.js#L278-L281) is used when the content is demuxed (audio and video in separate playlists).
|
||||
[this.audioSegmentLoader_](/src/playlist-controller.js#L277-L280) is used when the content is demuxed (audio and video in separate playlists).
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
VhsSourceHandler --> VhsHandler
|
||||
VhsHandler --> MasterPlaylistController
|
||||
MasterPlaylistController --> PlaylistLoader
|
||||
MasterPlaylistController --> SourceUpdater
|
||||
MasterPlaylistController --> SegmentLoader
|
||||
VhsHandler --> PlaylistController
|
||||
PlaylistController --> PlaylistLoader
|
||||
PlaylistController --> SourceUpdater
|
||||
PlaylistController --> SegmentLoader
|
||||
```
|
||||
|
||||
Besides options and the `sourceUpdater_` from MPC, the segment loaders are given a [playlist](https://github.com/videojs/http-streaming/blob/0964cb4827d9e80aa36f2fa29e35dad92ca84111/src/segment-loader.js#L988). This playlist is a media playlist from the `masterPlaylistLoader_`. So looking back at our parsed manifest object:
|
||||
Besides options and the `sourceUpdater_` from PC, the segment loaders are given a [playlist](https://github.com/videojs/http-streaming/blob/0964cb4827d9e80aa36f2fa29e35dad92ca84111/src/segment-loader.js#L988). This playlist is a media playlist from the `mainPlaylistLoader_`. So looking back at our parsed manifest object:
|
||||
|
||||
```
|
||||
Manifest {
|
||||
|
@ -174,19 +172,19 @@ VHS uses a strategy called `mediaIndex++` for choosing the next segment, see [he
|
|||
|
||||
If there are no seeks or rendition changes, `chooseNextRequest_` will rely on the `mediaIndex++` strategy.
|
||||
|
||||
If there are seeks or rendition changes, then `chooseNextRequest_` will look at segment timing values via the `SyncController` (created previously in MPC), the current time, and the buffer, to determine what the next segment should be, and what it's start time should be (to position it on the timeline).
|
||||
If there are seeks or rendition changes, then `chooseNextRequest_` will look at segment timing values via the `SyncController` (created previously in PC), the current time, and the buffer, to determine what the next segment should be, and what it's start time should be (to position it on the timeline).
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
VhsSourceHandler --> VhsHandler
|
||||
VhsHandler --> MasterPlaylistController
|
||||
MasterPlaylistController --> PlaylistLoader
|
||||
MasterPlaylistController --> SourceUpdater
|
||||
MasterPlaylistController --> SegmentLoader
|
||||
VhsHandler --> PlaylistController
|
||||
PlaylistController --> PlaylistLoader
|
||||
PlaylistController --> SourceUpdater
|
||||
PlaylistController --> SegmentLoader
|
||||
SegmentLoader --> SyncController
|
||||
```
|
||||
|
||||
The `SyncController` has various [strategies](https://github.com/videojs/http-streaming/blob/0964cb4827d9e80aa36f2fa29e35dad92ca84111/src/sync-controller.js#L16) for ensuring that different renditions, which can have different media sequence and segment timing values, can be positioned on the playback timeline successfully. (It is also be [used by MPC](https://github.com/videojs/http-streaming/blob/0964cb4827d9e80aa36f2fa29e35dad92ca84111/src/master-playlist-controller.js#L1477) to establish a `seekable` range.)
|
||||
The `SyncController` has various [strategies](https://github.com/videojs/http-streaming/blob/0964cb4827d9e80aa36f2fa29e35dad92ca84111/src/sync-controller.js#L16) for ensuring that different renditions, which can have different media sequence and segment timing values, can be positioned on the playback timeline successfully. (It is also be [used by PC](/src/playlist-controller.js#L1472) to establish a `seekable` range.)
|
||||
|
||||
### Downloading and Appending Segments
|
||||
|
||||
|
@ -196,10 +194,10 @@ If the buffer is not full, and a segment was chosen, then `SegmentLoader` will d
|
|||
```mermaid
|
||||
flowchart TD
|
||||
VhsSourceHandler --> VhsHandler
|
||||
VhsHandler --> MasterPlaylistController
|
||||
MasterPlaylistController --> PlaylistLoader
|
||||
MasterPlaylistController --> SourceUpdater
|
||||
MasterPlaylistController --> SegmentLoader
|
||||
VhsHandler --> PlaylistController
|
||||
PlaylistController --> PlaylistLoader
|
||||
PlaylistController --> SourceUpdater
|
||||
PlaylistController --> SegmentLoader
|
||||
SegmentLoader --> SyncController
|
||||
SegmentLoader --> mediaSegmentRequest
|
||||
```
|
||||
|
@ -213,10 +211,10 @@ When the `SegmentLoader` receives segment data events, it can append the data to
|
|||
```mermaid
|
||||
flowchart TD
|
||||
VhsSourceHandler --> VhsHandler
|
||||
VhsHandler --> MasterPlaylistController
|
||||
MasterPlaylistController --> PlaylistLoader
|
||||
MasterPlaylistController --> SourceUpdater
|
||||
MasterPlaylistController --> SegmentLoader
|
||||
VhsHandler --> PlaylistController
|
||||
PlaylistController --> PlaylistLoader
|
||||
PlaylistController --> SourceUpdater
|
||||
PlaylistController --> SegmentLoader
|
||||
SegmentLoader --> SyncController
|
||||
SegmentLoader --> mediaSegmentRequest
|
||||
SegmentLoader --> SourceUpdater
|
||||
|
@ -231,10 +229,10 @@ Besides downloading segments, `mediaSegmentRequest` [decrypts](https://github.co
|
|||
```mermaid
|
||||
flowchart TD
|
||||
VhsSourceHandler --> VhsHandler
|
||||
VhsHandler --> MasterPlaylistController
|
||||
MasterPlaylistController --> PlaylistLoader
|
||||
MasterPlaylistController --> SourceUpdater
|
||||
MasterPlaylistController --> SegmentLoader
|
||||
VhsHandler --> PlaylistController
|
||||
PlaylistController --> PlaylistLoader
|
||||
PlaylistController --> SourceUpdater
|
||||
PlaylistController --> SegmentLoader
|
||||
SegmentLoader --> SyncController
|
||||
SegmentLoader --> mediaSegmentRequest
|
||||
SegmentLoader --> SourceUpdater
|
||||
|
@ -247,4 +245,4 @@ The video can start playing as soon as there's enough audio and video (for muxed
|
|||
|
||||
But once `SegmentLoader` does finish, it starts the process again, looking for new content.
|
||||
|
||||
There are other modules, and other functions of the code (e.g., blacklisting logic, ABR, etc.), but this is the most critical path of VHS, the one that allows video to play in the browser.
|
||||
There are other modules, and other functions of the code (e.g., excluding logic, ABR, etc.), but this is the most critical path of VHS, the one that allows video to play in the browser.
|
||||
|
|
2
node_modules/@videojs/http-streaming/docs/arch.md
generated
vendored
2
node_modules/@videojs/http-streaming/docs/arch.md
generated
vendored
|
@ -13,7 +13,7 @@ The [playlist loader](../src/playlist-loader.js) handles all of the details of r
|
|||
During VOD playback, the loader will move quickly to the HAVE_METADATA state and then stay there unless a quality switch request sends it to SWITCHING_MEDIA while it fetches an alternate playlist. The loader enters the HAVE_CURRENT_METADATA when a live stream is detected and it's time to refresh the current media playlist to find out about new video segments.
|
||||
|
||||
### HLS Tech
|
||||
Currently, the HLS project integrates with [video.js](http://www.videojs.com/) as a [tech](https://github.com/videojs/video.js/blob/master/docs/guides/tech.md). That means it's responsible for providing an interface that closely mirrors the `<video>` element. You can see that implementation in [videojs-http-streaming.js](../src/videojs-http-streaming.js), the primary entry point of the project.
|
||||
Currently, the HLS project integrates with [video.js](http://www.videojs.com/) as a [tech](https://github.com/videojs/video.js/blob/main/docs/guides/tech.md). That means it's responsible for providing an interface that closely mirrors the `<video>` element. You can see that implementation in [videojs-http-streaming.js](../src/videojs-http-streaming.js), the primary entry point of the project.
|
||||
|
||||
### Transmuxing
|
||||
Most browsers don't have support for the file type that HLS video segments are stored in. To get HLS playing back on those browsers, contrib-hls strings together a number of technologies:
|
||||
|
|
2
node_modules/@videojs/http-streaming/docs/bitrate-switching.md
generated
vendored
2
node_modules/@videojs/http-streaming/docs/bitrate-switching.md
generated
vendored
|
@ -34,7 +34,7 @@ gets used:
|
|||

|
||||
|
||||
If it turns out no rendition is acceptable based on the filtering
|
||||
described above, the first encoding listed in the master playlist will
|
||||
described above, the first encoding listed in the main playlist will
|
||||
be used.
|
||||
|
||||
If you'd like your player to use a different set of priorities, it's
|
||||
|
|
20
node_modules/@videojs/http-streaming/docs/dash-playlist-loader.md
generated
vendored
20
node_modules/@videojs/http-streaming/docs/dash-playlist-loader.md
generated
vendored
|
@ -22,19 +22,19 @@ The [DPL] is written to be as similar as possible to the [PlaylistLoader][pl]. T
|
|||

|
||||
|
||||
- `HAVE_NOTHING` the state before the MPD is received and parsed.
|
||||
- `HAVE_MASTER` the state before a media stream is setup but the MPD has been parsed.
|
||||
- `HAVE_MAIN_MANIFEST` the state before a media stream is setup but the MPD has been parsed.
|
||||
- `HAVE_METADATA` the state after a media stream is setup.
|
||||
|
||||
### API
|
||||
|
||||
- `load()` this will either start or kick the loader during playback.
|
||||
- `start()` this will start the [DPL] and request the MPD.
|
||||
- `parseMasterXml()` this will parse the MPD manifest and return the result.
|
||||
- `parseMainXml()` this will parse the MPD manifest and return the result.
|
||||
- `media()` this will return the currently active media stream or set a new active media stream.
|
||||
|
||||
### Events
|
||||
|
||||
- `loadedplaylist` signals the setup of a master playlist, representing the DASH source as a whole, from the MPD; or a media playlist, representing a media stream.
|
||||
- `loadedplaylist` signals the setup of a main playlist, representing the DASH source as a whole, from the MPD; or a media playlist, representing a media stream.
|
||||
- `loadedmetadata` signals initial setup of a media stream.
|
||||
- `minimumUpdatePeriod` signals that a update period has ended and the MPD must be requested again.
|
||||
- `playlistunchanged` signals that no changes have been made to a MPD.
|
||||
|
@ -44,7 +44,7 @@ The [DPL] is written to be as similar as possible to the [PlaylistLoader][pl]. T
|
|||
|
||||
### Interaction with Other Modules
|
||||
|
||||

|
||||

|
||||
|
||||
### Special Features
|
||||
|
||||
|
@ -64,17 +64,17 @@ To be filled out.
|
|||
|
||||
### Previous Behavior
|
||||
|
||||
Until version 1.9.0 of [VHS], we thought that [DPL] could skip the `HAVE_NOTHING` and `HAVE_MASTER` states, as no other XHR requests are needed once the MPD has been downloaded and parsed. However, this is incorrect as there are some Presentations that signal the use of a "Segment Index box" or `sidx`. This `sidx` references specific byte ranges in a file that could contain media or potentially other `sidx` boxes.
|
||||
Until version 1.9.0 of [VHS], we thought that [DPL] could skip the `HAVE_NOTHING` and `HAVE_MAIN_MANIFEST` states, as no other XHR requests are needed once the MPD has been downloaded and parsed. However, this is incorrect as there are some Presentations that signal the use of a "Segment Index box" or `sidx`. This `sidx` references specific byte ranges in a file that could contain media or potentially other `sidx` boxes.
|
||||
|
||||
A DASH MPD that describes a `sidx` is therefore similar to an HLS master manifest, in that the MPD contains references to something that must be requested and parsed first before references to media segments can be obtained. With this in mind, it was necessary to update the initialization and state transitions of [DPL] to allow further XHR requests to be made after the initial request for the MPD.
|
||||
A DASH MPD that describes a `sidx` is therefore similar to an HLS main manifest, in that the MPD contains references to something that must be requested and parsed first before references to media segments can be obtained. With this in mind, it was necessary to update the initialization and state transitions of [DPL] to allow further XHR requests to be made after the initial request for the MPD.
|
||||
|
||||
### Current Behavior
|
||||
|
||||
In [this PR](https://github.com/videojs/http-streaming/pull/386), the [DPL] was updated to go through the `HAVE_NOTHING` and `HAVE_MASTER` states before arriving at `HAVE_METADATA`. If the MPD does not contain `sidx` boxes, then this transition happens quickly after `load()` is called, spending little time in the `HAVE_MASTER` state.
|
||||
In [this PR](https://github.com/videojs/http-streaming/pull/386), the [DPL] was updated to go through the `HAVE_NOTHING` and `HAVE_MAIN_MANIFEST` states before arriving at `HAVE_METADATA`. If the MPD does not contain `sidx` boxes, then this transition happens quickly after `load()` is called, spending little time in the `HAVE_MAIN_MANIFEST` state.
|
||||
|
||||
The initial media selection for `masterPlaylistLoader` is made in the `loadedplaylist` handler located in [MasterPlaylistController][mpc]. We now use `hasPendingRequest` to determine whether to automatically select a media playlist for the `masterPlaylistLoader` as a fallback in case one is not selected by [MPC]. The child [DPL]s are created with a media playlist passed in as an argument, so this fallback is not necessary for them. Instead, that media playlist is saved and auto-selected once we enter the `HAVE_MASTER` state.
|
||||
The initial media selection for `mainPlaylistLoader` is made in the `loadedplaylist` handler located in [PlaylistController][pc]. We now use `hasPendingRequest` to determine whether to automatically select a media playlist for the `mainPlaylistLoader` as a fallback in case one is not selected by [PC]. The child [DPL]s are created with a media playlist passed in as an argument, so this fallback is not necessary for them. Instead, that media playlist is saved and auto-selected once we enter the `HAVE_MAIN_MANIFEST` state.
|
||||
|
||||
The `updateMaster` method will return `null` if no updates are found.
|
||||
The `updateMain` method will return `null` if no updates are found.
|
||||
|
||||
The `selectinitialmedia` event is not triggered until an audioPlaylistLoader (which for DASH is always a child [DPL]) has a media playlist. This is signaled by triggering `loadedmetadata` on the respective [DPL]. This event is used to initialize the [Representations API][representations] and setup EME (see [contrib-eme]).
|
||||
|
||||
|
@ -82,6 +82,6 @@ The `selectinitialmedia` event is not triggered until an audioPlaylistLoader (wh
|
|||
[sl]: ../src/segment-loader.js
|
||||
[vhs]: intro.md
|
||||
[pl]: ../src/playlist-loader.js
|
||||
[mpc]: ../src/master-playlist-controller.js
|
||||
[pc]: ../src/playlist-controller.js
|
||||
[representations]: ../README.md#hlsrepresentations
|
||||
[contrib-eme]: https://github.com/videojs/videojs-contrib-eme
|
||||
|
|
4
node_modules/@videojs/http-streaming/docs/glossary.md
generated
vendored
4
node_modules/@videojs/http-streaming/docs/glossary.md
generated
vendored
|
@ -4,9 +4,9 @@
|
|||
|
||||
**Media Playlist**: This is a manifest that represents a single rendition or media stream of the source.
|
||||
|
||||
**Master Playlist Controller**: This acts as the main controller for the playback engine. It interacts with the SegmentLoaders, PlaylistLoaders, PlaybackWatcher, etc.
|
||||
**Playlist Controller**: This acts as the main controller for the playback engine. It interacts with the SegmentLoaders, PlaylistLoaders, PlaybackWatcher, etc.
|
||||
|
||||
**Playlist Loader**: This will request the source and load the master manifest. It is also instructed by the ABR algorithm to load a media playlist or wraps a media playlist if it is provided as the source. There are more details about the playlist loader [here](./arch.md).
|
||||
**Playlist Loader**: This will request the source and load the main manifest. It is also instructed by the ABR algorithm to load a media playlist or wraps a media playlist if it is provided as the source. There are more details about the playlist loader [here](./arch.md).
|
||||
|
||||
**DASH Playlist Loader**: This will do as the PlaylistLoader does, but for DASH sources. It also handles DASH specific functionaltiy, such as refreshing the MPD according to the minimumRefreshPeriod and synchronizing to a server clock.
|
||||
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 169 KiB |
24
node_modules/@videojs/http-streaming/docs/images/dash-playlist-loader-states.nomnoml.svg
generated
vendored
24
node_modules/@videojs/http-streaming/docs/images/dash-playlist-loader-states.nomnoml.svg
generated
vendored
|
@ -1,12 +1,12 @@
|
|||
<svg width="228" height="310" version="1.1" baseProfile="full" viewbox="0 0 228 310" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events" style="font-weight:bold; font-size:10pt; font-family:'Arial', Helvetica, sans-serif;;stroke-width:2;stroke-linejoin:round;stroke-linecap:round"><text x="134" y="111" style="font-weight:normal;">load()</text>
|
||||
<path d="M114 81 L114 105 L114 129 L114 129 " style="stroke:#33322E;fill:none;stroke-dasharray:none;"></path>
|
||||
<path d="M110.8 121 L114 125 L117.2 121 L114 129 Z" style="stroke:#33322E;fill:#33322E;stroke-dasharray:none;"></path>
|
||||
<text x="134" y="211" style="font-weight:normal;">media()</text>
|
||||
<path d="M114 181 L114 205 L114 229 L114 229 " style="stroke:#33322E;fill:none;stroke-dasharray:none;"></path>
|
||||
<path d="M110.8 221 L114 225 L117.2 221 L114 229 Z" style="stroke:#33322E;fill:#33322E;stroke-dasharray:none;"></path>
|
||||
<rect x="37" y="30" height="50" width="154" style="stroke:#33322E;fill:#eee8d5;stroke-dasharray:none;"></rect>
|
||||
<text x="57" y="60" style="">HAVE_NOTHING</text>
|
||||
<rect x="40" y="130" height="50" width="149" style="stroke:#33322E;fill:#eee8d5;stroke-dasharray:none;"></rect>
|
||||
<text x="60" y="160" style="">HAVE_MASTER</text>
|
||||
<rect x="30" y="230" height="50" width="168" style="stroke:#33322E;fill:#eee8d5;stroke-dasharray:none;"></rect>
|
||||
<text x="50" y="260" style="">HAVE_METADATA</text></svg>
|
||||
<svg width="280" height="310" version="1.1" baseProfile="full" viewbox="0 0 280 310" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events" style="font-weight:bold; font-size:10pt; font-family:'Arial', Helvetica, sans-serif;;stroke-width:2;stroke-linejoin:round;stroke-linecap:round"><text x="160" y="111" style="font-weight:normal;">load()</text>
|
||||
<path d="M140 81 L140 105 L140 129 L140 129 " style="stroke:#33322E;fill:none;stroke-dasharray:none;"></path>
|
||||
<path d="M136.8 121 L140 125 L143.2 121 L140 129 Z" style="stroke:#33322E;fill:#33322E;stroke-dasharray:none;"></path>
|
||||
<text x="160" y="211" style="font-weight:normal;">media()</text>
|
||||
<path d="M140 181 L140 205 L140 229 L140 229 " style="stroke:#33322E;fill:none;stroke-dasharray:none;"></path>
|
||||
<path d="M136.8 221 L140 225 L143.2 221 L140 229 Z" style="stroke:#33322E;fill:#33322E;stroke-dasharray:none;"></path>
|
||||
<rect x="63" y="30" height="50" width="154" style="stroke:#33322E;fill:#eee8d5;stroke-dasharray:none;"></rect>
|
||||
<text x="83" y="60" style="">HAVE_NOTHING</text>
|
||||
<rect x="30" y="130" height="50" width="220" style="stroke:#33322E;fill:#eee8d5;stroke-dasharray:none;"></rect>
|
||||
<text x="50" y="160" style="">HAVE_MAIN_MANIFEST</text>
|
||||
<rect x="56" y="230" height="50" width="168" style="stroke:#33322E;fill:#eee8d5;stroke-dasharray:none;"></rect>
|
||||
<text x="76" y="260" style="">HAVE_METADATA</text></svg>
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
Before Width: | Height: | Size: 162 KiB |
4
node_modules/@videojs/http-streaming/docs/images/playlist-loader-states.nomnoml.svg
generated
vendored
4
node_modules/@videojs/http-streaming/docs/images/playlist-loader-states.nomnoml.svg
generated
vendored
|
@ -15,8 +15,8 @@
|
|||
<path d="M155.2 489 L152 485 L148.8 489 L152 481 Z" style="stroke:#33322E;fill:#33322E;stroke-dasharray:none;"></path>
|
||||
<rect x="75" y="30" height="50" width="154" style="stroke:#33322E;fill:#eee8d5;stroke-dasharray:none;"></rect>
|
||||
<text x="95" y="60" style="">HAVE_NOTHING</text>
|
||||
<rect x="78" y="130" height="50" width="149" style="stroke:#33322E;fill:#eee8d5;stroke-dasharray:none;"></rect>
|
||||
<text x="98" y="160" style="">HAVE_MASTER</text>
|
||||
<rect x="42" y="130" height="50" width="220" style="stroke:#33322E;fill:#eee8d5;stroke-dasharray:none;"></rect>
|
||||
<text x="62" y="160" style="">HAVE_MAIN_MANIFEST</text>
|
||||
<rect x="56" y="230" height="50" width="192" style="stroke:#33322E;fill:#eee8d5;stroke-dasharray:none;"></rect>
|
||||
<text x="76.3" y="260" style="">SWITCHING_MEDIA</text>
|
||||
<rect x="68" y="330" height="50" width="168" style="stroke:#33322E;fill:#eee8d5;stroke-dasharray:none;"></rect>
|
||||
|
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
|
@ -1,119 +0,0 @@
|
|||
@startuml
|
||||
|
||||
header DashPlaylistLoader sequences
|
||||
title DashPlaylistLoader sequences: Master Manifest with Alternate Audio
|
||||
|
||||
Participant "MasterPlaylistController" as MPC #red
|
||||
Participant "MasterDashPlaylistLoader" as MPL #blue
|
||||
Participant "mainSegmentLoader" as SL #blue
|
||||
Participant "AudioDashPlaylistLoader" as APL #green
|
||||
Participant "audioSegmentLoader" as ASL #green
|
||||
Participant "external server" as ext #brown
|
||||
Participant "mpdParser" as parser #orange
|
||||
Participant "mediaGroups" as MG #purple
|
||||
Participant Tech #lightblue
|
||||
|
||||
== Initialization ==
|
||||
|
||||
MPC -> MPL : construct MasterPlaylistLoader
|
||||
MPC -> MPL: load()
|
||||
|
||||
== Requesting Master Manifest ==
|
||||
|
||||
MPL -> MPL : start()
|
||||
|
||||
MPL -> ext: xhr request for master manifest
|
||||
ext -> MPL : response with master manifest
|
||||
|
||||
MPL -> parser: parse manifest
|
||||
parser -> MPL: object representing manifest
|
||||
|
||||
note over MPL #lightblue: trigger 'loadedplaylist'
|
||||
|
||||
== Requesting Video Manifest ==
|
||||
|
||||
note over MPL #lightblue: handling loadedplaylist
|
||||
MPL -> MPL: media(x)
|
||||
|
||||
alt if no sidx
|
||||
note over MPL #lightgray: zero delay to fake network request
|
||||
else if sidx
|
||||
break
|
||||
MPL -> ext: request sidx
|
||||
end
|
||||
end
|
||||
|
||||
note over MPL #lightblue: trigger 'loadedmetadata' on master loader [T1]
|
||||
|
||||
note over MPL #lightblue: handling 'loadedmetadata'
|
||||
|
||||
opt vod and preload !== 'none'
|
||||
|
||||
MPL -> SL: playlist()
|
||||
MPL -> SL: load()
|
||||
|
||||
end
|
||||
|
||||
== Initializing Media Groups, Choosing Active Tracks ==
|
||||
|
||||
MPL -> MG: setupMediaGroups()
|
||||
MG -> MG: initialize()
|
||||
|
||||
== Initializing Alternate Audio Loader ==
|
||||
|
||||
MG -> APL: create child playlist loader for alt audio
|
||||
|
||||
MG -> MG: activeGroup and audio variant selected
|
||||
MG -> MG: enable activeTrack, onTrackChanged()
|
||||
MG -> ASL: reset audio segment loader
|
||||
|
||||
== Requesting Alternate Audio Manifest ==
|
||||
|
||||
MG -> MG: startLoaders()
|
||||
|
||||
MG -> APL: load()
|
||||
APL -> APL: start()
|
||||
APL -> APL: zero delay to fake network request
|
||||
|
||||
break finish pending tasks
|
||||
MG -> Tech: add audioTrack
|
||||
MPL -> MPC: setupSourceBuffers_()
|
||||
MPL -> MPC: setupFirstPlay()
|
||||
|
||||
loop mainSegmentLoader.monitorBufferTick_()
|
||||
SL -> ext: requests media segments
|
||||
ext -> SL: response with media segment bytes
|
||||
end
|
||||
end
|
||||
|
||||
APL -> APL: zero delay over
|
||||
APL -> APL: media(x)
|
||||
|
||||
alt if no sidx
|
||||
note over APL #lightgray: zero delay to fake network request
|
||||
else if sidx
|
||||
break
|
||||
MPL -> ext: request sidx
|
||||
end
|
||||
end
|
||||
|
||||
== Requesting Alternate Audio Segments ==
|
||||
|
||||
note over APL #lightblue: trigger 'loadedplaylist'
|
||||
note over APL #lightblue: handling 'loadedplaylist'
|
||||
APL -> ASL: playlist()
|
||||
|
||||
|
||||
note over ASL #lightblue: trigger 'loadedmetadata' [T2]
|
||||
note over APL #lightblue: handling 'loadedmetadata'
|
||||
APL -> ASL: playlist()
|
||||
APL -> ASL: load()
|
||||
|
||||
loop audioSegmentLoader.monitorBufferTick_()
|
||||
|
||||
ASL -> ext: requests media segments
|
||||
ext -> ASL: response with media segment bytes
|
||||
|
||||
end
|
||||
|
||||
@enduml
|
|
@ -17,5 +17,5 @@
|
|||
|
||||
#.label: align=center visual=none italic
|
||||
|
||||
[HAVE_NOTHING] load()-> [HAVE_MASTER]
|
||||
[HAVE_MASTER] media()-> [HAVE_METADATA]
|
||||
[HAVE_NOTHING] load()-> [HAVE_MAIN_MANIFEST]
|
||||
[HAVE_MAIN_MANIFEST] media()-> [HAVE_METADATA]
|
||||
|
|
|
@ -1,246 +0,0 @@
|
|||
@startuml
|
||||
|
||||
header PlaylistLoader sequences
|
||||
title PlaylistLoader sequences: Master Manifest and Alternate Audio
|
||||
|
||||
Participant "MasterPlaylistController" as MPC #red
|
||||
Participant "MasterPlaylistLoader" as MPL #blue
|
||||
Participant "mainSegmentLoader" as SL #blue
|
||||
Participant "AudioPlaylistLoader" as APL #green
|
||||
Participant "audioSegmentLoader" as ASL #green
|
||||
Participant "external server" as ext #brown
|
||||
Participant "m3u8Parser" as parser #orange
|
||||
Participant "mediaGroups" as MG #purple
|
||||
Participant Tech #lightblue
|
||||
|
||||
== Initialization ==
|
||||
|
||||
group MasterPlaylistController.constructor()
|
||||
|
||||
MPC -> MPL : setting up MasterPlaylistLoader
|
||||
note left #lightyellow
|
||||
sets up mediaupdatetimeout
|
||||
handler for live playlist staleness
|
||||
end note
|
||||
note over MPL #lightgray: state = 'HAVE_NOTHING'
|
||||
|
||||
MPC -> MPL: load()
|
||||
|
||||
end
|
||||
|
||||
group MasterPlaylistLoader.load()
|
||||
|
||||
MPL -> MPL : start()
|
||||
note left #lightyellow: not started yet
|
||||
|
||||
== Requesting Master Manifest ==
|
||||
|
||||
group start()
|
||||
|
||||
note over MPL #lightgray: started = true
|
||||
|
||||
MPL -> ext: xhr request for master manifest
|
||||
ext -> MPL : response with master manifest
|
||||
|
||||
MPL -> parser: parse master manifest
|
||||
parser -> MPL: object representing manifest
|
||||
MPL -> MPL: set loader's master playlist
|
||||
note over MPL #lightgray: state = 'HAVE_MASTER'
|
||||
note over MPL #lightblue: trigger 'loadedplaylist' on master loader
|
||||
|
||||
== Requesting Video Manifest ==
|
||||
|
||||
group 'loadedplaylist' handler
|
||||
|
||||
note over MPL #lightblue: handling loadedplaylist
|
||||
MPL -> MPL : media()
|
||||
note left #lightgray: select initial (video) playlist
|
||||
note over MPL #lightyellow: state = 'SWITCHING_MEDIA'
|
||||
|
||||
group media()
|
||||
|
||||
MPL -> ext : request child manifest
|
||||
ext -> MPL: child manifest returned
|
||||
MPL -> MPL: haveMetadata()
|
||||
note over MPL #lightyellow: state = 'HAVE_METADATA'
|
||||
|
||||
group haveMetadata()
|
||||
|
||||
MPL -> parser: parse child manifest
|
||||
parser -> MPL: object representing the child manifest
|
||||
note over MPL #lightyellow
|
||||
update master and media playlists
|
||||
end note
|
||||
|
||||
opt live
|
||||
MPL -> MPL: setup mediaupdatetimeout
|
||||
end
|
||||
|
||||
note over MPL #lightblue
|
||||
trigger 'loadedplaylist' on master loader.
|
||||
This does not end up requesting segments
|
||||
at this point.
|
||||
end note
|
||||
|
||||
group MasterPlaylistLoader 'loadedplaylist' handler
|
||||
|
||||
MPL -> MPL : setup durationchange handler
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
== Requesting Video Segments ==
|
||||
|
||||
note over MPL #lightblue: trigger 'loadedmetadata'
|
||||
|
||||
group 'loadedmetadata' handler
|
||||
|
||||
note over MPL #lightblue: handling 'loadedmetadata'
|
||||
|
||||
opt vod and preload !== 'none'
|
||||
|
||||
MPL -> SL: playlist()
|
||||
note over SL #lightyellow: updates playlist
|
||||
|
||||
MPL -> SL: load()
|
||||
note right #lightgray
|
||||
This does nothing as mimeTypes
|
||||
have not been set yet.
|
||||
end note
|
||||
|
||||
end
|
||||
|
||||
MPL -> MG: setupMediaGroups()
|
||||
|
||||
== Initializing Media Groups, Choosing Active Tracks ==
|
||||
|
||||
group MediaGroups.setupMediaGroups()
|
||||
|
||||
group initialize()
|
||||
|
||||
MG -> APL: create child playlist loader for alt audio
|
||||
note over APL #lightyellow: state = 'HAVE_NOTHING'
|
||||
|
||||
note left #lightgray
|
||||
setup 'loadedmetadata' and 'loadedplaylist' listeners
|
||||
on child alt audio playlist loader
|
||||
end note
|
||||
|
||||
MG -> Tech: add audioTracks
|
||||
|
||||
end
|
||||
|
||||
MG -> MG: activeGroup and audio variant selected
|
||||
MG -> MG: enable activeTrack, onTrackChanged()
|
||||
note left #lightgray
|
||||
There is no activePlaylistLoader at this point,
|
||||
but there is an audio playlistLoader
|
||||
end note
|
||||
|
||||
group onTrackChanged()
|
||||
|
||||
MG -> SL: reset mainSegmentLoader
|
||||
note left #lightgray: Clears buffer, aborts all inflight requests
|
||||
|
||||
== Requesting Alternate Audio Manifest ==
|
||||
|
||||
MG -> MG: startLoaders()
|
||||
|
||||
group startLoaders()
|
||||
note over MG #lightyellow
|
||||
activePlaylistLoader = AudioPlaylistLoader
|
||||
end note
|
||||
|
||||
MG -> APL: load()
|
||||
end
|
||||
|
||||
group AudioPlaylistLoader.load()
|
||||
APL -> APL: start()
|
||||
|
||||
group alt start()
|
||||
|
||||
note over APL #lightyellow: started = true
|
||||
APL -> ext: request alt audio media manifest
|
||||
|
||||
break MasterPlaylistLoader 'loadedmetadata' handler
|
||||
|
||||
MPL -> MPC: setupSourceBuffers()
|
||||
note left #lightgray
|
||||
This will set mimeType.
|
||||
Segments can be loaded from now on.
|
||||
end note
|
||||
|
||||
MPL -> MPC: setupFirstPlay()
|
||||
note left #lightgray
|
||||
Immediate exit since the player
|
||||
is paused
|
||||
end note
|
||||
|
||||
end
|
||||
|
||||
ext -> APL: responds with child manifest
|
||||
APL -> parser: parse child manifest
|
||||
parser -> APL: object representing child manifest returned
|
||||
note over APL #lightyellow: state = 'HAVE_MASTER'
|
||||
note left #lightgray: Infer a master playlist
|
||||
|
||||
APL -> APL: haveMetadata()
|
||||
note over APL #lightyellow: state = 'HAVE_METADATA'
|
||||
|
||||
group haveMetadata()
|
||||
|
||||
APL -> parser: parsing the child manifest again
|
||||
parser -> APL: returning object representing child manifest
|
||||
note over APL #lightyellow
|
||||
update master and media references
|
||||
end note
|
||||
|
||||
== Requesting Alternate Audio Segments ==
|
||||
|
||||
note over APL #lightblue: trigger 'loadedplaylist'
|
||||
|
||||
group 'loadedplaylist' handler
|
||||
|
||||
note over APL #lightblue: handling 'loadedplaylist'
|
||||
APL -> ASL: playlist()
|
||||
note over ASL #lightyellow: set playlist
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
note over APL #lightblue: trigger 'loadedmetadata'
|
||||
|
||||
group 'loadedmetadata' handler
|
||||
|
||||
note over APL #lightblue: handling 'loadedmetadata'
|
||||
|
||||
APL -> ASL: playlist()
|
||||
APL -> ASL: load()
|
||||
|
||||
loop audioSegmentLoader.load()
|
||||
|
||||
ASL -> ext: requests media segments
|
||||
ext -> ASL: response with media segment bytes
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@enduml
|
|
@ -1,114 +0,0 @@
|
|||
@startuml
|
||||
|
||||
header PlaylistLoader sequences
|
||||
title PlaylistLoader sequences: Master Manifest and Alternate Audio
|
||||
|
||||
Participant "MasterPlaylistController" as MPC #red
|
||||
Participant "MasterPlaylistLoader" as MPL #blue
|
||||
Participant "mainSegmentLoader" as SL #blue
|
||||
Participant "AudioPlaylistLoader" as APL #green
|
||||
Participant "audioSegmentLoader" as ASL #green
|
||||
Participant "external server" as ext #brown
|
||||
Participant "m3u8Parser" as parser #orange
|
||||
Participant "mediaGroups" as MG #purple
|
||||
Participant Tech #lightblue
|
||||
|
||||
== Initialization ==
|
||||
|
||||
MPC -> MPL : construct MasterPlaylistLoader
|
||||
MPC -> MPL: load()
|
||||
|
||||
MPL -> MPL : start()
|
||||
|
||||
== Requesting Master Manifest ==
|
||||
|
||||
MPL -> ext: xhr request for master manifest
|
||||
ext -> MPL : response with master manifest
|
||||
|
||||
MPL -> parser: parse master manifest
|
||||
parser -> MPL: object representing manifest
|
||||
|
||||
note over MPL #lightblue: trigger 'loadedplaylist'
|
||||
|
||||
== Requesting Video Manifest ==
|
||||
|
||||
note over MPL #lightblue: handling loadedplaylist
|
||||
MPL -> MPL : media()
|
||||
|
||||
MPL -> ext : request child manifest
|
||||
ext -> MPL: child manifest returned
|
||||
|
||||
MPL -> parser: parse child manifest
|
||||
parser -> MPL: object representing the child manifest
|
||||
|
||||
note over MPL #lightblue: trigger 'loadedplaylist'
|
||||
note over MPL #lightblue: handleing 'loadedplaylist'
|
||||
|
||||
MPL -> SL: playlist()
|
||||
MPL -> SL: load()
|
||||
|
||||
== Requesting Video Segments ==
|
||||
|
||||
note over MPL #lightblue: trigger 'loadedmetadata'
|
||||
note over MPL #lightblue: handling 'loadedmetadata'
|
||||
|
||||
opt vod and preload !== 'none'
|
||||
|
||||
MPL -> SL: playlist()
|
||||
MPL -> SL: load()
|
||||
|
||||
end
|
||||
|
||||
MPL -> MG: setupMediaGroups()
|
||||
|
||||
== Initializing Media Groups, Choosing Active Tracks ==
|
||||
|
||||
MG -> APL: create child playlist loader for alt audio
|
||||
|
||||
MG -> MG: activeGroup and audio variant selected
|
||||
MG -> MG: enable activeTrack, onTrackChanged()
|
||||
MG -> SL: reset mainSegmentLoader
|
||||
|
||||
== Requesting Alternate Audio Manifest ==
|
||||
|
||||
MG -> MG: startLoaders()
|
||||
|
||||
MG -> APL: load()
|
||||
APL -> APL: start()
|
||||
|
||||
APL -> ext: request alt audio media manifest
|
||||
|
||||
break finish pending tasks
|
||||
MG -> Tech: add audioTracks
|
||||
MPL -> MPC: setupSourceBuffers()
|
||||
MPL -> MPC: setupFirstPlay()
|
||||
|
||||
loop on monitorBufferTick
|
||||
SL -> ext: requests media segments
|
||||
ext -> SL: response with media segment bytes
|
||||
end
|
||||
end
|
||||
|
||||
ext -> APL: responds with child manifest
|
||||
|
||||
APL -> parser: parse child manifest
|
||||
parser -> APL: object representing child manifest returned
|
||||
|
||||
== Requesting Alternate Audio Segments ==
|
||||
|
||||
note over APL #lightblue: trigger 'loadedplaylist'
|
||||
note over APL #lightblue: handling 'loadedplaylist'
|
||||
APL -> ASL: playlist()
|
||||
|
||||
note over APL #lightblue: trigger 'loadedmetadata'
|
||||
note over APL #lightblue: handling 'loadedmetadata'
|
||||
APL -> ASL: playlist()
|
||||
APL -> ASL: load()
|
||||
|
||||
loop audioSegmentLoader.load()
|
||||
|
||||
ASL -> ext: requests media segments
|
||||
ext -> ASL: response with media segment bytes
|
||||
end
|
||||
|
||||
@enduml
|
|
@ -17,8 +17,8 @@
|
|||
|
||||
#.label: align=center visual=none italic
|
||||
|
||||
[HAVE_NOTHING] load()-> [HAVE_MASTER]
|
||||
[HAVE_MASTER] media()-> [SWITCHING_MEDIA]
|
||||
[HAVE_NOTHING] load()-> [HAVE_MAIN_MANIFEST]
|
||||
[HAVE_MAIN_MANIFEST] media()-> [SWITCHING_MEDIA]
|
||||
[SWITCHING_MEDIA] media()/ start()-> [HAVE_METADATA]
|
||||
|
||||
[HAVE_METADATA] <--> [<label> mediaupdatetimeout]
|
||||
|
|
4
node_modules/@videojs/http-streaming/docs/lhls/index.md
generated
vendored
4
node_modules/@videojs/http-streaming/docs/lhls/index.md
generated
vendored
|
@ -53,7 +53,7 @@ The first change was to request pieces of a segment. There are a few approaches
|
|||
|
||||
*Plain text MIME type* was chosen because of its wide support. It provides a mechanism to access progressive bytes downloaded on [XMLHttpRequest progress events](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequestEventTarget/onprogress).
|
||||
|
||||
This change was made in [media-segment-request](https://github.com/videojs/http-streaming/blob/master/src/media-segment-request.js).
|
||||
This change was made in [media-segment-request](/src/media-segment-request.js).
|
||||
|
||||
### Transmux and Append Segment Pieces
|
||||
|
||||
|
@ -93,7 +93,7 @@ The transmuxing logic moved to a new module called segment-transmuxer, which wra
|
|||
|
||||
##### mux.js
|
||||
|
||||
While most of the [mux.js pipeline](https://github.com/videojs/mux.js/blob/master/docs/diagram.png) supports pushing pieces of data (and should support LHLS by default), its "flushes" to send transmuxed data back to the caller expected full segments.
|
||||
While most of the [mux.js pipeline](/docs/diagram.png) supports pushing pieces of data (and should support LHLS by default), its "flushes" to send transmuxed data back to the caller expected full segments.
|
||||
|
||||
Much of the pipeline was reused, however, the top level audio and video segment streams, as well as the entry point, were rewritten so that instead of providing a full segment on flushes, each frame of video was provided individually (audio frames still flush as a group). The new concept of partial flushes was added into the pipeline to handle this case.
|
||||
|
||||
|
|
2
node_modules/@videojs/http-streaming/docs/lhls/transmux-before-append-changes.md
generated
vendored
2
node_modules/@videojs/http-streaming/docs/lhls/transmux-before-append-changes.md
generated
vendored
|
@ -33,4 +33,4 @@ With the transmux before append and LHLS changes, we only append video init segm
|
|||
|
||||
### Test Changes
|
||||
|
||||
Some tests were removed because they were no longer relevant after the change to creating source buffers later. For instance, `waits for both main and audio loaders to finish before calling endOfStream if main loader starting media is unknown` no longer can be tested by waiting for an audio loader response and checking for end of stream, as the test will time out since MasterPlaylistController will wait for track info from the main loader before the source buffers are created. That condition is checked elsewhere.
|
||||
Some tests were removed because they were no longer relevant after the change to creating source buffers later. For instance, `waits for both main and audio loaders to finish before calling endOfStream if main loader starting media is unknown` no longer can be tested by waiting for an audio loader response and checking for end of stream, as the test will time out since PlaylistController will wait for track info from the main loader before the source buffers are created. That condition is checked elsewhere.
|
||||
|
|
30
node_modules/@videojs/http-streaming/docs/multiple-alternative-audio-tracks.md
generated
vendored
30
node_modules/@videojs/http-streaming/docs/multiple-alternative-audio-tracks.md
generated
vendored
|
@ -65,19 +65,19 @@ Corresponding AudioTrackList when media-group-1 is used (before any tracks have
|
|||
## Startup (how tracks are added and used)
|
||||
> AudioTrack & AudioTrackList live in video.js
|
||||
|
||||
1. `HLS` creates a `MasterPlaylistController` and watches for the `loadedmetadata` event
|
||||
1. `HLS` parses the m3u8 using the `MasterPlaylistController`
|
||||
1. `MasterPlaylistController` creates a `PlaylistLoader` for the master m3u8
|
||||
1. `MasterPlaylistController` creates `PlaylistLoader`s for every audio playlist
|
||||
1. `MasterPlaylistController` creates a `SegmentLoader` for the main m3u8
|
||||
1. `MasterPlaylistController` creates a `SegmentLoader` for a potential audio playlist
|
||||
1. `HLS` creates a `PlaylistController` and watches for the `loadedmetadata` event
|
||||
1. `HLS` parses the m3u8 using the `PlaylistController`
|
||||
1. `PlaylistController` creates a `PlaylistLoader` for the main m3u8
|
||||
1. `PlaylistController` creates `PlaylistLoader`s for every audio playlist
|
||||
1. `PlaylistController` creates a `SegmentLoader` for the main m3u8
|
||||
1. `PlaylistController` creates a `SegmentLoader` for a potential audio playlist
|
||||
1. `HLS` sees the `loadedmetadata` and finds the currently selected MediaGroup and all the metadata
|
||||
1. `HLS` removes all `AudioTrack`s from the `AudioTrackList`
|
||||
1. `HLS` created `AudioTrack`s for the MediaGroup and adds them to the `AudioTrackList`
|
||||
1. `HLS` calls `MasterPlaylistController`s `useAudio` with no arguments (causes it to use the currently enabled audio)
|
||||
1. `MasterPlaylistController` turns off the current audio `PlaylistLoader` if it is on
|
||||
1. `MasterPlaylistController` maps the `label` to the `PlaylistLoader` containing the audio
|
||||
1. `MasterPlaylistController` turns on that `PlaylistLoader` and the Corresponding `SegmentLoader` (master or audio only)
|
||||
1. `HLS` calls `PlaylistController`s `useAudio` with no arguments (causes it to use the currently enabled audio)
|
||||
1. `PlaylistController` turns off the current audio `PlaylistLoader` if it is on
|
||||
1. `PlaylistController` maps the `label` to the `PlaylistLoader` containing the audio
|
||||
1. `PlaylistController` turns on that `PlaylistLoader` and the Corresponding `SegmentLoader` (main or audio only)
|
||||
1. `MediaSource`/`mux.js` determine how to mux
|
||||
|
||||
## How tracks are switched
|
||||
|
@ -88,9 +88,9 @@ Corresponding AudioTrackList when media-group-1 is used (before any tracks have
|
|||
1. `AudioTrackList` enables the new `Audiotrack` and disables all others
|
||||
1. `AudioTrackList` triggers a `changed` event
|
||||
1. `HLS` sees the `changed` event and finds the newly enabled `AudioTrack`
|
||||
1. `HLS` sends the `label` for the new `AudioTrack` to `MasterPlaylistController`s `useAudio` function
|
||||
1. `MasterPlaylistController` turns off the current audio `PlaylistLoader` if it is on
|
||||
1. `MasterPlaylistController` maps the `label` to the `PlaylistLoader` containing the audio
|
||||
1. `MasterPlaylistController` maps the `label` to the `PlaylistLoader` containing the audio
|
||||
1. `MasterPlaylistController` turns on that `PlaylistLoader` and the Corresponding `SegmentLoader` (master or audio only)
|
||||
1. `HLS` sends the `label` for the new `AudioTrack` to `PlaylistController`s `useAudio` function
|
||||
1. `PlaylistController` turns off the current audio `PlaylistLoader` if it is on
|
||||
1. `PlaylistController` maps the `label` to the `PlaylistLoader` containing the audio
|
||||
1. `PlaylistController` maps the `label` to the `PlaylistLoader` containing the audio
|
||||
1. `PlaylistController` turns on that `PlaylistLoader` and the Corresponding `SegmentLoader` (main or audio only)
|
||||
1. `MediaSource`/`mux.js` determine how to mux
|
||||
|
|
8
node_modules/@videojs/http-streaming/docs/playlist-loader.md
generated
vendored
8
node_modules/@videojs/http-streaming/docs/playlist-loader.md
generated
vendored
|
@ -9,7 +9,7 @@ The [PlaylistLoader][pl] (PL) is responsible for requesting m3u8s, parsing them
|
|||
1. To request an m3u8.
|
||||
2. To parse a m3u8 into a format [videojs-http-streaming][vhs] can understand.
|
||||
3. To allow selection of a specific media stream.
|
||||
4. To refresh a live master m3u8 for changes.
|
||||
4. To refresh a live m3u8 for changes.
|
||||
|
||||
## Design
|
||||
|
||||
|
@ -18,7 +18,7 @@ The [PlaylistLoader][pl] (PL) is responsible for requesting m3u8s, parsing them
|
|||

|
||||
|
||||
- `HAVE_NOTHING` the state before the m3u8 is received and parsed.
|
||||
- `HAVE_MASTER` the state before a media manifest is parsed and setup but after the master manifest has been parsed and setup.
|
||||
- `HAVE_MAIN_MANIFEST` the state before a media manifest is parsed and setup but after the main manifest has been parsed and setup.
|
||||
- `HAVE_METADATA` the state after a media stream is setup.
|
||||
- `SWITCHING_MEDIA` the intermediary state we go though while changing to a newly selected media playlist
|
||||
- `HAVE_CURRENT_METADATA` a temporary state after requesting a refresh of the live manifest and before receiving the update
|
||||
|
@ -31,7 +31,7 @@ The [PlaylistLoader][pl] (PL) is responsible for requesting m3u8s, parsing them
|
|||
|
||||
### Events
|
||||
|
||||
- `loadedplaylist` signals the setup of a master playlist, representing the HLS source as a whole, from the m3u8; or a media playlist, representing a media stream.
|
||||
- `loadedplaylist` signals the setup of a main playlist, representing the HLS source as a whole, from the m3u8; or a media playlist, representing a media stream.
|
||||
- `loadedmetadata` signals initial setup of a media stream.
|
||||
- `playlistunchanged` signals that no changes have been made to a m3u8.
|
||||
- `mediaupdatetimeout` signals that a live m3u8 and media stream must be refreshed.
|
||||
|
@ -40,7 +40,7 @@ The [PlaylistLoader][pl] (PL) is responsible for requesting m3u8s, parsing them
|
|||
|
||||
### Interaction with Other Modules
|
||||
|
||||

|
||||

|
||||
|
||||
[pl]: ../src/playlist-loader.js
|
||||
[sl]: ../src/segment-loader.js
|
||||
|
|
2
node_modules/@videojs/http-streaming/docs/troubleshooting.md
generated
vendored
2
node_modules/@videojs/http-streaming/docs/troubleshooting.md
generated
vendored
|
@ -2,7 +2,7 @@
|
|||
|
||||
## Other troubleshooting guides
|
||||
|
||||
For issues around data embedded into media segments (e.g., 608 captions), see the [mux.js troubleshooting guide](https://github.com/videojs/mux.js/blob/master/docs/troubleshooting.md).
|
||||
For issues around data embedded into media segments (e.g., 608 captions), see the [mux.js troubleshooting guide](https://github.com/videojs/mux.js/blob/main/docs/troubleshooting.md).
|
||||
|
||||
## Tools
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue