public DashMediaPeriod(int id, DashManifest manifest, int periodIndex, DashChunkSource.Factory chunkSourceFactory, int minLoadableRetryCount, EventDispatcher eventDispatcher, long elapsedRealtimeOffset, LoaderErrorThrower manifestLoaderErrorThrower, Allocator allocator) { this.id = id; this.manifest = manifest; this.periodIndex = periodIndex; this.chunkSourceFactory = chunkSourceFactory; this.minLoadableRetryCount = minLoadableRetryCount; this.eventDispatcher = eventDispatcher; this.elapsedRealtimeOffset = elapsedRealtimeOffset; this.manifestLoaderErrorThrower = manifestLoaderErrorThrower; this.allocator = allocator; sampleStreams = newSampleStreamArray(0); sequenceableLoader = new CompositeSequenceableLoader(sampleStreams); adaptationSets = manifest.getPeriod(periodIndex).adaptationSets; Pair<TrackGroupArray, EmbeddedTrackInfo[]> result = buildTrackGroups(adaptationSets); trackGroups = result.first; embeddedTrackInfos = result.second; }
public SsMediaPeriod(SsManifest manifest, SsChunkSource.Factory chunkSourceFactory, int minLoadableRetryCount, EventDispatcher eventDispatcher, LoaderErrorThrower manifestLoaderErrorThrower, Allocator allocator) { this.chunkSourceFactory = chunkSourceFactory; this.manifestLoaderErrorThrower = manifestLoaderErrorThrower; this.minLoadableRetryCount = minLoadableRetryCount; this.eventDispatcher = eventDispatcher; this.allocator = allocator; trackGroups = buildTrackGroups(manifest); ProtectionElement protectionElement = manifest.protectionElement; if (protectionElement != null) { byte[] keyId = getProtectionElementKeyId(protectionElement.data); trackEncryptionBoxes = new TrackEncryptionBox[] { new TrackEncryptionBox(true, INITIALIZATION_VECTOR_SIZE, keyId)}; } else { trackEncryptionBoxes = null; } this.manifest = manifest; sampleStreams = newSampleStreamArray(0); sequenceableLoader = new CompositeSequenceableLoader(sampleStreams); }
public DashMediaPeriod(int id, DashManifest manifest, int index, DashChunkSource.Factory chunkSourceFactory, int minLoadableRetryCount, EventDispatcher eventDispatcher, long elapsedRealtimeOffset, LoaderErrorThrower manifestLoaderErrorThrower, Allocator allocator) { this.id = id; this.manifest = manifest; this.index = index; this.chunkSourceFactory = chunkSourceFactory; this.minLoadableRetryCount = minLoadableRetryCount; this.eventDispatcher = eventDispatcher; this.elapsedRealtimeOffset = elapsedRealtimeOffset; this.manifestLoaderErrorThrower = manifestLoaderErrorThrower; this.allocator = allocator; sampleStreams = newSampleStreamArray(0); sequenceableLoader = new CompositeSequenceableLoader(sampleStreams); period = manifest.getPeriod(index); trackGroups = buildTrackGroups(period); }
@Override @SuppressWarnings("unchecked") public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags, SampleStream[] streams, boolean[] streamResetFlags, long positionUs) { long returnPositionUs = super.selectTracks(selections, mayRetainStreamFlags, streams, streamResetFlags, positionUs); List<ChunkSampleStream<FakeChunkSource>> validStreams = new ArrayList<>(); for (SampleStream stream : streams) { if (stream != null) { validStreams.add((ChunkSampleStream<FakeChunkSource>) stream); } } this.sampleStreams = validStreams.toArray(new ChunkSampleStream[validStreams.size()]); this.sequenceableLoader = new CompositeSequenceableLoader(sampleStreams); return returnPositionUs; }
public DashMediaPeriod(int id, DashManifest manifest, int periodIndex, DashChunkSource.Factory chunkSourceFactory, int minLoadableRetryCount, EventDispatcher eventDispatcher, long elapsedRealtimeOffset, LoaderErrorThrower manifestLoaderErrorThrower, Allocator allocator) { this.id = id; this.manifest = manifest; this.periodIndex = periodIndex; this.chunkSourceFactory = chunkSourceFactory; this.minLoadableRetryCount = minLoadableRetryCount; this.eventDispatcher = eventDispatcher; this.elapsedRealtimeOffset = elapsedRealtimeOffset; this.manifestLoaderErrorThrower = manifestLoaderErrorThrower; this.allocator = allocator; sampleStreams = newSampleStreamArray(0); sequenceableLoader = new CompositeSequenceableLoader(sampleStreams); Pair<TrackGroupArray, TrackGroupInfo[]> result = buildTrackGroups(manifest.getPeriod(periodIndex).adaptationSets); trackGroups = result.first; trackGroupInfos = result.second; }
public SsMediaPeriod(SsManifest manifest, SsChunkSource.Factory chunkSourceFactory, int minLoadableRetryCount, EventDispatcher eventDispatcher, LoaderErrorThrower manifestLoaderErrorThrower, Allocator allocator) { this.chunkSourceFactory = chunkSourceFactory; this.manifestLoaderErrorThrower = manifestLoaderErrorThrower; this.minLoadableRetryCount = minLoadableRetryCount; this.eventDispatcher = eventDispatcher; this.allocator = allocator; trackGroups = buildTrackGroups(manifest); ProtectionElement protectionElement = manifest.protectionElement; if (protectionElement != null) { byte[] keyId = getProtectionElementKeyId(protectionElement.data); // We assume pattern encryption does not apply. trackEncryptionBoxes = new TrackEncryptionBox[] { new TrackEncryptionBox(true, null, INITIALIZATION_VECTOR_SIZE, keyId, 0, 0, null)}; } else { trackEncryptionBoxes = null; } this.manifest = manifest; sampleStreams = newSampleStreamArray(0); sequenceableLoader = new CompositeSequenceableLoader(sampleStreams); }
@Override public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags, SampleStream[] streams, boolean[] streamResetFlags, long positionUs) { // Map each selection and stream onto a child period index. int[] streamChildIndices = new int[selections.length]; int[] selectionChildIndices = new int[selections.length]; for (int i = 0; i < selections.length; i++) { streamChildIndices[i] = streams[i] == null ? C.INDEX_UNSET : streamWrapperIndices.get(streams[i]); selectionChildIndices[i] = C.INDEX_UNSET; if (selections[i] != null) { TrackGroup trackGroup = selections[i].getTrackGroup(); for (int j = 0; j < sampleStreamWrappers.length; j++) { if (sampleStreamWrappers[j].getTrackGroups().indexOf(trackGroup) != C.INDEX_UNSET) { selectionChildIndices[i] = j; break; } } } } boolean selectedNewTracks = false; streamWrapperIndices.clear(); // Select tracks for each child, copying the resulting streams back into a new streams array. SampleStream[] newStreams = new SampleStream[selections.length]; SampleStream[] childStreams = new SampleStream[selections.length]; TrackSelection[] childSelections = new TrackSelection[selections.length]; ArrayList<HlsSampleStreamWrapper> enabledSampleStreamWrapperList = new ArrayList<>( sampleStreamWrappers.length); for (int i = 0; i < sampleStreamWrappers.length; i++) { for (int j = 0; j < selections.length; j++) { childStreams[j] = streamChildIndices[j] == i ? streams[j] : null; childSelections[j] = selectionChildIndices[j] == i ? selections[j] : null; } selectedNewTracks |= sampleStreamWrappers[i].selectTracks(childSelections, mayRetainStreamFlags, childStreams, streamResetFlags, !seenFirstTrackSelection); boolean wrapperEnabled = false; for (int j = 0; j < selections.length; j++) { if (selectionChildIndices[j] == i) { // Assert that the child provided a stream for the selection. Assertions.checkState(childStreams[j] != null); newStreams[j] = childStreams[j]; wrapperEnabled = true; streamWrapperIndices.put(childStreams[j], i); } else if (streamChildIndices[j] == i) { // Assert that the child cleared any previous stream. Assertions.checkState(childStreams[j] == null); } } if (wrapperEnabled) { enabledSampleStreamWrapperList.add(sampleStreamWrappers[i]); } } // Copy the new streams back into the streams array. System.arraycopy(newStreams, 0, streams, 0, newStreams.length); // Update the local state. enabledSampleStreamWrappers = new HlsSampleStreamWrapper[enabledSampleStreamWrapperList.size()]; enabledSampleStreamWrapperList.toArray(enabledSampleStreamWrappers); sequenceableLoader = new CompositeSequenceableLoader(enabledSampleStreamWrappers); if (seenFirstTrackSelection && selectedNewTracks) { seekToUs(positionUs); // We'll need to reset renderers consuming from all streams due to the seek. for (int i = 0; i < selections.length; i++) { if (streams[i] != null) { streamResetFlags[i] = true; } } } seenFirstTrackSelection = true; return positionUs; }
@Override public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags, SampleStream[] streams, boolean[] streamResetFlags, long positionUs) { // Map each selection and stream onto a child period index. int[] streamChildIndices = new int[selections.length]; int[] selectionChildIndices = new int[selections.length]; for (int i = 0; i < selections.length; i++) { streamChildIndices[i] = streams[i] == null ? C.INDEX_UNSET : streamWrapperIndices.get(streams[i]); selectionChildIndices[i] = C.INDEX_UNSET; if (selections[i] != null) { TrackGroup trackGroup = selections[i].getTrackGroup(); for (int j = 0; j < sampleStreamWrappers.length; j++) { if (sampleStreamWrappers[j].getTrackGroups().indexOf(trackGroup) != C.INDEX_UNSET) { selectionChildIndices[i] = j; break; } } } } boolean forceReset = false; streamWrapperIndices.clear(); // Select tracks for each child, copying the resulting streams back into a new streams array. SampleStream[] newStreams = new SampleStream[selections.length]; SampleStream[] childStreams = new SampleStream[selections.length]; TrackSelection[] childSelections = new TrackSelection[selections.length]; int newEnabledSampleStreamWrapperCount = 0; HlsSampleStreamWrapper[] newEnabledSampleStreamWrappers = new HlsSampleStreamWrapper[sampleStreamWrappers.length]; for (int i = 0; i < sampleStreamWrappers.length; i++) { for (int j = 0; j < selections.length; j++) { childStreams[j] = streamChildIndices[j] == i ? streams[j] : null; childSelections[j] = selectionChildIndices[j] == i ? selections[j] : null; } HlsSampleStreamWrapper sampleStreamWrapper = sampleStreamWrappers[i]; boolean wasReset = sampleStreamWrapper.selectTracks(childSelections, mayRetainStreamFlags, childStreams, streamResetFlags, positionUs, forceReset); boolean wrapperEnabled = false; for (int j = 0; j < selections.length; j++) { if (selectionChildIndices[j] == i) { // Assert that the child provided a stream for the selection. Assertions.checkState(childStreams[j] != null); newStreams[j] = childStreams[j]; wrapperEnabled = true; streamWrapperIndices.put(childStreams[j], i); } else if (streamChildIndices[j] == i) { // Assert that the child cleared any previous stream. Assertions.checkState(childStreams[j] == null); } } if (wrapperEnabled) { newEnabledSampleStreamWrappers[newEnabledSampleStreamWrapperCount] = sampleStreamWrapper; if (newEnabledSampleStreamWrapperCount++ == 0) { // The first enabled wrapper is responsible for initializing timestamp adjusters. This // way, if enabled, variants are responsible. Else audio renditions. Else text renditions. sampleStreamWrapper.setIsTimestampMaster(true); if (wasReset || enabledSampleStreamWrappers.length == 0 || sampleStreamWrapper != enabledSampleStreamWrappers[0]) { // The wrapper responsible for initializing the timestamp adjusters was reset or // changed. We need to reset the timestamp adjuster provider and all other wrappers. timestampAdjusterProvider.reset(); forceReset = true; } } else { sampleStreamWrapper.setIsTimestampMaster(false); } } } // Copy the new streams back into the streams array. System.arraycopy(newStreams, 0, streams, 0, newStreams.length); // Update the local state. enabledSampleStreamWrappers = Arrays.copyOf(newEnabledSampleStreamWrappers, newEnabledSampleStreamWrapperCount); sequenceableLoader = new CompositeSequenceableLoader(enabledSampleStreamWrappers); return positionUs; }