1 /* 2 * Copyright (C) 2017 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 androidx.annotation.Nullable; 19 import com.google.android.exoplayer2.C; 20 import com.google.android.exoplayer2.Format; 21 import com.google.android.exoplayer2.Player; 22 import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; 23 import com.google.android.exoplayer2.util.Assertions; 24 import com.google.android.exoplayer2.util.CopyOnWriteMultiset; 25 import com.google.android.exoplayer2.util.MediaSourceEventDispatcher; 26 import java.io.IOException; 27 28 /** Interface for callbacks to be notified of {@link MediaSource} events. */ 29 public interface MediaSourceEventListener { 30 31 /** 32 * Called when a media period is created by the media source. 33 * 34 * @param windowIndex The window index in the timeline this media period belongs to. 35 * @param mediaPeriodId The {@link MediaPeriodId} of the created media period. 36 */ onMediaPeriodCreated(int windowIndex, MediaPeriodId mediaPeriodId)37 default void onMediaPeriodCreated(int windowIndex, MediaPeriodId mediaPeriodId) {} 38 39 /** 40 * Called when a media period is released by the media source. 41 * 42 * @param windowIndex The window index in the timeline this media period belongs to. 43 * @param mediaPeriodId The {@link MediaPeriodId} of the released media period. 44 */ onMediaPeriodReleased(int windowIndex, MediaPeriodId mediaPeriodId)45 default void onMediaPeriodReleased(int windowIndex, MediaPeriodId mediaPeriodId) {} 46 47 /** 48 * Called when a load begins. 49 * 50 * @param windowIndex The window index in the timeline of the media source this load belongs to. 51 * @param mediaPeriodId The {@link MediaPeriodId} this load belongs to. Null if the load does not 52 * belong to a specific media period. 53 * @param loadEventInfo The {@link LoadEventInfo} corresponding to the event. The value of {@link 54 * LoadEventInfo#uri} won't reflect potential redirection yet and {@link 55 * LoadEventInfo#responseHeaders} will be empty. 56 * @param mediaLoadData The {@link MediaLoadData} defining the data being loaded. 57 */ onLoadStarted( int windowIndex, @Nullable MediaPeriodId mediaPeriodId, LoadEventInfo loadEventInfo, MediaLoadData mediaLoadData)58 default void onLoadStarted( 59 int windowIndex, 60 @Nullable MediaPeriodId mediaPeriodId, 61 LoadEventInfo loadEventInfo, 62 MediaLoadData mediaLoadData) {} 63 64 /** 65 * Called when a load ends. 66 * 67 * @param windowIndex The window index in the timeline of the media source this load belongs to. 68 * @param mediaPeriodId The {@link MediaPeriodId} this load belongs to. Null if the load does not 69 * belong to a specific media period. 70 * @param loadEventInfo The {@link LoadEventInfo} corresponding to the event. The values of {@link 71 * LoadEventInfo#elapsedRealtimeMs} and {@link LoadEventInfo#bytesLoaded} are relative to the 72 * corresponding {@link #onLoadStarted(int, MediaPeriodId, LoadEventInfo, MediaLoadData)} 73 * event. 74 * @param mediaLoadData The {@link MediaLoadData} defining the data being loaded. 75 */ onLoadCompleted( int windowIndex, @Nullable MediaPeriodId mediaPeriodId, LoadEventInfo loadEventInfo, MediaLoadData mediaLoadData)76 default void onLoadCompleted( 77 int windowIndex, 78 @Nullable MediaPeriodId mediaPeriodId, 79 LoadEventInfo loadEventInfo, 80 MediaLoadData mediaLoadData) {} 81 82 /** 83 * Called when a load is canceled. 84 * 85 * @param windowIndex The window index in the timeline of the media source this load belongs to. 86 * @param mediaPeriodId The {@link MediaPeriodId} this load belongs to. Null if the load does not 87 * belong to a specific media period. 88 * @param loadEventInfo The {@link LoadEventInfo} corresponding to the event. The values of {@link 89 * LoadEventInfo#elapsedRealtimeMs} and {@link LoadEventInfo#bytesLoaded} are relative to the 90 * corresponding {@link #onLoadStarted(int, MediaPeriodId, LoadEventInfo, MediaLoadData)} 91 * event. 92 * @param mediaLoadData The {@link MediaLoadData} defining the data being loaded. 93 */ onLoadCanceled( int windowIndex, @Nullable MediaPeriodId mediaPeriodId, LoadEventInfo loadEventInfo, MediaLoadData mediaLoadData)94 default void onLoadCanceled( 95 int windowIndex, 96 @Nullable MediaPeriodId mediaPeriodId, 97 LoadEventInfo loadEventInfo, 98 MediaLoadData mediaLoadData) {} 99 100 /** 101 * Called when a load error occurs. 102 * 103 * <p>The error may or may not have resulted in the load being canceled, as indicated by the 104 * {@code wasCanceled} parameter. If the load was canceled, {@link #onLoadCanceled} will 105 * <em>not</em> be called in addition to this method. 106 * 107 * <p>This method being called does not indicate that playback has failed, or that it will fail. 108 * The player may be able to recover from the error and continue. Hence applications should 109 * <em>not</em> implement this method to display a user visible error or initiate an application 110 * level retry ({@link Player.EventListener#onPlayerError} is the appropriate place to implement 111 * such behavior). This method is called to provide the application with an opportunity to log the 112 * error if it wishes to do so. 113 * 114 * @param windowIndex The window index in the timeline of the media source this load belongs to. 115 * @param mediaPeriodId The {@link MediaPeriodId} this load belongs to. Null if the load does not 116 * belong to a specific media period. 117 * @param loadEventInfo The {@link LoadEventInfo} corresponding to the event. The values of {@link 118 * LoadEventInfo#elapsedRealtimeMs} and {@link LoadEventInfo#bytesLoaded} are relative to the 119 * corresponding {@link #onLoadStarted(int, MediaPeriodId, LoadEventInfo, MediaLoadData)} 120 * event. 121 * @param mediaLoadData The {@link MediaLoadData} defining the data being loaded. 122 * @param error The load error. 123 * @param wasCanceled Whether the load was canceled as a result of the error. 124 */ onLoadError( int windowIndex, @Nullable MediaPeriodId mediaPeriodId, LoadEventInfo loadEventInfo, MediaLoadData mediaLoadData, IOException error, boolean wasCanceled)125 default void onLoadError( 126 int windowIndex, 127 @Nullable MediaPeriodId mediaPeriodId, 128 LoadEventInfo loadEventInfo, 129 MediaLoadData mediaLoadData, 130 IOException error, 131 boolean wasCanceled) {} 132 133 /** 134 * Called when a media period is first being read from. 135 * 136 * @param windowIndex The window index in the timeline this media period belongs to. 137 * @param mediaPeriodId The {@link MediaPeriodId} of the media period being read from. 138 */ onReadingStarted(int windowIndex, MediaPeriodId mediaPeriodId)139 default void onReadingStarted(int windowIndex, MediaPeriodId mediaPeriodId) {} 140 141 /** 142 * Called when data is removed from the back of a media buffer, typically so that it can be 143 * re-buffered in a different format. 144 * 145 * @param windowIndex The window index in the timeline of the media source this load belongs to. 146 * @param mediaPeriodId The {@link MediaPeriodId} the media belongs to. 147 * @param mediaLoadData The {@link MediaLoadData} defining the media being discarded. 148 */ onUpstreamDiscarded( int windowIndex, MediaPeriodId mediaPeriodId, MediaLoadData mediaLoadData)149 default void onUpstreamDiscarded( 150 int windowIndex, MediaPeriodId mediaPeriodId, MediaLoadData mediaLoadData) {} 151 152 /** 153 * Called when a downstream format change occurs (i.e. when the format of the media being read 154 * from one or more {@link SampleStream}s provided by the source changes). 155 * 156 * @param windowIndex The window index in the timeline of the media source this load belongs to. 157 * @param mediaPeriodId The {@link MediaPeriodId} the media belongs to. 158 * @param mediaLoadData The {@link MediaLoadData} defining the newly selected downstream data. 159 */ onDownstreamFormatChanged( int windowIndex, @Nullable MediaPeriodId mediaPeriodId, MediaLoadData mediaLoadData)160 default void onDownstreamFormatChanged( 161 int windowIndex, @Nullable MediaPeriodId mediaPeriodId, MediaLoadData mediaLoadData) {} 162 163 /** @deprecated Use {@link MediaSourceEventDispatcher} directly instead. */ 164 @Deprecated 165 final class EventDispatcher extends MediaSourceEventDispatcher { 166 EventDispatcher()167 public EventDispatcher() { 168 super(); 169 } 170 EventDispatcher( CopyOnWriteMultiset<ListenerInfo> listeners, int windowIndex, @Nullable MediaPeriodId mediaPeriodId, long mediaTimeOffsetMs)171 private EventDispatcher( 172 CopyOnWriteMultiset<ListenerInfo> listeners, 173 int windowIndex, 174 @Nullable MediaPeriodId mediaPeriodId, 175 long mediaTimeOffsetMs) { 176 super(listeners, windowIndex, mediaPeriodId, mediaTimeOffsetMs); 177 } 178 179 @Override withParameters( int windowIndex, @Nullable MediaPeriodId mediaPeriodId, long mediaTimeOffsetMs)180 public EventDispatcher withParameters( 181 int windowIndex, @Nullable MediaPeriodId mediaPeriodId, long mediaTimeOffsetMs) { 182 return new EventDispatcher(listenerInfos, windowIndex, mediaPeriodId, mediaTimeOffsetMs); 183 } 184 mediaPeriodCreated()185 public void mediaPeriodCreated() { 186 dispatch( 187 (listener, windowIndex, mediaPeriodId) -> 188 listener.onMediaPeriodCreated(windowIndex, Assertions.checkNotNull(mediaPeriodId)), 189 MediaSourceEventListener.class); 190 } 191 mediaPeriodReleased()192 public void mediaPeriodReleased() { 193 dispatch( 194 (listener, windowIndex, mediaPeriodId) -> 195 listener.onMediaPeriodReleased(windowIndex, Assertions.checkNotNull(mediaPeriodId)), 196 MediaSourceEventListener.class); 197 } 198 loadStarted(LoadEventInfo loadEventInfo, int dataType)199 public void loadStarted(LoadEventInfo loadEventInfo, int dataType) { 200 loadStarted( 201 loadEventInfo, 202 dataType, 203 /* trackType= */ C.TRACK_TYPE_UNKNOWN, 204 /* trackFormat= */ null, 205 /* trackSelectionReason= */ C.SELECTION_REASON_UNKNOWN, 206 /* trackSelectionData= */ null, 207 /* mediaStartTimeUs= */ C.TIME_UNSET, 208 /* mediaEndTimeUs= */ C.TIME_UNSET); 209 } 210 loadStarted( LoadEventInfo loadEventInfo, int dataType, int trackType, @Nullable Format trackFormat, int trackSelectionReason, @Nullable Object trackSelectionData, long mediaStartTimeUs, long mediaEndTimeUs)211 public void loadStarted( 212 LoadEventInfo loadEventInfo, 213 int dataType, 214 int trackType, 215 @Nullable Format trackFormat, 216 int trackSelectionReason, 217 @Nullable Object trackSelectionData, 218 long mediaStartTimeUs, 219 long mediaEndTimeUs) { 220 loadStarted( 221 loadEventInfo, 222 new MediaLoadData( 223 dataType, 224 trackType, 225 trackFormat, 226 trackSelectionReason, 227 trackSelectionData, 228 adjustMediaTime(mediaStartTimeUs), 229 adjustMediaTime(mediaEndTimeUs))); 230 } 231 loadStarted(LoadEventInfo loadEventInfo, MediaLoadData mediaLoadData)232 public void loadStarted(LoadEventInfo loadEventInfo, MediaLoadData mediaLoadData) { 233 dispatch( 234 (listener, windowIndex, mediaPeriodId) -> 235 listener.onLoadStarted(windowIndex, mediaPeriodId, loadEventInfo, mediaLoadData), 236 MediaSourceEventListener.class); 237 } 238 loadCompleted(LoadEventInfo loadEventInfo, int dataType)239 public void loadCompleted(LoadEventInfo loadEventInfo, int dataType) { 240 loadCompleted( 241 loadEventInfo, 242 dataType, 243 /* trackType= */ C.TRACK_TYPE_UNKNOWN, 244 /* trackFormat= */ null, 245 /* trackSelectionReason= */ C.SELECTION_REASON_UNKNOWN, 246 /* trackSelectionData= */ null, 247 /* mediaStartTimeUs= */ C.TIME_UNSET, 248 /* mediaEndTimeUs= */ C.TIME_UNSET); 249 } 250 loadCompleted( LoadEventInfo loadEventInfo, int dataType, int trackType, @Nullable Format trackFormat, int trackSelectionReason, @Nullable Object trackSelectionData, long mediaStartTimeUs, long mediaEndTimeUs)251 public void loadCompleted( 252 LoadEventInfo loadEventInfo, 253 int dataType, 254 int trackType, 255 @Nullable Format trackFormat, 256 int trackSelectionReason, 257 @Nullable Object trackSelectionData, 258 long mediaStartTimeUs, 259 long mediaEndTimeUs) { 260 loadCompleted( 261 loadEventInfo, 262 new MediaLoadData( 263 dataType, 264 trackType, 265 trackFormat, 266 trackSelectionReason, 267 trackSelectionData, 268 adjustMediaTime(mediaStartTimeUs), 269 adjustMediaTime(mediaEndTimeUs))); 270 } 271 loadCompleted(LoadEventInfo loadEventInfo, MediaLoadData mediaLoadData)272 public void loadCompleted(LoadEventInfo loadEventInfo, MediaLoadData mediaLoadData) { 273 dispatch( 274 (listener, windowIndex, mediaPeriodId) -> 275 listener.onLoadCompleted(windowIndex, mediaPeriodId, loadEventInfo, mediaLoadData), 276 MediaSourceEventListener.class); 277 } 278 loadCanceled(LoadEventInfo loadEventInfo, int dataType)279 public void loadCanceled(LoadEventInfo loadEventInfo, int dataType) { 280 loadCanceled( 281 loadEventInfo, 282 dataType, 283 /* trackType= */ C.TRACK_TYPE_UNKNOWN, 284 /* trackFormat= */ null, 285 /* trackSelectionReason= */ C.SELECTION_REASON_UNKNOWN, 286 /* trackSelectionData= */ null, 287 /* mediaStartTimeUs= */ C.TIME_UNSET, 288 /* mediaEndTimeUs= */ C.TIME_UNSET); 289 } 290 loadCanceled( LoadEventInfo loadEventInfo, int dataType, int trackType, @Nullable Format trackFormat, int trackSelectionReason, @Nullable Object trackSelectionData, long mediaStartTimeUs, long mediaEndTimeUs)291 public void loadCanceled( 292 LoadEventInfo loadEventInfo, 293 int dataType, 294 int trackType, 295 @Nullable Format trackFormat, 296 int trackSelectionReason, 297 @Nullable Object trackSelectionData, 298 long mediaStartTimeUs, 299 long mediaEndTimeUs) { 300 loadCanceled( 301 loadEventInfo, 302 new MediaLoadData( 303 dataType, 304 trackType, 305 trackFormat, 306 trackSelectionReason, 307 trackSelectionData, 308 adjustMediaTime(mediaStartTimeUs), 309 adjustMediaTime(mediaEndTimeUs))); 310 } 311 loadCanceled(LoadEventInfo loadEventInfo, MediaLoadData mediaLoadData)312 public void loadCanceled(LoadEventInfo loadEventInfo, MediaLoadData mediaLoadData) { 313 dispatch( 314 (listener, windowIndex, mediaPeriodId) -> 315 listener.onLoadCanceled(windowIndex, mediaPeriodId, loadEventInfo, mediaLoadData), 316 MediaSourceEventListener.class); 317 } 318 loadError( LoadEventInfo loadEventInfo, int dataType, IOException error, boolean wasCanceled)319 public void loadError( 320 LoadEventInfo loadEventInfo, int dataType, IOException error, boolean wasCanceled) { 321 loadError( 322 loadEventInfo, 323 dataType, 324 /* trackType= */ C.TRACK_TYPE_UNKNOWN, 325 /* trackFormat= */ null, 326 /* trackSelectionReason= */ C.SELECTION_REASON_UNKNOWN, 327 /* trackSelectionData= */ null, 328 /* mediaStartTimeUs= */ C.TIME_UNSET, 329 /* mediaEndTimeUs= */ C.TIME_UNSET, 330 error, 331 wasCanceled); 332 } 333 loadError( LoadEventInfo loadEventInfo, int dataType, int trackType, @Nullable Format trackFormat, int trackSelectionReason, @Nullable Object trackSelectionData, long mediaStartTimeUs, long mediaEndTimeUs, IOException error, boolean wasCanceled)334 public void loadError( 335 LoadEventInfo loadEventInfo, 336 int dataType, 337 int trackType, 338 @Nullable Format trackFormat, 339 int trackSelectionReason, 340 @Nullable Object trackSelectionData, 341 long mediaStartTimeUs, 342 long mediaEndTimeUs, 343 IOException error, 344 boolean wasCanceled) { 345 loadError( 346 loadEventInfo, 347 new MediaLoadData( 348 dataType, 349 trackType, 350 trackFormat, 351 trackSelectionReason, 352 trackSelectionData, 353 adjustMediaTime(mediaStartTimeUs), 354 adjustMediaTime(mediaEndTimeUs)), 355 error, 356 wasCanceled); 357 } 358 loadError( LoadEventInfo loadEventInfo, MediaLoadData mediaLoadData, IOException error, boolean wasCanceled)359 public void loadError( 360 LoadEventInfo loadEventInfo, 361 MediaLoadData mediaLoadData, 362 IOException error, 363 boolean wasCanceled) { 364 dispatch( 365 (listener, windowIndex, mediaPeriodId) -> 366 listener.onLoadError( 367 windowIndex, mediaPeriodId, loadEventInfo, mediaLoadData, error, wasCanceled), 368 MediaSourceEventListener.class); 369 } 370 readingStarted()371 public void readingStarted() { 372 dispatch( 373 (listener, windowIndex, mediaPeriodId) -> 374 listener.onReadingStarted(windowIndex, Assertions.checkNotNull(mediaPeriodId)), 375 MediaSourceEventListener.class); 376 } 377 upstreamDiscarded(int trackType, long mediaStartTimeUs, long mediaEndTimeUs)378 public void upstreamDiscarded(int trackType, long mediaStartTimeUs, long mediaEndTimeUs) { 379 upstreamDiscarded( 380 new MediaLoadData( 381 C.DATA_TYPE_MEDIA, 382 trackType, 383 /* trackFormat= */ null, 384 C.SELECTION_REASON_ADAPTIVE, 385 /* trackSelectionData= */ null, 386 adjustMediaTime(mediaStartTimeUs), 387 adjustMediaTime(mediaEndTimeUs))); 388 } 389 upstreamDiscarded(MediaLoadData mediaLoadData)390 public void upstreamDiscarded(MediaLoadData mediaLoadData) { 391 dispatch( 392 (listener, windowIndex, mediaPeriodId) -> 393 listener.onUpstreamDiscarded( 394 windowIndex, Assertions.checkNotNull(mediaPeriodId), mediaLoadData), 395 MediaSourceEventListener.class); 396 } 397 downstreamFormatChanged( int trackType, @Nullable Format trackFormat, int trackSelectionReason, @Nullable Object trackSelectionData, long mediaTimeUs)398 public void downstreamFormatChanged( 399 int trackType, 400 @Nullable Format trackFormat, 401 int trackSelectionReason, 402 @Nullable Object trackSelectionData, 403 long mediaTimeUs) { 404 downstreamFormatChanged( 405 new MediaLoadData( 406 C.DATA_TYPE_MEDIA, 407 trackType, 408 trackFormat, 409 trackSelectionReason, 410 trackSelectionData, 411 adjustMediaTime(mediaTimeUs), 412 /* mediaEndTimeMs= */ C.TIME_UNSET)); 413 } 414 downstreamFormatChanged(MediaLoadData mediaLoadData)415 public void downstreamFormatChanged(MediaLoadData mediaLoadData) { 416 dispatch( 417 (listener, windowIndex, mediaPeriodId) -> 418 listener.onDownstreamFormatChanged(windowIndex, mediaPeriodId, mediaLoadData), 419 MediaSourceEventListener.class); 420 } 421 adjustMediaTime(long mediaTimeUs)422 private long adjustMediaTime(long mediaTimeUs) { 423 return adjustMediaTime(mediaTimeUs, mediaTimeOffsetMs); 424 } 425 } 426 } 427