diff options
Diffstat (limited to 'mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/upstream/ResolvingDataSource.java')
-rw-r--r-- | mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/upstream/ResolvingDataSource.java | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/upstream/ResolvingDataSource.java b/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/upstream/ResolvingDataSource.java new file mode 100644 index 0000000000..80046e1757 --- /dev/null +++ b/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/upstream/ResolvingDataSource.java @@ -0,0 +1,132 @@ +/* + * Copyright (C) 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 org.mozilla.thirdparty.com.google.android.exoplayer2.upstream; + +import android.net.Uri; +import androidx.annotation.Nullable; +import java.io.IOException; +import java.util.List; +import java.util.Map; + +/** {@link DataSource} wrapper allowing just-in-time resolution of {@link DataSpec DataSpecs}. */ +public final class ResolvingDataSource implements DataSource { + + /** Resolves {@link DataSpec DataSpecs}. */ + public interface Resolver { + + /** + * Resolves a {@link DataSpec} before forwarding it to the wrapped {@link DataSource}. This + * method is allowed to block until the {@link DataSpec} has been resolved. + * + * <p>Note that this method is called for every new connection, so caching of results is + * recommended, especially if network operations are involved. + * + * @param dataSpec The original {@link DataSpec}. + * @return The resolved {@link DataSpec}. + * @throws IOException If an {@link IOException} occurred while resolving the {@link DataSpec}. + */ + DataSpec resolveDataSpec(DataSpec dataSpec) throws IOException; + + /** + * Resolves a URI reported by {@link DataSource#getUri()} for event reporting and caching + * purposes. + * + * <p>Implementations do not need to overwrite this method unless they want to change the + * reported URI. + * + * <p>This method is <em>not</em> allowed to block. + * + * @param uri The URI as reported by {@link DataSource#getUri()}. + * @return The resolved URI used for event reporting and caching. + */ + default Uri resolveReportedUri(Uri uri) { + return uri; + } + } + + /** {@link DataSource.Factory} for {@link ResolvingDataSource} instances. */ + public static final class Factory implements DataSource.Factory { + + private final DataSource.Factory upstreamFactory; + private final Resolver resolver; + + /** + * @param upstreamFactory The wrapped {@link DataSource.Factory} for handling resolved {@link + * DataSpec DataSpecs}. + * @param resolver The {@link Resolver} to resolve the {@link DataSpec DataSpecs}. + */ + public Factory(DataSource.Factory upstreamFactory, Resolver resolver) { + this.upstreamFactory = upstreamFactory; + this.resolver = resolver; + } + + @Override + public ResolvingDataSource createDataSource() { + return new ResolvingDataSource(upstreamFactory.createDataSource(), resolver); + } + } + + private final DataSource upstreamDataSource; + private final Resolver resolver; + + private boolean upstreamOpened; + + /** + * @param upstreamDataSource The wrapped {@link DataSource}. + * @param resolver The {@link Resolver} to resolve the {@link DataSpec DataSpecs}. + */ + public ResolvingDataSource(DataSource upstreamDataSource, Resolver resolver) { + this.upstreamDataSource = upstreamDataSource; + this.resolver = resolver; + } + + @Override + public void addTransferListener(TransferListener transferListener) { + upstreamDataSource.addTransferListener(transferListener); + } + + @Override + public long open(DataSpec dataSpec) throws IOException { + DataSpec resolvedDataSpec = resolver.resolveDataSpec(dataSpec); + upstreamOpened = true; + return upstreamDataSource.open(resolvedDataSpec); + } + + @Override + public int read(byte[] buffer, int offset, int readLength) throws IOException { + return upstreamDataSource.read(buffer, offset, readLength); + } + + @Nullable + @Override + public Uri getUri() { + Uri reportedUri = upstreamDataSource.getUri(); + return reportedUri == null ? null : resolver.resolveReportedUri(reportedUri); + } + + @Override + public Map<String, List<String>> getResponseHeaders() { + return upstreamDataSource.getResponseHeaders(); + } + + @Override + public void close() throws IOException { + if (upstreamOpened) { + upstreamOpened = false; + upstreamDataSource.close(); + } + } +} |