diff --git a/demo/src/main/java/com/google/android/exoplayer/demo/player/DashSourceBuilder.java b/demo/src/main/java/com/google/android/exoplayer/demo/player/DashSourceBuilder.java index 533f5a527d..a7f2a356a2 100644 --- a/demo/src/main/java/com/google/android/exoplayer/demo/player/DashSourceBuilder.java +++ b/demo/src/main/java/com/google/android/exoplayer/demo/player/DashSourceBuilder.java @@ -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 manifestFetcher = new ManifestFetcher<>(url, - manifestDataSource, parser); + DefaultDataSource manifestDataSource = new DefaultDataSource(context, userAgent); + ManifestFetcher 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, diff --git a/demo/src/main/java/com/google/android/exoplayer/demo/player/ExtractorSourceBuilder.java b/demo/src/main/java/com/google/android/exoplayer/demo/player/ExtractorSourceBuilder.java index 03e2dcf7e9..6f5d958db6 100644 --- a/demo/src/main/java/com/google/android/exoplayer/demo/player/ExtractorSourceBuilder.java +++ b/demo/src/main/java/com/google/android/exoplayer/demo/player/ExtractorSourceBuilder.java @@ -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); } diff --git a/demo/src/main/java/com/google/android/exoplayer/demo/player/HlsSourceBuilder.java b/demo/src/main/java/com/google/android/exoplayer/demo/player/HlsSourceBuilder.java index d3098dc2fa..c29c26ac7a 100644 --- a/demo/src/main/java/com/google/android/exoplayer/demo/player/HlsSourceBuilder.java +++ b/demo/src/main/java/com/google/android/exoplayer/demo/player/HlsSourceBuilder.java @@ -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 manifestFetcher = new ManifestFetcher<>(url, + DefaultDataSource manifestDataSource = new DefaultDataSource(context, userAgent); + ManifestFetcher 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, diff --git a/demo/src/main/java/com/google/android/exoplayer/demo/player/SmoothStreamingSourceBuilder.java b/demo/src/main/java/com/google/android/exoplayer/demo/player/SmoothStreamingSourceBuilder.java index 389c0fb2a2..92f250977b 100644 --- a/demo/src/main/java/com/google/android/exoplayer/demo/player/SmoothStreamingSourceBuilder.java +++ b/demo/src/main/java/com/google/android/exoplayer/demo/player/SmoothStreamingSourceBuilder.java @@ -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 manifestFetcher = new ManifestFetcher<>(url, + ManifestFetcher 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); diff --git a/library/src/androidTest/java/com/google/android/exoplayer/dash/mpd/MediaPresentationDescriptionParserTest.java b/library/src/androidTest/java/com/google/android/exoplayer/dash/mpd/MediaPresentationDescriptionParserTest.java index d24a51208c..f9a3f43706 100644 --- a/library/src/androidTest/java/com/google/android/exoplayer/dash/mpd/MediaPresentationDescriptionParserTest.java +++ b/library/src/androidTest/java/com/google/android/exoplayer/dash/mpd/MediaPresentationDescriptionParserTest.java @@ -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); } } diff --git a/library/src/androidTest/java/com/google/android/exoplayer/hls/HlsMasterPlaylistParserTest.java b/library/src/androidTest/java/com/google/android/exoplayer/hls/HlsMasterPlaylistParserTest.java index 0fa9f89b98..bd61a5da34 100644 --- a/library/src/androidTest/java/com/google/android/exoplayer/hls/HlsMasterPlaylistParserTest.java +++ b/library/src/androidTest/java/com/google/android/exoplayer/hls/HlsMasterPlaylistParserTest.java @@ -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); diff --git a/library/src/androidTest/java/com/google/android/exoplayer/hls/HlsMediaPlaylistParserTest.java b/library/src/androidTest/java/com/google/android/exoplayer/hls/HlsMediaPlaylistParserTest.java index bc8fcdae51..7075e7ebce 100644 --- a/library/src/androidTest/java/com/google/android/exoplayer/hls/HlsMediaPlaylistParserTest.java +++ b/library/src/androidTest/java/com/google/android/exoplayer/hls/HlsMediaPlaylistParserTest.java @@ -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); diff --git a/library/src/androidTest/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingManifestParserTest.java b/library/src/androidTest/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingManifestParserTest.java index c8bc4241fa..3731589062 100644 --- a/library/src/androidTest/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingManifestParserTest.java +++ b/library/src/androidTest/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingManifestParserTest.java @@ -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); } } diff --git a/library/src/androidTest/java/com/google/android/exoplayer/testutil/FakeDataSource.java b/library/src/androidTest/java/com/google/android/exoplayer/testutil/FakeDataSource.java index 8d71dc8ed7..5aa3b97717 100644 --- a/library/src/androidTest/java/com/google/android/exoplayer/testutil/FakeDataSource.java +++ b/library/src/androidTest/java/com/google/android/exoplayer/testutil/FakeDataSource.java @@ -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; diff --git a/library/src/main/java/com/google/android/exoplayer/dash/mpd/MediaPresentationDescription.java b/library/src/main/java/com/google/android/exoplayer/dash/mpd/MediaPresentationDescription.java index 4b0b94754d..455d6b7732 100644 --- a/library/src/main/java/com/google/android/exoplayer/dash/mpd/MediaPresentationDescription.java +++ b/library/src/main/java/com/google/android/exoplayer/dash/mpd/MediaPresentationDescription.java @@ -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 periods; public MediaPresentationDescription(long availabilityStartTime, long duration, long minBufferTime, boolean dynamic, long minUpdatePeriod, long timeShiftBufferDepth, UtcTimingElement utcTiming, - String location, List periods) { + Uri location, List 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; } diff --git a/library/src/main/java/com/google/android/exoplayer/dash/mpd/MediaPresentationDescriptionParser.java b/library/src/main/java/com/google/android/exoplayer/dash/mpd/MediaPresentationDescriptionParser.java index 7a398311de..dd8e5959dc 100644 --- a/library/src/main/java/com/google/android/exoplayer/dash/mpd/MediaPresentationDescriptionParser.java +++ b/library/src/main/java/com/google/android/exoplayer/dash/mpd/MediaPresentationDescriptionParser.java @@ -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 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 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 periods) { + Uri location, List periods) { return new MediaPresentationDescription(availabilityStartTime, durationMs, minBufferTimeMs, dynamic, minUpdateTimeMs, timeShiftBufferDepthMs, utcTiming, location, periods); } diff --git a/library/src/main/java/com/google/android/exoplayer/dash/mpd/UtcTimingElementResolver.java b/library/src/main/java/com/google/android/exoplayer/dash/mpd/UtcTimingElementResolver.java index 19098fa8f5..dff24a8e53 100644 --- a/library/src/main/java/com/google/android/exoplayer/dash/mpd/UtcTimingElementResolver.java +++ b/library/src/main/java/com/google/android/exoplayer/dash/mpd/UtcTimingElementResolver.java @@ -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 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 { @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 { @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. diff --git a/library/src/main/java/com/google/android/exoplayer/hls/Aes128DataSource.java b/library/src/main/java/com/google/android/exoplayer/hls/Aes128DataSource.java index 3406eba658..1d45793e8d 100644 --- a/library/src/main/java/com/google/android/exoplayer/hls/Aes128DataSource.java +++ b/library/src/main/java/com/google/android/exoplayer/hls/Aes128DataSource.java @@ -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(); + } + } diff --git a/library/src/main/java/com/google/android/exoplayer/hls/HlsChunkSource.java b/library/src/main/java/com/google/android/exoplayer/hls/HlsChunkSource.java index 6d179dbef5..828069a82c 100644 --- a/library/src/main/java/com/google/android/exoplayer/hls/HlsChunkSource.java +++ b/library/src/main/java/com/google/android/exoplayer/hls/HlsChunkSource.java @@ -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)); } diff --git a/library/src/main/java/com/google/android/exoplayer/hls/HlsPlaylistParser.java b/library/src/main/java/com/google/android/exoplayer/hls/HlsPlaylistParser.java index bcc12d73b7..7c8d2a978c 100644 --- a/library/src/main/java/com/google/android/exoplayer/hls/HlsPlaylistParser.java +++ b/library/src/main/java/com/google/android/exoplayer/hls/HlsPlaylistParser.java @@ -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 // 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 extraLines = new LinkedList<>(); String line; @@ -119,7 +120,7 @@ public final class HlsPlaylistParser implements UriLoadable.Parser // 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 || 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); } diff --git a/library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingManifestParser.java b/library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingManifestParser.java index e11940ad7d..88ba4e7ad8 100644 --- a/library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingManifestParser.java +++ b/library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingManifestParser.java @@ -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 - * 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. + *

