diff --git a/just_audio/android/src/main/java/com/ryanheise/just_audio/AudioPlayer.java b/just_audio/android/src/main/java/com/ryanheise/just_audio/AudioPlayer.java index d31c284d..45032a1e 100644 --- a/just_audio/android/src/main/java/com/ryanheise/just_audio/AudioPlayer.java +++ b/just_audio/android/src/main/java/com/ryanheise/just_audio/AudioPlayer.java @@ -31,6 +31,7 @@ import com.google.android.exoplayer2.metadata.icy.IcyInfo; import com.google.android.exoplayer2.source.ClippingMediaSource; import com.google.android.exoplayer2.source.ConcatenatingMediaSource; +import com.google.android.exoplayer2.source.MaskingMediaSource; import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.ProgressiveMediaSource; import com.google.android.exoplayer2.source.ShuffleOrder; @@ -62,7 +63,7 @@ import java.util.Map; import java.util.Random; -public class AudioPlayer implements MethodCallHandler, Player.Listener, MetadataOutput { +public class AudioPlayer implements MethodCallHandler, Player.Listener, MetadataOutput, LazyMediaSourceProvider { static final String TAG = "AudioPlayer"; @@ -611,6 +612,17 @@ private MediaSource decodeAudioSource(final Object json) { .setUri(Uri.parse((String)map.get("uri"))) .setMimeType(MimeTypes.APPLICATION_M3U8) .build()); + case "mapping": + return new MaskingMediaSource( + new LazyMediaSource( + this, + id, + new MediaItem.Builder() + .setTag(id) + .build() + ), + true + ); case "silence": return new SilenceMediaSource.Factory() .setDurationUs(getLong(map.get("duration"))) @@ -695,6 +707,29 @@ private DataSource.Factory buildDataSourceFactory() { return new DefaultDataSource.Factory(context, httpDataSourceFactory); } + @Override + public void createMediaSource(String id, LazyMediaSourceReceiver receiver) { + handler.post(() -> { + methodChannel.invokeMethod("createMappedAudioSourceSource", Collections.singletonMap("id", id), new Result() { + @Override + public void success(Object json) { + final MediaSource mediaSource = decodeAudioSource(json); + receiver.onMediaSourceCreated(mediaSource); + } + + @Override + public void error(String errorCode, String errorMessage, Object errorDetails) { + throw new IllegalStateException("createMappedAudioSourceSource failed. Cannot proceed. (" + errorCode + ", " + errorMessage + ", " + errorDetails + ")"); + } + + @Override + public void notImplemented() { + throw new IllegalArgumentException("createMappedAudioSourceSource is not implemented by the platform."); + } + }); + }); + } + private void load(final MediaSource mediaSource, final long initialPosition, final Integer initialIndex, final Result result) { this.initialPos = initialPosition; this.initialIndex = initialIndex; diff --git a/just_audio/android/src/main/java/com/ryanheise/just_audio/LazyMediaSource.java b/just_audio/android/src/main/java/com/ryanheise/just_audio/LazyMediaSource.java new file mode 100644 index 00000000..56b82f66 --- /dev/null +++ b/just_audio/android/src/main/java/com/ryanheise/just_audio/LazyMediaSource.java @@ -0,0 +1,160 @@ +package com.ryanheise.just_audio; + +import android.os.Handler; + +import com.google.android.exoplayer2.MediaItem; +import com.google.android.exoplayer2.Timeline; +import com.google.android.exoplayer2.analytics.PlayerId; +import com.google.android.exoplayer2.drm.DrmSessionEventListener; +import com.google.android.exoplayer2.source.MediaPeriod; +import com.google.android.exoplayer2.source.MediaSource; +import com.google.android.exoplayer2.source.MediaSourceEventListener; +import com.google.android.exoplayer2.upstream.Allocator; +import com.google.android.exoplayer2.upstream.TransferListener; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +/** + * A {@link MediaSource} that lazily defers to another {@link MediaSource} when it is required. + *
+ * This {@link MediaSource} must be used with a {@link com.google.android.exoplayer2.source.MaskingMediaSource}.
+ */
+class LazyMediaSource implements MediaSource {
+ private final LazyMediaSourceProvider mediaSourceProvider;
+ public final String id;
+ public final MediaItem placeholderMediaItem;
+
+ private final Map