mirror of
https://github.com/samsonjs/media.git
synced 2026-04-10 12:05:47 +00:00
Handle preload callbacks asynchronously in PreloadMediaSource
When there is an exception thrown from the `LoadTask`, the `Loader` will call `Loader.Callback.onLoadError`. Some implementations of `onLoadError` method may call `MediaPeriod.onContinueLoadingRequested`, and in the `PreloadMediaSource`, its `PreloadMediaPeriodCallback` will be triggered and then it can further call `continueLoading` if it finds needed. However the above process is currently done synchronously, which will cause problem. By calling `continueLoading`, the `Loader` is set with a `currentTask`, and when that long sync logic in `Loader.Callback.onLoadError` ends, the `Loader` will immediately retry, and then a non-null `currentTask` will cause the `IllegalStateException`.
Issue: androidx/media#1568
PiperOrigin-RevId: 662550622
(cherry picked from commit cd532c5fb2)
This commit is contained in:
parent
07e9c659d7
commit
f139d709c7
2 changed files with 64 additions and 53 deletions
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
* Common Library:
|
||||
* ExoPlayer:
|
||||
* Handle preload callbacks asynchronously in `PreloadMediaSource`
|
||||
([#1568](https://github.com/androidx/media/issues/1568)).
|
||||
* Transformer:
|
||||
* Track Selection:
|
||||
* Extractors:
|
||||
|
|
|
|||
|
|
@ -293,25 +293,28 @@ public final class PreloadMediaSource extends WrappingMediaSource {
|
|||
protected void onChildSourceInfoRefreshed(Timeline newTimeline) {
|
||||
this.timeline = newTimeline;
|
||||
refreshSourceInfo(newTimeline);
|
||||
if (isUsedByPlayer() || onSourcePreparedNotified) {
|
||||
return;
|
||||
}
|
||||
onSourcePreparedNotified = true;
|
||||
if (!preloadControl.onSourcePrepared(this)) {
|
||||
return;
|
||||
}
|
||||
Pair<Object, Long> periodPosition =
|
||||
newTimeline.getPeriodPositionUs(
|
||||
new Timeline.Window(),
|
||||
new Timeline.Period(),
|
||||
/* windowIndex= */ 0,
|
||||
/* windowPositionUs= */ startPositionUs);
|
||||
MediaPeriodId mediaPeriodId = new MediaPeriodId(periodPosition.first);
|
||||
PreloadMediaPeriod mediaPeriod =
|
||||
PreloadMediaSource.this.createPeriod(mediaPeriodId, allocator, periodPosition.second);
|
||||
mediaPeriod.preload(
|
||||
new PreloadMediaPeriodCallback(periodPosition.second),
|
||||
/* positionUs= */ periodPosition.second);
|
||||
preloadHandler.post(
|
||||
() -> {
|
||||
if (isUsedByPlayer() || onSourcePreparedNotified) {
|
||||
return;
|
||||
}
|
||||
onSourcePreparedNotified = true;
|
||||
if (!preloadControl.onSourcePrepared(this)) {
|
||||
return;
|
||||
}
|
||||
Pair<Object, Long> periodPosition =
|
||||
newTimeline.getPeriodPositionUs(
|
||||
new Timeline.Window(),
|
||||
new Timeline.Period(),
|
||||
/* windowIndex= */ 0,
|
||||
/* windowPositionUs= */ startPositionUs);
|
||||
MediaPeriodId mediaPeriodId = new MediaPeriodId(periodPosition.first);
|
||||
PreloadMediaPeriod mediaPeriod =
|
||||
PreloadMediaSource.this.createPeriod(mediaPeriodId, allocator, periodPosition.second);
|
||||
mediaPeriod.preload(
|
||||
new PreloadMediaPeriodCallback(periodPosition.second),
|
||||
/* positionUs= */ periodPosition.second);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -405,44 +408,50 @@ public final class PreloadMediaSource extends WrappingMediaSource {
|
|||
@Override
|
||||
public void onPrepared(MediaPeriod mediaPeriod) {
|
||||
prepared = true;
|
||||
if (isUsedByPlayer()) {
|
||||
return;
|
||||
}
|
||||
PreloadMediaPeriod preloadMediaPeriod = (PreloadMediaPeriod) mediaPeriod;
|
||||
TrackGroupArray trackGroups = preloadMediaPeriod.getTrackGroups();
|
||||
@Nullable TrackSelectorResult trackSelectorResult = null;
|
||||
MediaPeriodKey key = checkNotNull(preloadingMediaPeriodAndKey).second;
|
||||
try {
|
||||
trackSelectorResult =
|
||||
trackSelector.selectTracks(
|
||||
rendererCapabilities, trackGroups, key.mediaPeriodId, checkNotNull(timeline));
|
||||
} catch (ExoPlaybackException e) {
|
||||
Log.e(TAG, "Failed to select tracks", e);
|
||||
}
|
||||
if (trackSelectorResult != null) {
|
||||
preloadMediaPeriod.selectTracksForPreloading(
|
||||
trackSelectorResult.selections, periodStartPositionUs);
|
||||
if (preloadControl.onTracksSelected(PreloadMediaSource.this)) {
|
||||
preloadMediaPeriod.continueLoading(
|
||||
new LoadingInfo.Builder().setPlaybackPositionUs(periodStartPositionUs).build());
|
||||
}
|
||||
}
|
||||
preloadHandler.post(
|
||||
() -> {
|
||||
if (isUsedByPlayer()) {
|
||||
return;
|
||||
}
|
||||
PreloadMediaPeriod preloadMediaPeriod = (PreloadMediaPeriod) mediaPeriod;
|
||||
TrackGroupArray trackGroups = preloadMediaPeriod.getTrackGroups();
|
||||
@Nullable TrackSelectorResult trackSelectorResult = null;
|
||||
MediaPeriodKey key = checkNotNull(preloadingMediaPeriodAndKey).second;
|
||||
try {
|
||||
trackSelectorResult =
|
||||
trackSelector.selectTracks(
|
||||
rendererCapabilities, trackGroups, key.mediaPeriodId, checkNotNull(timeline));
|
||||
} catch (ExoPlaybackException e) {
|
||||
Log.e(TAG, "Failed to select tracks", e);
|
||||
}
|
||||
if (trackSelectorResult != null) {
|
||||
preloadMediaPeriod.selectTracksForPreloading(
|
||||
trackSelectorResult.selections, periodStartPositionUs);
|
||||
if (preloadControl.onTracksSelected(PreloadMediaSource.this)) {
|
||||
preloadMediaPeriod.continueLoading(
|
||||
new LoadingInfo.Builder().setPlaybackPositionUs(periodStartPositionUs).build());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onContinueLoadingRequested(MediaPeriod mediaPeriod) {
|
||||
if (isUsedByPlayer()) {
|
||||
return;
|
||||
}
|
||||
PreloadMediaPeriod preloadMediaPeriod = (PreloadMediaPeriod) mediaPeriod;
|
||||
if (prepared && mediaPeriod.getBufferedPositionUs() == C.TIME_END_OF_SOURCE) {
|
||||
preloadControl.onLoadedToTheEndOfSource(PreloadMediaSource.this);
|
||||
} else if (!prepared
|
||||
|| preloadControl.onContinueLoadingRequested(
|
||||
PreloadMediaSource.this, preloadMediaPeriod.getBufferedPositionUs())) {
|
||||
preloadMediaPeriod.continueLoading(
|
||||
new LoadingInfo.Builder().setPlaybackPositionUs(periodStartPositionUs).build());
|
||||
}
|
||||
preloadHandler.post(
|
||||
() -> {
|
||||
if (isUsedByPlayer()) {
|
||||
return;
|
||||
}
|
||||
PreloadMediaPeriod preloadMediaPeriod = (PreloadMediaPeriod) mediaPeriod;
|
||||
if (prepared && mediaPeriod.getBufferedPositionUs() == C.TIME_END_OF_SOURCE) {
|
||||
preloadControl.onLoadedToTheEndOfSource(PreloadMediaSource.this);
|
||||
} else if (!prepared
|
||||
|| preloadControl.onContinueLoadingRequested(
|
||||
PreloadMediaSource.this, preloadMediaPeriod.getBufferedPositionUs())) {
|
||||
preloadMediaPeriod.continueLoading(
|
||||
new LoadingInfo.Builder().setPlaybackPositionUs(periodStartPositionUs).build());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue