Skip to content

Commit

Permalink
Cleanup - Make RollingSampleBuffer append methods more consistent.
Browse files Browse the repository at this point in the history
  • Loading branch information
ojw28 committed Jul 30, 2015
1 parent 0d42032 commit 5f51a4f
Show file tree
Hide file tree
Showing 12 changed files with 101 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ public void format(MediaFormat format) {
}

@Override
public int sampleData(ExtractorInput input, int length) throws IOException,
InterruptedException {
public int sampleData(ExtractorInput input, int length, boolean allowEndOfInput)
throws IOException, InterruptedException {
byte[] newData = new byte[length];
input.readFully(newData, 0, length);
sampleData = TestUtil.joinByteArrays(sampleData, newData);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,9 @@ public void format(MediaFormat format) {
}

@Override
public int sampleData(ExtractorInput input, int length) throws IOException, InterruptedException {
return output.sampleData(input, length);
public int sampleData(ExtractorInput input, int length, boolean allowEndOfInput)
throws IOException, InterruptedException {
return output.sampleData(input, length, allowEndOfInput);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,9 @@ public void format(MediaFormat mediaFormat) {
}

@Override
public int sampleData(ExtractorInput input, int length) throws IOException, InterruptedException {
return getOutput().sampleData(input, length);
public int sampleData(ExtractorInput input, int length, boolean allowEndOfInput)
throws IOException, InterruptedException {
return getOutput().sampleData(input, length, allowEndOfInput);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,8 @@ public void format(MediaFormat mediaFormat) {
}

@Override
public int sampleData(ExtractorInput input, int length) throws IOException, InterruptedException {
public int sampleData(ExtractorInput input, int length, boolean allowEndOfInput)
throws IOException, InterruptedException {
throw new IllegalStateException("Unexpected sample data in initialization chunk");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,8 @@ public void load() throws IOException, InterruptedException {
// Load the sample data.
int result = 0;
while (result != C.RESULT_END_OF_INPUT) {
result = getOutput().sampleData(dataSource, Integer.MAX_VALUE);
if (result != C.RESULT_END_OF_INPUT) {
bytesLoaded += result;
}
bytesLoaded += result;
result = getOutput().sampleData(dataSource, Integer.MAX_VALUE, true);
}
int sampleSize = bytesLoaded;
if (headerData != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@
*/
package com.google.android.exoplayer.extractor;

import com.google.android.exoplayer.C;
import com.google.android.exoplayer.MediaFormat;
import com.google.android.exoplayer.SampleHolder;
import com.google.android.exoplayer.upstream.Allocator;
import com.google.android.exoplayer.upstream.DataSource;
import com.google.android.exoplayer.util.ParsableByteArray;

import java.io.EOFException;
import java.io.IOException;

/**
Expand Down Expand Up @@ -225,8 +227,20 @@ private boolean advanceToEligibleSample() {

// Called by the loading thread.

public int sampleData(DataSource dataSource, int length) throws IOException {
return rollingBuffer.appendData(dataSource, length);
/**
* Invoked to write sample data to the output.
*
* @param dataSource A {@link DataSource} from which to read the sample data.
* @param length The maximum length to read from the input.
* @param allowEndOfInput True if encountering the end of the input having read no data is
* allowed, and should result in {@link C#RESULT_END_OF_INPUT} being returned. False if it
* should be considered an error, causing an {@link EOFException} to be thrown.
* @return The number of bytes appended.
* @throws IOException If an error occurred reading from the input.
*/
public int sampleData(DataSource dataSource, int length, boolean allowEndOfInput)
throws IOException {
return rollingBuffer.appendData(dataSource, length, allowEndOfInput);
}

// TrackOutput implementation. Called by the loading thread.
Expand All @@ -237,8 +251,9 @@ public void format(MediaFormat format) {
}

@Override
public int sampleData(ExtractorInput input, int length) throws IOException, InterruptedException {
return rollingBuffer.appendData(input, length);
public int sampleData(ExtractorInput input, int length, boolean allowEndOfInput)
throws IOException, InterruptedException {
return rollingBuffer.appendData(input, length, allowEndOfInput);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.google.android.exoplayer.util.Assertions;
import com.google.android.exoplayer.util.ParsableByteArray;

import java.io.EOFException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.concurrent.LinkedBlockingDeque;
Expand Down Expand Up @@ -350,44 +351,55 @@ public long getWritePosition() {
* Appends data to the rolling buffer.
*
* @param dataSource The source from which to read.
* @param length The maximum length of the read, or {@link C#LENGTH_UNBOUNDED} if the caller does
* not wish to impose a limit.
* @return The number of bytes appended.
* @param length The maximum length of the read.
* @param allowEndOfInput True if encountering the end of the input having appended no data is
* allowed, and should result in {@link C#RESULT_END_OF_INPUT} being returned. False if it
* should be considered an error, causing an {@link EOFException} to be thrown.
* @return The number of bytes appended, or {@link C#RESULT_END_OF_INPUT} if the input has ended.
* @throws IOException If an error occurs reading from the source.
*/
public int appendData(DataSource dataSource, int length) throws IOException {
ensureSpaceForWrite();
int remainingAllocationCapacity = allocationLength - lastAllocationOffset;
length = length != C.LENGTH_UNBOUNDED ? Math.min(length, remainingAllocationCapacity)
: remainingAllocationCapacity;

int bytesRead = dataSource.read(lastAllocation.data,
public int appendData(DataSource dataSource, int length, boolean allowEndOfInput)
throws IOException {
length = prepareForAppend(length);
int bytesAppended = dataSource.read(lastAllocation.data,
lastAllocation.translateOffset(lastAllocationOffset), length);
if (bytesRead == C.RESULT_END_OF_INPUT) {
return C.RESULT_END_OF_INPUT;
if (bytesAppended == C.RESULT_END_OF_INPUT) {
if (allowEndOfInput) {
return C.RESULT_END_OF_INPUT;
}
throw new EOFException();
}

lastAllocationOffset += bytesRead;
totalBytesWritten += bytesRead;
return bytesRead;
lastAllocationOffset += bytesAppended;
totalBytesWritten += bytesAppended;
return bytesAppended;
}

/**
* Appends data to the rolling buffer.
*
* @param input The source from which to read.
* @param length The maximum length of the read.
* @return The number of bytes appended.
* @param allowEndOfInput True if encountering the end of the input having appended no data is
* allowed, and should result in {@link C#RESULT_END_OF_INPUT} being returned. False if it
* should be considered an error, causing an {@link EOFException} to be thrown.
* @return The number of bytes appended, or {@link C#RESULT_END_OF_INPUT} if the input has ended.
* @throws IOException If an error occurs reading from the source.
* @throws InterruptedException If the thread has been interrupted.
*/
public int appendData(ExtractorInput input, int length) throws IOException, InterruptedException {
ensureSpaceForWrite();
int thisWriteLength = Math.min(length, allocationLength - lastAllocationOffset);
input.readFully(lastAllocation.data, lastAllocation.translateOffset(lastAllocationOffset),
thisWriteLength);
lastAllocationOffset += thisWriteLength;
totalBytesWritten += thisWriteLength;
return thisWriteLength;
public int appendData(ExtractorInput input, int length, boolean allowEndOfInput)
throws IOException, InterruptedException {
length = prepareForAppend(length);
int bytesAppended = input.read(lastAllocation.data,
lastAllocation.translateOffset(lastAllocationOffset), length);
if (bytesAppended == C.RESULT_END_OF_INPUT) {
if (allowEndOfInput) {
return C.RESULT_END_OF_INPUT;
}
throw new EOFException();
}
lastAllocationOffset += bytesAppended;
totalBytesWritten += bytesAppended;
return bytesAppended;
}

/**
Expand All @@ -397,16 +409,14 @@ public int appendData(ExtractorInput input, int length) throws IOException, Inte
* @param length The length of the data to append.
*/
public void appendData(ParsableByteArray buffer, int length) {
int remainingWriteLength = length;
while (remainingWriteLength > 0) {
ensureSpaceForWrite();
int thisWriteLength = Math.min(remainingWriteLength, allocationLength - lastAllocationOffset);
while (length > 0) {
int thisAppendLength = prepareForAppend(length);
buffer.readBytes(lastAllocation.data, lastAllocation.translateOffset(lastAllocationOffset),
thisWriteLength);
lastAllocationOffset += thisWriteLength;
remainingWriteLength -= thisWriteLength;
thisAppendLength);
lastAllocationOffset += thisAppendLength;
totalBytesWritten += thisAppendLength;
length -= thisAppendLength;
}
totalBytesWritten += length;
}

/**
Expand All @@ -424,14 +434,16 @@ public void commitSample(long sampleTimeUs, int flags, long position, int size,
}

/**
* Ensures at least one byte can be written, obtaining an additional allocation if necessary.
* Prepares the rolling sample buffer for an append of up to {@code length} bytes, returning the
* number of bytes that can actually be appended.
*/
private void ensureSpaceForWrite() {
private int prepareForAppend(int length) {
if (lastAllocationOffset == allocationLength) {
lastAllocationOffset = 0;
lastAllocation = allocator.allocate();
dataQueue.add(lastAllocation);
}
return Math.min(length, allocationLength - lastAllocationOffset);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@
*/
package com.google.android.exoplayer.extractor;

import com.google.android.exoplayer.C;
import com.google.android.exoplayer.MediaFormat;
import com.google.android.exoplayer.SampleHolder;
import com.google.android.exoplayer.util.ParsableByteArray;

import java.io.EOFException;
import java.io.IOException;

/**
Expand All @@ -38,11 +40,15 @@ public interface TrackOutput {
*
* @param input An {@link ExtractorInput} from which to read the sample data.
* @param length The maximum length to read from the input.
* @param allowEndOfInput True if encountering the end of the input having read no data is
* allowed, and should result in {@link C#RESULT_END_OF_INPUT} being returned. False if it
* should be considered an error, causing an {@link EOFException} to be thrown.
* @return The number of bytes appended.
* @throws IOException If an error occurred reading from the input.
* @throws InterruptedException If the thread was interrupted.
*/
int sampleData(ExtractorInput input, int length) throws IOException, InterruptedException;
int sampleData(ExtractorInput input, int length, boolean allowEndOfInput)
throws IOException, InterruptedException;

/**
* Invoked to write sample data to the output.
Expand All @@ -56,14 +62,16 @@ public interface TrackOutput {
* Invoked when metadata associated with a sample has been extracted from the stream.
* <p>
* The corresponding sample data will have already been passed to the output via calls to
* {@link #sampleData(ExtractorInput, int)} or {@link #sampleData(ParsableByteArray, int)}.
* {@link #sampleData(ExtractorInput, int, boolean)} or
* {@link #sampleData(ParsableByteArray, int)}.
*
* @param timeUs The media timestamp associated with the sample, in microseconds.
* @param flags Flags associated with the sample. See {@link SampleHolder#flags}.
* @param size The size of the sample data, in bytes.
* @param offset The number of bytes that have been passed to
* {@link #sampleData(ExtractorInput, int)} or {@link #sampleData(ParsableByteArray, int)}
* since the last byte belonging to the sample whose metadata is being passed.
* {@link #sampleData(ExtractorInput, int, boolean)} or
* {@link #sampleData(ParsableByteArray, int)} since the last byte belonging to the sample
* whose metadata is being passed.
* @param encryptionKey The encryption key associated with the sample. May be null.
*/
void sampleMetadata(long timeUs, int flags, int size, int offset, byte[] encryptionKey);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,11 +170,11 @@ private int readSample(ExtractorInput extractorInput) throws IOException, Interr
sampleBytesRemaining -= inputBuffer.drainToOutput(trackOutput, sampleBytesRemaining);
if (sampleBytesRemaining > 0) {
inputBuffer.mark();
try {
sampleBytesRemaining -= trackOutput.sampleData(extractorInput, sampleBytesRemaining);
} catch (EOFException e) {
int bytesAppended = trackOutput.sampleData(extractorInput, sampleBytesRemaining, true);
if (bytesAppended == C.RESULT_END_OF_INPUT) {
return RESULT_END_OF_INPUT;
}
sampleBytesRemaining -= bytesAppended;
// Return if we still need more data.
if (sampleBytesRemaining > 0) {
return RESULT_CONTINUE;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -663,14 +663,14 @@ private boolean readSample(ExtractorInput input) throws IOException, Interrupted
sampleSize += nalUnitLengthFieldLengthDiff;
} else {
// Write the payload of the NAL unit.
int writtenBytes = trackOutput.sampleData(input, sampleCurrentNalBytesRemaining);
int writtenBytes = trackOutput.sampleData(input, sampleCurrentNalBytesRemaining, false);
sampleBytesWritten += writtenBytes;
sampleCurrentNalBytesRemaining -= writtenBytes;
}
}
} else {
while (sampleBytesWritten < sampleSize) {
int writtenBytes = trackOutput.sampleData(input, sampleSize - sampleBytesWritten);
int writtenBytes = trackOutput.sampleData(input, sampleSize - sampleBytesWritten, false);
sampleBytesWritten += writtenBytes;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ private int readSample(ExtractorInput input, PositionHolder positionHolder)
return RESULT_END_OF_INPUT;
}
Mp4Track track = tracks[trackIndex];
TrackOutput trackOutput = track.trackOutput;
int sampleIndex = track.sampleIndex;
long position = track.sampleTable.offsets[sampleIndex];
long skipAmount = position - input.getPosition() + sampleBytesWritten;
Expand Down Expand Up @@ -327,24 +328,24 @@ private int readSample(ExtractorInput input, PositionHolder positionHolder)
sampleCurrentNalBytesRemaining = nalLength.readUnsignedIntToInt();
// Write a start code for the current NAL unit.
nalStartCode.setPosition(0);
track.trackOutput.sampleData(nalStartCode, 4);
trackOutput.sampleData(nalStartCode, 4);
sampleBytesWritten += 4;
sampleSize += nalUnitLengthFieldLengthDiff;
} else {
// Write the payload of the NAL unit.
int writtenBytes = track.trackOutput.sampleData(input, sampleCurrentNalBytesRemaining);
int writtenBytes = trackOutput.sampleData(input, sampleCurrentNalBytesRemaining, false);
sampleBytesWritten += writtenBytes;
sampleCurrentNalBytesRemaining -= writtenBytes;
}
}
} else {
while (sampleBytesWritten < sampleSize) {
int writtenBytes = track.trackOutput.sampleData(input, sampleSize - sampleBytesWritten);
int writtenBytes = trackOutput.sampleData(input, sampleSize - sampleBytesWritten, false);
sampleBytesWritten += writtenBytes;
sampleCurrentNalBytesRemaining -= writtenBytes;
}
}
track.trackOutput.sampleMetadata(track.sampleTable.timestampsUs[sampleIndex],
trackOutput.sampleMetadata(track.sampleTable.timestampsUs[sampleIndex],
track.sampleTable.flags[sampleIndex], sampleSize, 0, null);
track.sampleIndex++;
sampleBytesWritten = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -885,7 +885,7 @@ private int readToOutput(ExtractorInput input, TrackOutput output, int length)
bytesRead = Math.min(length, strippedBytesLeft);
output.sampleData(sampleStrippedBytes, bytesRead);
} else {
bytesRead = output.sampleData(input, length);
bytesRead = output.sampleData(input, length, false);
}
sampleBytesRead += bytesRead;
sampleBytesWritten += bytesRead;
Expand Down

0 comments on commit 5f51a4f

Please sign in to comment.