+ * 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}. + *

+ * 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; + } diff --git a/library/src/main/java/com/google/android/exoplayer/upstream/DefaultUriDataSource.java b/library/src/main/java/com/google/android/exoplayer/upstream/DefaultDataSource.java similarity index 82% rename from library/src/main/java/com/google/android/exoplayer/upstream/DefaultUriDataSource.java rename to library/src/main/java/com/google/android/exoplayer/upstream/DefaultDataSource.java index 018e1a5823..318a3993d1 100644 --- a/library/src/main/java/com/google/android/exoplayer/upstream/DefaultUriDataSource.java +++ b/library/src/main/java/com/google/android/exoplayer/upstream/DefaultDataSource.java @@ -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: * *

    *
  • 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; *
  • content: For fetching data from a content URI (e.g. content://authority/path/123). *
*/ -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. *

* 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 { *

* 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(); } diff --git a/library/src/main/java/com/google/android/exoplayer/upstream/DefaultHttpDataSource.java b/library/src/main/java/com/google/android/exoplayer/upstream/DefaultHttpDataSource.java index 59d6c2bff2..38d0c498b3 100644 --- a/library/src/main/java/com/google/android/exoplayer/upstream/DefaultHttpDataSource.java +++ b/library/src/main/java/com/google/android/exoplayer/upstream/DefaultHttpDataSource.java @@ -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 diff --git a/library/src/main/java/com/google/android/exoplayer/upstream/FileDataSource.java b/library/src/main/java/com/google/android/exoplayer/upstream/FileDataSource.java index 784914a7ef..65d9e79f38 100644 --- a/library/src/main/java/com/google/android/exoplayer/upstream/FileDataSource.java +++ b/library/src/main/java/com/google/android/exoplayer/upstream/FileDataSource.java @@ -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(); diff --git a/library/src/main/java/com/google/android/exoplayer/upstream/HttpDataSource.java b/library/src/main/java/com/google/android/exoplayer/upstream/HttpDataSource.java index c9d977cd87..76dc9c6aa4 100644 --- a/library/src/main/java/com/google/android/exoplayer/upstream/HttpDataSource.java +++ b/library/src/main/java/com/google/android/exoplayer/upstream/HttpDataSource.java @@ -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. diff --git a/library/src/main/java/com/google/android/exoplayer/upstream/PriorityDataSource.java b/library/src/main/java/com/google/android/exoplayer/upstream/PriorityDataSource.java index 19a2b224de..310a054296 100644 --- a/library/src/main/java/com/google/android/exoplayer/upstream/PriorityDataSource.java +++ b/library/src/main/java/com/google/android/exoplayer/upstream/PriorityDataSource.java @@ -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(); diff --git a/library/src/main/java/com/google/android/exoplayer/upstream/TeeDataSource.java b/library/src/main/java/com/google/android/exoplayer/upstream/TeeDataSource.java index 2623e8ce7f..0ce0647cd5 100644 --- a/library/src/main/java/com/google/android/exoplayer/upstream/TeeDataSource.java +++ b/library/src/main/java/com/google/android/exoplayer/upstream/TeeDataSource.java @@ -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 { diff --git a/library/src/main/java/com/google/android/exoplayer/upstream/UdpDataSource.java b/library/src/main/java/com/google/android/exoplayer/upstream/UdpDataSource.java index 4c4bd70f5a..c5317e5f6d 100644 --- a/library/src/main/java/com/google/android/exoplayer/upstream/UdpDataSource.java +++ b/library/src/main/java/com/google/android/exoplayer/upstream/UdpDataSource.java @@ -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(); - } - } diff --git a/library/src/main/java/com/google/android/exoplayer/upstream/UriDataSource.java b/library/src/main/java/com/google/android/exoplayer/upstream/UriDataSource.java deleted file mode 100644 index 61da0520ba..0000000000 --- a/library/src/main/java/com/google/android/exoplayer/upstream/UriDataSource.java +++ /dev/null @@ -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. - *

