mirror of
https://github.com/samsonjs/media.git
synced 2026-03-26 09:35:47 +00:00
Increase flexibility of ISM URL handling
PiperOrigin-RevId: 326025335
This commit is contained in:
parent
607e11718b
commit
511a6c729e
5 changed files with 56 additions and 43 deletions
|
|
@ -142,8 +142,7 @@ public final class Util {
|
|||
private static final Pattern ESCAPED_CHARACTER_PATTERN = Pattern.compile("%([A-Fa-f0-9]{2})");
|
||||
|
||||
// https://docs.microsoft.com/en-us/azure/media-services/previous/media-services-deliver-content-overview#URLs.
|
||||
private static final Pattern ISM_URL_PATTERN =
|
||||
Pattern.compile(".*\\.ism(?:l)?(?:/(?:manifest(?:\\((.+)\\))?)?)?");
|
||||
private static final Pattern ISM_URL_PATTERN = Pattern.compile(".*\\.isml?(?:/(manifest(.*))?)?");
|
||||
private static final String ISM_HLS_FORMAT_EXTENSION = "format=m3u8-aapl";
|
||||
private static final String ISM_DASH_FORMAT_EXTENSION = "format=mpd-time-csf";
|
||||
|
||||
|
|
@ -1723,7 +1722,7 @@ public final class Util {
|
|||
}
|
||||
Matcher ismMatcher = ISM_URL_PATTERN.matcher(fileName);
|
||||
if (ismMatcher.matches()) {
|
||||
@Nullable String extensions = ismMatcher.group(1);
|
||||
@Nullable String extensions = ismMatcher.group(2);
|
||||
if (extensions != null) {
|
||||
if (extensions.contains(ISM_DASH_FORMAT_EXTENSION)) {
|
||||
return C.TYPE_DASH;
|
||||
|
|
@ -1779,6 +1778,27 @@ public final class Util {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the provided URI is an ISM Presentation URI, returns the URI with "Manifest" appended to its
|
||||
* path (i.e., the corresponding default manifest URI). Else returns the provided URI without
|
||||
* modification. See [MS-SSTR] v20180912, section 2.2.1.
|
||||
*
|
||||
* @param uri The original URI.
|
||||
* @return The fixed URI.
|
||||
*/
|
||||
public static Uri fixSmoothStreamingIsmManifestUri(Uri uri) {
|
||||
@Nullable String path = toLowerInvariant(uri.getPath());
|
||||
if (path == null) {
|
||||
return uri;
|
||||
}
|
||||
Matcher ismMatcher = ISM_URL_PATTERN.matcher(path);
|
||||
if (ismMatcher.matches() && ismMatcher.group(1) == null) {
|
||||
// Add missing "Manifest" suffix.
|
||||
return Uri.withAppendedPath(uri, "Manifest");
|
||||
}
|
||||
return uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the specified millisecond time formatted as a string.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import static com.google.common.truth.Truth.assertThat;
|
|||
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.net.Uri;
|
||||
import android.text.SpannableString;
|
||||
import android.text.Spanned;
|
||||
import android.text.style.StrikethroughSpan;
|
||||
|
|
@ -127,13 +128,39 @@ public class UtilTest {
|
|||
assertThat(Util.inferContentType("http://a.b/c.ism/Manifest")).isEqualTo(C.TYPE_SS);
|
||||
assertThat(Util.inferContentType("http://a.b/c.isml/manifest")).isEqualTo(C.TYPE_SS);
|
||||
assertThat(Util.inferContentType("http://a.b/c.isml/manifest(filter=x)")).isEqualTo(C.TYPE_SS);
|
||||
assertThat(Util.inferContentType("http://a.b/c.isml/manifest_hd")).isEqualTo(C.TYPE_SS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inferContentType_handlesOtherIsmUris() {
|
||||
assertThat(Util.inferContentType("http://a.b/c.ism/video.mp4")).isEqualTo(C.TYPE_OTHER);
|
||||
assertThat(Util.inferContentType("http://a.b/c.ism/prefix-manifest")).isEqualTo(C.TYPE_OTHER);
|
||||
assertThat(Util.inferContentType("http://a.b/c.ism/manifest-suffix")).isEqualTo(C.TYPE_OTHER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fixSmoothStreamingIsmManifestUri_addsManifestSuffix() {
|
||||
assertThat(Util.fixSmoothStreamingIsmManifestUri(Uri.parse("http://a.b/c.ism")))
|
||||
.isEqualTo(Uri.parse("http://a.b/c.ism/Manifest"));
|
||||
assertThat(Util.fixSmoothStreamingIsmManifestUri(Uri.parse("http://a.b/c.isml")))
|
||||
.isEqualTo(Uri.parse("http://a.b/c.isml/Manifest"));
|
||||
|
||||
assertThat(Util.fixSmoothStreamingIsmManifestUri(Uri.parse("http://a.b/c.ism/")))
|
||||
.isEqualTo(Uri.parse("http://a.b/c.ism/Manifest"));
|
||||
assertThat(Util.fixSmoothStreamingIsmManifestUri(Uri.parse("http://a.b/c.isml/")))
|
||||
.isEqualTo(Uri.parse("http://a.b/c.isml/Manifest"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fixSmoothStreamingIsmManifestUri_doesNotAlterManifestUri() {
|
||||
assertThat(Util.fixSmoothStreamingIsmManifestUri(Uri.parse("http://a.b/c.ism/Manifest")))
|
||||
.isEqualTo(Uri.parse("http://a.b/c.ism/Manifest"));
|
||||
assertThat(Util.fixSmoothStreamingIsmManifestUri(Uri.parse("http://a.b/c.isml/Manifest")))
|
||||
.isEqualTo(Uri.parse("http://a.b/c.isml/Manifest"));
|
||||
assertThat(
|
||||
Util.fixSmoothStreamingIsmManifestUri(Uri.parse("http://a.b/c.ism/Manifest(filter=x)")))
|
||||
.isEqualTo(Uri.parse("http://a.b/c.ism/Manifest(filter=x)"));
|
||||
assertThat(Util.fixSmoothStreamingIsmManifestUri(Uri.parse("http://a.b/c.ism/Manifest_hd")))
|
||||
.isEqualTo(Uri.parse("http://a.b/c.ism/Manifest_hd"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -47,7 +47,6 @@ import com.google.android.exoplayer2.source.SinglePeriodTimeline;
|
|||
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest;
|
||||
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest.StreamElement;
|
||||
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifestParser;
|
||||
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsUtil;
|
||||
import com.google.android.exoplayer2.upstream.Allocator;
|
||||
import com.google.android.exoplayer2.upstream.DataSource;
|
||||
import com.google.android.exoplayer2.upstream.DefaultLoadErrorHandlingPolicy;
|
||||
|
|
@ -581,7 +580,7 @@ public final class SsMediaSource extends BaseMediaSource
|
|||
this.manifestUri =
|
||||
playbackProperties.uri.equals(Uri.EMPTY)
|
||||
? null
|
||||
: SsUtil.fixManifestUri(playbackProperties.uri);
|
||||
: Util.fixSmoothStreamingIsmManifestUri(playbackProperties.uri);
|
||||
this.manifestDataSourceFactory = manifestDataSourceFactory;
|
||||
this.manifestParser = manifestParser;
|
||||
this.chunkSourceFactory = chunkSourceFactory;
|
||||
|
|
|
|||
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2018 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.manifest;
|
||||
|
||||
import android.net.Uri;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
|
||||
/** SmoothStreaming related utility methods. */
|
||||
public final class SsUtil {
|
||||
|
||||
/** Returns a fixed SmoothStreaming client manifest {@link Uri}. */
|
||||
public static Uri fixManifestUri(Uri manifestUri) {
|
||||
String lastPathSegment = manifestUri.getLastPathSegment();
|
||||
if (lastPathSegment != null
|
||||
&& Util.toLowerInvariant(lastPathSegment).matches("manifest(\\(.+\\))?")) {
|
||||
return manifestUri;
|
||||
}
|
||||
return Uri.withAppendedPath(manifestUri, "Manifest");
|
||||
}
|
||||
|
||||
private SsUtil() {}
|
||||
}
|
||||
|
|
@ -24,11 +24,11 @@ import com.google.android.exoplayer2.offline.StreamKey;
|
|||
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest;
|
||||
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest.StreamElement;
|
||||
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifestParser;
|
||||
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsUtil;
|
||||
import com.google.android.exoplayer2.upstream.DataSource;
|
||||
import com.google.android.exoplayer2.upstream.DataSpec;
|
||||
import com.google.android.exoplayer2.upstream.ParsingLoadable.Parser;
|
||||
import com.google.android.exoplayer2.upstream.cache.CacheDataSource;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
|
|
@ -112,7 +112,9 @@ public final class SsDownloader extends SegmentDownloader<SsManifest> {
|
|||
this(
|
||||
mediaItem
|
||||
.buildUpon()
|
||||
.setUri(SsUtil.fixManifestUri(checkNotNull(mediaItem.playbackProperties).uri))
|
||||
.setUri(
|
||||
Util.fixSmoothStreamingIsmManifestUri(
|
||||
checkNotNull(mediaItem.playbackProperties).uri))
|
||||
.build(),
|
||||
new SsManifestParser(),
|
||||
cacheDataSourceFactory,
|
||||
|
|
|
|||
Loading…
Reference in a new issue