Make all DataSource implementations implement getUri.

In V2 we'll at some point start using DataSource factories
for creating DataSource instances. If there are two DataSource
interfaces this gets unnecessarily awkward.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=118470751
This commit is contained in:
olly 2016-03-29 09:34:37 -07:00 committed by Oliver Woodman
parent d869a8d2fa
commit 6cc507aac0
31 changed files with 256 additions and 215 deletions

View file

@ -31,10 +31,11 @@ import com.google.android.exoplayer.drm.MediaDrmCallback;
import com.google.android.exoplayer.upstream.BandwidthMeter;
import com.google.android.exoplayer.upstream.DataSource;
import com.google.android.exoplayer.upstream.DefaultAllocator;
import com.google.android.exoplayer.upstream.DefaultUriDataSource;
import com.google.android.exoplayer.upstream.DefaultDataSource;
import com.google.android.exoplayer.util.ManifestFetcher;
import android.content.Context;
import android.net.Uri;
import android.os.Handler;
/**
@ -68,16 +69,16 @@ public class DashSourceBuilder implements SourceBuilder {
@Override
public SampleSource buildRenderers(DemoPlayer player) {
MediaPresentationDescriptionParser parser = new MediaPresentationDescriptionParser();
DefaultUriDataSource manifestDataSource = new DefaultUriDataSource(context, userAgent);
ManifestFetcher<MediaPresentationDescription> manifestFetcher = new ManifestFetcher<>(url,
manifestDataSource, parser);
DefaultDataSource manifestDataSource = new DefaultDataSource(context, userAgent);
ManifestFetcher<MediaPresentationDescription> manifestFetcher = new ManifestFetcher<>(
Uri.parse(url), manifestDataSource, parser);
Handler mainHandler = player.getMainHandler();
BandwidthMeter bandwidthMeter = player.getBandwidthMeter();
LoadControl loadControl = new DefaultLoadControl(new DefaultAllocator(BUFFER_SEGMENT_SIZE));
// Build the video renderer.
DataSource videoDataSource = new DefaultUriDataSource(context, bandwidthMeter, userAgent);
DataSource videoDataSource = new DefaultDataSource(context, bandwidthMeter, userAgent);
ChunkSource videoChunkSource = new DashChunkSource(manifestFetcher, AdaptationSet.TYPE_VIDEO,
videoDataSource, new AdaptiveEvaluator(bandwidthMeter), LIVE_EDGE_LATENCY_MS,
0, mainHandler, player, DemoPlayer.TYPE_VIDEO);
@ -85,7 +86,7 @@ public class DashSourceBuilder implements SourceBuilder {
VIDEO_BUFFER_SEGMENTS * BUFFER_SEGMENT_SIZE, mainHandler, player, DemoPlayer.TYPE_VIDEO);
// Build the audio renderer.
DataSource audioDataSource = new DefaultUriDataSource(context, bandwidthMeter, userAgent);
DataSource audioDataSource = new DefaultDataSource(context, bandwidthMeter, userAgent);
ChunkSource audioChunkSource = new DashChunkSource(manifestFetcher, AdaptationSet.TYPE_AUDIO,
audioDataSource, null, LIVE_EDGE_LATENCY_MS, 0, mainHandler, player, DemoPlayer.TYPE_AUDIO);
ChunkSampleSource audioSampleSource = new ChunkSampleSource(audioChunkSource, loadControl,
@ -93,7 +94,7 @@ public class DashSourceBuilder implements SourceBuilder {
DemoPlayer.TYPE_AUDIO);
// Build the text renderer.
DataSource textDataSource = new DefaultUriDataSource(context, bandwidthMeter, userAgent);
DataSource textDataSource = new DefaultDataSource(context, bandwidthMeter, userAgent);
ChunkSource textChunkSource = new DashChunkSource(manifestFetcher, AdaptationSet.TYPE_TEXT,
textDataSource, null, LIVE_EDGE_LATENCY_MS, 0, mainHandler, player, DemoPlayer.TYPE_TEXT);
ChunkSampleSource textSampleSource = new ChunkSampleSource(textChunkSource, loadControl,

View file

@ -22,7 +22,7 @@ import com.google.android.exoplayer.extractor.ExtractorSampleSource;
import com.google.android.exoplayer.upstream.Allocator;
import com.google.android.exoplayer.upstream.DataSource;
import com.google.android.exoplayer.upstream.DefaultAllocator;
import com.google.android.exoplayer.upstream.DefaultUriDataSource;
import com.google.android.exoplayer.upstream.DefaultDataSource;
import android.content.Context;
import android.net.Uri;
@ -48,8 +48,7 @@ public class ExtractorSourceBuilder implements SourceBuilder {
@Override
public SampleSource buildRenderers(DemoPlayer player) {
Allocator allocator = new DefaultAllocator(BUFFER_SEGMENT_SIZE);
DataSource dataSource = new DefaultUriDataSource(context, player.getBandwidthMeter(),
userAgent);
DataSource dataSource = new DefaultDataSource(context, player.getBandwidthMeter(), userAgent);
return new ExtractorSampleSource(uri, dataSource, allocator,
BUFFER_SEGMENT_COUNT * BUFFER_SEGMENT_SIZE, player.getMainHandler(), player, 0);
}

View file

@ -29,10 +29,11 @@ import com.google.android.exoplayer.hls.PtsTimestampAdjusterProvider;
import com.google.android.exoplayer.upstream.BandwidthMeter;
import com.google.android.exoplayer.upstream.DataSource;
import com.google.android.exoplayer.upstream.DefaultAllocator;
import com.google.android.exoplayer.upstream.DefaultUriDataSource;
import com.google.android.exoplayer.upstream.DefaultDataSource;
import com.google.android.exoplayer.util.ManifestFetcher;
import android.content.Context;
import android.net.Uri;
import android.os.Handler;
/**
@ -59,8 +60,8 @@ public class HlsSourceBuilder implements SourceBuilder {
@Override
public SampleSource buildRenderers(DemoPlayer player) {
HlsPlaylistParser parser = new HlsPlaylistParser();
DefaultUriDataSource manifestDataSource = new DefaultUriDataSource(context, userAgent);
ManifestFetcher<HlsPlaylist> manifestFetcher = new ManifestFetcher<>(url,
DefaultDataSource manifestDataSource = new DefaultDataSource(context, userAgent);
ManifestFetcher<HlsPlaylist> manifestFetcher = new ManifestFetcher<>(Uri.parse(url),
manifestDataSource, parser);
Handler mainHandler = player.getMainHandler();
@ -68,20 +69,20 @@ public class HlsSourceBuilder implements SourceBuilder {
LoadControl loadControl = new DefaultLoadControl(new DefaultAllocator(BUFFER_SEGMENT_SIZE));
PtsTimestampAdjusterProvider timestampAdjusterProvider = new PtsTimestampAdjusterProvider();
DataSource defaultDataSource = new DefaultUriDataSource(context, bandwidthMeter, userAgent);
DataSource defaultDataSource = new DefaultDataSource(context, bandwidthMeter, userAgent);
HlsChunkSource defaultChunkSource = new HlsChunkSource(manifestFetcher,
HlsChunkSource.TYPE_DEFAULT, defaultDataSource, timestampAdjusterProvider,
new FormatEvaluator.AdaptiveEvaluator(bandwidthMeter));
HlsSampleSource defaultSampleSource = new HlsSampleSource(defaultChunkSource, loadControl,
MAIN_BUFFER_SEGMENTS * BUFFER_SEGMENT_SIZE, mainHandler, player, DemoPlayer.TYPE_VIDEO);
DataSource audioDataSource = new DefaultUriDataSource(context, bandwidthMeter, userAgent);
DataSource audioDataSource = new DefaultDataSource(context, bandwidthMeter, userAgent);
HlsChunkSource audioChunkSource = new HlsChunkSource(manifestFetcher, HlsChunkSource.TYPE_AUDIO,
audioDataSource, timestampAdjusterProvider, null);
HlsSampleSource audioSampleSource = new HlsSampleSource(audioChunkSource, loadControl,
AUDIO_BUFFER_SEGMENTS * BUFFER_SEGMENT_SIZE, mainHandler, player, DemoPlayer.TYPE_AUDIO);
DataSource subtitleDataSource = new DefaultUriDataSource(context, bandwidthMeter, userAgent);
DataSource subtitleDataSource = new DefaultDataSource(context, bandwidthMeter, userAgent);
HlsChunkSource subtitleChunkSource = new HlsChunkSource(manifestFetcher,
HlsChunkSource.TYPE_SUBTITLE, subtitleDataSource, timestampAdjusterProvider, null);
HlsSampleSource subtitleSampleSource = new HlsSampleSource(subtitleChunkSource, loadControl,

View file

@ -30,12 +30,13 @@ import com.google.android.exoplayer.smoothstreaming.SmoothStreamingManifestParse
import com.google.android.exoplayer.upstream.BandwidthMeter;
import com.google.android.exoplayer.upstream.DataSource;
import com.google.android.exoplayer.upstream.DefaultAllocator;
import com.google.android.exoplayer.upstream.DefaultDataSource;
import com.google.android.exoplayer.upstream.DefaultHttpDataSource;
import com.google.android.exoplayer.upstream.DefaultUriDataSource;
import com.google.android.exoplayer.util.ManifestFetcher;
import com.google.android.exoplayer.util.Util;
import android.content.Context;
import android.net.Uri;
import android.os.Handler;
/**
@ -66,14 +67,14 @@ public class SmoothStreamingSourceBuilder implements SourceBuilder {
@Override
public SampleSource buildRenderers(DemoPlayer player) {
SmoothStreamingManifestParser parser = new SmoothStreamingManifestParser();
ManifestFetcher<SmoothStreamingManifest> manifestFetcher = new ManifestFetcher<>(url,
ManifestFetcher<SmoothStreamingManifest> manifestFetcher = new ManifestFetcher<>(Uri.parse(url),
new DefaultHttpDataSource(userAgent, null), parser);
Handler mainHandler = player.getMainHandler();
BandwidthMeter bandwidthMeter = player.getBandwidthMeter();
LoadControl loadControl = new DefaultLoadControl(new DefaultAllocator(BUFFER_SEGMENT_SIZE));
// Build the video renderer.
DataSource videoDataSource = new DefaultUriDataSource(context, bandwidthMeter, userAgent);
DataSource videoDataSource = new DefaultDataSource(context, bandwidthMeter, userAgent);
ChunkSource videoChunkSource = new SmoothStreamingChunkSource(manifestFetcher,
SmoothStreamingManifest.StreamElement.TYPE_VIDEO,
videoDataSource, new AdaptiveEvaluator(bandwidthMeter), LIVE_EDGE_LATENCY_MS);
@ -82,7 +83,7 @@ public class SmoothStreamingSourceBuilder implements SourceBuilder {
DemoPlayer.TYPE_VIDEO);
// Build the audio renderer.
DataSource audioDataSource = new DefaultUriDataSource(context, bandwidthMeter, userAgent);
DataSource audioDataSource = new DefaultDataSource(context, bandwidthMeter, userAgent);
ChunkSource audioChunkSource = new SmoothStreamingChunkSource(manifestFetcher,
SmoothStreamingManifest.StreamElement.TYPE_AUDIO, audioDataSource, null,
LIVE_EDGE_LATENCY_MS);
@ -90,7 +91,7 @@ public class SmoothStreamingSourceBuilder implements SourceBuilder {
AUDIO_BUFFER_SEGMENTS * BUFFER_SEGMENT_SIZE, mainHandler, player, DemoPlayer.TYPE_AUDIO);
// Build the text renderer.
DataSource textDataSource = new DefaultUriDataSource(context, bandwidthMeter, userAgent);
DataSource textDataSource = new DefaultDataSource(context, bandwidthMeter, userAgent);
ChunkSource textChunkSource = new SmoothStreamingChunkSource(manifestFetcher,
SmoothStreamingManifest.StreamElement.TYPE_TEXT, textDataSource, null,
LIVE_EDGE_LATENCY_MS);

View file

@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer.dash.mpd;
import android.net.Uri;
import android.test.InstrumentationTestCase;
import java.io.IOException;
@ -34,7 +35,7 @@ public class MediaPresentationDescriptionParserTest extends InstrumentationTestC
InputStream inputStream =
getInstrumentation().getContext().getResources().getAssets().open(SAMPLE_MPD_1);
// Simple test to ensure that the sample manifest parses without throwing any exceptions.
parser.parse("https://example.com/test.mpd", inputStream);
parser.parse(Uri.parse("https://example.com/test.mpd"), inputStream);
}
public void testParseMediaPresentationDescriptionWithUnknownMimeType() throws IOException {
@ -43,7 +44,7 @@ public class MediaPresentationDescriptionParserTest extends InstrumentationTestC
.open(SAMPLE_MPD_2_UNKNOWN_MIME_TYPE);
// Simple test to ensure that the sample manifest with an unknown mime type parses without
// throwing any exceptions.
parser.parse("https://example.com/test.mpd", inputStream);
parser.parse(Uri.parse("https://example.com/test.mpd"), inputStream);
}
}

View file

@ -17,6 +17,8 @@ package com.google.android.exoplayer.hls;
import com.google.android.exoplayer.C;
import android.net.Uri;
import junit.framework.TestCase;
import java.io.ByteArrayInputStream;
@ -30,7 +32,7 @@ import java.util.List;
public class HlsMasterPlaylistParserTest extends TestCase {
public void testParseMasterPlaylist() {
String playlistUrl = "https://example.com/test.m3u8";
Uri playlistUri = Uri.parse("https://example.com/test.m3u8");
String playlistString = "#EXTM3U\n"
+ "\n"
+ "#EXT-X-STREAM-INF:BANDWIDTH=1280000,CODECS=\"mp4a.40.2,avc1.66.30\",RESOLUTION=304x128\n"
@ -50,7 +52,7 @@ public class HlsMasterPlaylistParserTest extends TestCase {
ByteArrayInputStream inputStream = new ByteArrayInputStream(
playlistString.getBytes(Charset.forName(C.UTF8_NAME)));
try {
HlsPlaylist playlist = new HlsPlaylistParser().parse(playlistUrl, inputStream);
HlsPlaylist playlist = new HlsPlaylistParser().parse(playlistUri, inputStream);
assertNotNull(playlist);
assertEquals(HlsPlaylist.TYPE_MASTER, playlist.type);

View file

@ -17,6 +17,8 @@ package com.google.android.exoplayer.hls;
import com.google.android.exoplayer.C;
import android.net.Uri;
import junit.framework.TestCase;
import java.io.ByteArrayInputStream;
@ -32,7 +34,7 @@ import java.util.Locale;
public class HlsMediaPlaylistParserTest extends TestCase {
public void testParseMediaPlaylist() {
String playlistUrl = "https://example.com/test.m3u8";
Uri playlistUri = Uri.parse("https://example.com/test.m3u8");
String playlistString = "#EXTM3U\n"
+ "#EXT-X-VERSION:3\n"
+ "#EXT-X-TARGETDURATION:8\n"
@ -66,7 +68,7 @@ public class HlsMediaPlaylistParserTest extends TestCase {
InputStream inputStream = new ByteArrayInputStream(
playlistString.getBytes(Charset.forName(C.UTF8_NAME)));
try {
HlsPlaylist playlist = new HlsPlaylistParser().parse(playlistUrl, inputStream);
HlsPlaylist playlist = new HlsPlaylistParser().parse(playlistUri, inputStream);
assertNotNull(playlist);
assertEquals(HlsPlaylist.TYPE_MEDIA, playlist.type);

View file

@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer.smoothstreaming;
import android.net.Uri;
import android.test.InstrumentationTestCase;
import java.io.IOException;
@ -34,11 +35,11 @@ public class SmoothStreamingManifestParserTest extends InstrumentationTestCase {
// SystemID UUID in the manifest is not wrapped in braces.
InputStream inputStream1 =
getInstrumentation().getContext().getResources().getAssets().open(SAMPLE_ISMC_1);
parser.parse("https://example.com/test.ismc", inputStream1);
parser.parse(Uri.parse("https://example.com/test.ismc"), inputStream1);
// Simple test to ensure that the sample manifest parses without throwing any exceptions.
// SystemID UUID in the manifest is wrapped in braces.
InputStream inputStream2 =
getInstrumentation().getContext().getResources().getAssets().open(SAMPLE_ISMC_2);
parser.parse("https://example.com/test.ismc", inputStream2);
parser.parse(Uri.parse("https://example.com/test.ismc"), inputStream2);
}
}

View file

@ -20,6 +20,8 @@ import com.google.android.exoplayer.upstream.DataSource;
import com.google.android.exoplayer.upstream.DataSpec;
import com.google.android.exoplayer.util.Assertions;
import android.net.Uri;
import java.io.IOException;
import java.util.ArrayList;
@ -44,6 +46,7 @@ public final class FakeDataSource implements DataSource {
private final boolean simulateUnknownLength;
private final long totalLength;
private Uri uri;
private boolean opened;
private int currentSegmentIndex;
private long bytesRemaining;
@ -63,6 +66,7 @@ public final class FakeDataSource implements DataSource {
Assertions.checkState(!opened);
// DataSpec requires a matching close call even if open fails.
opened = true;
uri = dataSpec.uri;
// If the source knows that the request is unsatisfiable then fail.
if (dataSpec.position >= totalLength) {
throw new IOException("Unsatisfiable position");
@ -94,18 +98,6 @@ public final class FakeDataSource implements DataSource {
}
}
@Override
public void close() throws IOException {
Assertions.checkState(opened);
opened = false;
if (currentSegmentIndex < segments.size()) {
Segment current = segments.get(currentSegmentIndex);
if (current.isErrorSegment() && current.exceptionThrown) {
current.exceptionCleared = true;
}
}
}
@Override
public int read(byte[] buffer, int offset, int readLength) throws IOException {
Assertions.checkState(opened);
@ -138,6 +130,24 @@ public final class FakeDataSource implements DataSource {
}
}
@Override
public Uri getUri() {
return uri;
}
@Override
public void close() throws IOException {
Assertions.checkState(opened);
opened = false;
uri = null;
if (currentSegmentIndex < segments.size()) {
Segment current = segments.get(currentSegmentIndex);
if (current.isErrorSegment() && current.exceptionThrown) {
current.exceptionCleared = true;
}
}
}
private static class Segment {
public final IOException exception;

View file

@ -17,6 +17,8 @@ package com.google.android.exoplayer.dash.mpd;
import com.google.android.exoplayer.util.ManifestFetcher.RedirectingManifest;
import android.net.Uri;
import java.util.Collections;
import java.util.List;
@ -39,13 +41,13 @@ public class MediaPresentationDescription implements RedirectingManifest {
public final UtcTimingElement utcTiming;
public final String location;
public final Uri location;
private final List<Period> periods;
public MediaPresentationDescription(long availabilityStartTime, long duration, long minBufferTime,
boolean dynamic, long minUpdatePeriod, long timeShiftBufferDepth, UtcTimingElement utcTiming,
String location, List<Period> periods) {
Uri location, List<Period> periods) {
this.availabilityStartTime = availabilityStartTime;
this.duration = duration;
this.minBufferTime = minBufferTime;
@ -58,7 +60,7 @@ public class MediaPresentationDescription implements RedirectingManifest {
}
@Override
public final String getNextManifestUri() {
public final Uri getNextManifestUri() {
return location;
}

View file

@ -30,6 +30,7 @@ import com.google.android.exoplayer.util.ParserUtil;
import com.google.android.exoplayer.util.UriUtil;
import com.google.android.exoplayer.util.Util;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;
@ -88,7 +89,7 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
// MPD parsing.
@Override
public MediaPresentationDescription parse(String connectionUrl, InputStream inputStream)
public MediaPresentationDescription parse(Uri uri, InputStream inputStream)
throws IOException, ParserException {
try {
XmlPullParser xpp = xmlParserFactory.newPullParser();
@ -98,7 +99,7 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
throw new ParserException(
"inputStream does not contain a valid media presentation description");
}
return parseMediaPresentationDescription(xpp, connectionUrl);
return parseMediaPresentationDescription(xpp, uri.toString());
} catch (XmlPullParserException e) {
throw new ParserException(e);
} catch (ParseException e) {
@ -116,7 +117,7 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
long minUpdateTimeMs = (dynamic) ? parseDuration(xpp, "minimumUpdatePeriod", -1) : -1;
long timeShiftBufferDepthMs = (dynamic) ? parseDuration(xpp, "timeShiftBufferDepth", -1) : -1;
UtcTimingElement utcTiming = null;
String location = null;
Uri location = null;
List<Period> periods = new ArrayList<>();
long nextPeriodStartMs = dynamic ? -1 : 0;
@ -132,7 +133,7 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
} else if (ParserUtil.isStartTag(xpp, "UTCTiming")) {
utcTiming = parseUtcTiming(xpp);
} else if (ParserUtil.isStartTag(xpp, "Location")) {
location = xpp.nextText();
location = Uri.parse(xpp.nextText());
} else if (ParserUtil.isStartTag(xpp, "Period") && !seenEarlyAccessPeriod) {
Pair<Period, Long> periodWithDurationMs = parsePeriod(xpp, baseUrl, nextPeriodStartMs);
Period period = periodWithDurationMs.first;
@ -172,7 +173,7 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
protected MediaPresentationDescription buildMediaPresentationDescription(
long availabilityStartTime, long durationMs, long minBufferTimeMs, boolean dynamic,
long minUpdateTimeMs, long timeShiftBufferDepthMs, UtcTimingElement utcTiming,
String location, List<Period> periods) {
Uri location, List<Period> periods) {
return new MediaPresentationDescription(availabilityStartTime, durationMs, minBufferTimeMs,
dynamic, minUpdateTimeMs, timeShiftBufferDepthMs, utcTiming, location, periods);
}

View file

@ -16,13 +16,14 @@
package com.google.android.exoplayer.dash.mpd;
import com.google.android.exoplayer.ParserException;
import com.google.android.exoplayer.upstream.DataSource;
import com.google.android.exoplayer.upstream.Loader;
import com.google.android.exoplayer.upstream.Loader.Loadable;
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;
import android.net.Uri;
import android.os.SystemClock;
import java.io.BufferedReader;
@ -64,7 +65,7 @@ public final class UtcTimingElementResolver implements Loader.Callback {
void onTimestampError(UtcTimingElement utcTiming, IOException e);
}
private final UriDataSource uriDataSource;
private final DataSource dataSource;
private final UtcTimingElement timingElement;
private final long timingElementElapsedRealtime;
private final UtcTimingCallback callback;
@ -75,23 +76,22 @@ public final class UtcTimingElementResolver implements Loader.Callback {
/**
* Resolves a {@link UtcTimingElement}.
*
* @param uriDataSource A source to use should loading from a URI be necessary.
* @param dataSource A {@link DataSource} to use should loading from a {@link 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(UriDataSource uriDataSource,
UtcTimingElement timingElement, long timingElementElapsedRealtime,
UtcTimingCallback callback) {
UtcTimingElementResolver resolver = new UtcTimingElementResolver(uriDataSource, timingElement,
public static void resolveTimingElement(DataSource dataSource, UtcTimingElement timingElement,
long timingElementElapsedRealtime, UtcTimingCallback callback) {
UtcTimingElementResolver resolver = new UtcTimingElementResolver(dataSource, timingElement,
timingElementElapsedRealtime, callback);
resolver.resolve();
}
private UtcTimingElementResolver(UriDataSource uriDataSource, UtcTimingElement timingElement,
private UtcTimingElementResolver(DataSource dataSource, UtcTimingElement timingElement,
long timingElementElapsedRealtime, UtcTimingCallback callback) {
this.uriDataSource = uriDataSource;
this.dataSource = dataSource;
this.timingElement = Assertions.checkNotNull(timingElement);
this.timingElementElapsedRealtime = timingElementElapsedRealtime;
this.callback = Assertions.checkNotNull(callback);
@ -124,7 +124,7 @@ public final class UtcTimingElementResolver implements Loader.Callback {
private void resolveHttp(UriLoadable.Parser<Long> parser) {
singleUseLoader = new Loader("utctiming");
singleUseLoadable = new UriLoadable<>(timingElement.value, uriDataSource, parser);
singleUseLoadable = new UriLoadable<>(Uri.parse(timingElement.value), dataSource, parser);
singleUseLoader.startLoading(singleUseLoadable, this);
}
@ -153,8 +153,7 @@ public final class UtcTimingElementResolver implements Loader.Callback {
private static class XsDateTimeParser implements UriLoadable.Parser<Long> {
@Override
public Long parse(String connectionUrl, InputStream inputStream) throws ParserException,
IOException {
public Long parse(Uri uri, InputStream inputStream) throws ParserException, IOException {
String firstLine = new BufferedReader(new InputStreamReader(inputStream)).readLine();
try {
return Util.parseXsDateTime(firstLine);
@ -168,8 +167,7 @@ public final class UtcTimingElementResolver implements Loader.Callback {
private static class Iso8601Parser implements UriLoadable.Parser<Long> {
@Override
public Long parse(String connectionUrl, InputStream inputStream) throws ParserException,
IOException {
public Long parse(Uri uri, InputStream inputStream) throws ParserException, IOException {
String firstLine = new BufferedReader(new InputStreamReader(inputStream)).readLine();
try {
// TODO: It may be necessary to handle timestamp offsets from UTC.

View file

@ -21,6 +21,8 @@ import com.google.android.exoplayer.upstream.DataSourceInputStream;
import com.google.android.exoplayer.upstream.DataSpec;
import com.google.android.exoplayer.util.Assertions;
import android.net.Uri;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
@ -105,4 +107,9 @@ import javax.crypto.spec.SecretKeySpec;
return bytesRead;
}
@Override
public Uri getUri() {
return upstream.getUri();
}
}

View file

@ -656,7 +656,7 @@ public class HlsChunkSource {
DataSpec dataSpec = new DataSpec(mediaPlaylistUri, 0, C.LENGTH_UNBOUNDED, null,
DataSpec.FLAG_ALLOW_GZIP);
return new MediaPlaylistChunk(dataSource, dataSpec, variants[variantIndex].format, scratchSpace,
playlistParser, variantIndex, mediaPlaylistUri.toString());
playlistParser, variantIndex, mediaPlaylistUri);
}
private EncryptionKeyChunk newEncryptionKeyChunk(Uri keyUri, String iv, int variantIndex) {
@ -735,23 +735,23 @@ public class HlsChunkSource {
public final int variantIndex;
private final HlsPlaylistParser playlistParser;
private final String playlistUrl;
private final Uri playlistUri;
private HlsMediaPlaylist result;
public MediaPlaylistChunk(DataSource dataSource, DataSpec dataSpec, Format format,
byte[] scratchSpace, HlsPlaylistParser playlistParser, int variantIndex,
String playlistUrl) {
Uri playlistUri) {
super(dataSource, dataSpec, Chunk.TYPE_MANIFEST, Chunk.TRIGGER_UNSPECIFIED, format,
Chunk.NO_PARENT_ID, scratchSpace);
this.variantIndex = variantIndex;
this.playlistParser = playlistParser;
this.playlistUrl = playlistUrl;
this.playlistUri = playlistUri;
}
@Override
protected void consume(byte[] data, int limit) throws IOException {
result = (HlsMediaPlaylist) playlistParser.parse(playlistUrl,
result = (HlsMediaPlaylist) playlistParser.parse(playlistUri,
new ByteArrayInputStream(data, 0, limit));
}

View file

@ -22,6 +22,8 @@ import com.google.android.exoplayer.hls.HlsMediaPlaylist.Segment;
import com.google.android.exoplayer.upstream.UriLoadable;
import com.google.android.exoplayer.util.MimeTypes;
import android.net.Uri;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
@ -107,8 +109,7 @@ public final class HlsPlaylistParser implements UriLoadable.Parser<HlsPlaylist>
// HlsParserUtil.compileBooleanAttrPattern(DEFAULT_ATTR);
@Override
public HlsPlaylist parse(String connectionUrl, InputStream inputStream)
throws IOException, ParserException {
public HlsPlaylist parse(Uri uri, InputStream inputStream) throws IOException, ParserException {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
Queue<String> extraLines = new LinkedList<>();
String line;
@ -119,7 +120,7 @@ public final class HlsPlaylistParser implements UriLoadable.Parser<HlsPlaylist>
// Do nothing.
} else if (line.startsWith(STREAM_INF_TAG)) {
extraLines.add(line);
return parseMasterPlaylist(new LineIterator(extraLines, reader), connectionUrl);
return parseMasterPlaylist(new LineIterator(extraLines, reader), uri.toString());
} else if (line.startsWith(TARGET_DURATION_TAG)
|| line.startsWith(MEDIA_SEQUENCE_TAG)
|| line.startsWith(MEDIA_DURATION_TAG)
@ -129,7 +130,7 @@ public final class HlsPlaylistParser implements UriLoadable.Parser<HlsPlaylist>
|| line.equals(DISCONTINUITY_SEQUENCE_TAG)
|| line.equals(ENDLIST_TAG)) {
extraLines.add(line);
return parseMediaPlaylist(new LineIterator(extraLines, reader), connectionUrl);
return parseMediaPlaylist(new LineIterator(extraLines, reader), uri.toString());
} else {
extraLines.add(line);
}

View file

@ -26,6 +26,7 @@ import com.google.android.exoplayer.util.CodecSpecificDataUtil;
import com.google.android.exoplayer.util.MimeTypes;
import com.google.android.exoplayer.util.Util;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Pair;
@ -61,13 +62,13 @@ public class SmoothStreamingManifestParser implements UriLoadable.Parser<SmoothS
}
@Override
public SmoothStreamingManifest parse(String connectionUrl, InputStream inputStream)
public SmoothStreamingManifest parse(Uri uri, InputStream inputStream)
throws IOException, ParserException {
try {
XmlPullParser xmlParser = xmlParserFactory.newPullParser();
xmlParser.setInput(inputStream, null);
SmoothStreamMediaParser smoothStreamMediaParser =
new SmoothStreamMediaParser(null, connectionUrl);
new SmoothStreamMediaParser(null, uri.toString());
return (SmoothStreamingManifest) smoothStreamMediaParser.parse(xmlParser);
} catch (XmlPullParserException e) {
throw new ParserException(e);

View file

@ -19,15 +19,16 @@ import com.google.android.exoplayer.C;
import android.content.Context;
import android.content.res.AssetManager;
import android.net.Uri;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
/**
* A local asset {@link UriDataSource}.
* A local asset {@link DataSource}.
*/
public final class AssetDataSource implements UriDataSource {
public final class AssetDataSource implements DataSource {
/**
* Thrown when an {@link IOException} is encountered reading a local asset.
@ -43,7 +44,7 @@ public final class AssetDataSource implements UriDataSource {
private final AssetManager assetManager;
private final TransferListener listener;
private String uriString;
private Uri uri;
private InputStream inputStream;
private long bytesRemaining;
private boolean opened;
@ -68,14 +69,13 @@ public final class AssetDataSource implements UriDataSource {
@Override
public long open(DataSpec dataSpec) throws AssetDataSourceException {
try {
uriString = dataSpec.uri.toString();
String path = dataSpec.uri.getPath();
uri = dataSpec.uri;
String path = uri.getPath();
if (path.startsWith("/android_asset/")) {
path = path.substring(15);
} else if (path.startsWith("/")) {
path = path.substring(1);
}
uriString = dataSpec.uri.toString();
inputStream = assetManager.open(path, AssetManager.ACCESS_RANDOM);
long skipped = inputStream.skip(dataSpec.position);
if (skipped < dataSpec.position) {
@ -133,13 +133,13 @@ public final class AssetDataSource implements UriDataSource {
}
@Override
public String getUri() {
return uriString;
public Uri getUri() {
return uri;
}
@Override
public void close() throws AssetDataSourceException {
uriString = null;
uri = null;
if (inputStream != null) {
try {
inputStream.close();

View file

@ -18,6 +18,8 @@ package com.google.android.exoplayer.upstream;
import com.google.android.exoplayer.C;
import com.google.android.exoplayer.util.Assertions;
import android.net.Uri;
import java.io.IOException;
/**
@ -26,6 +28,8 @@ import java.io.IOException;
public final class ByteArrayDataSource implements DataSource {
private final byte[] data;
private Uri uri;
private int readPosition;
private int remainingBytes;
@ -40,6 +44,7 @@ public final class ByteArrayDataSource implements DataSource {
@Override
public long open(DataSpec dataSpec) throws IOException {
uri = dataSpec.uri;
readPosition = (int) dataSpec.position;
remainingBytes = (int) ((dataSpec.length == C.LENGTH_UNBOUNDED)
? (data.length - dataSpec.position) : dataSpec.length);
@ -50,11 +55,6 @@ public final class ByteArrayDataSource implements DataSource {
return remainingBytes;
}
@Override
public void close() throws IOException {
// Do nothing.
}
@Override
public int read(byte[] buffer, int offset, int length) throws IOException {
if (remainingBytes == 0) {
@ -66,5 +66,16 @@ public final class ByteArrayDataSource implements DataSource {
remainingBytes -= length;
return length;
}
@Override
public Uri getUri() {
return uri;
}
@Override
public void close() throws IOException {
uri = null;
}
}

View file

@ -20,6 +20,7 @@ import com.google.android.exoplayer.C;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.net.Uri;
import java.io.EOFException;
import java.io.FileInputStream;
@ -27,9 +28,9 @@ import java.io.IOException;
import java.io.InputStream;
/**
* A content URI {@link UriDataSource}.
* A content URI {@link DataSource}.
*/
public final class ContentDataSource implements UriDataSource {
public final class ContentDataSource implements DataSource {
/**
* Thrown when an {@link IOException} is encountered reading from a content URI.
@ -45,8 +46,8 @@ public final class ContentDataSource implements UriDataSource {
private final ContentResolver resolver;
private final TransferListener listener;
private Uri uri;
private InputStream inputStream;
private String uriString;
private long bytesRemaining;
private boolean opened;
@ -70,8 +71,8 @@ public final class ContentDataSource implements UriDataSource {
@Override
public long open(DataSpec dataSpec) throws ContentDataSourceException {
try {
uriString = dataSpec.uri.toString();
AssetFileDescriptor assetFd = resolver.openAssetFileDescriptor(dataSpec.uri, "r");
uri = dataSpec.uri;
AssetFileDescriptor assetFd = resolver.openAssetFileDescriptor(uri, "r");
inputStream = new FileInputStream(assetFd.getFileDescriptor());
long skipped = inputStream.skip(dataSpec.position);
if (skipped < dataSpec.position) {
@ -130,13 +131,13 @@ public final class ContentDataSource implements UriDataSource {
}
@Override
public String getUri() {
return uriString;
public Uri getUri() {
return uri;
}
@Override
public void close() throws ContentDataSourceException {
uriString = null;
uri = null;
if (inputStream != null) {
try {
inputStream.close();

View file

@ -17,6 +17,8 @@ package com.google.android.exoplayer.upstream;
import com.google.android.exoplayer.C;
import android.net.Uri;
import java.io.IOException;
/**
@ -43,16 +45,6 @@ public interface DataSource {
*/
long open(DataSpec dataSpec) throws IOException;
/**
* Closes the {@link DataSource}.
* <p>
* Note: This method will be called even if the corresponding call to {@link #open(DataSpec)}
* threw an {@link IOException}. See {@link #open(DataSpec)} for more details.
*
* @throws IOException If an error occurs closing the source.
*/
void close() throws IOException;
/**
* Reads up to {@code length} bytes of data and stores them into {@code buffer}, starting at
* index {@code offset}.
@ -69,4 +61,25 @@ public interface DataSource {
*/
int read(byte[] buffer, int offset, int readLength) throws IOException;
/**
* When the source is open, returns the {@link Uri} from which data is being read.
* <p>
* The returned {@link Uri} will be identical to the one passed {@link #open(DataSpec)} in the
* {@link DataSpec} unless redirection has occurred. If redirection has occurred, the {@link Uri}
* after redirection is returned.
*
* @return When the source is open, the {@link Uri} from which data is being read. Null otherwise.
*/
Uri getUri();
/**
* Closes the {@link DataSource}.
* <p>
* Note: This method will be called even if the corresponding call to {@link #open(DataSpec)}
* threw an {@link IOException}. See {@link #open(DataSpec)} for more details.
*
* @throws IOException If an error occurs closing the source.
*/
void close() throws IOException;
}

View file

@ -19,11 +19,12 @@ import com.google.android.exoplayer.util.Assertions;
import com.google.android.exoplayer.util.Util;
import android.content.Context;
import android.net.Uri;
import java.io.IOException;
/**
* A {@link UriDataSource} that supports multiple URI schemes. The supported schemes are:
* A {@link DataSource} that supports multiple URI schemes. The supported schemes are:
*
* <ul>
* <li>http(s): For fetching data over HTTP and HTTPS (e.g. https://www.something.com/media.mp4).
@ -34,34 +35,34 @@ import java.io.IOException;
* <li>content: For fetching data from a content URI (e.g. content://authority/path/123).
* </ul>
*/
public final class DefaultUriDataSource implements UriDataSource {
public final class DefaultDataSource implements DataSource {
private static final String SCHEME_ASSET = "asset";
private static final String SCHEME_CONTENT = "content";
private final UriDataSource httpDataSource;
private final UriDataSource fileDataSource;
private final UriDataSource assetDataSource;
private final UriDataSource contentDataSource;
private final DataSource httpDataSource;
private final DataSource fileDataSource;
private final DataSource assetDataSource;
private final DataSource contentDataSource;
/**
* {@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;
private DataSource dataSource;
/**
* Constructs a new instance.
* <p>
* The constructed instance will not follow cross-protocol redirects (i.e. redirects from HTTP to
* HTTPS or vice versa) when fetching remote data. Cross-protocol redirects can be enabled by
* using {@link #DefaultUriDataSource(Context, TransferListener, String, boolean)} and passing
* using {@link #DefaultDataSource(Context, TransferListener, String, boolean)} and passing
* {@code true} as the final argument.
*
* @param context A context.
* @param userAgent The User-Agent string that should be used when requesting remote data.
*/
public DefaultUriDataSource(Context context, String userAgent) {
public DefaultDataSource(Context context, String userAgent) {
this(context, null, userAgent, false);
}
@ -70,14 +71,14 @@ public final class DefaultUriDataSource implements UriDataSource {
* <p>
* The constructed instance will not follow cross-protocol redirects (i.e. redirects from HTTP to
* HTTPS or vice versa) when fetching remote data. Cross-protocol redirects can be enabled by
* using {@link #DefaultUriDataSource(Context, TransferListener, String, boolean)} and passing
* using {@link #DefaultDataSource(Context, TransferListener, String, boolean)} and passing
* {@code true} as the final argument.
*
* @param context A context.
* @param listener An optional {@link TransferListener}.
* @param userAgent The User-Agent string that should be used when requesting remote data.
*/
public DefaultUriDataSource(Context context, TransferListener listener, String userAgent) {
public DefaultDataSource(Context context, TransferListener listener, String userAgent) {
this(context, listener, userAgent, false);
}
@ -90,7 +91,7 @@ public final class DefaultUriDataSource implements UriDataSource {
* @param allowCrossProtocolRedirects Whether cross-protocol redirects (i.e. redirects from HTTP
* to HTTPS and vice versa) are enabled when fetching remote data..
*/
public DefaultUriDataSource(Context context, TransferListener listener, String userAgent,
public DefaultDataSource(Context context, TransferListener listener, String userAgent,
boolean allowCrossProtocolRedirects) {
this(context, listener,
new DefaultHttpDataSource(userAgent, null, listener,
@ -103,10 +104,10 @@ public final class DefaultUriDataSource implements UriDataSource {
*
* @param context A context.
* @param listener An optional {@link TransferListener}.
* @param httpDataSource {@link UriDataSource} to use for non-file URIs.
* @param httpDataSource {@link DataSource} to use for non-file URIs.
*/
public DefaultUriDataSource(Context context, TransferListener listener,
UriDataSource httpDataSource) {
public DefaultDataSource(Context context, TransferListener listener,
DataSource httpDataSource) {
this.httpDataSource = Assertions.checkNotNull(httpDataSource);
this.fileDataSource = new FileDataSource(listener);
this.assetDataSource = new AssetDataSource(context, listener);
@ -141,7 +142,7 @@ public final class DefaultUriDataSource implements UriDataSource {
}
@Override
public String getUri() {
public Uri getUri() {
return dataSource == null ? null : dataSource.getUri();
}

View file

@ -20,6 +20,7 @@ import com.google.android.exoplayer.util.Assertions;
import com.google.android.exoplayer.util.Predicate;
import com.google.android.exoplayer.util.Util;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
@ -149,8 +150,8 @@ public class DefaultHttpDataSource implements HttpDataSource {
}
@Override
public String getUri() {
return connection == null ? null : connection.getURL().toString();
public Uri getUri() {
return connection == null ? null : Uri.parse(connection.getURL().toString());
}
@Override

View file

@ -17,14 +17,16 @@ package com.google.android.exoplayer.upstream;
import com.google.android.exoplayer.C;
import android.net.Uri;
import java.io.EOFException;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* A local file {@link UriDataSource}.
* A local file {@link DataSource}.
*/
public final class FileDataSource implements UriDataSource {
public final class FileDataSource implements DataSource {
/**
* Thrown when IOException is encountered during local file read operation.
@ -40,7 +42,7 @@ public final class FileDataSource implements UriDataSource {
private final TransferListener listener;
private RandomAccessFile file;
private String uriString;
private Uri uri;
private long bytesRemaining;
private boolean opened;
@ -63,7 +65,7 @@ public final class FileDataSource implements UriDataSource {
@Override
public long open(DataSpec dataSpec) throws FileDataSourceException {
try {
uriString = dataSpec.uri.toString();
uri = dataSpec.uri;
file = new RandomAccessFile(dataSpec.uri.getPath(), "r");
file.seek(dataSpec.position);
bytesRemaining = dataSpec.length == C.LENGTH_UNBOUNDED ? file.length() - dataSpec.position
@ -107,13 +109,13 @@ public final class FileDataSource implements UriDataSource {
}
@Override
public String getUri() {
return uriString;
public Uri getUri() {
return uri;
}
@Override
public void close() throws FileDataSourceException {
uriString = null;
uri = null;
if (file != null) {
try {
file.close();

View file

@ -25,9 +25,9 @@ import java.util.List;
import java.util.Map;
/**
* An HTTP specific extension to {@link UriDataSource}.
* An HTTP specific extension to {@link DataSource}.
*/
public interface HttpDataSource extends UriDataSource {
public interface HttpDataSource extends DataSource {
/**
* A {@link Predicate} that rejects content types often used for pay-walls.

View file

@ -17,6 +17,8 @@ package com.google.android.exoplayer.upstream;
import com.google.android.exoplayer.util.Assertions;
import android.net.Uri;
import java.io.IOException;
/**
@ -50,6 +52,11 @@ public final class PriorityDataSource implements DataSource {
return upstream.read(buffer, offset, max);
}
@Override
public Uri getUri() {
return upstream.getUri();
}
@Override
public void close() throws IOException {
upstream.close();

View file

@ -18,6 +18,8 @@ package com.google.android.exoplayer.upstream;
import com.google.android.exoplayer.C;
import com.google.android.exoplayer.util.Assertions;
import android.net.Uri;
import java.io.IOException;
/**
@ -59,6 +61,11 @@ public final class TeeDataSource implements DataSource {
return num;
}
@Override
public Uri getUri() {
return upstream.getUri();
}
@Override
public void close() throws IOException {
try {

View file

@ -17,6 +17,8 @@ package com.google.android.exoplayer.upstream;
import com.google.android.exoplayer.C;
import android.net.Uri;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
@ -27,7 +29,7 @@ import java.net.MulticastSocket;
/**
* A UDP {@link DataSource}.
*/
public final class UdpDataSource implements UriDataSource {
public final class UdpDataSource implements DataSource {
/**
* Thrown when an error is encountered when trying to read from a {@link UdpDataSource}.
@ -52,7 +54,7 @@ public final class UdpDataSource implements UriDataSource {
private final TransferListener listener;
private final DatagramPacket packet;
private DataSpec dataSpec;
private Uri uri;
private DatagramSocket socket;
private MulticastSocket multicastSocket;
private InetAddress address;
@ -81,9 +83,9 @@ public final class UdpDataSource implements UriDataSource {
@Override
public long open(DataSpec dataSpec) throws UdpDataSourceException {
this.dataSpec = dataSpec;
String host = dataSpec.uri.getHost();
int port = dataSpec.uri.getPort();
uri = dataSpec.uri;
String host = uri.getHost();
int port = uri.getPort();
try {
address = InetAddress.getByName(host);
@ -129,8 +131,14 @@ public final class UdpDataSource implements UriDataSource {
return bytesToRead;
}
@Override
public Uri getUri() {
return uri;
}
@Override
public void close() {
uri = null;
if (multicastSocket != null) {
try {
multicastSocket.leaveGroup(address);
@ -154,9 +162,4 @@ public final class UdpDataSource implements UriDataSource {
}
}
@Override
public String getUri() {
return dataSpec == null ? null : dataSpec.uri.toString();
}
}

View file

@ -1,32 +0,0 @@
/*
* 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;
/**
* A component that provides media data from a URI.
*/
public interface UriDataSource extends DataSource {
/**
* 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.
*
* @return When the source is open, the URI from which data is being read. Null otherwise.
*/
String getUri();
}

View file

@ -38,32 +38,32 @@ public final class UriLoadable<T> implements Loadable {
/**
* Parses an object from a response.
*
* @param connectionUrl The source of the response, after any redirection.
* @param uri The source of the response, after any redirection.
* @param inputStream An {@link InputStream} from which the response data can be read.
* @return The parsed object.
* @throws ParserException If an error occurs parsing the data.
* @throws IOException If an error occurs reading data from the stream.
*/
T parse(String connectionUrl, InputStream inputStream) throws ParserException, IOException;
T parse(Uri uri, InputStream inputStream) throws ParserException, IOException;
}
private final DataSpec dataSpec;
private final UriDataSource uriDataSource;
private final DataSource dataSource;
private final Parser<T> parser;
private volatile T result;
private volatile boolean isCanceled;
/**
* @param url The url from which the object should be loaded.
* @param uriDataSource A {@link UriDataSource} to use when loading the data.
* @param uri The {@link Uri} from which the object should be loaded.
* @param dataSource A {@link DataSource} to use when loading the data.
* @param parser Parses the object from the response.
*/
public UriLoadable(String url, UriDataSource uriDataSource, Parser<T> parser) {
this.uriDataSource = uriDataSource;
public UriLoadable(Uri uri, DataSource dataSource, Parser<T> parser) {
this.dataSource = dataSource;
this.parser = parser;
dataSpec = new DataSpec(Uri.parse(url), DataSpec.FLAG_ALLOW_GZIP);
dataSpec = new DataSpec(uri, DataSpec.FLAG_ALLOW_GZIP);
}
/**
@ -87,10 +87,10 @@ public final class UriLoadable<T> implements Loadable {
@Override
public final void load() throws IOException, InterruptedException {
DataSourceInputStream inputStream = new DataSourceInputStream(uriDataSource, dataSpec);
DataSourceInputStream inputStream = new DataSourceInputStream(dataSource, dataSpec);
try {
inputStream.open();
result = parser.parse(uriDataSource.getUri(), inputStream);
result = parser.parse(dataSource.getUri(), inputStream);
} finally {
inputStream.close();
}

View file

@ -166,8 +166,14 @@ public final class CacheDataSource implements DataSource {
}
}
@Override
public Uri getUri() {
return currentDataSource == upstreamDataSource ? currentDataSource.getUri() : uri;
}
@Override
public void close() throws IOException {
uri = null;
notifyBytesRead();
try {
closeCurrentSource();

View file

@ -15,14 +15,14 @@
*/
package com.google.android.exoplayer.util;
import com.google.android.exoplayer.upstream.DataSource;
import com.google.android.exoplayer.upstream.Loader;
import com.google.android.exoplayer.upstream.Loader.Loadable;
import com.google.android.exoplayer.upstream.UriDataSource;
import com.google.android.exoplayer.upstream.UriLoadable;
import android.net.Uri;
import android.os.Handler;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.Pair;
import java.io.IOException;
@ -62,19 +62,19 @@ public class ManifestFetcher<T> implements Loader.Callback {
public interface RedirectingManifest {
/**
* Returns the URI from which subsequent manifests should be requested, or null to continue
* using the current URI.
* Returns the {@link Uri} from which subsequent manifests should be requested, or null to
* continue using the current {@link Uri}.
*/
public String getNextManifestUri();
public Uri getNextManifestUri();
}
private final UriLoadable.Parser<T> parser;
private final UriDataSource uriDataSource;
private final DataSource dataSource;
private final Handler eventHandler;
private final EventListener eventListener;
/* package */ volatile String manifestUri;
private volatile Uri manifestUri;
private int enabledCount;
private Loader loader;
@ -90,38 +90,37 @@ public class ManifestFetcher<T> implements Loader.Callback {
private volatile long manifestLoadCompleteTimestamp;
/**
* @param manifestUri The manifest location.
* @param uriDataSource The {@link UriDataSource} to use when loading the manifest.
* @param manifestUri The manifest {@link Uri}.
* @param dataSource The {@link DataSource} to use when loading the manifest.
* @param parser A parser to parse the loaded manifest data.
*/
public ManifestFetcher(String manifestUri, UriDataSource uriDataSource,
UriLoadable.Parser<T> parser) {
this(manifestUri, uriDataSource, parser, null, null);
public ManifestFetcher(Uri manifestUri, DataSource dataSource, UriLoadable.Parser<T> parser) {
this(manifestUri, dataSource, parser, null, null);
}
/**
* @param manifestUri The manifest location.
* @param uriDataSource The {@link UriDataSource} to use when loading the manifest.
* @param manifestUri The manifest {@link Uri}.
* @param dataSource The {@link DataSource} 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 manifestUri, UriDataSource uriDataSource,
UriLoadable.Parser<T> parser, Handler eventHandler, EventListener eventListener) {
public ManifestFetcher(Uri manifestUri, DataSource dataSource, UriLoadable.Parser<T> parser,
Handler eventHandler, EventListener eventListener) {
this.parser = parser;
this.manifestUri = manifestUri;
this.uriDataSource = uriDataSource;
this.dataSource = dataSource;
this.eventHandler = eventHandler;
this.eventListener = eventListener;
}
/**
* Updates the manifest location.
* Updates the manifest {@link Uri}.
*
* @param manifestUri The manifest location.
* @param manifestUri The manifest {@link Uri}.
*/
public void updateManifestUri(String manifestUri) {
public void updateManifestUri(Uri manifestUri) {
this.manifestUri = manifestUri;
}
@ -205,7 +204,7 @@ public class ManifestFetcher<T> implements Loader.Callback {
loader = new Loader("manifestLoader");
}
if (!loader.isLoading()) {
currentLoadable = new UriLoadable<>(manifestUri, uriDataSource, parser);
currentLoadable = new UriLoadable<>(manifestUri, dataSource, parser);
currentLoadStartTimestamp = SystemClock.elapsedRealtime();
loader.startLoading(currentLoadable, this);
notifyManifestRefreshStarted();
@ -227,9 +226,9 @@ public class ManifestFetcher<T> implements Loader.Callback {
if (manifest instanceof RedirectingManifest) {
RedirectingManifest redirectingManifest = (RedirectingManifest) manifest;
String nextLocation = redirectingManifest.getNextManifestUri();
if (!TextUtils.isEmpty(nextLocation)) {
manifestUri = nextLocation;
Uri nextUri = redirectingManifest.getNextManifestUri();
if (nextUri != null) {
manifestUri = nextUri;
}
}
@ -255,12 +254,6 @@ public class ManifestFetcher<T> implements Loader.Callback {
notifyManifestError(loadException);
}
/* package */ void onSingleFetchCompleted(T result, long loadStartTimestamp) {
manifest = result;
manifestLoadStartTimestamp = loadStartTimestamp;
manifestLoadCompleteTimestamp = SystemClock.elapsedRealtime();
}
private long getRetryDelayMillis(long errorCount) {
return Math.min((errorCount - 1) * 1000, 5000);
}