The SourceBuffers
Overview
The core/source-buffer
directory contains the part of the code directly
related to the insertion and removal of media segments.
This is done through SourceBuffers
, which are JavaScript objects.
The name is taken from the MSE SourceBuffer[1] JavaScript object, which are the native browser interface through which media segments are pushed.
In the RxPlayer, those SourceBuffer objects are only used for audio and video decoding. For the other types of media (e.g. text - for subtitles - and image - for thumbnails), custom SourceBuffer implementation have been written entirely in JavaScript instead, to allow more advanced treatment of those.
Those custom SourceBuffer implementation are defined in the
src/custom_source_buffers
directory.
[1] MSE SourceBuffer
Here’s a vulgarized architecture schema of the code in that directory:
+--------------------------------------------------------------------------+
| Rest of the RxPlayer's code |
+--------------------------------------------------------------------------+
| ^
Ask to get / create / remove | | Returns created QueuedSourceBuffer or
SourceBuffer for a given type | | wanted information
or get information about the | |
available types | |
| |
V |
+--------------------------------------------------------------------------+
| SourceBuffersStore |
+--------------------------------------------------------------------------+
| | | |
| creates | creates | creates | creates
| (if needed) | (if needed) | (if needed) | (if needed)
| | | |
V V V V
+------------+ +------------+ +------------+ +------------+
| Queued | | Queued | | Queued | | Queued |
|SourceBuffer| |SourceBuffer| |SourceBuffer| |SourceBuffer|
| (video) | | (audio) | | (text) | | (image) |
+------------+ +------------+ +------------+ +------------+
Creates | Creates | Creates | Creates |
| | | | | | | |
| | | | | | | |
V V V V V V V V
+-----+ +------+ +-----+ +------+ +-----+ +------+ +-----+ +------+
| SI* | | NSB* | | SI* | | NSB* | | SI* | | TSB* | | SI* | | ISB* |
+-----+ +------+ +-----+ +------+ +-----+ +------+ +-----+ +------+
SI*: SegmentInventory. Store the information on every segments currently
available in the associated SourceBuffer.
NSB*: Native [browser implementation of a] SourceBuffer.
TSB*: Text SourceBuffer (either HTMLTextSourceBuffer or
NativeTextSourceBuffer depending on the current textrack mode chosen.).
Custom SourceBuffer implementation for subtitles which handle the logic
of storing subtitles and displaying them at the right time and with the
right style (color, position etc.).
ISB*: ImageSourceBuffer. Custom SourceBuffer implementation for image
thumbnails which will just store them.
SourceBuffersStore
The SourceBuffersStore
is the main export from there. It facilitates the
creation and destruction of SourceBuffers.
Its roles are to:
-
announce which types of SourceBuffer can be currently created on the HTMLMediaElement (example of a type of buffer would be “audio”, “video” or “text”).
For example, no “video” SourceBuffer should be created on an
<audio>
element (though it wouldn’t cause any problem, it would be useless as video cannot be rendered here). To give another example, you should not create a “text” SourceBuffer if no text track parser has been added to the RxPlayer. -
Create only one
QueuedSourceBuffer
instance per type of buffer.Multiple
QueuedSourceBuffer
for a single type could lead to browser issues and to conflicts in the RxPlayer code. -
Provide a synchronization mechanism to announce when all “native” SourceBuffers are ready to receive segments. I’ll explain:
“Native” SourceBuffers are SourceBuffers directly implemented by the browser. They typically are the “video” and “audio” SourceBuffers.
Among several other constraints, all native SourceBuffers needed to play a given content should be created before we can start pushing segments to any of them. This is a browser limitation.
This is where this synchronization mechanism can become useful. The SourceBuffersStore will signal when all of the native SourceBuffers needed for the given contents are created, so that the rest of the RxPlayer knows when it can begin to push segments to those.
Note that this means that un-needed SourceBuffers have to be explicitely “disabled” here, as the SourceBuffersStore cannot know whether it should wait until those SourceBuffers are created of if you just don’t need it.
QueuedSourceBuffer
A QueuedSourceBuffer
is a wrapper on top of a SourceBuffer
(a native one
or a custom RxPlayer implementation) that allows to push and remove segments
sequentially.
Basically, it waits for the previous action to be finished before going on the
next step.
It also keeps an inventory of all segments currently contained in it, with the
help of a SegmentInventory
(see corresponding chapter).
It is the main interface the rest of the RxPlayer code has with SourceBuffers.
BufferGarbageCollector
The BufferGarbageCollector is a function used by the RxPlayer to
periodically perform “garbage collection” manually on a given
QueuedSourceBuffer
.
It is based on the following building bricks:
-
A clock, which is an observable emitting the current time (in seconds) when the garbage collection task should be performed
-
The QueuedSourceBuffer on which the garbage collection task should run
-
The maximum time margin authorized for the buffer behind the current position
-
The maximum time margin authorized for the buffer ahead of the current position
Basically, each times the given clock ticks, the BufferGarbageCollector will ensure that the volume of data before and ahead of the current position does not grow into a larger value than what is configured.
For now, its code is completely decoupled for the rest of the code in that directory. This is why it is not included in the schema included on the top of this page.
The SegmentInventory
The SegmentInventory
keeps track of which segments are currently bufferized
to avoid unnecessary re-downloads.
You can have more information on it in the SegmentInventory documentation.