1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package org.mozilla.thirdparty.com.google.android.exoplayer2; 17 18 import androidx.annotation.Nullable; 19 import org.mozilla.thirdparty.com.google.android.exoplayer2.source.SampleStream; 20 import org.mozilla.thirdparty.com.google.android.exoplayer2.util.Assertions; 21 import org.mozilla.thirdparty.com.google.android.exoplayer2.util.MediaClock; 22 import java.io.IOException; 23 import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 24 25 /** 26 * A {@link Renderer} implementation whose track type is {@link C#TRACK_TYPE_NONE} and does not 27 * consume data from its {@link SampleStream}. 28 */ 29 public abstract class NoSampleRenderer implements Renderer, RendererCapabilities { 30 31 @MonotonicNonNull private RendererConfiguration configuration; 32 private int index; 33 private int state; 34 @Nullable private SampleStream stream; 35 private boolean streamIsFinal; 36 37 @Override getTrackType()38 public final int getTrackType() { 39 return C.TRACK_TYPE_NONE; 40 } 41 42 @Override getCapabilities()43 public final RendererCapabilities getCapabilities() { 44 return this; 45 } 46 47 @Override setIndex(int index)48 public final void setIndex(int index) { 49 this.index = index; 50 } 51 52 @Override 53 @Nullable getMediaClock()54 public MediaClock getMediaClock() { 55 return null; 56 } 57 58 @Override getState()59 public final int getState() { 60 return state; 61 } 62 63 /** 64 * Replaces the {@link SampleStream} that will be associated with this renderer. 65 * <p> 66 * This method may be called when the renderer is in the following states: 67 * {@link #STATE_DISABLED}. 68 * 69 * @param configuration The renderer configuration. 70 * @param formats The enabled formats. Should be empty. 71 * @param stream The {@link SampleStream} from which the renderer should consume. 72 * @param positionUs The player's current position. 73 * @param joining Whether this renderer is being enabled to join an ongoing playback. 74 * @param offsetUs The offset that should be subtracted from {@code positionUs} 75 * to get the playback position with respect to the media. 76 * @throws ExoPlaybackException If an error occurs. 77 */ 78 @Override enable(RendererConfiguration configuration, Format[] formats, SampleStream stream, long positionUs, boolean joining, long offsetUs)79 public final void enable(RendererConfiguration configuration, Format[] formats, 80 SampleStream stream, long positionUs, boolean joining, long offsetUs) 81 throws ExoPlaybackException { 82 Assertions.checkState(state == STATE_DISABLED); 83 this.configuration = configuration; 84 state = STATE_ENABLED; 85 onEnabled(joining); 86 replaceStream(formats, stream, offsetUs); 87 onPositionReset(positionUs, joining); 88 } 89 90 @Override start()91 public final void start() throws ExoPlaybackException { 92 Assertions.checkState(state == STATE_ENABLED); 93 state = STATE_STARTED; 94 onStarted(); 95 } 96 97 /** 98 * Replaces the {@link SampleStream} that will be associated with this renderer. 99 * <p> 100 * This method may be called when the renderer is in the following states: 101 * {@link #STATE_ENABLED}, {@link #STATE_STARTED}. 102 * 103 * @param formats The enabled formats. Should be empty. 104 * @param stream The {@link SampleStream} to be associated with this renderer. 105 * @param offsetUs The offset that should be subtracted from {@code positionUs} in 106 * {@link #render(long, long)} to get the playback position with respect to the media. 107 * @throws ExoPlaybackException If an error occurs. 108 */ 109 @Override replaceStream(Format[] formats, SampleStream stream, long offsetUs)110 public final void replaceStream(Format[] formats, SampleStream stream, long offsetUs) 111 throws ExoPlaybackException { 112 Assertions.checkState(!streamIsFinal); 113 this.stream = stream; 114 onRendererOffsetChanged(offsetUs); 115 } 116 117 @Override 118 @Nullable getStream()119 public final SampleStream getStream() { 120 return stream; 121 } 122 123 @Override hasReadStreamToEnd()124 public final boolean hasReadStreamToEnd() { 125 return true; 126 } 127 128 @Override getReadingPositionUs()129 public long getReadingPositionUs() { 130 return C.TIME_END_OF_SOURCE; 131 } 132 133 @Override setCurrentStreamFinal()134 public final void setCurrentStreamFinal() { 135 streamIsFinal = true; 136 } 137 138 @Override isCurrentStreamFinal()139 public final boolean isCurrentStreamFinal() { 140 return streamIsFinal; 141 } 142 143 @Override maybeThrowStreamError()144 public final void maybeThrowStreamError() throws IOException { 145 } 146 147 @Override resetPosition(long positionUs)148 public final void resetPosition(long positionUs) throws ExoPlaybackException { 149 streamIsFinal = false; 150 onPositionReset(positionUs, false); 151 } 152 153 @Override stop()154 public final void stop() throws ExoPlaybackException { 155 Assertions.checkState(state == STATE_STARTED); 156 state = STATE_ENABLED; 157 onStopped(); 158 } 159 160 @Override disable()161 public final void disable() { 162 Assertions.checkState(state == STATE_ENABLED); 163 state = STATE_DISABLED; 164 stream = null; 165 streamIsFinal = false; 166 onDisabled(); 167 } 168 169 @Override reset()170 public final void reset() { 171 Assertions.checkState(state == STATE_DISABLED); 172 onReset(); 173 } 174 175 @Override isReady()176 public boolean isReady() { 177 return true; 178 } 179 180 @Override isEnded()181 public boolean isEnded() { 182 return true; 183 } 184 185 // RendererCapabilities implementation. 186 187 @Override 188 @Capabilities supportsFormat(Format format)189 public int supportsFormat(Format format) throws ExoPlaybackException { 190 return RendererCapabilities.create(FORMAT_UNSUPPORTED_TYPE); 191 } 192 193 @Override 194 @AdaptiveSupport supportsMixedMimeTypeAdaptation()195 public int supportsMixedMimeTypeAdaptation() throws ExoPlaybackException { 196 return ADAPTIVE_NOT_SUPPORTED; 197 } 198 199 // PlayerMessage.Target implementation. 200 201 @Override handleMessage(int what, @Nullable Object object)202 public void handleMessage(int what, @Nullable Object object) throws ExoPlaybackException { 203 // Do nothing. 204 } 205 206 // Methods to be overridden by subclasses. 207 208 /** 209 * Called when the renderer is enabled. 210 * <p> 211 * The default implementation is a no-op. 212 * 213 * @param joining Whether this renderer is being enabled to join an ongoing playback. 214 * @throws ExoPlaybackException If an error occurs. 215 */ onEnabled(boolean joining)216 protected void onEnabled(boolean joining) throws ExoPlaybackException { 217 // Do nothing. 218 } 219 220 /** 221 * Called when the renderer's offset has been changed. 222 * <p> 223 * The default implementation is a no-op. 224 * 225 * @param offsetUs The offset that should be subtracted from {@code positionUs} in 226 * {@link #render(long, long)} to get the playback position with respect to the media. 227 * @throws ExoPlaybackException If an error occurs. 228 */ onRendererOffsetChanged(long offsetUs)229 protected void onRendererOffsetChanged(long offsetUs) throws ExoPlaybackException { 230 // Do nothing. 231 } 232 233 /** 234 * Called when the position is reset. This occurs when the renderer is enabled after 235 * {@link #onRendererOffsetChanged(long)} has been called, and also when a position 236 * discontinuity is encountered. 237 * <p> 238 * The default implementation is a no-op. 239 * 240 * @param positionUs The new playback position in microseconds. 241 * @param joining Whether this renderer is being enabled to join an ongoing playback. 242 * @throws ExoPlaybackException If an error occurs. 243 */ onPositionReset(long positionUs, boolean joining)244 protected void onPositionReset(long positionUs, boolean joining) throws ExoPlaybackException { 245 // Do nothing. 246 } 247 248 /** 249 * Called when the renderer is started. 250 * <p> 251 * The default implementation is a no-op. 252 * 253 * @throws ExoPlaybackException If an error occurs. 254 */ onStarted()255 protected void onStarted() throws ExoPlaybackException { 256 // Do nothing. 257 } 258 259 /** 260 * Called when the renderer is stopped. 261 * <p> 262 * The default implementation is a no-op. 263 * 264 * @throws ExoPlaybackException If an error occurs. 265 */ onStopped()266 protected void onStopped() throws ExoPlaybackException { 267 // Do nothing. 268 } 269 270 /** 271 * Called when the renderer is disabled. 272 * <p> 273 * The default implementation is a no-op. 274 */ onDisabled()275 protected void onDisabled() { 276 // Do nothing. 277 } 278 279 /** 280 * Called when the renderer is reset. 281 * 282 * <p>The default implementation is a no-op. 283 */ onReset()284 protected void onReset() { 285 // Do nothing. 286 } 287 288 // Methods to be called by subclasses. 289 290 /** 291 * Returns the configuration set when the renderer was most recently enabled, or {@code null} if 292 * the renderer has never been enabled. 293 */ 294 @Nullable getConfiguration()295 protected final RendererConfiguration getConfiguration() { 296 return configuration; 297 } 298 299 /** 300 * Returns the index of the renderer within the player. 301 */ getIndex()302 protected final int getIndex() { 303 return index; 304 } 305 306 } 307