Separate UriDataSource from HttpDataSource.

Using a file:// URL for loading an HLS stream (for testing) would fail due to
casting the connection to an HttpURLConnection in DefaultHttpDataSource.

This change makes UriDataSource an interface for objects that are DataSources
with URIs. That allows for reading manifests for HLS using just a UriDataSource
rather than an HttpDataSource (URLs in the playlist are relative to the data
source's URL so the getUri method is needed).
This commit is contained in:
Oliver Woodman 2015-04-22 16:22:48 +01:00
parent d43d55edeb
commit 1a01dcc55a
16 changed files with 167 additions and 132 deletions

View File

@ -52,8 +52,8 @@ import com.google.android.exoplayer.upstream.BufferPool;
import com.google.android.exoplayer.upstream.DataSource;
import com.google.android.exoplayer.upstream.DefaultBandwidthMeter;
import com.google.android.exoplayer.upstream.DefaultHttpDataSource;
import com.google.android.exoplayer.upstream.DefaultUriDataSource;
import com.google.android.exoplayer.upstream.HttpDataSource;
import com.google.android.exoplayer.upstream.UriDataSource;
import com.google.android.exoplayer.util.ManifestFetcher;
import com.google.android.exoplayer.util.ManifestFetcher.ManifestCallback;
import com.google.android.exoplayer.util.MimeTypes;
@ -247,7 +247,7 @@ public class DashRendererBuilder implements RendererBuilder,
debugRenderer = null;
} else {
int[] videoRepresentationIndices = Util.toArray(videoRepresentationIndexList);
DataSource videoDataSource = new UriDataSource(userAgent, bandwidthMeter);
DataSource videoDataSource = new DefaultUriDataSource(userAgent, bandwidthMeter);
ChunkSource videoChunkSource = new DashChunkSource(manifestFetcher, videoAdaptationSetIndex,
videoRepresentationIndices, videoDataSource, new AdaptiveEvaluator(bandwidthMeter),
LIVE_EDGE_LATENCY_MS, elapsedRealtimeOffset);
@ -265,7 +265,7 @@ public class DashRendererBuilder implements RendererBuilder,
List<String> audioTrackNameList = new ArrayList<String>();
int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
if (audioAdaptationSet != null) {
DataSource audioDataSource = new UriDataSource(userAgent, bandwidthMeter);
DataSource audioDataSource = new DefaultUriDataSource(userAgent, bandwidthMeter);
FormatEvaluator audioEvaluator = new FormatEvaluator.FixedEvaluator();
List<Representation> audioRepresentations = audioAdaptationSet.representations;
List<String> codecs = new ArrayList<String>();
@ -321,7 +321,7 @@ public class DashRendererBuilder implements RendererBuilder,
}
// Build the text chunk sources.
DataSource textDataSource = new UriDataSource(userAgent, bandwidthMeter);
DataSource textDataSource = new DefaultUriDataSource(userAgent, bandwidthMeter);
FormatEvaluator textEvaluator = new FormatEvaluator.FixedEvaluator();
List<ChunkSource> textChunkSourceList = new ArrayList<ChunkSource>();
List<String> textTrackNameList = new ArrayList<String>();

View File

@ -23,7 +23,7 @@ import com.google.android.exoplayer.demo.player.DemoPlayer.RendererBuilderCallba
import com.google.android.exoplayer.extractor.Extractor;
import com.google.android.exoplayer.extractor.ExtractorSampleSource;
import com.google.android.exoplayer.upstream.DataSource;
import com.google.android.exoplayer.upstream.UriDataSource;
import com.google.android.exoplayer.upstream.DefaultUriDataSource;
import android.media.MediaCodec;
import android.net.Uri;
@ -52,7 +52,7 @@ public class ExtractorRendererBuilder implements RendererBuilder {
@Override
public void buildRenderers(DemoPlayer player, RendererBuilderCallback callback) {
// Build the video and audio renderers.
DataSource dataSource = new UriDataSource(userAgent, null);
DataSource dataSource = new DefaultUriDataSource(userAgent, null);
ExtractorSampleSource sampleSource = new ExtractorSampleSource(uri, dataSource, extractor, 2,
BUFFER_SIZE);
MediaCodecVideoTrackRenderer videoRenderer = new MediaCodecVideoTrackRenderer(sampleSource,

View File

@ -30,7 +30,7 @@ import com.google.android.exoplayer.text.eia608.Eia608TrackRenderer;
import com.google.android.exoplayer.upstream.DataSource;
import com.google.android.exoplayer.upstream.DefaultBandwidthMeter;
import com.google.android.exoplayer.upstream.DefaultHttpDataSource;
import com.google.android.exoplayer.upstream.UriDataSource;
import com.google.android.exoplayer.upstream.DefaultUriDataSource;
import com.google.android.exoplayer.util.ManifestFetcher;
import com.google.android.exoplayer.util.ManifestFetcher.ManifestCallback;
@ -79,7 +79,7 @@ public class HlsRendererBuilder implements RendererBuilder, ManifestCallback<Hls
Handler mainHandler = player.getMainHandler();
DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
DataSource dataSource = new UriDataSource(userAgent, bandwidthMeter);
DataSource dataSource = new DefaultUriDataSource(userAgent, bandwidthMeter);
HlsChunkSource chunkSource = new HlsChunkSource(dataSource, url, manifest, bandwidthMeter, null,
HlsChunkSource.ADAPTIVE_MODE_SPLICE);
HlsSampleSource sampleSource = new HlsSampleSource(chunkSource, true, 3, mainHandler, player,

View File

@ -43,7 +43,7 @@ import com.google.android.exoplayer.upstream.BufferPool;
import com.google.android.exoplayer.upstream.DataSource;
import com.google.android.exoplayer.upstream.DefaultBandwidthMeter;
import com.google.android.exoplayer.upstream.DefaultHttpDataSource;
import com.google.android.exoplayer.upstream.UriDataSource;
import com.google.android.exoplayer.upstream.DefaultUriDataSource;
import com.google.android.exoplayer.util.ManifestFetcher;
import com.google.android.exoplayer.util.Util;
@ -164,7 +164,7 @@ public class SmoothStreamingRendererBuilder implements RendererBuilder,
debugRenderer = null;
} else {
int[] videoTrackIndices = Util.toArray(videoTrackIndexList);
DataSource videoDataSource = new UriDataSource(userAgent, bandwidthMeter);
DataSource videoDataSource = new DefaultUriDataSource(userAgent, bandwidthMeter);
ChunkSource videoChunkSource = new SmoothStreamingChunkSource(manifestFetcher,
videoStreamElementIndex, videoTrackIndices, videoDataSource,
new AdaptiveEvaluator(bandwidthMeter), LIVE_EDGE_LATENCY_MS);
@ -188,7 +188,7 @@ public class SmoothStreamingRendererBuilder implements RendererBuilder,
} else {
audioTrackNames = new String[audioStreamElementCount];
ChunkSource[] audioChunkSources = new ChunkSource[audioStreamElementCount];
DataSource audioDataSource = new UriDataSource(userAgent, bandwidthMeter);
DataSource audioDataSource = new DefaultUriDataSource(userAgent, bandwidthMeter);
FormatEvaluator audioFormatEvaluator = new FormatEvaluator.FixedEvaluator();
audioStreamElementCount = 0;
for (int i = 0; i < manifest.streamElements.length; i++) {
@ -219,7 +219,7 @@ public class SmoothStreamingRendererBuilder implements RendererBuilder,
} else {
textTrackNames = new String[textStreamElementCount];
ChunkSource[] textChunkSources = new ChunkSource[textStreamElementCount];
DataSource ttmlDataSource = new UriDataSource(userAgent, bandwidthMeter);
DataSource ttmlDataSource = new DefaultUriDataSource(userAgent, bandwidthMeter);
FormatEvaluator ttmlFormatEvaluator = new FormatEvaluator.FixedEvaluator();
textStreamElementCount = 0;
for (int i = 0; i < manifest.streamElements.length; i++) {

View File

@ -21,7 +21,7 @@ import com.google.android.exoplayer.dash.mpd.SegmentBase.SegmentList;
import com.google.android.exoplayer.dash.mpd.SegmentBase.SegmentTemplate;
import com.google.android.exoplayer.dash.mpd.SegmentBase.SegmentTimelineElement;
import com.google.android.exoplayer.dash.mpd.SegmentBase.SingleSegmentBase;
import com.google.android.exoplayer.upstream.NetworkLoadable;
import com.google.android.exoplayer.upstream.UriLoadable;
import com.google.android.exoplayer.util.Assertions;
import com.google.android.exoplayer.util.MimeTypes;
import com.google.android.exoplayer.util.UriUtil;
@ -48,7 +48,7 @@ import java.util.regex.Pattern;
* A parser of media presentation description files.
*/
public class MediaPresentationDescriptionParser extends DefaultHandler
implements NetworkLoadable.Parser<MediaPresentationDescription> {
implements UriLoadable.Parser<MediaPresentationDescription> {
private static final Pattern FRAME_RATE_PATTERN = Pattern.compile("(\\d+)(?:/(\\d+))??");

View File

@ -16,10 +16,10 @@
package com.google.android.exoplayer.dash.mpd;
import com.google.android.exoplayer.ParserException;
import com.google.android.exoplayer.upstream.HttpDataSource;
import com.google.android.exoplayer.upstream.Loader;
import com.google.android.exoplayer.upstream.Loader.Loadable;
import com.google.android.exoplayer.upstream.NetworkLoadable;
import com.google.android.exoplayer.upstream.UriDataSource;
import com.google.android.exoplayer.upstream.UriLoadable;
import com.google.android.exoplayer.util.Assertions;
import com.google.android.exoplayer.util.Util;
@ -64,34 +64,34 @@ public class UtcTimingElementResolver implements Loader.Callback {
void onTimestampError(UtcTimingElement utcTiming, IOException e);
}
private final HttpDataSource httpDataSource;
private final UriDataSource uriDataSource;
private final UtcTimingElement timingElement;
private final long timingElementElapsedRealtime;
private final UtcTimingCallback callback;
private Loader singleUseLoader;
private NetworkLoadable<Long> singleUseLoadable;
private UriLoadable<Long> singleUseLoadable;
/**
* Resolves a {@link UtcTimingElement}.
*
* @param httpDataSource A source to use should network requests be necessary.
* @param uriDataSource A source to use should loading from a URI be necessary.
* @param timingElement The element to resolve.
* @param timingElementElapsedRealtime The {@link SystemClock#elapsedRealtime()} timestamp at
* which the element was obtained. Used if the element contains a timestamp directly.
* @param callback The callback to invoke on resolution or failure.
*/
public static void resolveTimingElement(HttpDataSource httpDataSource,
public static void resolveTimingElement(UriDataSource uriDataSource,
UtcTimingElement timingElement, long timingElementElapsedRealtime,
UtcTimingCallback callback) {
UtcTimingElementResolver resolver = new UtcTimingElementResolver(httpDataSource, timingElement,
UtcTimingElementResolver resolver = new UtcTimingElementResolver(uriDataSource, timingElement,
timingElementElapsedRealtime, callback);
resolver.resolve();
}
private UtcTimingElementResolver(HttpDataSource httpDataSource, UtcTimingElement timingElement,
private UtcTimingElementResolver(UriDataSource uriDataSource, UtcTimingElement timingElement,
long timingElementElapsedRealtime, UtcTimingCallback callback) {
this.httpDataSource = httpDataSource;
this.uriDataSource = uriDataSource;
this.timingElement = Assertions.checkNotNull(timingElement);
this.timingElementElapsedRealtime = timingElementElapsedRealtime;
this.callback = Assertions.checkNotNull(callback);
@ -122,9 +122,9 @@ public class UtcTimingElementResolver implements Loader.Callback {
}
}
private void resolveHttp(NetworkLoadable.Parser<Long> parser) {
private void resolveHttp(UriLoadable.Parser<Long> parser) {
singleUseLoader = new Loader("utctiming");
singleUseLoadable = new NetworkLoadable<Long>(timingElement.value, httpDataSource, parser);
singleUseLoadable = new UriLoadable<Long>(timingElement.value, uriDataSource, parser);
singleUseLoader.startLoading(singleUseLoadable, this);
}
@ -150,7 +150,7 @@ public class UtcTimingElementResolver implements Loader.Callback {
singleUseLoader.release();
}
private static class XsDateTimeParser implements NetworkLoadable.Parser<Long> {
private static class XsDateTimeParser implements UriLoadable.Parser<Long> {
@Override
public Long parse(String connectionUrl, InputStream inputStream) throws ParserException,
@ -165,7 +165,7 @@ public class UtcTimingElementResolver implements Loader.Callback {
}
private static class Iso8601Parser implements NetworkLoadable.Parser<Long> {
private static class Iso8601Parser implements UriLoadable.Parser<Long> {
@Override
public Long parse(String connectionUrl, InputStream inputStream) throws ParserException,

View File

@ -18,7 +18,7 @@ package com.google.android.exoplayer.hls;
import com.google.android.exoplayer.C;
import com.google.android.exoplayer.ParserException;
import com.google.android.exoplayer.hls.HlsMediaPlaylist.Segment;
import com.google.android.exoplayer.upstream.NetworkLoadable;
import com.google.android.exoplayer.upstream.UriLoadable;
import java.io.BufferedReader;
import java.io.IOException;
@ -34,7 +34,7 @@ import java.util.regex.Pattern;
/**
* HLS playlists parsing logic.
*/
public final class HlsPlaylistParser implements NetworkLoadable.Parser<HlsPlaylist> {
public final class HlsPlaylistParser implements UriLoadable.Parser<HlsPlaylist> {
private static final String VERSION_TAG = "#EXT-X-VERSION";
private static final String STREAM_INF_TAG = "#EXT-X-STREAM-INF";

View File

@ -19,7 +19,7 @@ import com.google.android.exoplayer.ParserException;
import com.google.android.exoplayer.smoothstreaming.SmoothStreamingManifest.ProtectionElement;
import com.google.android.exoplayer.smoothstreaming.SmoothStreamingManifest.StreamElement;
import com.google.android.exoplayer.smoothstreaming.SmoothStreamingManifest.TrackElement;
import com.google.android.exoplayer.upstream.NetworkLoadable;
import com.google.android.exoplayer.upstream.UriLoadable;
import com.google.android.exoplayer.util.Assertions;
import com.google.android.exoplayer.util.CodecSpecificDataUtil;
import com.google.android.exoplayer.util.MimeTypes;
@ -44,8 +44,7 @@ import java.util.UUID;
* @see <a href="http://msdn.microsoft.com/en-us/library/ee673436(v=vs.90).aspx">
* IIS Smooth Streaming Client Manifest Format</a>
*/
public class SmoothStreamingManifestParser implements
NetworkLoadable.Parser<SmoothStreamingManifest> {
public class SmoothStreamingManifestParser implements UriLoadable.Parser<SmoothStreamingManifest> {
private final XmlPullParserFactory xmlParserFactory;

View File

@ -41,7 +41,7 @@ public interface DataSource {
* unresolved. For all other requests, the value returned will be equal to the request's
* {@link DataSpec#length}.
*/
public long open(DataSpec dataSpec) throws IOException;
long open(DataSpec dataSpec) throws IOException;
/**
* Closes the {@link DataSource}.
@ -51,7 +51,7 @@ public interface DataSource {
*
* @throws IOException If an error occurs closing the source.
*/
public void close() throws IOException;
void close() throws IOException;
/**
* Reads up to {@code length} bytes of data and stores them into {@code buffer}, starting at
@ -67,6 +67,6 @@ public interface DataSource {
* range is reached.
* @throws IOException If an error occurs reading from the source.
*/
public int read(byte[] buffer, int offset, int readLength) throws IOException;
int read(byte[] buffer, int offset, int readLength) throws IOException;
}

View File

@ -112,7 +112,7 @@ public class DefaultHttpDataSource implements HttpDataSource {
}
@Override
public String getUrl() {
public String getUri() {
return connection == null ? null : connection.getURL().toString();
}

View File

@ -0,0 +1,87 @@
/*
* Copyright (C) 2014 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.exoplayer.upstream;
import com.google.android.exoplayer.util.Assertions;
import java.io.IOException;
/**
* A data source that fetches data from a local or remote {@link DataSpec}.
*/
public final class DefaultUriDataSource implements UriDataSource {
private static final String FILE_URI_SCHEME = "file";
private final UriDataSource fileDataSource;
private final UriDataSource httpDataSource;
/**
* {@code null} if no data source is open. Otherwise, equal to {@link #fileDataSource} if the open
* data source is a file, or {@link #httpDataSource} otherwise.
*/
private UriDataSource dataSource;
/**
* Constructs a new data source that delegates to a {@link FileDataSource} for file URIs and an
* {@link DefaultHttpDataSource} for other URIs.
*
* @param userAgent The User-Agent string that should be used when requesting remote data.
* @param transferListener An optional listener.
*/
public DefaultUriDataSource(String userAgent, TransferListener transferListener) {
this(new FileDataSource(transferListener),
new DefaultHttpDataSource(userAgent, null, transferListener));
}
/**
* Constructs a new data source using {@code fileDataSource} for file URIs, and
* {@code httpDataSource} for non-file URIs.
*
* @param fileDataSource {@link UriDataSource} to use for file URIs.
* @param httpDataSource {@link UriDataSource} to use for non-file URIs.
*/
public DefaultUriDataSource(UriDataSource fileDataSource, UriDataSource httpDataSource) {
this.fileDataSource = Assertions.checkNotNull(fileDataSource);
this.httpDataSource = Assertions.checkNotNull(httpDataSource);
}
@Override
public long open(DataSpec dataSpec) throws IOException {
Assertions.checkState(dataSource == null);
dataSource = FILE_URI_SCHEME.equals(dataSpec.uri.getScheme()) ? fileDataSource : httpDataSource;
return dataSource.open(dataSpec);
}
@Override
public int read(byte[] buffer, int offset, int readLength) throws IOException {
return dataSource.read(buffer, offset, readLength);
}
@Override
public String getUri() {
return dataSource == null ? null : dataSource.getUri();
}
@Override
public void close() throws IOException {
if (dataSource != null) {
dataSource.close();
dataSource = null;
}
}
}

View File

@ -24,7 +24,7 @@ import java.io.RandomAccessFile;
/**
* A local file {@link DataSource}.
*/
public final class FileDataSource implements DataSource {
public final class FileDataSource implements UriDataSource {
/**
* Thrown when IOException is encountered during local file read operation.
@ -40,6 +40,7 @@ public final class FileDataSource implements DataSource {
private final TransferListener listener;
private RandomAccessFile file;
private String uri;
private long bytesRemaining;
private boolean opened;
@ -62,6 +63,7 @@ public final class FileDataSource implements DataSource {
@Override
public long open(DataSpec dataSpec) throws FileDataSourceException {
try {
uri = dataSpec.uri.toString();
file = new RandomAccessFile(dataSpec.uri.getPath(), "r");
file.seek(dataSpec.position);
bytesRemaining = dataSpec.length == C.LENGTH_UNBOUNDED ? file.length() - dataSpec.position
@ -104,6 +106,11 @@ public final class FileDataSource implements DataSource {
}
}
@Override
public String getUri() {
return uri;
}
@Override
public void close() throws FileDataSourceException {
if (file != null) {
@ -113,6 +120,7 @@ public final class FileDataSource implements DataSource {
throw new FileDataSourceException(e);
} finally {
file = null;
uri = null;
if (opened) {
opened = false;

View File

@ -27,7 +27,7 @@ import java.util.Map;
/**
* An HTTP specific extension to {@link DataSource}.
*/
public interface HttpDataSource extends DataSource {
public interface HttpDataSource extends UriDataSource {
/**
* A {@link Predicate} that rejects content types often used for pay-walls.
@ -123,15 +123,6 @@ public interface HttpDataSource extends DataSource {
@Override
int read(byte[] buffer, int offset, int readLength) throws HttpDataSourceException;
/**
* When the source is open, returns the url from which data is being read.
* <p>
* If redirection occurred, the url after redirection is the one returned.
*
* @return When the source is open, the url from which data is being read. Null otherwise.
*/
String getUrl();
/**
* Sets the value of a request header field. The value will be used for subsequent connections
* established by the source.

View File

@ -15,68 +15,18 @@
*/
package com.google.android.exoplayer.upstream;
import com.google.android.exoplayer.util.Assertions;
import java.io.IOException;
/**
* A data source that fetches data from a local or remote {@link DataSpec}.
* A component that provides media data from a URI.
*/
public final class UriDataSource implements DataSource {
private static final String FILE_URI_SCHEME = "file";
private final DataSource fileDataSource;
private final DataSource httpDataSource;
public interface UriDataSource extends DataSource {
/**
* {@code null} if no data source is open. Otherwise, equal to {@link #fileDataSource} if the open
* data source is a file, or {@link #httpDataSource} otherwise.
*/
private DataSource dataSource;
/**
* Constructs a new data source that delegates to a {@link FileDataSource} for file URIs and an
* {@link DefaultHttpDataSource} for other URIs.
* When the source is open, returns the URI from which data is being read.
* <p>
* If redirection occurred, the URI after redirection is the one returned.
*
* @param userAgent The User-Agent string that should be used when requesting remote data.
* @param transferListener An optional listener.
* @return When the source is open, the URI from which data is being read. Null otherwise.
*/
public UriDataSource(String userAgent, TransferListener transferListener) {
this(new FileDataSource(transferListener),
new DefaultHttpDataSource(userAgent, null, transferListener));
}
/**
* Constructs a new data source using {@code fileDataSource} for file URIs, and
* {@code httpDataSource} for non-file URIs.
*
* @param fileDataSource {@link DataSource} to use for file URIs.
* @param httpDataSource {@link DataSource} to use for non-file URIs.
*/
public UriDataSource(DataSource fileDataSource, DataSource httpDataSource) {
this.fileDataSource = Assertions.checkNotNull(fileDataSource);
this.httpDataSource = Assertions.checkNotNull(httpDataSource);
}
@Override
public long open(DataSpec dataSpec) throws IOException {
Assertions.checkState(dataSource == null);
dataSource = FILE_URI_SCHEME.equals(dataSpec.uri.getScheme()) ? fileDataSource : httpDataSource;
return dataSource.open(dataSpec);
}
@Override
public int read(byte[] buffer, int offset, int readLength) throws IOException {
return dataSource.read(buffer, offset, readLength);
}
@Override
public void close() throws IOException {
if (dataSource != null) {
dataSource.close();
dataSource = null;
}
}
String getUri();
}

View File

@ -24,19 +24,19 @@ import java.io.IOException;
import java.io.InputStream;
/**
* A {@link Loadable} for loading an object over the network.
* A {@link Loadable} for loading an object from a URI.
*
* @param <T> The type of the object being loaded.
*/
public final class NetworkLoadable<T> implements Loadable {
public final class UriLoadable<T> implements Loadable {
/**
* Parses an object from data loaded over the network.
* Parses an object from loaded data.
*/
public interface Parser<T> {
/**
* Parses an object from a network response.
* Parses an object from a response.
*
* @param connectionUrl The source of the response, after any redirection.
* @param inputStream An {@link InputStream} from which the response data can be read.
@ -49,7 +49,7 @@ public final class NetworkLoadable<T> implements Loadable {
}
private final DataSpec dataSpec;
private final HttpDataSource httpDataSource;
private final UriDataSource uriDataSource;
private final Parser<T> parser;
private volatile T result;
@ -57,11 +57,11 @@ public final class NetworkLoadable<T> implements Loadable {
/**
* @param url The url from which the object should be loaded.
* @param httpDataSource A {@link HttpDataSource} to use when loading the data.
* @param parser Parses the object from the network response.
* @param uriDataSource A {@link UriDataSource} to use when loading the data.
* @param parser Parses the object from the response.
*/
public NetworkLoadable(String url, HttpDataSource httpDataSource, Parser<T> parser) {
this.httpDataSource = httpDataSource;
public UriLoadable(String url, UriDataSource uriDataSource, Parser<T> parser) {
this.uriDataSource = uriDataSource;
this.parser = parser;
dataSpec = new DataSpec(Uri.parse(url), DataSpec.FLAG_ALLOW_GZIP);
}
@ -87,10 +87,10 @@ public final class NetworkLoadable<T> implements Loadable {
@Override
public final void load() throws IOException, InterruptedException {
DataSourceInputStream inputStream = new DataSourceInputStream(httpDataSource, dataSpec);
DataSourceInputStream inputStream = new DataSourceInputStream(uriDataSource, dataSpec);
try {
inputStream.open();
result = parser.parse(httpDataSource.getUrl(), inputStream);
result = parser.parse(uriDataSource.getUri(), inputStream);
} finally {
inputStream.close();
}

View File

@ -15,10 +15,10 @@
*/
package com.google.android.exoplayer.util;
import com.google.android.exoplayer.upstream.HttpDataSource;
import com.google.android.exoplayer.upstream.Loader;
import com.google.android.exoplayer.upstream.Loader.Loadable;
import com.google.android.exoplayer.upstream.NetworkLoadable;
import com.google.android.exoplayer.upstream.UriDataSource;
import com.google.android.exoplayer.upstream.UriLoadable;
import android.os.Handler;
import android.os.Looper;
@ -83,8 +83,8 @@ public class ManifestFetcher<T> implements Loader.Callback {
}
private final NetworkLoadable.Parser<T> parser;
private final HttpDataSource httpDataSource;
private final UriLoadable.Parser<T> parser;
private final UriDataSource uriDataSource;
private final Handler eventHandler;
private final EventListener eventListener;
@ -92,7 +92,7 @@ public class ManifestFetcher<T> implements Loader.Callback {
private int enabledCount;
private Loader loader;
private NetworkLoadable<T> currentLoadable;
private UriLoadable<T> currentLoadable;
private int loadExceptionCount;
private long loadExceptionTimestamp;
@ -103,27 +103,27 @@ public class ManifestFetcher<T> implements Loader.Callback {
/**
* @param manifestUrl The manifest location.
* @param httpDataSource The {@link HttpDataSource} to use when loading the manifest.
* @param uriDataSource The {@link UriDataSource} to use when loading the manifest.
* @param parser A parser to parse the loaded manifest data.
*/
public ManifestFetcher(String manifestUrl, HttpDataSource httpDataSource,
NetworkLoadable.Parser<T> parser) {
this(manifestUrl, httpDataSource, parser, null, null);
public ManifestFetcher(String manifestUrl, UriDataSource uriDataSource,
UriLoadable.Parser<T> parser) {
this(manifestUrl, uriDataSource, parser, null, null);
}
/**
* @param manifestUrl The manifest location.
* @param httpDataSource The {@link HttpDataSource} to use when loading the manifest.
* @param uriDataSource The {@link UriDataSource} to use when loading the manifest.
* @param parser A parser to parse the loaded manifest data.
* @param eventHandler A handler to use when delivering events to {@code eventListener}. May be
* null if delivery of events is not required.
* @param eventListener A listener of events. May be null if delivery of events is not required.
*/
public ManifestFetcher(String manifestUrl, HttpDataSource httpDataSource,
NetworkLoadable.Parser<T> parser, Handler eventHandler, EventListener eventListener) {
public ManifestFetcher(String manifestUrl, UriDataSource uriDataSource,
UriLoadable.Parser<T> parser, Handler eventHandler, EventListener eventListener) {
this.parser = parser;
this.manifestUrl = manifestUrl;
this.httpDataSource = httpDataSource;
this.uriDataSource = uriDataSource;
this.eventHandler = eventHandler;
this.eventListener = eventListener;
}
@ -146,7 +146,7 @@ public class ManifestFetcher<T> implements Loader.Callback {
*/
public void singleLoad(Looper callbackLooper, final ManifestCallback<T> callback) {
SingleFetchHelper fetchHelper = new SingleFetchHelper(
new NetworkLoadable<T>(manifestUrl, httpDataSource, parser), callbackLooper, callback);
new UriLoadable<T>(manifestUrl, uriDataSource, parser), callbackLooper, callback);
fetchHelper.startLoading();
}
@ -219,7 +219,7 @@ public class ManifestFetcher<T> implements Loader.Callback {
loader = new Loader("manifestLoader");
}
if (!loader.isLoading()) {
currentLoadable = new NetworkLoadable<T>(manifestUrl, httpDataSource, parser);
currentLoadable = new UriLoadable<T>(manifestUrl, uriDataSource, parser);
loader.startLoading(currentLoadable, this);
notifyManifestRefreshStarted();
}
@ -303,12 +303,12 @@ public class ManifestFetcher<T> implements Loader.Callback {
private class SingleFetchHelper implements Loader.Callback {
private final NetworkLoadable<T> singleUseLoadable;
private final UriLoadable<T> singleUseLoadable;
private final Looper callbackLooper;
private final ManifestCallback<T> wrappedCallback;
private final Loader singleUseLoader;
public SingleFetchHelper(NetworkLoadable<T> singleUseLoadable, Looper callbackLooper,
public SingleFetchHelper(UriLoadable<T> singleUseLoadable, Looper callbackLooper,
ManifestCallback<T> wrappedCallback) {
this.singleUseLoadable = singleUseLoadable;
this.callbackLooper = callbackLooper;