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
This commit is contained in:
aquilescanta 2017-03-08 07:51:13 -08:00 committed by Oliver Woodman
parent 78e7c3c510
commit 3be4451e13
7 changed files with 105 additions and 19 deletions

View File

@ -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();
}
}

View File

@ -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 TimestampAdjusterProvider timestampAdjusterProvider;
private final HlsUrl[] variants; private final HlsUrl[] variants;
private final HlsPlaylistTracker playlistTracker; private final HlsPlaylistTracker playlistTracker;
@ -105,18 +106,18 @@ import java.util.Locale;
/** /**
* @param playlistTracker The {@link HlsPlaylistTracker} from which to obtain media playlists. * @param playlistTracker The {@link HlsPlaylistTracker} from which to obtain media playlists.
* @param variants The available variants. * @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 * @param timestampAdjusterProvider A provider of {@link TimestampAdjuster} instances. If
* multiple {@link HlsChunkSource}s are used for a single playback, they should all share the * multiple {@link HlsChunkSource}s are used for a single playback, they should all share the
* same provider. * same provider.
* @param muxedCaptionFormats List of muxed caption {@link Format}s. * @param muxedCaptionFormats List of muxed caption {@link Format}s.
*/ */
public HlsChunkSource(HlsPlaylistTracker playlistTracker, HlsUrl[] variants, public HlsChunkSource(HlsPlaylistTracker playlistTracker, HlsUrl[] variants,
DataSource dataSource, TimestampAdjusterProvider timestampAdjusterProvider, HlsDataSourceFactory dataSourceFactory, TimestampAdjusterProvider timestampAdjusterProvider,
List<Format> muxedCaptionFormats) { List<Format> muxedCaptionFormats) {
this.playlistTracker = playlistTracker; this.playlistTracker = playlistTracker;
this.variants = variants; this.variants = variants;
this.dataSource = dataSource;
this.timestampAdjusterProvider = timestampAdjusterProvider; this.timestampAdjusterProvider = timestampAdjusterProvider;
this.muxedCaptionFormats = muxedCaptionFormats; this.muxedCaptionFormats = muxedCaptionFormats;
Format[] variantFormats = new Format[variants.length]; Format[] variantFormats = new Format[variants.length];
@ -125,6 +126,8 @@ import java.util.Locale;
variantFormats[i] = variants[i].format; variantFormats[i] = variants[i].format;
initialTrackSelection[i] = i; initialTrackSelection[i] = i;
} }
mediaDataSource = dataSourceFactory.createDataSource(C.DATA_TYPE_MEDIA);
encryptionDataSource = dataSourceFactory.createDataSource(C.DATA_TYPE_DRM);
trackGroup = new TrackGroup(variantFormats); trackGroup = new TrackGroup(variantFormats);
trackSelection = new InitializationTrackSelection(trackGroup, initialTrackSelection); trackSelection = new InitializationTrackSelection(trackGroup, initialTrackSelection);
} }
@ -285,7 +288,7 @@ import java.util.Locale;
Uri chunkUri = UriUtil.resolveToUri(mediaPlaylist.baseUri, segment.url); Uri chunkUri = UriUtil.resolveToUri(mediaPlaylist.baseUri, segment.url);
DataSpec dataSpec = new DataSpec(chunkUri, segment.byterangeOffset, segment.byterangeLength, DataSpec dataSpec = new DataSpec(chunkUri, segment.byterangeOffset, segment.byterangeLength,
null); null);
out.chunk = new HlsMediaChunk(dataSource, dataSpec, initDataSpec, selectedUrl, out.chunk = new HlsMediaChunk(mediaDataSource, dataSpec, initDataSpec, selectedUrl,
muxedCaptionFormats, trackSelection.getSelectionReason(), trackSelection.getSelectionData(), muxedCaptionFormats, trackSelection.getSelectionReason(), trackSelection.getSelectionData(),
startTimeUs, startTimeUs + segment.durationUs, chunkMediaSequence, discontinuitySequence, startTimeUs, startTimeUs + segment.durationUs, chunkMediaSequence, discontinuitySequence,
isTimestampMaster, timestampAdjuster, previous, encryptionKey, encryptionIv); isTimestampMaster, timestampAdjuster, previous, encryptionKey, encryptionIv);
@ -341,7 +344,7 @@ import java.util.Locale;
private EncryptionKeyChunk newEncryptionKeyChunk(Uri keyUri, String iv, int variantIndex, private EncryptionKeyChunk newEncryptionKeyChunk(Uri keyUri, String iv, int variantIndex,
int trackSelectionReason, Object trackSelectionData) { int trackSelectionReason, Object trackSelectionData) {
DataSpec dataSpec = new DataSpec(keyUri, 0, C.LENGTH_UNSET, null, DataSpec.FLAG_ALLOW_GZIP); 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); trackSelectionReason, trackSelectionData, scratchSpace, iv);
} }

