This directory contains the PlayerCore
class and related classes. These classes are part of the Fuchsia media player implementation.
PlayerCore
is concerned with managing a graph that contains the demux, decoders, renderers and other components that constitute a media player graph. It deals with graph building, priming, timeline control, flushing, end-of-stream and related issues. It aggregates some aspects of the underlying components, leaving other aspects to direct communication between those compenents and the client (PlayerImpl
, specifically).
PlayerCore
delegates many of its concerns to subordinate segments, each of which manages a subset (segment) of the graph. A PlayerCore
has at most one source segment (defined by the SourceSegment
abstract class) and at most one sink segment (defined by the SinkSegment
abstract class) per medium (audio, video, text, subpicture).
The client creates the segments it wants the player to use and registers them with the player. For example, PlayerImpl
typically wants the player to host a demux, so it will create a DemuxSourceSegment
and register it with the player using PlayerCore::SetSourceSegment
.
Likewise, PlayerImpl
wants content rendered, so it creates one or more RendererSinkSegment
objects and registers them using PlayerCore::SetSinkSegment
. RendererSinkSegment
uses the renderer provided to it in its constructor, which means PlayerImpl
has to create that, too. This creates the opportunity for PlayerImpl
to have its own relationship with a renderer that doesn‘t concern the player or the sink segments. For example, PlayerImpl
can control gain on the audio renderer directly and doesn’t need PlayerCore
or RendererSinkSegment
to help with that. The video renderer reports video geometry and supports the creation of Scenic views, both aspects of its direct relationship with PlayerImpl
.
DemuxSourceSegment
is a source segment that hosts a demux. Its job is to add the demux to the graph, enumerate the demux‘s elementary streams for the player and control the demux on behalf of the player. The DemuxSourceSegment
constructor accepts a demux, so PlayerImpl
has to create the demux. This allows PlayerImpl
to decide how it wants to set up the demux and allows PlayerImpl
to have a relationship with the demux that doesn’t involve the player. For example, the player doesn't concern itself with metadata, which PlayerImpl
obtains directly from the demux.
RenderSinkSegment
is a sink segment that hosts a renderer. Its job is to add the renderer to the graph and insert whatever type conversion nodes (e.g. decoder) required to convert the elementary stream to a type that the renderer can handle. It also controls the renderer on behalf of the player. The RenderSinkSegment
accepts a renderer, so PlayerImpl
has to create the renderer and can talk to the renderer directly. This allows RenderSinkSegment
and PlayerCore
to be ignorant of the medium-specific aspects of the renderers. Neither RenderSinkSegment
nor PlayerCore
concern themselves with gain control, view creation or video geometry.
PlayerCore
will eventually be dynamic in the sense that it will handle precisely-timed replacement of segments while playback is underway. This will enable features such as gapless transitions from one source to another and gapless rerouting to renderers.
In order to enable routing of elementary streams to multiple renderers concurrently, a new sink segment will be created that aggregates multiple subordinate sink segments. This enables fanout to multiple renderers without complicating the PlayerCore
class.
Currently, the only source segment implemented is DemuxSourceSegment
, which hosts a demux. A new source segment will be implemented that handles FIDL sources that supply separate elementary streams.