# MetaPlaylist

The MetaPlaylist is a specific kind of transport: a playlist of multiple Manifests.

## How the original Manifest files are considered

To play a MetaPlaylist content, each manifest it depends on has to be downloaded and
parsed through their original logic (a `MPD` through DASH's logic and a Smooth Manifest
through Smooth's logic).

We then merge each of these Manifest, to construct a `Manifest` object with the same
structure and properties than we would have with a DASH or Smooth manifest.

The trick is to consider each of those original Manifest as different Periods (like DASH
Periods). The trick works here because the RxPlayer's definition of a transport (and of
the underlying properties) is much more flexible than in DASH. If an original MPD already
has multiple Periods, each of them are also converted as different RxPlayer's Period so
that no feature from the original content is lost.

Each of those Period is then concatenated one after the other thanks to the time
information announced in the MetaPlaylist file.

## How about the segments

The exploitation of segment metadata is even trickier.

In `DASH` or `Smooth`, the URL of each segment could be constructed from the starting time
of each of those segments.

The problem here is that a `MetaPlaylist` player has to mutate those to place them at the
position indicated in the MetaPlaylist's JSON instead.

To simplify everything, we choose to rely on a simple but effective wrapper on top of the
original transport protocol.

When the core logic of the player wants to load a segment from the network, that wrapper
translate back the data as if we're just playing the original content at its original
position. How it works: the wrapper removes a specific time offset from the wanted
segment's metadata, before contacting the transport's logic.

When giving back the segment to the core logic of the player, the wrapper first update
those loaded segment with the wanted position data. How it works: the wrapper adds back
the time offset it previously substracted from the wanted segment's metadata before giving
it back to the core logic.

To illustrate, it kind of goes like this:

```
+----------------+ 1. Ask for segments infos from t to t+n  +--------------+
|                | ---------------------------------------> |              |
|                |                                          |              |
|                | <--------------------------------------- |              |
|                |  4. Gives segment infos asked (offseted) |              |
|                |                                          |              |
|      CORE      |                                          | METAPLAYLIST |
|                |                                          |    WRAPPER   |
|                | 5. Ask to download segment (offseted)    |              |
|                | ---------------------------------------> |              |
|                |                                          |              |
|                | <--------------------------------------- |              |
+----------------+              8. Gives segment (offseted) +--------------+
                                                             | ^     |  ^
                                                             | |     |  |
                                                             | |     |  |
   +------------+   2. get segment infos from t-offset to t+n-offset |  |
   | +--------+ | <------------------------------------------+ |     |  |
   | |        | |                                              |     |  |
   | |  DASH  | |                                              |     |  |
   | |        | |  3. Gives segment infos asked                |     |  |
   | +--------+ | ---------------------------------------------+     |  |
   | +-------+  |                                                    |  |
   | |       |  |                                                    |  |
   | |  HSS  |  |                                                    |  |
   | |       |  |                                                    |  |
   | +-------+  |                                                    |  |
   | +-------+  |  6. Ask to download non-offseted (normal) segments |  |
   | |       |  | <--------------------------------------------------+  |
   | |  ...  |  |                                                       |
   | |       |  |  7. Gives normal segment                              |
   | +-------+  | ------------------------------------------------------+
   +------------+
```

To make sure the segment is pushed at the right moment and doesn't overlap other contents,
we make heavy use of some specific `SourceBuffer` properties:

- the `timestampOffset` property allows to set a specific offset
- `appendWindowStart` allows to limit the starting time of the pushed segment
- `appendWindowEnd` allows to limit the ending time of the pushed segment
