Document Renderer and BaseRenderer in more detail
PiperOrigin-RevId: 651008509
This commit is contained in:
parent
f673ef43b4
commit
e8778d77fa
@ -39,7 +39,31 @@ import androidx.media3.exoplayer.source.SampleStream.ReadFlags;
|
||||
import java.io.IOException;
|
||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
|
||||
/** An abstract base class suitable for most {@link Renderer} implementations. */
|
||||
/**
|
||||
* An abstract base class suitable for most {@link Renderer} implementations.
|
||||
*
|
||||
* <p>It converts many of the state transitions explained in {@link Renderer} docs to protected
|
||||
* callbacks and provides utilities to access current state values without tracking them manually:
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@link #onInit}, {@link #onEnabled}, {@link #onStarted}, {@link #onStopped}, {@link
|
||||
* #onDisabled}, {@link #onReset} and {@link #onRelease} are called for the corresponding
|
||||
* {@link Renderer} method.
|
||||
* <li>{@link #onStreamChanged} is called for both the initial stream set via {@link #enable} as
|
||||
* well as subsequent streams set via {@link #replaceStream}.
|
||||
* <li>{@link #onPositionReset} is called for the initial reset via {@link #enable} as well as
|
||||
* subsequent resets via {@link #resetPosition}.
|
||||
* <li>The current {@link SampleStream} can be read with {@link #readSource} or skipped with
|
||||
* {@link #skipSource}. {@link #isSourceReady()} returning {@code true} indicates that samples
|
||||
* are available to be read.
|
||||
* <li>Current state is available with additional getter methods like {@link
|
||||
* #getLastResetPositionUs()}, {@link #getPlayerId()}, {@link #getTimeline()}.
|
||||
* <li>Exceptions can be created with {@link #createRendererException} to fill in additional
|
||||
* metadata about the renderer automatically.
|
||||
* <li>The renderer can call {@link #onRendererCapabilitiesChanged()} to tell the player of a
|
||||
* change in its capabilities, which may lead to new tracks being selected for playback.
|
||||
* </ul>
|
||||
*/
|
||||
@UnstableApi
|
||||
public abstract class BaseRenderer implements Renderer, RendererCapabilities {
|
||||
|
||||
|
@ -58,6 +58,90 @@ import java.util.List;
|
||||
* <p style="align:center"><img
|
||||
* src="https://developer.android.com/static/images/reference/androidx/media3/exoplayer/renderer-states.svg"
|
||||
* alt="Renderer state transitions">
|
||||
*
|
||||
* <h2>Format support</h2>
|
||||
*
|
||||
* The player will select a renderer based on the {@link RendererCapabilities} returned from {@link
|
||||
* #getCapabilities()}. If the capabilities indicate support for a {@link Format}, the renderer is
|
||||
* expected to handle {@link SampleStream} instances containing samples of this {@link Format}.
|
||||
*
|
||||
* <h2>Resource management</h2>
|
||||
*
|
||||
* <p>Renderers should acquire resources like codecs when entering {@link #STATE_ENABLED} for the
|
||||
* first time. As the renderer may transition quickly to and from {@link #STATE_DISABLED}, it is
|
||||
* recommended to hold onto resources even when entering {@link #STATE_DISABLED}. The player will
|
||||
* explicitly call {@link #reset()} if the renderer is no longer needed, at which point any acquired
|
||||
* limited resources should be released.
|
||||
*
|
||||
* <h2>Configuration changes</h2>
|
||||
*
|
||||
* <p>As renderers are created once in the lifetime of a player, they may need to be re-configured
|
||||
* later based on user settings or other environmental changes. This is generally done by handling
|
||||
* {@linkplain PlayerMessage player messages} in {@link #handleMessage}. There are many predefined
|
||||
* common reconfigurations in {@link MessageType}, but custom renderers can add their own handling
|
||||
* as needed.
|
||||
*
|
||||
* <h2>Reading and rendering samples</h2>
|
||||
*
|
||||
* <p>The renderer receives a {@link SampleStream} to read from when {@linkplain #enable enabled}.
|
||||
* When seamlessly transitioning from one item to another, the renderer may get new {@link
|
||||
* SampleStream} instances via {@link #replaceStream}. Note that {@link #replaceStream} may be
|
||||
* called as soon as the {@linkplain C#BUFFER_FLAG_END_OF_STREAM end-of-stream signal} has been read
|
||||
* from the current {@link SampleStream} to allow reading new samples as early as possible. At this
|
||||
* point, the renderer may still be processing samples from the previous stream(s). Once the current
|
||||
* stream has been {@linkplain #setCurrentStreamFinal() marked as final}, no further calls to {@link
|
||||
* #replaceStream} are allowed to happen without first {@link #disable disabling} the renderer
|
||||
* again.
|
||||
*
|
||||
* <p>The player will regularly call {@link #render} to let the renderer make progress. Once the
|
||||
* renderer has prepared its internal pipeline to handle continuous playback progress, it should
|
||||
* report itself as {@link #isReady()}. The player will only transition the renderer to {@link
|
||||
* #STATE_STARTED} if it reports itself as ready. If the renderer is blocked from making progress,
|
||||
* it should return {@code false} from {@link #isReady()}, which will result in a {@link #stop()}
|
||||
* operation back to {@link #STATE_ENABLED}.
|
||||
*
|
||||
* <p>As long as it is in {@link #STATE_STARTED}, the renderer is expected to actively output the
|
||||
* data it is processing in line with the current playback position passed to {@link #render}. The
|
||||
* only exception is the very first sample (for example the first video frame), that is allowed to
|
||||
* be output in {@link #STATE_ENABLED} if the {@code mayRenderStartOfStream} flag was set in {@link
|
||||
* #enable} or later set via {@link #enableMayRenderStartOfStream()}.
|
||||
*
|
||||
* <p>Once the renderer finished all processing it needs to do (that is, no further call to {@link
|
||||
* #render} is needed) and the current stream is {@linkplain #isCurrentStreamFinal() final}, it
|
||||
* should report itself as {@link #isEnded()}.
|
||||
*
|
||||
* <h2>Timestamps and offsets</h2>
|
||||
*
|
||||
* <p>The renderer deals with potentially multiple consecutive input streams and has to handle
|
||||
* position updates and stream transitions. This means there are multiple types of timestamps and
|
||||
* offsets relevant in the context of this class:
|
||||
*
|
||||
* <ul>
|
||||
* <li><b>{@link SampleStream} timestamp</b>: The timestamp associated with each sample read from
|
||||
* a {@link SampleStream}. This corresponds to the time in the {@link Timeline.Period} this
|
||||
* stream belongs to. The current playback context can be obtained by using the {@link
|
||||
* #setTimeline Timeline} and the {@link MediaPeriodId} provided together with each {@link
|
||||
* SampleStream}.
|
||||
* <li><b>Renderer timestamp</b>: The timestamp of the overall playback. This is a continuously
|
||||
* increasing value across all input sample streams and what it passed to {@link #render} as
|
||||
* the current {@code positionUs}.
|
||||
* <li><b>Stream offset</b>: The constant offset between the current <i>{@link SampleStream}
|
||||
* timestamps</i> and the <i>renderer timestamp</i>. This value is provided when setting a new
|
||||
* stream in {@link #enable} or {@link #replaceStream}.
|
||||
* <li><b>Stream start position</b>: The <i>renderer timestamp</i> at which the current {@link
|
||||
* SampleStream} first starts playing. This value is provided when setting a new stream in
|
||||
* {@link #enable} or {@link #replaceStream}. Note that it may be different from the <i>Stream
|
||||
* offset</i> as streams can start at non-zero <i>{@link SampleStream} timestamps</i>.
|
||||
* <li><b>Reset position</b>: The <i>Renderer timestamp</i> at which continuous playback last
|
||||
* started. This is either the <i>stream start position</i> provided in {@link #enable}, or
|
||||
* the position set in any subsequent {@link #resetPosition} call. Note that this value is not
|
||||
* changed when playback transitions seamlessly to a new stream after calling {@link
|
||||
* #replaceStream}. After any position reset, the samples read next are those needed to start
|
||||
* playback at the intended <i>reset position</i>. In some cases, the renderer will encounter
|
||||
* output data before the intended <i>reset position</i> (for example video frames starting
|
||||
* from the previous keyframe). In these cases, the renderer should drop data internally and
|
||||
* only start producing output at the intended <i>reset position</i>.
|
||||
* </ul>
|
||||
*/
|
||||
@UnstableApi
|
||||
public interface Renderer extends PlayerMessage.Target {
|
||||
|
Loading…
x
Reference in New Issue
Block a user