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 f6a20485d8..3f9fd69253 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 @@ -473,9 +473,7 @@ public class PlayerActivity extends AppCompatActivity @Nullable private MediaSource createLeafMediaSource(UriSample parameters) { MediaItem.Builder builder = new MediaItem.Builder().setSourceUri(parameters.uri); - if (parameters.extension != null) { - builder.setExtension(parameters.extension); - } + builder.setMimeType(Sample.inferAdaptiveStreamMimeType(parameters.uri, parameters.extension)); int[] drmSessionForClearTypes = new int[0]; HttpDataSource.Factory drmDataSourceFactory = null; if (parameters.drmInfo != null) { diff --git a/demos/main/src/main/java/com/google/android/exoplayer2/demo/Sample.java b/demos/main/src/main/java/com/google/android/exoplayer2/demo/Sample.java index 2f01179cef..0d43bec890 100644 --- a/demos/main/src/main/java/com/google/android/exoplayer2/demo/Sample.java +++ b/demos/main/src/main/java/com/google/android/exoplayer2/demo/Sample.java @@ -35,6 +35,7 @@ import android.net.Uri; import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.util.Assertions; +import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.Util; import java.util.ArrayList; import java.util.HashSet; @@ -42,6 +43,31 @@ import java.util.UUID; /* package */ abstract class Sample { + /** + * Returns the mime type which is one of {@link MimeTypes#APPLICATION_MPD} for DASH, {@link + * MimeTypes#APPLICATION_M3U8} for HLS, {@link MimeTypes#APPLICATION_SS} for SmoothStreaming or + * {@code null} for all other streams. + * + * @param uri The uri of the stream. + * @param extension The extension + * @return The adaptive mime type or {@code null} for non-adaptive streams. + */ + @Nullable + public static String inferAdaptiveStreamMimeType(Uri uri, @Nullable String extension) { + @C.ContentType int contentType = Util.inferContentType(uri, extension); + switch (contentType) { + case C.TYPE_DASH: + return MimeTypes.APPLICATION_MPD; + case C.TYPE_HLS: + return MimeTypes.APPLICATION_M3U8; + case C.TYPE_SS: + return MimeTypes.APPLICATION_SS; + case C.TYPE_OTHER: + default: + return null; + } + } + public static final class UriSample extends Sample { public static UriSample createFromIntent(Uri uri, Intent intent, String extrasKeySuffix) { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/MediaItem.java b/library/core/src/main/java/com/google/android/exoplayer2/MediaItem.java index c4cff6195c..e2440983a9 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/MediaItem.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/MediaItem.java @@ -55,7 +55,7 @@ public final class MediaItem { @Nullable private String mediaId; @Nullable private Uri sourceUri; - @Nullable private String extension; + @Nullable private String mimeType; @Nullable private Uri drmLicenseUri; private Map drmLicenseRequestHeaders; @Nullable private UUID drmUuid; @@ -70,7 +70,7 @@ public final class MediaItem { } /** - * Sets the optional media id which identifies the media item. If not specified, {@code + * Sets the optional media id which identifies the media item. If not specified, {@link * #setSourceUri} must be called and the string representation of {@link * PlaybackProperties#sourceUri} is used as the media id. */ @@ -96,16 +96,17 @@ public final class MediaItem { } /** - * Sets the optional extension of the item. + * Sets the optional mime type. * - *

The extension can be used to disambiguate media items that have a uri which does not allow - * to infer the actual media type. + *

The mime type may be used as a hint for inferring the type of the media item. * - *

If a {@link PlaybackProperties#sourceUri} is set, the extension is used to create a {@link + *

If a {@link PlaybackProperties#sourceUri} is set, the mime type is used to create a {@link * PlaybackProperties} object. Otherwise it will be ignored. + * + * @param mimeType The mime type. */ - public Builder setExtension(@Nullable String extension) { - this.extension = extension; + public Builder setMimeType(@Nullable String mimeType) { + this.mimeType = mimeType; return this; } @@ -208,7 +209,7 @@ public final class MediaItem { playbackProperties = new PlaybackProperties( sourceUri, - extension, + mimeType, drmUuid != null ? new DrmConfiguration( drmUuid, drmLicenseUri, drmLicenseRequestHeaders, drmMultiSession) @@ -291,12 +292,12 @@ public final class MediaItem { public final Uri sourceUri; /** - * The optional extension of the item, or {@code null} if unspecified. + * The optional mime type of the item, or {@code null} if unspecified. * - *

The extension can be used to disambiguate media items that have a uri which does not allow + *

The mime type can be used to disambiguate media items that have a uri which does not allow * to infer the actual media type. */ - @Nullable public final String extension; + @Nullable public final String mimeType; /** Optional {@link DrmConfiguration} for the media. */ @Nullable public final DrmConfiguration drmConfiguration; @@ -313,12 +314,12 @@ public final class MediaItem { public PlaybackProperties( Uri sourceUri, - @Nullable String extension, + @Nullable String mimeType, @Nullable DrmConfiguration drmConfiguration, List streamKeys, @Nullable Object tag) { this.sourceUri = sourceUri; - this.extension = extension; + this.mimeType = mimeType; this.drmConfiguration = drmConfiguration; this.streamKeys = streamKeys; this.tag = tag; @@ -335,7 +336,7 @@ public final class MediaItem { PlaybackProperties other = (PlaybackProperties) obj; return sourceUri.equals(other.sourceUri) - && Util.areEqual(extension, other.extension) + && Util.areEqual(mimeType, other.mimeType) && Util.areEqual(drmConfiguration, other.drmConfiguration) && Util.areEqual(streamKeys, other.streamKeys) && Util.areEqual(tag, other.tag); @@ -344,7 +345,7 @@ public final class MediaItem { @Override public int hashCode() { int result = sourceUri.hashCode(); - result = 31 * result + (extension == null ? 0 : extension.hashCode()); + result = 31 * result + (mimeType == null ? 0 : mimeType.hashCode()); result = 31 * result + (drmConfiguration == null ? 0 : drmConfiguration.hashCode()); result = 31 * result + streamKeys.hashCode(); result = 31 * result + (tag == null ? 0 : tag.hashCode()); 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 index c18d8d413a..3ebbd7331f 100644 --- 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 @@ -16,6 +16,7 @@ package com.google.android.exoplayer2.source; import android.content.Context; +import android.net.Uri; import android.util.SparseArray; import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; @@ -34,6 +35,7 @@ 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.MimeTypes; import com.google.android.exoplayer2.util.Util; import java.util.Arrays; import java.util.List; @@ -47,19 +49,20 @@ import java.util.Map; * *