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