Commit 122b2a1a by olly Committed by Oliver Woodman

Use single TrackGroup for switchable adaptation sets

Issue: #2431

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=157236031
parent 27fc82f0
...@@ -28,8 +28,8 @@ public interface DashChunkSource extends ChunkSource { ...@@ -28,8 +28,8 @@ public interface DashChunkSource extends ChunkSource {
interface Factory { interface Factory {
DashChunkSource createDashChunkSource(LoaderErrorThrower manifestLoaderErrorThrower, DashChunkSource createDashChunkSource(LoaderErrorThrower manifestLoaderErrorThrower,
DashManifest manifest, int periodIndex, int adaptationSetIndex, DashManifest manifest, int periodIndex, int[] adaptationSetIndices,
TrackSelection trackSelection, long elapsedRealtimeOffsetMs, TrackSelection trackSelection, int type, long elapsedRealtimeOffsetMs,
boolean enableEventMessageTrack, boolean enableCea608Track); boolean enableEventMessageTrack, boolean enableCea608Track);
} }
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
package com.google.android.exoplayer2.source.dash; package com.google.android.exoplayer2.source.dash;
import android.util.Pair; import android.util.Pair;
import android.util.SparseIntArray;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener.EventDispatcher; import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener.EventDispatcher;
...@@ -37,6 +38,7 @@ import com.google.android.exoplayer2.upstream.Allocator; ...@@ -37,6 +38,7 @@ import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.LoaderErrorThrower; import com.google.android.exoplayer2.upstream.LoaderErrorThrower;
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.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
...@@ -55,7 +57,7 @@ import java.util.List; ...@@ -55,7 +57,7 @@ import java.util.List;
private final LoaderErrorThrower manifestLoaderErrorThrower; private final LoaderErrorThrower manifestLoaderErrorThrower;
private final Allocator allocator; private final Allocator allocator;
private final TrackGroupArray trackGroups; private final TrackGroupArray trackGroups;
private final EmbeddedTrackInfo[] embeddedTrackInfos; private final TrackGroupInfo[] trackGroupInfos;
private Callback callback; private Callback callback;
private ChunkSampleStream<DashChunkSource>[] sampleStreams; private ChunkSampleStream<DashChunkSource>[] sampleStreams;
...@@ -80,9 +82,9 @@ import java.util.List; ...@@ -80,9 +82,9 @@ import java.util.List;
sampleStreams = newSampleStreamArray(0); sampleStreams = newSampleStreamArray(0);
sequenceableLoader = new CompositeSequenceableLoader(sampleStreams); sequenceableLoader = new CompositeSequenceableLoader(sampleStreams);
adaptationSets = manifest.getPeriod(periodIndex).adaptationSets; adaptationSets = manifest.getPeriod(periodIndex).adaptationSets;
Pair<TrackGroupArray, EmbeddedTrackInfo[]> result = buildTrackGroups(adaptationSets); Pair<TrackGroupArray, TrackGroupInfo[]> result = buildTrackGroups(adaptationSets);
trackGroups = result.first; trackGroups = result.first;
embeddedTrackInfos = result.second; trackGroupInfos = result.second;
} }
public void updateManifest(DashManifest manifest, int periodIndex) { public void updateManifest(DashManifest manifest, int periodIndex) {
...@@ -122,7 +124,6 @@ import java.util.List; ...@@ -122,7 +124,6 @@ import java.util.List;
@Override @Override
public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags, public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags,
SampleStream[] streams, boolean[] streamResetFlags, long positionUs) { SampleStream[] streams, boolean[] streamResetFlags, long positionUs) {
int adaptationSetCount = adaptationSets.size();
HashMap<Integer, ChunkSampleStream<DashChunkSource>> primarySampleStreams = new HashMap<>(); HashMap<Integer, ChunkSampleStream<DashChunkSource>> primarySampleStreams = new HashMap<>();
// First pass for primary tracks. // First pass for primary tracks.
for (int i = 0; i < selections.length; i++) { for (int i = 0; i < selections.length; i++) {
...@@ -133,14 +134,15 @@ import java.util.List; ...@@ -133,14 +134,15 @@ import java.util.List;
stream.release(); stream.release();
streams[i] = null; streams[i] = null;
} else { } else {
int adaptationSetIndex = trackGroups.indexOf(selections[i].getTrackGroup()); int trackGroupIndex = trackGroups.indexOf(selections[i].getTrackGroup());
primarySampleStreams.put(adaptationSetIndex, stream); primarySampleStreams.put(trackGroupIndex, stream);
} }
} }
if (streams[i] == null && selections[i] != null) { if (streams[i] == null && selections[i] != null) {
int trackGroupIndex = trackGroups.indexOf(selections[i].getTrackGroup()); int trackGroupIndex = trackGroups.indexOf(selections[i].getTrackGroup());
if (trackGroupIndex < adaptationSetCount) { TrackGroupInfo trackGroupInfo = trackGroupInfos[trackGroupIndex];
ChunkSampleStream<DashChunkSource> stream = buildSampleStream(trackGroupIndex, if (trackGroupInfo.isPrimary) {
ChunkSampleStream<DashChunkSource> stream = buildSampleStream(trackGroupInfo,
selections[i], positionUs); selections[i], positionUs);
primarySampleStreams.put(trackGroupIndex, stream); primarySampleStreams.put(trackGroupIndex, stream);
streams[i] = stream; streams[i] = stream;
...@@ -160,11 +162,10 @@ import java.util.List; ...@@ -160,11 +162,10 @@ import java.util.List;
// may have been replaced, selected or deselected. // may have been replaced, selected or deselected.
if (selections[i] != null) { if (selections[i] != null) {
int trackGroupIndex = trackGroups.indexOf(selections[i].getTrackGroup()); int trackGroupIndex = trackGroups.indexOf(selections[i].getTrackGroup());
if (trackGroupIndex >= adaptationSetCount) { TrackGroupInfo trackGroupInfo = trackGroupInfos[trackGroupIndex];
int embeddedTrackIndex = trackGroupIndex - adaptationSetCount; if (!trackGroupInfo.isPrimary) {
EmbeddedTrackInfo embeddedTrackInfo = embeddedTrackInfos[embeddedTrackIndex]; ChunkSampleStream<?> primaryStream = primarySampleStreams.get(
int adaptationSetIndex = embeddedTrackInfo.adaptationSetIndex; trackGroupInfo.primaryTrackGroupIndex);
ChunkSampleStream<?> primaryStream = primarySampleStreams.get(adaptationSetIndex);
SampleStream stream = streams[i]; SampleStream stream = streams[i];
boolean mayRetainStream = primaryStream == null ? stream instanceof EmptySampleStream boolean mayRetainStream = primaryStream == null ? stream instanceof EmptySampleStream
: (stream instanceof EmbeddedSampleStream : (stream instanceof EmbeddedSampleStream
...@@ -172,7 +173,7 @@ import java.util.List; ...@@ -172,7 +173,7 @@ import java.util.List;
if (!mayRetainStream) { if (!mayRetainStream) {
releaseIfEmbeddedSampleStream(stream); releaseIfEmbeddedSampleStream(stream);
streams[i] = primaryStream == null ? new EmptySampleStream() streams[i] = primaryStream == null ? new EmptySampleStream()
: primaryStream.selectEmbeddedTrack(positionUs, embeddedTrackInfo.trackType); : primaryStream.selectEmbeddedTrack(positionUs, trackGroupInfo.trackType);
streamResetFlags[i] = true; streamResetFlags[i] = true;
} }
} }
...@@ -235,49 +236,114 @@ import java.util.List; ...@@ -235,49 +236,114 @@ import java.util.List;
// Internal methods. // Internal methods.
private static Pair<TrackGroupArray, EmbeddedTrackInfo[]> buildTrackGroups( private static Pair<TrackGroupArray, TrackGroupInfo[]> buildTrackGroups(
List<AdaptationSet> adaptationSets) { List<AdaptationSet> adaptationSets) {
int adaptationSetCount = adaptationSets.size(); int[][] groupedAdaptationSetIndices = getGroupedAdaptationSetIndices(adaptationSets);
int embeddedTrackCount = getEmbeddedTrackCount(adaptationSets);
TrackGroup[] trackGroupArray = new TrackGroup[adaptationSetCount + embeddedTrackCount];
EmbeddedTrackInfo[] embeddedTrackInfos = new EmbeddedTrackInfo[embeddedTrackCount];
int embeddedTrackIndex = 0; int primaryGroupCount = groupedAdaptationSetIndices.length;
for (int i = 0; i < adaptationSetCount; i++) { boolean[] primaryGroupHasEventMessageTrackFlags = new boolean[primaryGroupCount];
AdaptationSet adaptationSet = adaptationSets.get(i); boolean[] primaryGroupHasCea608TrackFlags = new boolean[primaryGroupCount];
List<Representation> representations = adaptationSet.representations; int totalGroupCount = primaryGroupCount;
for (int i = 0; i < primaryGroupCount; i++) {
if (hasEventMessageTrack(adaptationSets, groupedAdaptationSetIndices[i])) {
primaryGroupHasEventMessageTrackFlags[i] = true;
totalGroupCount++;
}
if (hasCea608Track(adaptationSets, groupedAdaptationSetIndices[i])) {
primaryGroupHasCea608TrackFlags[i] = true;
totalGroupCount++;
}
}
TrackGroup[] trackGroups = new TrackGroup[totalGroupCount];
TrackGroupInfo[] trackGroupInfos = new TrackGroupInfo[totalGroupCount];
int trackGroupCount = 0;
for (int i = 0; i < primaryGroupCount; i++) {
int[] adaptationSetIndices = groupedAdaptationSetIndices[i];
List<Representation> representations = new ArrayList<>();
for (int adaptationSetIndex : adaptationSetIndices) {
representations.addAll(adaptationSets.get(adaptationSetIndex).representations);
}
Format[] formats = new Format[representations.size()]; Format[] formats = new Format[representations.size()];
for (int j = 0; j < formats.length; j++) { for (int j = 0; j < formats.length; j++) {
formats[j] = representations.get(j).format; formats[j] = representations.get(j).format;
} }
trackGroupArray[i] = new TrackGroup(formats);
if (hasEventMessageTrack(adaptationSet)) { AdaptationSet firstAdaptationSet = adaptationSets.get(adaptationSetIndices[0]);
Format format = Format.createSampleFormat(adaptationSet.id + ":emsg", int primaryTrackGroupIndex = trackGroupCount;
boolean hasEventMessageTrack = primaryGroupHasEventMessageTrackFlags[i];
boolean hasCea608Track = primaryGroupHasEventMessageTrackFlags[i];
trackGroups[trackGroupCount] = new TrackGroup(formats);
trackGroupInfos[trackGroupCount++] = new TrackGroupInfo(firstAdaptationSet.type,
adaptationSetIndices, primaryTrackGroupIndex, true, hasEventMessageTrack, hasCea608Track);
if (hasEventMessageTrack) {
Format format = Format.createSampleFormat(firstAdaptationSet.id + ":emsg",
MimeTypes.APPLICATION_EMSG, null, Format.NO_VALUE, null); MimeTypes.APPLICATION_EMSG, null, Format.NO_VALUE, null);
trackGroupArray[adaptationSetCount + embeddedTrackIndex] = new TrackGroup(format); trackGroups[trackGroupCount] = new TrackGroup(format);
embeddedTrackInfos[embeddedTrackIndex++] = new EmbeddedTrackInfo(i, C.TRACK_TYPE_METADATA); trackGroupInfos[trackGroupCount++] = new TrackGroupInfo(C.TRACK_TYPE_METADATA,
adaptationSetIndices, primaryTrackGroupIndex, false, false, false);
} }
if (hasCea608Track(adaptationSet)) { if (hasCea608Track) {
Format format = Format.createTextSampleFormat(adaptationSet.id + ":cea608", Format format = Format.createTextSampleFormat(firstAdaptationSet.id + ":cea608",
MimeTypes.APPLICATION_CEA608, null, Format.NO_VALUE, 0, null, null); MimeTypes.APPLICATION_CEA608, null, Format.NO_VALUE, 0, null, null);
trackGroupArray[adaptationSetCount + embeddedTrackIndex] = new TrackGroup(format); trackGroups[trackGroupCount] = new TrackGroup(format);
embeddedTrackInfos[embeddedTrackIndex++] = new EmbeddedTrackInfo(i, C.TRACK_TYPE_TEXT); trackGroupInfos[trackGroupCount++] = new TrackGroupInfo(C.TRACK_TYPE_TEXT,
adaptationSetIndices, primaryTrackGroupIndex, false, false, false);
} }
} }
return Pair.create(new TrackGroupArray(trackGroupArray), embeddedTrackInfos); return Pair.create(new TrackGroupArray(trackGroups), trackGroupInfos);
} }
private ChunkSampleStream<DashChunkSource> buildSampleStream(int adaptationSetIndex, private static int[][] getGroupedAdaptationSetIndices(List<AdaptationSet> adaptationSets) {
int adaptationSetCount = adaptationSets.size();
SparseIntArray idToIndexMap = new SparseIntArray(adaptationSetCount);
for (int i = 0; i < adaptationSetCount; i++) {
idToIndexMap.put(adaptationSets.get(i).id, i);
}
int[][] groupedAdaptationSetIndices = new int[adaptationSetCount][];
boolean[] adaptationSetUsedFlags = new boolean[adaptationSetCount];
int groupCount = 0;
for (int i = 0; i < adaptationSetCount; i++) {
if (adaptationSetUsedFlags[i]) {
// This adaptation set has already been included in a group.
continue;
}
adaptationSetUsedFlags[i] = true;
Descriptor adaptationSetSwitchingProperty = findAdaptationSetSwitchingProperty(
adaptationSets.get(i).supplementalProperties);
if (adaptationSetSwitchingProperty == null) {
groupedAdaptationSetIndices[groupCount++] = new int[] {i};
} else {
String[] extraAdaptationSetIds = adaptationSetSwitchingProperty.value.split(",");
int[] adaptationSetIndices = new int[1 + extraAdaptationSetIds.length];
adaptationSetIndices[0] = i;
for (int j = 0; j < extraAdaptationSetIds.length; j++) {
int extraIndex = idToIndexMap.get(Integer.parseInt(extraAdaptationSetIds[j]));
adaptationSetUsedFlags[extraIndex] = true;
adaptationSetIndices[1 + j] = extraIndex;
}
groupedAdaptationSetIndices[groupCount++] = adaptationSetIndices;
}
}
return groupCount < adaptationSetCount
? Arrays.copyOf(groupedAdaptationSetIndices, groupCount) : groupedAdaptationSetIndices;
}
private ChunkSampleStream<DashChunkSource> buildSampleStream(TrackGroupInfo trackGroupInfo,
TrackSelection selection, long positionUs) { TrackSelection selection, long positionUs) {
AdaptationSet adaptationSet = adaptationSets.get(adaptationSetIndex);
int embeddedTrackCount = 0; int embeddedTrackCount = 0;
int[] embeddedTrackTypes = new int[2]; int[] embeddedTrackTypes = new int[2];
boolean enableEventMessageTrack = hasEventMessageTrack(adaptationSet); boolean enableEventMessageTrack = trackGroupInfo.hasEmbeddedEventMessageTrack;
if (enableEventMessageTrack) { if (enableEventMessageTrack) {
embeddedTrackTypes[embeddedTrackCount++] = C.TRACK_TYPE_METADATA; embeddedTrackTypes[embeddedTrackCount++] = C.TRACK_TYPE_METADATA;
} }
boolean enableCea608Track = hasCea608Track(adaptationSet); boolean enableCea608Track = trackGroupInfo.hasEmbeddedCea608Track;
if (enableCea608Track) { if (enableCea608Track) {
embeddedTrackTypes[embeddedTrackCount++] = C.TRACK_TYPE_TEXT; embeddedTrackTypes[embeddedTrackCount++] = C.TRACK_TYPE_TEXT;
} }
...@@ -285,47 +351,50 @@ import java.util.List; ...@@ -285,47 +351,50 @@ import java.util.List;
embeddedTrackTypes = Arrays.copyOf(embeddedTrackTypes, embeddedTrackCount); embeddedTrackTypes = Arrays.copyOf(embeddedTrackTypes, embeddedTrackCount);
} }
DashChunkSource chunkSource = chunkSourceFactory.createDashChunkSource( DashChunkSource chunkSource = chunkSourceFactory.createDashChunkSource(
manifestLoaderErrorThrower, manifest, periodIndex, adaptationSetIndex, selection, manifestLoaderErrorThrower, manifest, periodIndex, trackGroupInfo.adaptationSetIndices,
elapsedRealtimeOffset, enableEventMessageTrack, enableCea608Track); selection, trackGroupInfo.trackType, elapsedRealtimeOffset, enableEventMessageTrack,
ChunkSampleStream<DashChunkSource> stream = new ChunkSampleStream<>(adaptationSet.type, enableCea608Track);
ChunkSampleStream<DashChunkSource> stream = new ChunkSampleStream<>(trackGroupInfo.trackType,
embeddedTrackTypes, chunkSource, this, allocator, positionUs, minLoadableRetryCount, embeddedTrackTypes, chunkSource, this, allocator, positionUs, minLoadableRetryCount,
eventDispatcher); eventDispatcher);
return stream; return stream;
} }
private static int getEmbeddedTrackCount(List<AdaptationSet> adaptationSets) { private static Descriptor findAdaptationSetSwitchingProperty(List<Descriptor> descriptors) {
int embeddedTrackCount = 0; for (int i = 0; i < descriptors.size(); i++) {
for (int i = 0; i < adaptationSets.size(); i++) { Descriptor descriptor = descriptors.get(i);
AdaptationSet adaptationSet = adaptationSets.get(i); if ("urn:mpeg:dash:adaptation-set-switching:2016".equals(descriptor.schemeIdUri)) {
if (hasEventMessageTrack(adaptationSet)) { return descriptor;
embeddedTrackCount++;
}
if (hasCea608Track(adaptationSet)) {
embeddedTrackCount++;
} }
} }
return embeddedTrackCount; return null;
} }
private static boolean hasEventMessageTrack(AdaptationSet adaptationSet) { private static boolean hasEventMessageTrack(List<AdaptationSet> adaptationSets,
List<Representation> representations = adaptationSet.representations; int[] adaptationSetIndices) {
for (int i = 0; i < representations.size(); i++) { for (int i : adaptationSetIndices) {
Representation representation = representations.get(i); List<Representation> representations = adaptationSets.get(i).representations;
for (int j = 0; j < representations.size(); j++) {
Representation representation = representations.get(j);
if (!representation.inbandEventStreams.isEmpty()) { if (!representation.inbandEventStreams.isEmpty()) {
return true; return true;
} }
} }
}
return false; return false;
} }
private static boolean hasCea608Track(AdaptationSet adaptationSet) { private static boolean hasCea608Track(List<AdaptationSet> adaptationSets,
List<Descriptor> descriptors = adaptationSet.accessibilityDescriptors; int[] adaptationSetIndices) {
for (int i = 0; i < descriptors.size(); i++) { for (int i : adaptationSetIndices) {
Descriptor descriptor = descriptors.get(i); List<Descriptor> descriptors = adaptationSets.get(i).accessibilityDescriptors;
for (int j = 0; j < descriptors.size(); j++) {
Descriptor descriptor = descriptors.get(j);
if ("urn:scte:dash:cc:cea-608:2015".equals(descriptor.schemeIdUri)) { if ("urn:scte:dash:cc:cea-608:2015".equals(descriptor.schemeIdUri)) {
return true; return true;
} }
} }
}
return false; return false;
} }
...@@ -340,14 +409,24 @@ import java.util.List; ...@@ -340,14 +409,24 @@ import java.util.List;
} }
} }
private static final class EmbeddedTrackInfo { private static final class TrackGroupInfo {
public final int adaptationSetIndex; public final int[] adaptationSetIndices;
public final int trackType; public final int trackType;
public final boolean isPrimary;
public final int primaryTrackGroupIndex;
public final boolean hasEmbeddedEventMessageTrack;
public final boolean hasEmbeddedCea608Track;
public EmbeddedTrackInfo(int adaptationSetIndex, int trackType) { public TrackGroupInfo(int trackType, int[] adaptationSetIndices, int primaryTrackGroupIndex,
this.adaptationSetIndex = adaptationSetIndex; boolean isPrimary, boolean hasEmbeddedEventMessageTrack, boolean hasEmbeddedCea608Track) {
this.trackType = trackType; this.trackType = trackType;
this.adaptationSetIndices = adaptationSetIndices;
this.primaryTrackGroupIndex = primaryTrackGroupIndex;
this.isPrimary = isPrimary;
this.hasEmbeddedEventMessageTrack = hasEmbeddedEventMessageTrack;
this.hasEmbeddedCea608Track = hasEmbeddedCea608Track;
} }
} }
......
...@@ -46,6 +46,7 @@ import com.google.android.exoplayer2.upstream.LoaderErrorThrower; ...@@ -46,6 +46,7 @@ import com.google.android.exoplayer2.upstream.LoaderErrorThrower;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
...@@ -69,20 +70,21 @@ public class DefaultDashChunkSource implements DashChunkSource { ...@@ -69,20 +70,21 @@ public class DefaultDashChunkSource implements DashChunkSource {
@Override @Override
public DashChunkSource createDashChunkSource(LoaderErrorThrower manifestLoaderErrorThrower, public DashChunkSource createDashChunkSource(LoaderErrorThrower manifestLoaderErrorThrower,
DashManifest manifest, int periodIndex, int adaptationSetIndex, DashManifest manifest, int periodIndex, int[] adaptationSetIndices,
TrackSelection trackSelection, long elapsedRealtimeOffsetMs, TrackSelection trackSelection, int trackType, long elapsedRealtimeOffsetMs,
boolean enableEventMessageTrack, boolean enableCea608Track) { boolean enableEventMessageTrack, boolean enableCea608Track) {
DataSource dataSource = dataSourceFactory.createDataSource(); DataSource dataSource = dataSourceFactory.createDataSource();
return new DefaultDashChunkSource(manifestLoaderErrorThrower, manifest, periodIndex, return new DefaultDashChunkSource(manifestLoaderErrorThrower, manifest, periodIndex,
adaptationSetIndex, trackSelection, dataSource, elapsedRealtimeOffsetMs, adaptationSetIndices, trackSelection, trackType, dataSource, elapsedRealtimeOffsetMs,
maxSegmentsPerLoad, enableEventMessageTrack, enableCea608Track); maxSegmentsPerLoad, enableEventMessageTrack, enableCea608Track);
} }
} }
private final LoaderErrorThrower manifestLoaderErrorThrower; private final LoaderErrorThrower manifestLoaderErrorThrower;
private final int adaptationSetIndex; private final int[] adaptationSetIndices;
private final TrackSelection trackSelection; private final TrackSelection trackSelection;
private final int trackType;
private final RepresentationHolder[] representationHolders; private final RepresentationHolder[] representationHolders;
private final DataSource dataSource; private final DataSource dataSource;
private final long elapsedRealtimeOffsetMs; private final long elapsedRealtimeOffsetMs;
...@@ -98,8 +100,9 @@ public class DefaultDashChunkSource implements DashChunkSource { ...@@ -98,8 +100,9 @@ public class DefaultDashChunkSource implements DashChunkSource {
* @param manifestLoaderErrorThrower Throws errors affecting loading of manifests. * @param manifestLoaderErrorThrower Throws errors affecting loading of manifests.
* @param manifest The initial manifest. * @param manifest The initial manifest.
* @param periodIndex The index of the period in the manifest. * @param periodIndex The index of the period in the manifest.
* @param adaptationSetIndex The index of the adaptation set in the period. * @param adaptationSetIndices The indices of the adaptation sets in the period.
* @param trackSelection The track selection. * @param trackSelection The track selection.
* @param trackType The type of the tracks in the selection.
* @param dataSource A {@link DataSource} suitable for loading the media data. * @param dataSource A {@link DataSource} suitable for loading the media data.
* @param elapsedRealtimeOffsetMs If known, an estimate of the instantaneous difference between * @param elapsedRealtimeOffsetMs If known, an estimate of the instantaneous difference between
* server-side unix time and {@link SystemClock#elapsedRealtime()} in milliseconds, specified * server-side unix time and {@link SystemClock#elapsedRealtime()} in milliseconds, specified
...@@ -112,26 +115,27 @@ public class DefaultDashChunkSource implements DashChunkSource { ...@@ -112,26 +115,27 @@ public class DefaultDashChunkSource implements DashChunkSource {
* @param enableCea608Track Whether the chunks generated by the source may output a CEA-608 track. * @param enableCea608Track Whether the chunks generated by the source may output a CEA-608 track.
*/ */
public DefaultDashChunkSource(LoaderErrorThrower manifestLoaderErrorThrower, public DefaultDashChunkSource(LoaderErrorThrower manifestLoaderErrorThrower,
DashManifest manifest, int periodIndex, int adaptationSetIndex, TrackSelection trackSelection, DashManifest manifest, int periodIndex, int[] adaptationSetIndices,
DataSource dataSource, long elapsedRealtimeOffsetMs, int maxSegmentsPerLoad, TrackSelection trackSelection, int trackType, DataSource dataSource,
boolean enableEventMessageTrack, boolean enableCea608Track) { long elapsedRealtimeOffsetMs, int maxSegmentsPerLoad, boolean enableEventMessageTrack,
boolean enableCea608Track) {
this.manifestLoaderErrorThrower = manifestLoaderErrorThrower; this.manifestLoaderErrorThrower = manifestLoaderErrorThrower;
this.manifest = manifest; this.manifest = manifest;
this.adaptationSetIndex = adaptationSetIndex; this.adaptationSetIndices = adaptationSetIndices;
this.trackSelection = trackSelection; this.trackSelection = trackSelection;
this.trackType = trackType;
this.dataSource = dataSource; this.dataSource = dataSource;
this.periodIndex = periodIndex; this.periodIndex = periodIndex;
this.elapsedRealtimeOffsetMs = elapsedRealtimeOffsetMs; this.elapsedRealtimeOffsetMs = elapsedRealtimeOffsetMs;
this.maxSegmentsPerLoad = maxSegmentsPerLoad; this.maxSegmentsPerLoad = maxSegmentsPerLoad;
long periodDurationUs = manifest.getPeriodDurationUs(periodIndex); long periodDurationUs = manifest.getPeriodDurationUs(periodIndex);
AdaptationSet adaptationSet = getAdaptationSet(); List<Representation> representations = getRepresentations();
List<Representation> representations = adaptationSet.representations;
representationHolders = new RepresentationHolder[trackSelection.length()]; representationHolders = new RepresentationHolder[trackSelection.length()];
for (int i = 0; i < representationHolders.length; i++) { for (int i = 0; i < representationHolders.length; i++) {
Representation representation = representations.get(trackSelection.getIndexInTrackGroup(i)); Representation representation = representations.get(trackSelection.getIndexInTrackGroup(i));
representationHolders[i] = new RepresentationHolder(periodDurationUs, representation, representationHolders[i] = new RepresentationHolder(periodDurationUs, representation,
enableEventMessageTrack, enableCea608Track, adaptationSet.type); enableEventMessageTrack, enableCea608Track);
} }
} }
...@@ -141,7 +145,7 @@ public class DefaultDashChunkSource implements DashChunkSource { ...@@ -141,7 +145,7 @@ public class DefaultDashChunkSource implements DashChunkSource {
manifest = newManifest; manifest = newManifest;
periodIndex = newPeriodIndex; periodIndex = newPeriodIndex;
long periodDurationUs = manifest.getPeriodDurationUs(periodIndex); long periodDurationUs = manifest.getPeriodDurationUs(periodIndex);
List<Representation> representations = getAdaptationSet().representations; List<Representation> representations = getRepresentations();
for (int i = 0; i < representationHolders.length; i++) { for (int i = 0; i < representationHolders.length; i++) {
Representation representation = representations.get(trackSelection.getIndexInTrackGroup(i)); Representation representation = representations.get(trackSelection.getIndexInTrackGroup(i));
representationHolders[i].updateRepresentation(periodDurationUs, representation); representationHolders[i].updateRepresentation(periodDurationUs, representation);
...@@ -248,9 +252,9 @@ public class DefaultDashChunkSource implements DashChunkSource { ...@@ -248,9 +252,9 @@ public class DefaultDashChunkSource implements DashChunkSource {
} }
int maxSegmentCount = Math.min(maxSegmentsPerLoad, lastAvailableSegmentNum - segmentNum + 1); int maxSegmentCount = Math.min(maxSegmentsPerLoad, lastAvailableSegmentNum - segmentNum + 1);
out.chunk = newMediaChunk(representationHolder, dataSource, trackSelection.getSelectedFormat(), out.chunk = newMediaChunk(representationHolder, dataSource, trackType,
trackSelection.getSelectionReason(), trackSelection.getSelectionData(), segmentNum, trackSelection.getSelectedFormat(), trackSelection.getSelectionReason(),
maxSegmentCount); trackSelection.getSelectionData(), segmentNum, maxSegmentCount);
} }
@Override @Override
...@@ -298,8 +302,13 @@ public class DefaultDashChunkSource implements DashChunkSource { ...@@ -298,8 +302,13 @@ public class DefaultDashChunkSource implements DashChunkSource {
// Private methods. // Private methods.
private AdaptationSet getAdaptationSet() { private ArrayList<Representation> getRepresentations() {
return manifest.getPeriod(periodIndex).adaptationSets.get(adaptationSetIndex); List<AdaptationSet> manifestAdapationSets = manifest.getPeriod(periodIndex).adaptationSets;
ArrayList<Representation> representations = new ArrayList<>();
for (int adaptationSetIndex : adaptationSetIndices) {
representations.addAll(manifestAdapationSets.get(adaptationSetIndex).representations);
}
return representations;
} }
private long getNowUnixTimeUs() { private long getNowUnixTimeUs() {
...@@ -332,7 +341,7 @@ public class DefaultDashChunkSource implements DashChunkSource { ...@@ -332,7 +341,7 @@ public class DefaultDashChunkSource implements DashChunkSource {
} }
private static Chunk newMediaChunk(RepresentationHolder representationHolder, private static Chunk newMediaChunk(RepresentationHolder representationHolder,
DataSource dataSource, Format trackFormat, int trackSelectionReason, DataSource dataSource, int trackType, Format trackFormat, int trackSelectionReason,
Object trackSelectionData, int firstSegmentNum, int maxSegmentCount) { Object trackSelectionData, int firstSegmentNum, int maxSegmentCount) {
Representation representation = representationHolder.representation; Representation representation = representationHolder.representation;
long startTimeUs = representationHolder.getSegmentStartTimeUs(firstSegmentNum); long startTimeUs = representationHolder.getSegmentStartTimeUs(firstSegmentNum);
...@@ -343,8 +352,7 @@ public class DefaultDashChunkSource implements DashChunkSource { ...@@ -343,8 +352,7 @@ public class DefaultDashChunkSource implements DashChunkSource {
DataSpec dataSpec = new DataSpec(segmentUri.resolveUri(baseUrl), DataSpec dataSpec = new DataSpec(segmentUri.resolveUri(baseUrl),
segmentUri.start, segmentUri.length, representation.getCacheKey()); segmentUri.start, segmentUri.length, representation.getCacheKey());
return new SingleSampleMediaChunk(dataSource, dataSpec, trackFormat, trackSelectionReason, return new SingleSampleMediaChunk(dataSource, dataSpec, trackFormat, trackSelectionReason,
trackSelectionData, startTimeUs, endTimeUs, firstSegmentNum, trackSelectionData, startTimeUs, endTimeUs, firstSegmentNum, trackType, trackFormat);
representationHolder.trackType, trackFormat);
} else { } else {
int segmentCount = 1; int segmentCount = 1;
for (int i = 1; i < maxSegmentCount; i++) { for (int i = 1; i < maxSegmentCount; i++) {
...@@ -371,7 +379,6 @@ public class DefaultDashChunkSource implements DashChunkSource { ...@@ -371,7 +379,6 @@ public class DefaultDashChunkSource implements DashChunkSource {
protected static final class RepresentationHolder { protected static final class RepresentationHolder {
public final int trackType;
public final ChunkExtractorWrapper extractorWrapper; public final ChunkExtractorWrapper extractorWrapper;
public Representation representation; public Representation representation;
...@@ -381,10 +388,9 @@ public class DefaultDashChunkSource implements DashChunkSource { ...@@ -381,10 +388,9 @@ public class DefaultDashChunkSource implements DashChunkSource {
private int segmentNumShift; private int segmentNumShift;
public RepresentationHolder(long periodDurationUs, Representation representation, public RepresentationHolder(long periodDurationUs, Representation representation,
boolean enableEventMessageTrack, boolean enableCea608Track, int trackType) { boolean enableEventMessageTrack, boolean enableCea608Track) {
this.periodDurationUs = periodDurationUs; this.periodDurationUs = periodDurationUs;
this.representation = representation; this.representation = representation;
this.trackType = trackType;
String containerMimeType = representation.format.containerMimeType; String containerMimeType = representation.format.containerMimeType;
if (mimeTypeIsRawText(containerMimeType)) { if (mimeTypeIsRawText(containerMimeType)) {
extractorWrapper = null; extractorWrapper = null;
......
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