mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Media2: Remove MediaSourceFactory + DataSourceCallback
- Applications should generally use DefaultMediaSourceFactory, or their own custom implementation if they need one. Having the media2 extension implement its own version directly doesn't seem that useful. - Remove support for CallbackMediaItem. This type of MediaItem doesn't go cross-process, and it seems like there would never be a use case where an app would need to generate one locally. If an app needs to provide data from a custom source, it should hook into ExoPlayer's way of doing this (i.e., use a UriMediaItem with a custom scheme, and inject a custom DataSource that can handle this scheme). PiperOrigin-RevId: 326914465
This commit is contained in:
parent
42cf213aea
commit
49bf83a169
@ -1,28 +0,0 @@
|
|||||||
# Proguard rules specific to the media2 extension.
|
|
||||||
|
|
||||||
# Constructors and methods accessed via reflection in ExoPlayerUtils.
|
|
||||||
-dontnote com.google.android.exoplayer2.source.dash.DashMediaSource$Factory
|
|
||||||
-keepclasseswithmembers class com.google.android.exoplayer2.source.dash.DashMediaSource$Factory {
|
|
||||||
public <init>(com.google.android.exoplayer2.upstream.DataSource$Factory);
|
|
||||||
public com.google.android.exoplayer2.source.dash.DashMediaSource$Factory setTag(java.lang.Object);
|
|
||||||
}
|
|
||||||
-dontnote com.google.android.exoplayer2.source.hls.HlsMediaSource$Factory
|
|
||||||
-keepclasseswithmembers class com.google.android.exoplayer2.source.hls.HlsMediaSource$Factory {
|
|
||||||
public <init>(com.google.android.exoplayer2.upstream.DataSource$Factory);
|
|
||||||
public com.google.android.exoplayer2.source.hls.HlsMediaSource$Factory setTag(java.lang.Object);
|
|
||||||
}
|
|
||||||
-dontnote com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource$Factory
|
|
||||||
-keepclasseswithmembers class com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource$Factory {
|
|
||||||
public <init>(com.google.android.exoplayer2.upstream.DataSource$Factory);
|
|
||||||
public com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource$Factory setTag(java.lang.Object);
|
|
||||||
}
|
|
||||||
|
|
||||||
# Don't warn about checkerframework and Kotlin annotations
|
|
||||||
-dontwarn org.checkerframework.**
|
|
||||||
-dontwarn kotlin.annotations.jvm.**
|
|
||||||
-dontwarn javax.annotation.**
|
|
||||||
|
|
||||||
# Work around [internal: b/151134701]: keep non-public versionedparcelable
|
|
||||||
# classes.
|
|
||||||
-keep class * implements androidx.versionedparcelable.VersionedParcelable
|
|
||||||
-keep class androidx.media2.common.MediaParcelUtils$MediaItemParcelImpl
|
|
@ -75,8 +75,8 @@ import org.junit.rules.ExternalResource;
|
|||||||
.setLooper(Looper.myLooper())
|
.setLooper(Looper.myLooper())
|
||||||
.setMediaSourceFactory(new DefaultMediaSourceFactory(dataSourceFactory, null))
|
.setMediaSourceFactory(new DefaultMediaSourceFactory(dataSourceFactory, null))
|
||||||
.build();
|
.build();
|
||||||
DefaultMediaItemConverter converter = new DefaultMediaItemConverter(context);
|
sessionPlayerConnector =
|
||||||
sessionPlayerConnector = new SessionPlayerConnector(exoPlayer, converter);
|
new SessionPlayerConnector(exoPlayer, new DefaultMediaItemConverter());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,7 +183,6 @@ public class SessionPlayerConnectorTest {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
DefaultMediaItemConverter converter = new DefaultMediaItemConverter(context);
|
|
||||||
SimpleExoPlayer simpleExoPlayer = null;
|
SimpleExoPlayer simpleExoPlayer = null;
|
||||||
try {
|
try {
|
||||||
simpleExoPlayer =
|
simpleExoPlayer =
|
||||||
@ -191,7 +190,8 @@ public class SessionPlayerConnectorTest {
|
|||||||
.setLooper(Looper.myLooper())
|
.setLooper(Looper.myLooper())
|
||||||
.build();
|
.build();
|
||||||
try (SessionPlayerConnector player =
|
try (SessionPlayerConnector player =
|
||||||
new SessionPlayerConnector(simpleExoPlayer, converter, controlDispatcher)) {
|
new SessionPlayerConnector(
|
||||||
|
simpleExoPlayer, new DefaultMediaItemConverter(), controlDispatcher)) {
|
||||||
assertPlayerResult(player.play(), RESULT_INFO_SKIPPED);
|
assertPlayerResult(player.play(), RESULT_INFO_SKIPPED);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -1,110 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2019 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package com.google.android.exoplayer2.ext.media2;
|
|
||||||
|
|
||||||
import android.net.Uri;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.media2.common.DataSourceCallback;
|
|
||||||
import com.google.android.exoplayer2.C;
|
|
||||||
import com.google.android.exoplayer2.upstream.BaseDataSource;
|
|
||||||
import com.google.android.exoplayer2.upstream.DataSource;
|
|
||||||
import com.google.android.exoplayer2.upstream.DataSpec;
|
|
||||||
import com.google.android.exoplayer2.util.Assertions;
|
|
||||||
import java.io.EOFException;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/** An ExoPlayer {@link DataSource} for reading from a {@link DataSourceCallback}. */
|
|
||||||
/* package */ final class DataSourceCallbackDataSource extends BaseDataSource {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a factory for {@link DataSourceCallbackDataSource}s.
|
|
||||||
*
|
|
||||||
* @return A factory for data sources that read from the data source callback.
|
|
||||||
*/
|
|
||||||
public static DataSource.Factory getFactory(DataSourceCallback dataSourceCallback) {
|
|
||||||
Assertions.checkNotNull(dataSourceCallback);
|
|
||||||
return () -> new DataSourceCallbackDataSource(dataSourceCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
private final DataSourceCallback dataSourceCallback;
|
|
||||||
|
|
||||||
@Nullable private Uri uri;
|
|
||||||
private long position;
|
|
||||||
private long bytesRemaining;
|
|
||||||
private boolean opened;
|
|
||||||
|
|
||||||
public DataSourceCallbackDataSource(DataSourceCallback dataSourceCallback) {
|
|
||||||
super(/* isNetwork= */ false);
|
|
||||||
this.dataSourceCallback = Assertions.checkNotNull(dataSourceCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long open(DataSpec dataSpec) throws IOException {
|
|
||||||
uri = dataSpec.uri;
|
|
||||||
position = dataSpec.position;
|
|
||||||
transferInitializing(dataSpec);
|
|
||||||
long dataSourceCallbackSize = dataSourceCallback.getSize();
|
|
||||||
if (dataSpec.length != C.LENGTH_UNSET) {
|
|
||||||
bytesRemaining = dataSpec.length;
|
|
||||||
} else if (dataSourceCallbackSize != -1) {
|
|
||||||
bytesRemaining = dataSourceCallbackSize - position;
|
|
||||||
} else {
|
|
||||||
bytesRemaining = C.LENGTH_UNSET;
|
|
||||||
}
|
|
||||||
opened = true;
|
|
||||||
transferStarted(dataSpec);
|
|
||||||
return bytesRemaining;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int read(byte[] buffer, int offset, int readLength) throws IOException {
|
|
||||||
if (readLength == 0) {
|
|
||||||
return 0;
|
|
||||||
} else if (bytesRemaining == 0) {
|
|
||||||
return C.RESULT_END_OF_INPUT;
|
|
||||||
}
|
|
||||||
int bytesToRead =
|
|
||||||
bytesRemaining == C.LENGTH_UNSET ? readLength : (int) Math.min(bytesRemaining, readLength);
|
|
||||||
int bytesRead = dataSourceCallback.readAt(position, buffer, offset, bytesToRead);
|
|
||||||
if (bytesRead == -1) {
|
|
||||||
if (bytesRemaining != C.LENGTH_UNSET) {
|
|
||||||
throw new EOFException();
|
|
||||||
}
|
|
||||||
return C.RESULT_END_OF_INPUT;
|
|
||||||
}
|
|
||||||
position += bytesRead;
|
|
||||||
if (bytesRemaining != C.LENGTH_UNSET) {
|
|
||||||
bytesRemaining -= bytesRead;
|
|
||||||
}
|
|
||||||
bytesTransferred(bytesRead);
|
|
||||||
return bytesRead;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
public Uri getUri() {
|
|
||||||
return uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
uri = null;
|
|
||||||
if (opened) {
|
|
||||||
opened = false;
|
|
||||||
transferEnded();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -16,82 +16,44 @@
|
|||||||
|
|
||||||
package com.google.android.exoplayer2.ext.media2;
|
package com.google.android.exoplayer2.ext.media2;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.media2.common.CallbackMediaItem;
|
||||||
import androidx.media2.common.FileMediaItem;
|
import androidx.media2.common.FileMediaItem;
|
||||||
import androidx.media2.common.MediaMetadata;
|
import androidx.media2.common.MediaMetadata;
|
||||||
import androidx.media2.common.UriMediaItem;
|
import androidx.media2.common.UriMediaItem;
|
||||||
import com.google.android.exoplayer2.C;
|
|
||||||
import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
|
|
||||||
import com.google.android.exoplayer2.MediaItem;
|
import com.google.android.exoplayer2.MediaItem;
|
||||||
import com.google.android.exoplayer2.drm.DrmSessionManager;
|
|
||||||
import com.google.android.exoplayer2.source.ClippingMediaSource;
|
|
||||||
import com.google.android.exoplayer2.source.MediaSource;
|
|
||||||
import com.google.android.exoplayer2.source.MediaSourceFactory;
|
|
||||||
import com.google.android.exoplayer2.upstream.DataSource;
|
|
||||||
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
|
||||||
import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy;
|
|
||||||
import com.google.android.exoplayer2.util.Assertions;
|
import com.google.android.exoplayer2.util.Assertions;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
|
||||||
|
|
||||||
/** Default implementation of both {@link MediaItemConverter} and {@link MediaSourceFactory}. */
|
/** Default implementation of {@link MediaItemConverter}. */
|
||||||
public final class DefaultMediaItemConverter implements MediaItemConverter, MediaSourceFactory {
|
public final class DefaultMediaItemConverter implements MediaItemConverter {
|
||||||
private static final int[] SUPPORTED_TYPES =
|
|
||||||
new int[] {C.TYPE_DASH, C.TYPE_SS, C.TYPE_HLS, C.TYPE_OTHER};
|
|
||||||
private final Context context;
|
|
||||||
private final DataSource.Factory dataSourceFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default constructor with {@link DefaultDataSourceFactory}.
|
|
||||||
*
|
|
||||||
* @param context The context.
|
|
||||||
*/
|
|
||||||
public DefaultMediaItemConverter(Context context) {
|
|
||||||
this(
|
|
||||||
context,
|
|
||||||
new DefaultDataSourceFactory(
|
|
||||||
context, Util.getUserAgent(context, ExoPlayerLibraryInfo.VERSION_SLASHY)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default constructor with {@link DataSource.Factory}.
|
|
||||||
*
|
|
||||||
* @param context The {@link Context}.
|
|
||||||
* @param dataSourceFactory The {@link DataSource.Factory} to create {@link MediaSource} from
|
|
||||||
* {@link MediaItem ExoPlayer MediaItem}.
|
|
||||||
*/
|
|
||||||
public DefaultMediaItemConverter(Context context, DataSource.Factory dataSourceFactory) {
|
|
||||||
this.context = Assertions.checkNotNull(context);
|
|
||||||
this.dataSourceFactory = Assertions.checkNotNull(dataSourceFactory);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implements MediaItemConverter
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MediaItem convertToExoPlayerMediaItem(androidx.media2.common.MediaItem androidXMediaItem) {
|
public MediaItem convertToExoPlayerMediaItem(androidx.media2.common.MediaItem androidXMediaItem) {
|
||||||
if (androidXMediaItem instanceof FileMediaItem) {
|
if (androidXMediaItem instanceof FileMediaItem) {
|
||||||
throw new IllegalStateException("FileMediaItem isn't supported");
|
throw new IllegalStateException("FileMediaItem isn't supported");
|
||||||
}
|
}
|
||||||
|
if (androidXMediaItem instanceof CallbackMediaItem) {
|
||||||
|
throw new IllegalStateException("CallbackMediaItem isn't supported");
|
||||||
|
}
|
||||||
|
|
||||||
com.google.android.exoplayer2.MediaItem.Builder exoplayerMediaItemBuilder =
|
MediaItem.Builder exoplayerMediaItemBuilder = new MediaItem.Builder();
|
||||||
new com.google.android.exoplayer2.MediaItem.Builder();
|
|
||||||
|
|
||||||
// Set mediaItem as tag for creating MediaSource via MediaSourceFactory methods.
|
// Set mediaItem as tag for creating MediaSource via MediaSourceFactory methods.
|
||||||
exoplayerMediaItemBuilder.setTag(androidXMediaItem);
|
exoplayerMediaItemBuilder.setTag(androidXMediaItem);
|
||||||
|
|
||||||
// Media id or Uri must be present. Get it from androidx.MediaItem if possible.
|
// Media ID or URI must be present. Get it from androidx.MediaItem if possible.
|
||||||
Uri uri = null;
|
@Nullable Uri uri = null;
|
||||||
String mediaId = null;
|
@Nullable String mediaId = null;
|
||||||
if (androidXMediaItem instanceof UriMediaItem) {
|
if (androidXMediaItem instanceof UriMediaItem) {
|
||||||
UriMediaItem uriMediaItem = (UriMediaItem) androidXMediaItem;
|
UriMediaItem uriMediaItem = (UriMediaItem) androidXMediaItem;
|
||||||
uri = uriMediaItem.getUri();
|
uri = uriMediaItem.getUri();
|
||||||
}
|
}
|
||||||
MediaMetadata metadata = androidXMediaItem.getMetadata();
|
@Nullable MediaMetadata metadata = androidXMediaItem.getMetadata();
|
||||||
if (metadata != null) {
|
if (metadata != null) {
|
||||||
mediaId = metadata.getString(MediaMetadata.METADATA_KEY_MEDIA_ID);
|
mediaId = metadata.getString(MediaMetadata.METADATA_KEY_MEDIA_ID);
|
||||||
String uriString = metadata.getString(MediaMetadata.METADATA_KEY_MEDIA_URI);
|
@Nullable String uriString = metadata.getString(MediaMetadata.METADATA_KEY_MEDIA_URI);
|
||||||
if (uriString != null) {
|
if (uri == null && uriString != null) {
|
||||||
uri = Uri.parse(uriString);
|
uri = Uri.parse(uriString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -102,8 +64,6 @@ public final class DefaultMediaItemConverter implements MediaItemConverter, Medi
|
|||||||
exoplayerMediaItemBuilder.setUri(uri);
|
exoplayerMediaItemBuilder.setUri(uri);
|
||||||
exoplayerMediaItemBuilder.setMediaId(mediaId);
|
exoplayerMediaItemBuilder.setMediaId(mediaId);
|
||||||
|
|
||||||
// These are actually aren't needed, because MediaSource will be generated only via tag.
|
|
||||||
// However, fills in the exoplayer2.MediaItem's fields as much as possible just in case.
|
|
||||||
if (androidXMediaItem.getStartPosition() != androidx.media2.common.MediaItem.POSITION_UNKNOWN) {
|
if (androidXMediaItem.getStartPosition() != androidx.media2.common.MediaItem.POSITION_UNKNOWN) {
|
||||||
exoplayerMediaItemBuilder.setClipStartPositionMs(androidXMediaItem.getStartPosition());
|
exoplayerMediaItemBuilder.setClipStartPositionMs(androidXMediaItem.getStartPosition());
|
||||||
exoplayerMediaItemBuilder.setClipRelativeToDefaultPosition(true);
|
exoplayerMediaItemBuilder.setClipRelativeToDefaultPosition(true);
|
||||||
@ -121,77 +81,11 @@ public final class DefaultMediaItemConverter implements MediaItemConverter, Medi
|
|||||||
Assertions.checkNotNull(exoplayerMediaItem);
|
Assertions.checkNotNull(exoplayerMediaItem);
|
||||||
MediaItem.PlaybackProperties playbackProperties =
|
MediaItem.PlaybackProperties playbackProperties =
|
||||||
Assertions.checkNotNull(exoplayerMediaItem.playbackProperties);
|
Assertions.checkNotNull(exoplayerMediaItem.playbackProperties);
|
||||||
Object tag = playbackProperties.tag;
|
@Nullable Object tag = playbackProperties.tag;
|
||||||
if (!(tag instanceof androidx.media2.common.MediaItem)) {
|
if (!(tag instanceof androidx.media2.common.MediaItem)) {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"DefaultMediaItemConverter cannot understand "
|
"MediaItem tag must be an instance of androidx.media2.common.MediaItem");
|
||||||
+ exoplayerMediaItem
|
|
||||||
+ ". Unexpected tag "
|
|
||||||
+ tag
|
|
||||||
+ " in PlaybackProperties");
|
|
||||||
}
|
}
|
||||||
return (androidx.media2.common.MediaItem) tag;
|
return (androidx.media2.common.MediaItem) tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements MediaSourceFactory
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MediaSourceFactory setDrmSessionManager(@Nullable DrmSessionManager drmSessionManager) {
|
|
||||||
// No-op
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MediaSourceFactory setLoadErrorHandlingPolicy(
|
|
||||||
@Nullable LoadErrorHandlingPolicy loadErrorHandlingPolicy) {
|
|
||||||
// No-op
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int[] getSupportedTypes() {
|
|
||||||
return SUPPORTED_TYPES;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MediaSource createMediaSource(com.google.android.exoplayer2.MediaItem exoplayerMediaItem) {
|
|
||||||
Assertions.checkNotNull(
|
|
||||||
exoplayerMediaItem.playbackProperties,
|
|
||||||
"DefaultMediaItemConverter cannot understand "
|
|
||||||
+ exoplayerMediaItem
|
|
||||||
+ ". PlaybackProperties is missing.");
|
|
||||||
Object tag = exoplayerMediaItem.playbackProperties.tag;
|
|
||||||
if (!(tag instanceof androidx.media2.common.MediaItem)) {
|
|
||||||
throw new IllegalStateException(
|
|
||||||
"DefaultMediaItemConverter cannot understand "
|
|
||||||
+ exoplayerMediaItem
|
|
||||||
+ ". Unexpected tag "
|
|
||||||
+ tag
|
|
||||||
+ " in PlaybackProperties");
|
|
||||||
}
|
|
||||||
androidx.media2.common.MediaItem androidXMediaItem = (androidx.media2.common.MediaItem) tag;
|
|
||||||
|
|
||||||
// Create a source for the item.
|
|
||||||
MediaSource mediaSource =
|
|
||||||
Utils.createUnclippedMediaSource(context, dataSourceFactory, androidXMediaItem);
|
|
||||||
|
|
||||||
// Apply clipping if needed.
|
|
||||||
long startPosition = androidXMediaItem.getStartPosition();
|
|
||||||
long endPosition = androidXMediaItem.getEndPosition();
|
|
||||||
if (startPosition != 0L || endPosition != androidx.media2.common.MediaItem.POSITION_UNKNOWN) {
|
|
||||||
if (endPosition == androidx.media2.common.MediaItem.POSITION_UNKNOWN) {
|
|
||||||
endPosition = C.TIME_END_OF_SOURCE;
|
|
||||||
}
|
|
||||||
// Disable the initial discontinuity to give seamless transitions to clips.
|
|
||||||
mediaSource =
|
|
||||||
new ClippingMediaSource(
|
|
||||||
mediaSource,
|
|
||||||
C.msToUs(startPosition),
|
|
||||||
C.msToUs(endPosition),
|
|
||||||
/* enableInitialDiscontinuity= */ false,
|
|
||||||
/* allowDynamicClippingUpdates= */ false,
|
|
||||||
/* relativeToDefaultPosition= */ true);
|
|
||||||
}
|
|
||||||
return mediaSource;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -19,15 +19,15 @@ import android.annotation.SuppressLint;
|
|||||||
import android.support.v4.media.session.MediaSessionCompat;
|
import android.support.v4.media.session.MediaSessionCompat;
|
||||||
import androidx.media2.session.MediaSession;
|
import androidx.media2.session.MediaSession;
|
||||||
|
|
||||||
/** Utility methods to use {@link MediaSession} with other existing Exo modules. */
|
/** Utility methods to use {@link MediaSession} with other ExoPlayer modules. */
|
||||||
public final class MediaSessionUtil {
|
public final class MediaSessionUtil {
|
||||||
|
|
||||||
/** Gets the {@link MediaSessionCompat.Token} from the {@link MediaSession}. */
|
/** Gets the {@link MediaSessionCompat.Token} from the {@link MediaSession}. */
|
||||||
// TODO(b/152764014): Deprecate this API when MediaSession#getSessionCompatToken() is released.
|
// TODO(b/152764014): Deprecate this API when MediaSession#getSessionCompatToken() is released.
|
||||||
public static MediaSessionCompat.Token getSessionCompatToken(MediaSession session2) {
|
public static MediaSessionCompat.Token getSessionCompatToken(MediaSession mediaSession) {
|
||||||
@SuppressLint("RestrictedApi")
|
@SuppressLint("RestrictedApi")
|
||||||
@SuppressWarnings("RestrictTo")
|
@SuppressWarnings("RestrictTo")
|
||||||
MediaSessionCompat sessionCompat = session2.getSessionCompat();
|
MediaSessionCompat sessionCompat = mediaSession.getSessionCompat();
|
||||||
return sessionCompat.getSessionToken();
|
return sessionCompat.getSessionToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,7 +126,7 @@ import java.util.List;
|
|||||||
* @param mediaItemConverter The {@link MediaItemConverter}.
|
* @param mediaItemConverter The {@link MediaItemConverter}.
|
||||||
* @param controlDispatcher A {@link ControlDispatcher}.
|
* @param controlDispatcher A {@link ControlDispatcher}.
|
||||||
*/
|
*/
|
||||||
PlayerWrapper(
|
public PlayerWrapper(
|
||||||
Listener listener,
|
Listener listener,
|
||||||
Player player,
|
Player player,
|
||||||
MediaItemConverter mediaItemConverter,
|
MediaItemConverter mediaItemConverter,
|
||||||
|
@ -15,81 +15,14 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.ext.media2;
|
package com.google.android.exoplayer2.ext.media2;
|
||||||
|
|
||||||
import android.content.ContentResolver;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.media.AudioAttributesCompat;
|
import androidx.media.AudioAttributesCompat;
|
||||||
import androidx.media2.common.CallbackMediaItem;
|
|
||||||
import androidx.media2.common.MediaItem;
|
|
||||||
import androidx.media2.common.SessionPlayer;
|
import androidx.media2.common.SessionPlayer;
|
||||||
import androidx.media2.common.UriMediaItem;
|
|
||||||
import com.google.android.exoplayer2.C;
|
|
||||||
import com.google.android.exoplayer2.Player;
|
import com.google.android.exoplayer2.Player;
|
||||||
import com.google.android.exoplayer2.audio.AudioAttributes;
|
import com.google.android.exoplayer2.audio.AudioAttributes;
|
||||||
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
|
|
||||||
import com.google.android.exoplayer2.extractor.ExtractorsFactory;
|
|
||||||
import com.google.android.exoplayer2.extractor.ts.AdtsExtractor;
|
|
||||||
import com.google.android.exoplayer2.source.MediaSource;
|
|
||||||
import com.google.android.exoplayer2.source.MediaSourceFactory;
|
|
||||||
import com.google.android.exoplayer2.source.ProgressiveMediaSource;
|
|
||||||
import com.google.android.exoplayer2.upstream.DataSource;
|
|
||||||
import com.google.android.exoplayer2.upstream.RawResourceDataSource;
|
|
||||||
import com.google.android.exoplayer2.util.Assertions;
|
|
||||||
import com.google.android.exoplayer2.util.Util;
|
|
||||||
|
|
||||||
/**
|
/** Utility methods for translating between the media2 and ExoPlayer APIs. */
|
||||||
* Utility methods for the media2 extension (primarily for translating between the media2 and
|
|
||||||
* ExoPlayer {@link Player} APIs).
|
|
||||||
*/
|
|
||||||
/* package */ final class Utils {
|
/* package */ final class Utils {
|
||||||
|
|
||||||
private static final ExtractorsFactory sExtractorsFactory =
|
|
||||||
new DefaultExtractorsFactory()
|
|
||||||
.setAdtsExtractorFlags(AdtsExtractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an ExoPlayer media source for the given media item. The given {@link MediaItem} is set
|
|
||||||
* as the tag of the source.
|
|
||||||
*/
|
|
||||||
public static MediaSource createUnclippedMediaSource(
|
|
||||||
Context context, DataSource.Factory dataSourceFactory, MediaItem androidXMediaItem) {
|
|
||||||
if (androidXMediaItem instanceof UriMediaItem) {
|
|
||||||
Uri uri = ((UriMediaItem) androidXMediaItem).getUri();
|
|
||||||
if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(uri.getScheme())) {
|
|
||||||
String path = Assertions.checkNotNull(uri.getPath());
|
|
||||||
int resourceIdentifier;
|
|
||||||
if (uri.getPathSegments().size() == 1 && uri.getPathSegments().get(0).matches("\\d+")) {
|
|
||||||
resourceIdentifier = Integer.parseInt(uri.getPathSegments().get(0));
|
|
||||||
} else {
|
|
||||||
if (path.startsWith("/")) {
|
|
||||||
path = path.substring(1);
|
|
||||||
}
|
|
||||||
@Nullable String host = uri.getHost();
|
|
||||||
String resourceName = (TextUtils.isEmpty(host) ? "" : (host + ":")) + path;
|
|
||||||
resourceIdentifier =
|
|
||||||
context.getResources().getIdentifier(resourceName, "raw", context.getPackageName());
|
|
||||||
}
|
|
||||||
Assertions.checkState(resourceIdentifier != 0);
|
|
||||||
uri = RawResourceDataSource.buildRawResourceUri(resourceIdentifier);
|
|
||||||
}
|
|
||||||
return createMediaSource(uri, dataSourceFactory, /* tag= */ androidXMediaItem);
|
|
||||||
} else if (androidXMediaItem instanceof CallbackMediaItem) {
|
|
||||||
CallbackMediaItem callbackMediaItem = (CallbackMediaItem) androidXMediaItem;
|
|
||||||
dataSourceFactory =
|
|
||||||
DataSourceCallbackDataSource.getFactory(callbackMediaItem.getDataSourceCallback());
|
|
||||||
return new ProgressiveMediaSource.Factory(dataSourceFactory, sExtractorsFactory)
|
|
||||||
.createMediaSource(
|
|
||||||
new com.google.android.exoplayer2.MediaItem.Builder()
|
|
||||||
.setUri(Uri.EMPTY)
|
|
||||||
.setTag(androidXMediaItem)
|
|
||||||
.build());
|
|
||||||
} else {
|
|
||||||
throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns ExoPlayer audio attributes for the given audio attributes. */
|
/** Returns ExoPlayer audio attributes for the given audio attributes. */
|
||||||
public static AudioAttributes getAudioAttributes(AudioAttributesCompat audioAttributesCompat) {
|
public static AudioAttributes getAudioAttributes(AudioAttributesCompat audioAttributesCompat) {
|
||||||
return new AudioAttributes.Builder()
|
return new AudioAttributes.Builder()
|
||||||
@ -156,49 +89,6 @@ import com.google.android.exoplayer2.util.Util;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MediaSource createMediaSource(
|
|
||||||
Uri uri, DataSource.Factory dataSourceFactory, Object tag) {
|
|
||||||
// TODO: Deduplicate with DefaultMediaSource once MediaItem support in ExoPlayer has been
|
|
||||||
// released. See [Internal: b/150857202].
|
|
||||||
@Nullable Class<? extends MediaSourceFactory> factoryClazz = null;
|
|
||||||
try {
|
|
||||||
// LINT.IfChange
|
|
||||||
switch (Util.inferContentType(uri)) {
|
|
||||||
case C.TYPE_DASH:
|
|
||||||
factoryClazz =
|
|
||||||
Class.forName("com.google.android.exoplayer2.source.dash.DashMediaSource$Factory")
|
|
||||||
.asSubclass(MediaSourceFactory.class);
|
|
||||||
break;
|
|
||||||
case C.TYPE_HLS:
|
|
||||||
factoryClazz =
|
|
||||||
Class.forName("com.google.android.exoplayer2.source.hls.HlsMediaSource$Factory")
|
|
||||||
.asSubclass(MediaSourceFactory.class);
|
|
||||||
break;
|
|
||||||
case C.TYPE_SS:
|
|
||||||
factoryClazz =
|
|
||||||
Class.forName(
|
|
||||||
"com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource$Factory")
|
|
||||||
.asSubclass(MediaSourceFactory.class);
|
|
||||||
break;
|
|
||||||
case C.TYPE_OTHER:
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (factoryClazz != null) {
|
|
||||||
MediaSourceFactory mediaSourceFactory =
|
|
||||||
factoryClazz.getConstructor(DataSource.Factory.class).newInstance(dataSourceFactory);
|
|
||||||
factoryClazz.getMethod("setTag", Object.class).invoke(mediaSourceFactory, tag);
|
|
||||||
return mediaSourceFactory.createMediaSource(
|
|
||||||
com.google.android.exoplayer2.MediaItem.fromUri(uri));
|
|
||||||
}
|
|
||||||
// LINT.ThenChange(../../../../../../../../../proguard-rules.txt)
|
|
||||||
} catch (Exception e) {
|
|
||||||
// Expected if the app was built without the corresponding module.
|
|
||||||
}
|
|
||||||
return new ProgressiveMediaSource.Factory(dataSourceFactory)
|
|
||||||
.createMediaSource(
|
|
||||||
new com.google.android.exoplayer2.MediaItem.Builder().setUri(uri).setTag(tag).build());
|
|
||||||
}
|
|
||||||
|
|
||||||
private Utils() {
|
private Utils() {
|
||||||
// Prevent instantiation.
|
// Prevent instantiation.
|
||||||
|
@ -1 +0,0 @@
|
|||||||
../../proguard-rules.txt
|
|
Loading…
x
Reference in New Issue
Block a user