View File

@ -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);
}

View File

@ -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.source.hls.playlist.HlsPlaylistTracker;
import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@ -44,7 +43,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
HlsPlaylistTracker.PlaylistEventListener { HlsPlaylistTracker.PlaylistEventListener {
private final HlsPlaylistTracker playlistTracker; private final HlsPlaylistTracker playlistTracker;
private final DataSource.Factory dataSourceFactory; private final HlsDataSourceFactory dataSourceFactory;
private final int minLoadableRetryCount; private final int minLoadableRetryCount;
private final EventDispatcher eventDispatcher; private final EventDispatcher eventDispatcher;
private final Allocator allocator; private final Allocator allocator;
@ -61,7 +60,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
private HlsSampleStreamWrapper[] enabledSampleStreamWrappers; private HlsSampleStreamWrapper[] enabledSampleStreamWrappers;
private CompositeSequenceableLoader sequenceableLoader; private CompositeSequenceableLoader sequenceableLoader;
public HlsMediaPeriod(HlsPlaylistTracker playlistTracker, DataSource.Factory dataSourceFactory, public HlsMediaPeriod(HlsPlaylistTracker playlistTracker, HlsDataSourceFactory dataSourceFactory,
int minLoadableRetryCount, EventDispatcher eventDispatcher, Allocator allocator, int minLoadableRetryCount, EventDispatcher eventDispatcher, Allocator allocator,
long positionUs) { long positionUs) {
this.playlistTracker = playlistTracker; this.playlistTracker = playlistTracker;
@ -349,9 +348,8 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
private HlsSampleStreamWrapper buildSampleStreamWrapper(int trackType, HlsUrl[] variants, private HlsSampleStreamWrapper buildSampleStreamWrapper(int trackType, HlsUrl[] variants,
Format muxedAudioFormat, List<Format> muxedCaptionFormats) { Format muxedAudioFormat, List<Format> muxedCaptionFormats) {
DataSource dataSource = dataSourceFactory.createDataSource(); HlsChunkSource defaultChunkSource = new HlsChunkSource(playlistTracker, variants,
HlsChunkSource defaultChunkSource = new HlsChunkSource(playlistTracker, variants, dataSource, dataSourceFactory, timestampAdjusterProvider, muxedCaptionFormats);
timestampAdjusterProvider, muxedCaptionFormats);
return new HlsSampleStreamWrapper(trackType, this, defaultChunkSource, allocator, return new HlsSampleStreamWrapper(trackType, this, defaultChunkSource, allocator,
preparePositionUs, muxedAudioFormat, minLoadableRetryCount, eventDispatcher); preparePositionUs, muxedAudioFormat, minLoadableRetryCount, eventDispatcher);
} }

View File

@ -44,7 +44,7 @@ public final class HlsMediaSource implements MediaSource,
public static final int DEFAULT_MIN_LOADABLE_RETRY_COUNT = 3; public static final int DEFAULT_MIN_LOADABLE_RETRY_COUNT = 3;
private final Uri manifestUri; private final Uri manifestUri;
private final DataSource.Factory dataSourceFactory; private final HlsDataSourceFactory dataSourceFactory;
private final int minLoadableRetryCount; private final int minLoadableRetryCount;
private final EventDispatcher eventDispatcher; private final EventDispatcher eventDispatcher;
@ -60,6 +60,13 @@ public final class HlsMediaSource implements MediaSource,
public HlsMediaSource(Uri manifestUri, DataSource.Factory dataSourceFactory, public HlsMediaSource(Uri manifestUri, DataSource.Factory dataSourceFactory,
int minLoadableRetryCount, Handler eventHandler, int minLoadableRetryCount, Handler eventHandler,
AdaptiveMediaSourceEventListener eventListener) { 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.manifestUri = manifestUri;
this.dataSourceFactory = dataSourceFactory; this.dataSourceFactory = dataSourceFactory;
this.minLoadableRetryCount = minLoadableRetryCount; this.minLoadableRetryCount = minLoadableRetryCount;

View File

@ -22,6 +22,7 @@ import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ParserException; import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener.EventDispatcher; import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener.EventDispatcher;
import com.google.android.exoplayer2.source.chunk.ChunkedTrackBlacklistUtil; 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.HlsMasterPlaylist.HlsUrl;
import com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist.Segment; import com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist.Segment;
import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSource;
@ -81,7 +82,7 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
private static final long PRIMARY_URL_KEEPALIVE_MS = 15000; private static final long PRIMARY_URL_KEEPALIVE_MS = 15000;
private final Uri initialPlaylistUri; private final Uri initialPlaylistUri;
private final DataSource.Factory dataSourceFactory; private final HlsDataSourceFactory dataSourceFactory;
private final HlsPlaylistParser playlistParser; private final HlsPlaylistParser playlistParser;
private final int minRetryCount; private final int minRetryCount;
private final IdentityHashMap<HlsUrl, MediaPlaylistBundle> playlistBundles; private final IdentityHashMap<HlsUrl, MediaPlaylistBundle> playlistBundles;
@ -105,7 +106,7 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
* playlist. * playlist.
* @param primaryPlaylistListener A callback for the primary playlist change events. * @param primaryPlaylistListener A callback for the primary playlist change events.
*/ */
public HlsPlaylistTracker(Uri initialPlaylistUri, DataSource.Factory dataSourceFactory, public HlsPlaylistTracker(Uri initialPlaylistUri, HlsDataSourceFactory dataSourceFactory,
EventDispatcher eventDispatcher, int minRetryCount, EventDispatcher eventDispatcher, int minRetryCount,
PrimaryPlaylistListener primaryPlaylistListener) { PrimaryPlaylistListener primaryPlaylistListener) {
this.initialPlaylistUri = initialPlaylistUri; this.initialPlaylistUri = initialPlaylistUri;
@ -143,8 +144,8 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
*/ */
public void start() { public void start() {
ParsingLoadable<HlsPlaylist> masterPlaylistLoadable = new ParsingLoadable<>( ParsingLoadable<HlsPlaylist> masterPlaylistLoadable = new ParsingLoadable<>(
dataSourceFactory.createDataSource(), initialPlaylistUri, C.DATA_TYPE_MANIFEST, dataSourceFactory.createDataSource(C.DATA_TYPE_MANIFEST), initialPlaylistUri,
playlistParser); C.DATA_TYPE_MANIFEST, playlistParser);
initialPlaylistLoader.startLoading(masterPlaylistLoadable, this, minRetryCount); initialPlaylistLoader.startLoading(masterPlaylistLoadable, this, minRetryCount);
} }
@ -436,7 +437,8 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
this.playlistUrl = playlistUrl; this.playlistUrl = playlistUrl;
lastSnapshotAccessTimeMs = initialLastSnapshotAccessTimeMs; lastSnapshotAccessTimeMs = initialLastSnapshotAccessTimeMs;
mediaPlaylistLoader = new Loader("HlsPlaylistTracker:MediaPlaylist"); mediaPlaylistLoader = new Loader("HlsPlaylistTracker:MediaPlaylist");
mediaPlaylistLoadable = new ParsingLoadable<>(dataSourceFactory.createDataSource(), mediaPlaylistLoadable = new ParsingLoadable<>(
dataSourceFactory.createDataSource(C.DATA_TYPE_MANIFEST),
UriUtil.resolveToUri(masterPlaylist.baseUri, playlistUrl.url), C.DATA_TYPE_MANIFEST, UriUtil.resolveToUri(masterPlaylist.baseUri, playlistUrl.url), C.DATA_TYPE_MANIFEST,
playlistParser); playlistParser);
} }

View File

@ -47,7 +47,9 @@ public final class DataSpec {
*/ */
public static final int FLAG_ALLOW_GZIP = 1 << 0; 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; public static final int FLAG_ALLOW_CACHING_UNKNOWN_LENGTH = 1 << 1;
/** /**