Skip to content

Commit

Permalink
Migrate HLS over to new SampleQueue methods
Browse files Browse the repository at this point in the history
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=161391296
  • Loading branch information
ojw28 committed Jul 10, 2017
1 parent 5ebbb6e commit 06b3b3c
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 175 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,10 @@ public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamF
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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,6 @@ public void clearSampleData() {
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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import java.io.EOFException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.concurrent.atomic.AtomicInteger;

/**
* A queue of media samples.
Expand All @@ -52,16 +51,11 @@ public interface UpstreamFormatChangedListener {

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;
Expand All @@ -88,7 +82,6 @@ public SampleQueue(Allocator allocator) {
metadataQueue = new SampleMetadataQueue();
extrasHolder = new SampleExtrasHolder();
scratch = new ParsableByteArray(INITIAL_SCRATCH_SIZE);
state = new AtomicInteger();
firstAllocationNode = new AllocationNode(0, allocationLength);
readAllocationNode = firstAllocationNode;
writeAllocationNode = firstAllocationNode;
Expand All @@ -100,20 +93,13 @@ public SampleQueue(Allocator allocator) {
* 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();
}

/**
Expand Down Expand Up @@ -174,16 +160,6 @@ public void discardUpstreamSamples(int discardFromIndex) {

// 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.
*/
Expand Down Expand Up @@ -265,33 +241,13 @@ public void discardToEnd() {
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.
*/
public void advanceToEnd() {
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.
*
Expand All @@ -307,19 +263,6 @@ public boolean advanceTo(long timeUs, boolean toKeyframe, boolean allowTimeBeyon
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.
*
Expand Down Expand Up @@ -558,47 +501,28 @@ public void format(Format format) {
@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();
}
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();
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;
}
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,
writeAllocationNode.translateOffset(totalBytesWritten), bytesAppended);
length -= bytesAppended;
postAppend(bytesAppended);
}
endWriteOperation();
}

@Override
Expand All @@ -607,47 +531,19 @@ public void sampleMetadata(long timeUs, @C.BufferFlags int flags, int size, int
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}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -84,8 +85,9 @@ public void release() {

@Override
public void prepare(Callback callback, long positionUs) {
playlistTracker.addListener(this);
this.callback = callback;
playlistTracker.addListener(this);
preparePositionUs = positionUs;
buildAndPrepareSampleStreamWrappers(positionUs);
}

Expand Down Expand Up @@ -123,7 +125,9 @@ public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamF
}
}
}
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];
Expand All @@ -136,8 +140,8 @@ public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamF
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) {
Expand Down Expand Up @@ -173,7 +177,7 @@ public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamF
}

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++) {
Expand All @@ -188,7 +192,9 @@ public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamF

@Override
public void discardBuffer(long positionUs) {
// Do nothing.
for (HlsSampleStreamWrapper sampleStreamWrapper : enabledSampleStreamWrappers) {
sampleStreamWrapper.discardBuffer(positionUs);
}
}

@Override
Expand Down
Loading

0 comments on commit 06b3b3c

Please sign in to comment.