mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08: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 #cherrypick PiperOrigin-RevId: 662550622
This commit is contained in:
parent
0b23285bae
commit
cd532c5fb2
@ -32,6 +32,8 @@
|
|||||||
zero.
|
zero.
|
||||||
* Allow the user to select the built-in speaker for playback on Wear OS
|
* Allow the user to select the built-in speaker for playback on Wear OS
|
||||||
API 35+ (where the device advertises support for this).
|
API 35+ (where the device advertises support for this).
|
||||||
|
* Handle preload callbacks asynchronously in `PreloadMediaSource`
|
||||||
|
([#1568](https://github.com/androidx/media/issues/1568)).
|
||||||
* Transformer:
|
* Transformer:
|
||||||
* Add `SurfaceAssetLoader`, which supports queueing video data to
|
* Add `SurfaceAssetLoader`, which supports queueing video data to
|
||||||
Transformer via a `Surface`.
|
Transformer via a `Surface`.
|
||||||
|
@ -306,26 +306,29 @@ public final class PreloadMediaSource extends WrappingMediaSource {
|
|||||||
protected void onChildSourceInfoRefreshed(Timeline newTimeline) {
|
protected void onChildSourceInfoRefreshed(Timeline newTimeline) {
|
||||||
this.timeline = newTimeline;
|
this.timeline = newTimeline;
|
||||||
refreshSourceInfo(newTimeline);
|
refreshSourceInfo(newTimeline);
|
||||||
if (isUsedByPlayer() || onSourcePreparedNotified) {
|
preloadHandler.post(
|
||||||
return;
|
() -> {
|
||||||
}
|
if (isUsedByPlayer() || onSourcePreparedNotified) {
|
||||||
onSourcePreparedNotified = true;
|
return;
|
||||||
if (!preloadControl.onSourcePrepared(this)) {
|
}
|
||||||
stopPreloading();
|
onSourcePreparedNotified = true;
|
||||||
return;
|
if (!preloadControl.onSourcePrepared(this)) {
|
||||||
}
|
stopPreloading();
|
||||||
Pair<Object, Long> periodPosition =
|
return;
|
||||||
newTimeline.getPeriodPositionUs(
|
}
|
||||||
new Timeline.Window(),
|
Pair<Object, Long> periodPosition =
|
||||||
new Timeline.Period(),
|
newTimeline.getPeriodPositionUs(
|
||||||
/* windowIndex= */ 0,
|
new Timeline.Window(),
|
||||||
/* windowPositionUs= */ startPositionUs);
|
new Timeline.Period(),
|
||||||
MediaPeriodId mediaPeriodId = new MediaPeriodId(periodPosition.first);
|
/* windowIndex= */ 0,
|
||||||
PreloadMediaPeriod mediaPeriod =
|
/* windowPositionUs= */ startPositionUs);
|
||||||
PreloadMediaSource.this.createPeriod(mediaPeriodId, allocator, periodPosition.second);
|
MediaPeriodId mediaPeriodId = new MediaPeriodId(periodPosition.first);
|
||||||
mediaPeriod.preload(
|
PreloadMediaPeriod mediaPeriod =
|
||||||
new PreloadMediaPeriodCallback(periodPosition.second),
|
PreloadMediaSource.this.createPeriod(mediaPeriodId, allocator, periodPosition.second);
|
||||||
/* positionUs= */ periodPosition.second);
|
mediaPeriod.preload(
|
||||||
|
new PreloadMediaPeriodCallback(periodPosition.second),
|
||||||
|
/* positionUs= */ periodPosition.second);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -455,53 +458,59 @@ public final class PreloadMediaSource extends WrappingMediaSource {
|
|||||||
@Override
|
@Override
|
||||||
public void onPrepared(MediaPeriod mediaPeriod) {
|
public void onPrepared(MediaPeriod mediaPeriod) {
|
||||||
prepared = true;
|
prepared = true;
|
||||||
if (isUsedByPlayer()) {
|
preloadHandler.post(
|
||||||
return;
|
() -> {
|
||||||
}
|
if (isUsedByPlayer()) {
|
||||||
PreloadMediaPeriod preloadMediaPeriod = (PreloadMediaPeriod) mediaPeriod;
|
return;
|
||||||
TrackGroupArray trackGroups = preloadMediaPeriod.getTrackGroups();
|
}
|
||||||
@Nullable TrackSelectorResult trackSelectorResult = null;
|
PreloadMediaPeriod preloadMediaPeriod = (PreloadMediaPeriod) mediaPeriod;
|
||||||
MediaPeriodKey key = checkNotNull(preloadingMediaPeriodAndKey).second;
|
TrackGroupArray trackGroups = preloadMediaPeriod.getTrackGroups();
|
||||||
try {
|
@Nullable TrackSelectorResult trackSelectorResult = null;
|
||||||
trackSelectorResult =
|
MediaPeriodKey key = checkNotNull(preloadingMediaPeriodAndKey).second;
|
||||||
trackSelector.selectTracks(
|
try {
|
||||||
rendererCapabilities, trackGroups, key.mediaPeriodId, checkNotNull(timeline));
|
trackSelectorResult =
|
||||||
} catch (ExoPlaybackException e) {
|
trackSelector.selectTracks(
|
||||||
Log.e(TAG, "Failed to select tracks", e);
|
rendererCapabilities, trackGroups, key.mediaPeriodId, checkNotNull(timeline));
|
||||||
}
|
} catch (ExoPlaybackException e) {
|
||||||
if (trackSelectorResult == null) {
|
Log.e(TAG, "Failed to select tracks", e);
|
||||||
stopPreloading();
|
}
|
||||||
return;
|
if (trackSelectorResult == null) {
|
||||||
}
|
stopPreloading();
|
||||||
preloadMediaPeriod.selectTracksForPreloading(
|
return;
|
||||||
trackSelectorResult.selections, periodStartPositionUs);
|
}
|
||||||
if (!preloadControl.onTracksSelected(PreloadMediaSource.this)) {
|
preloadMediaPeriod.selectTracksForPreloading(
|
||||||
stopPreloading();
|
trackSelectorResult.selections, periodStartPositionUs);
|
||||||
return;
|
if (!preloadControl.onTracksSelected(PreloadMediaSource.this)) {
|
||||||
}
|
stopPreloading();
|
||||||
preloadMediaPeriod.continueLoading(
|
return;
|
||||||
new LoadingInfo.Builder().setPlaybackPositionUs(periodStartPositionUs).build());
|
}
|
||||||
|
preloadMediaPeriod.continueLoading(
|
||||||
|
new LoadingInfo.Builder().setPlaybackPositionUs(periodStartPositionUs).build());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onContinueLoadingRequested(MediaPeriod mediaPeriod) {
|
public void onContinueLoadingRequested(MediaPeriod mediaPeriod) {
|
||||||
if (isUsedByPlayer()) {
|
preloadHandler.post(
|
||||||
return;
|
() -> {
|
||||||
}
|
if (isUsedByPlayer()) {
|
||||||
PreloadMediaPeriod preloadMediaPeriod = (PreloadMediaPeriod) mediaPeriod;
|
return;
|
||||||
if (prepared && mediaPeriod.getBufferedPositionUs() == C.TIME_END_OF_SOURCE) {
|
}
|
||||||
preloadControl.onLoadedToTheEndOfSource(PreloadMediaSource.this);
|
PreloadMediaPeriod preloadMediaPeriod = (PreloadMediaPeriod) mediaPeriod;
|
||||||
stopPreloading();
|
if (prepared && mediaPeriod.getBufferedPositionUs() == C.TIME_END_OF_SOURCE) {
|
||||||
return;
|
preloadControl.onLoadedToTheEndOfSource(PreloadMediaSource.this);
|
||||||
}
|
stopPreloading();
|
||||||
if (prepared
|
return;
|
||||||
&& !preloadControl.onContinueLoadingRequested(
|
}
|
||||||
PreloadMediaSource.this, preloadMediaPeriod.getBufferedPositionUs())) {
|
if (prepared
|
||||||
stopPreloading();
|
&& !preloadControl.onContinueLoadingRequested(
|
||||||
return;
|
PreloadMediaSource.this, preloadMediaPeriod.getBufferedPositionUs())) {
|
||||||
}
|
stopPreloading();
|
||||||
preloadMediaPeriod.continueLoading(
|
return;
|
||||||
new LoadingInfo.Builder().setPlaybackPositionUs(periodStartPositionUs).build());
|
}
|
||||||
|
preloadMediaPeriod.continueLoading(
|
||||||
|
new LoadingInfo.Builder().setPlaybackPositionUs(periodStartPositionUs).build());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user