mirror of
https://github.com/androidx/media.git
synced 2025-04-29 22:36:54 +08:00
Fix issue where ProgressiveMediaPeriod fails assertPrepared
In `PreloadMediaSource` we accesses the `MediaPeriod.getBufferedPositionUs()` when we receive `onContinueLoadingRequested()` from the period. For `ProgressiveMediaPeriod` which requires loading a portion of media file to get it prepared, there is a chance that it needs more than one round of `onContinueLoadingRequested()` -> `continueLoading()` to complete preparation, for example, when the `setContinueLoadingIntervalBytes()` is small enough to not include the full information for preparation. Thus we should avoid `MediaPeriod.getBufferedPositionUs()` being called before period is prepared, as it will fail at `assertPrepared`. Issue: androidx/media#2315 #cherrypick PiperOrigin-RevId: 746490375
This commit is contained in:
parent
df8763ae0d
commit
344f249511
@ -21,6 +21,10 @@
|
||||
groups have been removed. The user still needs to pass in an array of
|
||||
durations for removed ad groups which can be empty or null
|
||||
([#2267](https://github.com/androidx/media/issues/2267)).
|
||||
* Fix issue where `ProgressiveMediaPeriod` throws an
|
||||
`IllegalStateException` as `PreloadMediaSource` attempts to call its
|
||||
`getBufferedDurationUs()` before it is prepared
|
||||
([#2315](https://github.com/androidx/media/issues/2315)).
|
||||
* Transformer:
|
||||
* Filling an initial gap (added via `addGap()`) with silent audio now
|
||||
requires explicitly setting `experimentalSetForceAudioTrack(true)` in
|
||||
|
@ -505,17 +505,18 @@ public final class PreloadMediaSource extends WrappingMediaSource {
|
||||
return;
|
||||
}
|
||||
PreloadMediaPeriod preloadMediaPeriod = (PreloadMediaPeriod) mediaPeriod;
|
||||
long bufferedPositionUs = mediaPeriod.getBufferedPositionUs();
|
||||
if (prepared && bufferedPositionUs == C.TIME_END_OF_SOURCE) {
|
||||
preloadControl.onLoadedToTheEndOfSource(PreloadMediaSource.this);
|
||||
stopPreloading();
|
||||
return;
|
||||
}
|
||||
if (prepared
|
||||
&& !preloadControl.onContinueLoadingRequested(
|
||||
PreloadMediaSource.this, bufferedPositionUs - periodStartPositionUs)) {
|
||||
stopPreloading();
|
||||
return;
|
||||
if (prepared) {
|
||||
long bufferedPositionUs = mediaPeriod.getBufferedPositionUs();
|
||||
if (bufferedPositionUs == C.TIME_END_OF_SOURCE) {
|
||||
preloadControl.onLoadedToTheEndOfSource(PreloadMediaSource.this);
|
||||
stopPreloading();
|
||||
return;
|
||||
}
|
||||
if (!preloadControl.onContinueLoadingRequested(
|
||||
PreloadMediaSource.this, bufferedPositionUs - periodStartPositionUs)) {
|
||||
stopPreloading();
|
||||
return;
|
||||
}
|
||||
}
|
||||
preloadMediaPeriod.continueLoading(
|
||||
new LoadingInfo.Builder().setPlaybackPositionUs(periodStartPositionUs).build());
|
||||
|
@ -90,12 +90,13 @@ import org.junit.runner.RunWith;
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public final class PreloadMediaSourceTest {
|
||||
|
||||
private static final int LOADING_CHECK_INTERVAL_BYTES = 10 * 1024;
|
||||
private static final int LOADING_CHECK_INTERVAL_BYTES = 32;
|
||||
private static final int TARGET_PRELOAD_DURATION_US = 10000;
|
||||
|
||||
private Allocator allocator;
|
||||
private BandwidthMeter bandwidthMeter;
|
||||
private RenderersFactory renderersFactory;
|
||||
private MediaItem mediaItem;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@ -112,6 +113,10 @@ public final class PreloadMediaSourceTest {
|
||||
SystemClock.DEFAULT.createHandler(handler.getLooper(), /* callback= */ null),
|
||||
audioListener)
|
||||
};
|
||||
mediaItem =
|
||||
new MediaItem.Builder()
|
||||
.setUri(Uri.parse("asset://android_asset/media/mp4/long_1080p_lowbitrate.mp4"))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -146,11 +151,7 @@ public final class PreloadMediaSourceTest {
|
||||
getRendererCapabilities(renderersFactory),
|
||||
allocator,
|
||||
Util.getCurrentOrMainLooper());
|
||||
PreloadMediaSource preloadMediaSource =
|
||||
preloadMediaSourceFactory.createMediaSource(
|
||||
new MediaItem.Builder()
|
||||
.setUri(Uri.parse("asset://android_asset/media/mp4/sample.mp4"))
|
||||
.build());
|
||||
PreloadMediaSource preloadMediaSource = preloadMediaSourceFactory.createMediaSource(mediaItem);
|
||||
|
||||
preloadMediaSource.preload(/* startPositionUs= */ 0L);
|
||||
runMainLooperUntil(() -> preloadMediaSourceReference.get() != null);
|
||||
@ -191,11 +192,7 @@ public final class PreloadMediaSourceTest {
|
||||
getRendererCapabilities(renderersFactory),
|
||||
allocator,
|
||||
Util.getCurrentOrMainLooper());
|
||||
PreloadMediaSource preloadMediaSource =
|
||||
preloadMediaSourceFactory.createMediaSource(
|
||||
new MediaItem.Builder()
|
||||
.setUri(Uri.parse("asset://android_asset/media/mp4/sample.mp4"))
|
||||
.build());
|
||||
PreloadMediaSource preloadMediaSource = preloadMediaSourceFactory.createMediaSource(mediaItem);
|
||||
|
||||
preloadMediaSource.preload(/* startPositionUs= */ 0L);
|
||||
runMainLooperUntil(() -> preloadMediaSourceReference.get() != null);
|
||||
@ -235,11 +232,7 @@ public final class PreloadMediaSourceTest {
|
||||
getRendererCapabilities(renderersFactory),
|
||||
allocator,
|
||||
Util.getCurrentOrMainLooper());
|
||||
PreloadMediaSource preloadMediaSource =
|
||||
preloadMediaSourceFactory.createMediaSource(
|
||||
new MediaItem.Builder()
|
||||
.setUri(Uri.parse("asset://android_asset/media/mp4/sample.mp4"))
|
||||
.build());
|
||||
PreloadMediaSource preloadMediaSource = preloadMediaSourceFactory.createMediaSource(mediaItem);
|
||||
|
||||
preloadMediaSource.preload(/* startPositionUs= */ 0L);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
@ -266,11 +259,7 @@ public final class PreloadMediaSourceTest {
|
||||
getRendererCapabilities(renderersFactory),
|
||||
allocator,
|
||||
Util.getCurrentOrMainLooper());
|
||||
PreloadMediaSource preloadMediaSource =
|
||||
preloadMediaSourceFactory.createMediaSource(
|
||||
new MediaItem.Builder()
|
||||
.setUri(Uri.parse("asset://android_asset/media/mp4/sample.mp4"))
|
||||
.build());
|
||||
PreloadMediaSource preloadMediaSource = preloadMediaSourceFactory.createMediaSource(mediaItem);
|
||||
|
||||
AtomicReference<MediaSource> externalCallerMediaSourceReference = new AtomicReference<>();
|
||||
MediaSource.MediaSourceCaller externalCaller =
|
||||
@ -315,11 +304,7 @@ public final class PreloadMediaSourceTest {
|
||||
getRendererCapabilities(renderersFactory),
|
||||
allocator,
|
||||
Util.getCurrentOrMainLooper());
|
||||
PreloadMediaSource preloadMediaSource =
|
||||
preloadMediaSourceFactory.createMediaSource(
|
||||
new MediaItem.Builder()
|
||||
.setUri(Uri.parse("asset://android_asset/media/mp4/sample.mp4"))
|
||||
.build());
|
||||
PreloadMediaSource preloadMediaSource = preloadMediaSourceFactory.createMediaSource(mediaItem);
|
||||
|
||||
preloadMediaSource.preload(/* startPositionUs= */ 0L);
|
||||
runMainLooperUntil(() -> preloadMediaSourceReference.get() != null);
|
||||
@ -388,11 +373,7 @@ public final class PreloadMediaSourceTest {
|
||||
getRendererCapabilities(renderersFactory),
|
||||
allocator,
|
||||
Util.getCurrentOrMainLooper());
|
||||
PreloadMediaSource preloadMediaSource =
|
||||
preloadMediaSourceFactory.createMediaSource(
|
||||
new MediaItem.Builder()
|
||||
.setUri(Uri.parse("asset://android_asset/media/mp4/sample.mp4"))
|
||||
.build());
|
||||
PreloadMediaSource preloadMediaSource = preloadMediaSourceFactory.createMediaSource(mediaItem);
|
||||
|
||||
preloadMediaSource.preload(/* startPositionUs= */ 0L);
|
||||
runMainLooperUntil(() -> preloadExceptionReference.get() != null);
|
||||
@ -472,11 +453,7 @@ public final class PreloadMediaSourceTest {
|
||||
getRendererCapabilities(renderersFactory),
|
||||
allocator,
|
||||
Util.getCurrentOrMainLooper());
|
||||
PreloadMediaSource preloadMediaSource =
|
||||
preloadMediaSourceFactory.createMediaSource(
|
||||
new MediaItem.Builder()
|
||||
.setUri(Uri.parse("asset://android_asset/media/mp4/sample.mp4"))
|
||||
.build());
|
||||
PreloadMediaSource preloadMediaSource = preloadMediaSourceFactory.createMediaSource(mediaItem);
|
||||
|
||||
preloadMediaSource.preload(/* startPositionUs= */ 0L);
|
||||
runMainLooperUntil(() -> preloadExceptionReference.get() != null);
|
||||
@ -583,11 +560,7 @@ public final class PreloadMediaSourceTest {
|
||||
getRendererCapabilities(renderersFactory),
|
||||
allocator,
|
||||
Util.getCurrentOrMainLooper());
|
||||
PreloadMediaSource preloadMediaSource =
|
||||
preloadMediaSourceFactory.createMediaSource(
|
||||
new MediaItem.Builder()
|
||||
.setUri(Uri.parse("asset://android_asset/media/mp4/sample.mp4"))
|
||||
.build());
|
||||
PreloadMediaSource preloadMediaSource = preloadMediaSourceFactory.createMediaSource(mediaItem);
|
||||
|
||||
preloadMediaSource.preload(/* startPositionUs= */ 0L);
|
||||
runMainLooperUntil(() -> preloadExceptionReference.get() != null);
|
||||
@ -615,11 +588,7 @@ public final class PreloadMediaSourceTest {
|
||||
getRendererCapabilities(renderersFactory),
|
||||
allocator,
|
||||
Util.getCurrentOrMainLooper());
|
||||
PreloadMediaSource preloadMediaSource =
|
||||
preloadMediaSourceFactory.createMediaSource(
|
||||
new MediaItem.Builder()
|
||||
.setUri(Uri.parse("asset://android_asset/media/mp4/sample.mp4"))
|
||||
.build());
|
||||
PreloadMediaSource preloadMediaSource = preloadMediaSourceFactory.createMediaSource(mediaItem);
|
||||
FakeMediaSource wrappedMediaSource = mediaSourceFactory.getLastCreatedSource();
|
||||
wrappedMediaSource.setAllowPreparation(false);
|
||||
preloadMediaSource.preload(/* startPositionUs= */ 0L);
|
||||
@ -653,11 +622,7 @@ public final class PreloadMediaSourceTest {
|
||||
getRendererCapabilities(renderersFactory),
|
||||
allocator,
|
||||
Util.getCurrentOrMainLooper());
|
||||
PreloadMediaSource preloadMediaSource =
|
||||
preloadMediaSourceFactory.createMediaSource(
|
||||
new MediaItem.Builder()
|
||||
.setUri(Uri.parse("asset://android_asset/media/mp4/sample.mp4"))
|
||||
.build());
|
||||
PreloadMediaSource preloadMediaSource = preloadMediaSourceFactory.createMediaSource(mediaItem);
|
||||
|
||||
preloadMediaSource.preload(/* startPositionUs= */ 0L);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
@ -727,11 +692,7 @@ public final class PreloadMediaSourceTest {
|
||||
getRendererCapabilities(renderersFactory),
|
||||
allocator,
|
||||
Util.getCurrentOrMainLooper());
|
||||
PreloadMediaSource preloadMediaSource =
|
||||
preloadMediaSourceFactory.createMediaSource(
|
||||
new MediaItem.Builder()
|
||||
.setUri(Uri.parse("asset://android_asset/media/mp4/sample.mp4"))
|
||||
.build());
|
||||
PreloadMediaSource preloadMediaSource = preloadMediaSourceFactory.createMediaSource(mediaItem);
|
||||
|
||||
preloadMediaSource.preload(/* startPositionUs= */ 0L);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
@ -808,11 +769,7 @@ public final class PreloadMediaSourceTest {
|
||||
getRendererCapabilities(renderersFactory),
|
||||
allocator,
|
||||
Util.getCurrentOrMainLooper());
|
||||
PreloadMediaSource preloadMediaSource =
|
||||
preloadMediaSourceFactory.createMediaSource(
|
||||
new MediaItem.Builder()
|
||||
.setUri(Uri.parse("asset://android_asset/media/mp4/sample.mp4"))
|
||||
.build());
|
||||
PreloadMediaSource preloadMediaSource = preloadMediaSourceFactory.createMediaSource(mediaItem);
|
||||
|
||||
preloadMediaSource.preload(/* startPositionUs= */ 0L);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
@ -876,11 +833,7 @@ public final class PreloadMediaSourceTest {
|
||||
getRendererCapabilities(renderersFactory),
|
||||
allocator,
|
||||
Util.getCurrentOrMainLooper());
|
||||
PreloadMediaSource preloadMediaSource =
|
||||
preloadMediaSourceFactory.createMediaSource(
|
||||
new MediaItem.Builder()
|
||||
.setUri(Uri.parse("asset://android_asset/media/mp4/sample.mp4"))
|
||||
.build());
|
||||
PreloadMediaSource preloadMediaSource = preloadMediaSourceFactory.createMediaSource(mediaItem);
|
||||
preloadMediaSource.preload(/* startPositionUs= */ 0L);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
@ -923,11 +876,7 @@ public final class PreloadMediaSourceTest {
|
||||
getRendererCapabilities(renderersFactory),
|
||||
allocator,
|
||||
Util.getCurrentOrMainLooper());
|
||||
PreloadMediaSource preloadMediaSource =
|
||||
preloadMediaSourceFactory.createMediaSource(
|
||||
new MediaItem.Builder()
|
||||
.setUri(Uri.parse("asset://android_asset/media/mp4/sample.mp4"))
|
||||
.build());
|
||||
PreloadMediaSource preloadMediaSource = preloadMediaSourceFactory.createMediaSource(mediaItem);
|
||||
AtomicBoolean externalCallerSourceInfoRefreshedCalled = new AtomicBoolean();
|
||||
MediaSource.MediaSourceCaller externalCaller =
|
||||
(source, timeline) -> externalCallerSourceInfoRefreshedCalled.set(true);
|
||||
@ -976,11 +925,7 @@ public final class PreloadMediaSourceTest {
|
||||
getRendererCapabilities(renderersFactory),
|
||||
allocator,
|
||||
Util.getCurrentOrMainLooper());
|
||||
PreloadMediaSource preloadMediaSource =
|
||||
preloadMediaSourceFactory.createMediaSource(
|
||||
new MediaItem.Builder()
|
||||
.setUri(Uri.parse("asset://android_asset/media/mp4/sample.mp4"))
|
||||
.build());
|
||||
PreloadMediaSource preloadMediaSource = preloadMediaSourceFactory.createMediaSource(mediaItem);
|
||||
AtomicBoolean externalCallerSourceInfoRefreshedCalled = new AtomicBoolean();
|
||||
MediaSource.MediaSourceCaller externalCaller =
|
||||
(source, timeline) -> externalCallerSourceInfoRefreshedCalled.set(true);
|
||||
@ -1031,11 +976,7 @@ public final class PreloadMediaSourceTest {
|
||||
getRendererCapabilities(renderersFactory),
|
||||
allocator,
|
||||
Util.getCurrentOrMainLooper());
|
||||
PreloadMediaSource preloadMediaSource =
|
||||
preloadMediaSourceFactory.createMediaSource(
|
||||
new MediaItem.Builder()
|
||||
.setUri(Uri.parse("asset://android_asset/media/mp4/sample.mp4"))
|
||||
.build());
|
||||
PreloadMediaSource preloadMediaSource = preloadMediaSourceFactory.createMediaSource(mediaItem);
|
||||
AtomicBoolean externalCaller1SourceInfoRefreshedCalled = new AtomicBoolean();
|
||||
AtomicBoolean externalCaller2SourceInfoRefreshedCalled = new AtomicBoolean();
|
||||
MediaSource.MediaSourceCaller externalCaller1 =
|
||||
@ -1090,11 +1031,7 @@ public final class PreloadMediaSourceTest {
|
||||
getRendererCapabilities(renderersFactory),
|
||||
allocator,
|
||||
Util.getCurrentOrMainLooper());
|
||||
PreloadMediaSource preloadMediaSource =
|
||||
preloadMediaSourceFactory.createMediaSource(
|
||||
new MediaItem.Builder()
|
||||
.setUri(Uri.parse("asset://android_asset/media/mp4/sample.mp4"))
|
||||
.build());
|
||||
PreloadMediaSource preloadMediaSource = preloadMediaSourceFactory.createMediaSource(mediaItem);
|
||||
preloadMediaSource.preload(/* startPositionUs= */ 0L);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
preloadMediaSource.releasePreloadMediaSource();
|
||||
@ -1140,11 +1077,7 @@ public final class PreloadMediaSourceTest {
|
||||
getRendererCapabilities(renderersFactory),
|
||||
allocator,
|
||||
Util.getCurrentOrMainLooper());
|
||||
PreloadMediaSource preloadMediaSource =
|
||||
preloadMediaSourceFactory.createMediaSource(
|
||||
new MediaItem.Builder()
|
||||
.setUri(Uri.parse("asset://android_asset/media/mp4/sample.mp4"))
|
||||
.build());
|
||||
PreloadMediaSource preloadMediaSource = preloadMediaSourceFactory.createMediaSource(mediaItem);
|
||||
AtomicBoolean externalCallerSourceInfoRefreshedCalled = new AtomicBoolean();
|
||||
MediaSource.MediaSourceCaller externalCaller =
|
||||
(source, timeline) -> externalCallerSourceInfoRefreshedCalled.set(true);
|
||||
|
Loading…
x
Reference in New Issue
Block a user