mirror of
https://github.com/androidx/media.git
synced 2025-05-14 11:09:53 +08:00
Migrate HLS over to new SampleQueue methods
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=161391296
This commit is contained in:
parent
5ebbb6ef45
commit
06b3b3ca8d
@ -219,6 +219,10 @@ import java.util.Arrays;
|
||||
if (!seekRequired) {
|
||||
SampleQueue sampleQueue = sampleQueues[track];
|
||||
sampleQueue.rewind();
|
||||
// A seek can be avoided if we're able to advance to the current playback position in the
|
||||
// sample queue, or if we haven't read anything from the queue since the previous seek
|
||||
// (this case is common for sparse tracks such as metadata tracks). In all other cases a
|
||||
// seek is required.
|
||||
seekRequired = !sampleQueue.advanceTo(positionUs, true, true)
|
||||
&& sampleQueue.getReadIndex() != 0;
|
||||
}
|
||||
|
@ -83,11 +83,6 @@ import com.google.android.exoplayer2.util.Util;
|
||||
relativeStartIndex = 0;
|
||||
readPosition = 0;
|
||||
upstreamKeyframeRequired = true;
|
||||
}
|
||||
|
||||
// Called by the consuming thread, but only when there is no loading thread.
|
||||
|
||||
public void resetLargestParsedTimestamps() {
|
||||
largestDiscardedTimestampUs = Long.MIN_VALUE;
|
||||
largestQueuedTimestampUs = Long.MIN_VALUE;
|
||||
}
|
||||
|
@ -29,7 +29,6 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* A queue of media samples.
|
||||
@ -52,16 +51,11 @@ public final class SampleQueue implements TrackOutput {
|
||||
|
||||
private static final int INITIAL_SCRATCH_SIZE = 32;
|
||||
|
||||
private static final int STATE_ENABLED = 0;
|
||||
private static final int STATE_ENABLED_WRITING = 1;
|
||||
private static final int STATE_DISABLED = 2;
|
||||
|
||||
private final Allocator allocator;
|
||||
private final int allocationLength;
|
||||
private final SampleMetadataQueue metadataQueue;
|
||||
private final SampleExtrasHolder extrasHolder;
|
||||
private final ParsableByteArray scratch;
|
||||
private final AtomicInteger state;
|
||||
|
||||
// References into the linked list of allocations.
|
||||
private AllocationNode firstAllocationNode;
|
||||
@ -88,7 +82,6 @@ public final class SampleQueue implements TrackOutput {
|
||||
metadataQueue = new SampleMetadataQueue();
|
||||
extrasHolder = new SampleExtrasHolder();
|
||||
scratch = new ParsableByteArray(INITIAL_SCRATCH_SIZE);
|
||||
state = new AtomicInteger();
|
||||
firstAllocationNode = new AllocationNode(0, allocationLength);
|
||||
readAllocationNode = firstAllocationNode;
|
||||
writeAllocationNode = firstAllocationNode;
|
||||
@ -100,20 +93,13 @@ public final class SampleQueue implements TrackOutput {
|
||||
* Resets the output.
|
||||
*/
|
||||
public void reset() {
|
||||
reset(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #reset()}. Don't disable sample queues.
|
||||
*/
|
||||
@Deprecated
|
||||
public void reset(boolean enable) {
|
||||
int previousState = state.getAndSet(enable ? STATE_ENABLED : STATE_DISABLED);
|
||||
clearSampleData();
|
||||
metadataQueue.resetLargestParsedTimestamps();
|
||||
if (previousState == STATE_DISABLED) {
|
||||
downstreamFormat = null;
|
||||
}
|
||||
metadataQueue.clearSampleData();
|
||||
clearAllocationNodes(firstAllocationNode);
|
||||
firstAllocationNode = new AllocationNode(0, allocationLength);
|
||||
readAllocationNode = firstAllocationNode;
|
||||
writeAllocationNode = firstAllocationNode;
|
||||
totalBytesWritten = 0;
|
||||
allocator.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -174,16 +160,6 @@ public final class SampleQueue implements TrackOutput {
|
||||
|
||||
// Called by the consuming thread.
|
||||
|
||||
/**
|
||||
* @deprecated Don't disable sample queues.
|
||||
*/
|
||||
@Deprecated
|
||||
public void disable() {
|
||||
if (state.getAndSet(STATE_DISABLED) == STATE_ENABLED) {
|
||||
clearSampleData();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether a sample is available to be read.
|
||||
*/
|
||||
@ -265,15 +241,6 @@ public final class SampleQueue implements TrackOutput {
|
||||
discardDownstreamTo(metadataQueue.discardToEnd());
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #advanceToEnd()} followed by {@link #discardToRead()}.
|
||||
*/
|
||||
@Deprecated
|
||||
public void skipAll() {
|
||||
advanceToEnd();
|
||||
discardToRead();
|
||||
}
|
||||
|
||||
/**
|
||||
* Advances the read position to the end of the queue.
|
||||
*/
|
||||
@ -281,17 +248,6 @@ public final class SampleQueue implements TrackOutput {
|
||||
metadataQueue.advanceToEnd();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #advanceTo(long, boolean, boolean)} followed by
|
||||
* {@link #discardToRead()}.
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean skipToKeyframeBefore(long timeUs, boolean allowTimeBeyondBuffer) {
|
||||
boolean success = advanceTo(timeUs, true, allowTimeBeyondBuffer);
|
||||
discardToRead();
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to advance the read position to the sample before or at the specified time.
|
||||
*
|
||||
@ -307,19 +263,6 @@ public final class SampleQueue implements TrackOutput {
|
||||
return metadataQueue.advanceTo(timeUs, toKeyframe, allowTimeBeyondBuffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #read(FormatHolder, DecoderInputBuffer, boolean, boolean, long)}
|
||||
* followed by {@link #discardToRead()}.
|
||||
*/
|
||||
@Deprecated
|
||||
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer, boolean formatRequired,
|
||||
boolean loadingFinished, long decodeOnlyUntilUs) {
|
||||
int result = read(formatHolder, buffer, formatRequired, loadingFinished,
|
||||
decodeOnlyUntilUs);
|
||||
discardToRead();
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to read from the queue.
|
||||
*
|
||||
@ -558,39 +501,21 @@ public final class SampleQueue implements TrackOutput {
|
||||
@Override
|
||||
public int sampleData(ExtractorInput input, int length, boolean allowEndOfInput)
|
||||
throws IOException, InterruptedException {
|
||||
if (!startWriteOperation()) {
|
||||
int bytesSkipped = input.skip(length);
|
||||
if (bytesSkipped == C.RESULT_END_OF_INPUT) {
|
||||
if (allowEndOfInput) {
|
||||
return C.RESULT_END_OF_INPUT;
|
||||
}
|
||||
throw new EOFException();
|
||||
length = preAppend(length);
|
||||
int bytesAppended = input.read(writeAllocationNode.allocation.data,
|
||||
writeAllocationNode.translateOffset(totalBytesWritten), length);
|
||||
if (bytesAppended == C.RESULT_END_OF_INPUT) {
|
||||
if (allowEndOfInput) {
|
||||
return C.RESULT_END_OF_INPUT;
|
||||
}
|
||||
return bytesSkipped;
|
||||
}
|
||||
try {
|
||||
length = preAppend(length);
|
||||
int bytesAppended = input.read(writeAllocationNode.allocation.data,
|
||||
writeAllocationNode.translateOffset(totalBytesWritten), length);
|
||||
if (bytesAppended == C.RESULT_END_OF_INPUT) {
|
||||
if (allowEndOfInput) {
|
||||
return C.RESULT_END_OF_INPUT;
|
||||
}
|
||||
throw new EOFException();
|
||||
}
|
||||
postAppend(bytesAppended);
|
||||
return bytesAppended;
|
||||
} finally {
|
||||
endWriteOperation();
|
||||
throw new EOFException();
|
||||
}
|
||||
postAppend(bytesAppended);
|
||||
return bytesAppended;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sampleData(ParsableByteArray buffer, int length) {
|
||||
if (!startWriteOperation()) {
|
||||
buffer.skipBytes(length);
|
||||
return;
|
||||
}
|
||||
while (length > 0) {
|
||||
int bytesAppended = preAppend(length);
|
||||
buffer.readBytes(writeAllocationNode.allocation.data,
|
||||
@ -598,7 +523,6 @@ public final class SampleQueue implements TrackOutput {
|
||||
length -= bytesAppended;
|
||||
postAppend(bytesAppended);
|
||||
}
|
||||
endWriteOperation();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -607,47 +531,19 @@ public final class SampleQueue implements TrackOutput {
|
||||
if (pendingFormatAdjustment) {
|
||||
format(lastUnadjustedFormat);
|
||||
}
|
||||
if (!startWriteOperation()) {
|
||||
metadataQueue.commitSampleTimestamp(timeUs);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (pendingSplice) {
|
||||
if ((flags & C.BUFFER_FLAG_KEY_FRAME) == 0 || !metadataQueue.attemptSplice(timeUs)) {
|
||||
return;
|
||||
}
|
||||
pendingSplice = false;
|
||||
if (pendingSplice) {
|
||||
if ((flags & C.BUFFER_FLAG_KEY_FRAME) == 0 || !metadataQueue.attemptSplice(timeUs)) {
|
||||
return;
|
||||
}
|
||||
timeUs += sampleOffsetUs;
|
||||
long absoluteOffset = totalBytesWritten - size - offset;
|
||||
metadataQueue.commitSample(timeUs, flags, absoluteOffset, size, cryptoData);
|
||||
} finally {
|
||||
endWriteOperation();
|
||||
pendingSplice = false;
|
||||
}
|
||||
timeUs += sampleOffsetUs;
|
||||
long absoluteOffset = totalBytesWritten - size - offset;
|
||||
metadataQueue.commitSample(timeUs, flags, absoluteOffset, size, cryptoData);
|
||||
}
|
||||
|
||||
// Private methods.
|
||||
|
||||
private boolean startWriteOperation() {
|
||||
return state.compareAndSet(STATE_ENABLED, STATE_ENABLED_WRITING);
|
||||
}
|
||||
|
||||
private void endWriteOperation() {
|
||||
if (!state.compareAndSet(STATE_ENABLED_WRITING, STATE_ENABLED)) {
|
||||
clearSampleData();
|
||||
}
|
||||
}
|
||||
|
||||
private void clearSampleData() {
|
||||
metadataQueue.clearSampleData();
|
||||
clearAllocationNodes(firstAllocationNode);
|
||||
firstAllocationNode = new AllocationNode(0, allocationLength);
|
||||
readAllocationNode = firstAllocationNode;
|
||||
writeAllocationNode = firstAllocationNode;
|
||||
totalBytesWritten = 0;
|
||||
allocator.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears allocation nodes starting from {@code fromNode}.
|
||||
*
|
||||
|
@ -53,6 +53,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
|
||||
private final Handler continueLoadingHandler;
|
||||
|
||||
private Callback callback;
|
||||
private long preparePositionUs;
|
||||
private int pendingPrepareCount;
|
||||
private boolean seenFirstTrackSelection;
|
||||
private TrackGroupArray trackGroups;
|
||||
@ -84,8 +85,9 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
|
||||
|
||||
@Override
|
||||
public void prepare(Callback callback, long positionUs) {
|
||||
playlistTracker.addListener(this);
|
||||
this.callback = callback;
|
||||
playlistTracker.addListener(this);
|
||||
preparePositionUs = positionUs;
|
||||
buildAndPrepareSampleStreamWrappers(positionUs);
|
||||
}
|
||||
|
||||
@ -123,7 +125,9 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
|
||||
}
|
||||
}
|
||||
}
|
||||
boolean selectedNewTracks = false;
|
||||
// We'll always need to seek if this is a first selection to a position other than the prepare
|
||||
// position.
|
||||
boolean seekRequired = !seenFirstTrackSelection && positionUs != preparePositionUs;
|
||||
streamWrapperIndices.clear();
|
||||
// Select tracks for each child, copying the resulting streams back into a new streams array.
|
||||
SampleStream[] newStreams = new SampleStream[selections.length];
|
||||
@ -136,8 +140,8 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
|
||||
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);
|
||||
seekRequired |= sampleStreamWrappers[i].selectTracks(childSelections, mayRetainStreamFlags,
|
||||
childStreams, streamResetFlags, positionUs, seenFirstTrackSelection, seekRequired);
|
||||
boolean wrapperEnabled = false;
|
||||
for (int j = 0; j < selections.length; j++) {
|
||||
if (selectionChildIndices[j] == i) {
|
||||
@ -173,7 +177,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
|
||||
}
|
||||
|
||||
sequenceableLoader = new CompositeSequenceableLoader(enabledSampleStreamWrappers);
|
||||
if (seenFirstTrackSelection && selectedNewTracks) {
|
||||
if (seekRequired) {
|
||||
seekToUs(positionUs);
|
||||
// We'll need to reset renderers consuming from all streams due to the seek.
|
||||
for (int i = 0; i < selections.length; i++) {
|
||||
@ -188,7 +192,9 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
|
||||
|
||||
@Override
|
||||
public void discardBuffer(long positionUs) {
|
||||
// Do nothing.
|
||||
for (HlsSampleStreamWrapper sampleStreamWrapper : enabledSampleStreamWrappers) {
|
||||
sampleStreamWrapper.discardBuffer(positionUs);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -47,7 +47,7 @@ import java.util.LinkedList;
|
||||
* {@link SampleStream}s from which the loaded media can be consumed.
|
||||
*/
|
||||
/* package */ final class HlsSampleStreamWrapper implements Loader.Callback<Chunk>,
|
||||
SequenceableLoader, ExtractorOutput, UpstreamFormatChangedListener {
|
||||
Loader.ReleaseCallback, SequenceableLoader, ExtractorOutput, UpstreamFormatChangedListener {
|
||||
|
||||
/**
|
||||
* A callback to be notified of events.
|
||||
@ -165,21 +165,42 @@ import java.util.LinkedList;
|
||||
return trackGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the parent {@link HlsMediaPeriod} when a track selection occurs.
|
||||
*
|
||||
* @param selections The renderer track selections.
|
||||
* @param mayRetainStreamFlags Flags indicating whether the existing sample stream can be retained
|
||||
* for each selection. A {@code true} value indicates that the selection is unchanged, and
|
||||
* that the caller does not require that the sample stream be recreated.
|
||||
* @param streams The existing sample streams, which will be updated to reflect the provided
|
||||
* selections.
|
||||
* @param streamResetFlags Will be updated to indicate new sample streams, and sample streams that
|
||||
* have been retained but with the requirement that the consuming renderer be reset.
|
||||
* @param positionUs The current playback position in microseconds.
|
||||
* @param seenFirstTrackSelection Whether we've already had the first track selection, meaning
|
||||
* this is a subsequent selection.
|
||||
* @param seekRequired Whether the parent {@link HlsMediaPeriod} is already guaranteed to perform
|
||||
* a seek as part of the track selection
|
||||
* @return Whether this wrapper requires the parent {@link HlsMediaPeriod} to perform a seek as
|
||||
* part of the track selection.
|
||||
*/
|
||||
public boolean selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags,
|
||||
SampleStream[] streams, boolean[] streamResetFlags, boolean isFirstTrackSelection) {
|
||||
SampleStream[] streams, boolean[] streamResetFlags, long positionUs,
|
||||
boolean seenFirstTrackSelection, boolean seekRequired) {
|
||||
Assertions.checkState(prepared);
|
||||
// Disable old tracks.
|
||||
int oldEnabledTrackCount = enabledTrackCount;
|
||||
// Deselect old tracks.
|
||||
for (int i = 0; i < selections.length; i++) {
|
||||
if (streams[i] != null && (selections[i] == null || !mayRetainStreamFlags[i])) {
|
||||
int group = ((HlsSampleStream) streams[i]).group;
|
||||
setTrackGroupEnabledState(group, false);
|
||||
sampleQueues.valueAt(group).disable();
|
||||
streams[i] = null;
|
||||
}
|
||||
}
|
||||
// Enable new tracks.
|
||||
// We'll always need to seek if we're making a selection having previously disabled all tracks.
|
||||
seekRequired |= seenFirstTrackSelection && oldEnabledTrackCount == 0;
|
||||
// Select new tracks.
|
||||
TrackSelection primaryTrackSelection = null;
|
||||
boolean selectedNewTracks = false;
|
||||
for (int i = 0; i < selections.length; i++) {
|
||||
if (streams[i] == null && selections[i] != null) {
|
||||
TrackSelection selection = selections[i];
|
||||
@ -191,37 +212,60 @@ import java.util.LinkedList;
|
||||
}
|
||||
streams[i] = new HlsSampleStream(this, group);
|
||||
streamResetFlags[i] = true;
|
||||
selectedNewTracks = true;
|
||||
}
|
||||
}
|
||||
if (isFirstTrackSelection) {
|
||||
// At the time of the first track selection all queues will be enabled, so we need to disable
|
||||
// any that are no longer required.
|
||||
int sampleQueueCount = sampleQueues.size();
|
||||
for (int i = 0; i < sampleQueueCount; i++) {
|
||||
if (!groupEnabledStates[i]) {
|
||||
sampleQueues.valueAt(i).disable();
|
||||
}
|
||||
}
|
||||
if (primaryTrackSelection != null && !mediaChunks.isEmpty()) {
|
||||
primaryTrackSelection.updateSelectedTrack(0);
|
||||
int chunkIndex = chunkSource.getTrackGroup().indexOf(mediaChunks.getLast().trackFormat);
|
||||
if (primaryTrackSelection.getSelectedIndexInTrackGroup() != chunkIndex) {
|
||||
// The loaded preparation chunk does match the selection. We discard it.
|
||||
seekTo(lastSeekPositionUs);
|
||||
// If there's still a chance of avoiding a seek, try and seek within the sample queue.
|
||||
if (!seekRequired) {
|
||||
SampleQueue sampleQueue = sampleQueues.valueAt(group);
|
||||
sampleQueue.rewind();
|
||||
// A seek can be avoided if we're able to advance to the current playback position in the
|
||||
// sample queue, or if we haven't read anything from the queue since the previous seek
|
||||
// (this case is common for sparse tracks such as metadata tracks). In all other cases a
|
||||
// seek is required.
|
||||
seekRequired = !sampleQueue.advanceTo(positionUs, true, true)
|
||||
&& sampleQueue.getReadIndex() != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Cancel requests if necessary.
|
||||
|
||||
if (enabledTrackCount == 0) {
|
||||
chunkSource.reset();
|
||||
downstreamTrackFormat = null;
|
||||
mediaChunks.clear();
|
||||
int sampleQueueCount = sampleQueues.size();
|
||||
if (loader.isLoading()) {
|
||||
// Discard as much as we can synchronously.
|
||||
for (int i = 0; i < sampleQueueCount; i++) {
|
||||
sampleQueues.valueAt(i).discardToEnd();
|
||||
}
|
||||
loader.cancelLoading();
|
||||
} else {
|
||||
for (int i = 0; i < sampleQueueCount; i++) {
|
||||
sampleQueues.valueAt(i).reset();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// If this is the first selection and the chunk loaded during preparation does not match the
|
||||
// selection, we call seekTo to discard it. Note that if seekRequired is true then the wrapping
|
||||
// HlsMediaPeriod will call seekTo regardless, and so we do not need to perform the selection
|
||||
// check here.
|
||||
if (!seekRequired && !seenFirstTrackSelection && primaryTrackSelection != null
|
||||
&& !mediaChunks.isEmpty()) {
|
||||
primaryTrackSelection.updateSelectedTrack(0);
|
||||
int chunkIndex = chunkSource.getTrackGroup().indexOf(mediaChunks.getLast().trackFormat);
|
||||
if (primaryTrackSelection.getSelectedIndexInTrackGroup() != chunkIndex) {
|
||||
// The loaded preparation chunk does not match the selection, so discard it.
|
||||
seekTo(positionUs);
|
||||
}
|
||||
}
|
||||
return selectedNewTracks;
|
||||
return seekRequired;
|
||||
}
|
||||
|
||||
public void discardBuffer(long positionUs) {
|
||||
int sampleQueueCount = sampleQueues.size();
|
||||
for (int i = 0; i < sampleQueueCount; i++) {
|
||||
sampleQueues.valueAt(i).discardTo(positionUs, false, groupEnabledStates[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void seekTo(long positionUs) {
|
||||
@ -234,7 +278,7 @@ import java.util.LinkedList;
|
||||
} else {
|
||||
int sampleQueueCount = sampleQueues.size();
|
||||
for (int i = 0; i < sampleQueueCount; i++) {
|
||||
sampleQueues.valueAt(i).reset(groupEnabledStates[i]);
|
||||
sampleQueues.valueAt(i).reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -262,15 +306,27 @@ import java.util.LinkedList;
|
||||
}
|
||||
|
||||
public void release() {
|
||||
int sampleQueueCount = sampleQueues.size();
|
||||
for (int i = 0; i < sampleQueueCount; i++) {
|
||||
sampleQueues.valueAt(i).disable();
|
||||
boolean releasedSynchronously = loader.release(this);
|
||||
if (prepared && !releasedSynchronously) {
|
||||
// Discard as much as we can synchronously. We only do this if we're prepared, since otherwise
|
||||
// sampleQueues may still be being modified by the loading thread.
|
||||
int sampleQueueCount = sampleQueues.size();
|
||||
for (int i = 0; i < sampleQueueCount; i++) {
|
||||
sampleQueues.valueAt(i).discardToEnd();
|
||||
}
|
||||
}
|
||||
loader.release();
|
||||
handler.removeCallbacksAndMessages(null);
|
||||
released = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReleased() {
|
||||
int sampleQueueCount = sampleQueues.size();
|
||||
for (int i = 0; i < sampleQueueCount; i++) {
|
||||
sampleQueues.valueAt(i).reset();
|
||||
}
|
||||
}
|
||||
|
||||
public void setIsTimestampMaster(boolean isTimestampMaster) {
|
||||
chunkSource.setIsTimestampMaster(isTimestampMaster);
|
||||
}
|
||||
@ -310,16 +366,16 @@ import java.util.LinkedList;
|
||||
downstreamTrackFormat = trackFormat;
|
||||
}
|
||||
|
||||
return sampleQueues.valueAt(group).readData(formatHolder, buffer, requireFormat,
|
||||
loadingFinished, lastSeekPositionUs);
|
||||
return sampleQueues.valueAt(group).read(formatHolder, buffer, requireFormat, loadingFinished,
|
||||
lastSeekPositionUs);
|
||||
}
|
||||
|
||||
/* package */ void skipData(int group, long positionUs) {
|
||||
SampleQueue sampleQueue = sampleQueues.valueAt(group);
|
||||
if (loadingFinished && positionUs > sampleQueue.getLargestQueuedTimestampUs()) {
|
||||
sampleQueue.skipAll();
|
||||
sampleQueue.advanceToEnd();
|
||||
} else {
|
||||
sampleQueue.skipToKeyframeBefore(positionUs, true);
|
||||
sampleQueue.advanceTo(positionUs, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -408,9 +464,11 @@ import java.util.LinkedList;
|
||||
if (!released) {
|
||||
int sampleQueueCount = sampleQueues.size();
|
||||
for (int i = 0; i < sampleQueueCount; i++) {
|
||||
sampleQueues.valueAt(i).reset(groupEnabledStates[i]);
|
||||
sampleQueues.valueAt(i).reset();
|
||||
}
|
||||
if (enabledTrackCount > 0) {
|
||||
callback.onContinueLoadingRequested(this);
|
||||
}
|
||||
callback.onContinueLoadingRequested(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user