Commit 0a8ae742 by tonihei Committed by Oliver Woodman

Update DownloadHelper to use MediaSource and MediaPeriod directly.

This requires to prepare the media source and the periods in a small helper similar
to the metadata retriever. It also gets rid of the need to have abstract protected
methods to load the manifest, to extract the track groups and to convert to stream keys,
as this can now be handled by the media period.

PiperOrigin-RevId: 231385590
parent 32b40502
...@@ -210,7 +210,7 @@ public class DownloadTracker implements DownloadManager.Listener { ...@@ -210,7 +210,7 @@ public class DownloadTracker implements DownloadManager.Listener {
DownloadService.startWithAction(context, DemoDownloadService.class, action, false); DownloadService.startWithAction(context, DemoDownloadService.class, action, false);
} }
private DownloadHelper<?> getDownloadHelper( private DownloadHelper getDownloadHelper(
Uri uri, String extension, RenderersFactory renderersFactory) { Uri uri, String extension, RenderersFactory renderersFactory) {
int type = Util.inferContentType(uri, extension); int type = Util.inferContentType(uri, extension);
switch (type) { switch (type) {
...@@ -231,10 +231,11 @@ public class DownloadTracker implements DownloadManager.Listener { ...@@ -231,10 +231,11 @@ public class DownloadTracker implements DownloadManager.Listener {
private final class StartDownloadDialogHelper private final class StartDownloadDialogHelper
implements DownloadHelper.Callback, implements DownloadHelper.Callback,
DialogInterface.OnClickListener, DialogInterface.OnClickListener,
DialogInterface.OnDismissListener,
View.OnClickListener, View.OnClickListener,
TrackSelectionView.DialogCallback { TrackSelectionView.DialogCallback {
private final DownloadHelper<?> downloadHelper; private final DownloadHelper downloadHelper;
private final String name; private final String name;
private final LayoutInflater dialogInflater; private final LayoutInflater dialogInflater;
private final AlertDialog dialog; private final AlertDialog dialog;
...@@ -244,20 +245,21 @@ public class DownloadTracker implements DownloadManager.Listener { ...@@ -244,20 +245,21 @@ public class DownloadTracker implements DownloadManager.Listener {
private DefaultTrackSelector.Parameters parameters; private DefaultTrackSelector.Parameters parameters;
private StartDownloadDialogHelper( private StartDownloadDialogHelper(
Activity activity, DownloadHelper<?> downloadHelper, String name) { Activity activity, DownloadHelper downloadHelper, String name) {
this.downloadHelper = downloadHelper; this.downloadHelper = downloadHelper;
this.name = name; this.name = name;
AlertDialog.Builder builder = AlertDialog.Builder builder =
new AlertDialog.Builder(activity) new AlertDialog.Builder(activity)
.setTitle(R.string.download_preparing) .setTitle(R.string.download_preparing)
.setPositiveButton(android.R.string.ok, this) .setPositiveButton(android.R.string.ok, /* listener= */ this)
.setNegativeButton(android.R.string.cancel, null); .setNegativeButton(android.R.string.cancel, /* listener= */ null);
// Inflate with the builder's context to ensure the correct style is used. // Inflate with the builder's context to ensure the correct style is used.
dialogInflater = LayoutInflater.from(builder.getContext()); dialogInflater = LayoutInflater.from(builder.getContext());
selectionList = (LinearLayout) dialogInflater.inflate(R.layout.start_download_dialog, null); selectionList = (LinearLayout) dialogInflater.inflate(R.layout.start_download_dialog, null);
builder.setView(selectionList); builder.setView(selectionList);
dialog = builder.create(); dialog = builder.create();
dialog.setOnDismissListener(/* listener= */ this);
dialog.show(); dialog.show();
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false); dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
...@@ -268,19 +270,17 @@ public class DownloadTracker implements DownloadManager.Listener { ...@@ -268,19 +270,17 @@ public class DownloadTracker implements DownloadManager.Listener {
// DownloadHelper.Callback implementation. // DownloadHelper.Callback implementation.
@Override @Override
public void onPrepared(DownloadHelper<?> helper) { public void onPrepared(DownloadHelper helper) {
if (helper.getPeriodCount() < 1) { if (helper.getPeriodCount() > 0) {
onPrepareError(downloadHelper, new IOException("Content is empty."));
return;
}
mappedTrackInfo = downloadHelper.getMappedTrackInfo(/* periodIndex= */ 0); mappedTrackInfo = downloadHelper.getMappedTrackInfo(/* periodIndex= */ 0);
updateSelectionList(); updateSelectionList();
}
dialog.setTitle(R.string.exo_download_description); dialog.setTitle(R.string.exo_download_description);
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(true); dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(true);
} }
@Override @Override
public void onPrepareError(DownloadHelper<?> helper, IOException e) { public void onPrepareError(DownloadHelper helper, IOException e) {
Toast.makeText( Toast.makeText(
context.getApplicationContext(), R.string.download_start_error, Toast.LENGTH_LONG) context.getApplicationContext(), R.string.download_start_error, Toast.LENGTH_LONG)
.show(); .show();
...@@ -326,6 +326,13 @@ public class DownloadTracker implements DownloadManager.Listener { ...@@ -326,6 +326,13 @@ public class DownloadTracker implements DownloadManager.Listener {
startDownload(downloadAction); startDownload(downloadAction);
} }
// DialogInterface.OnDismissListener implementation.
@Override
public void onDismiss(DialogInterface dialog) {
downloadHelper.release();
}
// Internal methods. // Internal methods.
private void updateSelectionList() { private void updateSelectionList() {
......
...@@ -17,11 +17,9 @@ package com.google.android.exoplayer2.offline; ...@@ -17,11 +17,9 @@ package com.google.android.exoplayer2.offline;
import android.net.Uri; import android.net.Uri;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.source.TrackGroupArray;
/** A {@link DownloadHelper} for progressive streams. */ /** A {@link DownloadHelper} for progressive streams. */
public final class ProgressiveDownloadHelper extends DownloadHelper<Void> { public final class ProgressiveDownloadHelper extends DownloadHelper {
/** /**
* Creates download helper for progressive streams. * Creates download helper for progressive streams.
...@@ -43,24 +41,9 @@ public final class ProgressiveDownloadHelper extends DownloadHelper<Void> { ...@@ -43,24 +41,9 @@ public final class ProgressiveDownloadHelper extends DownloadHelper<Void> {
DownloadAction.TYPE_PROGRESSIVE, DownloadAction.TYPE_PROGRESSIVE,
uri, uri,
cacheKey, cacheKey,
DownloadHelper.DEFAULT_TRACK_SELECTOR_PARAMETERS, /* mediaSource= */ null,
(handler, videoListener, audioListener, metadata, text, drm) -> new Renderer[0], /* trackSelectorParameters= */ DownloadHelper.DEFAULT_TRACK_SELECTOR_PARAMETERS,
/* renderersFactory= */ null,
/* drmSessionManager= */ null); /* drmSessionManager= */ null);
} }
@Override
protected Void loadManifest(Uri uri) {
return null;
}
@Override
protected TrackGroupArray[] getTrackGroupArrays(Void manifest) {
return new TrackGroupArray[] {TrackGroupArray.EMPTY};
}
@Override
protected StreamKey toStreamKey(
int periodIndex, int trackGroupIndex, int trackIndexInTrackGroup) {
return new StreamKey(periodIndex, trackGroupIndex, trackIndexInTrackGroup);
}
} }
...@@ -22,17 +22,28 @@ import com.google.android.exoplayer2.C; ...@@ -22,17 +22,28 @@ import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.Renderer; import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.RenderersFactory; import com.google.android.exoplayer2.RenderersFactory;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.offline.DownloadHelper.Callback; import com.google.android.exoplayer2.offline.DownloadHelper.Callback;
import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher;
import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.testutil.FakeMediaPeriod;
import com.google.android.exoplayer2.testutil.FakeMediaSource;
import com.google.android.exoplayer2.testutil.FakeRenderer; import com.google.android.exoplayer2.testutil.FakeRenderer;
import com.google.android.exoplayer2.testutil.FakeTimeline;
import com.google.android.exoplayer2.testutil.FakeTimeline.TimelineWindowDefinition;
import com.google.android.exoplayer2.testutil.RobolectricUtil;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector.ParametersBuilder; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector.ParametersBuilder;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo; import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo;
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.util.ConditionVariable; import com.google.android.exoplayer2.util.ConditionVariable;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
...@@ -40,15 +51,19 @@ import org.junit.Before; ...@@ -40,15 +51,19 @@ import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowLooper; import org.robolectric.shadows.ShadowLooper;
/** Unit tests for {@link DownloadHelper}. */ /** Unit tests for {@link DownloadHelper}. */
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
@Config(shadows = {RobolectricUtil.CustomLooper.class, RobolectricUtil.CustomMessageQueue.class})
public class DownloadHelperTest { public class DownloadHelperTest {
private static final String TEST_DOWNLOAD_TYPE = "downloadType"; private static final String TEST_DOWNLOAD_TYPE = "downloadType";
private static final String TEST_CACHE_KEY = "cacheKey"; private static final String TEST_CACHE_KEY = "cacheKey";
private static final ManifestType TEST_MANIFEST = new ManifestType(); private static final Timeline TEST_TIMELINE =
new FakeTimeline(new TimelineWindowDefinition(/* periodCount= */ 2, /* id= */ new Object()));
private static final Object TEST_MANIFEST = new Object();
private static final Format VIDEO_FORMAT_LOW = createVideoFormat(/* bitrate= */ 200_000); private static final Format VIDEO_FORMAT_LOW = createVideoFormat(/* bitrate= */ 200_000);
private static final Format VIDEO_FORMAT_HIGH = createVideoFormat(/* bitrate= */ 800_000); private static final Format VIDEO_FORMAT_HIGH = createVideoFormat(/* bitrate= */ 800_000);
...@@ -98,7 +113,7 @@ public class DownloadHelperTest { ...@@ -98,7 +113,7 @@ public class DownloadHelperTest {
public void getManifest_returnsManifest() throws Exception { public void getManifest_returnsManifest() throws Exception {
prepareDownloadHelper(downloadHelper); prepareDownloadHelper(downloadHelper);
ManifestType manifest = downloadHelper.getManifest(); Object manifest = downloadHelper.getManifest();
assertThat(manifest).isEqualTo(TEST_MANIFEST); assertThat(manifest).isEqualTo(TEST_MANIFEST);
} }
...@@ -337,12 +352,12 @@ public class DownloadHelperTest { ...@@ -337,12 +352,12 @@ public class DownloadHelperTest {
downloadHelper.prepare( downloadHelper.prepare(
new Callback() { new Callback() {
@Override @Override
public void onPrepared(DownloadHelper<?> helper) { public void onPrepared(DownloadHelper helper) {
preparedCondition.open(); preparedCondition.open();
} }
@Override @Override
public void onPrepareError(DownloadHelper<?> helper, IOException e) { public void onPrepareError(DownloadHelper helper, IOException e) {
prepareException.set(e); prepareException.set(e);
preparedCondition.open(); preparedCondition.open();
} }
...@@ -411,35 +426,52 @@ public class DownloadHelperTest { ...@@ -411,35 +426,52 @@ public class DownloadHelperTest {
assertThat(selectedTracksInGroup).isEqualTo(tracks); assertThat(selectedTracksInGroup).isEqualTo(tracks);
} }
private static final class ManifestType {} private static final class FakeDownloadHelper extends DownloadHelper {
private static final class FakeDownloadHelper extends DownloadHelper<ManifestType> {
public FakeDownloadHelper(Uri testUri, RenderersFactory renderersFactory) { public FakeDownloadHelper(Uri testUri, RenderersFactory renderersFactory) {
super( super(
TEST_DOWNLOAD_TYPE, TEST_DOWNLOAD_TYPE,
testUri, testUri,
TEST_CACHE_KEY, TEST_CACHE_KEY,
new TestMediaSource(),
DownloadHelper.DEFAULT_TRACK_SELECTOR_PARAMETERS, DownloadHelper.DEFAULT_TRACK_SELECTOR_PARAMETERS,
renderersFactory, renderersFactory,
/* drmSessionManager= */ null); /* drmSessionManager= */ null);
} }
}
@Override private static final class TestMediaSource extends FakeMediaSource {
protected ManifestType loadManifest(Uri uri) throws IOException {
return TEST_MANIFEST; public TestMediaSource() {
super(TEST_TIMELINE, TEST_MANIFEST);
} }
@Override @Override
protected TrackGroupArray[] getTrackGroupArrays(ManifestType manifest) { public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) {
assertThat(manifest).isEqualTo(TEST_MANIFEST); int periodIndex = TEST_TIMELINE.getIndexOfPeriod(id.periodUid);
return TRACK_GROUP_ARRAYS; return new FakeMediaPeriod(
TRACK_GROUP_ARRAYS[periodIndex],
new EventDispatcher()
.withParameters(/* windowIndex= */ 0, id, /* mediaTimeOffsetMs= */ 0)) {
@Override
public List<StreamKey> getStreamKeys(List<TrackSelection> trackSelections) {
List<StreamKey> result = new ArrayList<>();
for (TrackSelection trackSelection : trackSelections) {
int groupIndex =
TRACK_GROUP_ARRAYS[periodIndex].indexOf(trackSelection.getTrackGroup());
for (int i = 0; i < trackSelection.length(); i++) {
result.add(
new StreamKey(periodIndex, groupIndex, trackSelection.getIndexInTrackGroup(i)));
}
}
return result;
}
};
} }
@Override @Override
protected StreamKey toStreamKey( public void releasePeriod(MediaPeriod mediaPeriod) {
int periodIndex, int trackGroupIndex, int trackIndexInTrackGroup) { // Do nothing.
return new StreamKey(periodIndex, trackGroupIndex, trackIndexInTrackGroup);
} }
} }
} }
...@@ -17,30 +17,17 @@ package com.google.android.exoplayer2.source.dash.offline; ...@@ -17,30 +17,17 @@ package com.google.android.exoplayer2.source.dash.offline;
import android.net.Uri; import android.net.Uri;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.RenderersFactory; import com.google.android.exoplayer2.RenderersFactory;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.drm.FrameworkMediaCrypto; import com.google.android.exoplayer2.drm.FrameworkMediaCrypto;
import com.google.android.exoplayer2.offline.DownloadAction; import com.google.android.exoplayer2.offline.DownloadAction;
import com.google.android.exoplayer2.offline.DownloadHelper; import com.google.android.exoplayer2.offline.DownloadHelper;
import com.google.android.exoplayer2.offline.StreamKey; import com.google.android.exoplayer2.source.dash.DashMediaSource;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.source.dash.manifest.AdaptationSet;
import com.google.android.exoplayer2.source.dash.manifest.DashManifest;
import com.google.android.exoplayer2.source.dash.manifest.DashManifestParser;
import com.google.android.exoplayer2.source.dash.manifest.Representation;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.ParsingLoadable;
import java.io.IOException;
import java.util.List;
/** A {@link DownloadHelper} for DASH streams. */ /** A {@link DownloadHelper} for DASH streams. */
public final class DashDownloadHelper extends DownloadHelper<DashManifest> { public final class DashDownloadHelper extends DownloadHelper {
private final DataSource.Factory manifestDataSourceFactory;
/** /**
* Creates a DASH download helper. * Creates a DASH download helper.
...@@ -85,42 +72,9 @@ public final class DashDownloadHelper extends DownloadHelper<DashManifest> { ...@@ -85,42 +72,9 @@ public final class DashDownloadHelper extends DownloadHelper<DashManifest> {
DownloadAction.TYPE_DASH, DownloadAction.TYPE_DASH,
uri, uri,
/* cacheKey= */ null, /* cacheKey= */ null,
new DashMediaSource.Factory(manifestDataSourceFactory).createMediaSource(uri),
trackSelectorParameters, trackSelectorParameters,
renderersFactory, renderersFactory,
drmSessionManager); drmSessionManager);
this.manifestDataSourceFactory = manifestDataSourceFactory;
}
@Override
protected DashManifest loadManifest(Uri uri) throws IOException {
DataSource dataSource = manifestDataSourceFactory.createDataSource();
return ParsingLoadable.load(dataSource, new DashManifestParser(), uri, C.DATA_TYPE_MANIFEST);
}
@Override
public TrackGroupArray[] getTrackGroupArrays(DashManifest manifest) {
int periodCount = manifest.getPeriodCount();
TrackGroupArray[] trackGroupArrays = new TrackGroupArray[periodCount];
for (int periodIndex = 0; periodIndex < periodCount; periodIndex++) {
List<AdaptationSet> adaptationSets = manifest.getPeriod(periodIndex).adaptationSets;
TrackGroup[] trackGroups = new TrackGroup[adaptationSets.size()];
for (int i = 0; i < trackGroups.length; i++) {
List<Representation> representations = adaptationSets.get(i).representations;
Format[] formats = new Format[representations.size()];
int representationsCount = representations.size();
for (int j = 0; j < representationsCount; j++) {
formats[j] = representations.get(j).format;
}
trackGroups[i] = new TrackGroup(formats);
}
trackGroupArrays[periodIndex] = new TrackGroupArray(trackGroups);
}
return trackGroupArrays;
}
@Override
protected StreamKey toStreamKey(
int periodIndex, int trackGroupIndex, int trackIndexInTrackGroup) {
return new StreamKey(periodIndex, trackGroupIndex, trackIndexInTrackGroup);
} }
} }
...@@ -17,34 +17,17 @@ package com.google.android.exoplayer2.source.hls.offline; ...@@ -17,34 +17,17 @@ package com.google.android.exoplayer2.source.hls.offline;
import android.net.Uri; import android.net.Uri;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.RenderersFactory; import com.google.android.exoplayer2.RenderersFactory;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.drm.FrameworkMediaCrypto; import com.google.android.exoplayer2.drm.FrameworkMediaCrypto;
import com.google.android.exoplayer2.offline.DownloadAction; import com.google.android.exoplayer2.offline.DownloadAction;
import com.google.android.exoplayer2.offline.DownloadHelper; import com.google.android.exoplayer2.offline.DownloadHelper;
import com.google.android.exoplayer2.offline.StreamKey; import com.google.android.exoplayer2.source.hls.HlsMediaSource;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist;
import com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist;
import com.google.android.exoplayer2.source.hls.playlist.HlsPlaylist;
import com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistParser;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.ParsingLoadable;
import com.google.android.exoplayer2.util.Assertions;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
/** A {@link DownloadHelper} for HLS streams. */ /** A {@link DownloadHelper} for HLS streams. */
public final class HlsDownloadHelper extends DownloadHelper<HlsPlaylist> { public final class HlsDownloadHelper extends DownloadHelper {
private final DataSource.Factory manifestDataSourceFactory;
private int[] renditionGroups;
/** /**
* Creates a HLS download helper. * Creates a HLS download helper.
...@@ -89,56 +72,11 @@ public final class HlsDownloadHelper extends DownloadHelper<HlsPlaylist> { ...@@ -89,56 +72,11 @@ public final class HlsDownloadHelper extends DownloadHelper<HlsPlaylist> {
DownloadAction.TYPE_HLS, DownloadAction.TYPE_HLS,
uri, uri,
/* cacheKey= */ null, /* cacheKey= */ null,
new HlsMediaSource.Factory(manifestDataSourceFactory)
.setAllowChunklessPreparation(true)
.createMediaSource(uri),
trackSelectorParameters, trackSelectorParameters,
renderersFactory, renderersFactory,
drmSessionManager); drmSessionManager);
this.manifestDataSourceFactory = manifestDataSourceFactory;
}
@Override
protected HlsPlaylist loadManifest(Uri uri) throws IOException {
DataSource dataSource = manifestDataSourceFactory.createDataSource();
return ParsingLoadable.load(dataSource, new HlsPlaylistParser(), uri, C.DATA_TYPE_MANIFEST);
}
@Override
protected TrackGroupArray[] getTrackGroupArrays(HlsPlaylist playlist) {
Assertions.checkNotNull(playlist);
if (playlist instanceof HlsMediaPlaylist) {
renditionGroups = new int[0];
return new TrackGroupArray[] {TrackGroupArray.EMPTY};
}
// TODO: Generate track groups as in playback. Reverse the mapping in toStreamKey.
HlsMasterPlaylist masterPlaylist = (HlsMasterPlaylist) playlist;
TrackGroup[] trackGroups = new TrackGroup[3];
renditionGroups = new int[3];
int trackGroupIndex = 0;
if (!masterPlaylist.variants.isEmpty()) {
renditionGroups[trackGroupIndex] = HlsMasterPlaylist.GROUP_INDEX_VARIANT;
trackGroups[trackGroupIndex++] = new TrackGroup(toFormats(masterPlaylist.variants));
}
if (!masterPlaylist.audios.isEmpty()) {
renditionGroups[trackGroupIndex] = HlsMasterPlaylist.GROUP_INDEX_AUDIO;
trackGroups[trackGroupIndex++] = new TrackGroup(toFormats(masterPlaylist.audios));
}
if (!masterPlaylist.subtitles.isEmpty()) {
renditionGroups[trackGroupIndex] = HlsMasterPlaylist.GROUP_INDEX_SUBTITLE;
trackGroups[trackGroupIndex++] = new TrackGroup(toFormats(masterPlaylist.subtitles));
}
return new TrackGroupArray[] {new TrackGroupArray(Arrays.copyOf(trackGroups, trackGroupIndex))};
}
@Override
protected StreamKey toStreamKey(
int periodIndex, int trackGroupIndex, int trackIndexInTrackGroup) {
return new StreamKey(renditionGroups[trackGroupIndex], trackIndexInTrackGroup);
}
private static Format[] toFormats(List<HlsMasterPlaylist.HlsUrl> hlsUrls) {
Format[] formats = new Format[hlsUrls.size()];
for (int i = 0; i < hlsUrls.size(); i++) {
formats[i] = hlsUrls.get(i).format;
}
return formats;
} }
} }
...@@ -17,27 +17,17 @@ package com.google.android.exoplayer2.source.smoothstreaming.offline; ...@@ -17,27 +17,17 @@ package com.google.android.exoplayer2.source.smoothstreaming.offline;
import android.net.Uri; import android.net.Uri;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.RenderersFactory; import com.google.android.exoplayer2.RenderersFactory;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.drm.FrameworkMediaCrypto; import com.google.android.exoplayer2.drm.FrameworkMediaCrypto;
import com.google.android.exoplayer2.offline.DownloadAction; import com.google.android.exoplayer2.offline.DownloadAction;
import com.google.android.exoplayer2.offline.DownloadHelper; import com.google.android.exoplayer2.offline.DownloadHelper;
import com.google.android.exoplayer2.offline.StreamKey; import com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest;
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifestParser;
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsUtil;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.ParsingLoadable;
import java.io.IOException;
/** A {@link DownloadHelper} for SmoothStreaming streams. */ /** A {@link DownloadHelper} for SmoothStreaming streams. */
public final class SsDownloadHelper extends DownloadHelper<SsManifest> { public final class SsDownloadHelper extends DownloadHelper {
private final DataSource.Factory manifestDataSourceFactory;
/** /**
* Creates a SmoothStreaming download helper. * Creates a SmoothStreaming download helper.
...@@ -82,32 +72,9 @@ public final class SsDownloadHelper extends DownloadHelper<SsManifest> { ...@@ -82,32 +72,9 @@ public final class SsDownloadHelper extends DownloadHelper<SsManifest> {
DownloadAction.TYPE_SS, DownloadAction.TYPE_SS,
uri, uri,
/* cacheKey= */ null, /* cacheKey= */ null,
new SsMediaSource.Factory(manifestDataSourceFactory).createMediaSource(uri),
trackSelectorParameters, trackSelectorParameters,
renderersFactory, renderersFactory,
drmSessionManager); drmSessionManager);
this.manifestDataSourceFactory = manifestDataSourceFactory;
}
@Override
protected SsManifest loadManifest(Uri uri) throws IOException {
DataSource dataSource = manifestDataSourceFactory.createDataSource();
Uri fixedUri = SsUtil.fixManifestUri(uri);
return ParsingLoadable.load(dataSource, new SsManifestParser(), fixedUri, C.DATA_TYPE_MANIFEST);
}
@Override
protected TrackGroupArray[] getTrackGroupArrays(SsManifest manifest) {
SsManifest.StreamElement[] streamElements = manifest.streamElements;
TrackGroup[] trackGroups = new TrackGroup[streamElements.length];
for (int i = 0; i < streamElements.length; i++) {
trackGroups[i] = new TrackGroup(streamElements[i].formats);
}
return new TrackGroupArray[] {new TrackGroupArray(trackGroups)};
}
@Override
protected StreamKey toStreamKey(
int periodIndex, int trackGroupIndex, int trackIndexInTrackGroup) {
return new StreamKey(trackGroupIndex, trackIndexInTrackGroup);
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment