From 3be4451e13d604b9a036bd90e8fcefd77c62c5a8 Mon Sep 17 00:00:00 2001 From: aquilescanta Date: Wed, 8 Mar 2017 07:51:13 -0800 Subject: [PATCH] Allow injection of DataSource's per type of data This allows the client to define what data source is used for media chunks, encryption chunks and playlists. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=149537766 --- .../hls/DefaultHlsDataSourceFactory.java | 39 +++++++++++++++++++ .../exoplayer2/source/hls/HlsChunkSource.java | 15 ++++--- .../source/hls/HlsDataSourceFactory.java | 35 +++++++++++++++++ .../exoplayer2/source/hls/HlsMediaPeriod.java | 10 ++--- .../exoplayer2/source/hls/HlsMediaSource.java | 9 ++++- .../hls/playlist/HlsPlaylistTracker.java | 12 +++--- .../android/exoplayer2/upstream/DataSpec.java | 4 +- 7 files changed, 105 insertions(+), 19 deletions(-) create mode 100644 library/src/main/java/com/google/android/exoplayer2/source/hls/DefaultHlsDataSourceFactory.java create mode 100644 library/src/main/java/com/google/android/exoplayer2/source/hls/HlsDataSourceFactory.java diff --git a/library/src/main/java/com/google/android/exoplayer2/source/hls/DefaultHlsDataSourceFactory.java b/library/src/main/java/com/google/android/exoplayer2/source/hls/DefaultHlsDataSourceFactory.java new file mode 100644 index 0000000000..b90dcb2139 --- /dev/null +++ b/library/src/main/java/com/google/android/exoplayer2/source/hls/DefaultHlsDataSourceFactory.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.android.exoplayer2.source.hls; + +import com.google.android.exoplayer2.upstream.DataSource; + +/** + * Default implementation of {@link HlsDataSourceFactory}. + */ +public final class DefaultHlsDataSourceFactory implements HlsDataSourceFactory { + + private final DataSource.Factory dataSourceFactory; + + /** + * @param dataSourceFactory The {@link DataSource.Factory} to use for all data types. + */ + public DefaultHlsDataSourceFactory(DataSource.Factory dataSourceFactory) { + this.dataSourceFactory = dataSourceFactory; + } + + @Override + public DataSource createDataSource(int dataType) { + return dataSourceFactory.createDataSource(); + } + +} diff --git a/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java b/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java index 7ba5cf2df1..5775e4ec38 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java @@ -81,7 +81,8 @@ import java.util.Locale; } - private final DataSource dataSource; + private final DataSource mediaDataSource; + private final DataSource encryptionDataSource; private final TimestampAdjusterProvider timestampAdjusterProvider; private final HlsUrl[] variants; private final HlsPlaylistTracker playlistTracker; @@ -105,18 +106,18 @@ import java.util.Locale; /** * @param playlistTracker The {@link HlsPlaylistTracker} from which to obtain media playlists. * @param variants The available variants. - * @param dataSource A {@link DataSource} suitable for loading the media data. + * @param dataSourceFactory An {@link HlsDataSourceFactory} to create {@link DataSource}s for the + * chunks. * @param timestampAdjusterProvider A provider of {@link TimestampAdjuster} instances. If * multiple {@link HlsChunkSource}s are used for a single playback, they should all share the * same provider. * @param muxedCaptionFormats List of muxed caption {@link Format}s. */ public HlsChunkSource(HlsPlaylistTracker playlistTracker, HlsUrl[] variants, - DataSource dataSource, TimestampAdjusterProvider timestampAdjusterProvider, + HlsDataSourceFactory dataSourceFactory, TimestampAdjusterProvider timestampAdjusterProvider, List muxedCaptionFormats) { this.playlistTracker = playlistTracker; this.variants = variants; - this.dataSource = dataSource; this.timestampAdjusterProvider = timestampAdjusterProvider; this.muxedCaptionFormats = muxedCaptionFormats; Format[] variantFormats = new Format[variants.length]; @@ -125,6 +126,8 @@ import java.util.Locale; variantFormats[i] = variants[i].format; initialTrackSelection[i] = i; } + mediaDataSource = dataSourceFactory.createDataSource(C.DATA_TYPE_MEDIA); + encryptionDataSource = dataSourceFactory.createDataSource(C.DATA_TYPE_DRM); trackGroup = new TrackGroup(variantFormats); trackSelection = new InitializationTrackSelection(trackGroup, initialTrackSelection); } @@ -285,7 +288,7 @@ import java.util.Locale; Uri chunkUri = UriUtil.resolveToUri(mediaPlaylist.baseUri, segment.url); DataSpec dataSpec = new DataSpec(chunkUri, segment.byterangeOffset, segment.byterangeLength, null); - out.chunk = new HlsMediaChunk(dataSource, dataSpec, initDataSpec, selectedUrl, + out.chunk = new HlsMediaChunk(mediaDataSource, dataSpec, initDataSpec, selectedUrl, muxedCaptionFormats, trackSelection.getSelectionReason(), trackSelection.getSelectionData(), startTimeUs, startTimeUs + segment.durationUs, chunkMediaSequence, discontinuitySequence, isTimestampMaster, timestampAdjuster, previous, encryptionKey, encryptionIv); @@ -341,7 +344,7 @@ import java.util.Locale; private EncryptionKeyChunk newEncryptionKeyChunk(Uri keyUri, String iv, int variantIndex, int trackSelectionReason, Object trackSelectionData) { DataSpec dataSpec = new DataSpec(keyUri, 0, C.LENGTH_UNSET, null, DataSpec.FLAG_ALLOW_GZIP); - return new EncryptionKeyChunk(dataSource, dataSpec, variants[variantIndex].format, + return new EncryptionKeyChunk(encryptionDataSource, dataSpec, variants[variantIndex].format, trackSelectionReason, trackSelectionData, scratchSpace, iv); } diff --git a/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsDataSourceFactory.java b/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsDataSourceFactory.java new file mode 100644 index 0000000000..30e7af5a0b --- /dev/null +++ b/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsDataSourceFactory.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.android.exoplayer2.source.hls; + +import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.upstream.DataSource; + +/** + * Creates {@link DataSource}s for HLS playlists, encryption and media chunks. + */ +public interface HlsDataSourceFactory { + + /** + * Creates a {@link DataSource} for the given data type. + * + * @param dataType The data type for which the {@link DataSource} will be used. One of {@link C} + * {@code .DATA_TYPE_*} constants. + * @return A {@link DataSource} for the given data type. + */ + DataSource createDataSource(int dataType); + +} diff --git a/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java b/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java index 23ccccbb6b..6515e912cd 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java @@ -30,7 +30,6 @@ import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist.HlsUr import com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistTracker; import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.upstream.Allocator; -import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.util.Assertions; import java.io.IOException; import java.util.ArrayList; @@ -44,7 +43,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper HlsPlaylistTracker.PlaylistEventListener { private final HlsPlaylistTracker playlistTracker; - private final DataSource.Factory dataSourceFactory; + private final HlsDataSourceFactory dataSourceFactory; private final int minLoadableRetryCount; private final EventDispatcher eventDispatcher; private final Allocator allocator; @@ -61,7 +60,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper private HlsSampleStreamWrapper[] enabledSampleStreamWrappers; private CompositeSequenceableLoader sequenceableLoader; - public HlsMediaPeriod(HlsPlaylistTracker playlistTracker, DataSource.Factory dataSourceFactory, + public HlsMediaPeriod(HlsPlaylistTracker playlistTracker, HlsDataSourceFactory dataSourceFactory, int minLoadableRetryCount, EventDispatcher eventDispatcher, Allocator allocator, long positionUs) { this.playlistTracker = playlistTracker; @@ -349,9 +348,8 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper private HlsSampleStreamWrapper buildSampleStreamWrapper(int trackType, HlsUrl[] variants, Format muxedAudioFormat, List muxedCaptionFormats) { - DataSource dataSource = dataSourceFactory.createDataSource(); - HlsChunkSource defaultChunkSource = new HlsChunkSource(playlistTracker, variants, dataSource, - timestampAdjusterProvider, muxedCaptionFormats); + HlsChunkSource defaultChunkSource = new HlsChunkSource(playlistTracker, variants, + dataSourceFactory, timestampAdjusterProvider, muxedCaptionFormats); return new HlsSampleStreamWrapper(trackType, this, defaultChunkSource, allocator, preparePositionUs, muxedAudioFormat, minLoadableRetryCount, eventDispatcher); } diff --git a/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaSource.java b/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaSource.java index 10e12f0ec6..11de1adfb1 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaSource.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaSource.java @@ -44,7 +44,7 @@ public final class HlsMediaSource implements MediaSource, public static final int DEFAULT_MIN_LOADABLE_RETRY_COUNT = 3; private final Uri manifestUri; - private final DataSource.Factory dataSourceFactory; + private final HlsDataSourceFactory dataSourceFactory; private final int minLoadableRetryCount; private final EventDispatcher eventDispatcher; @@ -60,6 +60,13 @@ public final class HlsMediaSource implements MediaSource, public HlsMediaSource(Uri manifestUri, DataSource.Factory dataSourceFactory, int minLoadableRetryCount, Handler eventHandler, AdaptiveMediaSourceEventListener eventListener) { + this(manifestUri, new DefaultHlsDataSourceFactory(dataSourceFactory), minLoadableRetryCount, + eventHandler, eventListener); + } + + public HlsMediaSource(Uri manifestUri, HlsDataSourceFactory dataSourceFactory, + int minLoadableRetryCount, Handler eventHandler, + AdaptiveMediaSourceEventListener eventListener) { this.manifestUri = manifestUri; this.dataSourceFactory = dataSourceFactory; this.minLoadableRetryCount = minLoadableRetryCount; diff --git a/library/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistTracker.java b/library/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistTracker.java index e2e5870777..447d9ba54e 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistTracker.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistTracker.java @@ -22,6 +22,7 @@ import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ParserException; import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener.EventDispatcher; import com.google.android.exoplayer2.source.chunk.ChunkedTrackBlacklistUtil; +import com.google.android.exoplayer2.source.hls.HlsDataSourceFactory; import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist.HlsUrl; import com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist.Segment; import com.google.android.exoplayer2.upstream.DataSource; @@ -81,7 +82,7 @@ public final class HlsPlaylistTracker implements Loader.Callback playlistBundles; @@ -105,7 +106,7 @@ public final class HlsPlaylistTracker implements Loader.Callback masterPlaylistLoadable = new ParsingLoadable<>( - dataSourceFactory.createDataSource(), initialPlaylistUri, C.DATA_TYPE_MANIFEST, - playlistParser); + dataSourceFactory.createDataSource(C.DATA_TYPE_MANIFEST), initialPlaylistUri, + C.DATA_TYPE_MANIFEST, playlistParser); initialPlaylistLoader.startLoading(masterPlaylistLoadable, this, minRetryCount); } @@ -436,7 +437,8 @@ public final class HlsPlaylistTracker implements Loader.Callback(dataSourceFactory.createDataSource(), + mediaPlaylistLoadable = new ParsingLoadable<>( + dataSourceFactory.createDataSource(C.DATA_TYPE_MANIFEST), UriUtil.resolveToUri(masterPlaylist.baseUri, playlistUrl.url), C.DATA_TYPE_MANIFEST, playlistParser); } diff --git a/library/src/main/java/com/google/android/exoplayer2/upstream/DataSpec.java b/library/src/main/java/com/google/android/exoplayer2/upstream/DataSpec.java index c9ff19aee6..d3c63b4454 100644 --- a/library/src/main/java/com/google/android/exoplayer2/upstream/DataSpec.java +++ b/library/src/main/java/com/google/android/exoplayer2/upstream/DataSpec.java @@ -47,7 +47,9 @@ public final class DataSpec { */ public static final int FLAG_ALLOW_GZIP = 1 << 0; - /** Permits content to be cached even if its length can not be resolved. */ + /** + * Permits content to be cached even if its length can not be resolved. + */ public static final int FLAG_ALLOW_CACHING_UNKNOWN_LENGTH = 1 << 1; /**