Document Renderer and BaseRenderer in more detail

PiperOrigin-RevId: 651008509
This commit is contained in:
tonihei 2024-07-10 07:21:37 -07:00 committed by Copybara-Service
parent f673ef43b4
commit e8778d77fa
2 changed files with 109 additions and 1 deletions

View File

@ -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 {

View File

@ -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 {