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 com.google.android.exoplayer2.source; 17 18 import com.google.android.exoplayer2.C; 19 import com.google.android.exoplayer2.ExoPlayer; 20 import com.google.android.exoplayer2.SeekParameters; 21 import com.google.android.exoplayer2.Timeline; 22 import com.google.android.exoplayer2.offline.StreamKey; 23 import com.google.android.exoplayer2.source.MediaSource.MediaSourceCaller; 24 import com.google.android.exoplayer2.trackselection.TrackSelection; 25 import java.io.IOException; 26 import java.util.Collections; 27 import java.util.List; 28 import org.checkerframework.checker.nullness.compatqual.NullableType; 29 30 /** 31 * Loads media corresponding to a {@link Timeline.Period}, and allows that media to be read. All 32 * methods are called on the player's internal playback thread, as described in the 33 * {@link ExoPlayer} Javadoc. 34 */ 35 public interface MediaPeriod extends SequenceableLoader { 36 37 /** 38 * A callback to be notified of {@link MediaPeriod} events. 39 */ 40 interface Callback extends SequenceableLoader.Callback<MediaPeriod> { 41 42 /** 43 * Called when preparation completes. 44 * 45 * <p>Called on the playback thread. After invoking this method, the {@link MediaPeriod} can 46 * expect for {@link #selectTracks(TrackSelection[], boolean[], SampleStream[], boolean[], 47 * long)} to be called with the initial track selection. 48 * 49 * @param mediaPeriod The prepared {@link MediaPeriod}. 50 */ onPrepared(MediaPeriod mediaPeriod)51 void onPrepared(MediaPeriod mediaPeriod); 52 } 53 54 /** 55 * Prepares this media period asynchronously. 56 * 57 * <p>{@code callback.onPrepared} is called when preparation completes. If preparation fails, 58 * {@link #maybeThrowPrepareError()} will throw an {@link IOException}. 59 * 60 * <p>If preparation succeeds and results in a source timeline change (e.g. the period duration 61 * becoming known), {@link MediaSourceCaller#onSourceInfoRefreshed(MediaSource, Timeline)} will be 62 * called before {@code callback.onPrepared}. 63 * 64 * @param callback Callback to receive updates from this period, including being notified when 65 * preparation completes. 66 * @param positionUs The expected starting position, in microseconds. 67 */ prepare(Callback callback, long positionUs)68 void prepare(Callback callback, long positionUs); 69 70 /** 71 * Throws an error that's preventing the period from becoming prepared. Does nothing if no such 72 * error exists. 73 * 74 * <p>This method is only called before the period has completed preparation. 75 * 76 * @throws IOException The underlying error. 77 */ maybeThrowPrepareError()78 void maybeThrowPrepareError() throws IOException; 79 80 /** 81 * Returns the {@link TrackGroup}s exposed by the period. 82 * 83 * <p>This method is only called after the period has been prepared. 84 * 85 * @return The {@link TrackGroup}s. 86 */ getTrackGroups()87 TrackGroupArray getTrackGroups(); 88 89 /** 90 * Returns a list of {@link StreamKey StreamKeys} which allow to filter the media in this period 91 * to load only the parts needed to play the provided {@link TrackSelection TrackSelections}. 92 * 93 * <p>This method is only called after the period has been prepared. 94 * 95 * @param trackSelections The {@link TrackSelection TrackSelections} describing the tracks for 96 * which stream keys are requested. 97 * @return The corresponding {@link StreamKey StreamKeys} for the selected tracks, or an empty 98 * list if filtering is not possible and the entire media needs to be loaded to play the 99 * selected tracks. 100 */ getStreamKeys(List<TrackSelection> trackSelections)101 default List<StreamKey> getStreamKeys(List<TrackSelection> trackSelections) { 102 return Collections.emptyList(); 103 } 104 105 /** 106 * Performs a track selection. 107 * 108 * <p>The call receives track {@code selections} for each renderer, {@code mayRetainStreamFlags} 109 * indicating whether the existing {@link SampleStream} can be retained for each selection, and 110 * the existing {@code stream}s themselves. The call will update {@code streams} to reflect the 111 * provided selections, clearing, setting and replacing entries as required. If an existing sample 112 * stream is retained but with the requirement that the consuming renderer be reset, then the 113 * corresponding flag in {@code streamResetFlags} will be set to true. This flag will also be set 114 * if a new sample stream is created. 115 * 116 * <p>Note that previously passed {@link TrackSelection TrackSelections} are no longer valid, and 117 * any references to them must be updated to point to the new selections. 118 * 119 * <p>This method is only called after the period has been prepared. 120 * 121 * @param selections The renderer track selections. 122 * @param mayRetainStreamFlags Flags indicating whether the existing sample stream can be retained 123 * for each track selection. A {@code true} value indicates that the selection is equivalent 124 * to the one that was previously passed, and that the caller does not require that the sample 125 * stream be recreated. If a retained sample stream holds any references to the track 126 * selection then they must be updated to point to the new selection. 127 * @param streams The existing sample streams, which will be updated to reflect the provided 128 * selections. 129 * @param streamResetFlags Will be updated to indicate new sample streams, and sample streams that 130 * have been retained but with the requirement that the consuming renderer be reset. 131 * @param positionUs The current playback position in microseconds. If playback of this period has 132 * not yet started, the value will be the starting position. 133 * @return The actual position at which the tracks were enabled, in microseconds. 134 */ selectTracks( @ullableType TrackSelection[] selections, boolean[] mayRetainStreamFlags, @NullableType SampleStream[] streams, boolean[] streamResetFlags, long positionUs)135 long selectTracks( 136 @NullableType TrackSelection[] selections, 137 boolean[] mayRetainStreamFlags, 138 @NullableType SampleStream[] streams, 139 boolean[] streamResetFlags, 140 long positionUs); 141 142 /** 143 * Discards buffered media up to the specified position. 144 * 145 * <p>This method is only called after the period has been prepared. 146 * 147 * @param positionUs The position in microseconds. 148 * @param toKeyframe If true then for each track discards samples up to the keyframe before or at 149 * the specified position, rather than any sample before or at that position. 150 */ discardBuffer(long positionUs, boolean toKeyframe)151 void discardBuffer(long positionUs, boolean toKeyframe); 152 153 /** 154 * Attempts to read a discontinuity. 155 * 156 * <p>After this method has returned a value other than {@link C#TIME_UNSET}, all {@link 157 * SampleStream}s provided by the period are guaranteed to start from a key frame. 158 * 159 * <p>This method is only called after the period has been prepared and before reading from any 160 * {@link SampleStream}s provided by the period. 161 * 162 * @return If a discontinuity was read then the playback position in microseconds after the 163 * discontinuity. Else {@link C#TIME_UNSET}. 164 */ readDiscontinuity()165 long readDiscontinuity(); 166 167 /** 168 * Attempts to seek to the specified position in microseconds. 169 * 170 * <p>After this method has been called, all {@link SampleStream}s provided by the period are 171 * guaranteed to start from a key frame. 172 * 173 * <p>This method is only called when at least one track is selected. 174 * 175 * @param positionUs The seek position in microseconds. 176 * @return The actual position to which the period was seeked, in microseconds. 177 */ seekToUs(long positionUs)178 long seekToUs(long positionUs); 179 180 /** 181 * Returns the position to which a seek will be performed, given the specified seek position and 182 * {@link SeekParameters}. 183 * 184 * <p>This method is only called after the period has been prepared. 185 * 186 * @param positionUs The seek position in microseconds. 187 * @param seekParameters Parameters that control how the seek is performed. Implementations may 188 * apply seek parameters on a best effort basis. 189 * @return The actual position to which a seek will be performed, in microseconds. 190 */ getAdjustedSeekPositionUs(long positionUs, SeekParameters seekParameters)191 long getAdjustedSeekPositionUs(long positionUs, SeekParameters seekParameters); 192 193 // SequenceableLoader interface. Overridden to provide more specific documentation. 194 195 /** 196 * Returns an estimate of the position up to which data is buffered for the enabled tracks. 197 * 198 * <p>This method is only called when at least one track is selected. 199 * 200 * @return An estimate of the absolute position in microseconds up to which data is buffered, or 201 * {@link C#TIME_END_OF_SOURCE} if the track is fully buffered. 202 */ 203 @Override getBufferedPositionUs()204 long getBufferedPositionUs(); 205 206 /** 207 * Returns the next load time, or {@link C#TIME_END_OF_SOURCE} if loading has finished. 208 * 209 * <p>This method is only called after the period has been prepared. It may be called when no 210 * tracks are selected. 211 */ 212 @Override getNextLoadPositionUs()213 long getNextLoadPositionUs(); 214 215 /** 216 * Attempts to continue loading. 217 * 218 * <p>This method may be called both during and after the period has been prepared. 219 * 220 * <p>A period may call {@link Callback#onContinueLoadingRequested(SequenceableLoader)} on the 221 * {@link Callback} passed to {@link #prepare(Callback, long)} to request that this method be 222 * called when the period is permitted to continue loading data. A period may do this both during 223 * and after preparation. 224 * 225 * @param positionUs The current playback position in microseconds. If playback of this period has 226 * not yet started, the value will be the starting position in this period minus the duration 227 * of any media in previous periods still to be played. 228 * @return True if progress was made, meaning that {@link #getNextLoadPositionUs()} will return a 229 * different value than prior to the call. False otherwise. 230 */ 231 @Override continueLoading(long positionUs)232 boolean continueLoading(long positionUs); 233 234 /** Returns whether the media period is currently loading. */ isLoading()235 boolean isLoading(); 236 237 /** 238 * Re-evaluates the buffer given the playback position. 239 * 240 * <p>This method is only called after the period has been prepared. 241 * 242 * <p>A period may choose to discard buffered media so that it can be re-buffered in a different 243 * quality. 244 * 245 * @param positionUs The current playback position in microseconds. If playback of this period has 246 * not yet started, the value will be the starting position in this period minus the duration 247 * of any media in previous periods still to be played. 248 */ 249 @Override reevaluateBuffer(long positionUs)250 void reevaluateBuffer(long positionUs); 251 } 252