diff --git a/demos/main/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java b/demos/main/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java index 71c9c28c96..e633b7b4ae 100644 --- a/demos/main/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java +++ b/demos/main/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java @@ -32,7 +32,6 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import com.google.android.exoplayer2.C; -import com.google.android.exoplayer2.C.ContentType; import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.MediaItem; @@ -41,28 +40,18 @@ import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.RenderersFactory; import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.demo.Sample.UriSample; -import com.google.android.exoplayer2.drm.DefaultDrmSessionManager; -import com.google.android.exoplayer2.drm.DrmSessionManager; -import com.google.android.exoplayer2.drm.ExoMediaCrypto; -import com.google.android.exoplayer2.drm.FrameworkMediaDrm; -import com.google.android.exoplayer2.drm.HttpMediaDrmCallback; -import com.google.android.exoplayer2.drm.MediaDrmCallback; import com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.DecoderInitializationException; import com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException; import com.google.android.exoplayer2.offline.DownloadHelper; import com.google.android.exoplayer2.offline.DownloadRequest; import com.google.android.exoplayer2.source.BehindLiveWindowException; +import com.google.android.exoplayer2.source.DefaultMediaSourceFactory; import com.google.android.exoplayer2.source.MediaSource; -import com.google.android.exoplayer2.source.MediaSourceFactory; import com.google.android.exoplayer2.source.MergingMediaSource; -import com.google.android.exoplayer2.source.ProgressiveMediaSource; import com.google.android.exoplayer2.source.SingleSampleMediaSource; import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.source.ads.AdsLoader; import com.google.android.exoplayer2.source.ads.AdsMediaSource; -import com.google.android.exoplayer2.source.dash.DashMediaSource; -import com.google.android.exoplayer2.source.hls.HlsMediaSource; -import com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource; import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo; @@ -75,7 +64,6 @@ import com.google.android.exoplayer2.ui.PlayerView; import com.google.android.exoplayer2.ui.spherical.SphericalGLSurfaceView; import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.HttpDataSource; -import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.ErrorMessageProvider; import com.google.android.exoplayer2.util.EventLogger; import com.google.android.exoplayer2.util.Util; @@ -85,7 +73,9 @@ import java.net.CookieManager; import java.net.CookiePolicy; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** An activity that plays media using {@link SimpleExoPlayer}. */ public class PlayerActivity extends AppCompatActivity @@ -156,7 +146,7 @@ public class PlayerActivity extends AppCompatActivity private DefaultTrackSelector.Parameters trackSelectorParameters; private DebugTextViewHelper debugViewHelper; private TrackGroupArray lastSeenTrackGroupArray; - + private DefaultMediaSourceFactory mediaSourceFactory; private boolean startAutoPlay; private int startWindow; private long startPosition; @@ -177,6 +167,8 @@ public class PlayerActivity extends AppCompatActivity } super.onCreate(savedInstanceState); dataSourceFactory = buildDataSourceFactory(); + mediaSourceFactory = + DefaultMediaSourceFactory.newInstance(/* context= */ this, dataSourceFactory); if (CookieHandler.getDefault() != DEFAULT_COOKIE_MANAGER) { CookieHandler.setDefault(DEFAULT_COOKIE_MANAGER); } @@ -480,30 +472,28 @@ public class PlayerActivity extends AppCompatActivity @Nullable private MediaSource createLeafMediaSource(UriSample parameters) { - Sample.DrmInfo drmInfo = parameters.drmInfo; - int errorStringId = R.string.error_drm_unknown; - DrmSessionManager drmSessionManager = null; - if (drmInfo == null) { - drmSessionManager = DrmSessionManager.getDummyDrmSessionManager(); - } else if (Util.SDK_INT < 18) { - errorStringId = R.string.error_drm_unsupported_before_api_18; - } else if (!MediaDrm.isCryptoSchemeSupported(drmInfo.drmScheme)) { - errorStringId = R.string.error_drm_unsupported_scheme; - } else { - MediaDrmCallback mediaDrmCallback = - createMediaDrmCallback(drmInfo.drmLicenseUrl, drmInfo.drmKeyRequestProperties); - drmSessionManager = - new DefaultDrmSessionManager.Builder() - .setUuidAndExoMediaDrmProvider(drmInfo.drmScheme, FrameworkMediaDrm.DEFAULT_PROVIDER) - .setMultiSession(drmInfo.drmMultiSession) - .setUseDrmSessionsForClearContent(drmInfo.drmSessionForClearTypes) - .build(mediaDrmCallback); + MediaItem.Builder builder = new MediaItem.Builder().setSourceUri(parameters.uri); + if (parameters.extension != null) { + builder.setExtension(parameters.extension); } - - if (drmSessionManager == null) { - showToast(errorStringId); - finish(); - return null; + int[] drmSessionForClearTypes = new int[0]; + HttpDataSource.Factory drmDataSourceFactory = null; + if (parameters.drmInfo != null) { + if (Util.SDK_INT < 18) { + showToast(R.string.error_drm_unsupported_before_api_18); + finish(); + return null; + } else if (!MediaDrm.isCryptoSchemeSupported(parameters.drmInfo.drmScheme)) { + showToast(R.string.error_drm_unsupported_scheme); + finish(); + return null; + } + builder + .setDrmLicenseUri(createLicenseUriBundle(parameters.drmInfo)) + .setDrmUuid(parameters.drmInfo.drmScheme) + .setDrmMultiSession(parameters.drmInfo.drmMultiSession); + drmSessionForClearTypes = parameters.drmInfo.drmSessionForClearTypes; + drmDataSourceFactory = ((DemoApplication) getApplication()).buildHttpDataSourceFactory(); } DownloadRequest downloadRequest = @@ -513,47 +503,22 @@ public class PlayerActivity extends AppCompatActivity if (downloadRequest != null) { return DownloadHelper.createMediaSource(downloadRequest, dataSourceFactory); } - return createLeafMediaSource(parameters.uri, parameters.extension, drmSessionManager); + return mediaSourceFactory + .setDrmHttpDataSourceFactory(drmDataSourceFactory) + .setUseDrmSessionForClearContent(drmSessionForClearTypes) + .createMediaSource(builder.build()); } - private MediaSource createLeafMediaSource( - Uri uri, String extension, DrmSessionManager drmSessionManager) { - @ContentType int type = Util.inferContentType(uri, extension); - switch (type) { - case C.TYPE_DASH: - return new DashMediaSource.Factory(dataSourceFactory) - .setDrmSessionManager(drmSessionManager) - .createMediaSource(uri); - case C.TYPE_SS: - return new SsMediaSource.Factory(dataSourceFactory) - .setDrmSessionManager(drmSessionManager) - .createMediaSource(uri); - case C.TYPE_HLS: - return new HlsMediaSource.Factory(dataSourceFactory) - .setDrmSessionManager(drmSessionManager) - .createMediaSource(uri); - case C.TYPE_OTHER: - return new ProgressiveMediaSource.Factory(dataSourceFactory) - .setDrmSessionManager(drmSessionManager) - .createMediaSource(uri); - default: - throw new IllegalStateException("Unsupported type: " + type); + private static MediaItem.UriBundle createLicenseUriBundle(Sample.DrmInfo drmInfo) { + Uri licenseUri = Uri.parse(drmInfo.drmLicenseUrl); + if (drmInfo.drmKeyRequestProperties == null || drmInfo.drmKeyRequestProperties.length == 0) { + return new MediaItem.UriBundle(licenseUri); } - } - - private HttpMediaDrmCallback createMediaDrmCallback( - String licenseUrl, String[] keyRequestPropertiesArray) { - HttpDataSource.Factory licenseDataSourceFactory = - ((DemoApplication) getApplication()).buildHttpDataSourceFactory(); - HttpMediaDrmCallback drmCallback = - new HttpMediaDrmCallback(licenseUrl, licenseDataSourceFactory); - if (keyRequestPropertiesArray != null) { - for (int i = 0; i < keyRequestPropertiesArray.length - 1; i += 2) { - drmCallback.setKeyRequestProperty(keyRequestPropertiesArray[i], - keyRequestPropertiesArray[i + 1]); - } + Map headers = new HashMap<>(); + for (int i = 0; i < drmInfo.drmKeyRequestProperties.length; i += 2) { + headers.put(drmInfo.drmKeyRequestProperties[i], drmInfo.drmKeyRequestProperties[i + 1]); } - return drmCallback; + return new MediaItem.UriBundle(licenseUri, headers); } private void releasePlayer() { @@ -623,35 +588,7 @@ public class PlayerActivity extends AppCompatActivity // LINT.ThenChange(../../../../../../../../proguard-rules.txt) adsLoader = loaderConstructor.newInstance(this, adTagUri); } - MediaSourceFactory adMediaSourceFactory = - new MediaSourceFactory() { - - private DrmSessionManager drmSessionManager = - DrmSessionManager.getDummyDrmSessionManager(); - - @Override - @NonNull - public MediaSourceFactory setDrmSessionManager(DrmSessionManager drmSessionManager) { - this.drmSessionManager = drmSessionManager; - return this; - } - - @Override - @NonNull - public MediaSource createMediaSource(@NonNull MediaItem mediaItem) { - Assertions.checkNotNull(mediaItem.playbackProperties); - return PlayerActivity.this.createLeafMediaSource( - mediaItem.playbackProperties.sourceUri, - mediaItem.playbackProperties.extension, - drmSessionManager); - } - - @Override - public int[] getSupportedTypes() { - return new int[] {C.TYPE_DASH, C.TYPE_SS, C.TYPE_HLS, C.TYPE_OTHER}; - } - }; - return new AdsMediaSource(mediaSource, adMediaSourceFactory, adsLoader, playerView); + return new AdsMediaSource(mediaSource, mediaSourceFactory, adsLoader, playerView); } catch (ClassNotFoundException e) { // IMA extension not loaded. return null; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/DefaultMediaSourceFactory.java b/library/core/src/main/java/com/google/android/exoplayer2/source/DefaultMediaSourceFactory.java new file mode 100644 index 0000000000..311a3fcc98 --- /dev/null +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/DefaultMediaSourceFactory.java @@ -0,0 +1,329 @@ +/* + * Copyright 2020 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.source; + +import android.content.Context; +import android.util.SparseArray; +import androidx.annotation.Nullable; +import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.ExoPlayerLibraryInfo; +import com.google.android.exoplayer2.MediaItem; +import com.google.android.exoplayer2.drm.DefaultDrmSessionManager; +import com.google.android.exoplayer2.drm.DrmSessionManager; +import com.google.android.exoplayer2.drm.FrameworkMediaDrm; +import com.google.android.exoplayer2.drm.HttpMediaDrmCallback; +import com.google.android.exoplayer2.drm.MediaDrmCallback; +import com.google.android.exoplayer2.offline.StreamKey; +import com.google.android.exoplayer2.upstream.DataSource; +import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; +import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory; +import com.google.android.exoplayer2.upstream.DefaultLoadErrorHandlingPolicy; +import com.google.android.exoplayer2.upstream.HttpDataSource; +import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy; +import com.google.android.exoplayer2.util.Assertions; +import com.google.android.exoplayer2.util.Util; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +/** + * The default {@link MediaSourceFactory} implementation. + * + *

This implementation delegates calls to {@link #createMediaSource(MediaItem)} to the following + * factories: + * + *

+ * + *

DrmSessionManager creation for protected content

+ * + *

For a media item with a valid {@link + * com.google.android.exoplayer2.MediaItem.DrmConfiguration}, a {@link DefaultDrmSessionManager} is + * created. The following setters can be used to optionally configure the creation: + * + *

+ * + *

For media items without a drm configuration {@link DrmSessionManager#DUMMY} is used. To use an + * alternative dummy, apps can pass a drm session manager to {@link + * #setDrmSessionManager(DrmSessionManager)} which will be used for all items without a drm + * configuration. + */ +public final class DefaultMediaSourceFactory implements MediaSourceFactory { + + /** + * A media source factory to which calls to {@link #createMediaSource(MediaItem)} calls are + * delegated by the {@link DefaultMediaSourceFactory}. + */ + public interface Delegate extends MediaSourceFactory { + /** + * Sets an optional {@link LoadErrorHandlingPolicy}. + * + * @param loadErrorHandlingPolicy A {@link LoadErrorHandlingPolicy}. + * @return This factory, for convenience. + */ + MediaSourceFactory setLoadErrorHandlingPolicy( + @Nullable LoadErrorHandlingPolicy loadErrorHandlingPolicy); + } + + /** + * Creates a new instance with the given {@link Context}. + * + *

This is functionally equivalent with calling {@code #newInstance(Context, + * DefaultDataSourceFactory)}. + * + * @param context The {@link Context}. + */ + public static DefaultMediaSourceFactory newInstance(Context context) { + return newInstance( + context, + new DefaultDataSourceFactory( + context, Util.getUserAgent(context, ExoPlayerLibraryInfo.VERSION_SLASHY))); + } + + /** + * Creates a new instance with the given {@link Context} and {@link DataSource.Factory}. + * + * @param context The {@link Context}. + * @param dataSourceFactory A {@link DataSource.Factory} to be used to create media sources. + */ + public static DefaultMediaSourceFactory newInstance( + Context context, DataSource.Factory dataSourceFactory) { + return new DefaultMediaSourceFactory(context, dataSourceFactory); + } + + private final SparseArray mediaSourceFactories; + @C.ContentType private final int[] supportedTypes; + private final String userAgent; + + private DrmSessionManager drmSessionManager; + private HttpDataSource.Factory drmHttpDataSourceFactory; + private boolean playClearContentWithoutKey; + private int[] useDrmSessionsForClearContentTrackTypes; + @Nullable private List streamKeys; + + private DefaultMediaSourceFactory(Context context, DataSource.Factory dataSourceFactory) { + drmSessionManager = DrmSessionManager.getDummyDrmSessionManager(); + userAgent = Util.getUserAgent(context, ExoPlayerLibraryInfo.VERSION_SLASHY); + drmHttpDataSourceFactory = new DefaultHttpDataSourceFactory(userAgent); + useDrmSessionsForClearContentTrackTypes = new int[0]; + mediaSourceFactories = loadDelegates(dataSourceFactory); + supportedTypes = new int[mediaSourceFactories.size()]; + for (int i = 0; i < mediaSourceFactories.size(); i++) { + supportedTypes[i] = mediaSourceFactories.keyAt(i); + } + } + + /** + * Sets the {@link HttpDataSource.Factory} to be used for creating {@link HttpMediaDrmCallback + * HttpMediaDrmCallbacks} which executes key and provisioning requests over HTTP. If {@code null} + * is passed the {@link DefaultHttpDataSourceFactory} is used. + * + * @param drmHttpDataSourceFactory The HTTP data source factory or {@code null} to use {@link + * DefaultHttpDataSourceFactory}. + * @return This factory, for convenience. + */ + public DefaultMediaSourceFactory setDrmHttpDataSourceFactory( + @Nullable HttpDataSource.Factory drmHttpDataSourceFactory) { + this.drmHttpDataSourceFactory = + drmHttpDataSourceFactory != null + ? drmHttpDataSourceFactory + : new DefaultHttpDataSourceFactory(userAgent); + return this; + } + + /** + * Used to create {@link DrmSessionManager DrmSessionManagers}. See {@link + * DefaultDrmSessionManager.Builder#setPlayClearSamplesWithoutKeys(boolean)}. + * + * @return This factory, for convenience. + */ + public DefaultMediaSourceFactory setPlayClearContentWithoutKey( + boolean playClearContentWithoutKey) { + this.playClearContentWithoutKey = playClearContentWithoutKey; + return this; + } + + /** + * Used to create {@link DrmSessionManager DrmSessionManagers}. See {@link + * DefaultDrmSessionManager.Builder#setUseDrmSessionsForClearContent(int...)}. + * + * @return This factory, for convenience. + */ + public DefaultMediaSourceFactory setUseDrmSessionForClearContent( + int... useDrmSessionsForClearContentTrackTypes) { + for (int trackType : useDrmSessionsForClearContentTrackTypes) { + Assertions.checkArgument(trackType == C.TRACK_TYPE_VIDEO || trackType == C.TRACK_TYPE_AUDIO); + } + this.useDrmSessionsForClearContentTrackTypes = useDrmSessionsForClearContentTrackTypes.clone(); + return this; + } + + @Override + public DefaultMediaSourceFactory setDrmSessionManager( + @Nullable DrmSessionManager drmSessionManager) { + this.drmSessionManager = + drmSessionManager != null + ? drmSessionManager + : DrmSessionManager.getDummyDrmSessionManager(); + return this; + } + + public DefaultMediaSourceFactory setLoadErrorHandlingPolicy( + @Nullable LoadErrorHandlingPolicy loadErrorHandlingPolicy) { + LoadErrorHandlingPolicy newLoadErrorHandlingPolicy = + loadErrorHandlingPolicy != null + ? loadErrorHandlingPolicy + : new DefaultLoadErrorHandlingPolicy(); + for (int i = 0; i < mediaSourceFactories.size(); i++) { + mediaSourceFactories.valueAt(i).setLoadErrorHandlingPolicy(newLoadErrorHandlingPolicy); + } + return this; + } + + /** + * @deprecated Use {@link MediaItem.Builder#setStreamKeys(List)} and {@link + * #createMediaSource(MediaItem)} instead. + */ + @SuppressWarnings("deprecation") + @Deprecated + @Override + public DefaultMediaSourceFactory setStreamKeys(@Nullable List streamKeys) { + this.streamKeys = streamKeys != null && !streamKeys.isEmpty() ? streamKeys : null; + return this; + } + + @Override + public int[] getSupportedTypes() { + return Arrays.copyOf(supportedTypes, supportedTypes.length); + } + + @SuppressWarnings("deprecation") + @Override + public MediaSource createMediaSource(MediaItem mediaItem) { + Assertions.checkNotNull(mediaItem.playbackProperties); + @C.ContentType + int type = + Util.inferContentType( + mediaItem.playbackProperties.sourceUri, mediaItem.playbackProperties.extension); + @Nullable MediaSourceFactory mediaSourceFactory = mediaSourceFactories.get(type); + Assertions.checkNotNull( + mediaSourceFactory, "No suitable media source factory found for content type: " + type); + mediaSourceFactory.setDrmSessionManager(createDrmSessionManager(mediaItem)); + mediaSourceFactory.setStreamKeys( + !mediaItem.playbackProperties.streamKeys.isEmpty() + ? mediaItem.playbackProperties.streamKeys + : streamKeys); + return mediaSourceFactory.createMediaSource(mediaItem); + } + + // internal methods + + private DrmSessionManager createDrmSessionManager(MediaItem mediaItem) { + Assertions.checkNotNull(mediaItem.playbackProperties); + if (mediaItem.playbackProperties.drmConfiguration == null + || mediaItem.playbackProperties.drmConfiguration.licenseUri == null + || Util.SDK_INT < 18) { + return drmSessionManager; + } + return new DefaultDrmSessionManager.Builder() + .setUuidAndExoMediaDrmProvider( + mediaItem.playbackProperties.drmConfiguration.uuid, FrameworkMediaDrm.DEFAULT_PROVIDER) + .setMultiSession(mediaItem.playbackProperties.drmConfiguration.multiSession) + .setPlayClearSamplesWithoutKeys(playClearContentWithoutKey) + .setUseDrmSessionsForClearContent(useDrmSessionsForClearContentTrackTypes) + .build(createHttpMediaDrmCallback(mediaItem.playbackProperties.drmConfiguration)); + } + + private MediaDrmCallback createHttpMediaDrmCallback(MediaItem.DrmConfiguration drmConfiguration) { + Assertions.checkNotNull(drmConfiguration.licenseUri); + HttpMediaDrmCallback drmCallback = + new HttpMediaDrmCallback( + drmConfiguration.licenseUri.uri.toString(), drmHttpDataSourceFactory); + for (Map.Entry entry : drmConfiguration.licenseUri.requestHeaders.entrySet()) { + drmCallback.setKeyRequestProperty(entry.getKey(), entry.getValue()); + } + return drmCallback; + } + + private static SparseArray loadDelegates(DataSource.Factory dataSourceFactory) { + SparseArray delegates = new SparseArray<>(); + // LINT.IfChange + try { + Class factoryClazz = + Class.forName("com.google.android.exoplayer2.source.dash.DashMediaSource$Factory") + .asSubclass(DefaultMediaSourceFactory.Delegate.class); + delegates.put( + C.TYPE_DASH, + factoryClazz.getConstructor(DataSource.Factory.class).newInstance(dataSourceFactory)); + } catch (Exception e) { + // Expected if the app was built without the dash module. + } + try { + Class factoryClazz = + Class.forName( + "com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource$Factory") + .asSubclass(DefaultMediaSourceFactory.Delegate.class); + delegates.put( + C.TYPE_SS, + factoryClazz.getConstructor(DataSource.Factory.class).newInstance(dataSourceFactory)); + } catch (Exception e) { + // Expected if the app was built without the smoothstreaming module. + } + try { + Class factoryClazz = + Class.forName("com.google.android.exoplayer2.source.hls.HlsMediaSource$Factory") + .asSubclass(DefaultMediaSourceFactory.Delegate.class); + delegates.put( + C.TYPE_HLS, + factoryClazz.getConstructor(DataSource.Factory.class).newInstance(dataSourceFactory)); + } catch (Exception e) { + // Expected if the app was built without the hls module. + } + // LINT.ThenChange(../../../../../../../../proguard-rules.txt) + delegates.put(C.TYPE_OTHER, new ProgressiveMediaSource.Factory(dataSourceFactory)); + return delegates; + } +} diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaSource.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaSource.java index 49478d0bf0..51d00e502c 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaSource.java @@ -112,7 +112,7 @@ public final class ExtractorMediaSource extends CompositeMediaSource { } /** - * @deprecated Use {@link MediaItem.PlaybackProperties#tag} and {@link + * @deprecated Use {@link MediaItem.Builder#setTag(Object)} and {@link * #createMediaSource(MediaItem)} instead. */ @Deprecated diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaSource.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaSource.java index dd7a0e743c..c570fd67d5 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaSource.java @@ -47,7 +47,7 @@ public final class ProgressiveMediaSource extends BaseMediaSource implements ProgressiveMediaPeriod.Listener { /** Factory for {@link ProgressiveMediaSource}s. */ - public static final class Factory implements MediaSourceFactory { + public static final class Factory implements DefaultMediaSourceFactory.Delegate { private final DataSource.Factory dataSourceFactory; @@ -108,7 +108,7 @@ public final class ProgressiveMediaSource extends BaseMediaSource } /** - * @deprecated Use {@link MediaItem.PlaybackProperties#tag} and {@link + * @deprecated Use {@link MediaItem.Builder#setTag(Object)} and {@link * #createMediaSource(MediaItem)} instead. */ @Deprecated diff --git a/library/core/src/test/java/com/google/android/exoplayer2/source/DefaultMediaSourceFactoryTest.java b/library/core/src/test/java/com/google/android/exoplayer2/source/DefaultMediaSourceFactoryTest.java new file mode 100644 index 0000000000..935119a9a4 --- /dev/null +++ b/library/core/src/test/java/com/google/android/exoplayer2/source/DefaultMediaSourceFactoryTest.java @@ -0,0 +1,92 @@ +/* + * Copyright 2020 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.source; + +import static com.google.common.truth.Truth.assertThat; + +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.MediaItem; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** Unit test for {@link DefaultMediaSourceFactory}. */ +@RunWith(AndroidJUnit4.class) +public final class DefaultMediaSourceFactoryTest { + + private static final String URI_MEDIA = "http://exoplayer.dev/video"; + + @Test + public void createMediaSource_withExtension_progressiveSource() { + DefaultMediaSourceFactory defaultMediaSourceFactory = + DefaultMediaSourceFactory.newInstance(ApplicationProvider.getApplicationContext()); + MediaItem mediaItem = + new MediaItem.Builder().setSourceUri(URI_MEDIA).setExtension("mp4").build(); + + MediaSource mediaSource = defaultMediaSourceFactory.createMediaSource(mediaItem); + + assertThat(mediaSource).isInstanceOf(ProgressiveMediaSource.class); + } + + @Test + public void createMediaSource_withTag_tagInSource() { + Object tag = new Object(); + DefaultMediaSourceFactory defaultMediaSourceFactory = + DefaultMediaSourceFactory.newInstance(ApplicationProvider.getApplicationContext()); + MediaItem mediaItem = new MediaItem.Builder().setSourceUri(URI_MEDIA).setTag(tag).build(); + + MediaSource mediaSource = defaultMediaSourceFactory.createMediaSource(mediaItem); + + assertThat(mediaSource.getTag()).isEqualTo(tag); + } + + @Test + public void createMediaSource_withPath_progressiveSource() { + DefaultMediaSourceFactory defaultMediaSourceFactory = + DefaultMediaSourceFactory.newInstance(ApplicationProvider.getApplicationContext()); + MediaItem mediaItem = new MediaItem.Builder().setSourceUri(URI_MEDIA + "/file.mp3").build(); + + MediaSource mediaSource = defaultMediaSourceFactory.createMediaSource(mediaItem); + + assertThat(mediaSource).isInstanceOf(ProgressiveMediaSource.class); + } + + @Test + public void createMediaSource_withNull_usesNonNullDefaults() { + DefaultMediaSourceFactory defaultMediaSourceFactory = + DefaultMediaSourceFactory.newInstance(ApplicationProvider.getApplicationContext()); + MediaItem mediaItem = new MediaItem.Builder().setSourceUri(URI_MEDIA).build(); + + MediaSource mediaSource = + defaultMediaSourceFactory + .setDrmSessionManager(null) + .setDrmHttpDataSourceFactory(null) + .setLoadErrorHandlingPolicy(null) + .createMediaSource(mediaItem); + + assertThat(mediaSource).isNotNull(); + } + + @Test + public void getSupportedTypes_coreModule_onlyOther() { + int[] supportedTypes = + DefaultMediaSourceFactory.newInstance(ApplicationProvider.getApplicationContext()) + .getSupportedTypes(); + + assertThat(supportedTypes).asList().containsExactly(C.TYPE_OTHER); + } +} diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java index 75b2505d76..f705f3027d 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java @@ -33,11 +33,11 @@ import com.google.android.exoplayer2.offline.StreamKey; import com.google.android.exoplayer2.source.BaseMediaSource; import com.google.android.exoplayer2.source.CompositeSequenceableLoaderFactory; import com.google.android.exoplayer2.source.DefaultCompositeSequenceableLoaderFactory; +import com.google.android.exoplayer2.source.DefaultMediaSourceFactory; 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.source.MediaSourceEventListener.EventDispatcher; -import com.google.android.exoplayer2.source.MediaSourceFactory; import com.google.android.exoplayer2.source.SequenceableLoader; import com.google.android.exoplayer2.source.dash.PlayerEmsgHandler.PlayerEmsgCallback; import com.google.android.exoplayer2.source.dash.manifest.AdaptationSet; @@ -79,7 +79,7 @@ public final class DashMediaSource extends BaseMediaSource { } /** Factory for {@link DashMediaSource}s. */ - public static final class Factory implements MediaSourceFactory { + public static final class Factory implements DefaultMediaSourceFactory.Delegate { private final DashChunkSource.Factory chunkSourceFactory; @Nullable private final DataSource.Factory manifestDataSourceFactory; @@ -125,7 +125,7 @@ public final class DashMediaSource extends BaseMediaSource { } /** - * @deprecated Use {@link MediaItem.PlaybackProperties#tag} and {@link + * @deprecated Use {@link MediaItem.Builder#setTag(Object)} and {@link * #createMediaSource(MediaItem)} instead. */ @Deprecated @@ -135,7 +135,7 @@ public final class DashMediaSource extends BaseMediaSource { } /** - * @deprecated Use {@link MediaItem.PlaybackProperties#streamKeys} and {@link + * @deprecated Use {@link MediaItem.Builder#setStreamKeys(List)} and {@link * #createMediaSource(MediaItem)} instead. */ @SuppressWarnings("deprecation") diff --git a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/DefaultMediaSourceFactoryTest.java b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/DefaultMediaSourceFactoryTest.java new file mode 100644 index 0000000000..0905924fcb --- /dev/null +++ b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/DefaultMediaSourceFactoryTest.java @@ -0,0 +1,95 @@ +/* + * Copyright 2020 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.source.dash; + +import static com.google.common.truth.Truth.assertThat; + +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.MediaItem; +import com.google.android.exoplayer2.source.DefaultMediaSourceFactory; +import com.google.android.exoplayer2.source.MediaSource; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** Unit test for creating DASH media sources with the {@link DefaultMediaSourceFactory}. */ +@RunWith(AndroidJUnit4.class) +public class DefaultMediaSourceFactoryTest { + + private static final String URI_MEDIA = "http://exoplayer.dev/video"; + + @Test + public void createMediaSource_withExtension_dashSource() { + DefaultMediaSourceFactory defaultMediaSourceFactory = + DefaultMediaSourceFactory.newInstance(ApplicationProvider.getApplicationContext()); + MediaItem mediaItem = + new MediaItem.Builder().setSourceUri(URI_MEDIA).setExtension("mpd").build(); + + MediaSource mediaSource = defaultMediaSourceFactory.createMediaSource(mediaItem); + + assertThat(mediaSource).isInstanceOf(DashMediaSource.class); + } + + @Test + public void createMediaSource_withTag_tagInSource() { + Object tag = new Object(); + DefaultMediaSourceFactory defaultMediaSourceFactory = + DefaultMediaSourceFactory.newInstance(ApplicationProvider.getApplicationContext()); + MediaItem mediaItem = + new MediaItem.Builder().setSourceUri(URI_MEDIA).setExtension("mpd").setTag(tag).build(); + + MediaSource mediaSource = defaultMediaSourceFactory.createMediaSource(mediaItem); + + assertThat(mediaSource.getTag()).isEqualTo(tag); + } + + @Test + public void createMediaSource_withPath_dashSource() { + DefaultMediaSourceFactory defaultMediaSourceFactory = + DefaultMediaSourceFactory.newInstance(ApplicationProvider.getApplicationContext()); + MediaItem mediaItem = new MediaItem.Builder().setSourceUri(URI_MEDIA + "/file.mpd").build(); + + MediaSource mediaSource = defaultMediaSourceFactory.createMediaSource(mediaItem); + + assertThat(mediaSource).isInstanceOf(DashMediaSource.class); + } + + @Test + public void createMediaSource_withNull_usesNonNullDefaults() { + DefaultMediaSourceFactory defaultMediaSourceFactory = + DefaultMediaSourceFactory.newInstance(ApplicationProvider.getApplicationContext()); + MediaItem mediaItem = new MediaItem.Builder().setSourceUri(URI_MEDIA + "/file.mpd").build(); + + MediaSource mediaSource = + defaultMediaSourceFactory + .setDrmSessionManager(null) + .setDrmHttpDataSourceFactory(null) + .setLoadErrorHandlingPolicy(null) + .createMediaSource(mediaItem); + + assertThat(mediaSource).isNotNull(); + } + + @Test + public void getSupportedTypes_dashModule_containsTypeDash() { + int[] supportedTypes = + DefaultMediaSourceFactory.newInstance(ApplicationProvider.getApplicationContext()) + .getSupportedTypes(); + + assertThat(supportedTypes).asList().containsExactly(C.TYPE_OTHER, C.TYPE_DASH); + } +} diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaSource.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaSource.java index 01b42c194c..174da0608f 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaSource.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaSource.java @@ -31,11 +31,11 @@ import com.google.android.exoplayer2.offline.StreamKey; import com.google.android.exoplayer2.source.BaseMediaSource; import com.google.android.exoplayer2.source.CompositeSequenceableLoaderFactory; import com.google.android.exoplayer2.source.DefaultCompositeSequenceableLoaderFactory; +import com.google.android.exoplayer2.source.DefaultMediaSourceFactory; 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.source.MediaSourceEventListener.EventDispatcher; -import com.google.android.exoplayer2.source.MediaSourceFactory; import com.google.android.exoplayer2.source.SequenceableLoader; import com.google.android.exoplayer2.source.SinglePeriodTimeline; import com.google.android.exoplayer2.source.hls.playlist.DefaultHlsPlaylistParserFactory; @@ -87,7 +87,7 @@ public final class HlsMediaSource extends BaseMediaSource public static final int METADATA_TYPE_EMSG = 3; /** Factory for {@link HlsMediaSource}s. */ - public static final class Factory implements MediaSourceFactory { + public static final class Factory implements DefaultMediaSourceFactory.Delegate { private final HlsDataSourceFactory hlsDataSourceFactory; @@ -133,7 +133,7 @@ public final class HlsMediaSource extends BaseMediaSource } /** - * @deprecated Use {@link MediaItem.PlaybackProperties#tag} and {@link + * @deprecated Use {@link MediaItem.Builder#setTag(Object)} and {@link * #createMediaSource(MediaItem)} instead. */ @Deprecated @@ -299,7 +299,7 @@ public final class HlsMediaSource extends BaseMediaSource } /** - * @deprecated Use {@link MediaItem.PlaybackProperties#streamKeys} and {@link + * @deprecated Use {@link MediaItem.Builder#setStreamKeys(List)} and {@link * #createMediaSource(MediaItem)} instead. */ @SuppressWarnings("deprecation") diff --git a/library/hls/src/test/java/com/google/android/exoplayer2/source/hls/DefaultMediaSourceFactoryTest.java b/library/hls/src/test/java/com/google/android/exoplayer2/source/hls/DefaultMediaSourceFactoryTest.java new file mode 100644 index 0000000000..9f9576c7ff --- /dev/null +++ b/library/hls/src/test/java/com/google/android/exoplayer2/source/hls/DefaultMediaSourceFactoryTest.java @@ -0,0 +1,95 @@ +/* + * Copyright 2020 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.source.hls; + +import static com.google.common.truth.Truth.assertThat; + +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.MediaItem; +import com.google.android.exoplayer2.source.DefaultMediaSourceFactory; +import com.google.android.exoplayer2.source.MediaSource; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** Unit test for creating HLS media sources with the {@link DefaultMediaSourceFactory}. */ +@RunWith(AndroidJUnit4.class) +public class DefaultMediaSourceFactoryTest { + + private static final String URI_MEDIA = "http://exoplayer.dev/video"; + + @Test + public void createMediaSource_withExtension_hlsSource() { + DefaultMediaSourceFactory defaultMediaSourceFactory = + DefaultMediaSourceFactory.newInstance(ApplicationProvider.getApplicationContext()); + MediaItem mediaItem = + new MediaItem.Builder().setSourceUri(URI_MEDIA).setExtension("m3u8").build(); + + MediaSource mediaSource = defaultMediaSourceFactory.createMediaSource(mediaItem); + + assertThat(mediaSource).isInstanceOf(HlsMediaSource.class); + } + + @Test + public void createMediaSource_withTag_tagInSource() { + Object tag = new Object(); + DefaultMediaSourceFactory defaultMediaSourceFactory = + DefaultMediaSourceFactory.newInstance(ApplicationProvider.getApplicationContext()); + MediaItem mediaItem = + new MediaItem.Builder().setSourceUri(URI_MEDIA).setExtension("m3u8").setTag(tag).build(); + + MediaSource mediaSource = defaultMediaSourceFactory.createMediaSource(mediaItem); + + assertThat(mediaSource.getTag()).isEqualTo(tag); + } + + @Test + public void testCreateMediaSource_withPath_hlsSource() { + DefaultMediaSourceFactory defaultMediaSourceFactory = + DefaultMediaSourceFactory.newInstance(ApplicationProvider.getApplicationContext()); + MediaItem mediaItem = new MediaItem.Builder().setSourceUri(URI_MEDIA + "/file.m3u8").build(); + + MediaSource mediaSource = defaultMediaSourceFactory.createMediaSource(mediaItem); + + assertThat(mediaSource).isInstanceOf(HlsMediaSource.class); + } + + @Test + public void createMediaSource_withNull_usesNonNullDefaults() { + DefaultMediaSourceFactory defaultMediaSourceFactory = + DefaultMediaSourceFactory.newInstance(ApplicationProvider.getApplicationContext()); + MediaItem mediaItem = new MediaItem.Builder().setSourceUri(URI_MEDIA + "/file.m3u8").build(); + + MediaSource mediaSource = + defaultMediaSourceFactory + .setDrmSessionManager(null) + .setDrmHttpDataSourceFactory(null) + .setLoadErrorHandlingPolicy(null) + .createMediaSource(mediaItem); + + assertThat(mediaSource).isNotNull(); + } + + @Test + public void getSupportedTypes_hlsModule_containsTypeHls() { + int[] supportedTypes = + DefaultMediaSourceFactory.newInstance(ApplicationProvider.getApplicationContext()) + .getSupportedTypes(); + + assertThat(supportedTypes).asList().containsExactly(C.TYPE_OTHER, C.TYPE_HLS); + } +} diff --git a/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaSource.java b/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaSource.java index b18bad63a2..929e0a0b4e 100644 --- a/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaSource.java +++ b/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaSource.java @@ -30,11 +30,11 @@ import com.google.android.exoplayer2.offline.StreamKey; import com.google.android.exoplayer2.source.BaseMediaSource; import com.google.android.exoplayer2.source.CompositeSequenceableLoaderFactory; import com.google.android.exoplayer2.source.DefaultCompositeSequenceableLoaderFactory; +import com.google.android.exoplayer2.source.DefaultMediaSourceFactory; 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.source.MediaSourceEventListener.EventDispatcher; -import com.google.android.exoplayer2.source.MediaSourceFactory; import com.google.android.exoplayer2.source.SequenceableLoader; import com.google.android.exoplayer2.source.SinglePeriodTimeline; import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest; @@ -66,7 +66,7 @@ public final class SsMediaSource extends BaseMediaSource } /** Factory for {@link SsMediaSource}. */ - public static final class Factory implements MediaSourceFactory { + public static final class Factory implements DefaultMediaSourceFactory.Delegate { private final SsChunkSource.Factory chunkSourceFactory; @Nullable private final DataSource.Factory manifestDataSourceFactory; @@ -111,7 +111,7 @@ public final class SsMediaSource extends BaseMediaSource } /** - * @deprecated Use {@link MediaItem.PlaybackProperties#tag} and {@link + * @deprecated Use {@link MediaItem.Builder#setTag(Object)} and {@link * #createMediaSource(MediaItem)} instead. */ @Deprecated @@ -206,7 +206,7 @@ public final class SsMediaSource extends BaseMediaSource } /** - * @deprecated Use {@link MediaItem.PlaybackProperties#streamKeys} and {@link + * @deprecated Use {@link MediaItem.Builder#setStreamKeys(List)} and {@link * #createMediaSource(MediaItem)} instead. */ @SuppressWarnings("deprecation") diff --git a/library/smoothstreaming/src/test/java/com/google/android/exoplayer2/source/smoothstreaming/DefaultMediaSourceFactoryTest.java b/library/smoothstreaming/src/test/java/com/google/android/exoplayer2/source/smoothstreaming/DefaultMediaSourceFactoryTest.java new file mode 100644 index 0000000000..3e16f19ac0 --- /dev/null +++ b/library/smoothstreaming/src/test/java/com/google/android/exoplayer2/source/smoothstreaming/DefaultMediaSourceFactoryTest.java @@ -0,0 +1,106 @@ +/* + * Copyright 2020 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.source.smoothstreaming; + +import static com.google.common.truth.Truth.assertThat; + +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.MediaItem; +import com.google.android.exoplayer2.source.DefaultMediaSourceFactory; +import com.google.android.exoplayer2.source.MediaSource; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Unit test for creating SmoothStreaming media sources with the {@link DefaultMediaSourceFactory}. + */ +@RunWith(AndroidJUnit4.class) +public class DefaultMediaSourceFactoryTest { + + private static final String URI_MEDIA = "http://exoplayer.dev/video"; + + @Test + public void createMediaSource_withExtension_smoothstreamingSource() { + DefaultMediaSourceFactory defaultMediaSourceFactory = + DefaultMediaSourceFactory.newInstance(ApplicationProvider.getApplicationContext()); + MediaItem mediaItem = + new MediaItem.Builder().setSourceUri(URI_MEDIA).setExtension("ism").build(); + MediaSource mediaSource = defaultMediaSourceFactory.createMediaSource(mediaItem); + assertThat(mediaSource).isInstanceOf(SsMediaSource.class); + } + + @Test + public void createMediaSource_withTag_tagInSource() { + Object tag = new Object(); + DefaultMediaSourceFactory defaultMediaSourceFactory = + DefaultMediaSourceFactory.newInstance(ApplicationProvider.getApplicationContext()); + MediaItem mediaItem = + new MediaItem.Builder().setSourceUri(URI_MEDIA).setExtension("ism").setTag(tag).build(); + + MediaSource mediaSource = defaultMediaSourceFactory.createMediaSource(mediaItem); + + assertThat(mediaSource.getTag()).isEqualTo(tag); + } + + @Test + public void createMediaSource_withIsmPath_smoothstreamingSource() { + DefaultMediaSourceFactory defaultMediaSourceFactory = + DefaultMediaSourceFactory.newInstance(ApplicationProvider.getApplicationContext()); + MediaItem mediaItem = new MediaItem.Builder().setSourceUri(URI_MEDIA + "/file.ism").build(); + + MediaSource mediaSource = defaultMediaSourceFactory.createMediaSource(mediaItem); + + assertThat(mediaSource).isInstanceOf(SsMediaSource.class); + } + + @Test + public void testCreateMediaSource_withManifestPath_smoothstreamingSource() { + DefaultMediaSourceFactory defaultMediaSourceFactory = + DefaultMediaSourceFactory.newInstance(ApplicationProvider.getApplicationContext()); + MediaItem mediaItem = new MediaItem.Builder().setSourceUri(URI_MEDIA + ".ism/Manifest").build(); + + MediaSource mediaSource = defaultMediaSourceFactory.createMediaSource(mediaItem); + + assertThat(mediaSource).isInstanceOf(SsMediaSource.class); + } + + @Test + public void createMediaSource_withNull_usesNonNullDefaults() { + DefaultMediaSourceFactory defaultMediaSourceFactory = + DefaultMediaSourceFactory.newInstance(ApplicationProvider.getApplicationContext()); + MediaItem mediaItem = new MediaItem.Builder().setSourceUri(URI_MEDIA + "/file.ism").build(); + + MediaSource mediaSource = + defaultMediaSourceFactory + .setDrmSessionManager(null) + .setDrmHttpDataSourceFactory(null) + .setLoadErrorHandlingPolicy(null) + .createMediaSource(mediaItem); + + assertThat(mediaSource).isNotNull(); + } + + @Test + public void getSupportedTypes_smoothstreamingModule_containsTypeSS() { + int[] supportedTypes = + DefaultMediaSourceFactory.newInstance(ApplicationProvider.getApplicationContext()) + .getSupportedTypes(); + + assertThat(supportedTypes).asList().containsExactly(C.TYPE_OTHER, C.TYPE_SS); + } +}