- * 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(); - -} diff --git a/library/src/main/java/com/google/android/exoplayer/upstream/UriLoadable.java b/library/src/main/java/com/google/android/exoplayer/upstream/UriLoadable.java index cce6f9347e..1bfef347b2 100644 --- a/library/src/main/java/com/google/android/exoplayer/upstream/UriLoadable.java +++ b/library/src/main/java/com/google/android/exoplayer/upstream/UriLoadable.java @@ -38,32 +38,32 @@ public final class UriLoadable 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 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 parser) { - this.uriDataSource = uriDataSource; + public UriLoadable(Uri uri, DataSource dataSource, Parser 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 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(); } diff --git a/library/src/main/java/com/google/android/exoplayer/upstream/cache/CacheDataSource.java b/library/src/main/java/com/google/android/exoplayer/upstream/cache/CacheDataSource.java index fb638ea462..1780bce16b 100644 --- a/library/src/main/java/com/google/android/exoplayer/upstream/cache/CacheDataSource.java +++ b/library/src/main/java/com/google/android/exoplayer/upstream/cache/CacheDataSource.java @@ -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(); diff --git a/library/src/main/java/com/google/android/exoplayer/util/ManifestFetcher.java b/library/src/main/java/com/google/android/exoplayer/util/ManifestFetcher.java index 2c1dc1e795..c28ce01592 100644 --- a/library/src/main/java/com/google/android/exoplayer/util/ManifestFetcher.java +++ b/library/src/main/java/com/google/android/exoplayer/util/ManifestFetcher.java @@ -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 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 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 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 parser) { - this(manifestUri, uriDataSource, parser, null, null); + public ManifestFetcher(Uri manifestUri, DataSource dataSource, UriLoadable.Parser 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 parser, Handler eventHandler, EventListener eventListener) { + public ManifestFetcher(Uri manifestUri, DataSource dataSource, UriLoadable.Parser 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 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 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 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); }